5

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.

Alexandre Santos
  • 8,170
  • 10
  • 42
  • 64
  • 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 Jun 19 '19 at 02:29
  • @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 Jun 19 '19 at 04:49

3 Answers3

7

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.

John Rotenstein
  • 241,921
  • 22
  • 380
  • 470
  • My suspicion is that only some resources can be used to resolve secrets. – Alexandre Santos Jun 19 '19 at 15:33
  • 2
    I believe the Cloud Formation team does not allow dynamic references to secrets to expand in places where they would be publicly visible. This includes things like EC2 metadata (which is visible in the console as base64 encoded data) and tags. – JoeB Jun 21 '19 at 00:16
0

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

krunal shimpi
  • 58
  • 1
  • 2
0

If you already have a secret in the secrets manager(for eg. API key) and your lambda function can read the secret. Just add the lines 4 and 5, which is to describe and get secret to your cloudformation YAML template.

Action:
  - 'logs:CreateLogGroup'
  - 'logs:CreateLogStream'
  - 'logs:PutLogEvents'
  - 'secretsmanager:DescribeSecret'
  - 'secretsmanager:GetSecretValue'
Resource: '*'`
Tyler2P
  • 2,324
  • 26
  • 22
  • 31
Yogesh
  • 1