Skip to content

Commit bd5b9ea

Browse files
committed
removed SSO checking for now
1 parent 3056255 commit bd5b9ea

File tree

5 files changed

+243
-2
lines changed

5 files changed

+243
-2
lines changed

src/aws-cpp-sdk-core/include/aws/core/client/UserAgent.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,10 @@ enum class UserAgentFeature {
3333
RESOLVED_ACCOUNT_ID,
3434
GZIP_REQUEST_COMPRESSION,
3535
CREDENTIALS_ENV_VARS,
36+
CREDENTIALS_PROFILE,
37+
CREDENTIALS_PROCESS,
38+
CREDENTIALS_IMDS,
39+
CREDENTIALS_STS_ASSUME_ROLE,
3640
};
3741

3842
class AWS_CORE_API UserAgent {

src/aws-cpp-sdk-core/source/auth/AWSCredentialsProvider.cpp

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -201,7 +201,11 @@ AWSCredentials ProfileConfigFileAWSCredentialsProvider::GetAWSCredentials()
201201

202202
if(credsFileProfileIter != profiles.end())
203203
{
204-
return credsFileProfileIter->second.GetCredentials();
204+
AWSCredentials credentials = credsFileProfileIter->second.GetCredentials();
205+
if (!credentials.IsEmpty()) {
206+
credentials.AddUserAgentFeature(UserAgentFeature::CREDENTIALS_PROFILE);
207+
}
208+
return credentials;
205209
}
206210

207211
return AWSCredentials();
@@ -265,7 +269,11 @@ AWSCredentials InstanceProfileCredentialsProvider::GetAWSCredentials()
265269
auto profileIter = profiles.find(Aws::Config::INSTANCE_PROFILE_KEY);
266270

267271
if (profileIter != profiles.end()) {
268-
return profileIter->second.GetCredentials();
272+
AWSCredentials credentials = profileIter->second.GetCredentials();
273+
if (!credentials.IsEmpty()) {
274+
credentials.AddUserAgentFeature(UserAgentFeature::CREDENTIALS_IMDS);
275+
}
276+
return credentials;
269277
}
270278
}
271279
else
@@ -357,6 +365,9 @@ void ProcessCredentialsProvider::Reload()
357365
return;
358366
}
359367
m_credentials = GetCredentialsFromProcess(command);
368+
if (!m_credentials.IsEmpty()) {
369+
m_credentials.AddUserAgentFeature(UserAgentFeature::CREDENTIALS_PROCESS);
370+
}
360371
}
361372

362373
void ProcessCredentialsProvider::RefreshIfExpired()

src/aws-cpp-sdk-core/source/auth/STSCredentialsProvider.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,11 @@ AWSCredentials STSAssumeRoleWebIdentityCredentialsProvider::GetAWSCredentials()
104104

105105
std::unique_lock<std::mutex> lock{m_refreshMutex};
106106
m_refreshSignal.wait_for(lock, m_providerFuturesTimeoutMs, [&refreshDone]() -> bool { return refreshDone; });
107+
108+
if (!credentials.IsEmpty()) {
109+
credentials.AddUserAgentFeature(Aws::Client::UserAgentFeature::CREDENTIALS_STS_ASSUME_ROLE);
110+
}
111+
107112
return credentials;
108113
}
109114

src/aws-cpp-sdk-core/source/client/UserAgent.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,10 @@ const std::pair<UserAgentFeature, const char*> BUSINESS_METRIC_MAPPING[] = {
4343
{UserAgentFeature::RESOLVED_ACCOUNT_ID, "T"},
4444
{UserAgentFeature::GZIP_REQUEST_COMPRESSION, "L"},
4545
{UserAgentFeature::CREDENTIALS_ENV_VARS, "g"},
46+
{UserAgentFeature::CREDENTIALS_PROFILE, "n"},
47+
{UserAgentFeature::CREDENTIALS_PROCESS, "w"},
48+
{UserAgentFeature::CREDENTIALS_IMDS, "0"},
49+
{UserAgentFeature::CREDENTIALS_STS_ASSUME_ROLE, "i"},
4650
};
4751

