Skip to content

Commit bff37c8

Browse files
Populate User Agent Details (#3733)
1 parent 873af21 commit bff37c8

File tree

10 files changed

+76
-34
lines changed

10 files changed

+76
-34
lines changed

Diff for: sdk/src/Core/Amazon.Runtime/CredentialManagement/AWSCredentialsFactory.cs

+33-29
Original file line numberDiff line numberDiff line change
@@ -199,14 +199,16 @@ private static AWSCredentials GetAWSCredentialsInternal(
199199
{
200200
if (profileType.HasValue)
201201
{
202+
AWSCredentials awsCredentials = null;
202203
switch (profileType)
203204
{
204205
case CredentialProfileType.Basic:
205-
var basicCredentials = new BasicAWSCredentials(options.AccessKey, options.SecretKey, options.AwsAccountId);
206-
basicCredentials.FeatureIdSources.Add(UserAgentFeatureId.CREDENTIALS_PROFILE);
207-
return basicCredentials;
206+
awsCredentials = new BasicAWSCredentials(options.AccessKey, options.SecretKey, options.AwsAccountId);
207+
awsCredentials.FeatureIdSources.Add(UserAgentFeatureId.CREDENTIALS_PROFILE);
208+
break;
208209
case CredentialProfileType.Session:
209-
return new SessionAWSCredentials(options.AccessKey, options.SecretKey, options.Token, options.AwsAccountId);
210+
awsCredentials = new SessionAWSCredentials(options.AccessKey, options.SecretKey, options.Token, options.AwsAccountId);
211+
break;
210212
case CredentialProfileType.AssumeRole:
211213
case CredentialProfileType.AssumeRoleExternal:
212214
case CredentialProfileType.AssumeRoleMFA:
@@ -252,10 +254,10 @@ private static AWSCredentials GetAWSCredentialsInternal(
252254
MfaSerialNumber = options.MfaSerial
253255
};
254256

255-
var assumeRoleCredentials = new AssumeRoleAWSCredentials(sourceCredentials, options.RoleArn, roleSessionName, assumeRoleOptions);
256-
assumeRoleCredentials.FeatureIdSources.Add(UserAgentFeatureId.CREDENTIALS_PROFILE_SOURCE_PROFILE);
257-
return assumeRoleCredentials;
258-
257+
awsCredentials = new AssumeRoleAWSCredentials(sourceCredentials, options.RoleArn, roleSessionName, assumeRoleOptions);
258+
awsCredentials.FeatureIdSources.Add(UserAgentFeatureId.CREDENTIALS_PROFILE_SOURCE_PROFILE);
259+
break;
260+
259261
case CredentialProfileType.AssumeRoleCredentialSource:
260262
case CredentialProfileType.AssumeRoleCredentialSourceSessionName:
261263
// get credentials specified by credentialSource
@@ -276,34 +278,30 @@ private static AWSCredentials GetAWSCredentialsInternal(
276278
roleSessionName = options.RoleSessionName ?? RoleSessionNamePrefix + AWSSDKUtils.CorrectedUtcNow.Ticks;
277279
assumeRoleOptions = new AssumeRoleAWSCredentialsOptions();
278280

279-
var assumeRoleSourceCredentials = new AssumeRoleAWSCredentials(sourceCredentials, options.RoleArn, roleSessionName, assumeRoleOptions);
280-
assumeRoleSourceCredentials.FeatureIdSources.Add(UserAgentFeatureId.CREDENTIALS_PROFILE_NAMED_PROVIDER);
281-
return assumeRoleSourceCredentials;
282-
281+
awsCredentials = new AssumeRoleAWSCredentials(sourceCredentials, options.RoleArn, roleSessionName, assumeRoleOptions);
282+
awsCredentials.FeatureIdSources.Add(UserAgentFeatureId.CREDENTIALS_PROFILE_NAMED_PROVIDER);
283+
break;
284+
283285
case CredentialProfileType.AssumeRoleWithWebIdentity:
284286
case CredentialProfileType.AssumeRoleWithWebIdentitySessionName:
285-
var assumeRoleWebIdentityCredentials = new AssumeRoleWithWebIdentityCredentials(options.WebIdentityTokenFile, options.RoleArn, options.RoleSessionName);
286-
assumeRoleWebIdentityCredentials.FeatureIdSources.Add(UserAgentFeatureId.CREDENTIALS_PROFILE_STS_WEB_ID_TOKEN);
287-
return assumeRoleWebIdentityCredentials;
288-
287+
awsCredentials = new AssumeRoleWithWebIdentityCredentials(options.WebIdentityTokenFile, options.RoleArn, options.RoleSessionName);
288+
awsCredentials.FeatureIdSources.Add(UserAgentFeatureId.CREDENTIALS_PROFILE_STS_WEB_ID_TOKEN);
289+
break;
290+
289291
case CredentialProfileType.SSO:
290-
{
291-
var ssoCredentialsOptions = new SSOAWSCredentialsOptions
292-
{
292+
var ssoCredentialsOptions = new SSOAWSCredentialsOptions
293+
{
293294
SessionName = options.SsoSession,
294295
Scopes = options.SsoRegistrationScopes?.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries).Select(p => p.Trim()).ToList()
295296
};
296297

297298
var isLegacyFormat = string.IsNullOrEmpty(options.SsoSession);
298-
var ssoCredentials = new SSOAWSCredentials(options.SsoAccountId, options.SsoRegion, options.SsoRoleName, options.SsoStartUrl, ssoCredentialsOptions);
299-
ssoCredentials.FeatureIdSources.Add(isLegacyFormat ? UserAgentFeatureId.CREDENTIALS_PROFILE_SSO_LEGACY : UserAgentFeatureId.CREDENTIALS_PROFILE_SSO);
299+
awsCredentials = new SSOAWSCredentials(options.SsoAccountId, options.SsoRegion, options.SsoRoleName, options.SsoStartUrl, ssoCredentialsOptions);
300+
awsCredentials.FeatureIdSources.Add(isLegacyFormat ? UserAgentFeatureId.CREDENTIALS_PROFILE_SSO_LEGACY : UserAgentFeatureId.CREDENTIALS_PROFILE_SSO);
301+
break;
300302

301-
return ssoCredentials;
302-
}
303-
304303
case CredentialProfileType.SAMLRole:
305304
case CredentialProfileType.SAMLRoleUserIdentity:
306-
307305
if (UserCrypto.IsUserCryptAvailable)
308306
{
309307
var federatedOptions = new FederatedAWSCredentialsOptions()
@@ -312,17 +310,18 @@ private static AWSCredentials GetAWSCredentialsInternal(
312310
UserIdentity = options.UserIdentity,
313311
ProfileName = profileName
314312
};
315-
return new FederatedAWSCredentials(new SAMLEndpointManager().GetEndpoint(options.EndpointName),
313+
awsCredentials = new FederatedAWSCredentials(new SAMLEndpointManager().GetEndpoint(options.EndpointName),
316314
options.RoleArn, federatedOptions);
315+
break;
317316
}
318317
else
319318
{
320319
return ThrowOrReturnNull("Federated credentials are not available on this platform.", null, throwIfInvalid);
321320
}
322321
case CredentialProfileType.CredentialProcess:
323-
var processCredentials = new ProcessAWSCredentials(options.CredentialProcess, options.AwsAccountId);
324-
processCredentials.FeatureIdSources.Add(UserAgentFeatureId.CREDENTIALS_PROFILE_PROCESS);
325-
return processCredentials;
322+
awsCredentials = new ProcessAWSCredentials(options.CredentialProcess, options.AwsAccountId);
323+
awsCredentials.FeatureIdSources.Add(UserAgentFeatureId.CREDENTIALS_PROFILE_PROCESS);
324+
break;
326325

327326
default:
328327
var defaultMessage = profileName == null
@@ -333,6 +332,11 @@ private static AWSCredentials GetAWSCredentialsInternal(
333332

334333
return ThrowOrReturnNull(defaultMessage, null, throwIfInvalid);
335334
}
335+
336+
if (profileSource is NetSDKCredentialsFile)
337+
awsCredentials.FeatureIdSources.Add(UserAgentFeatureId.CREDENTIALS_AWS_SDK_STORE);
338+
339+
return awsCredentials;
336340
}
337341
else
338342
{

Diff for: sdk/src/Core/Amazon.Runtime/Credentials/FederatedAWSCredentials.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ public FederatedAWSCredentials(SAMLEndpoint samlEndpoint, string roleArn,
7777
SAMLEndpoint = samlEndpoint ?? throw new ArgumentNullException("samlEndpoint");
7878
RoleArn = roleArn;
7979
PreemptExpiryTime = DefaultPreemptExpiryTime;
80-
FeatureIdSources.Add(UserAgentFeatureId.CREDENTIALS_STS_FEDERATION_TOKEN);
80+
FeatureIdSources.Add(UserAgentFeatureId.CREDENTIALS_STS_ASSUME_ROLE_SAML);
8181
}
8282

8383
/// <summary>

Diff for: sdk/src/Core/Amazon.Runtime/IClientConfig.cs

+7
Original file line numberDiff line numberDiff line change
@@ -387,6 +387,13 @@ public partial interface IClientConfig
387387
/// </summary>
388388
ResponseChecksumValidation ResponseChecksumValidation { get; }
389389

390+
/// <summary>
391+
/// Controls whether the resolved endpoint will include the account id. This allows for direct routing of traffic
392+
/// to the cell responsible for a given account, which avoids the additional latency of extra backend hops and reduces
393+
/// complexity in the routing layer.
394+
/// </summary>
395+
public AccountIdEndpointMode AccountIdEndpointMode { get; }
396+
390397
#if BCL
391398
/// <summary>
392399
/// Gets the TCP keep-alive values to use for service requests. Enabling TCP keep-alive sends periodic TCP keep-alive probe packets, to prevent disconnection due to

Diff for: sdk/src/Core/Amazon.Runtime/Internal/UserAgent/UserAgentFeatureId.cs

+2-2
Original file line numberDiff line numberDiff line change
@@ -156,9 +156,9 @@ public class UserAgentFeatureId : ConstantClass
156156
public static readonly UserAgentFeatureId CREDENTIALS_STS_ASSUME_ROLE_WEB_ID = new UserAgentFeatureId("k");
157157

158158
/// <summary>
159-
/// An operation called using credentials resolved from STS using a federation token.
159+
/// An operation called using credentials resolved from STS using assume role with SAML.
160160
/// </summary>
161-
public static readonly UserAgentFeatureId CREDENTIALS_STS_FEDERATION_TOKEN = new UserAgentFeatureId("l");
161+
public static readonly UserAgentFeatureId CREDENTIALS_STS_ASSUME_ROLE_SAML = new UserAgentFeatureId("j");
162162

163163
/// <summary>
164164
/// An operation called using credentials resolved from STS using a session token.

Diff for: sdk/src/Core/Amazon.Runtime/Pipeline/Handlers/BaseEndpointResolver.cs

+5
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
using Amazon.Runtime.Internal.Auth;
2121
using Amazon.Runtime.Telemetry;
2222
using Amazon.Runtime.Telemetry.Metrics;
23+
using Amazon.Runtime.Internal.UserAgent;
2324

2425
namespace Amazon.Runtime.Internal
2526
{
@@ -73,6 +74,10 @@ public virtual void ProcessRequestHandlers(IExecutionContext executionContext)
7374
};
7475
requestContext.Request.Endpoint = uriBuilder.Uri;
7576
}
77+
if (!string.IsNullOrEmpty(requestContext.ClientConfig.ServiceURL))
78+
{
79+
requestContext.UserAgentDetails.AddFeature(UserAgentFeatureId.ENDPOINT_OVERRIDE);
80+
}
7681

7782
// set authentication parameters and headers
7883
SetAuthenticationAndHeaders(requestContext.Request, endpoint);

Diff for: sdk/src/Core/Amazon.Runtime/Pipeline/Handlers/Marshaller.cs

+7-1
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,13 @@ private static void SetRecursionDetectionHeader(IDictionary<string, string> head
126126

127127
private static void UpdateUserAgentDetails(IRequestContext requestContext)
128128
{
129-
var sb = new StringBuilder(256);
129+
var accountIdMode = requestContext.ClientConfig.AccountIdEndpointMode;
130+
if (accountIdMode == AccountIdEndpointMode.DISABLED)
131+
requestContext.UserAgentDetails.AddFeature(UserAgentFeatureId.ACCOUNT_ID_MODE_DISABLED);
132+
else if (accountIdMode == AccountIdEndpointMode.PREFERRED)
133+
requestContext.UserAgentDetails.AddFeature(UserAgentFeatureId.ACCOUNT_ID_MODE_PREFERRED);
134+
else if (accountIdMode == AccountIdEndpointMode.REQUIRED)
135+
requestContext.UserAgentDetails.AddFeature(UserAgentFeatureId.ACCOUNT_ID_MODE_REQUIRED);
130136

131137
requestContext.UserAgentDetails.AddUserAgentComponent(InternalSDKUtils.ReplaceInvalidUserAgentCharacters(requestContext.ClientConfig.UserAgent));
132138

Diff for: sdk/src/Core/Amazon.Runtime/Pipeline/Handlers/Signer.cs

+10
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515

1616
using Amazon.Runtime.EventStreams.Internal;
1717
using Amazon.Runtime.Internal.Auth;
18+
using Amazon.Runtime.Internal.UserAgent;
19+
using Amazon.Runtime.Internal.Util;
1820
using Amazon.Runtime.Telemetry;
1921
using Amazon.Runtime.Telemetry.Metrics;
2022
using Amazon.Runtime.Telemetry.Tracing;
@@ -133,6 +135,10 @@ public static void SignRequest(IRequestContext requestContext)
133135
throw new InvalidDataException("Cannot determine protocol");
134136
}
135137
}
138+
if (!string.IsNullOrEmpty(immutableCredentials?.AccountId))
139+
{
140+
requestContext.UserAgentDetails.AddFeature(UserAgentFeatureId.RESOLVED_ACCOUNT_ID);
141+
}
136142

137143
requestContext.Signer.Sign(
138144
requestContext.Request,
@@ -198,6 +204,10 @@ private static async Task SignRequestAsync(IRequestContext requestContext)
198204
throw new InvalidDataException("Cannot determine protocol");
199205
}
200206
}
207+
if (!string.IsNullOrEmpty(immutableCredentials?.AccountId))
208+
{
209+
requestContext.UserAgentDetails.AddFeature(UserAgentFeatureId.RESOLVED_ACCOUNT_ID);
210+
}
201211

202212
await requestContext.Signer
203213
.SignAsync(

Diff for: sdk/src/Core/Amazon.Runtime/Pipeline/HttpHandler/HttpHandler.cs

+4
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
using System.Net;
2727
using System.Reflection;
2828
using System.Text;
29+
using Amazon.Runtime.Internal.UserAgent;
2930

3031
namespace Amazon.Runtime.Internal
3132
{
@@ -503,6 +504,9 @@ private static System.IO.Stream GetInputStream(IRequestContext requestContext, S
503504

504505
private void SetUserAgentHeader(IRequestContext requestContext)
505506
{
507+
if (requestContext.Request.SignatureVersion == SignatureVersion.SigV4a)
508+
requestContext.UserAgentDetails.AddFeature(UserAgentFeatureId.SIGV4A_SIGNING);
509+
506510
var metricsUserAgent = requestContext.UserAgentDetails.GenerateUserAgentWithMetrics();
507511
Logger.DebugFormat("User-Agent Header: {0}", metricsUserAgent);
508512

Diff for: sdk/src/Services/S3/Custom/Internal/AmazonS3PostMarshallHandler.cs

+4
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
using Amazon.Util;
2525
using Amazon.S3.Util;
2626
using Amazon.S3.Model;
27+
using Amazon.Runtime.Internal.UserAgent;
2728

2829
#pragma warning disable 1591
2930

@@ -66,6 +67,9 @@ protected virtual void PreInvoke(IExecutionContext executionContext)
6667

6768
private static void ProcessPreRequestHandlers(IExecutionContext executionContext)
6869
{
70+
if (executionContext.RequestContext.Request.IsDirectoryBucket())
71+
executionContext.RequestContext.UserAgentDetails.AddFeature(UserAgentFeatureId.S3_EXPRESS_BUCKET);
72+
6973
var originalRequest = executionContext.RequestContext.OriginalRequest;
7074
if (SetStreamChecksum(originalRequest, executionContext.RequestContext.Request))
7175
return;

Diff for: sdk/test/UnitTests/Custom/EndpointsTests.cs

+3-1
Original file line numberDiff line numberDiff line change
@@ -68,10 +68,12 @@ public void EndpointResolverHttpsServiceURLVsUseHttp()
6868
ServiceURL = serviceURL,
6969
UseHttp = true
7070
};
71+
var originalRequest = new MockAmazonWebServiceRequest();
7172
var requestContext = new RequestContext(false, new NullSigner())
7273
{
7374
ClientConfig = config,
74-
Request = new DefaultRequest(new MockAmazonWebServiceRequest(), "test-service")
75+
Request = new DefaultRequest(originalRequest, "test-service"),
76+
OriginalRequest = originalRequest,
7577
};
7678

7779
var executionContext = new ExecutionContext(requestContext, null);

0 commit comments

Comments
 (0)