55
66#include  < aws/identity-management/auth/STSProfileCredentialsProvider.h> 
77#include  < aws/sts/model/AssumeRoleRequest.h> 
8+ #include  < aws/sts/model/AssumeRoleWithWebIdentityRequest.h> 
89#include  < aws/sts/STSClient.h> 
910#include  < aws/core/utils/logging/LogMacros.h> 
1011#include  < aws/core/utils/Outcome.h> 
1112#include  < aws/core/utils/UUID.h> 
1213
14+ #include  < fstream> 
1315#include  < utility> 
1416
1517using  namespace  Aws ; 
@@ -88,25 +90,27 @@ enum class ProfileState
8890    Process,
8991    SourceProfile,
9092    SelfReferencing, //  special case of SourceProfile.
93+     RoleARNWebIdentity
9194};
9295
9396/* 
9497 * 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+ +---------+-----------+-----------+--------------+------------+ 
110114
111115*/ 
112116static  ProfileState CheckProfile (const  Aws::Config::Profile& profile, bool  topLevelProfile)
@@ -115,6 +119,7 @@ static ProfileState CheckProfile(const Aws::Config::Profile& profile, bool topLe
115119    constexpr  int  PROCESS_CREDENTIALS = 2 ;
116120    constexpr  int  SOURCE_PROFILE = 4 ;
117121    constexpr  int  ROLE_ARN = 8 ;
122+     constexpr  int  WEB_IDENTITY_TOKEN_FILE = 16 ;
118123
119124    int  state = 0 ;
120125
@@ -138,6 +143,11 @@ static ProfileState CheckProfile(const Aws::Config::Profile& profile, bool topLe
138143        state += ROLE_ARN;
139144    }
140145
146+     if  (!profile.GetValue (" web_identity_token_file" empty ())
147+     {
148+         state += WEB_IDENTITY_TOKEN_FILE;
149+     }
150+ 
141151    if  (topLevelProfile)
142152    {
143153        switch (state)
@@ -155,6 +165,8 @@ static ProfileState CheckProfile(const Aws::Config::Profile& profile, bool topLe
155165                }
156166                //  source-profile over-rule static credentials in top-level profiles (except when self-referencing)
157167                return  ProfileState::SourceProfile;
168+             case  24 : //  role arn && web identity
169+                 return  ProfileState::RoleARNWebIdentity;
158170            default :
159171                //  All other cases are considered malformed configuration.
160172                return  ProfileState::Invalid;
@@ -176,6 +188,8 @@ static ProfileState CheckProfile(const Aws::Config::Profile& profile, bool topLe
176188                    return  ProfileState::SelfReferencing;
177189                }
178190                return  ProfileState::Static; //  static credentials over-rule source-profile (except when self-referencing)
191+             case  24 : //  role arn && web identity
192+                 return  ProfileState::RoleARNWebIdentity;
179193            default :
180194                //  All other cases are considered malformed configuration.
181195                return  ProfileState::Invalid;
@@ -302,10 +316,14 @@ void STSProfileCredentialsProvider::Reload()
302316
303317    while  (sourceProfiles.size () > 1 )
304318    {
305-         const  auto  profile = sourceProfiles.back ()->second ;
319+         const  auto &  profile = sourceProfiles.back ()->second ;
306320        sourceProfiles.pop_back ();
307321        AWSCredentials stsCreds;
308-         if  (profile.GetCredentialProcess ().empty ())
322+         if  (CheckProfile (profile, false  /* topLevelProfile*/ 
323+         {
324+             stsCreds = GetCredentialsFromWebIdentity (profile);
325+         }
326+         else  if  (profile.GetCredentialProcess ().empty ())
309327        {
310328            assert (!profile.GetCredentials ().IsEmpty ());
311329            stsCreds = profile.GetCredentials ();
@@ -316,7 +334,7 @@ void STSProfileCredentialsProvider::Reload()
316334        }
317335
318336        //  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 ();
320338        const  auto & assumedCreds = GetCredentialsFromSTS (stsCreds, arn);
321339        sourceProfiles.back ()->second .SetCredentials (assumedCreds);
322340    }
@@ -366,3 +384,61 @@ AWSCredentials STSProfileCredentialsProvider::GetCredentialsFromSTS(const AWSCre
366384    Aws::STS::STSClient stsClient {credentials};
367385    return  GetCredentialsFromSTSInternal (roleArn, &stsClient);
368386}
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: " 
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 " 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