Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
c14eda9
Adding CRTProfileCredentialsProvider for CRT-based profile credential
pulimsr Feb 3, 2026
3dcacf1
Merge branch 'main' of https://github.com/aws/aws-sdk-cpp into crt-pr…
pulimsr Feb 3, 2026
288b730
Merge branch 'main' of https://github.com/aws/aws-sdk-cpp into crt-pr…
pulimsr Feb 4, 2026
3a600b2
implementing the currently existing profile provider to add CRT profi…
pulimsr Feb 4, 2026
0d459ee
merging from main
pulimsr Feb 5, 2026
5eb8769
Merge branch 'main' of https://github.com/aws/aws-sdk-cpp into crt-pr…
pulimsr Feb 5, 2026
444c9d8
changing names and moving functions to the pointer class
pulimsr Feb 6, 2026
2f38818
Merge branch 'main' into crt-profile-credentials-provider
pulimsr Feb 9, 2026
da5b2f0
Deprecate ProfileConfigFileAWSCredentialsProvider and migrate callers…
pulimsr Feb 9, 2026
65e5eb9
Merge branch 'main' into crt-profile-credentials-provider
pulimsr Feb 10, 2026
621afbf
using the new profile credential provider class
pulimsr Feb 10, 2026
00e8616
removing AWS_DEPRECATED for now
pulimsr Feb 10, 2026
69959c7
Merge branch 'main' into crt-profile-credentials-provider
pulimsr Feb 10, 2026
233c9c0
Merge branch 'main' into crt-profile-credentials-provider
pulimsr Feb 11, 2026
d2bca9f
adding missing headers
pulimsr Feb 11, 2026
ed61b12
Adding missing Aws::Client namespace for UserAgentFeature
pulimsr Feb 11, 2026
575f570
adding namespaces
pulimsr Feb 11, 2026
8a7967c
fixing missing constant declarations in ProfileCredentialsProvider
pulimsr Feb 11, 2026
29b61af
fixing missing constant declarations in ProfileCredentialsProvider
pulimsr Feb 11, 2026
dd2dc8e
adding namespace
pulimsr Feb 11, 2026
1b0c159
extern variables
pulimsr Feb 12, 2026
01057cd
Merge branch 'main' into crt-profile-credentials-provider
pulimsr Feb 12, 2026
bb2223e
symbol collision in ProfileCredentialsProvider
pulimsr Feb 12, 2026
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
#pragma once

#include <aws/core/Core_EXPORTS.h>
#include <aws/core/auth/AWSCredentialsProvider.h>
//#include <aws/core/auth/AWSCredentials.h>
//#include <aws/crt/auth/Credentials.h>
#include <memory>

namespace Aws
{
namespace Auth
{
/**
* CRT-based credentials provider that sources credentials from config files with full SEP compliance.
* Supports assume role, credential_source, role chaining, and all SEP scenarios.
*/
class AWS_CORE_API CRTProfileCredentialsProvider : public AWSCredentialsProvider
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lets not name this CRTProfileCredentialsProvider because its just going to be the new ProfileCredentialsProvider. lets just name it ProfileCredentialsProvider. also please add a AWS_DEPRECATED to the old class so that people using it directly will get a warning to update to the new one.

{
public:
CRTProfileCredentialsProvider();
explicit CRTProfileCredentialsProvider(const char* profileName);
~CRTProfileCredentialsProvider();

CRTProfileCredentialsProvider(const CRTProfileCredentialsProvider&) = delete;
CRTProfileCredentialsProvider& operator=(const CRTProfileCredentialsProvider&) = delete;

AWSCredentials GetAWSCredentials() override;

protected:
void Reload() override;

private:
class Impl;
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So when trying to do pimpl with the profile credentials provider i see it more so going like this.

In the real profile credentials provider

class AWS_CORE_API ProfileConfigFileAWSCredentialsProvider : public AWSCredentialsProvider
{
public:
  ProfileConfigFileAWSCredentialsProvider(long refreshRateMs = REFRESH_THRESHOLD);
  ProfileConfigFileAWSCredentialsProvider(const char* profile, long refreshRateMs = REFRESH_THRESHOLD);
  AWSCredentials GetAWSCredentials() override;
  static Aws::String GetCredentialsProfileFilename();
  static Aws::String GetProfileDirectory();

protected:
  void Reload() override;
private:
  void RefreshIfExpired();
  Aws::String m_profileToUse;
  Aws::Config::AWSConfigFileProfileConfigLoader m_credentialsFileLoader;
  long m_loadFrequencyMs;
};

becomes

class ProfileCredentialsProviderImpl;

class AWS_CORE_API ProfileConfigFileAWSCredentialsProvider : public AWSCredentialsProvider
{
public:
  ProfileConfigFileAWSCredentialsProvider(long refreshRateMs = REFRESH_THRESHOLD);
  ProfileConfigFileAWSCredentialsProvider(const char* profile, long refreshRateMs = REFRESH_THRESHOLD);
  AWSCredentials GetAWSCredentials() override;
  static Aws::String GetCredentialsProfileFilename();
  static Aws::String GetProfileDirectory();

protected:
  void Reload() override;
  Aws::UniquePtr<ProfileCredentialsProviderImpl> m_impl;
};

then in the cpp file for for ProfileConfigFileAWSCredentialsProvider we construct a point to ProfileCredentialsProviderImpl.

That is step one to move the existing credentials provider to PIMPL.

Then step two is your change, ProfileCredentialsProviderImpl is changed to the implementation of your existing CRTProfileCredentialsProvider.

So:
Step 1: change ProfileConfigFileAWSCredentialsProvider to use PIMPL to current existing implementation called ProfileCredentialsProviderImpl.
Step 2: change ProfileCredentialsProviderImpl to us the implementation from this PR.

std::shared_ptr<Impl> m_impl;
};
}
}
78 changes: 78 additions & 0 deletions src/aws-cpp-sdk-core/source/auth/CRTProfileCredentialsProvider.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
#include <aws/core/auth/CRTProfileCredentialsProvider.h>
#include <aws/core/Globals.h>
#include <aws/core/platform/Environment.h>
#include <condition_variable>
#include <mutex>
#include <aws/crt/auth/Credentials.h>

