-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Adding CRTProfileCredentialsProvider for CRT-based profile credential #3713
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
pulimsr
wants to merge
7
commits into
main
Choose a base branch
from
crt-profile-credentials-provider
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
7 commits
Select commit
Hold shift + click to select a range
c14eda9
Adding CRTProfileCredentialsProvider for CRT-based profile credential
pulimsr 3dcacf1
Merge branch 'main' of https://github.com/aws/aws-sdk-cpp into crt-pr…
pulimsr 288b730
Merge branch 'main' of https://github.com/aws/aws-sdk-cpp into crt-pr…
pulimsr 3a600b2
implementing the currently existing profile provider to add CRT profi…
pulimsr 0d459ee
merging from main
pulimsr 5eb8769
Merge branch 'main' of https://github.com/aws/aws-sdk-cpp into crt-pr…
pulimsr 444c9d8
changing names and moving functions to the pointer class
pulimsr File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
51 changes: 51 additions & 0 deletions
51
src/aws-cpp-sdk-core/include/aws/core/auth/ProfileCredentialsProvider.h
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,51 @@ | ||
| #pragma once | ||
|
|
||
| #include <aws/core/Core_EXPORTS.h> | ||
| #include <aws/core/utils/memory/stl/AWSString.h> | ||
| #include <aws/core/auth/AWSCredentials.h> | ||
| #include <aws/core/auth/AWSCredentialsProvider.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 ProfileCredentialsProvider : public AWSCredentialsProvider { | ||
| public: | ||
| /** | ||
| * Initializes with refreshRateMs as the frequency at which the file is reparsed in milliseconds. Defaults to 5 minutes. | ||
| */ | ||
| ProfileCredentialsProvider(long refreshRateMs = REFRESH_THRESHOLD); | ||
|
|
||
| /** | ||
| * Initializes with a profile override and | ||
| * refreshRateMs as the frequency at which the file is reparsed in milliseconds. Defaults to 5 minutes. | ||
| */ | ||
| ProfileCredentialsProvider(const char* profile, long refreshRateMs = REFRESH_THRESHOLD); | ||
|
|
||
| /** | ||
| * Retrieves the credentials if found, otherwise returns empty credential set. | ||
| */ | ||
| AWSCredentials GetAWSCredentials() override; | ||
|
|
||
| /** | ||
| * Returns the fullpath of the calculated credentials profile file | ||
| */ | ||
| static Aws::String GetCredentialsProfileFilename(); | ||
|
|
||
| /** | ||
| * Returns the directory storing the profile file. | ||
| */ | ||
| static Aws::String GetProfileDirectory(); | ||
|
|
||
| protected: | ||
| void Reload() override; | ||
|
|
||
| private: | ||
| class ProfileCredentialsProviderImp; | ||
| std::shared_ptr<ProfileCredentialsProviderImp> m_impl; | ||
| }; | ||
| } // namespace Auth | ||
| } // namespace Aws |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
111 changes: 111 additions & 0 deletions
111
src/aws-cpp-sdk-core/source/auth/ProfileCredentialsProvider.cpp
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,111 @@ | ||
| #include <aws/core/auth/AWSCredentialsProvider.h> | ||
|
|
||
| #include <aws/core/config/AWSProfileConfigLoader.h> | ||
| #include <aws/core/platform/Environment.h> | ||
| #include <aws/core/platform/FileSystem.h> | ||
| #include <aws/core/utils/logging/LogMacros.h> | ||
| #include <aws/core/client/UserAgent.h> | ||
| #include <cstdlib> | ||
| #include <string.h> | ||
| #include <climits> | ||
| #include <aws/core/auth/ProfileCredentialsProvider.h> | ||
|
|
||
| using namespace Aws::Auth; | ||
|
|
||
| class ProfileCredentialsProvider::ProfileCredentialsProviderImp : public AWSCredentialsProvider { | ||
| public: | ||
| ProfileCredentialsProviderImp(long refreshRateMs) | ||
| : m_profileToUse(Aws::Auth::GetConfigProfileName()), | ||
| m_credentialsFileLoader(GetCredentialsProfileFilename()), | ||
| m_loadFrequencyMs(refreshRateMs) { | ||
| AWS_LOGSTREAM_INFO(PROFILE_LOG_TAG, "Setting provider to read credentials from " | ||
| << GetCredentialsProfileFilename() << " for credentials file" | ||
| << " and " << GetConfigProfileFilename() << " for the config file " | ||
| << ", for use with profile " << m_profileToUse); | ||
| } | ||
|
|
||
| ProfileCredentialsProviderImp(const char* profile, long refreshRateMs) | ||
| : m_profileToUse(profile), m_credentialsFileLoader(GetCredentialsProfileFilename()), m_loadFrequencyMs(refreshRateMs) { | ||
| AWS_LOGSTREAM_INFO(PROFILE_LOG_TAG, "Setting provider to read credentials from " | ||
| << GetCredentialsProfileFilename() << " for credentials file" | ||
| << " and " << GetConfigProfileFilename() << " for the config file " | ||
| << ", for use with profile " << m_profileToUse); | ||
| } | ||
|
|
||
| static Aws::String GetCredentialsProfileFilename() { | ||
| auto credentialsFileNameFromVar = Aws::Environment::GetEnv(AWS_CREDENTIALS_FILE); | ||
|
|
||
| if (credentialsFileNameFromVar.empty()) { | ||
| return Aws::FileSystem::GetHomeDirectory() + PROFILE_DIRECTORY + PATH_DELIM + DEFAULT_CREDENTIALS_FILE; | ||
| } | ||
| return credentialsFileNameFromVar; | ||
| } | ||
|
|
||
| static Aws::String GetProfileDirectory() { | ||
| Aws::String credentialsFileName = GetCredentialsProfileFilename(); | ||
| auto lastSeparator = credentialsFileName.find_last_of(PATH_DELIM); | ||
| if (lastSeparator != std::string::npos) { | ||
| return credentialsFileName.substr(0, lastSeparator); | ||
| } else { | ||
| return {}; | ||
| } | ||
| } | ||
|
|
||
| AWSCredentials GetAWSCredentials() override { | ||
| RefreshIfExpired(); | ||
| ReaderLockGuard guard(m_reloadLock); | ||
| const Aws::Map<Aws::String, Aws::Config::Profile>& profiles = m_credentialsFileLoader.GetProfiles(); | ||
| auto credsFileProfileIter = profiles.find(m_profileToUse); | ||
|
|
||
| if (credsFileProfileIter != profiles.end()) { | ||
| AWSCredentials credentials = credsFileProfileIter->second.GetCredentials(); | ||
| if (!credentials.IsEmpty()) { | ||
| credentials.AddUserAgentFeature(UserAgentFeature::CREDENTIALS_PROFILE); | ||
| } | ||
| return credentials; | ||
| } | ||
|
|
||
| return AWSCredentials(); | ||
| } | ||
|
|
||
| void Reload() override { | ||
| m_credentialsFileLoader.Load(); | ||
| AWSCredentialsProvider::Reload(); | ||
| } | ||
|
|
||
| private: | ||
| Aws::String m_profileToUse; | ||
| Aws::Config::AWSConfigFileProfileConfigLoader m_credentialsFileLoader; | ||
| long m_loadFrequencyMs; | ||
|
|
||
| void RefreshIfExpired() { | ||
| ReaderLockGuard guard(m_reloadLock); | ||
| if (!IsTimeToRefresh(m_loadFrequencyMs)) { | ||
| return; | ||
| } | ||
|
|
||
| guard.UpgradeToWriterLock(); | ||
| if (!IsTimeToRefresh(m_loadFrequencyMs)) // double-checked lock to avoid refreshing twice | ||
| { | ||
| return; | ||
| } | ||
|
|
||
| Reload(); | ||
| } | ||
| }; | ||
|
|
||
| ProfileCredentialsProvider::ProfileCredentialsProvider(long refreshRateMs) | ||
| : m_impl(std::make_shared<ProfileCredentialsProviderImp>(refreshRateMs)) {} | ||
|
|
||
| ProfileCredentialsProvider::ProfileCredentialsProvider(const char* profile, long refreshRateMs) | ||
| : m_impl(std::make_shared<ProfileCredentialsProviderImp>(profile, refreshRateMs)) {} | ||
|
|
||
| Aws::String ProfileCredentialsProvider::GetCredentialsProfileFilename() { | ||
| return ProfileCredentialsProviderImp::GetCredentialsProfileFilename(); | ||
| } | ||
|
|
||
| Aws::String ProfileCredentialsProvider::GetProfileDirectory() { return ProfileCredentialsProviderImp::GetProfileDirectory(); } | ||
|
|
||
| AWSCredentials ProfileCredentialsProvider::GetAWSCredentials() { return m_impl->GetAWSCredentials(); } | ||
|
|
||
| void ProfileCredentialsProvider::Reload() { m_impl->Reload(); } | ||
125 changes: 125 additions & 0 deletions
125
tests/aws-cpp-sdk-core-tests/aws/auth/ProfileCredentialsProviderTests.cpp
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,125 @@ | ||
| #include <aws/core/auth/ProfileCredentialsProvider.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 ProfileCredentialsProviderTests : 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(ProfileCredentialsProviderTests, 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(); | ||
|
|
||
| ProfileCredentialsProvider provider; | ||
| auto credentials = provider.GetAWSCredentials(); | ||
|
|
||
| EXPECT_STREQ("AKIATEST123", credentials.GetAWSAccessKeyId().c_str()); | ||
| EXPECT_STREQ("SecretKey456", credentials.GetAWSSecretKey().c_str()); | ||
| } | ||
|
|
||
| TEST_F(ProfileCredentialsProviderTests, 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(); | ||
|
|
||
| ProfileCredentialsProvider provider("test-profile"); | ||
| auto credentials = provider.GetAWSCredentials(); | ||
|
|
||
| EXPECT_STREQ("TestKey", credentials.GetAWSAccessKeyId().c_str()); | ||
| EXPECT_STREQ("TestSecret", credentials.GetAWSSecretKey().c_str()); | ||
| } | ||
|
|
||
| TEST_F(ProfileCredentialsProviderTests, 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(); | ||
|
|
||
| ProfileCredentialsProvider 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(ProfileCredentialsProviderTests, 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(); | ||
|
|
||
| ProfileCredentialsProvider provider("nonexistent"); | ||
| auto credentials = provider.GetAWSCredentials(); | ||
|
|
||
| EXPECT_TRUE(credentials.IsEmpty()); | ||
| } | ||
|
|
||
| TEST_F(ProfileCredentialsProviderTests, DISABLED_ProcessCredentials) { | ||
| std::ofstream config(m_configFile.c_str()); | ||
| config << "[default]\n"; | ||
| config << "credential_process = echo '{\"Version\": 1, \"AccessKeyId\": \"ProcessKey\", \"SecretAccessKey\": \"ProcessSecret\"}'\n"; | ||
| config.close(); | ||
|
|
||
| ProfileCredentialsProvider provider; | ||
| auto credentials = provider.GetAWSCredentials(); | ||
|
|
||
| EXPECT_STREQ("ProcessKey", credentials.GetAWSAccessKeyId().c_str()); | ||
| EXPECT_STREQ("ProcessSecret", credentials.GetAWSSecretKey().c_str()); | ||
| } |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
do we need
cstdlib/string.h/climitshere? they seem sort of suspect imports