Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .changelog/feature-refresh.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"type": "feature",
"category": "aws-cpp-sdk-core",
"contributor": "kai-ion",
"description": "Add the shared credential refresh lifecycle to built-in credential providers: advisory and mandatory refresh windows, a jittered backoff that keeps serving cached credentials when a refresh fails, and invalidation of credentials rejected with ExpiredToken or InvalidToken"
}
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,11 @@ namespace Aws
*/
virtual AWSCredentials GetAWSCredentials() = 0;

/**
* Invalidate tells a caching provider that a service rejected the credentials with this access key ID.
*/
virtual void Invalidate(const Aws::String& /*rejectedAccessKeyId*/) {}

protected:
/**
* The default implementation keeps up with the cache times and lets you know if it's time to refresh your internal caching
Expand Down Expand Up @@ -227,15 +232,16 @@ namespace Aws
*/
AWSCredentials GetAWSCredentials() override;

/**
* Invalidate marks the cached credentials for refresh if they match accessKeyId.
*/
void Invalidate(const Aws::String& accessKeyId) override;

protected:
void Reload() override;

private:
bool ExpiresSoon() const;
void RefreshIfExpired();

std::shared_ptr<Aws::Config::AWSProfileConfigLoader> m_ec2MetadataConfigLoader;
long m_loadFrequencyMs;
std::shared_ptr<Aws::Config::EC2InstanceProfileConfigLoader> m_ec2MetadataConfigLoader;
};

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,11 @@ namespace Aws
*/
virtual AWSCredentials GetAWSCredentials() override;

/**
* Invalidate forwards to the provider that supplied the current credentials.
*/
void Invalidate(const Aws::String& accessKeyId) override;

/**
* Gets all providers stored in this chain.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

#include <aws/core/Core_EXPORTS.h>
#include <aws/core/auth/AWSCredentialsProvider.h>
#include <aws/core/internal/CredentialsCachingProvider.h>

#include <atomic>
#include <memory>
Expand Down Expand Up @@ -37,6 +38,16 @@ class AWS_CORE_API CrtCredentialsProvider : public AWSCredentialsProvider {
*/
AWSCredentials GetAWSCredentials() override;

/**
* Invalidate marks the cached credentials for refresh if they match accessKeyId.
*/
void Invalidate(const Aws::String& accessKeyId) override;

protected:
CrtCredentialsProvider(const std::function<std::shared_ptr<Aws::Crt::Auth::ICredentialsProvider>()>& credentialsProviderFactory,
std::chrono::milliseconds providerFuturesTimeoutMs, Aws::Client::UserAgentFeature userAgentFeature,
const Aws::String& providerName, Aws::Internal::RefreshFailurePolicy failurePolicy);

private:
enum class STATE {
INITIALIZED,
Expand All @@ -45,13 +56,14 @@ class AWS_CORE_API CrtCredentialsProvider : public AWSCredentialsProvider {

static AWSCredentials ExtractCredentialsFromCrt(const Aws::Crt::Auth::Credentials& crtCredentials);
void Reload() override;
void RefreshIfExpired();

std::shared_ptr<Aws::Crt::Auth::ICredentialsProvider> m_credentialsProvider;
AWSCredentials m_credentials;
std::chrono::milliseconds m_providerFuturesTimeoutMs;
Aws::Client::UserAgentFeature m_userAgentFeature;
Aws::String m_providerName;
AWSCredentials RetrieveForCache();
std::shared_ptr<AWSCredentialsProvider> m_cachingProvider;
STATE m_state{STATE::NOT_INITIALIZED};
};
} // namespace Auth
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,11 @@ namespace Aws
*/
AWSCredentials GetAWSCredentials() override;

/**
* Invalidate marks the cached credentials for refresh if they match accessKeyId.
*/
void Invalidate(const Aws::String& accessKeyId) override;

static const char AWS_CONTAINER_AUTHORIZATION_TOKEN_FILE[];
static const char AWS_CONTAINER_CREDENTIALS_RELATIVE_URI[];
static const char AWS_CONTAINER_CREDENTIALS_FULL_URI[];
Expand All @@ -102,16 +107,14 @@ namespace Aws
void Reload() override;

private:
bool ExpiresSoon() const;
void RefreshIfExpired();

Aws::String LoadTokenFromFile() const;

std::shared_ptr<Aws::Internal::ECSCredentialsClient> m_ecsCredentialsClient;
Aws::String m_authTokenFilePath;