4852
const std::pair<const char*, UserAgentFeature> RETRY_FEATURE_MAPPING[] = {

tests/aws-cpp-sdk-core-tests/aws/auth/CredentialTrackingTest.cpp

Lines changed: 217 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,18 +7,33 @@
77
#include <aws/testing/AwsTestHelpers.h>
88
#include <aws/testing/mocks/aws/client/MockAWSClient.h>
99
#include <aws/testing/mocks/http/MockHttpClient.h>
10+
#include <aws/testing/mocks/aws/auth/MockAWSHttpResourceClient.h>
1011
#include <aws/testing/platform/PlatformTesting.h>
1112
#include <aws/core/auth/AWSCredentialsProvider.h>
1213
#include <aws/core/auth/AWSCredentialsProviderChain.h>
1314
#include <aws/core/client/AWSClient.h>
1415
#include <aws/core/utils/StringUtils.h>
16+
#include <aws/core/utils/HashingUtils.h>
17+
#include <aws/core/platform/FileSystem.h>
18+
#include <aws/core/utils/FileSystemUtils.h>
19+
#include <fstream>
20+
#include <sys/stat.h>
1521

1622
using namespace Aws::Client;
1723
using namespace Aws::Auth;
1824
using namespace Aws::Http;
1925

2026
static const char ALLOCATION_TAG[] = "CredentialTrackingTest";
2127

28+
static Aws::String WrapEchoStringWithSingleQuoteForUnixShell(Aws::String str)
29+
{
30+
#ifndef _WIN32
31+
str.insert(0, 1, '\'');
32+
str.append(1, '\'');
33+
#endif
34+
return str;
35+
}
36+
2237
// Custom client that uses default credential provider for testing
2338
class CredentialTestingClient : public Aws::Client::AWSClient
2439
{
@@ -32,6 +47,17 @@ class CredentialTestingClient : public Aws::Client::AWSClient
3247
{
3348
}
3449

50+
// Constructor with custom credential provider for IMDS test
51+
explicit CredentialTestingClient(const Aws::Client::ClientConfiguration& configuration,
52+
std::shared_ptr<AWSCredentialsProvider> credentialsProvider)
53+
: AWSClient(configuration,
54+
Aws::MakeShared<Aws::Client::AWSAuthV4Signer>(ALLOCATION_TAG,
55+
credentialsProvider,
56+
"service", configuration.region),
57+
Aws::MakeShared<MockAWSErrorMarshaller>(ALLOCATION_TAG))
58+
{
59+
}
60+
3561
Aws::Client::HttpResponseOutcome MakeRequest(const Aws::AmazonWebServiceRequest& request)
3662
{
3763
auto uri = Aws::Http::URI("https://test.com");
@@ -127,3 +153,194 @@ TEST_F(CredentialTrackingTest, TestEnvironmentCredentialsTracking)
127153

128154
EXPECT_TRUE(businessMetrics != userAgentParsed.end());
129155
}
156+
157+
TEST_F(CredentialTrackingTest, TestProfileCredentialsTracking)
158+
{
159+
// Create temporary credentials file
160+
Aws::Utils::TempFile credentialsFile(std::ios_base::out | std::ios_base::trunc);
161+
ASSERT_TRUE(credentialsFile.good());
162+
credentialsFile << "[default]" << std::endl;
163+
credentialsFile << "aws_access_key_id = test-profile-access-key" << std::endl;
164+
credentialsFile << "aws_secret_access_key = test-profile-secret-key" << std::endl;
165+
credentialsFile.close();
166+
167+
// Set environment to use our test credentials file
168+
Aws::Environment::EnvironmentRAII testEnvironment{{
169+
{"AWS_SHARED_CREDENTIALS_FILE", credentialsFile.GetFileName().c_str()},
170+
}};
171+
Aws::Config::ReloadCachedCredentialsFile();
172+
173+
// Setup mock response
174+
std::shared_ptr<HttpRequest> requestTmp =
175+
CreateHttpRequest(Aws::Http::URI("dummy"), Aws::Http::HttpMethod::HTTP_POST,
176+
Aws::Utils::Stream::DefaultResponseStreamFactoryMethod);
177+
auto successResponse = Aws::MakeShared<Standard::StandardHttpResponse>(ALLOCATION_TAG, requestTmp);
178+
successResponse->SetResponseCode(HttpResponseCode::OK);
179+
successResponse->GetResponseBody() << "{}";
180+
mockHttpClient->AddResponseToReturn(successResponse);
181+
182+
// Create client configuration
183+
Aws::Client::ClientConfigurationInitValues cfgInit;
184+
cfgInit.shouldDisableIMDS = true;
185+
Aws::Client::ClientConfiguration clientConfig(cfgInit);
186+
clientConfig.region = Aws::Region::US_EAST_1;
187+
188+
// Create credential testing client that uses default provider chain
189+
CredentialTestingClient client(clientConfig);
190+
191+
// Create mock request
192+
AmazonWebServiceRequestMock mockRequest;
193+
194+
// Make request
195+
auto outcome = client.MakeRequest(mockRequest);
196+
ASSERT_TRUE(outcome.IsSuccess());
197+
198+
// Verify User-Agent contains profile credentials tracking
199+
auto lastRequest = mockHttpClient->GetMostRecentHttpRequest();
200+
EXPECT_TRUE(lastRequest.HasHeader(Aws::Http::USER_AGENT_HEADER));
201+
const auto& userAgent = lastRequest.GetHeaderValue(Aws::Http::USER_AGENT_HEADER);
202+
EXPECT_FALSE(userAgent.empty());
203+
204+
const auto userAgentParsed = Aws::Utils::StringUtils::Split(userAgent, ' ');
205+
206+
// Verify there's only one m/ section (no duplicate m/ sections)
207+
int mSectionCount = 0;
208+
for (const auto& part : userAgentParsed) {
209+
if (part.find("m/") != Aws::String::npos) {
210+
mSectionCount++;
211+
}
212+
}
213+
EXPECT_EQ(1, mSectionCount);
214+
215+
// Check for profile credentials business metric (n) in user agent
216+
auto businessMetrics = std::find_if(userAgentParsed.begin(), userAgentParsed.end(),
217+
[](const Aws::String& value) { return value.find("m/") != Aws::String::npos && value.find("n") != Aws::String::npos; });
218+
219+
EXPECT_TRUE(businessMetrics != userAgentParsed.end());
220+
}
221+
222+
TEST_F(CredentialTrackingTest, TestProcessCredentialsTracking)
223+
{
224+
// Create temporary config file with credential_process
225+
Aws::Utils::TempFile configFile(std::ios_base::out | std::ios_base::trunc);
226+
ASSERT_TRUE(configFile.good());
227+
configFile << "[default]" << std::endl;
228+
configFile << "credential_process = echo " << WrapEchoStringWithSingleQuoteForUnixShell("{\"Version\": 1, \"AccessKeyId\": \"test-process-key\", \"SecretAccessKey\": \"test-process-secret\"}") << std::endl;
229+
configFile.close();
230+
231+
// Set environment to use our test config file
232+
Aws::Environment::EnvironmentRAII testEnvironment{{
233+
{"AWS_CONFIG_FILE", configFile.GetFileName().c_str()},
234+
}};
235+
236+
// Force reload config file after setting environment variable
237+
Aws::Config::ReloadCachedConfigFile();
238+
239+
// Setup mock response
240+
std::shared_ptr<HttpRequest> requestTmp =
241+
CreateHttpRequest(Aws::Http::URI("dummy"), Aws::Http::HttpMethod::HTTP_POST,
242+
Aws::Utils::Stream::DefaultResponseStreamFactoryMethod);
243+
auto successResponse = Aws::MakeShared<Standard::StandardHttpResponse>(ALLOCATION_TAG, requestTmp);
244+
successResponse->SetResponseCode(HttpResponseCode::OK);
245+
successResponse->GetResponseBody() << "{}";
246+
mockHttpClient->AddResponseToReturn(successResponse);
247+
248+
// Create client configuration
249+
Aws::Client::ClientConfigurationInitValues cfgInit;
250+
cfgInit.shouldDisableIMDS = true;
251+
Aws::Client::ClientConfiguration clientConfig(cfgInit);
252+
clientConfig.region = Aws::Region::US_EAST_1;
253+
254+
// Create credential testing client that uses default provider chain
255+
CredentialTestingClient client(clientConfig);
256+
257+
// Create mock request
258+
AmazonWebServiceRequestMock mockRequest;
259+
260+
// Make request
261+
auto outcome = client.MakeRequest(mockRequest);
262+
ASSERT_TRUE(outcome.IsSuccess());
263+
264+
// Verify User-Agent contains process credentials tracking
265+
auto lastRequest = mockHttpClient->GetMostRecentHttpRequest();
266+
EXPECT_TRUE(lastRequest.HasHeader(Aws::Http::USER_AGENT_HEADER));
267+
const auto& userAgent = lastRequest.GetHeaderValue(Aws::Http::USER_AGENT_HEADER);
268+
EXPECT_FALSE(userAgent.empty());
269+
270+
const auto userAgentParsed = Aws::Utils::StringUtils::Split(userAgent, ' ');
271+
272+
// Verify there's only one m/ section (no duplicate m/ sections)
273+
int mSectionCount = 0;
274+
for (const auto& part : userAgentParsed) {
275+
if (part.find("m/") != Aws::String::npos) {
276+
mSectionCount++;
277+
}
278+
}
279+
EXPECT_EQ(1, mSectionCount);
280+
281+
// Check for process credentials business metric (w) in user agent
282+
auto businessMetrics = std::find_if(userAgentParsed.begin(), userAgentParsed.end(),
283+
[](const Aws::String& value) { return value.find("m/") != Aws::String::npos && value.find("w") != Aws::String::npos; });
284+
285+
EXPECT_TRUE(businessMetrics != userAgentParsed.end());
286+
}
287+
288+
TEST_F(CredentialTrackingTest, TestInstanceProfileCredentialsTracking)
289+
{
290+
// Create mock EC2 metadata client with valid credentials
291+
auto mockClient = Aws::MakeShared<MockEC2MetadataClient>(ALLOCATION_TAG);
292+
const char* validCredentials = R"({ "AccessKeyId": "test-imds-access-key", "SecretAccessKey": "test-imds-secret-key", "Token": "test-imds-token", "Code": "Success", "Expiration": "2037-04-19T00:00:00Z" })";
293+
mockClient->SetMockedCredentialsValue(validCredentials);
294+
295+
// Create IMDS credential provider with mock client
296+
auto imdsProvider = Aws::MakeShared<InstanceProfileCredentialsProvider>(ALLOCATION_TAG,
297+
Aws::MakeShared<Aws::Config::EC2InstanceProfileConfigLoader>(ALLOCATION_TAG, mockClient), 1000 * 60 * 15);
298+
299+
// Setup mock response for service call
300+
std::shared_ptr<HttpRequest> requestTmp =
301+
CreateHttpRequest(Aws::Http::URI("dummy"), Aws::Http::HttpMethod::HTTP_POST,
302+
Aws::Utils::Stream::DefaultResponseStreamFactoryMethod);
303+
auto successResponse = Aws::MakeShared<Standard::StandardHttpResponse>(ALLOCATION_TAG, requestTmp);
304+
successResponse->SetResponseCode(HttpResponseCode::OK);
305+
successResponse->GetResponseBody() << "{}";
306+
mockHttpClient->AddResponseToReturn(successResponse);
307+
308+
// Create client configuration
309+
Aws::Client::ClientConfigurationInitValues cfgInit;
310+
cfgInit.shouldDisableIMDS = false;
311+
Aws::Client::ClientConfiguration clientConfig(cfgInit);
312+
clientConfig.region = Aws::Region::US_EAST_1;
313+
314+
// Create credential testing client with IMDS provider
315+
CredentialTestingClient client(clientConfig, imdsProvider);
316+
317+
// Create mock request
318+
AmazonWebServiceRequestMock mockRequest;
319+
320+
// Make request
321+
auto outcome = client.MakeRequest(mockRequest);
322+
ASSERT_TRUE(outcome.IsSuccess());
323+
324+
// Verify User-Agent contains IMDS credentials tracking
325+
auto lastRequest = mockHttpClient->GetMostRecentHttpRequest();
326+
EXPECT_TRUE(lastRequest.HasHeader(Aws::Http::USER_AGENT_HEADER));
327+
const auto& userAgent = lastRequest.GetHeaderValue(Aws::Http::USER_AGENT_HEADER);
328+
EXPECT_FALSE(userAgent.empty());
329+
330+
const auto userAgentParsed = Aws::Utils::StringUtils::Split(userAgent, ' ');
331+
332+
// Verify there's only one m/ section (no duplicate m/ sections)
333+
int mSectionCount = 0;
334+
for (const auto& part : userAgentParsed) {
335+
if (part.find("m/") != Aws::String::npos) {
336+
mSectionCount++;
337+
}
338+
}
339+
EXPECT_EQ(1, mSectionCount);
340+
341+
// Check for IMDS credentials business metric (0) in user agent
342+
auto businessMetrics = std::find_if(userAgentParsed.begin(), userAgentParsed.end(),
343+
[](const Aws::String& value) { return value.find("m/") != Aws::String::npos && value.find("0") != Aws::String::npos; });
344+
345+
EXPECT_TRUE(businessMetrics != userAgentParsed.end());
346+
}

0 commit comments

Comments
 (0)