Skip to content

Introduce AddCredentialsFactory() extension methods #3715

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

Closed
Closed
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
3 changes: 2 additions & 1 deletion extensions/src/AWSSDK.Extensions.NETCore.Setup/AWSOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
using Amazon.Runtime;

using Amazon.Extensions.NETCore.Setup;
using AWSSDK.Extensions.NETCore.Setup;

namespace Amazon.Extensions.NETCore.Setup
{
Expand Down Expand Up @@ -110,7 +111,7 @@ internal set
/// <returns>The service client that implements the service interface.</returns>
public T CreateServiceClient<T>() where T : IAmazonService
{
return (T)ClientFactory.CreateServiceClient(null, typeof(T), this);
return (T)ClientFactory.CreateServiceClient(null, typeof(T), this, new DefaultAWSCredentialsFactory(this));
}

/// <summary>
Expand Down
79 changes: 19 additions & 60 deletions extensions/src/AWSSDK.Extensions.NETCore.Setup/ClientFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
using System.Reflection;
using Amazon.Runtime;
using Amazon.Runtime.CredentialManagement;

using AWSSDK.Extensions.NETCore.Setup;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
Expand All @@ -34,17 +34,23 @@ internal class ClientFactory
private static readonly Type[] EMPTY_TYPES = Array.Empty<Type>();
private static readonly object[] EMPTY_PARAMETERS = Array.Empty<object>();

private Type _serviceInterfaceType;
private AWSOptions _awsOptions;
private readonly Type _serviceInterfaceType;
private readonly AWSOptions _awsOptions;
private readonly IAWSCredentialsFactory _credentialsFactory;
private readonly ILoggerFactory _loggerFactory;
private readonly IConfiguration _configuration;

/// <summary>
/// Constructs an instance of the ClientFactory
/// </summary>
/// <param name="type">The type object for the Amazon service client interface, for example IAmazonS3.</param>
internal ClientFactory(Type type, AWSOptions awsOptions)
internal ClientFactory(Type type, AWSOptions awsOptions, IAWSCredentialsFactory credentialsFactory, ILoggerFactory loggerFactory, IConfiguration configuration)
{
_serviceInterfaceType = type;
_awsOptions = awsOptions;
_credentialsFactory = credentialsFactory;
_loggerFactory = loggerFactory;
_configuration = configuration;
}

/// <summary>
Expand All @@ -53,24 +59,22 @@ internal ClientFactory(Type type, AWSOptions awsOptions)
/// </summary>
/// <param name="provider">The dependency injection provider.</param>
/// <returns>The AWS service client</returns>
internal object CreateServiceClient(IServiceProvider provider)
internal object CreateServiceClient()
{
var loggerFactory = provider.GetService<Microsoft.Extensions.Logging.ILoggerFactory>();
var logger = loggerFactory?.CreateLogger("AWSSDK");
var logger = _loggerFactory?.CreateLogger("AWSSDK");

var options = _awsOptions ?? provider.GetService<AWSOptions>();
if(options == null)
var options = _awsOptions;
if(_awsOptions == null)
{
var configuration = provider.GetService<IConfiguration>();
if(configuration != null)
if(_configuration != null)
{
options = configuration.GetAWSOptions();
options = _configuration.GetAWSOptions();
if (options != null)
logger?.LogInformation("Found AWS options in IConfiguration");
}
}

return CreateServiceClient(logger, _serviceInterfaceType, options);
return CreateServiceClient(logger, _serviceInterfaceType, options, _credentialsFactory);
}

/// <summary>
Expand All @@ -79,10 +83,10 @@ internal object CreateServiceClient(IServiceProvider provider)
/// </summary>
/// <param name="provider">The dependency injection provider.</param>
/// <returns>The AWS service client</returns>
internal static IAmazonService CreateServiceClient(ILogger logger, Type serviceInterfaceType, AWSOptions options)
internal static IAmazonService CreateServiceClient(ILogger logger, Type serviceInterfaceType, AWSOptions options, IAWSCredentialsFactory credentialsFactory)
{
PerformGlobalConfig(logger, options);
var credentials = CreateCredentials(logger, options);
var credentials = credentialsFactory.Create();

if (!string.IsNullOrEmpty(options?.SessionRoleArn))
{
Expand Down Expand Up @@ -160,51 +164,6 @@ private static AmazonServiceClient CreateClient(Type serviceInterfaceType, AWSCr
return constructor.Invoke(new object[] { credentials, config }) as AmazonServiceClient;
}

/// <summary>
/// Creates the AWSCredentials using either the profile indicated from the AWSOptions object
/// of the SDK fallback credentials search.
/// </summary>
/// <param name="options"></param>
/// <returns></returns>
private static AWSCredentials CreateCredentials(ILogger logger, AWSOptions options)
{
if (options != null)
{
if (options.Credentials != null)
{
logger?.LogInformation("Using AWS credentials specified with the AWSOptions.Credentials property");
return options.Credentials;
}
if (!string.IsNullOrEmpty(options.Profile))
{
var chain = new CredentialProfileStoreChain(options.ProfilesLocation);
AWSCredentials result;
if (chain.TryGetAWSCredentials(options.Profile, out result))
{
logger?.LogInformation($"Found AWS credentials for the profile {options.Profile}");
return result;
}
else
{
logger?.LogInformation($"Failed to find AWS credentials for the profile {options.Profile}");
}
}
}

var credentials = FallbackCredentialsFactory.GetCredentials();
if (credentials == null)
{
logger?.LogError("Last effort to find AWS Credentials with AWS SDK's default credential search failed");
throw new AmazonClientException("Failed to find AWS Credentials for constructing AWS service client");
}
else
{
logger?.LogInformation("Found credentials using the AWS SDK's default credential search");
}

return credentials;
}

/// <summary>
/// Creates the ClientConfig object for the service client.
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
/*
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
using Amazon.Extensions.NETCore.Setup;
using Amazon.Runtime;
using Amazon.Runtime.CredentialManagement;
using Microsoft.Extensions.Logging;

namespace AWSSDK.Extensions.NETCore.Setup
{
public class DefaultAWSCredentialsFactory : IAWSCredentialsFactory
{
private readonly AWSOptions _options;
private readonly ILogger<DefaultAWSCredentialsFactory> _logger;

public DefaultAWSCredentialsFactory(AWSOptions options, ILogger<DefaultAWSCredentialsFactory> logger = null)
{
_options = options;
_logger = logger;
}

/// <summary>
/// Creates the AWSCredentials using either AWSOptions.Credentials, AWSOptions.Profile + AWSOptions.ProfilesLocation,
/// or the SDK fallback credentials search.
/// </summary>
public AWSCredentials Create()
{
if (_options?.Credentials != null)
{
_logger?.LogInformation("Using AWS credentials specified with the AWSOptions.Credentials property");
return _options.Credentials;
}

if (!string.IsNullOrWhiteSpace(_options?.Profile))
{
var chain = new CredentialProfileStoreChain(_options.ProfilesLocation);
if (chain.TryGetAWSCredentials(_options.Profile, out var result))
{
_logger?.LogInformation("Found AWS credentials for the profile {OptionsProfile}", _options.Profile);
return result;
}

_logger?.LogInformation("Failed to find AWS credentials for the profile {OptionsProfile}", _options.Profile);
}

var credentials = FallbackCredentialsFactory.GetCredentials();
if (credentials == null)
{
_logger?.LogError("Last effort to find AWS Credentials with AWS SDK's default credential search failed");
throw new AmazonClientException("Failed to find AWS Credentials for constructing AWS service client");
}

_logger?.LogInformation("Found credentials using the AWS SDK's default credential search");

return credentials;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/*
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
using Amazon.Runtime;

namespace AWSSDK.Extensions.NETCore.Setup
{
public interface IAWSCredentialsFactory
{
AWSCredentials Create();
}
}
Loading