github.com/aavshr/aws-sdk-go@v1.41.3/aws/credentials/shared_credentials_provider.go (about) 1 package credentials 2 3 import ( 4 "fmt" 5 "os" 6 7 "github.com/aavshr/aws-sdk-go/aws/awserr" 8 "github.com/aavshr/aws-sdk-go/internal/ini" 9 "github.com/aavshr/aws-sdk-go/internal/shareddefaults" 10 ) 11 12 // SharedCredsProviderName provides a name of SharedCreds provider 13 const SharedCredsProviderName = "SharedCredentialsProvider" 14 15 var ( 16 // ErrSharedCredentialsHomeNotFound is emitted when the user directory cannot be found. 17 ErrSharedCredentialsHomeNotFound = awserr.New("UserHomeNotFound", "user home directory not found.", nil) 18 ) 19 20 // A SharedCredentialsProvider retrieves access key pair (access key ID, 21 // secret access key, and session token if present) credentials from the current 22 // user's home directory, and keeps track if those credentials are expired. 23 // 24 // Profile ini file example: $HOME/.aws/credentials 25 type SharedCredentialsProvider struct { 26 // Path to the shared credentials file. 27 // 28 // If empty will look for "AWS_SHARED_CREDENTIALS_FILE" env variable. If the 29 // env value is empty will default to current user's home directory. 30 // Linux/OSX: "$HOME/.aws/credentials" 31 // Windows: "%USERPROFILE%\.aws\credentials" 32 Filename string 33 34 // AWS Profile to extract credentials from the shared credentials file. If empty 35 // will default to environment variable "AWS_PROFILE" or "default" if 36 // environment variable is also not set. 37 Profile string 38 39 // retrieved states if the credentials have been successfully retrieved. 40 retrieved bool 41 } 42 43 // NewSharedCredentials returns a pointer to a new Credentials object 44 // wrapping the Profile file provider. 45 func NewSharedCredentials(filename, profile string) *Credentials { 46 return NewCredentials(&SharedCredentialsProvider{ 47 Filename: filename, 48 Profile: profile, 49 }) 50 } 51 52 // Retrieve reads and extracts the shared credentials from the current 53 // users home directory. 54 func (p *SharedCredentialsProvider) Retrieve() (Value, error) { 55 p.retrieved = false 56 57 filename, err := p.filename() 58 if err != nil { 59 return Value{ProviderName: SharedCredsProviderName}, err 60 } 61 62 creds, err := loadProfile(filename, p.profile()) 63 if err != nil { 64 return Value{ProviderName: SharedCredsProviderName}, err 65 } 66 67 p.retrieved = true 68 return creds, nil 69 } 70 71 // IsExpired returns if the shared credentials have expired. 72 func (p *SharedCredentialsProvider) IsExpired() bool { 73 return !p.retrieved 74 } 75 76 // loadProfiles loads from the file pointed to by shared credentials filename for profile. 77 // The credentials retrieved from the profile will be returned or error. Error will be 78 // returned if it fails to read from the file, or the data is invalid. 79 func loadProfile(filename, profile string) (Value, error) { 80 config, err := ini.OpenFile(filename) 81 if err != nil { 82 return Value{ProviderName: SharedCredsProviderName}, awserr.New("SharedCredsLoad", "failed to load shared credentials file", err) 83 } 84 85 iniProfile, ok := config.GetSection(profile) 86 if !ok { 87 return Value{ProviderName: SharedCredsProviderName}, awserr.New("SharedCredsLoad", "failed to get profile", nil) 88 } 89 90 id := iniProfile.String("aws_access_key_id") 91 if len(id) == 0 { 92 return Value{ProviderName: SharedCredsProviderName}, awserr.New("SharedCredsAccessKey", 93 fmt.Sprintf("shared credentials %s in %s did not contain aws_access_key_id", profile, filename), 94 nil) 95 } 96 97 secret := iniProfile.String("aws_secret_access_key") 98 if len(secret) == 0 { 99 return Value{ProviderName: SharedCredsProviderName}, awserr.New("SharedCredsSecret", 100 fmt.Sprintf("shared credentials %s in %s did not contain aws_secret_access_key", profile, filename), 101 nil) 102 } 103 104 // Default to empty string if not found 105 token := iniProfile.String("aws_session_token") 106 107 return Value{ 108 AccessKeyID: id, 109 SecretAccessKey: secret, 110 SessionToken: token, 111 ProviderName: SharedCredsProviderName, 112 }, nil 113 } 114 115 // filename returns the filename to use to read AWS shared credentials. 116 // 117 // Will return an error if the user's home directory path cannot be found. 118 func (p *SharedCredentialsProvider) filename() (string, error) { 119 if len(p.Filename) != 0 { 120 return p.Filename, nil 121 } 122 123 if p.Filename = os.Getenv("AWS_SHARED_CREDENTIALS_FILE"); len(p.Filename) != 0 { 124 return p.Filename, nil 125 } 126 127 if home := shareddefaults.UserHomeDir(); len(home) == 0 { 128 // Backwards compatibility of home directly not found error being returned. 129 // This error is too verbose, failure when opening the file would of been 130 // a better error to return. 131 return "", ErrSharedCredentialsHomeNotFound 132 } 133 134 p.Filename = shareddefaults.SharedCredentialsFilename() 135 136 return p.Filename, nil 137 } 138 139 // profile returns the AWS shared credentials profile. If empty will read 140 // environment variable "AWS_PROFILE". If that is not set profile will 141 // return "default". 142 func (p *SharedCredentialsProvider) profile() string { 143 if p.Profile == "" { 144 p.Profile = os.Getenv("AWS_PROFILE") 145 } 146 if p.Profile == "" { 147 p.Profile = "default" 148 } 149 150 return p.Profile 151 }