diff options
Diffstat (limited to 'vendor/github.com/aws/aws-sdk-go/aws/session/shared_config.go')
-rw-r--r-- | vendor/github.com/aws/aws-sdk-go/aws/session/shared_config.go | 339 |
1 files changed, 238 insertions, 101 deletions
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 | } | ||