aws-cloudformation / cloudformation-coverage-roadmap

The AWS CloudFormation Public Coverage Roadmap
https://aws.amazon.com/cloudformation/
Creative Commons Attribution Share Alike 4.0 International
1.11k stars 54 forks source link

AWS::CloudFormation::Init dynamic-references #179

Open destroy-everything opened 4 years ago

destroy-everything commented 4 years ago

Quick Sample Summary:

  1. Title -> AWS::CloudFormation::Init dynamic-references
  2. Scope of request -> Use of Dynamic referencing in UserData ( Instance resource) and aws::cloudformation::init currently is not supported

Dynamic referencing allows resolution of secrets ( via secretsmanager ) or parameters ( via parameters store) in cloud formation, which will in-turn discontinue the practice of putting secrets in plain text in CloudFormation templates (https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/dynamic-references.html)

  1. Expected behavior -> Dynamic referencing inside AWS::CloudFormation::Init should resolve secrets .
  2. Test case recommendation (optional) -> it should help me do X given existing Y (if applicable); it should/shouldn't change Z.
  3. Links to existing API doc (optional) -> Updated API docs at https://example.com/api-new.html
  4. Category tag (optional) -> Compute
  5. Any additional context (optional)
riosje commented 4 years ago

ey, we really need this feature.

chaserb commented 3 years ago

Not sure if this would work for your needs, but I was able to workaround this limitation by adding the "IamInstanceProfile" property to the EC2 instance that needed the secret from secretsmanager. First, I create the secret, a role for that secret, and an instance profile for that role:

Resources:
    MySecret:
        Type: AWS::SecretsManager::Secret
        Properties:
            Name: !Sub /${AWS::Region}/${Env}/my/secret
            SecretString: changeme
    MySecretReadWriteRole:
        Type: AWS::IAM::Role
        Properties:
            RoleName: !Sub MySecretReadWrite-${AWS::Region}-${Env}
            AssumeRolePolicyDocument:
                Version: 2012-10-17
                Statement:
                    - Effect: Allow
                      Principal:
                          Service: [ ec2.amazonaws.com ]
                      Action: [ sts:AssumeRole ]
            Policies:
                - PolicyName: root
                  PolicyDocument:
                      Version: 2012-10-17
                      Statement:
                          - Effect: Allow
                            Action:
                              - secretsmanager:GetSecretValue
                              - secretsmanager:UpdateSecret
                            Resource: !Ref MySecret
    MySecretReadWriteProfile:
        Type: AWS::IAM::InstanceProfile
        Properties:
            Roles:
                - !Ref MySecretReadWriteRole

Then, I can attach the instance profile to any EC2 instance that needs to the secret:

Resources:
    MyInstance:
        Type: AWS::EC2::Instance
        Properties:
            KeyName: !Ref KeyPair
            IamInstanceProfile: !Ref MySecretReadWriteProfile
        Metadata:
            AWS::CloudFormation::Init:
                configSets:
                    installAndConfigure: [ install, configure ]
                install:
                    commands:
                        01-grab-secret:
                            command: !Sub aws --region "${AWS::Region}" secretsmanager get-secret-value --secret-id "${MySecret}" | grep SecretString | awk -F'"' '{ print $4 }' > /tmp/hereIsMySecret.txt
markotrenkovski commented 3 years ago

Any ETA from the team on this issue? We would really like to use secrets manager to reference values in Metadata safely.

umutawakil commented 1 year ago

You can reference external values in your stack like so: Instead of this -> {"Ref": "Password"} you can do -> {"Fn::ImportValue": "dev-password"} The dev-password field can come from a stack you created that holds nothing but properties. The plain text will be visible in the cloudformation console for that stack but you wont need to keep the values in source control and they'll be available to your other templates. If you have a concern about users with cloudformation console access being able to see secrets they wouldn't normally have access to I imagine you can limit the visibility through IAM.

You can also inject template properties at the command line so you dont have to use files. Same syntax as the usual createStack updateStack command but as key pairs instead of .json or yml files. Just some alternatives till an integration with the secrets manager is in place. At least thats how I keep my secrets out of git.