diff options
Diffstat (limited to 'vendor/github.com/aws/aws-sdk-go/aws/session')
4 files changed, 602 insertions, 280 deletions
diff --git a/vendor/github.com/aws/aws-sdk-go/aws/session/credentials.go b/vendor/github.com/aws/aws-sdk-go/aws/session/credentials.go new file mode 100644 index 0000000..ce41518 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/aws/session/credentials.go | |||
@@ -0,0 +1,258 @@ | |||
1 | package session | ||
2 | |||
3 | import ( | ||
4 | "fmt" | ||
5 | "os" | ||
6 | |||
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" | ||
15 | ) | ||
16 | |||
17 | func resolveCredentials(cfg *aws.Config, | ||
18 | envCfg envConfig, sharedCfg sharedConfig, | ||
19 | handlers request.Handlers, | ||
20 | sessOpts Options, | ||
21 | ) (*credentials.Credentials, error) { | ||
22 | |||
23 | switch { | ||
24 | case len(envCfg.Profile) != 0: | ||
25 | // User explicitly provided an Profile, so load from shared config | ||
26 | // first. | ||
27 | return resolveCredsFromProfile(cfg, envCfg, sharedCfg, handlers, sessOpts) | ||
28 | |||
29 | case envCfg.Creds.HasKeys(): | ||
30 | // Environment credentials | ||
31 | return credentials.NewStaticCredentialsFromCreds(envCfg.Creds), nil | ||
32 | |||
33 | case len(envCfg.WebIdentityTokenFilePath) != 0: | ||
34 | // Web identity token from environment, RoleARN required to also be | ||
35 | // set. | ||
36 | return assumeWebIdentity(cfg, handlers, | ||
37 | envCfg.WebIdentityTokenFilePath, | ||
38 | envCfg.RoleARN, | ||
39 | envCfg.RoleSessionName, | ||
40 | ) | ||
41 | |||
42 | default: | ||
43 | // Fallback to the "default" credential resolution chain. | ||
44 | return resolveCredsFromProfile(cfg, envCfg, sharedCfg, handlers, sessOpts) | ||
45 | } | ||
46 | } | ||
47 | |||
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) | ||
51 | |||
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) | ||
55 | |||
56 | func assumeWebIdentity(cfg *aws.Config, handlers request.Handlers, | ||
57 | filepath string, | ||
58 | roleARN, sessionName string, | ||
59 | ) (*credentials.Credentials, error) { | ||
60 | |||
61 | if len(filepath) == 0 { | ||
62 | return nil, WebIdentityEmptyTokenFilePathErr | ||
63 | } | ||
64 | |||
65 | if len(roleARN) == 0 { | ||
66 | return nil, WebIdentityEmptyRoleARNErr | ||
67 | } | ||
68 | |||
69 | creds := stscreds.NewWebIdentityCredentials( | ||
70 | &Session{ | ||
71 | Config: cfg, | ||
72 | Handlers: handlers.Copy(), | ||
73 | }, | ||
74 | roleARN, | ||
75 | sessionName, | ||
76 | filepath, | ||
77 | ) | ||
78 | |||
79 | return creds, nil | ||
80 | } | ||
81 | |||
82 | func resolveCredsFromProfile(cfg *aws.Config, | ||
83 | envCfg envConfig, sharedCfg sharedConfig, | ||
84 | handlers request.Handlers, | ||
85 | sessOpts Options, | ||
86 | ) (creds *credentials.Credentials, err error) { | ||
87 | |||
88 | switch { | ||
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, | ||
93 | ) | ||
94 | |||
95 | case sharedCfg.Creds.HasKeys(): | ||
96 | // Static Credentials from Shared Config/Credentials file. | ||
97 | creds = credentials.NewStaticCredentialsFromCreds( | ||
98 | sharedCfg.Creds, | ||
99 | ) | ||
100 | |||
101 | case len(sharedCfg.CredentialProcess) != 0: | ||
102 | // Get credentials from CredentialProcess | ||
103 | creds = processcreds.NewCredentials(sharedCfg.CredentialProcess) | ||
104 | |||
105 | case len(sharedCfg.CredentialSource) != 0: | ||
106 | creds, err = resolveCredsFromSource(cfg, envCfg, | ||
107 | sharedCfg, handlers, sessOpts, | ||
108 | ) | ||
109 | |||
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, | ||
116 | sharedCfg.RoleARN, | ||
117 | sharedCfg.RoleSessionName, | ||
118 | ) | ||
119 | |||
120 | default: | ||
121 | // Fallback to default credentials provider, include mock errors for | ||
122 | // the credential chain so user can identify why credentials failed to | ||
123 | // be retrieved. | ||
124 | creds = credentials.NewCredentials(&credentials.ChainProvider{ | ||
125 | VerboseErrors: aws.BoolValue(cfg.CredentialsChainVerboseErrors), | ||
126 | Providers: []credentials.Provider{ | ||
127 | &credProviderError{ | ||
128 | Err: awserr.New("EnvAccessKeyNotFound", | ||
129 | "failed to find credentials in the environment.", nil), | ||
130 | }, | ||
131 | &credProviderError{ | ||
132 | Err: awserr.New("SharedCredsLoad", | ||
133 | fmt.Sprintf("failed to load profile, %s.", envCfg.Profile), nil), | ||
134 | }, | ||
135 | defaults.RemoteCredProvider(*cfg, handlers), | ||
136 | }, | ||
137 | }) | ||
138 | } | ||
139 | if err != nil { | ||
140 | return nil, err | ||
141 | } | ||
142 | |||
143 | if len(sharedCfg.RoleARN) > 0 { | ||
144 | cfgCp := *cfg | ||
145 | cfgCp.Credentials = creds | ||
146 | return credsFromAssumeRole(cfgCp, handlers, sharedCfg, sessOpts) | ||
147 | } | ||
148 | |||
149 | return creds, nil | ||
150 | } | ||
151 | |||
152 | // valid credential source values | ||
153 | const ( | ||
154 | credSourceEc2Metadata = "Ec2InstanceMetadata" | ||
155 | credSourceEnvironment = "Environment" | ||
156 | credSourceECSContainer = "EcsContainer" | ||
157 | ) | ||
158 | |||
159 | func resolveCredsFromSource(cfg *aws.Config, | ||
160 | envCfg envConfig, sharedCfg sharedConfig, | ||
161 | handlers request.Handlers, | ||
162 | sessOpts Options, | ||
163 | ) (creds *credentials.Credentials, err error) { | ||
164 | |||
165 | switch sharedCfg.CredentialSource { | ||
166 | case credSourceEc2Metadata: | ||
167 | p := defaults.RemoteCredProvider(*cfg, handlers) | ||
168 | creds = credentials.NewCredentials(p) | ||
169 | |||
170 | case credSourceEnvironment: | ||
171 | creds = credentials.NewStaticCredentialsFromCreds(envCfg.Creds) | ||
172 | |||
173 | case credSourceECSContainer: | ||
174 | if len(os.Getenv(shareddefaults.ECSCredsProviderEnvVar)) == 0 { | ||
175 | return nil, ErrSharedConfigECSContainerEnvVarEmpty | ||
176 | } | ||
177 | |||
178 | p := defaults.RemoteCredProvider(*cfg, handlers) | ||
179 | creds = credentials.NewCredentials(p) | ||
180 | |||
181 | default: | ||
182 | return nil, ErrSharedConfigInvalidCredSource | ||
183 | } | ||
184 | |||
185 | return creds, nil | ||
186 | } | ||
187 | |||
188 | func credsFromAssumeRole(cfg aws.Config, | ||
189 | handlers request.Handlers, | ||
190 | sharedCfg sharedConfig, | ||
191 | sessOpts Options, | ||
192 | ) (*credentials.Credentials, error) { | ||
193 | |||
194 | if len(sharedCfg.MFASerial) != 0 && sessOpts.AssumeRoleTokenProvider == nil { | ||
195 | // AssumeRole Token provider is required if doing Assume Role | ||
196 | // with MFA. | ||
197 | return nil, AssumeRoleTokenProviderNotSetError{} | ||
198 | } | ||
199 | |||
200 | return stscreds.NewCredentials( | ||
201 | &Session{ | ||
202 | Config: &cfg, | ||
203 | Handlers: handlers.Copy(), | ||
204 | }, | ||
205 | sharedCfg.RoleARN, | ||
206 | func(opt *stscreds.AssumeRoleProvider) { | ||
207 | opt.RoleSessionName = sharedCfg.RoleSessionName | ||
208 | opt.Duration = sessOpts.AssumeRoleDuration | ||
209 | |||
210 | // Assume role with external ID | ||
211 | if len(sharedCfg.ExternalID) > 0 { | ||
212 | opt.ExternalID = aws.String(sharedCfg.ExternalID) | ||
213 | } | ||
214 | |||
215 | // Assume role with MFA | ||
216 | if len(sharedCfg.MFASerial) > 0 { | ||
217 | opt.SerialNumber = aws.String(sharedCfg.MFASerial) | ||
218 | opt.TokenProvider = sessOpts.AssumeRoleTokenProvider | ||
219 | } | ||
220 | }, | ||
221 | ), nil | ||
222 | } | ||
223 | |||
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{} | ||
228 | |||
229 | // Code is the short id of the error. | ||
230 | func (e AssumeRoleTokenProviderNotSetError) Code() string { | ||
231 | return "AssumeRoleTokenProviderNotSetError" | ||
232 | } | ||
233 | |||
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.") | ||
237 | } | ||
238 | |||
239 | // OrigErr is the underlying error that caused the failure. | ||
240 | func (e AssumeRoleTokenProviderNotSetError) OrigErr() error { | ||
241 | return nil | ||
242 | } | ||
243 | |||
244 | // Error satisfies the error interface. | ||
245 | func (e AssumeRoleTokenProviderNotSetError) Error() string { | ||
246 | return awserr.SprintError(e.Code(), e.Message(), "", nil) | ||
247 | } | ||
248 | |||
249 | type credProviderError struct { | ||
250 | Err error | ||
251 | } | ||
252 | |||
253 | func (c credProviderError) Retrieve() (credentials.Value, error) { | ||
254 | return credentials.Value{}, c.Err | ||
255 | } | ||
256 | func (c credProviderError) IsExpired() bool { | ||
257 | return true | ||
258 | } | ||
diff --git a/vendor/github.com/aws/aws-sdk-go/aws/session/env_config.go b/vendor/github.com/aws/aws-sdk-go/aws/session/env_config.go index e3959b9..3a998d5 100644 --- a/vendor/github.com/aws/aws-sdk-go/aws/session/env_config.go +++ b/vendor/github.com/aws/aws-sdk-go/aws/session/env_config.go | |||
@@ -102,18 +102,38 @@ type envConfig struct { | |||
102 | CSMEnabled bool | 102 | CSMEnabled bool |
103 | CSMPort string | 103 | CSMPort string |
104 | CSMClientID string | 104 | CSMClientID string |
105 | CSMHost string | ||
105 | 106 | ||
106 | enableEndpointDiscovery string | ||
107 | // Enables endpoint discovery via environment variables. | 107 | // Enables endpoint discovery via environment variables. |
108 | // | 108 | // |
109 | // AWS_ENABLE_ENDPOINT_DISCOVERY=true | 109 | // AWS_ENABLE_ENDPOINT_DISCOVERY=true |
110 | EnableEndpointDiscovery *bool | 110 | EnableEndpointDiscovery *bool |
111 | enableEndpointDiscovery string | ||
112 | |||
113 | // Specifies the WebIdentity token the SDK should use to assume a role | ||
114 | // with. | ||
115 | // | ||
116 | // AWS_WEB_IDENTITY_TOKEN_FILE=file_path | ||
117 | WebIdentityTokenFilePath string | ||
118 | |||
119 | // Specifies the IAM role arn to use when assuming an role. | ||
120 | // | ||
121 | // AWS_ROLE_ARN=role_arn | ||
122 | RoleARN string | ||
123 | |||
124 | // Specifies the IAM role session name to use when assuming a role. | ||
125 | // | ||
126 | // AWS_ROLE_SESSION_NAME=session_name | ||
127 | RoleSessionName string | ||
111 | } | 128 | } |
112 | 129 | ||
113 | var ( | 130 | var ( |
114 | csmEnabledEnvKey = []string{ | 131 | csmEnabledEnvKey = []string{ |
115 | "AWS_CSM_ENABLED", | 132 | "AWS_CSM_ENABLED", |
116 | } | 133 | } |
134 | csmHostEnvKey = []string{ | ||
135 | "AWS_CSM_HOST", | ||
136 | } | ||
117 | csmPortEnvKey = []string{ | 137 | csmPortEnvKey = []string{ |
118 | "AWS_CSM_PORT", | 138 | "AWS_CSM_PORT", |
119 | } | 139 | } |
@@ -150,6 +170,15 @@ var ( | |||
150 | sharedConfigFileEnvKey = []string{ | 170 | sharedConfigFileEnvKey = []string{ |
151 | "AWS_CONFIG_FILE", | 171 | "AWS_CONFIG_FILE", |
152 | } | 172 | } |
173 | webIdentityTokenFilePathEnvKey = []string{ | ||
174 | "AWS_WEB_IDENTITY_TOKEN_FILE", | ||
175 | } | ||
176 | roleARNEnvKey = []string{ | ||
177 | "AWS_ROLE_ARN", | ||
178 | } | ||
179 | roleSessionNameEnvKey = []string{ | ||
180 | "AWS_ROLE_SESSION_NAME", | ||
181 | } | ||
153 | ) | 182 | ) |
154 | 183 | ||
155 | // loadEnvConfig retrieves the SDK's environment configuration. | 184 | // loadEnvConfig retrieves the SDK's environment configuration. |
@@ -178,23 +207,31 @@ func envConfigLoad(enableSharedConfig bool) envConfig { | |||
178 | 207 | ||
179 | cfg.EnableSharedConfig = enableSharedConfig | 208 | cfg.EnableSharedConfig = enableSharedConfig |
180 | 209 | ||
181 | setFromEnvVal(&cfg.Creds.AccessKeyID, credAccessEnvKey) | 210 | // Static environment credentials |
182 | setFromEnvVal(&cfg.Creds.SecretAccessKey, credSecretEnvKey) | 211 | var creds credentials.Value |
183 | setFromEnvVal(&cfg.Creds.SessionToken, credSessionEnvKey) | 212 | setFromEnvVal(&creds.AccessKeyID, credAccessEnvKey) |
213 | setFromEnvVal(&creds.SecretAccessKey, credSecretEnvKey) | ||
214 | setFromEnvVal(&creds.SessionToken, credSessionEnvKey) | ||
215 | if creds.HasKeys() { | ||
216 | // Require logical grouping of credentials | ||
217 | creds.ProviderName = EnvProviderName | ||
218 | cfg.Creds = creds | ||
219 | } | ||
220 | |||
221 | // Role Metadata | ||
222 | setFromEnvVal(&cfg.RoleARN, roleARNEnvKey) | ||
223 | setFromEnvVal(&cfg.RoleSessionName, roleSessionNameEnvKey) | ||
224 | |||
225 | // Web identity environment variables | ||
226 | setFromEnvVal(&cfg.WebIdentityTokenFilePath, webIdentityTokenFilePathEnvKey) | ||
184 | 227 | ||
185 | // CSM environment variables | 228 | // CSM environment variables |
186 | setFromEnvVal(&cfg.csmEnabled, csmEnabledEnvKey) | 229 | setFromEnvVal(&cfg.csmEnabled, csmEnabledEnvKey) |
230 | setFromEnvVal(&cfg.CSMHost, csmHostEnvKey) | ||
187 | setFromEnvVal(&cfg.CSMPort, csmPortEnvKey) | 231 | setFromEnvVal(&cfg.CSMPort, csmPortEnvKey) |
188 | setFromEnvVal(&cfg.CSMClientID, csmClientIDEnvKey) | 232 | setFromEnvVal(&cfg.CSMClientID, csmClientIDEnvKey) |
189 | cfg.CSMEnabled = len(cfg.csmEnabled) > 0 | 233 | cfg.CSMEnabled = len(cfg.csmEnabled) > 0 |
190 | 234 | ||
191 | // Require logical grouping of credentials | ||
192 | if len(cfg.Creds.AccessKeyID) == 0 || len(cfg.Creds.SecretAccessKey) == 0 { | ||
193 | cfg.Creds = credentials.Value{} | ||
194 | } else { | ||
195 | cfg.Creds.ProviderName = EnvProviderName | ||
196 | } | ||
197 | |||
198 | regionKeys := regionEnvKeys | 235 | regionKeys := regionEnvKeys |
199 | profileKeys := profileEnvKeys | 236 | profileKeys := profileEnvKeys |
200 | if !cfg.EnableSharedConfig { | 237 | if !cfg.EnableSharedConfig { |
diff --git a/vendor/github.com/aws/aws-sdk-go/aws/session/session.go b/vendor/github.com/aws/aws-sdk-go/aws/session/session.go index be4b5f0..3a28da5 100644 --- a/vendor/github.com/aws/aws-sdk-go/aws/session/session.go +++ b/vendor/github.com/aws/aws-sdk-go/aws/session/session.go | |||
@@ -8,19 +8,17 @@ import ( | |||
8 | "io/ioutil" | 8 | "io/ioutil" |
9 | "net/http" | 9 | "net/http" |
10 | "os" | 10 | "os" |
11 | "time" | ||
11 | 12 | ||
12 | "github.com/aws/aws-sdk-go/aws" | 13 | "github.com/aws/aws-sdk-go/aws" |
13 | "github.com/aws/aws-sdk-go/aws/awserr" | 14 | "github.com/aws/aws-sdk-go/aws/awserr" |
14 | "github.com/aws/aws-sdk-go/aws/client" | 15 | "github.com/aws/aws-sdk-go/aws/client" |
15 | "github.com/aws/aws-sdk-go/aws/corehandlers" | 16 | "github.com/aws/aws-sdk-go/aws/corehandlers" |
16 | "github.com/aws/aws-sdk-go/aws/credentials" | 17 | "github.com/aws/aws-sdk-go/aws/credentials" |
17 | "github.com/aws/aws-sdk-go/aws/credentials/processcreds" | ||
18 | "github.com/aws/aws-sdk-go/aws/credentials/stscreds" | ||
19 | "github.com/aws/aws-sdk-go/aws/csm" | 18 | "github.com/aws/aws-sdk-go/aws/csm" |
20 | "github.com/aws/aws-sdk-go/aws/defaults" | 19 | "github.com/aws/aws-sdk-go/aws/defaults" |
21 | "github.com/aws/aws-sdk-go/aws/endpoints" | 20 | "github.com/aws/aws-sdk-go/aws/endpoints" |
22 | "github.com/aws/aws-sdk-go/aws/request" | 21 | "github.com/aws/aws-sdk-go/aws/request" |
23 | "github.com/aws/aws-sdk-go/internal/shareddefaults" | ||
24 | ) | 22 | ) |
25 | 23 | ||
26 | const ( | 24 | const ( |
@@ -107,7 +105,15 @@ func New(cfgs ...*aws.Config) *Session { | |||
107 | 105 | ||
108 | s := deprecatedNewSession(cfgs...) | 106 | s := deprecatedNewSession(cfgs...) |
109 | if envCfg.CSMEnabled { | 107 | if envCfg.CSMEnabled { |
110 | enableCSM(&s.Handlers, envCfg.CSMClientID, envCfg.CSMPort, s.Config.Logger) | 108 | err := enableCSM(&s.Handlers, envCfg.CSMClientID, |
109 | envCfg.CSMHost, envCfg.CSMPort, s.Config.Logger) | ||
110 | if err != nil { | ||
111 | err = fmt.Errorf("failed to enable CSM, %v", err) | ||
112 | s.Config.Logger.Log("ERROR:", err.Error()) | ||
113 | s.Handlers.Validate.PushBack(func(r *request.Request) { | ||
114 | r.Error = err | ||
115 | }) | ||
116 | } | ||
111 | } | 117 | } |
112 | 118 | ||
113 | return s | 119 | return s |
@@ -210,6 +216,12 @@ type Options struct { | |||
210 | // the config enables assume role wit MFA via the mfa_serial field. | 216 | // the config enables assume role wit MFA via the mfa_serial field. |
211 | AssumeRoleTokenProvider func() (string, error) | 217 | AssumeRoleTokenProvider func() (string, error) |
212 | 218 | ||
219 | // When the SDK's shared config is configured to assume a role this option | ||
220 | // may be provided to set the expiry duration of the STS credentials. | ||
221 | // Defaults to 15 minutes if not set as documented in the | ||
222 | // stscreds.AssumeRoleProvider. | ||
223 | AssumeRoleDuration time.Duration | ||
224 | |||
213 | // Reader for a custom Credentials Authority (CA) bundle in PEM format that | 225 | // Reader for a custom Credentials Authority (CA) bundle in PEM format that |
214 | // the SDK will use instead of the default system's root CA bundle. Use this | 226 | // the SDK will use instead of the default system's root CA bundle. Use this |
215 | // only if you want to replace the CA bundle the SDK uses for TLS requests. | 227 | // only if you want to replace the CA bundle the SDK uses for TLS requests. |
@@ -224,6 +236,12 @@ type Options struct { | |||
224 | // to also enable this feature. CustomCABundle session option field has priority | 236 | // to also enable this feature. CustomCABundle session option field has priority |
225 | // over the AWS_CA_BUNDLE environment variable, and will be used if both are set. | 237 | // over the AWS_CA_BUNDLE environment variable, and will be used if both are set. |
226 | CustomCABundle io.Reader | 238 | CustomCABundle io.Reader |
239 | |||
240 | // The handlers that the session and all API clients will be created with. | ||
241 | // This must be a complete set of handlers. Use the defaults.Handlers() | ||
242 | // function to initialize this value before changing the handlers to be | ||
243 | // used by the SDK. | ||
244 | Handlers request.Handlers | ||
227 | } | 245 | } |
228 | 246 | ||
229 | // NewSessionWithOptions returns a new Session created from SDK defaults, config files, | 247 | // NewSessionWithOptions returns a new Session created from SDK defaults, config files, |
@@ -329,27 +347,36 @@ func deprecatedNewSession(cfgs ...*aws.Config) *Session { | |||
329 | return s | 347 | return s |
330 | } | 348 | } |
331 | 349 | ||
332 | func enableCSM(handlers *request.Handlers, clientID string, port string, logger aws.Logger) { | 350 | func enableCSM(handlers *request.Handlers, |
333 | logger.Log("Enabling CSM") | 351 | clientID, host, port string, |
334 | if len(port) == 0 { | 352 | logger aws.Logger, |
335 | port = csm.DefaultPort | 353 | ) error { |
354 | if logger != nil { | ||
355 | logger.Log("Enabling CSM") | ||
336 | } | 356 | } |
337 | 357 | ||
338 | r, err := csm.Start(clientID, "127.0.0.1:"+port) | 358 | r, err := csm.Start(clientID, csm.AddressWithDefaults(host, port)) |
339 | if err != nil { | 359 | if err != nil { |
340 | return | 360 | return err |
341 | } | 361 | } |
342 | r.InjectHandlers(handlers) | 362 | r.InjectHandlers(handlers) |
363 | |||
364 | return nil | ||
343 | } | 365 | } |
344 | 366 | ||
345 | func newSession(opts Options, envCfg envConfig, cfgs ...*aws.Config) (*Session, error) { | 367 | func newSession(opts Options, envCfg envConfig, cfgs ...*aws.Config) (*Session, error) { |
346 | cfg := defaults.Config() | 368 | cfg := defaults.Config() |
347 | handlers := defaults.Handlers() | 369 | |
370 | handlers := opts.Handlers | ||
371 | if handlers.IsEmpty() { | ||
372 | handlers = defaults.Handlers() | ||
373 | } | ||
348 | 374 | ||
349 | // Get a merged version of the user provided config to determine if | 375 | // Get a merged version of the user provided config to determine if |
350 | // credentials were. | 376 | // credentials were. |
351 | userCfg := &aws.Config{} | 377 | userCfg := &aws.Config{} |
352 | userCfg.MergeIn(cfgs...) | 378 | userCfg.MergeIn(cfgs...) |
379 | cfg.MergeIn(userCfg) | ||
353 | 380 | ||
354 | // Ordered config files will be loaded in with later files overwriting | 381 | // Ordered config files will be loaded in with later files overwriting |
355 | // previous config file values. | 382 | // previous config file values. |
@@ -366,9 +393,11 @@ func newSession(opts Options, envCfg envConfig, cfgs ...*aws.Config) (*Session, | |||
366 | } | 393 | } |
367 | 394 | ||
368 | // Load additional config from file(s) | 395 | // Load additional config from file(s) |
369 | sharedCfg, err := loadSharedConfig(envCfg.Profile, cfgFiles) | 396 | sharedCfg, err := loadSharedConfig(envCfg.Profile, cfgFiles, envCfg.EnableSharedConfig) |
370 | if err != nil { | 397 | if err != nil { |
371 | return nil, err | 398 | if _, ok := err.(SharedConfigProfileNotExistsError); !ok { |
399 | return nil, err | ||
400 | } | ||
372 | } | 401 | } |
373 | 402 | ||
374 | if err := mergeConfigSrcs(cfg, userCfg, envCfg, sharedCfg, handlers, opts); err != nil { | 403 | if err := mergeConfigSrcs(cfg, userCfg, envCfg, sharedCfg, handlers, opts); err != nil { |
@@ -382,7 +411,11 @@ func newSession(opts Options, envCfg envConfig, cfgs ...*aws.Config) (*Session, | |||
382 | 411 | ||
383 | initHandlers(s) | 412 | initHandlers(s) |
384 | if envCfg.CSMEnabled { | 413 | if envCfg.CSMEnabled { |
385 | enableCSM(&s.Handlers, envCfg.CSMClientID, envCfg.CSMPort, s.Config.Logger) | 414 | err := enableCSM(&s.Handlers, envCfg.CSMClientID, |
415 | envCfg.CSMHost, envCfg.CSMPort, s.Config.Logger) | ||
416 | if err != nil { | ||
417 | return nil, err | ||
418 | } | ||
386 | } | 419 | } |
387 | 420 | ||
388 | // Setup HTTP client with custom cert bundle if enabled | 421 | // Setup HTTP client with custom cert bundle if enabled |
@@ -443,9 +476,11 @@ func loadCertPool(r io.Reader) (*x509.CertPool, error) { | |||
443 | return p, nil | 476 | return p, nil |
444 | } | 477 | } |
445 | 478 | ||
446 | func mergeConfigSrcs(cfg, userCfg *aws.Config, envCfg envConfig, sharedCfg sharedConfig, handlers request.Handlers, sessOpts Options) error { | 479 | func mergeConfigSrcs(cfg, userCfg *aws.Config, |
447 | // Merge in user provided configuration | 480 | envCfg envConfig, sharedCfg sharedConfig, |
448 | cfg.MergeIn(userCfg) | 481 | handlers request.Handlers, |
482 | sessOpts Options, | ||
483 | ) error { | ||
449 | 484 | ||
450 | // Region if not already set by user | 485 | // Region if not already set by user |
451 | if len(aws.StringValue(cfg.Region)) == 0 { | 486 | if len(aws.StringValue(cfg.Region)) == 0 { |
@@ -464,164 +499,19 @@ func mergeConfigSrcs(cfg, userCfg *aws.Config, envCfg envConfig, sharedCfg share | |||
464 | } | 499 | } |
465 | } | 500 | } |
466 | 501 | ||
467 | // Configure credentials if not already set | 502 | // Configure credentials if not already set by the user when creating the |
503 | // Session. | ||
468 | if cfg.Credentials == credentials.AnonymousCredentials && userCfg.Credentials == nil { | 504 | if cfg.Credentials == credentials.AnonymousCredentials && userCfg.Credentials == nil { |
469 | 505 | creds, err := resolveCredentials(cfg, envCfg, sharedCfg, handlers, sessOpts) | |
470 | // inspect the profile to see if a credential source has been specified. | 506 | if err != nil { |
471 | if envCfg.EnableSharedConfig && len(sharedCfg.AssumeRole.CredentialSource) > 0 { | 507 | return err |
472 | |||
473 | // if both credential_source and source_profile have been set, return an error | ||
474 | // as this is undefined behavior. | ||
475 | if len(sharedCfg.AssumeRole.SourceProfile) > 0 { | ||
476 | return ErrSharedConfigSourceCollision | ||
477 | } | ||
478 | |||
479 | // valid credential source values | ||
480 | const ( | ||
481 | credSourceEc2Metadata = "Ec2InstanceMetadata" | ||
482 | credSourceEnvironment = "Environment" | ||
483 | credSourceECSContainer = "EcsContainer" | ||
484 | ) | ||
485 | |||
486 | switch sharedCfg.AssumeRole.CredentialSource { | ||
487 | case credSourceEc2Metadata: | ||
488 | cfgCp := *cfg | ||
489 | p := defaults.RemoteCredProvider(cfgCp, handlers) | ||
490 | cfgCp.Credentials = credentials.NewCredentials(p) | ||
491 | |||
492 | if len(sharedCfg.AssumeRole.MFASerial) > 0 && sessOpts.AssumeRoleTokenProvider == nil { | ||
493 | // AssumeRole Token provider is required if doing Assume Role | ||
494 | // with MFA. | ||
495 | return AssumeRoleTokenProviderNotSetError{} | ||
496 | } | ||
497 | |||
498 | cfg.Credentials = assumeRoleCredentials(cfgCp, handlers, sharedCfg, sessOpts) | ||
499 | case credSourceEnvironment: | ||
500 | cfg.Credentials = credentials.NewStaticCredentialsFromCreds( | ||
501 | envCfg.Creds, | ||
502 | ) | ||
503 | case credSourceECSContainer: | ||
504 | if len(os.Getenv(shareddefaults.ECSCredsProviderEnvVar)) == 0 { | ||
505 | return ErrSharedConfigECSContainerEnvVarEmpty | ||
506 | } | ||
507 | |||
508 | cfgCp := *cfg | ||
509 | p := defaults.RemoteCredProvider(cfgCp, handlers) | ||
510 | creds := credentials.NewCredentials(p) | ||
511 | |||
512 | cfg.Credentials = creds | ||
513 | default: | ||
514 | return ErrSharedConfigInvalidCredSource | ||
515 | } | ||
516 | |||
517 | return nil | ||
518 | } | ||
519 | |||
520 | if len(envCfg.Creds.AccessKeyID) > 0 { | ||
521 | cfg.Credentials = credentials.NewStaticCredentialsFromCreds( | ||
522 | envCfg.Creds, | ||
523 | ) | ||
524 | } else if envCfg.EnableSharedConfig && len(sharedCfg.AssumeRole.RoleARN) > 0 && sharedCfg.AssumeRoleSource != nil { | ||
525 | cfgCp := *cfg | ||
526 | cfgCp.Credentials = credentials.NewStaticCredentialsFromCreds( | ||
527 | sharedCfg.AssumeRoleSource.Creds, | ||
528 | ) | ||
529 | |||
530 | if len(sharedCfg.AssumeRole.MFASerial) > 0 && sessOpts.AssumeRoleTokenProvider == nil { | ||
531 | // AssumeRole Token provider is required if doing Assume Role | ||
532 | // with MFA. | ||
533 | return AssumeRoleTokenProviderNotSetError{} | ||
534 | } | ||
535 | |||
536 | cfg.Credentials = assumeRoleCredentials(cfgCp, handlers, sharedCfg, sessOpts) | ||
537 | } else if len(sharedCfg.Creds.AccessKeyID) > 0 { | ||
538 | cfg.Credentials = credentials.NewStaticCredentialsFromCreds( | ||
539 | sharedCfg.Creds, | ||
540 | ) | ||
541 | } else if len(sharedCfg.CredentialProcess) > 0 { | ||
542 | cfg.Credentials = processcreds.NewCredentials( | ||
543 | sharedCfg.CredentialProcess, | ||
544 | ) | ||
545 | } else { | ||
546 | // Fallback to default credentials provider, include mock errors | ||
547 | // for the credential chain so user can identify why credentials | ||
548 | // failed to be retrieved. | ||
549 | cfg.Credentials = credentials.NewCredentials(&credentials.ChainProvider{ | ||
550 | VerboseErrors: aws.BoolValue(cfg.CredentialsChainVerboseErrors), | ||
551 | Providers: []credentials.Provider{ | ||
552 | &credProviderError{Err: awserr.New("EnvAccessKeyNotFound", "failed to find credentials in the environment.", nil)}, | ||
553 | &credProviderError{Err: awserr.New("SharedCredsLoad", fmt.Sprintf("failed to load profile, %s.", envCfg.Profile), nil)}, | ||
554 | defaults.RemoteCredProvider(*cfg, handlers), | ||
555 | }, | ||
556 | }) | ||
557 | } | 508 | } |
509 | cfg.Credentials = creds | ||
558 | } | 510 | } |
559 | 511 | ||
560 | return nil | 512 | return nil |
561 | } | 513 | } |
562 | 514 | ||
563 | func assumeRoleCredentials(cfg aws.Config, handlers request.Handlers, sharedCfg sharedConfig, sessOpts Options) *credentials.Credentials { | ||
564 | return stscreds.NewCredentials( | ||
565 | &Session{ | ||
566 | Config: &cfg, | ||
567 | Handlers: handlers.Copy(), | ||
568 | }, | ||
569 | sharedCfg.AssumeRole.RoleARN, | ||
570 | func(opt *stscreds.AssumeRoleProvider) { | ||
571 | opt.RoleSessionName = sharedCfg.AssumeRole.RoleSessionName | ||
572 | |||
573 | // Assume role with external ID | ||
574 | if len(sharedCfg.AssumeRole.ExternalID) > 0 { | ||
575 | opt.ExternalID = aws.String(sharedCfg.AssumeRole.ExternalID) | ||
576 | } | ||
577 | |||
578 | // Assume role with MFA | ||
579 | if len(sharedCfg.AssumeRole.MFASerial) > 0 { | ||
580 | opt.SerialNumber = aws.String(sharedCfg.AssumeRole.MFASerial) | ||
581 | opt.TokenProvider = sessOpts.AssumeRoleTokenProvider | ||
582 | } | ||
583 | }, | ||
584 | ) | ||
585 | } | ||
586 | |||
587 | // AssumeRoleTokenProviderNotSetError is an error returned when creating a session when the | ||
588 | // MFAToken option is not set when shared config is configured load assume a | ||
589 | // role with an MFA token. | ||
590 | type AssumeRoleTokenProviderNotSetError struct{} | ||
591 | |||
592 | // Code is the short id of the error. | ||
593 | func (e AssumeRoleTokenProviderNotSetError) Code() string { | ||
594 | return "AssumeRoleTokenProviderNotSetError" | ||
595 | } | ||
596 | |||
597 | // Message is the description of the error | ||
598 | func (e AssumeRoleTokenProviderNotSetError) Message() string { | ||
599 | return fmt.Sprintf("assume role with MFA enabled, but AssumeRoleTokenProvider session option not set.") | ||
600 | } | ||
601 | |||
602 | // OrigErr is the underlying error that caused the failure. | ||
603 | func (e AssumeRoleTokenProviderNotSetError) OrigErr() error { | ||
604 | return nil | ||
605 | } | ||
606 | |||
607 | // Error satisfies the error interface. | ||
608 | func (e AssumeRoleTokenProviderNotSetError) Error() string { | ||
609 | return awserr.SprintError(e.Code(), e.Message(), "", nil) | ||
610 | } | ||
611 | |||
612 | type credProviderError struct { | ||
613 | Err error | ||
614 | } | ||
615 | |||
616 | var emptyCreds = credentials.Value{} | ||
617 | |||
618 | func (c credProviderError) Retrieve() (credentials.Value, error) { | ||
619 | return credentials.Value{}, c.Err | ||
620 | } | ||
621 | func (c credProviderError) IsExpired() bool { | ||
622 | return true | ||
623 | } | ||
624 | |||
625 | func initHandlers(s *Session) { | 515 | func initHandlers(s *Session) { |
626 | // Add the Validate parameter handler if it is not disabled. | 516 | // Add the Validate parameter handler if it is not disabled. |
627 | s.Handlers.Validate.Remove(corehandlers.ValidateParametersHandler) | 517 | s.Handlers.Validate.Remove(corehandlers.ValidateParametersHandler) |
diff --git a/vendor/github.com/aws/aws-sdk-go/aws/session/shared_config.go b/vendor/github.com/aws/aws-sdk-go/aws/session/shared_config.go index 7cb4402..5170b49 100644 --- a/vendor/github.com/aws/aws-sdk-go/aws/session/shared_config.go +++ b/vendor/github.com/aws/aws-sdk-go/aws/session/shared_config.go | |||
@@ -5,7 +5,6 @@ import ( | |||
5 | 5 | ||
6 | "github.com/aws/aws-sdk-go/aws/awserr" | 6 | "github.com/aws/aws-sdk-go/aws/awserr" |
7 | "github.com/aws/aws-sdk-go/aws/credentials" | 7 | "github.com/aws/aws-sdk-go/aws/credentials" |
8 | |||
9 | "github.com/aws/aws-sdk-go/internal/ini" | 8 | "github.com/aws/aws-sdk-go/internal/ini" |
10 | ) | 9 | ) |
11 | 10 | ||
@@ -28,8 +27,12 @@ const ( | |||
28 | 27 | ||
29 | // endpoint discovery group | 28 | // endpoint discovery group |
30 | enableEndpointDiscoveryKey = `endpoint_discovery_enabled` // optional | 29 | enableEndpointDiscoveryKey = `endpoint_discovery_enabled` // optional |
30 | |||
31 | // External Credential Process | 31 | // External Credential Process |
32 | credentialProcessKey = `credential_process` | 32 | credentialProcessKey = `credential_process` // optional |
33 | |||
34 | // Web Identity Token File | ||
35 | webIdentityTokenFileKey = `web_identity_token_file` // optional | ||
33 | 36 | ||
34 | // DefaultSharedConfigProfile is the default profile to be used when | 37 | // DefaultSharedConfigProfile is the default profile to be used when |
35 | // loading configuration from the config files if another profile name | 38 | // loading configuration from the config files if another profile name |
@@ -37,36 +40,33 @@ const ( | |||
37 | DefaultSharedConfigProfile = `default` | 40 | DefaultSharedConfigProfile = `default` |
38 | ) | 41 | ) |
39 | 42 | ||
40 | type assumeRoleConfig struct { | ||
41 | RoleARN string | ||
42 | SourceProfile string | ||
43 | CredentialSource string | ||
44 | ExternalID string | ||
45 | MFASerial string | ||
46 | RoleSessionName string | ||
47 | } | ||
48 | |||
49 | // sharedConfig represents the configuration fields of the SDK config files. | 43 | // sharedConfig represents the configuration fields of the SDK config files. |
50 | type sharedConfig struct { | 44 | type sharedConfig struct { |
51 | // Credentials values from the config file. Both aws_access_key_id | 45 | // Credentials values from the config file. Both aws_access_key_id and |
52 | // and aws_secret_access_key must be provided together in the same file | 46 | // aws_secret_access_key must be provided together in the same file to be |
53 | // to be considered valid. The values will be ignored if not a complete group. | 47 | // considered valid. The values will be ignored if not a complete group. |
54 | // aws_session_token is an optional field that can be provided if both of the | 48 | // aws_session_token is an optional field that can be provided if both of |
55 | // other two fields are also provided. | 49 | // the other two fields are also provided. |
56 | // | 50 | // |
57 | // aws_access_key_id | 51 | // aws_access_key_id |
58 | // aws_secret_access_key | 52 | // aws_secret_access_key |
59 | // aws_session_token | 53 | // aws_session_token |
60 | Creds credentials.Value | 54 | Creds credentials.Value |
61 | 55 | ||
62 | AssumeRole assumeRoleConfig | 56 | CredentialSource string |
63 | AssumeRoleSource *sharedConfig | 57 | CredentialProcess string |
58 | WebIdentityTokenFile string | ||
59 | |||
60 | RoleARN string | ||
61 | RoleSessionName string | ||
62 | ExternalID string | ||
63 | MFASerial string | ||
64 | 64 | ||
65 | // An external process to request credentials | 65 | SourceProfileName string |
66 | CredentialProcess string | 66 | SourceProfile *sharedConfig |
67 | 67 | ||
68 | // Region is the region the SDK should use for looking up AWS service endpoints | 68 | // Region is the region the SDK should use for looking up AWS service |
69 | // and signing requests. | 69 | // endpoints and signing requests. |
70 | // | 70 | // |
71 | // region | 71 | // region |
72 | Region string | 72 | Region string |
@@ -83,17 +83,18 @@ type sharedConfigFile struct { | |||
83 | IniData ini.Sections | 83 | IniData ini.Sections |
84 | } | 84 | } |
85 | 85 | ||
86 | // loadSharedConfig retrieves the configuration from the list of files | 86 | // loadSharedConfig retrieves the configuration from the list of files using |
87 | // using the profile provided. The order the files are listed will determine | 87 | // the profile provided. The order the files are listed will determine |
88 | // precedence. Values in subsequent files will overwrite values defined in | 88 | // precedence. Values in subsequent files will overwrite values defined in |
89 | // earlier files. | 89 | // earlier files. |
90 | // | 90 | // |
91 | // For example, given two files A and B. Both define credentials. If the order | 91 | // For example, given two files A and B. Both define credentials. If the order |
92 | // of the files are A then B, B's credential values will be used instead of A's. | 92 | // of the files are A then B, B's credential values will be used instead of |
93 | // A's. | ||
93 | // | 94 | // |
94 | // See sharedConfig.setFromFile for information how the config files | 95 | // See sharedConfig.setFromFile for information how the config files |
95 | // will be loaded. | 96 | // will be loaded. |
96 | func loadSharedConfig(profile string, filenames []string) (sharedConfig, error) { | 97 | func loadSharedConfig(profile string, filenames []string, exOpts bool) (sharedConfig, error) { |
97 | if len(profile) == 0 { | 98 | if len(profile) == 0 { |
98 | profile = DefaultSharedConfigProfile | 99 | profile = DefaultSharedConfigProfile |
99 | } | 100 | } |
@@ -104,16 +105,11 @@ func loadSharedConfig(profile string, filenames []string) (sharedConfig, error) | |||
104 | } | 105 | } |
105 | 106 | ||
106 | cfg := sharedConfig{} | 107 | cfg := sharedConfig{} |
107 | if err = cfg.setFromIniFiles(profile, files); err != nil { | 108 | profiles := map[string]struct{}{} |
109 | if err = cfg.setFromIniFiles(profiles, profile, files, exOpts); err != nil { | ||
108 | return sharedConfig{}, err | 110 | return sharedConfig{}, err |
109 | } | 111 | } |
110 | 112 | ||
111 | if len(cfg.AssumeRole.SourceProfile) > 0 { | ||
112 | if err := cfg.setAssumeRoleSource(profile, files); err != nil { | ||
113 | return sharedConfig{}, err | ||
114 | } | ||
115 | } | ||
116 | |||
117 | return cfg, nil | 113 | return cfg, nil |
118 | } | 114 | } |
119 | 115 | ||
@@ -137,60 +133,88 @@ func loadSharedConfigIniFiles(filenames []string) ([]sharedConfigFile, error) { | |||
137 | return files, nil | 133 | return files, nil |
138 | } | 134 | } |
139 | 135 | ||
140 | func (cfg *sharedConfig) setAssumeRoleSource(origProfile string, files []sharedConfigFile) error { | 136 | func (cfg *sharedConfig) setFromIniFiles(profiles map[string]struct{}, profile string, files []sharedConfigFile, exOpts bool) error { |
141 | var assumeRoleSrc sharedConfig | 137 | // Trim files from the list that don't exist. |
142 | 138 | var skippedFiles int | |
143 | if len(cfg.AssumeRole.CredentialSource) > 0 { | 139 | var profileNotFoundErr error |
144 | // setAssumeRoleSource is only called when source_profile is found. | 140 | for _, f := range files { |
145 | // If both source_profile and credential_source are set, then | 141 | if err := cfg.setFromIniFile(profile, f, exOpts); err != nil { |
146 | // ErrSharedConfigSourceCollision will be returned | 142 | if _, ok := err.(SharedConfigProfileNotExistsError); ok { |
147 | return ErrSharedConfigSourceCollision | 143 | // Ignore profiles not defined in individual files. |
144 | profileNotFoundErr = err | ||
145 | skippedFiles++ | ||
146 | continue | ||
147 | } | ||
148 | return err | ||
149 | } | ||
150 | } | ||
151 | if skippedFiles == len(files) { | ||
152 | // If all files were skipped because the profile is not found, return | ||
153 | // the original profile not found error. | ||
154 | return profileNotFoundErr | ||
148 | } | 155 | } |
149 | 156 | ||
150 | // Multiple level assume role chains are not support | 157 | if _, ok := profiles[profile]; ok { |
151 | if cfg.AssumeRole.SourceProfile == origProfile { | 158 | // if this is the second instance of the profile the Assume Role |
152 | assumeRoleSrc = *cfg | 159 | // options must be cleared because they are only valid for the |
153 | assumeRoleSrc.AssumeRole = assumeRoleConfig{} | 160 | // first reference of a profile. The self linked instance of the |
161 | // profile only have credential provider options. | ||
162 | cfg.clearAssumeRoleOptions() | ||
154 | } else { | 163 | } else { |
155 | err := assumeRoleSrc.setFromIniFiles(cfg.AssumeRole.SourceProfile, files) | 164 | // First time a profile has been seen, It must either be a assume role |
156 | if err != nil { | 165 | // or credentials. Assert if the credential type requires a role ARN, |
166 | // the ARN is also set. | ||
167 | if err := cfg.validateCredentialsRequireARN(profile); err != nil { | ||
157 | return err | 168 | return err |
158 | } | 169 | } |
159 | } | 170 | } |
171 | profiles[profile] = struct{}{} | ||
160 | 172 | ||
161 | if len(assumeRoleSrc.Creds.AccessKeyID) == 0 { | 173 | if err := cfg.validateCredentialType(); err != nil { |
162 | return SharedConfigAssumeRoleError{RoleARN: cfg.AssumeRole.RoleARN} | 174 | return err |
163 | } | 175 | } |
164 | 176 | ||
165 | cfg.AssumeRoleSource = &assumeRoleSrc | 177 | // Link source profiles for assume roles |
166 | 178 | if len(cfg.SourceProfileName) != 0 { | |
167 | return nil | 179 | // Linked profile via source_profile ignore credential provider |
168 | } | 180 | // options, the source profile must provide the credentials. |
181 | cfg.clearCredentialOptions() | ||
169 | 182 | ||
170 | func (cfg *sharedConfig) setFromIniFiles(profile string, files []sharedConfigFile) error { | 183 | srcCfg := &sharedConfig{} |
171 | // Trim files from the list that don't exist. | 184 | err := srcCfg.setFromIniFiles(profiles, cfg.SourceProfileName, files, exOpts) |
172 | for _, f := range files { | 185 | if err != nil { |
173 | if err := cfg.setFromIniFile(profile, f); err != nil { | 186 | // SourceProfile that doesn't exist is an error in configuration. |
174 | if _, ok := err.(SharedConfigProfileNotExistsError); ok { | 187 | if _, ok := err.(SharedConfigProfileNotExistsError); ok { |
175 | // Ignore proviles missings | 188 | err = SharedConfigAssumeRoleError{ |
176 | continue | 189 | RoleARN: cfg.RoleARN, |
190 | SourceProfile: cfg.SourceProfileName, | ||
191 | } | ||
177 | } | 192 | } |
178 | return err | 193 | return err |
179 | } | 194 | } |
195 | |||
196 | if !srcCfg.hasCredentials() { | ||
197 | return SharedConfigAssumeRoleError{ | ||
198 | RoleARN: cfg.RoleARN, | ||
199 | SourceProfile: cfg.SourceProfileName, | ||
200 | } | ||
201 | } | ||
202 | |||
203 | cfg.SourceProfile = srcCfg | ||
180 | } | 204 | } |
181 | 205 | ||
182 | return nil | 206 | return nil |
183 | } | 207 | } |
184 | 208 | ||
185 | // setFromFile loads the configuration from the file using | 209 | // setFromFile loads the configuration from the file using the profile |
186 | // the profile provided. A sharedConfig pointer type value is used so that | 210 | // provided. A sharedConfig pointer type value is used so that multiple config |
187 | // multiple config file loadings can be chained. | 211 | // file loadings can be chained. |
188 | // | 212 | // |
189 | // Only loads complete logically grouped values, and will not set fields in cfg | 213 | // Only loads complete logically grouped values, and will not set fields in cfg |
190 | // for incomplete grouped values in the config. Such as credentials. For example | 214 | // for incomplete grouped values in the config. Such as credentials. For |
191 | // if a config file only includes aws_access_key_id but no aws_secret_access_key | 215 | // example if a config file only includes aws_access_key_id but no |
192 | // the aws_access_key_id will be ignored. | 216 | // aws_secret_access_key the aws_access_key_id will be ignored. |
193 | func (cfg *sharedConfig) setFromIniFile(profile string, file sharedConfigFile) error { | 217 | func (cfg *sharedConfig) setFromIniFile(profile string, file sharedConfigFile, exOpts bool) error { |
194 | section, ok := file.IniData.GetSection(profile) | 218 | section, ok := file.IniData.GetSection(profile) |
195 | if !ok { | 219 | if !ok { |
196 | // Fallback to to alternate profile name: profile <name> | 220 | // Fallback to to alternate profile name: profile <name> |
@@ -200,42 +224,30 @@ func (cfg *sharedConfig) setFromIniFile(profile string, file sharedConfigFile) e | |||
200 | } | 224 | } |
201 | } | 225 | } |
202 | 226 | ||
203 | // Shared Credentials | 227 | if exOpts { |
204 | akid := section.String(accessKeyIDKey) | 228 | // Assume Role Parameters |
205 | secret := section.String(secretAccessKey) | 229 | updateString(&cfg.RoleARN, section, roleArnKey) |
206 | if len(akid) > 0 && len(secret) > 0 { | 230 | updateString(&cfg.ExternalID, section, externalIDKey) |
207 | cfg.Creds = credentials.Value{ | 231 | updateString(&cfg.MFASerial, section, mfaSerialKey) |
208 | AccessKeyID: akid, | 232 | updateString(&cfg.RoleSessionName, section, roleSessionNameKey) |
209 | SecretAccessKey: secret, | 233 | updateString(&cfg.SourceProfileName, section, sourceProfileKey) |
210 | SessionToken: section.String(sessionTokenKey), | 234 | updateString(&cfg.CredentialSource, section, credentialSourceKey) |
211 | ProviderName: fmt.Sprintf("SharedConfigCredentials: %s", file.Filename), | ||
212 | } | ||
213 | } | ||
214 | 235 | ||
215 | // Assume Role | 236 | updateString(&cfg.Region, section, regionKey) |
216 | roleArn := section.String(roleArnKey) | ||
217 | srcProfile := section.String(sourceProfileKey) | ||
218 | credentialSource := section.String(credentialSourceKey) | ||
219 | hasSource := len(srcProfile) > 0 || len(credentialSource) > 0 | ||
220 | if len(roleArn) > 0 && hasSource { | ||
221 | cfg.AssumeRole = assumeRoleConfig{ | ||
222 | RoleARN: roleArn, | ||
223 | SourceProfile: srcProfile, | ||
224 | CredentialSource: credentialSource, | ||
225 | ExternalID: section.String(externalIDKey), | ||
226 | MFASerial: section.String(mfaSerialKey), | ||
227 | RoleSessionName: section.String(roleSessionNameKey), | ||
228 | } | ||
229 | } | 237 | } |
230 | 238 | ||
231 | // `credential_process` | 239 | updateString(&cfg.CredentialProcess, section, credentialProcessKey) |
232 | if credProc := section.String(credentialProcessKey); len(credProc) > 0 { | 240 | updateString(&cfg.WebIdentityTokenFile, section, webIdentityTokenFileKey) |
233 | cfg.CredentialProcess = credProc | ||
234 | } | ||
235 | 241 | ||
236 | // Region | 242 | // Shared Credentials |
237 | if v := section.String(regionKey); len(v) > 0 { | 243 | creds := credentials.Value{ |
238 | cfg.Region = v | 244 | AccessKeyID: section.String(accessKeyIDKey), |
245 | SecretAccessKey: section.String(secretAccessKey), | ||
246 | SessionToken: section.String(sessionTokenKey), | ||
247 | ProviderName: fmt.Sprintf("SharedConfigCredentials: %s", file.Filename), | ||
248 | } | ||
249 | if creds.HasKeys() { | ||
250 | cfg.Creds = creds | ||
239 | } | 251 | } |
240 | 252 | ||
241 | // Endpoint discovery | 253 | // Endpoint discovery |
@@ -247,6 +259,95 @@ func (cfg *sharedConfig) setFromIniFile(profile string, file sharedConfigFile) e | |||
247 | return nil | 259 | return nil |
248 | } | 260 | } |
249 | 261 | ||
262 | func (cfg *sharedConfig) validateCredentialsRequireARN(profile string) error { | ||
263 | var credSource string | ||
264 | |||
265 | switch { | ||
266 | case len(cfg.SourceProfileName) != 0: | ||
267 | credSource = sourceProfileKey | ||
268 | case len(cfg.CredentialSource) != 0: | ||
269 | credSource = credentialSourceKey | ||
270 | case len(cfg.WebIdentityTokenFile) != 0: | ||
271 | credSource = webIdentityTokenFileKey | ||
272 | } | ||
273 | |||
274 | if len(credSource) != 0 && len(cfg.RoleARN) == 0 { | ||
275 | return CredentialRequiresARNError{ | ||
276 | Type: credSource, | ||
277 | Profile: profile, | ||
278 | } | ||
279 | } | ||
280 | |||
281 | return nil | ||
282 | } | ||
283 | |||
284 | func (cfg *sharedConfig) validateCredentialType() error { | ||
285 | // Only one or no credential type can be defined. | ||
286 | if !oneOrNone( | ||
287 | len(cfg.SourceProfileName) != 0, | ||
288 | len(cfg.CredentialSource) != 0, | ||
289 | len(cfg.CredentialProcess) != 0, | ||
290 | len(cfg.WebIdentityTokenFile) != 0, | ||
291 | ) { | ||
292 | return ErrSharedConfigSourceCollision | ||
293 | } | ||
294 | |||
295 | return nil | ||
296 | } | ||
297 | |||
298 | func (cfg *sharedConfig) hasCredentials() bool { | ||
299 | switch { | ||
300 | case len(cfg.SourceProfileName) != 0: | ||
301 | case len(cfg.CredentialSource) != 0: | ||
302 | case len(cfg.CredentialProcess) != 0: | ||
303 | case len(cfg.WebIdentityTokenFile) != 0: | ||
304 | case cfg.Creds.HasKeys(): | ||
305 | default: | ||
306 | return false | ||
307 | } | ||
308 | |||
309 | return true | ||
310 | } | ||
311 | |||
312 | func (cfg *sharedConfig) clearCredentialOptions() { | ||
313 | cfg.CredentialSource = "" | ||
314 | cfg.CredentialProcess = "" | ||
315 | cfg.WebIdentityTokenFile = "" | ||
316 | cfg.Creds = credentials.Value{} | ||
317 | } | ||
318 | |||
319 | func (cfg *sharedConfig) clearAssumeRoleOptions() { | ||
320 | cfg.RoleARN = "" | ||
321 | cfg.ExternalID = "" | ||
322 | cfg.MFASerial = "" | ||
323 | cfg.RoleSessionName = "" | ||
324 | cfg.SourceProfileName = "" | ||
325 | } | ||
326 | |||
327 | func oneOrNone(bs ...bool) bool { | ||
328 | var count int | ||
329 | |||
330 | for _, b := range bs { | ||
331 | if b { | ||
332 | count++ | ||
333 | if count > 1 { | ||
334 | return false | ||
335 | } | ||
336 | } | ||
337 | } | ||
338 | |||
339 | return true | ||
340 | } | ||
341 | |||
342 | // updateString will only update the dst with the value in the section key, key | ||
343 | // is present in the section. | ||
344 | func updateString(dst *string, section ini.Section, key string) { | ||
345 | if !section.Has(key) { | ||
346 | return | ||
347 | } | ||
348 | *dst = section.String(key) | ||
349 | } | ||
350 | |||
250 | // SharedConfigLoadError is an error for the shared config file failed to load. | 351 | // SharedConfigLoadError is an error for the shared config file failed to load. |
251 | type SharedConfigLoadError struct { | 352 | type SharedConfigLoadError struct { |
252 | Filename string | 353 | Filename string |
@@ -304,7 +405,8 @@ func (e SharedConfigProfileNotExistsError) Error() string { | |||
304 | // profile contains assume role information, but that information is invalid | 405 | // profile contains assume role information, but that information is invalid |
305 | // or not complete. | 406 | // or not complete. |
306 | type SharedConfigAssumeRoleError struct { | 407 | type SharedConfigAssumeRoleError struct { |
307 | RoleARN string | 408 | RoleARN string |
409 | SourceProfile string | ||
308 | } | 410 | } |
309 | 411 | ||
310 | // Code is the short id of the error. | 412 | // Code is the short id of the error. |
@@ -314,8 +416,10 @@ func (e SharedConfigAssumeRoleError) Code() string { | |||
314 | 416 | ||
315 | // Message is the description of the error | 417 | // Message is the description of the error |
316 | func (e SharedConfigAssumeRoleError) Message() string { | 418 | func (e SharedConfigAssumeRoleError) Message() string { |
317 | return fmt.Sprintf("failed to load assume role for %s, source profile has no shared credentials", | 419 | return fmt.Sprintf( |
318 | e.RoleARN) | 420 | "failed to load assume role for %s, source profile %s has no shared credentials", |
421 | e.RoleARN, e.SourceProfile, | ||
422 | ) | ||
319 | } | 423 | } |
320 | 424 | ||
321 | // OrigErr is the underlying error that caused the failure. | 425 | // OrigErr is the underlying error that caused the failure. |
@@ -327,3 +431,36 @@ func (e SharedConfigAssumeRoleError) OrigErr() error { | |||
327 | func (e SharedConfigAssumeRoleError) Error() string { | 431 | func (e SharedConfigAssumeRoleError) Error() string { |
328 | return awserr.SprintError(e.Code(), e.Message(), "", nil) | 432 | return awserr.SprintError(e.Code(), e.Message(), "", nil) |
329 | } | 433 | } |
434 | |||
435 | // CredentialRequiresARNError provides the error for shared config credentials | ||
436 | // that are incorrectly configured in the shared config or credentials file. | ||
437 | type CredentialRequiresARNError struct { | ||
438 | // type of credentials that were configured. | ||
439 | Type string | ||
440 | |||
441 | // Profile name the credentials were in. | ||
442 | Profile string | ||
443 | } | ||
444 | |||
445 | // Code is the short id of the error. | ||
446 | func (e CredentialRequiresARNError) Code() string { | ||
447 | return "CredentialRequiresARNError" | ||
448 | } | ||
449 | |||
450 | // Message is the description of the error | ||
451 | func (e CredentialRequiresARNError) Message() string { | ||
452 | return fmt.Sprintf( | ||
453 | "credential type %s requires role_arn, profile %s", | ||
454 | e.Type, e.Profile, | ||
455 | ) | ||
456 | } | ||
457 | |||
458 | // OrigErr is the underlying error that caused the failure. | ||
459 | func (e CredentialRequiresARNError) OrigErr() error { | ||
460 | return nil | ||
461 | } | ||
462 | |||
463 | // Error satisfies the error interface. | ||
464 | func (e CredentialRequiresARNError) Error() string { | ||
465 | return awserr.SprintError(e.Code(), e.Message(), "", nil) | ||
466 | } | ||