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 2 commits into
base: main-staging
Choose a base branch
from
Open
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
@@ -20,6 +20,9 @@
using System;
using System.Globalization;
using System.Net;
#if AWS_ASYNC_API
using System.Threading.Tasks;
#endif

namespace Amazon.Runtime
{
@@ -130,11 +133,68 @@ 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;

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;
}
}

AssumeRoleImmutableCredentials credentials;
var coreSTSClientAsync = coreSTSClient as ICoreAmazonSTSAsync;
if (coreSTSClientAsync != null)
{
credentials = await coreSTSClientAsync.CredentialsFromAssumeRoleAuthenticationAsync(RoleArn, RoleSessionName, Options).ConfigureAwait(false);
}
else
{
_logger.InfoFormat("{0} does not implement {1}. AWSSDK.Core likely needs to be upgraded to a newer version.", coreSTSClient.GetType(), nameof(ICoreAmazonSTSAsync));
credentials = coreSTSClient.CredentialsFromAssumeRoleAuthentication(RoleArn, RoleSessionName, Options);
}

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);
}
#endif
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
using System.Threading.Tasks;

namespace Amazon.Runtime.SharedInterfaces
{
#if AWS_ASYNC_API
/// <summary>
/// ICoreAmazonSTSAsync is not meant to be used directly. It defines Security Token
/// service with basic .NET types and allows other services to be able to use the service as
/// a runtime dependency. This interface is implemented by the AmazonSecurityTokenServiceClient
/// defined in the AWSSDK.SecurityToken assembly.
/// </summary>
public interface ICoreAmazonSTSAsync
{
/// <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
}
Original file line number Diff line number Diff line change
@@ -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> ICoreAmazonSTSAsync.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
}
}
Original file line number Diff line number Diff line change
@@ -20,6 +20,9 @@ namespace Amazon.SecurityToken
public partial interface IAmazonSecurityTokenService : IDisposable, ICoreAmazonSTS
#if NETSTANDARD20 || NETCOREAPP3_1_OR_GREATER
, ICoreAmazonSTS_SAML
#endif
#if AWS_ASYNC_API
, ICoreAmazonSTSAsync
#endif
{
}
1 change: 1 addition & 0 deletions sdk/src/Services/SecurityToken/GlobalSuppressions.cs
Original file line number Diff line number Diff line change
@@ -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#ICoreAmazonSTSAsync#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}")]