3

I want to create a SecretsManager secret with two values both generated on the fly. Is that possible and how do I do it?

For example, if I wanted the final secret to look like this in JSON, what would the CloudFormation yaml look like?

{
  "password": "<Generated Value>",
  "serviceId": "fd07f2ab-96bd-4c5c-a4a9-9b8c43b666d7",
  "login": "<Different Generated Value>"
}

If this is part of a CF template that generates the password part of the secret string, how would I generate a dynamic 'login' field as well?

#This is a Secret resource with a randomly generated password in its SecretString JSON.
MySecretA:
  Type: 'AWS::SecretsManager::Secret'
  Properties:
    Name: MySecretForAppA
    Description: "This secret has a dynamically generated secret password and login."
    GenerateSecretString:
      SecretStringTemplate: '{"service-id": "<some guid>"}'
      GenerateStringKey: "password"
      PasswordLength: 30
      ExcludeCharacters: '"@/\'
John Rotenstein
  • 241,921
  • 22
  • 380
  • 470
TreverW
  • 440
  • 7
  • 16

3 Answers3

2

It appears that the AWS::SecretsManager::Secret resource only generates a single secret.

I could not find a way to refer to the actual contents of the secret via !Ref, which would have allowed two secrets to be generated, then referenced and combined in another resource. The only !Ref value available is the ARN of the secret.

Thus, I couldn't see a way to create two secrets in the one resource.

John Rotenstein
  • 241,921
  • 22
  • 380
  • 470
1

The AWS::SecretsManager::Secret resource does not support generating multiple random keys in a single secret. One way to accomplish this today is to leverage a custom CloudFormation resource (see https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/template-custom-resources.html). You can write a custom resource lambda that generates two random strings and does a PutSecretValue on the secret with the new values.

Another possible option is to have CloudFormation generate two secrets (one for username and one for password). I would not recommend this approach since every time you need the secret you will need to do two retrieves and it doubles your AWS Secrets Manager costs.

WillT
  • 109
  • 5
-1

You could create two secrets, and only use one.

For example, you could create one for the password:

MySecretPassword:
  Type: 'AWS::SecretsManager::Secret'
  Properties:
    Name: MySecretPasswordForAppA
    Description: "This secret has a dynamically generated secret password."
    GenerateSecretString:
      SecretStringTemplate: '{"serviceId": "<some guid>"}'
      GenerateStringKey: "password"
      PasswordLength: 30
      ExcludeCharacters: '"@/\'

And then another one that creates the login value, and uses the generated value guarded by MySecretPassword:

MySecret:
  Type: 'AWS::SecretsManager::Secret'
  Properties:
    Name: MySecretForAppA
    Description: "This secret has a dynamically generated secret password and login."
    GenerateSecretString:
      SecretStringTemplate:
        !Join:
          - ''
          - '{ "password": "'
          - !Join:
            - ':'
            - '{{resolve'
            - 'secretsmanager'
            - !Ref: MySecretPassword
            - 'SecretString'
            - 'password}}'
          - '", "service-id": "'
          - !Join:
            - ':'
            - '{{resolve'
            - 'secretsmanager'
            - !Ref: MySecretPassword
            - 'SecretString'
            - 'serviceId}}'
          - '" }'
      GenerateStringKey: "login"
      PasswordLength: 30
      ExcludeCharacters: '"@/\'