Skip to content

Commit

Permalink
Adds async methods for assuming roles
Browse files Browse the repository at this point in the history
This is an attempt to fix aws#3626.
  • Loading branch information
mscottford committed Jan 29, 2025
1 parent d5b9b73 commit 6e3932e
Show file tree
Hide file tree
Showing 4 changed files with 132 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@
using System;
using System.Globalization;
using System.Net;
#if AWS_ASYNC_API
using System.Threading.Tasks;
#endif

namespace Amazon.Runtime
{
Expand Down Expand Up @@ -130,11 +133,57 @@ protected override CredentialsRefreshState GenerateNewCredentials()
}
}

var credentials = coreSTSClient.CredentialsFromAssumeRoleAuthentication(RoleArn, RoleSessionName, Options);
_logger.InfoFormat("New credentials created for assume role that expire at {0}", credentials.Expiration.ToString("yyyy-MM-ddTHH:mm:ss.fffffffK", CultureInfo.InvariantCulture));
return new CredentialsRefreshState(credentials, credentials.Expiration);
}

#if AWS_ASYNC_API
#if NET8_0_OR_GREATER
[System.Diagnostics.CodeAnalysis.UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026",
Justification = "Reflection code is only used as a fallback in case the SDK was not trimmed. Trimmed scenarios should register dependencies with Amazon.RuntimeDependencyRegistry.GlobalRuntimeDependencyRegistry")]
#endif
protected override async Task<CredentialsRefreshState> GenerateNewCredentialsAsync()
{
var region = FallbackRegionFactory.GetRegionEndpoint() ?? DefaultSTSClientRegion;
ICoreAmazonSTS coreSTSClient = GlobalRuntimeDependencyRegistry.Instance.GetInstance<ICoreAmazonSTS>(ServiceClientHelpers.STS_ASSEMBLY_NAME, ServiceClientHelpers.STS_SERVICE_CLASS_NAME,
new CreateInstanceContext(new SecurityTokenServiceClientContext {Action = SecurityTokenServiceClientContext.ActionContext.AssumeRoleAWSCredentials, Region = region, ProxySettings = Options?.ProxySettings } ));

if (coreSTSClient == null)
{
try
{
var stsConfig = ServiceClientHelpers.CreateServiceConfig(ServiceClientHelpers.STS_ASSEMBLY_NAME, ServiceClientHelpers.STS_SERVICE_CONFIG_NAME);
stsConfig.RegionEndpoint = region;

var credentials = coreSTSClient.CredentialsFromAssumeRoleAuthentication(RoleArn, RoleSessionName, Options);
if (Options?.ProxySettings != null)
{
stsConfig.SetWebProxy(Options.ProxySettings);
}

coreSTSClient = ServiceClientHelpers.CreateServiceFromAssembly<ICoreAmazonSTS>(
ServiceClientHelpers.STS_ASSEMBLY_NAME, ServiceClientHelpers.STS_SERVICE_CLASS_NAME, SourceCredentials, stsConfig);
}
catch (Exception e)
{
if (InternalSDKUtils.IsRunningNativeAot())
{
throw new MissingRuntimeDependencyException(ServiceClientHelpers.STS_ASSEMBLY_NAME, ServiceClientHelpers.STS_SERVICE_CLASS_NAME, nameof(GlobalRuntimeDependencyRegistry.RegisterSecurityTokenServiceClient));
}

var msg = string.Format(CultureInfo.CurrentCulture,
"Assembly {0} could not be found or loaded. This assembly must be available at runtime to use Amazon.Runtime.AssumeRoleAWSCredentials.",
ServiceClientHelpers.STS_ASSEMBLY_NAME);
var exception = new InvalidOperationException(msg, e);
Logger.GetLogger(typeof(AssumeRoleAWSCredentials)).Error(exception, exception.Message);
throw exception;
}
}

var credentials = await coreSTSClient.CredentialsFromAssumeRoleAuthenticationAsync(RoleArn, RoleSessionName, Options).ConfigureAwait(false);
_logger.InfoFormat("New credentials created for assume role that expire at {0}", credentials.Expiration.ToString("yyyy-MM-ddTHH:mm:ss.fffffffK", CultureInfo.InvariantCulture));
return new CredentialsRefreshState(credentials, credentials.Expiration);
}
#endif
}
}
23 changes: 23 additions & 0 deletions sdk/src/Core/Amazon.Runtime/SharedInterfaces/ICoreAmazonSTS.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,29 @@ public interface ICoreAmazonSTS
/// <returns></returns>
AssumeRoleImmutableCredentials CredentialsFromAssumeRoleAuthentication(string roleArn, string roleSessionName, AssumeRoleAWSCredentialsOptions options);

#if AWS_ASYNC_API
/// <summary>
/// <para>
/// This method is used internally to access the Amazon Security Token
/// service within other service assemblies.
/// Please use AmazonSecurityTokenServiceClient to access the Amazon Security Token
/// service instead.
/// </para>
/// Use Amazon Security Token Service to assume a role.
/// <remarks>
/// Proxy settings that are required for the HTTPS and STS calls made during the authentication/credential
/// generation process are supported and should have been configured on the STS ClientConfig instance
/// associated with the STS client instance exposing this interface.
/// </remarks>
/// </summary>
/// <param name="roleArn">The Amazon Resource Name (ARN) of the role to assume.</param>
/// <param name="roleSessionName"> An identifier for the assumed role session.</param>
/// <param name="options">Options to be used in the call to AssumeRole.</param>
/// <returns></returns>
Task<AssumeRoleImmutableCredentials> CredentialsFromAssumeRoleAuthenticationAsync(string roleArn, string roleSessionName, AssumeRoleAWSCredentialsOptions options);
#endif


