Sunday, June 18, 2017

ImportValue in UserData with YAML ~ CloudFormation

When trying to concoct a UserData statement in an EC2 CloudFormation in YAML a !SUB function can be used to replace variables in the UserData with values from the same template, or from another template using the !ImportValue directive.

The UserData must be converted to Base64, followed by a Sub function which has two inputs: the first is the string with variables to replace. The second input is the map of variables. When the sub function is created a pipe or | is added to create a multiline statement. Note that UserData seems to be picky about when you use the fn:: format and when you reference something with an exclamation point like !Sub. Maybe this will change but for now this works:

     Fn::Base64: !Sub 
       - | 

The first argument of the sub function is the UserData section with variables in the format of a dollar sign and enclosed in curly braces like this:

     this is some text ${Variable1} followed by more text

The second argument is the list of variables.

When only one variable is required the argument can look like this:

          - Variable1: 
          'Fn::ImportValue': 'NameOfTemplateOutputValue'

In the case of multiple variables, a map is passed in so have to understand the format for a map in YAML. The map format does not have dashes like a list. It is simply key value pairs on separate lines like this:

           'Fn::ImportValue': 'NameOfTemplateOutputValue1'
           'Fn::ImportValue': 'NameOfTemplateOutputValue2'
           'Fn::ImportValue': 'NameOfTemplateOutputValue3'

For a complete template in action you can check out this one which is used to capture packets from a WatchGuard Firebox Cloud. It needs to retrieve the SSH key from an S3 bucket, SSH into the Firebox Cloud and it also sets up the instance to use the Firebox Cloud as an NTP server. The IP address for the Firebox Cloud and the S3 bucket name are output values from other templates: