]> git.immae.eu Git - github/fretlink/terraform-provider-statuscake.git/blame - vendor/github.com/aws/aws-sdk-go/aws/session/shared_config.go
Upgrade to 0.12
[github/fretlink/terraform-provider-statuscake.git] / vendor / github.com / aws / aws-sdk-go / aws / session / shared_config.go
CommitLineData
bae9f6d2
JC
1package session
2
3import (
4 "fmt"
bae9f6d2
JC
5
6 "github.com/aws/aws-sdk-go/aws/awserr"
7 "github.com/aws/aws-sdk-go/aws/credentials"
107c1cdb
ND
8
9 "github.com/aws/aws-sdk-go/internal/ini"
bae9f6d2
JC
10)
11
12const (
13 // Static Credentials group
14 accessKeyIDKey = `aws_access_key_id` // group required
15 secretAccessKey = `aws_secret_access_key` // group required
16 sessionTokenKey = `aws_session_token` // optional
17
18 // Assume Role Credentials group
107c1cdb
ND
19 roleArnKey = `role_arn` // group required
20 sourceProfileKey = `source_profile` // group required (or credential_source)
21 credentialSourceKey = `credential_source` // group required (or source_profile)
22 externalIDKey = `external_id` // optional
23 mfaSerialKey = `mfa_serial` // optional
24 roleSessionNameKey = `role_session_name` // optional
bae9f6d2
JC
25
26 // Additional Config fields
27 regionKey = `region`
28
107c1cdb
ND
29 // endpoint discovery group
30 enableEndpointDiscoveryKey = `endpoint_discovery_enabled` // optional
31 // External Credential Process
32 credentialProcessKey = `credential_process`
33
bae9f6d2
JC
34 // DefaultSharedConfigProfile is the default profile to be used when
35 // loading configuration from the config files if another profile name
36 // is not provided.
37 DefaultSharedConfigProfile = `default`
38)
39
40type assumeRoleConfig struct {
107c1cdb
ND
41 RoleARN string
42 SourceProfile string
43 CredentialSource string
44 ExternalID string
45 MFASerial string
46 RoleSessionName string
bae9f6d2
JC
47}
48
49// sharedConfig represents the configuration fields of the SDK config files.
50type sharedConfig struct {
51 // Credentials values from the config file. Both aws_access_key_id
52 // and aws_secret_access_key must be provided together in the same file
53 // to be 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
55 // other two fields are also provided.
56 //
57 // aws_access_key_id
58 // aws_secret_access_key
59 // aws_session_token
60 Creds credentials.Value
61
62 AssumeRole assumeRoleConfig
63 AssumeRoleSource *sharedConfig
64
107c1cdb
ND
65 // An external process to request credentials
66 CredentialProcess string
67
bae9f6d2
JC
68 // Region is the region the SDK should use for looking up AWS service endpoints
69 // and signing requests.
70 //
71 // region
72 Region string
107c1cdb
ND
73
74 // EnableEndpointDiscovery can be enabled in the shared config by setting
75 // endpoint_discovery_enabled to true
76 //
77 // endpoint_discovery_enabled = true
78 EnableEndpointDiscovery *bool
bae9f6d2
JC
79}
80
81type sharedConfigFile struct {
82 Filename string
107c1cdb 83 IniData ini.Sections
bae9f6d2
JC
84}
85
86// loadSharedConfig retrieves the configuration from the list of files
87// using the profile provided. The order the files are listed will determine
88// precedence. Values in subsequent files will overwrite values defined in
89// earlier files.
90//
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.
93//
94// See sharedConfig.setFromFile for information how the config files
95// will be loaded.
96func loadSharedConfig(profile string, filenames []string) (sharedConfig, error) {
97 if len(profile) == 0 {
98 profile = DefaultSharedConfigProfile
99 }
100
101 files, err := loadSharedConfigIniFiles(filenames)
102 if err != nil {
103 return sharedConfig{}, err
104 }
105
106 cfg := sharedConfig{}
107 if err = cfg.setFromIniFiles(profile, files); err != nil {
108 return sharedConfig{}, err
109 }
110
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
118}
119
120func loadSharedConfigIniFiles(filenames []string) ([]sharedConfigFile, error) {
121 files := make([]sharedConfigFile, 0, len(filenames))
122
123 for _, filename := range filenames {
107c1cdb
ND
124 sections, err := ini.OpenFile(filename)
125 if aerr, ok := err.(awserr.Error); ok && aerr.Code() == ini.ErrCodeUnableToReadFile {
bae9f6d2
JC
126 // Skip files which can't be opened and read for whatever reason
127 continue
107c1cdb 128 } else if err != nil {
9b12e4fe 129 return nil, SharedConfigLoadError{Filename: filename, Err: err}
bae9f6d2
JC
130 }
131
132 files = append(files, sharedConfigFile{
107c1cdb 133 Filename: filename, IniData: sections,
bae9f6d2
JC
134 })
135 }
136
137 return files, nil
138}
139
140func (cfg *sharedConfig) setAssumeRoleSource(origProfile string, files []sharedConfigFile) error {
141 var assumeRoleSrc sharedConfig
142
107c1cdb
ND
143 if len(cfg.AssumeRole.CredentialSource) > 0 {
144 // setAssumeRoleSource is only called when source_profile is found.
145 // If both source_profile and credential_source are set, then
146 // ErrSharedConfigSourceCollision will be returned
147 return ErrSharedConfigSourceCollision
148 }
149
bae9f6d2
JC
150 // Multiple level assume role chains are not support
151 if cfg.AssumeRole.SourceProfile == origProfile {
152 assumeRoleSrc = *cfg
153 assumeRoleSrc.AssumeRole = assumeRoleConfig{}
154 } else {
155 err := assumeRoleSrc.setFromIniFiles(cfg.AssumeRole.SourceProfile, files)
156 if err != nil {
157 return err
158 }
159 }
160
161 if len(assumeRoleSrc.Creds.AccessKeyID) == 0 {
162 return SharedConfigAssumeRoleError{RoleARN: cfg.AssumeRole.RoleARN}
163 }
164
165 cfg.AssumeRoleSource = &assumeRoleSrc
166
167 return nil
168}
169
170func (cfg *sharedConfig) setFromIniFiles(profile string, files []sharedConfigFile) error {
171 // Trim files from the list that don't exist.
172 for _, f := range files {
173 if err := cfg.setFromIniFile(profile, f); err != nil {
174 if _, ok := err.(SharedConfigProfileNotExistsError); ok {
175 // Ignore proviles missings
176 continue
177 }
178 return err
179 }
180 }
181
182 return nil
183}
184
185// setFromFile loads the configuration from the file using
186// the profile provided. A sharedConfig pointer type value is used so that
187// multiple config file loadings can be chained.
188//
189// 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
191// if a config file only includes aws_access_key_id but no aws_secret_access_key
192// the aws_access_key_id will be ignored.
193func (cfg *sharedConfig) setFromIniFile(profile string, file sharedConfigFile) error {
107c1cdb
ND
194 section, ok := file.IniData.GetSection(profile)
195 if !ok {
bae9f6d2 196 // Fallback to to alternate profile name: profile <name>
107c1cdb
ND
197 section, ok = file.IniData.GetSection(fmt.Sprintf("profile %s", profile))
198 if !ok {
199 return SharedConfigProfileNotExistsError{Profile: profile, Err: nil}
bae9f6d2
JC
200 }
201 }
202
203 // Shared Credentials
107c1cdb
ND
204 akid := section.String(accessKeyIDKey)
205 secret := section.String(secretAccessKey)
bae9f6d2
JC
206 if len(akid) > 0 && len(secret) > 0 {
207 cfg.Creds = credentials.Value{
208 AccessKeyID: akid,
209 SecretAccessKey: secret,
107c1cdb 210 SessionToken: section.String(sessionTokenKey),
bae9f6d2
JC
211 ProviderName: fmt.Sprintf("SharedConfigCredentials: %s", file.Filename),
212 }
213 }
214
215 // Assume Role
107c1cdb
ND
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 {
bae9f6d2 221 cfg.AssumeRole = assumeRoleConfig{
107c1cdb
ND
222 RoleARN: roleArn,
223 SourceProfile: srcProfile,
224 CredentialSource: credentialSource,
225 ExternalID: section.String(externalIDKey),
226 MFASerial: section.String(mfaSerialKey),
227 RoleSessionName: section.String(roleSessionNameKey),
bae9f6d2
JC
228 }
229 }
230
107c1cdb
ND
231 // `credential_process`
232 if credProc := section.String(credentialProcessKey); len(credProc) > 0 {
233 cfg.CredentialProcess = credProc
234 }
235
bae9f6d2 236 // Region
107c1cdb 237 if v := section.String(regionKey); len(v) > 0 {
bae9f6d2
JC
238 cfg.Region = v
239 }
240
107c1cdb
ND
241 // Endpoint discovery
242 if section.Has(enableEndpointDiscoveryKey) {
243 v := section.Bool(enableEndpointDiscoveryKey)
244 cfg.EnableEndpointDiscovery = &v
245 }
246
bae9f6d2
JC
247 return nil
248}
249
250// SharedConfigLoadError is an error for the shared config file failed to load.
251type SharedConfigLoadError struct {
252 Filename string
253 Err error
254}
255
256// Code is the short id of the error.
257func (e SharedConfigLoadError) Code() string {
258 return "SharedConfigLoadError"
259}
260
261// Message is the description of the error
262func (e SharedConfigLoadError) Message() string {
263 return fmt.Sprintf("failed to load config file, %s", e.Filename)
264}
265
266// OrigErr is the underlying error that caused the failure.
267func (e SharedConfigLoadError) OrigErr() error {
268 return e.Err
269}
270
271// Error satisfies the error interface.
272func (e SharedConfigLoadError) Error() string {
273 return awserr.SprintError(e.Code(), e.Message(), "", e.Err)
274}
275
276// SharedConfigProfileNotExistsError is an error for the shared config when
277// the profile was not find in the config file.
278type SharedConfigProfileNotExistsError struct {
279 Profile string
280 Err error
281}
282
283// Code is the short id of the error.
284func (e SharedConfigProfileNotExistsError) Code() string {
285 return "SharedConfigProfileNotExistsError"
286}
287
288// Message is the description of the error
289func (e SharedConfigProfileNotExistsError) Message() string {
290 return fmt.Sprintf("failed to get profile, %s", e.Profile)
291}
292
293// OrigErr is the underlying error that caused the failure.
294func (e SharedConfigProfileNotExistsError) OrigErr() error {
295 return e.Err
296}
297
298// Error satisfies the error interface.
299func (e SharedConfigProfileNotExistsError) Error() string {
300 return awserr.SprintError(e.Code(), e.Message(), "", e.Err)
301}
302
303// SharedConfigAssumeRoleError is an error for the shared config when the
304// profile contains assume role information, but that information is invalid
305// or not complete.
306type SharedConfigAssumeRoleError struct {
307 RoleARN string
308}
309
310// Code is the short id of the error.
311func (e SharedConfigAssumeRoleError) Code() string {
312 return "SharedConfigAssumeRoleError"
313}
314
315// Message is the description of the error
316func (e SharedConfigAssumeRoleError) Message() string {
317 return fmt.Sprintf("failed to load assume role for %s, source profile has no shared credentials",
318 e.RoleARN)
319}
320
321// OrigErr is the underlying error that caused the failure.
322func (e SharedConfigAssumeRoleError) OrigErr() error {
323 return nil
324}
325
326// Error satisfies the error interface.
327func (e SharedConfigAssumeRoleError) Error() string {
328 return awserr.SprintError(e.Code(), e.Message(), "", nil)
329}