// Copyright 2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"). You may not // use this file except in compliance with the License. A copy of the // License is located at // // http://aws.amazon.com/apache2.0/ // // or in the "license" file accompanying this file. This file is distributed // on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, // either express or implied. See the License for the specific language governing // permissions and limitations under the License. // package sharedCredentials provides access to the aws shared credentials file. package sharedCredentials import ( "fmt" "os" "path/filepath" "github.com/aws/amazon-ssm-agent/agent/log" "github.com/aws/amazon-ssm-agent/agent/fileutil" "github.com/aws/aws-sdk-go/aws/awserr" "gopkg.in/ini.v1" ) const ( defaultProfile = "default" awsAccessKeyID = "aws_access_key_id" awsSecretAccessKey = "aws_secret_access_key" awsSessionToken = "aws_session_token" ) // GetSharedCredsFilePath returns the filename to use to read AWS shared credentials. // Will return an error if the user's home directory path cannot be found. func GetSharedCredsFilePath(filename string) (string, error) { if credPath := os.Getenv("AWS_SHARED_CREDENTIALS_FILE"); credPath != "" && filename == "" { return credPath, nil } homeDir := getPlatformSpecificHomeLocation() if homeDir == "" { return "", awserr.New("UserHomeNotFound", "user home directory not found.", nil) } if filename == "" { return filepath.Join(homeDir, ".aws", "credentials"), nil } else { return filepath.Join(homeDir, ".aws", filename), nil } } func createFile(filePath string) error { dir, _ := filepath.Split(filePath) if err := fileutil.MakeDirs(dir); err != nil { return fmt.Errorf("error creating directories, %s. %v", dir, err) } if err := fileutil.HardenedWriteFile(filePath, []byte("")); err != nil { return fmt.Errorf("error creating file, %s. %v", filePath, err) } return nil } // Store function updates the shared credentials with the specified values: // * If the shared credentials file does not exist, it will be created. Any parent directories will also be created. // * If the section to update does not exist, it will be created. func Store(log log.T, accessKeyID, secretAccessKey, sessionToken, shareFilePath, profile string, force bool) error { if profile == "" { profile = defaultProfile } // check if file exists, if not create it if !fileutil.Exists(shareFilePath) { err := createFile(shareFilePath) if err != nil { return awserr.New("SharedCredentialsStore", "failed to create shared credentials file", err) } } config, err := ini.Load(shareFilePath) if err != nil { if force { log.Warn("Failed to load shared credentials file. Force update is enabled, creating a new empty config.", err) config = ini.Empty() } else { return awserr.New("SharedCredentialsStore", "failed to load shared credentials file", err) } } iniProfile := config.Section(profile) // Default to empty string if not found iniProfile.Key(awsAccessKeyID).SetValue(accessKeyID) iniProfile.Key(awsSecretAccessKey).SetValue(secretAccessKey) iniProfile.Key(awsSessionToken).SetValue(sessionToken) err = config.SaveTo(shareFilePath) if err != nil { return awserr.New("SharedCredentialsStore", "failed to save profile", err) } return nil } // Purge deletes the shared credentials file at the given path func Purge(shareFilePath string) error { return fileutil.DeleteFile(shareFilePath) }