7 "github.com/aws/aws-sdk-go/aws"
8 "github.com/aws/aws-sdk-go/aws/awserr"
9 "github.com/aws/aws-sdk-go/aws/credentials"
10 "github.com/aws/aws-sdk-go/aws/credentials/processcreds"
11 "github.com/aws/aws-sdk-go/aws/credentials/stscreds"
12 "github.com/aws/aws-sdk-go/aws/defaults"
13 "github.com/aws/aws-sdk-go/aws/request"
14 "github.com/aws/aws-sdk-go/internal/shareddefaults"
17 // valid credential source values
19 credSourceEc2Metadata = "Ec2InstanceMetadata"
20 credSourceEnvironment = "Environment"
21 credSourceECSContainer = "EcsContainer"
24 func resolveCredentials(cfg *aws.Config,
25 envCfg envConfig, sharedCfg sharedConfig,
26 handlers request.Handlers,
28 ) (*credentials.Credentials, error) {
29 // Credentials from Assume Role with specific credentials source.
30 if envCfg.EnableSharedConfig && len(sharedCfg.AssumeRole.CredentialSource) > 0 {
31 return resolveCredsFromSource(cfg, envCfg, sharedCfg, handlers, sessOpts)
34 // Credentials from environment variables
35 if len(envCfg.Creds.AccessKeyID) > 0 {
36 return credentials.NewStaticCredentialsFromCreds(envCfg.Creds), nil
39 // Fallback to the "default" credential resolution chain.
40 return resolveCredsFromProfile(cfg, envCfg, sharedCfg, handlers, sessOpts)
43 func resolveCredsFromProfile(cfg *aws.Config,
44 envCfg envConfig, sharedCfg sharedConfig,
45 handlers request.Handlers,
47 ) (*credentials.Credentials, error) {
49 if envCfg.EnableSharedConfig && len(sharedCfg.AssumeRole.RoleARN) > 0 && sharedCfg.AssumeRoleSource != nil {
50 // Assume IAM role with credentials source from a different profile.
51 cred, err := resolveCredsFromProfile(cfg, envCfg, *sharedCfg.AssumeRoleSource, handlers, sessOpts)
57 cfgCp.Credentials = cred
58 return credsFromAssumeRole(cfgCp, handlers, sharedCfg, sessOpts)
60 } else if len(sharedCfg.Creds.AccessKeyID) > 0 {
61 // Static Credentials from Shared Config/Credentials file.
62 return credentials.NewStaticCredentialsFromCreds(
66 } else if len(sharedCfg.CredentialProcess) > 0 {
67 // Credential Process credentials from Shared Config/Credentials file.
68 return processcreds.NewCredentials(
69 sharedCfg.CredentialProcess,
72 } else if envCfg.EnableSharedConfig && len(sharedCfg.AssumeRole.CredentialSource) > 0 {
73 // Assume IAM Role with specific credential source.
74 return resolveCredsFromSource(cfg, envCfg, sharedCfg, handlers, sessOpts)
77 // Fallback to default credentials provider, include mock errors
78 // for the credential chain so user can identify why credentials
79 // failed to be retrieved.
80 return credentials.NewCredentials(&credentials.ChainProvider{
81 VerboseErrors: aws.BoolValue(cfg.CredentialsChainVerboseErrors),
82 Providers: []credentials.Provider{
84 Err: awserr.New("EnvAccessKeyNotFound",
85 "failed to find credentials in the environment.", nil),
88 Err: awserr.New("SharedCredsLoad",
89 fmt.Sprintf("failed to load profile, %s.", envCfg.Profile), nil),
91 defaults.RemoteCredProvider(*cfg, handlers),
96 func resolveCredsFromSource(cfg *aws.Config,
97 envCfg envConfig, sharedCfg sharedConfig,
98 handlers request.Handlers,
100 ) (*credentials.Credentials, error) {
101 // if both credential_source and source_profile have been set, return an
102 // error as this is undefined behavior. Only one can be used at a time
104 if len(sharedCfg.AssumeRole.SourceProfile) > 0 {
105 return nil, ErrSharedConfigSourceCollision
109 switch sharedCfg.AssumeRole.CredentialSource {
110 case credSourceEc2Metadata:
111 p := defaults.RemoteCredProvider(cfgCp, handlers)
112 cfgCp.Credentials = credentials.NewCredentials(p)
114 case credSourceEnvironment:
115 cfgCp.Credentials = credentials.NewStaticCredentialsFromCreds(envCfg.Creds)
117 case credSourceECSContainer:
118 if len(os.Getenv(shareddefaults.ECSCredsProviderEnvVar)) == 0 {
119 return nil, ErrSharedConfigECSContainerEnvVarEmpty
122 p := defaults.RemoteCredProvider(cfgCp, handlers)
123 cfgCp.Credentials = credentials.NewCredentials(p)
126 return nil, ErrSharedConfigInvalidCredSource
129 return credsFromAssumeRole(cfgCp, handlers, sharedCfg, sessOpts)
132 func credsFromAssumeRole(cfg aws.Config,
133 handlers request.Handlers,
134 sharedCfg sharedConfig,
136 ) (*credentials.Credentials, error) {
137 if len(sharedCfg.AssumeRole.MFASerial) > 0 && sessOpts.AssumeRoleTokenProvider == nil {
138 // AssumeRole Token provider is required if doing Assume Role
140 return nil, AssumeRoleTokenProviderNotSetError{}
143 return stscreds.NewCredentials(
146 Handlers: handlers.Copy(),
148 sharedCfg.AssumeRole.RoleARN,
149 func(opt *stscreds.AssumeRoleProvider) {
150 opt.RoleSessionName = sharedCfg.AssumeRole.RoleSessionName
151 opt.Duration = sessOpts.AssumeRoleDuration
153 // Assume role with external ID
154 if len(sharedCfg.AssumeRole.ExternalID) > 0 {
155 opt.ExternalID = aws.String(sharedCfg.AssumeRole.ExternalID)
158 // Assume role with MFA
159 if len(sharedCfg.AssumeRole.MFASerial) > 0 {
160 opt.SerialNumber = aws.String(sharedCfg.AssumeRole.MFASerial)
161 opt.TokenProvider = sessOpts.AssumeRoleTokenProvider
167 // AssumeRoleTokenProviderNotSetError is an error returned when creating a session when the
168 // MFAToken option is not set when shared config is configured load assume a
169 // role with an MFA token.
170 type AssumeRoleTokenProviderNotSetError struct{}
172 // Code is the short id of the error.
173 func (e AssumeRoleTokenProviderNotSetError) Code() string {
174 return "AssumeRoleTokenProviderNotSetError"
177 // Message is the description of the error
178 func (e AssumeRoleTokenProviderNotSetError) Message() string {
179 return fmt.Sprintf("assume role with MFA enabled, but AssumeRoleTokenProvider session option not set.")
182 // OrigErr is the underlying error that caused the failure.
183 func (e AssumeRoleTokenProviderNotSetError) OrigErr() error {
187 // Error satisfies the error interface.
188 func (e AssumeRoleTokenProviderNotSetError) Error() string {
189 return awserr.SprintError(e.Code(), e.Message(), "", nil)
192 type credProviderError struct {
196 var emptyCreds = credentials.Value{}
198 func (c credProviderError) Retrieve() (credentials.Value, error) {
199 return credentials.Value{}, c.Err
201 func (c credProviderError) IsExpired() bool {