github.com/aavshr/aws-sdk-go@v1.41.3/aws/session/credentials.go (about) 1 package session 2 3 import ( 4 "fmt" 5 "os" 6 "time" 7 8 "github.com/aavshr/aws-sdk-go/aws" 9 "github.com/aavshr/aws-sdk-go/aws/awserr" 10 "github.com/aavshr/aws-sdk-go/aws/credentials" 11 "github.com/aavshr/aws-sdk-go/aws/credentials/processcreds" 12 "github.com/aavshr/aws-sdk-go/aws/credentials/ssocreds" 13 "github.com/aavshr/aws-sdk-go/aws/credentials/stscreds" 14 "github.com/aavshr/aws-sdk-go/aws/defaults" 15 "github.com/aavshr/aws-sdk-go/aws/request" 16 "github.com/aavshr/aws-sdk-go/internal/shareddefaults" 17 ) 18 19 func resolveCredentials(cfg *aws.Config, 20 envCfg envConfig, sharedCfg sharedConfig, 21 handlers request.Handlers, 22 sessOpts Options, 23 ) (*credentials.Credentials, error) { 24 25 switch { 26 case len(sessOpts.Profile) != 0: 27 // User explicitly provided an Profile in the session's configuration 28 // so load that profile from shared config first. 29 // Github(aws/aws-sdk-go#2727) 30 return resolveCredsFromProfile(cfg, envCfg, sharedCfg, handlers, sessOpts) 31 32 case envCfg.Creds.HasKeys(): 33 // Environment credentials 34 return credentials.NewStaticCredentialsFromCreds(envCfg.Creds), nil 35 36 case len(envCfg.WebIdentityTokenFilePath) != 0: 37 // Web identity token from environment, RoleARN required to also be 38 // set. 39 return assumeWebIdentity(cfg, handlers, 40 envCfg.WebIdentityTokenFilePath, 41 envCfg.RoleARN, 42 envCfg.RoleSessionName, 43 ) 44 45 default: 46 // Fallback to the "default" credential resolution chain. 47 return resolveCredsFromProfile(cfg, envCfg, sharedCfg, handlers, sessOpts) 48 } 49 } 50 51 // WebIdentityEmptyRoleARNErr will occur if 'AWS_WEB_IDENTITY_TOKEN_FILE' was set but 52 // 'AWS_ROLE_ARN' was not set. 53 var WebIdentityEmptyRoleARNErr = awserr.New(stscreds.ErrCodeWebIdentity, "role ARN is not set", nil) 54 55 // WebIdentityEmptyTokenFilePathErr will occur if 'AWS_ROLE_ARN' was set but 56 // 'AWS_WEB_IDENTITY_TOKEN_FILE' was not set. 57 var WebIdentityEmptyTokenFilePathErr = awserr.New(stscreds.ErrCodeWebIdentity, "token file path is not set", nil) 58 59 func assumeWebIdentity(cfg *aws.Config, handlers request.Handlers, 60 filepath string, 61 roleARN, sessionName string, 62 ) (*credentials.Credentials, error) { 63 64 if len(filepath) == 0 { 65 return nil, WebIdentityEmptyTokenFilePathErr 66 } 67 68 if len(roleARN) == 0 { 69 return nil, WebIdentityEmptyRoleARNErr 70 } 71 72 creds := stscreds.NewWebIdentityCredentials( 73 &Session{ 74 Config: cfg, 75 Handlers: handlers.Copy(), 76 }, 77 roleARN, 78 sessionName, 79 filepath, 80 ) 81 82 return creds, nil 83 } 84 85 func resolveCredsFromProfile(cfg *aws.Config, 86 envCfg envConfig, sharedCfg sharedConfig, 87 handlers request.Handlers, 88 sessOpts Options, 89 ) (creds *credentials.Credentials, err error) { 90 91 switch { 92 case sharedCfg.SourceProfile != nil: 93 // Assume IAM role with credentials source from a different profile. 94 creds, err = resolveCredsFromProfile(cfg, envCfg, 95 *sharedCfg.SourceProfile, handlers, sessOpts, 96 ) 97 98 case sharedCfg.Creds.HasKeys(): 99 // Static Credentials from Shared Config/Credentials file. 100 creds = credentials.NewStaticCredentialsFromCreds( 101 sharedCfg.Creds, 102 ) 103 104 case len(sharedCfg.CredentialSource) != 0: 105 creds, err = resolveCredsFromSource(cfg, envCfg, 106 sharedCfg, handlers, sessOpts, 107 ) 108 109 case len(sharedCfg.WebIdentityTokenFile) != 0: 110 // Credentials from Assume Web Identity token require an IAM Role, and 111 // that roll will be assumed. May be wrapped with another assume role 112 // via SourceProfile. 113 return assumeWebIdentity(cfg, handlers, 114 sharedCfg.WebIdentityTokenFile, 115 sharedCfg.RoleARN, 116 sharedCfg.RoleSessionName, 117 ) 118 119 case sharedCfg.hasSSOConfiguration(): 120 creds, err = resolveSSOCredentials(cfg, sharedCfg, handlers) 121 122 case len(sharedCfg.CredentialProcess) != 0: 123 // Get credentials from CredentialProcess 124 creds = processcreds.NewCredentials(sharedCfg.CredentialProcess) 125 126 default: 127 // Fallback to default credentials provider, include mock errors for 128 // the credential chain so user can identify why credentials failed to 129 // be retrieved. 130 creds = credentials.NewCredentials(&credentials.ChainProvider{ 131 VerboseErrors: aws.BoolValue(cfg.CredentialsChainVerboseErrors), 132 Providers: []credentials.Provider{ 133 &credProviderError{ 134 Err: awserr.New("EnvAccessKeyNotFound", 135 "failed to find credentials in the environment.", nil), 136 }, 137 &credProviderError{ 138 Err: awserr.New("SharedCredsLoad", 139 fmt.Sprintf("failed to load profile, %s.", envCfg.Profile), nil), 140 }, 141 defaults.RemoteCredProvider(*cfg, handlers), 142 }, 143 }) 144 } 145 if err != nil { 146 return nil, err 147 } 148 149 if len(sharedCfg.RoleARN) > 0 { 150 cfgCp := *cfg 151 cfgCp.Credentials = creds 152 return credsFromAssumeRole(cfgCp, handlers, sharedCfg, sessOpts) 153 } 154 155 return creds, nil 156 } 157 158 func resolveSSOCredentials(cfg *aws.Config, sharedCfg sharedConfig, handlers request.Handlers) (*credentials.Credentials, error) { 159 if err := sharedCfg.validateSSOConfiguration(); err != nil { 160 return nil, err 161 } 162 163 cfgCopy := cfg.Copy() 164 cfgCopy.Region = &sharedCfg.SSORegion 165 166 return ssocreds.NewCredentials( 167 &Session{ 168 Config: cfgCopy, 169 Handlers: handlers.Copy(), 170 }, 171 sharedCfg.SSOAccountID, 172 sharedCfg.SSORoleName, 173 sharedCfg.SSOStartURL, 174 ), nil 175 } 176 177 // valid credential source values 178 const ( 179 credSourceEc2Metadata = "Ec2InstanceMetadata" 180 credSourceEnvironment = "Environment" 181 credSourceECSContainer = "EcsContainer" 182 ) 183 184 func resolveCredsFromSource(cfg *aws.Config, 185 envCfg envConfig, sharedCfg sharedConfig, 186 handlers request.Handlers, 187 sessOpts Options, 188 ) (creds *credentials.Credentials, err error) { 189 190 switch sharedCfg.CredentialSource { 191 case credSourceEc2Metadata: 192 p := defaults.RemoteCredProvider(*cfg, handlers) 193 creds = credentials.NewCredentials(p) 194 195 case credSourceEnvironment: 196 creds = credentials.NewStaticCredentialsFromCreds(envCfg.Creds) 197 198 case credSourceECSContainer: 199 if len(os.Getenv(shareddefaults.ECSCredsProviderEnvVar)) == 0 { 200 return nil, ErrSharedConfigECSContainerEnvVarEmpty 201 } 202 203 p := defaults.RemoteCredProvider(*cfg, handlers) 204 creds = credentials.NewCredentials(p) 205 206 default: 207 return nil, ErrSharedConfigInvalidCredSource 208 } 209 210 return creds, nil 211 } 212 213 func credsFromAssumeRole(cfg aws.Config, 214 handlers request.Handlers, 215 sharedCfg sharedConfig, 216 sessOpts Options, 217 ) (*credentials.Credentials, error) { 218 219 if len(sharedCfg.MFASerial) != 0 && sessOpts.AssumeRoleTokenProvider == nil { 220 // AssumeRole Token provider is required if doing Assume Role 221 // with MFA. 222 return nil, AssumeRoleTokenProviderNotSetError{} 223 } 224 225 return stscreds.NewCredentials( 226 &Session{ 227 Config: &cfg, 228 Handlers: handlers.Copy(), 229 }, 230 sharedCfg.RoleARN, 231 func(opt *stscreds.AssumeRoleProvider) { 232 opt.RoleSessionName = sharedCfg.RoleSessionName 233 234 if sessOpts.AssumeRoleDuration == 0 && 235 sharedCfg.AssumeRoleDuration != nil && 236 *sharedCfg.AssumeRoleDuration/time.Minute > 15 { 237 opt.Duration = *sharedCfg.AssumeRoleDuration 238 } else if sessOpts.AssumeRoleDuration != 0 { 239 opt.Duration = sessOpts.AssumeRoleDuration 240 } 241 242 // Assume role with external ID 243 if len(sharedCfg.ExternalID) > 0 { 244 opt.ExternalID = aws.String(sharedCfg.ExternalID) 245 } 246 247 // Assume role with MFA 248 if len(sharedCfg.MFASerial) > 0 { 249 opt.SerialNumber = aws.String(sharedCfg.MFASerial) 250 opt.TokenProvider = sessOpts.AssumeRoleTokenProvider 251 } 252 }, 253 ), nil 254 } 255 256 // AssumeRoleTokenProviderNotSetError is an error returned when creating a 257 // session when the MFAToken option is not set when shared config is configured 258 // load assume a role with an MFA token. 259 type AssumeRoleTokenProviderNotSetError struct{} 260 261 // Code is the short id of the error. 262 func (e AssumeRoleTokenProviderNotSetError) Code() string { 263 return "AssumeRoleTokenProviderNotSetError" 264 } 265 266 // Message is the description of the error 267 func (e AssumeRoleTokenProviderNotSetError) Message() string { 268 return fmt.Sprintf("assume role with MFA enabled, but AssumeRoleTokenProvider session option not set.") 269 } 270 271 // OrigErr is the underlying error that caused the failure. 272 func (e AssumeRoleTokenProviderNotSetError) OrigErr() error { 273 return nil 274 } 275 276 // Error satisfies the error interface. 277 func (e AssumeRoleTokenProviderNotSetError) Error() string { 278 return awserr.SprintError(e.Code(), e.Message(), "", nil) 279 } 280 281 type credProviderError struct { 282 Err error 283 } 284 285 func (c credProviderError) Retrieve() (credentials.Value, error) { 286 return credentials.Value{}, c.Err 287 } 288 func (c credProviderError) IsExpired() bool { 289 return true 290 }