skip to Main Content

We’ve got some Windows EC2 Instances deployed using Cloudformation that are configured using cfn-init scripts.

In order to update components on the instances later on, we need to re-run some of the Cloudformation::Init configsets using the cfn-init helper scripts and one of the required parameters, –stack, is the stack name. I was expecting this value would be dynamically available via the EC2 Instance Metadata as a single call but I have not been able to find it.

I am posting a workaround script but I’m still wondering if there is a simpler, robust way that I am missing.

2

Answers


  1. Chosen as BEST ANSWER

    Since the initial cfn-init command included in the User Data script includes the ${AWS::StackName} Psuedo parameter we can parse this script to extract it. The following PowerShell script illustrates the technique and a similar bash script could be used on Linux instances:

    function Get-CfnInitStackName {
        [string]$token = Invoke-RestMethod -Headers @{"X-aws-ec2-metadata-token-ttl-seconds" = "21600"} -Method PUT -Uri http://169.254.169.254/latest/api/token
        $userDataScript = (Invoke-RestMethod -Headers @{"X-aws-ec2-metadata-token" = $token} -Method GET -Uri http://169.254.169.254/latest/user-data).script
        # Exact regex would be determined by your command usage in the UserData element of your Cloudformation template
        if ($userDataScript -match 'cfn-init.+ --stack (?<stackName>S+) --resource') {
            $stackName = $Matches.stackName
        } else {
            throw "Stack name not found within user data script" + [System.Environment]::NewLine + $userDataScript
        }
    
        $stackName
    }
    
    function Invoke-CfnInitConfigset([string]$ConfigSet = 'deploy_full') {
        $stackName = Get-CfnInitStackName
        cfn-init --verbose --stack $stackName --resource Instance --region ap-southeast-2 --configsets $ConfigSet
        # TODO: Handle result code and disploy cfn-init.log output
    }
    

    Note I considered using the aws cloudformation describe-stack-resources call providing the ec2 instance-id from metadata as the --physical-resource-id parmeter. This does work but is an extra dependency on an external service acall and would require the IAM Instance Profile permissions to be extended.


  2. You probably want to define cfn-hup in your cloudformation template so that it lays down the files with variables you need:

    from docs

    ...
      LaunchConfig:
        Type: "AWS::AutoScaling::LaunchConfiguration"
        Metadata:
          QBVersion: !Ref paramQBVersion
          AWS::CloudFormation::Init:
    ...
                /etc/cfn/hooks.d/cfn-auto-reloader.conf:
                  content: !Sub |
                    [cfn-auto-reloader-hook]
                    triggers=post.update
                    path=Resources.LaunchConfig.Metadata.AWS::CloudFormation::Init
                    action=/opt/aws/bin/cfn-init -v --stack ${AWS::StackName} --resource LaunchConfig --configsets wordpress_install --region ${AWS::Region}
                    runas=root
                  mode: "000400"
                  owner: "root"
                  group: "root"
    ...
    

    https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/cfn-hup.html

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search