Skip to content

Commit d0cf353

Browse files
committed
Introduce IAWSCredentialsFactory and related extension methods
1 parent 96a01f2 commit d0cf353

File tree

5 files changed

+299
-82
lines changed

5 files changed

+299
-82
lines changed

extensions/src/AWSSDK.Extensions.NETCore.Setup/AWSOptions.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
using Amazon.Runtime;
2222

2323
using Amazon.Extensions.NETCore.Setup;
24+
using AWSSDK.Extensions.NETCore.Setup;
2425

2526
namespace Amazon.Extensions.NETCore.Setup
2627
{
@@ -110,7 +111,7 @@ internal set
110111
/// <returns>The service client that implements the service interface.</returns>
111112
public T CreateServiceClient<T>() where T : IAmazonService
112113
{
113-
return (T)ClientFactory.CreateServiceClient(null, typeof(T), this);
114+
return (T)ClientFactory.CreateServiceClient(null, typeof(T), this, new DefaultAWSCredentialsFactory(this));
114115
}
115116

116117
/// <summary>

extensions/src/AWSSDK.Extensions.NETCore.Setup/ClientFactory.cs

Lines changed: 19 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
using System.Reflection;
1717
using Amazon.Runtime;
1818
using Amazon.Runtime.CredentialManagement;
19-
19+
using AWSSDK.Extensions.NETCore.Setup;
2020
using Microsoft.Extensions.Configuration;
2121
using Microsoft.Extensions.DependencyInjection;
2222
using Microsoft.Extensions.Logging;
@@ -34,17 +34,23 @@ internal class ClientFactory
3434
private static readonly Type[] EMPTY_TYPES = Array.Empty<Type>();
3535
private static readonly object[] EMPTY_PARAMETERS = Array.Empty<object>();
3636

37-
private Type _serviceInterfaceType;
38-
private AWSOptions _awsOptions;
37+
private readonly Type _serviceInterfaceType;
38+
private readonly AWSOptions _awsOptions;
39+
private readonly IAWSCredentialsFactory _credentialsFactory;
40+
private readonly ILoggerFactory _loggerFactory;
41+
private readonly IConfiguration _configuration;
3942

4043
/// <summary>
4144
/// Constructs an instance of the ClientFactory
4245
/// </summary>
4346
/// <param name="type">The type object for the Amazon service client interface, for example IAmazonS3.</param>
44-
internal ClientFactory(Type type, AWSOptions awsOptions)
47+
internal ClientFactory(Type type, AWSOptions awsOptions, IAWSCredentialsFactory credentialsFactory, ILoggerFactory loggerFactory, IConfiguration configuration)
4548
{
4649
_serviceInterfaceType = type;
4750
_awsOptions = awsOptions;
51+
_credentialsFactory = credentialsFactory;
52+
_loggerFactory = loggerFactory;
53+
_configuration = configuration;
4854
}
4955

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

61-
var options = _awsOptions ?? provider.GetService<AWSOptions>();
62-
if(options == null)
66+
var options = _awsOptions;
67+
if(_awsOptions == null)
6368
{
64-
var configuration = provider.GetService<IConfiguration>();
65-
if(configuration != null)
69+
if(_configuration != null)
6670
{
67-
options = configuration.GetAWSOptions();
71+
options = _configuration.GetAWSOptions();
6872
if (options != null)
6973
logger?.LogInformation("Found AWS options in IConfiguration");
7074
}
7175
}
7276

73-
return CreateServiceClient(logger, _serviceInterfaceType, options);
77+
return CreateServiceClient(logger, _serviceInterfaceType, options, _credentialsFactory);
7478
}
7579