using namespace Aws::Auth;

class CRTProfileCredentialsProvider::Impl {
public:
std::shared_ptr<Aws::Crt::Auth::ICredentialsProvider> m_crtProvider;
};

CRTProfileCredentialsProvider::CRTProfileCredentialsProvider()
: m_impl(Aws::MakeShared<Impl>("CRTProfileCredentialsProvider")){
Aws::Crt::Auth::CredentialsProviderProfileConfig config{};
config.Bootstrap = GetDefaultClientBootstrap();
auto profileName = Aws::Environment::GetEnv("AWS_PROFILE");
if(!profileName.empty()){
config.ProfileNameOverride = Aws::Crt::ByteCursorFromCString(profileName.c_str());
}
m_impl->m_crtProvider = Aws::Crt::Auth::CredentialsProvider::CreateCredentialsProviderProfile(config);
}

CRTProfileCredentialsProvider::CRTProfileCredentialsProvider(const char *profileName)
:m_impl(Aws::MakeShared<Impl>("CRTProfileCredentialsProvider")){
Aws::Crt::Auth::CredentialsProviderProfileConfig config{};
config.Bootstrap = GetDefaultClientBootstrap();
if (profileName) {
config.ProfileNameOverride = Aws::Crt::ByteCursorFromCString(profileName);
}
m_impl->m_crtProvider = Aws::Crt::Auth::CredentialsProvider::CreateCredentialsProviderProfile(config);
}

CRTProfileCredentialsProvider::~CRTProfileCredentialsProvider() = default;

AWSCredentials CRTProfileCredentialsProvider::GetAWSCredentials() {
if (!m_impl || !m_impl->m_crtProvider) {
return AWSCredentials{};
}
AWSCredentials credentials;
std::mutex mtx;
std::condition_variable cv;
bool done = false;

m_impl->m_crtProvider->GetCredentials([&](std::shared_ptr<Aws::Crt::Auth::Credentials> crtCreds, int errorCode) {
{
std::lock_guard<std::mutex> lock(mtx);
if (errorCode == 0 && crtCreds) {
auto accessKey = crtCreds->GetAccessKeyId();
auto secretKey = crtCreds->GetSecretAccessKey();
auto sessionToken = crtCreds->GetSessionToken();

credentials.SetAWSAccessKeyId({reinterpret_cast<char*>(accessKey.ptr), accessKey.len});
credentials.SetAWSSecretKey({reinterpret_cast<char*>(secretKey.ptr), secretKey.len});
if (sessionToken.len > 0) {
credentials.SetSessionToken({reinterpret_cast<char*>(sessionToken.ptr), sessionToken.len});
}
auto expiration = crtCreds->GetExpirationTimepointInSeconds();
if (expiration > 0) {
credentials.SetExpiration(Aws::Utils::DateTime(static_cast<double>(expiration)));
}
}
done = true;
}
cv.notify_one();
});

std::unique_lock<std::mutex> lock(mtx);
cv.wait_for(lock,std::chrono::milliseconds(5000), [&done]() -> bool { return done;});
return credentials;
}

void CRTProfileCredentialsProvider::Reload() {}



Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
#include <aws/core/auth/CRTProfileCredentialsProvider.h>
#include <aws/core/platform/Environment.h>
#include <aws/core/platform/FileSystem.h>
#include <aws/core/utils/FileSystemUtils.h>
#include <aws/testing/AwsCppSdkGTestSuite.h>
#include <fstream>

using namespace Aws::Auth;

