aboutsummaryrefslogtreecommitdiffhomepage
path: root/vendor/github.com/aws/aws-sdk-go/aws/session/shared_config.go
diff options
context:
space:
mode:
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.go339
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
40type 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.
50type sharedConfig struct { 44type 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.
96func loadSharedConfig(profile string, filenames []string) (sharedConfig, error) { 97func 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
140func (cfg *sharedConfig) setAssumeRoleSource(origProfile string, files []sharedConfigFile) error { 136func (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
170func (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.
193func (cfg *sharedConfig) setFromIniFile(profile string, file sharedConfigFile) error { 217func (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
262func (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
284func (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
298func (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
312func (cfg *sharedConfig) clearCredentialOptions() {
313 cfg.CredentialSource = ""
314 cfg.CredentialProcess = ""
315 cfg.WebIdentityTokenFile = ""
316 cfg.Creds = credentials.Value{}
317}
318
319func (cfg *sharedConfig) clearAssumeRoleOptions() {
320 cfg.RoleARN = ""
321 cfg.ExternalID = ""
322 cfg.MFASerial = ""
323 cfg.RoleSessionName = ""
324 cfg.SourceProfileName = ""
325}
326
327func 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.
344func 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.
251type SharedConfigLoadError struct { 352type 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.
306type SharedConfigAssumeRoleError struct { 407type 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
316func (e SharedConfigAssumeRoleError) Message() string { 418func (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 {
327func (e SharedConfigAssumeRoleError) Error() string { 431func (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.
437type 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.
446func (e CredentialRequiresARNError) Code() string {
447 return "CredentialRequiresARNError"
448}
449
450// Message is the description of the error
451func (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.
459func (e CredentialRequiresARNError) OrigErr() error {
460 return nil
461}
462
463// Error satisfies the error interface.
464func (e CredentialRequiresARNError) Error() string {
465 return awserr.SprintError(e.Code(), e.Message(), "", nil)
466}