long m_loadFrequencyMs = REFRESH_THRESHOLD;
Aws::Auth::AWSCredentials m_credentials;
AWSCredentials RetrieveForCache();
std::shared_ptr<AWSCredentialsProvider> m_cachingProvider;
};

// GeneralHTTPCredentialsProvider was previously known as TaskRoleCredentialsProvider or "ECS credentials provider"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,11 @@ class AWS_CORE_API ProfileCredentialsProvider : public AWSCredentialsProvider {
*/
AWSCredentials GetAWSCredentials() override;

/**
* Invalidate marks the cached credentials for refresh if they match accessKeyId.
*/
void Invalidate(const Aws::String& accessKeyId) override;

/**
* Returns the fullpath of the calculated credentials profile file
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,11 @@ namespace Aws {
*/
AWSCredentials GetAWSCredentials() override;

/**
* Invalidate marks the cached credentials for refresh if they match accessKeyId.
*/
void Invalidate(const Aws::String& accessKeyId) override;

private:
Aws::UniquePtr<Aws::Internal::SSOCredentialsClient> m_client;
Aws::Auth::AWSCredentials m_credentials;
Expand All @@ -45,9 +50,10 @@ namespace Aws {
Aws::Auth::SSOBearerTokenProvider m_bearerTokenProvider;
// The client configuration to use
std::shared_ptr<const Aws::Client::ClientConfiguration> m_config;
AWSCredentials RetrieveForCache();
std::shared_ptr<AWSCredentialsProvider> m_cachingProvider;

void Reload() override;
void RefreshIfExpired();
Aws::String LoadAccessTokenFile(const Aws::String& ssoAccessTokenPath);
};
} // namespace Auth
Expand Down
4 changes: 4 additions & 0 deletions src/aws-cpp-sdk-core/include/aws/core/client/AWSClient.h
Original file line number Diff line number Diff line change
Expand Up @@ -371,6 +371,10 @@ namespace Aws
* return true if signer's clock is adjusted, false otherwise.
*/
bool AdjustClockSkew(HttpResponseOutcome& outcome, const Aws::Utils::DateTime& timeRequestSent, const Aws::Utils::DateTime& timeResponseReceived, std::chrono::milliseconds attemptSkew) const;
/**
* InvalidateCredentials invalidates the provider's credentials when a service rejects them as expired or invalid.
*/
void InvalidateCredentials(const AWSError<CoreErrors>& error, const Aws::String& accessKeyId) const;
std::shared_ptr<Aws::Http::HttpRequest> StartOneAttemptAsync(const std::shared_ptr<AWSClientAsyncRequestContext>& context) const;
Aws::Http::HttpClient::AttemptOutcome OnResponseReceivedAsync(const std::shared_ptr<AWSClientAsyncRequestContext>& context, std::shared_ptr<Aws::Http::HttpResponse> httpResponse) const;
Aws::Http::HttpClient::AttemptOutcome OnAttemptCompleteAsync(const std::shared_ptr<AWSClientAsyncRequestContext>& context, HttpResponseOutcome&& outcome) const;
Expand Down
2 changes: 2 additions & 0 deletions src/aws-cpp-sdk-core/include/aws/core/client/CoreErrors.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ namespace Aws
NOT_INITIALIZED = 25,
MEMORY_ALLOCATION = 26,
NOT_IMPLEMENTED = 27,
EXPIRED_TOKEN = 28,
INVALID_TOKEN = 29,

NETWORK_CONNECTION = 99, // General failure to send message to service

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,12 @@ namespace Aws
class EC2MetadataClient;
}

namespace Auth
{
class AWSCredentialsProvider;
class InstanceProfileCredentialsProvider;
}

namespace Config
{
static const char* const INSTANCE_PROFILE_KEY = "InstanceProfile";
Expand All @@ -44,9 +50,15 @@ namespace Aws
protected:
virtual bool LoadInternal() override;
private:
friend class Aws::Auth::InstanceProfileCredentialsProvider;

bool RetrieveCredentials();
Aws::Auth::AWSCredentials GetCredentials() const;
void Invalidate(const Aws::String& accessKeyId);

std::shared_ptr<Aws::Internal::EC2MetadataClient> m_ec2metadataClient;
int64_t credentialsValidUntilMillis = 0;
int64_t calculateRetryTime() const;
Aws::Auth::AWSCredentials RetrieveForCache();
std::shared_ptr<Aws::Auth::AWSCredentialsProvider> m_cachingProvider;
};
}
}
Loading
Loading