/** * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. * SPDX-License-Identifier: Apache-2.0. */ #include #include #include #include #include using namespace Aws::Utils; using namespace Aws::STS; namespace Aws { namespace Auth { static const char* CLASS_TAG = "STSAssumeRoleCredentialsProvider"; //60 seconds; static const int ACCOUNT_FOR_LATENCY = 60; STSAssumeRoleCredentialsProvider::STSAssumeRoleCredentialsProvider(const Aws::String& roleArn, const Aws::String& sessionName, const Aws::String& externalId, int loadFrequency, const std::shared_ptr& stsClient) : m_stsClient(stsClient == nullptr ? Aws::MakeShared(CLASS_TAG) : stsClient), m_roleArn(roleArn), m_sessionName(sessionName), m_externalId(externalId), m_expiry(0), m_loadFrequency(loadFrequency) { if (sessionName.empty()) { Aws::StringStream ss; ss << "aws-sdk-cpp-" << Aws::Utils::DateTime::CurrentTimeMillis(); m_sessionName = ss.str(); } AWS_LOGSTREAM_INFO(CLASS_TAG, "Role ARN set to: " << m_roleArn << ". Session Name set to: " << m_sessionName); } AWSCredentials STSAssumeRoleCredentialsProvider::GetAWSCredentials() { LoadCredentialsFromSTS(); std::lock_guard locker(m_credsMutex); return m_cachedCredentials; } void STSAssumeRoleCredentialsProvider::LoadCredentialsFromSTS() { //standard check lock check auto diffSeconds = static_cast(DateTime::Now().SecondsWithMSPrecision() - DateTime(m_expiry.load()).SecondsWithMSPrecision()); if (diffSeconds > 0 - ACCOUNT_FOR_LATENCY) { AWS_LOGSTREAM_DEBUG(CLASS_TAG, "Credentials have expired with diff of " << diffSeconds << " since last credentials pull."); AWS_LOGSTREAM_TRACE(CLASS_TAG, "Grabbing lock."); std::lock_guard locker(m_credsMutex); AWS_LOGSTREAM_TRACE(CLASS_TAG, "Lock acquired. Checking expiration again."); diffSeconds = static_cast(DateTime::Now().SecondsWithMSPrecision() - DateTime(m_expiry.load()).SecondsWithMSPrecision()); if (diffSeconds > 0 - ACCOUNT_FOR_LATENCY) { AWS_LOGSTREAM_INFO(CLASS_TAG, "Credentials have expired with diff of " << diffSeconds << " since last credentials pull."); Model::AssumeRoleRequest assumeRoleRequest; assumeRoleRequest.WithRoleArn(m_roleArn) .WithRoleSessionName(m_sessionName) .WithDurationSeconds(m_loadFrequency); if (!m_externalId.empty()) { assumeRoleRequest.SetExternalId(m_externalId); } auto assumeRoleOutcome = m_stsClient->AssumeRole(assumeRoleRequest); if (assumeRoleOutcome.IsSuccess()) { const auto& stsCredentials = assumeRoleOutcome.GetResult().GetCredentials(); m_cachedCredentials = AWSCredentials(stsCredentials.GetAccessKeyId(), stsCredentials.GetSecretAccessKey(), stsCredentials.GetSessionToken()); m_expiry = stsCredentials.GetExpiration().Millis(); AWS_LOGSTREAM_DEBUG(CLASS_TAG, "Credentials refreshed with new expiry " << DateTime(m_expiry.load()).ToGmtString(DateFormat::ISO_8601)); } else { AWS_LOGSTREAM_ERROR(CLASS_TAG, "Credentials refresh failed with error " << assumeRoleOutcome.GetError().GetExceptionName() << " message: " << assumeRoleOutcome.GetError().GetMessage()); } } } } } }