5
5
6
6
#include < aws/identity-management/auth/STSProfileCredentialsProvider.h>
7
7
#include < aws/sts/model/AssumeRoleRequest.h>
8
+ #include < aws/sts/model/AssumeRoleWithWebIdentityRequest.h>
8
9
#include < aws/sts/STSClient.h>
9
10
#include < aws/core/utils/logging/LogMacros.h>
10
11
#include < aws/core/utils/Outcome.h>
11
12
#include < aws/core/utils/UUID.h>
12
13
14
+ #include < fstream>
13
15
#include < utility>
14
16
15
17
using namespace Aws ;
@@ -88,25 +90,27 @@ enum class ProfileState
88
90
Process,
89
91
SourceProfile,
90
92
SelfReferencing, // special case of SourceProfile.
93
+ RoleARNWebIdentity
91
94
};
92
95
93
96
/*
94
97
* A valid profile can be in one of the following states. Any other state is considered invalid.
95
- +---------+-----------+-----------+--------------+
96
- | | | | |
97
- | Role | Source | Process | Static |
98
- | ARN | Profile | | Credentials |
99
- +------------------------------------------------+
100
- | | | | |
101
- | false | false | false | TRUE |
102
- | | | | |
103
- | false | false | TRUE | false |
104
- | | | | |
105
- | TRUE | TRUE | false | false |
106
- | | | | |
107
- | TRUE | TRUE | false | TRUE |
108
- | | | | |
109
- +---------+-----------+-----------+--------------+
98
+ +---------+-----------+-----------+--------------+------------+
99
+ | | | | | |
100
+ | Role | Source | Process | Static | Web |
101
+ | ARN | Profile | | Credentials | Identity |
102
+ +------------------------------------------------+------------+
103
+ | | | | | |
104
+ | false | false | false | TRUE | false |
105
+ | | | | | |
106
+ | false | false | TRUE | false | false |
107
+ | | | | | |
108
+ | TRUE | TRUE | false | false | false |
109
+ | | | | | |
110
+ | TRUE | TRUE | false | TRUE | false |
111
+ | | | | | |
112
+ | TRUE | false | false | false | TRUE |
113
+ +---------+-----------+-----------+--------------+------------+
110
114
111
115
*/
112
116
static ProfileState CheckProfile (const Aws::Config::Profile& profile, bool topLevelProfile)
@@ -115,6 +119,7 @@ static ProfileState CheckProfile(const Aws::Config::Profile& profile, bool topLe
115
119
constexpr int PROCESS_CREDENTIALS = 2 ;
116
120
constexpr int SOURCE_PROFILE = 4 ;
117
121
constexpr int ROLE_ARN = 8 ;
122
+ constexpr int WEB_IDENTITY_TOKEN_FILE = 16 ;
118
123
119
124
int state = 0 ;
120
125
@@ -138,6 +143,11 @@ static ProfileState CheckProfile(const Aws::Config::Profile& profile, bool topLe
138
143
state += ROLE_ARN;
139
144
}
140
145
146
+ if (!profile.GetValue (" web_identity_token_file" ).empty ())
147
+ {
148
+ state += WEB_IDENTITY_TOKEN_FILE;
149
+ }
150
+
141
151
if (topLevelProfile)
142
152
{
143
153
switch (state)
@@ -155,6 +165,8 @@ static ProfileState CheckProfile(const Aws::Config::Profile& profile, bool topLe
155
165
}
156
166
// source-profile over-rule static credentials in top-level profiles (except when self-referencing)
157
167
return ProfileState::SourceProfile;
168
+ case 24 : // role arn && web identity
169
+ return ProfileState::RoleARNWebIdentity;
158
170
default :
159
171
// All other cases are considered malformed configuration.
160
172
return ProfileState::Invalid;
@@ -176,6 +188,8 @@ static ProfileState CheckProfile(const Aws::Config::Profile& profile, bool topLe
176
188
return ProfileState::SelfReferencing;
177
189
}
178
190
return ProfileState::Static; // static credentials over-rule source-profile (except when self-referencing)
191
+ case 24 : // role arn && web identity
192
+ return ProfileState::RoleARNWebIdentity;
179
193
default :
180
194
// All other cases are considered malformed configuration.
181
195
return ProfileState::Invalid;
@@ -302,10 +316,14 @@ void STSProfileCredentialsProvider::Reload()
302
316
303
317
while (sourceProfiles.size () > 1 )
304
318
{
305
- const auto profile = sourceProfiles.back ()->second ;
319
+ const auto & profile = sourceProfiles.back ()->second ;
306
320
sourceProfiles.pop_back ();
307
321
AWSCredentials stsCreds;
308
- if (profile.GetCredentialProcess ().empty ())
322
+ if (CheckProfile (profile, false /* topLevelProfile*/ ) == ProfileState::RoleARNWebIdentity)
323
+ {
324
+ stsCreds = GetCredentialsFromWebIdentity (profile);
325
+ }
326
+ else if (profile.GetCredentialProcess ().empty ())
309
327
{
310
328
assert (!profile.GetCredentials ().IsEmpty ());
311
329
stsCreds = profile.GetCredentials ();
@@ -316,7 +334,7 @@ void STSProfileCredentialsProvider::Reload()
316
334
}
317
335
318
336
// get the role arn from the profile at the top of the stack (which hasn't been popped out yet)
319
- const auto arn = sourceProfiles.back ()->second .GetRoleArn ();
337
+ const auto & arn = sourceProfiles.back ()->second .GetRoleArn ();
320
338
const auto & assumedCreds = GetCredentialsFromSTS (stsCreds, arn);
321
339
sourceProfiles.back ()->second .SetCredentials (assumedCreds);
322
340
}
@@ -366,3 +384,61 @@ AWSCredentials STSProfileCredentialsProvider::GetCredentialsFromSTS(const AWSCre
366
384
Aws::STS::STSClient stsClient {credentials};
367
385
return GetCredentialsFromSTSInternal (roleArn, &stsClient);
368
386
}
387
+
388
+ AWSCredentials STSProfileCredentialsProvider::GetCredentialsFromWebIdentityInternal (const Config::Profile& profile, Aws::STS::STSClient* client)
389
+ {
390
+ Aws::String roleSessionName = profile.GetValue (" role_session_name" );
391
+ if (roleSessionName.empty ())
392
+ {
393
+ roleSessionName = Aws::Utils::UUID::PseudoRandomUUID ();
394
+ }
395
+
396
+ Aws::String token;
397
+ {
398
+ auto & tokenPath = profile.GetValue (" web_identity_token_file" );
399
+ Aws::IFStream tokenFile (tokenPath);
400
+ if (tokenFile) {
401
+ token = Aws::String (
402
+ (std::istreambuf_iterator<char >(tokenFile)),
403
+ std::istreambuf_iterator<char >());
404
+ }
405
+ else {
406
+ AWS_LOGSTREAM_ERROR (CLASS_TAG, " Can't open token file: " << tokenPath);
407
+ return {};
408
+ }
409
+ }
410
+
411
+ using namespace Aws ::STS::Model;
412
+ AssumeRoleWithWebIdentityRequest assumeRoleRequest;
413
+ assumeRoleRequest
414
+ .WithRoleArn (profile.GetRoleArn ())
415
+ .WithRoleSessionName (roleSessionName)
416
+ .WithWebIdentityToken (token)
417
+ .WithDurationSeconds (static_cast <int >(std::chrono::seconds (m_duration).count ()));
418
+ auto outcome = client->AssumeRoleWithWebIdentity (assumeRoleRequest);
419
+ if (outcome.IsSuccess ())
420
+ {
421
+ const auto & modelCredentials = outcome.GetResult ().GetCredentials ();
422
+ return {modelCredentials.GetAccessKeyId (),
423
+ modelCredentials.GetSecretAccessKey (),
424
+ modelCredentials.GetSessionToken (),
425
+ modelCredentials.GetExpiration ()};
426
+ }
427
+ else
428
+ {
429
+ AWS_LOGSTREAM_ERROR (CLASS_TAG, " Failed to assume role " << profile.GetRoleArn ());
430
+ }
431
+ return {};
432
+ }
433
+
434
+ AWSCredentials STSProfileCredentialsProvider::GetCredentialsFromWebIdentity (const Config::Profile& profile)
435
+ {
436
+ using namespace Aws ::STS::Model;
437
+ if (m_stsClientFactory) {
438
+ auto client = m_stsClientFactory ({});
439
+ return GetCredentialsFromWebIdentityInternal (profile, client.get ());
440
+ }
441
+
442
+ Aws::STS::STSClient stsClient{AWSCredentials{}};
443
+ return GetCredentialsFromWebIdentityInternal (profile, &stsClient);
444
+ }
0 commit comments