7680
/// <summary>
@@ -79,10 +83,10 @@ internal object CreateServiceClient(IServiceProvider provider)
7983
/// </summary>
8084
/// <param name="provider">The dependency injection provider.</param>
8185
/// <returns>The AWS service client</returns>
82-
internal static IAmazonService CreateServiceClient(ILogger logger, Type serviceInterfaceType, AWSOptions options)
86+
internal static IAmazonService CreateServiceClient(ILogger logger, Type serviceInterfaceType, AWSOptions options, IAWSCredentialsFactory credentialsFactory)
8387
{
8488
PerformGlobalConfig(logger, options);
85-
var credentials = CreateCredentials(logger, options);
89+
var credentials = credentialsFactory.Create();
8690

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

163-
/// <summary>
164-
/// Creates the AWSCredentials using either the profile indicated from the AWSOptions object
165-
/// of the SDK fallback credentials search.
166-
/// </summary>
167-
/// <param name="options"></param>
168-
/// <returns></returns>
169-
private static AWSCredentials CreateCredentials(ILogger logger, AWSOptions options)
170-
{
171-
if (options != null)
172-
{
173-
if (options.Credentials != null)
174-
{
175-
logger?.LogInformation("Using AWS credentials specified with the AWSOptions.Credentials property");
176-
return options.Credentials;
177-
}
178-
if (!string.IsNullOrEmpty(options.Profile))
179-
{
180-
var chain = new CredentialProfileStoreChain(options.ProfilesLocation);
181-
AWSCredentials result;
182-
if (chain.TryGetAWSCredentials(options.Profile, out result))
183-
{
184-
logger?.LogInformation($"Found AWS credentials for the profile {options.Profile}");
185-
return result;
186-
}
187-
else
188-
{
189-
logger?.LogInformation($"Failed to find AWS credentials for the profile {options.Profile}");
190-
}
191-
}
192-
}
193-
194-
var credentials = FallbackCredentialsFactory.GetCredentials();
195-
if (credentials == null)
196-
{
197-
logger?.LogError("Last effort to find AWS Credentials with AWS SDK's default credential search failed");
198-
throw new AmazonClientException("Failed to find AWS Credentials for constructing AWS service client");
199-
}
200-
else
201-
{
202-
logger?.LogInformation("Found credentials using the AWS SDK's default credential search");
203-
}
204-
205-
return credentials;
206-
}
207-
208167
/// <summary>
209168
/// Creates the ClientConfig object for the service client.
210169
/// </summary>
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
/*
2+
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License").
5+
* You may not use this file except in compliance with the License.
6+
* A copy of the License is located at
7+
*
8+
* http://aws.amazon.com/apache2.0
9+
*
10+
* or in the "license" file accompanying this file. This file is distributed
11+
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
12+
* express or implied. See the License for the specific language governing
13+
* permissions and limitations under the License.
14+
*/
15+
using Amazon.Extensions.NETCore.Setup;
16+
using Amazon.Runtime;
17+
using Amazon.Runtime.CredentialManagement;
18+
using Microsoft.Extensions.Logging;
19+
20+
namespace AWSSDK.Extensions.NETCore.Setup
21+
{
22+
public class DefaultAWSCredentialsFactory : IAWSCredentialsFactory
23+
{
24+
private readonly AWSOptions _options;
25+
private readonly ILogger<DefaultAWSCredentialsFactory> _logger;
26+
27+
public DefaultAWSCredentialsFactory(AWSOptions options, ILogger<DefaultAWSCredentialsFactory> logger = null)
28+
{
29+
_options = options;
30+
_logger = logger;
31+
}
32+
33+
/// <summary>
34+
/// Creates the AWSCredentials using either AWSOptions.Credentials, AWSOptions.Profile + AWSOptions.ProfilesLocation,
35+
/// or the SDK fallback credentials search.
36+
/// </summary>
37+
public AWSCredentials Create()
38+
{
39+
if (_options?.Credentials != null)
40+
{
41+
_logger?.LogInformation("Using AWS credentials specified with the AWSOptions.Credentials property");
42+
return _options.Credentials;
43+
}
44+
45+
if (!string.IsNullOrWhiteSpace(_options?.Profile))
46+
{
47+
var chain = new CredentialProfileStoreChain(_options.ProfilesLocation);
48+
if (chain.TryGetAWSCredentials(_options.Profile, out var result))
49+
{
50+
_logger?.LogInformation("Found AWS credentials for the profile {OptionsProfile}", _options.Profile);
51+
return result;
52+
}
53+
54+
_logger?.LogInformation("Failed to find AWS credentials for the profile {OptionsProfile}", _options.Profile);
55+
}
56+
57+
var credentials = FallbackCredentialsFactory.GetCredentials();
58+
if (credentials == null)
59+
{
60+
_logger?.LogError("Last effort to find AWS Credentials with AWS SDK's default credential search failed");
61+
throw new AmazonClientException("Failed to find AWS Credentials for constructing AWS service client");
62+
}
63+
64+
_logger?.LogInformation("Found credentials using the AWS SDK's default credential search");
65+
66+
return credentials;
67+
}
68+
}
69+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
/*
2+
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License").
5+
* You may not use this file except in compliance with the License.
6+
* A copy of the License is located at
7+
*
8+
* http://aws.amazon.com/apache2.0
9+
*
10+
* or in the "license" file accompanying this file. This file is distributed
11+
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
12+
* express or implied. See the License for the specific language governing
13+
* permissions and limitations under the License.
14+
*/
15+
using Amazon.Runtime;
16+
17+
namespace AWSSDK.Extensions.NETCore.Setup
18+
{
19+
public interface IAWSCredentialsFactory
20+
{
21+
AWSCredentials Create();
22+
}
23+
}

0 commit comments

Comments
 (0)