AWS Cloudformation output double quotes in a file

2019-02-15 13:33发布

After much research and frustration, I'm not quite getting the output I'm hoping for.

The desired output into a file would be for example

"accessKeyId":"UIIUHO]SOMEKEY[SHPIUIUHIU"

But what I'm getting is

accessKeyId:UIIUHO]SOMEKEY[SHPIUIUHIU

Below is the line in an AWS Cloudformation template

{"Fn::Join": ["", ["echo \" accessKeyId:", {"Ref": "AccessKeyId"}, "\" >>  /home/ubuntu/myfile.json"] ] }, 

I've tried adding \" with in the echo statement but no quotes are output. Can someone show how to produce the desired output above?

2条回答
ら.Afraid
2楼-- · 2019-02-15 14:06

It's a problem of correctly escaping the quotes in fact.

Reason is : \" inside a CloudFormation string is escaped as " (double-quote).

For example, "hello \"me\"" gives you :

hello "me"

In your line, what you really feed to bash is :

echo " accessKeyId:XXXXX" >> /home/ubuntu/myfile.json

Considering bash use of quotes, you get the string

accessKeyId:XXXXX

inside your /home/ubuntu/myfile.json

To solve your problem, I would recommend using:

{"Fn::Join": ["", ["echo '\"accessKeyId\":\"", {"Ref": "AccessKeyId"}, "\"' >>  /home/ubuntu/myfile.json"] ] },

which is escaped as

echo '"accessKeyId":"XXXXX"' >>  /home/ubuntu/myfile.json

(hard to read : the whole string used by echo is inside single-quotes).

I'm not able to try it now, but it should do the trick.

查看更多
劳资没心,怎么记你
3楼-- · 2019-02-15 14:16

If you are trying to generate a file on the EC2 instance being started by CloudFormation, I would recommend the following approach :

In the "Resources" section (adapt your policy accordingly):

     "User": {
            "Type": "AWS::IAM::User",
            "Properties": {
                "Path": "/",
                "Policies": [
                    {
                        "PolicyName": "AllPrivileges",
                        "PolicyDocument": {
                            "Statement": [
                                {
                                    "Effect": "Allow",
                                    "Action": [
                                        "*"
                                    ],
                                    "Resource": [ "*" ]
                                }
                            ]
                        }
                    }
                ]
            }
    },
    "AccessKey" : {
       "Type" : "AWS::IAM::AccessKey",
       "Properties" : {
          "UserName" : { "Ref" : "User" }
       }
    },

In the EC2 Instance resource section :

        "Metadata" : {
            "AWS::CloudFormation::Init" : {
              "config" : {
                    "files" : {
                      "/home/ec2-user/.aws/config" : {
                        "content" : { "Fn::Join" : ["", [
                          "[profile eb-cli]", "\n",
                          "aws_access_key_id = ", { "Ref" : "AccessKey" }, "\n",
                          "aws_secret_access_key = ", { "Fn::GetAtt" : [ "AccessKey", "SecretAccessKey" ] }, "\n"
                        ]]},
                        "mode" : "000600",
                        "owner" : "ec2-user",
                        "group" : "ec2-user"
                      }
                    },

Adding double quotes in the output should be as simple as escaping them such as

          "files" : {
                      "/home/ec2-user/.aws/config" : {
                        "content" : { "Fn::Join" : ["", [
                          "[profile eb-cli]", "\n",
                          "\"aws_access_key_id\" = \"", { "Ref" : "AccessKey" }, "\"", "\n",
                          "\"aws_secret_access_key\" = \"", { "Fn::GetAtt" : [ "AccessKey", "SecretAccessKey" ] }, , "\"", "\n"
                        ]]},
                        "mode" : "000600",
                        "owner" : "ec2-user",
                        "group" : "ec2-user"
                      }
                    },

But this is not required for AWS CLI and SDK configuration files

In order to trigger the AWS::Cloudformation::Init section of your template, you must explicitly call cfn-init

I am usually doing this from the user data section :

            "UserData" : { "Fn::Base64" : { "Fn::Join" : ["", [
                "#!/bin/bash -x\n",
                "exec &> /home/ec2-user/userdata.log\n",
                "/opt/aws/bin/cfn-init --region ", { "Ref" : "AWS::Region" }, " -s ", { "Ref" : "AWS::StackId" }, " -r DockerInstance -v\n",
                "/opt/aws/bin/cfn-signal -e $? ", { "Fn::Base64" : { "Ref" : "WaitConditionHandle" }}, "\n"
            ]] } }
查看更多
登录 后发表回答