]> git.immae.eu Git - github/fretlink/terraform-provider-statuscake.git/blob - vendor/github.com/aws/aws-sdk-go/aws/credentials/stscreds/assume_role_provider.go
Initial transfer of provider code
[github/fretlink/terraform-provider-statuscake.git] / vendor / github.com / aws / aws-sdk-go / aws / credentials / stscreds / assume_role_provider.go
1 /*
2 Package stscreds are credential Providers to retrieve STS AWS credentials.
3
4 STS provides multiple ways to retrieve credentials which can be used when making
5 future AWS service API operation calls.
6
7 The SDK will ensure that per instance of credentials.Credentials all requests
8 to refresh the credentials will be synchronized. But, the SDK is unable to
9 ensure synchronous usage of the AssumeRoleProvider if the value is shared
10 between multiple Credentials, Sessions or service clients.
11
12 Assume Role
13
14 To assume an IAM role using STS with the SDK you can create a new Credentials
15 with the SDKs's stscreds package.
16
17 // Initial credentials loaded from SDK's default credential chain. Such as
18 // the environment, shared credentials (~/.aws/credentials), or EC2 Instance
19 // Role. These credentials will be used to to make the STS Assume Role API.
20 sess := session.Must(session.NewSession())
21
22 // Create the credentials from AssumeRoleProvider to assume the role
23 // referenced by the "myRoleARN" ARN.
24 creds := stscreds.NewCredentials(sess, "myRoleArn")
25
26 // Create service client value configured for credentials
27 // from assumed role.
28 svc := s3.New(sess, &aws.Config{Credentials: creds})
29
30 Assume Role with static MFA Token
31
32 To assume an IAM role with a MFA token you can either specify a MFA token code
33 directly or provide a function to prompt the user each time the credentials
34 need to refresh the role's credentials. Specifying the TokenCode should be used
35 for short lived operations that will not need to be refreshed, and when you do
36 not want to have direct control over the user provides their MFA token.
37
38 With TokenCode the AssumeRoleProvider will be not be able to refresh the role's
39 credentials.
40
41 // Create the credentials from AssumeRoleProvider to assume the role
42 // referenced by the "myRoleARN" ARN using the MFA token code provided.
43 creds := stscreds.NewCredentials(sess, "myRoleArn", func(p *stscreds.AssumeRoleProvider) {
44 p.SerialNumber = aws.String("myTokenSerialNumber")
45 p.TokenCode = aws.String("00000000")
46 })
47
48 // Create service client value configured for credentials
49 // from assumed role.
50 svc := s3.New(sess, &aws.Config{Credentials: creds})
51
52 Assume Role with MFA Token Provider
53
54 To assume an IAM role with MFA for longer running tasks where the credentials
55 may need to be refreshed setting the TokenProvider field of AssumeRoleProvider
56 will allow the credential provider to prompt for new MFA token code when the
57 role's credentials need to be refreshed.
58
59 The StdinTokenProvider function is available to prompt on stdin to retrieve
60 the MFA token code from the user. You can also implement custom prompts by
61 satisfing the TokenProvider function signature.
62
63 Using StdinTokenProvider with multiple AssumeRoleProviders, or Credentials will
64 have undesirable results as the StdinTokenProvider will not be synchronized. A
65 single Credentials with an AssumeRoleProvider can be shared safely.
66
67 // Create the credentials from AssumeRoleProvider to assume the role
68 // referenced by the "myRoleARN" ARN. Prompting for MFA token from stdin.
69 creds := stscreds.NewCredentials(sess, "myRoleArn", func(p *stscreds.AssumeRoleProvider) {
70 p.SerialNumber = aws.String("myTokenSerialNumber")
71 p.TokenProvider = stscreds.StdinTokenProvider
72 })
73
74 // Create service client value configured for credentials
75 // from assumed role.
76 svc := s3.New(sess, &aws.Config{Credentials: creds})
77
78 */
79 package stscreds
80
81 import (
82 "fmt"
83 "time"
84
85 "github.com/aws/aws-sdk-go/aws"
86 "github.com/aws/aws-sdk-go/aws/awserr"
87 "github.com/aws/aws-sdk-go/aws/client"
88 "github.com/aws/aws-sdk-go/aws/credentials"
89 "github.com/aws/aws-sdk-go/service/sts"
90 )
91
92 // StdinTokenProvider will prompt on stdout and read from stdin for a string value.
93 // An error is returned if reading from stdin fails.
94 //
95 // Use this function go read MFA tokens from stdin. The function makes no attempt
96 // to make atomic prompts from stdin across multiple gorouties.
97 //
98 // Using StdinTokenProvider with multiple AssumeRoleProviders, or Credentials will
99 // have undesirable results as the StdinTokenProvider will not be synchronized. A
100 // single Credentials with an AssumeRoleProvider can be shared safely
101 //
102 // Will wait forever until something is provided on the stdin.
103 func StdinTokenProvider() (string, error) {
104 var v string
105 fmt.Printf("Assume Role MFA token code: ")
106 _, err := fmt.Scanln(&v)
107
108 return v, err
109 }
110
111 // ProviderName provides a name of AssumeRole provider
112 const ProviderName = "AssumeRoleProvider"
113
114 // AssumeRoler represents the minimal subset of the STS client API used by this provider.
115 type AssumeRoler interface {
116 AssumeRole(input *sts.AssumeRoleInput) (*sts.AssumeRoleOutput, error)
117 }
118
119 // DefaultDuration is the default amount of time in minutes that the credentials
120 // will be valid for.
121 var DefaultDuration = time.Duration(15) * time.Minute
122
123 // AssumeRoleProvider retrieves temporary credentials from the STS service, and
124 // keeps track of their expiration time.
125 //
126 // This credential provider will be used by the SDKs default credential change
127 // when shared configuration is enabled, and the shared config or shared credentials
128 // file configure assume role. See Session docs for how to do this.
129 //
130 // AssumeRoleProvider does not provide any synchronization and it is not safe
131 // to share this value across multiple Credentials, Sessions, or service clients
132 // without also sharing the same Credentials instance.
133 type AssumeRoleProvider struct {
134 credentials.Expiry
135
136 // STS client to make assume role request with.
137 Client AssumeRoler
138
139 // Role to be assumed.
140 RoleARN string
141
142 // Session name, if you wish to reuse the credentials elsewhere.
143 RoleSessionName string
144
145 // Expiry duration of the STS credentials. Defaults to 15 minutes if not set.
146 Duration time.Duration
147
148 // Optional ExternalID to pass along, defaults to nil if not set.
149 ExternalID *string
150
151 // The policy plain text must be 2048 bytes or shorter. However, an internal
152 // conversion compresses it into a packed binary format with a separate limit.
153 // The PackedPolicySize response element indicates by percentage how close to
154 // the upper size limit the policy is, with 100% equaling the maximum allowed
155 // size.
156 Policy *string
157
158 // The identification number of the MFA device that is associated with the user
159 // who is making the AssumeRole call. Specify this value if the trust policy
160 // of the role being assumed includes a condition that requires MFA authentication.
161 // The value is either the serial number for a hardware device (such as GAHT12345678)
162 // or an Amazon Resource Name (ARN) for a virtual device (such as arn:aws:iam::123456789012:mfa/user).
163 SerialNumber *string
164
165 // The value provided by the MFA device, if the trust policy of the role being
166 // assumed requires MFA (that is, if the policy includes a condition that tests
167 // for MFA). If the role being assumed requires MFA and if the TokenCode value
168 // is missing or expired, the AssumeRole call returns an "access denied" error.
169 //
170 // If SerialNumber is set and neither TokenCode nor TokenProvider are also
171 // set an error will be returned.
172 TokenCode *string
173
174 // Async method of providing MFA token code for assuming an IAM role with MFA.
175 // The value returned by the function will be used as the TokenCode in the Retrieve
176 // call. See StdinTokenProvider for a provider that prompts and reads from stdin.
177 //
178 // This token provider will be called when ever the assumed role's
179 // credentials need to be refreshed when SerialNumber is also set and
180 // TokenCode is not set.
181 //
182 // If both TokenCode and TokenProvider is set, TokenProvider will be used and
183 // TokenCode is ignored.
184 TokenProvider func() (string, error)
185
186 // ExpiryWindow will allow the credentials to trigger refreshing prior to
187 // the credentials actually expiring. This is beneficial so race conditions
188 // with expiring credentials do not cause request to fail unexpectedly
189 // due to ExpiredTokenException exceptions.
190 //
191 // So a ExpiryWindow of 10s would cause calls to IsExpired() to return true
192 // 10 seconds before the credentials are actually expired.
193 //
194 // If ExpiryWindow is 0 or less it will be ignored.
195 ExpiryWindow time.Duration
196 }
197
198 // NewCredentials returns a pointer to a new Credentials object wrapping the
199 // AssumeRoleProvider. The credentials will expire every 15 minutes and the
200 // role will be named after a nanosecond timestamp of this operation.
201 //
202 // Takes a Config provider to create the STS client. The ConfigProvider is
203 // satisfied by the session.Session type.
204 //
205 // It is safe to share the returned Credentials with multiple Sessions and
206 // service clients. All access to the credentials and refreshing them
207 // will be synchronized.
208 func NewCredentials(c client.ConfigProvider, roleARN string, options ...func(*AssumeRoleProvider)) *credentials.Credentials {
209 p := &AssumeRoleProvider{
210 Client: sts.New(c),
211 RoleARN: roleARN,
212 Duration: DefaultDuration,
213 }
214
215 for _, option := range options {
216 option(p)
217 }
218
219 return credentials.NewCredentials(p)
220 }
221
222 // NewCredentialsWithClient returns a pointer to a new Credentials object wrapping the
223 // AssumeRoleProvider. The credentials will expire every 15 minutes and the
224 // role will be named after a nanosecond timestamp of this operation.
225 //
226 // Takes an AssumeRoler which can be satisfied by the STS client.
227 //
228 // It is safe to share the returned Credentials with multiple Sessions and
229 // service clients. All access to the credentials and refreshing them
230 // will be synchronized.
231 func NewCredentialsWithClient(svc AssumeRoler, roleARN string, options ...func(*AssumeRoleProvider)) *credentials.Credentials {
232 p := &AssumeRoleProvider{
233 Client: svc,
234 RoleARN: roleARN,
235 Duration: DefaultDuration,
236 }
237
238 for _, option := range options {
239 option(p)
240 }
241
242 return credentials.NewCredentials(p)
243 }
244
245 // Retrieve generates a new set of temporary credentials using STS.
246 func (p *AssumeRoleProvider) Retrieve() (credentials.Value, error) {
247
248 // Apply defaults where parameters are not set.
249 if p.RoleSessionName == "" {
250 // Try to work out a role name that will hopefully end up unique.
251 p.RoleSessionName = fmt.Sprintf("%d", time.Now().UTC().UnixNano())
252 }
253 if p.Duration == 0 {
254 // Expire as often as AWS permits.
255 p.Duration = DefaultDuration
256 }
257 input := &sts.AssumeRoleInput{
258 DurationSeconds: aws.Int64(int64(p.Duration / time.Second)),
259 RoleArn: aws.String(p.RoleARN),
260 RoleSessionName: aws.String(p.RoleSessionName),
261 ExternalId: p.ExternalID,
262 }
263 if p.Policy != nil {
264 input.Policy = p.Policy
265 }
266 if p.SerialNumber != nil {
267 if p.TokenCode != nil {
268 input.SerialNumber = p.SerialNumber
269 input.TokenCode = p.TokenCode
270 } else if p.TokenProvider != nil {
271 input.SerialNumber = p.SerialNumber
272 code, err := p.TokenProvider()
273 if err != nil {
274 return credentials.Value{ProviderName: ProviderName}, err
275 }
276 input.TokenCode = aws.String(code)
277 } else {
278 return credentials.Value{ProviderName: ProviderName},
279 awserr.New("AssumeRoleTokenNotAvailable",
280 "assume role with MFA enabled, but neither TokenCode nor TokenProvider are set", nil)
281 }
282 }
283
284 roleOutput, err := p.Client.AssumeRole(input)
285 if err != nil {
286 return credentials.Value{ProviderName: ProviderName}, err
287 }
288
289 // We will proactively generate new credentials before they expire.
290 p.SetExpiration(*roleOutput.Credentials.Expiration, p.ExpiryWindow)
291
292 return credentials.Value{
293 AccessKeyID: *roleOutput.Credentials.AccessKeyId,
294 SecretAccessKey: *roleOutput.Credentials.SecretAccessKey,
295 SessionToken: *roleOutput.Credentials.SessionToken,
296 ProviderName: ProviderName,
297 }, nil
298 }