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