class CRTProfileCredentialsProviderTest : public Aws::Testing::AwsCppSdkGTestSuite {
protected:
void SetUp() override {
SaveEnv("AWS_CONFIG_FILE");
SaveEnv("AWS_SHARED_CREDENTIALS_FILE");
SaveEnv("AWS_PROFILE");

Aws::FileSystem::CreateDirectoryIfNotExists(GetTestDir().c_str());
m_configFile = GetTestDir() + "/config";
m_credsFile = GetTestDir() + "/credentials";

Aws::Environment::SetEnv("AWS_CONFIG_FILE", m_configFile.c_str(), 1);
Aws::Environment::SetEnv("AWS_SHARED_CREDENTIALS_FILE", m_credsFile.c_str(), 1);
}

void TearDown() override {
Aws::FileSystem::RemoveFileIfExists(m_configFile.c_str());
Aws::FileSystem::RemoveFileIfExists(m_credsFile.c_str());
RestoreEnv();
}

void SaveEnv(const char* name) {
m_savedEnv.emplace_back(name, Aws::Environment::GetEnv(name));
}

void RestoreEnv() {
for (const auto& pair : m_savedEnv) {
if (pair.second.empty()) {
Aws::Environment::UnSetEnv(pair.first);
} else {
Aws::Environment::SetEnv(pair.first, pair.second.c_str(), 1);
}
}
}

Aws::String GetTestDir() {
return Aws::FileSystem::GetHomeDirectory() + "/.aws_test_" +
Aws::Utils::StringUtils::to_string(std::this_thread::get_id());
}

Aws::String m_configFile;
Aws::String m_credsFile;
Aws::Vector<std::pair<const char*, Aws::String>> m_savedEnv;
};

TEST_F(CRTProfileCredentialsProviderTest, LoadStaticCredentials) {
std::ofstream creds(m_credsFile.c_str());
creds << "[default]\n";
creds << "aws_access_key_id = AKIATEST123\n";
creds << "aws_secret_access_key = SecretKey456\n";
creds.close();

CRTProfileCredentialsProvider provider;
auto credentials = provider.GetAWSCredentials();

EXPECT_STREQ("AKIATEST123", credentials.GetAWSAccessKeyId().c_str());
EXPECT_STREQ("SecretKey456", credentials.GetAWSSecretKey().c_str());
}

TEST_F(CRTProfileCredentialsProviderTest, LoadNamedProfile) {
std::ofstream creds(m_credsFile.c_str());
creds << "[default]\n";
creds << "aws_access_key_id = DefaultKey\n";
creds << "aws_secret_access_key = DefaultSecret\n";
creds << "\n";
creds << "[test-profile]\n";
creds << "aws_access_key_id = TestKey\n";
creds << "aws_secret_access_key = TestSecret\n";
creds.close();

CRTProfileCredentialsProvider provider("test-profile");
auto credentials = provider.GetAWSCredentials();

EXPECT_STREQ("TestKey", credentials.GetAWSAccessKeyId().c_str());
EXPECT_STREQ("TestSecret", credentials.GetAWSSecretKey().c_str());
}

TEST_F(CRTProfileCredentialsProviderTest, LoadWithSessionToken) {
std::ofstream creds(m_credsFile.c_str());
creds << "[default]\n";
creds << "aws_access_key_id = AKIATEST\n";
creds << "aws_secret_access_key = SecretKey\n";
creds << "aws_session_token = SessionToken123\n";
creds.close();

CRTProfileCredentialsProvider provider;
auto credentials = provider.GetAWSCredentials();

EXPECT_STREQ("AKIATEST", credentials.GetAWSAccessKeyId().c_str());
EXPECT_STREQ("SecretKey", credentials.GetAWSSecretKey().c_str());
EXPECT_STREQ("SessionToken123", credentials.GetSessionToken().c_str());
}

TEST_F(CRTProfileCredentialsProviderTest, MissingProfileReturnsEmpty) {
std::ofstream creds(m_credsFile.c_str());
creds << "[default]\n";
creds << "aws_access_key_id = DefaultKey\n";
creds << "aws_secret_access_key = DefaultSecret\n";
creds.close();

CRTProfileCredentialsProvider provider("nonexistent");
auto credentials = provider.GetAWSCredentials();

EXPECT_TRUE(credentials.IsEmpty());
}

TEST_F(CRTProfileCredentialsProviderTest, ProcessCredentials) {
std::ofstream config(m_configFile.c_str());
config << "[default]\n";
config << "credential_process = echo '{\"Version\": 1, \"AccessKeyId\": \"ProcessKey\", \"SecretAccessKey\": \"ProcessSecret\"}'\n";
config.close();

CRTProfileCredentialsProvider provider;
auto credentials = provider.GetAWSCredentials();

EXPECT_STREQ("ProcessKey", credentials.GetAWSAccessKeyId().c_str());
EXPECT_STREQ("ProcessSecret", credentials.GetAWSSecretKey().c_str());
}
Loading