Open brignolij opened 1 year ago
I will have to think at the best way to support this scenario.
@Kralizek Hi again,
I spend time on this topic.
Using your Extension, we can "use" a custom implementation of GetSecret to call manually the secret layer.
I did it, but the layer seems not working very well. I'm getting error 4xx, not read to serve traffic.
But here how i did it :
public class SecretManagerAdvanced : AmazonSecretsManagerClient
{
private readonly ISecretsProvider _secretsProvider;
public SecretManagerAdvanced(AmazonSecretsManagerConfig config) : base(config)
{
_secretsProvider = new SecretsProvider();
}
public SecretManagerAdvanced(AWSCredentials credentials, AmazonSecretsManagerConfig config) : base(credentials, config)
{
_secretsProvider = new SecretsProvider();
}
public override async Task<GetSecretValueResponse> GetSecretValueAsync(GetSecretValueRequest request,
CancellationToken cancellationToken = new CancellationToken())
{
var result = _secretsProvider.GetSecretAsync(request.SecretId);
if (result.Result is not null)
{
var response = new GetSecretValueResponse();
response.Name = request.SecretId;
response.SecretString = result.Result;
return response;
}
return await base.GetSecretValueAsync(request, cancellationToken);
}
}
public static class SecretMapper{
///
private static IAmazonSecretsManager CreateClient()
{
var options = new SecretsManagerConfigurationProviderOptions();
var region = RegionEndpoint.EUCentral1;
// AWSCredentials? Credentials;
if (options.CreateClient != null)
{
return options.CreateClient();
}
var clientConfig = new AmazonSecretsManagerConfig
{
RegionEndpoint = region
};
options.ConfigureSecretsManagerConfig(clientConfig);
return Credentials switch
{
null => new SecretManagerAdvanced(clientConfig),
_ => new SecretManagerAdvanced(Credentials, clientConfig)
};
}
}
internal interface ISecretsProvider
{
Task<string?> GetSecretAsync(string secretName);
}
class SecretsProvider : ISecretsProvider
{
private readonly HttpClient _httpClient;
private readonly string _token;
private readonly string GetSecretsEndpoint = "/secretsmanager/get?secretId=";
public SecretsProvider()
{
_httpClient = new HttpClient() { BaseAddress = new Uri("http://localhost:2773") };
_httpClient.DefaultRequestHeaders.Add("X-AWS-Parameters-Secrets-Token", Environment.GetEnvironmentVariable("AWS_SESSION_TOKEN"));
}
public async Task<string?> GetSecretAsync(string secretName)
{
var httpRequest = new HttpRequestMessage(
HttpMethod.Get,
new Uri($"{GetSecretsEndpoint}{secretName}", UriKind.Relative));
var response = await _httpClient
.SendAsync(httpRequest)
.ConfigureAwait(false);
var responseAsJsonString = await response.Content
.ReadAsStringAsync()
.ConfigureAwait(false);
if (response.IsSuccessStatusCode)
{
return responseAsJsonString;
}
return null;
}
}
Did you already use lambda secret layer and make it work ?
Regards
No I've never used the layer tbh
@Kralizek according this : https://stackoverflow.com/questions/75624681/aws-secrets-and-parameters-lambda-extension-throw-not-ready-to-serve-traffic
the layer will be ready when the application has already started.
Is there a way to use your Extension after the application start ?
EDIT: I confirm, when calling HTTP GetSecret after application start, for example in a controller, the layer return the secret effectively.
For information, here how it works in lambda:
Hello,
I'm using AWSSecretsManagerConfigurationExtensions with api running on Lambda. But i'm now facing the issue where the GetSecretValue limit of 10k read/seconds is reached.
I saw AWS provide a cache layer for secret and parameter that can be dirrectly link to a lambda function : https://docs.aws.amazon.com/secretsmanager/latest/userguide/retrieving-secrets_lambda.html
For example you can add this layer to your function with cloudformation like this :
Actually AWSSecretsManagerConfigurationExtensions is reading secret at each application start. in the case of .net api running on lambda, each invocations is reading secret.
Can we imagine an implementation of the cache layer of lambda ?
Regards