#if !BCL // In the NETSTANDARD flavors of the SDK ICoreAmazonSTS is declared without CredentialsFromSAMLAuthentication,
} // we cannot add a new method to the interface for backward compatibility concerns.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
*/
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Net;
using System.Linq;
using Amazon.Runtime;
Expand Down Expand Up @@ -166,6 +167,7 @@ async Task<AssumeRoleImmutableCredentials> ICoreAmazonSTS_WebIdentity.Credential
/// <param name="roleSessionName"></param>
/// <param name="options"></param>
/// <returns></returns>
[SuppressMessage("Design", "CA1033:Interface methods should be callable by child types")]
AssumeRoleImmutableCredentials ICoreAmazonSTS.CredentialsFromAssumeRoleAuthentication(string roleArn,
string roleSessionName, AssumeRoleAWSCredentialsOptions options)
{
Expand Down Expand Up @@ -212,5 +214,61 @@ AssumeRoleImmutableCredentials ICoreAmazonSTS.CredentialsFromAssumeRoleAuthentic
throw exception;
}
}

#if AWS_ASYNC_API
/// <summary>
/// <see cref="ICoreAmazonSTS"/>
/// </summary>
/// <param name="roleArn"></param>
/// <param name="roleSessionName"></param>
/// <param name="options"></param>
/// <returns></returns>
async Task<AssumeRoleImmutableCredentials> ICoreAmazonSTS.CredentialsFromAssumeRoleAuthenticationAsync(string roleArn,
string roleSessionName, AssumeRoleAWSCredentialsOptions options)
{
try
{
var request = new AssumeRoleRequest
{
RoleArn = roleArn,
RoleSessionName = roleSessionName
};
if (options != null)
{
request.ExternalId = options.ExternalId;
request.SerialNumber = options.MfaSerialNumber;
request.TokenCode = options.MfaTokenCode;
request.Policy = options.Policy;
request.SourceIdentity = options.SourceIdentity;

if (options.DurationSeconds.HasValue)
{
request.DurationSeconds = options.DurationSeconds.Value;
}

if (options.Tags != null && options.Tags.Count > 0)
{
request.Tags = options.Tags.Select(kv => new Tag() { Key = kv.Key, Value = kv.Value }).ToList();
}

if (options.TransitiveTagKeys != null && options.TransitiveTagKeys.Count > 0)
{
request.TransitiveTagKeys = options.TransitiveTagKeys;
}
}

var response = await AssumeRoleAsync(request).ConfigureAwait(false);
return new AssumeRoleImmutableCredentials(response.Credentials.AccessKeyId, response.Credentials.SecretAccessKey,
response.Credentials.SessionToken, response.Credentials.Expiration);
}
catch (Exception e)
{
var msg = "Error calling AssumeRole for role " + roleArn;
var exception = new AmazonClientException(msg, e);
Logger.GetLogger(typeof(AmazonSecurityTokenServiceClient)).Error(exception, exception.Message);
throw exception;
}
}
#endif
}
}
1 change: 1 addition & 0 deletions sdk/src/Services/SecurityToken/GlobalSuppressions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
// a specific target and scoped to a namespace, type, member, etc.

[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Design", "CA1033:Interface methods should be callable by child types", Scope = "member", Target = "~M:Amazon.SecurityToken.AmazonSecurityTokenServiceClient.Amazon#Runtime#SharedInterfaces#ICoreAmazonSTS#CredentialsFromAssumeRoleAuthentication(System.String,System.String,Amazon.Runtime.AssumeRoleAWSCredentialsOptions)~Amazon.Runtime.AssumeRoleImmutableCredentials")]
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Design", "CA1033:Interface methods should be callable by child types", Scope = "member", Target = "~M:Amazon.SecurityToken.AmazonSecurityTokenServiceClient.Amazon#Runtime#SharedInterfaces#ICoreAmazonSTS#CredentialsFromAssumeRoleAuthenticationAsync(System.String,System.String,Amazon.Runtime.AssumeRoleAWSCredentialsOptions)~System.Threading.Tasks.Task{Amazon.Runtime.AssumeRoleImmutableCredentials}")]
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Design", "CA1033:Interface methods should be callable by child types", Scope = "member", Target = "~M:Amazon.SecurityToken.AmazonSecurityTokenServiceClient.Amazon#Runtime#SharedInterfaces#ICoreAmazonSTS#CredentialsFromSAMLAuthentication(System.String,System.String,System.String,System.TimeSpan,System.Net.ICredentials)~Amazon.Runtime.SAMLImmutableCredentials")]
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Design", "CA1033:Interface methods should be callable by child types", Scope = "member", Target = "~M:Amazon.SecurityToken.AmazonSecurityTokenServiceClient.Amazon#Runtime#SharedInterfaces#ICoreAmazonSTS_WebIdentity#CredentialsFromAssumeRoleWithWebIdentityAuthentication(System.String,System.String,System.String,Amazon.Runtime.AssumeRoleWithWebIdentityCredentialsOptions)~Amazon.Runtime.AssumeRoleImmutableCredentials")]
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Design", "CA1033:Interface methods should be callable by child types", Scope = "member", Target = "~M:Amazon.SecurityToken.AmazonSecurityTokenServiceClient.Amazon#Runtime#SharedInterfaces#ICoreAmazonSTS_WebIdentity#CredentialsFromAssumeRoleWithWebIdentityAuthenticationAsync(System.String,System.String,System.String,Amazon.Runtime.AssumeRoleWithWebIdentityCredentialsOptions)~System.Threading.Tasks.Task{Amazon.Runtime.AssumeRoleImmutableCredentials}")]
Expand Down

0 comments on commit 6e3932e

Please sign in to comment.