Skip to content
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

Adds async methods for assuming roles #3627

Open
wants to merge 1 commit into
base: main-staging
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
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 @@ -212,5 +212,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