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