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 func resolveCredentials(cfg *aws.Config,
18 envCfg envConfig, sharedCfg sharedConfig,
19 handlers request.Handlers,
21 ) (*credentials.Credentials, error) {
24 case len(envCfg.Profile) != 0:
25 // User explicitly provided an Profile, so load from shared config
27 return resolveCredsFromProfile(cfg, envCfg, sharedCfg, handlers, sessOpts)
29 case envCfg.Creds.HasKeys():
30 // Environment credentials
31 return credentials.NewStaticCredentialsFromCreds(envCfg.Creds), nil
33 case len(envCfg.WebIdentityTokenFilePath) != 0:
34 // Web identity token from environment, RoleARN required to also be
36 return assumeWebIdentity(cfg, handlers,
37 envCfg.WebIdentityTokenFilePath,
39 envCfg.RoleSessionName,
43 // Fallback to the "default" credential resolution chain.
44 return resolveCredsFromProfile(cfg, envCfg, sharedCfg, handlers, sessOpts)
48 // WebIdentityEmptyRoleARNErr will occur if 'AWS_WEB_IDENTITY_TOKEN_FILE' was set but
49 // 'AWS_IAM_ROLE_ARN' was not set.
50 var WebIdentityEmptyRoleARNErr = awserr.New(stscreds.ErrCodeWebIdentity, "role ARN is not set", nil)
52 // WebIdentityEmptyTokenFilePathErr will occur if 'AWS_IAM_ROLE_ARN' was set but
53 // 'AWS_WEB_IDENTITY_TOKEN_FILE' was not set.
54 var WebIdentityEmptyTokenFilePathErr = awserr.New(stscreds.ErrCodeWebIdentity, "token file path is not set", nil)
56 func assumeWebIdentity(cfg *aws.Config, handlers request.Handlers,
58 roleARN, sessionName string,
59 ) (*credentials.Credentials, error) {
61 if len(filepath) == 0 {
62 return nil, WebIdentityEmptyTokenFilePathErr
65 if len(roleARN) == 0 {
66 return nil, WebIdentityEmptyRoleARNErr
69 creds := stscreds.NewWebIdentityCredentials(
72 Handlers: handlers.Copy(),
82 func resolveCredsFromProfile(cfg *aws.Config,
83 envCfg envConfig, sharedCfg sharedConfig,
84 handlers request.Handlers,
86 ) (creds *credentials.Credentials, err error) {
89 case sharedCfg.SourceProfile != nil:
90 // Assume IAM role with credentials source from a different profile.
91 creds, err = resolveCredsFromProfile(cfg, envCfg,
92 *sharedCfg.SourceProfile, handlers, sessOpts,
95 case sharedCfg.Creds.HasKeys():
96 // Static Credentials from Shared Config/Credentials file.
97 creds = credentials.NewStaticCredentialsFromCreds(
101 case len(sharedCfg.CredentialProcess) != 0:
102 // Get credentials from CredentialProcess
103 creds = processcreds.NewCredentials(sharedCfg.CredentialProcess)
105 case len(sharedCfg.CredentialSource) != 0:
106 creds, err = resolveCredsFromSource(cfg, envCfg,
107 sharedCfg, handlers, sessOpts,
110 case len(sharedCfg.WebIdentityTokenFile) != 0:
111 // Credentials from Assume Web Identity token require an IAM Role, and
112 // that roll will be assumed. May be wrapped with another assume role
113 // via SourceProfile.
114 return assumeWebIdentity(cfg, handlers,
115 sharedCfg.WebIdentityTokenFile,
117 sharedCfg.RoleSessionName,
121 // Fallback to default credentials provider, include mock errors for
122 // the credential chain so user can identify why credentials failed to
124 creds = credentials.NewCredentials(&credentials.ChainProvider{
125 VerboseErrors: aws.BoolValue(cfg.CredentialsChainVerboseErrors),
126 Providers: []credentials.Provider{
128 Err: awserr.New("EnvAccessKeyNotFound",
129 "failed to find credentials in the environment.", nil),
132 Err: awserr.New("SharedCredsLoad",
133 fmt.Sprintf("failed to load profile, %s.", envCfg.Profile), nil),
135 defaults.RemoteCredProvider(*cfg, handlers),
143 if len(sharedCfg.RoleARN) > 0 {
145 cfgCp.Credentials = creds
146 return credsFromAssumeRole(cfgCp, handlers, sharedCfg, sessOpts)
152 // valid credential source values
154 credSourceEc2Metadata = "Ec2InstanceMetadata"
155 credSourceEnvironment = "Environment"
156 credSourceECSContainer = "EcsContainer"
159 func resolveCredsFromSource(cfg *aws.Config,
160 envCfg envConfig, sharedCfg sharedConfig,
161 handlers request.Handlers,
163 ) (creds *credentials.Credentials, err error) {
165 switch sharedCfg.CredentialSource {
166 case credSourceEc2Metadata:
167 p := defaults.RemoteCredProvider(*cfg, handlers)
168 creds = credentials.NewCredentials(p)
170 case credSourceEnvironment:
171 creds = credentials.NewStaticCredentialsFromCreds(envCfg.Creds)
173 case credSourceECSContainer:
174 if len(os.Getenv(shareddefaults.ECSCredsProviderEnvVar)) == 0 {
175 return nil, ErrSharedConfigECSContainerEnvVarEmpty
178 p := defaults.RemoteCredProvider(*cfg, handlers)
179 creds = credentials.NewCredentials(p)
182 return nil, ErrSharedConfigInvalidCredSource
188 func credsFromAssumeRole(cfg aws.Config,
189 handlers request.Handlers,
190 sharedCfg sharedConfig,
192 ) (*credentials.Credentials, error) {
194 if len(sharedCfg.MFASerial) != 0 && sessOpts.AssumeRoleTokenProvider == nil {
195 // AssumeRole Token provider is required if doing Assume Role
197 return nil, AssumeRoleTokenProviderNotSetError{}
200 return stscreds.NewCredentials(
203 Handlers: handlers.Copy(),
206 func(opt *stscreds.AssumeRoleProvider) {
207 opt.RoleSessionName = sharedCfg.RoleSessionName
208 opt.Duration = sessOpts.AssumeRoleDuration
210 // Assume role with external ID
211 if len(sharedCfg.ExternalID) > 0 {
212 opt.ExternalID = aws.String(sharedCfg.ExternalID)
215 // Assume role with MFA
216 if len(sharedCfg.MFASerial) > 0 {
217 opt.SerialNumber = aws.String(sharedCfg.MFASerial)
218 opt.TokenProvider = sessOpts.AssumeRoleTokenProvider
224 // AssumeRoleTokenProviderNotSetError is an error returned when creating a
225 // session when the MFAToken option is not set when shared config is configured
226 // load assume a role with an MFA token.
227 type AssumeRoleTokenProviderNotSetError struct{}
229 // Code is the short id of the error.
230 func (e AssumeRoleTokenProviderNotSetError) Code() string {
231 return "AssumeRoleTokenProviderNotSetError"
234 // Message is the description of the error
235 func (e AssumeRoleTokenProviderNotSetError) Message() string {
236 return fmt.Sprintf("assume role with MFA enabled, but AssumeRoleTokenProvider session option not set.")
239 // OrigErr is the underlying error that caused the failure.
240 func (e AssumeRoleTokenProviderNotSetError) OrigErr() error {
244 // Error satisfies the error interface.
245 func (e AssumeRoleTokenProviderNotSetError) Error() string {
246 return awserr.SprintError(e.Code(), e.Message(), "", nil)
249 type credProviderError struct {
253 func (c credProviderError) Retrieve() (credentials.Value, error) {
254 return credentials.Value{}, c.Err
256 func (c credProviderError) IsExpired() bool {