4

I want to export the read_only_user's password to the EC2 instance. How can I access the created password inside the UserData?

Resources:
  ReadOnlyUserCredentials:
      Type: AWS::SecretsManager::Secret
      Properties:
        Name: !Sub "${AWS::StackName}/readonly-user-credentials"
        GenerateSecretString:
          SecretStringTemplate: '{"username": "read_only_user"}'
          GenerateStringKey: 'password'
          PasswordLength: 16
          ExcludeCharacters: '"@/\'
  WebServer:
    Type: AWS::EC2::Instance
    Properties:
      ImageId: ami-a4c7edb2
      InstanceType: t2.micro
      UserData:
        Fn::Base64: !Sub |
          #!/bin/bash
          echo "${!Join ['', ['{{resolve:secretsmanager:', !Ref ReadOnlyUserCredentials, ':SecretString:password}}' ]]}" > password

I tried using the !Join but of course that is not working. I will really appreciate any help here.

Update:

      UserData:
        Fn::Base64:
         Fn::Sub:
          - |
            echo ${PasswordStr} > password
          - PasswordStr: !Join ['', ['{{resolve:secretsmanager:', !Ref ReadOnlyUserCredentials, ':SecretString:password}}' ]]

By changing the code as shown above, I did get the resolve string, but it did not give me the actual password. How do I resolve the arn to get the plain password?

SpaceX
  • 555
  • 1
  • 6
  • 16
  • 1
    Is this not the same as https://stackoverflow.com/questions/48625737/userdata-script-with-resource-attribute-cloudformation – David Webster Jan 17 '19 at 08:29
  • David, you're right. By using the link above, I was able to pass the variable. Is there anyway to get access to the password in the cloudformation, `!Join ['', ['{{resolve:secretsmanager:', !Ref ReadOnlyUserCredentials, ':SecretString:password}}' ]]` is just giving the resolver string. How can I get the actual password? – SpaceX Jan 17 '19 at 10:21

1 Answers1

3

You probably do not want CFN to expand your secret in the user data because the password would be embedded in the base64 encoded user data script which is visible in the EC2 console.

Instead you should take advantage of the fact that you have a script that executes on the host and call secrets manager at script execution time (warning, not tested):

Resources:
  ReadOnlyUserCredentials:
      Type: AWS::SecretsManager::Secret
      Properties:
        Name: !Sub "${AWS::StackName}/readonly-user-credentials"
        GenerateSecretString:
          SecretStringTemplate: '{"username": "read_only_user"}'
          GenerateStringKey: 'password'
          PasswordLength: 16
          ExcludeCharacters: '"@/\'
  WebServer:
    Type: AWS::EC2::Instance
    Properties:
      ImageId: ami-a4c7edb2
      InstanceType: t2.micro
      UserData:
        Fn::Base64: !Sub |
          #!/bin/bash
          yum update -y
          yum install -y jq
          aws --region ${AWS::Region} secretsmanager get-secret-value --secret-id !Ref ReadOnlyUserCredentials --query SecretString --output text | jq -r .password > password
JoeB
  • 1,503
  • 7
  • 9
  • I tried this, however, this assumes that you have your access credentials set inside of the instance in order to perform operations using aws cli ... – Benny Jul 07 '20 at 09:42
  • Yes, you need to use [Roles for EC2](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/iam-roles-for-amazon-ec2.html) to setup permissions for the instance to access the secret. You can find more details in the previous answer to the [dynamic-references](https://stackoverflow.com/questions/53589880/dynamic-references-to-specify-secret-manager-values-in-aws-cloudformation/53638555#53638555) question. – JoeB Jul 08 '20 at 20:54