0
votes

My Secret Stored look like this

Secret Manager

SecretName : MultipleKeySecretName

{
  "Key1": "Key1 Value",
  "Key2": "Key2 Value"
}

SecretName : SingleSecretName

{
  "Key1": "Key1 Value"
}

I have shared package where there is a common code which retrieve AWS Secret Values.

 public async Task<string> GetValue(string key)
    {
        Requires.ArgumentNotNullOrWhitespace(key, "key");
        var region = RegionEndpoint.GetBySystemName(CurrentRegion);

        if (region == null)
        {
            logger.LogError($"Unable to retrieve key because region is not specified by application");
            throw new ArgumentNullException("Unable to retrieve key because region is not specified by application");
        }

        try
        {
            var secretsManager = new AmazonSecretsManagerClient(region);
            var request = new GetSecretValueRequest
            {
                SecretId = key
            };
            var getSecretValueResponse = await secretsManager.GetSecretValueAsync(request);

            if (getSecretValueResponse.HttpStatusCode != System.Net.HttpStatusCode.OK)
            {
                logger.LogError($"Unable to find secret with keyname : {key} in secret manager");
                throw new ArgumentNullException($"Unable to find secret with keyname : {key} in secret manager");
            }

            var secretStringJson = getSecretValueResponse.SecretString;
            return JsonConvert.DeserializeObject<Dictionary<string, string>>(secretStringJson).Values.FirstOrDefault();
        }
        catch (Exception exception)
        {
            logger.LogError($" An error occurred getting value from secret manager for" +
                   $" Key :{key} Region : {region} {exception.Message}");
            throw;
        }
    }

I consumed this above code like this when I had single secertkeys in one secret

var mysingleKey =  GetValue("SingleSecretName").Result; //Work perfect for single scenearios

Now I have multiple keys with same secret see above.

var multipleValues =  GetValue("MultipleKeySecretName").Result

as per the current implementation it will always bring first value. I can change the shared package to get Dictionary of values.

  1. How do get each key separately with above code
    Is this possible (GetValue("SingleSecretName.Key1").Result?
  2. What is the best way to get multiple keys with one single call to AWS Secret Manager?
    Getting all values in shared code and get the value from the dictionary ?
1

1 Answers

2
votes

The problem with your code is that you are assuming there is just one item in the dictionary, and always returning it. If you really want to just get the one item from the dictionary you need to specify the secretId (you were calling this key) as well as the dictionary key. Then you can look for that key in the result. Something like this:

public async Task<string> GetValueAsync(string secretId, string key)
    {
        Requires.ArgumentNotNullOrWhitespace(secretId, "secretId");
        Requires.ArgumentNotNullOrWhitespace(key, "key");
        var region = RegionEndpoint.GetBySystemName(CurrentRegion);

        if (region == null)
        {
            logger.LogError($"Unable to retrieve key because region is not specified by application");
            throw new ArgumentNullException("Unable to retrieve key because region is not specified by application");
        }

        try
        {
            var secretsManager = new AmazonSecretsManagerClient(region);
            var request = new GetSecretValueRequest
            {
                SecretId = secretId
            };
            var getSecretValueResponse = await secretsManager.GetSecretValueAsync(request);

            if (getSecretValueResponse.HttpStatusCode != System.Net.HttpStatusCode.OK)
            {
                logger.LogError($"Unable to find secret with secretId : {secretId} in secret manager");
                throw new ArgumentException($"Unable to find secret with secretId : {secretId} in secret manager");
            }

            var secretStringJson = getSecretValueResponse.SecretString;
            var secret = JsonConvert.DeserializeObject<Dictionary<string, string>>(secretStringJson);

            if (secret.ContainsKey(key))
            {
                return secret[key];
            }
            else 
            {
                logger.LogError($"Unable to find key within secret : {key}");
                throw new ArgumentException($"Unable to find key within secret : {key}");
            }
        }
        catch (Exception exception)
        {
            logger.LogError($" An error occurred getting value from secret manager for" +
                   $" Key :{key} Region : {region} {exception.Message}");
            throw;
        }
    }