5
votes

I am trying to create an AWS stack in CloudFormation having a secret in the JSON.

I don't want the value of the secret displayed in the parameters and I don't want my instance (fargate or ec2) to access the secrets manager. I want CloudFormation to retrieve the value from the secrets manager and inject it in the template during runtime.

This is what I did:

  1. Create a secret

  2. Create a template using Designer

  3. Read the secret and create a resource. In this case I am creating a bucket that has as a tag the secret. I know this is not secure, but the bucket is being used just as a proof of concept.

  4. Validate that the bucket contains a tag with the secret

This is my template:

{
    "AWSTemplateFormatVersion": "2010-09-09",
    "Description": "create a single S3 bucket",
    "Resources": {
        "SampleBucket": {
            "Type": "AWS::S3::Bucket",
            "Properties": {
                "BucketName": "asantostestbucket",
                "Tags" : [
                    {
                        "Key" : "keyname",
                        "Value" : "{{resolve:secretsmanager:dev/learning:SecretString:hello}}"
                    }
            ]
            }
        }
    }
}

Which is giving me the error One or more tags are not valid.

How can I indicate to CloudFormation that I want it to read the secret, instead of trying to read the tag as text? In other words, replace "{{resolve:secretsmanager:dev/learning:SecretString:hello}}" with the value, instead of reading it as a text.

2
Why do you not want the instance to access Secrets Manager? This is the most secure method, with auditing. The only other method would be to pass the value from CloudFormation to the instance via User Data, but the secret would be visible in the User Data. The bucket method is "security by obscurity", which is not real security. Plus, the instance would need permission to retrieve the S3 metadata, which no different to giving it permission to access the Secrets Manager.John Rotenstein
@JohnRotenstein, I am aware of all you mentioned. This is not production code, it is a proof of concept. We want to know if it is possible.Alexandre Santos

2 Answers

4
votes

To reproduce this situation, I did the following:

  • In the Secrets Manager, created a new secret
    • "Other type of secrets"
    • Key: hello
    • Value: surprise
    • Secret name: dev/learning
  • Tested the secret using the AWS CLI

Here's the output:

aws secretsmanager get-secret-value --secret-id dev/learning
{
    "ARN": "arn:aws:secretsmanager:ap-southeast-2:123456789012:secret:dev/learning-kCxSK3",
    "Name": "dev/learning",
    "VersionId": "...",
    "SecretString": "{\"hello\":\"surprise\"}",
    "VersionStages": [
        "AWSCURRENT"
    ],
    "CreatedDate": 1560925072.106
}
  • Launched the CloudFormation template you supplied above (but with a different bucket name)

Result: I received the message One or more tags are not valid

So, I got the same result as you did.

I then tried creating a different type of resource using the secret:

{
    "AWSTemplateFormatVersion": "2010-09-09",
    "Resources": {
        "SecurityGroup": {
            "Type": "AWS::EC2::SecurityGroup",
            "Properties": {
                "GroupDescription": "{{resolve:secretsmanager:dev/learning:SecretString:hello}}"
            }
        }
    }
}

This worked successfully:

aws ec2 describe-security-groups --group-id sg-03cfd71f4539a4b7e
{
    "SecurityGroups": [
        {
            "Description": "surprise",
            ...

So, it seems that the {{resolve}} is behaving correctly, but for some reason the S3 Tag doesn't like it.

Bottom line: It is possible, but not advisable.

0
votes

Btw instead of using designer (which is a bit cumbersome to work with) you can try cloudkast which is an online cloudformation template generator.