Parameters

Parameters

Everything you need to know about CloudFormation Parameters; the next top-level section of AWS CloudFormation

Introduction

From the previous blog posts, we have been hardcoding specific values like ImageId, InstanceType, KeyName etc. directly in our template.

MyEC2Instance: 
    Type: AWS::EC2::Instance
    Properties: 
      ImageId: ami-04e5276ebb8451442
      InstanceType: t2.micro

But what about situations where you want to choose between different EC2 instance types during deployment, or maybe reference existing security groups by name, or maybe you want to securely manage database credentials without exposing them in the template? You will need parameters for such reasons.

So, what are parameters?

Parameters allow us to provide dynamic values when we are creating new stacks or when updating an existing stack. This prevents you from hardcoding specific values from your template.

Here is a code snippet of parameters from my template

Parameters:
  ParamKeyName:
    Description: Select the key name from the list
    Type: AWS::EC2::KeyPair::KeyName

  ParamAZName:
    Description: Select the Avaiability Zone name from the list
    Type: AWS::EC2::AvailabilityZone::Name

  ParamInstanceType: #Go to SSM> PARAMETER STORE,,,E.G. Name - DemoInstance  Value - t2.micro
    Description: Select the Instance Type from the list
    Type: AWS::SSM::Parameter::Value<String>

Here are the dynamic values that I will key in before uploading the template on AWS CloudFormation.

In the Parameters section, we have declared a parameter named ParamKeyName (You can declare any name) of type AWS::EC2::KeyPair::KeyName. It gives you the flexibility to choose which ssh key to use when creating or updating your stack.

Benefits of Parameters

Parameters are essential for a couple of reasons:

  • Offer flexibility - Parameters enable you to reuse templates. You can deploy different stacks with different configurations based on the values that you specify when reuploading the template. you can have one template deploying an instance in Availability zone A with a ssh key (KeyName) called 'cloudformation'. You can have the same template deploying another instance in Availability zone B with a ssh key called 'demo-key'.

  • Environment-Specific Deployments - You can have different parameter values for different environments (e.g., dev, test, prod) where you can create different stacks. One for dev, test and another for prod.

  • Security - Like I stated earlier, you can secure database credentials alongside other sensitive information such as sensitive URLs and endpoints, user credentials etc. using parameters

  • Validation - You can declare predefined constraints that ensure only certain input values are added as parameter values. You can specify to only allow certain instance types in your stack e.g. t3.small, t2.micro, t3.large. This validation enforces compliance by only accepting allowed values specified in the parameters section of the template.

Parameter Types

AWS-specific parameter types

These parameter types are essential in helping you detect invalid values when creating or updating your stack. The parameter you specify must be assigned a value when uploading the template for CloudFormation to create/update a stack successfully.

Supported AWS-specific parameter types

If you intend to use parameters with AWS-specific types, you must enter existing AWS values in your account e.g. key pair names, VPC id, instance id etc. AWS CloudFormation will validate these input values against existing values in the account.

AWS::EC2::AvailabilityZone::Name - Depending on the region you're deploying your template in, it will list out all the availability zones

Parameters:
  ParamAZName:
    Description: Select the Avaiability Zone name from the list
    Type: AWS::EC2::AvailabilityZone::Name

AWS::EC2::Image::Id - Allows you to specify the Image Id you want to use. You have to confirm from the console the image id depending on the region you want to deploy your stack in.

Note that when uploading a template, it doesn't show a drop-down list of values for this parameter type. You simply type it out after confirming from the console.

Parameters:
  ParamImageId:
    Description: specify the Image Id for your Instance
    Type: AWS::EC2::Image::Id

AWS::EC2::KeyPair::KeyName - Allows you to specify the ssh key to use depending on the ssh keys you have created in your account.

ParamKeyName:
    Description: Select the ssh key from the list
    Type: AWS::EC2::KeyPair::KeyName

Other supported AWS-specific parameter types

  • AWS::EC2::Instance::Id

  • AWS::EC2::SecurityGroup::GroupName

  • AWS::EC2::SecurityGroup::Id

  • AWS::EC2::Subnet::Id

  • AWS::EC2::Volume::Id

  • AWS::EC2::VPC::Id

  • AWS::Route53::HostedZone::Id

SSM Parameters

To understand SSM parameters, we will have to revisit AWS Systems Manager Parameter Store and understand its essence.

Parameter store acts as a central repository for all your configuration data and application settings. It also allows versioning by keeping records of all parameter changes, allowing you to rollback to previous versions if necessary.

It also improves security by encrypting your parameters either at rest or in transit thus reducing the risk of exposing sensitive values that would have been visible in your template.

By referencing SSM Parameters, your templates become leaner and more focused on infrastructure definitions. The template size becomes smaller and less complex, making them easier to understand and manage.

We start by creating a parameter in AWS SSM Parameter Store

Navigate to AWS System Manager console and on the left hand pane, choose Parameter Store under Application Management

Under Parameter Store, choose Create Parameter

Next, configure your parameter as follows. Name - DefaultInstance, Description - Default Instance Type, Tier - Standard, Type - String, Data Type - Text, Value - t2.micro

Next, upload your template in the console and take note of the parameter value (DefaultInstance) under ParamInstanceType entry

Below is the template that captures the AWS SSM parameter you created (DefaultInstance) to be fetched by AWS CloudFormation.

AWSTemplateFormatVersion: 2010-09-09
Description: Creating an ec2 instance

Parameters:
  ParamKeyName:
    Description: Select the key name from the list
    Type: AWS::EC2::KeyPair::KeyName

  ParamAZName:
    Description: Select the Avaiability Zone name from the list
    Type: AWS::EC2::AvailabilityZone::Name

  ParamInstanceType: #Go to SSM> PARAMETER STORE,,,E.G. Name - DemoInstance  Value - t2.micro
    Description: Select the Instance Type from the list
    Type: AWS::SSM::Parameter::Value<String>

Resources:
  HTTpSShSecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: Allow HTTP and SSH traffic 
      GroupName: DemoHTTPSShSecurityGroup
      SecurityGroupIngress:
        - IpProtocol: tcp
          FromPort: '80'
          ToPort: '80'
          CidrIp: 0.0.0.0/0
        - IpProtocol: tcp
          FromPort: '22'
          ToPort: '22'
          CidrIp: 0.0.0.0/0

  MyEC2Instance: 
    Type: AWS::EC2::Instance
    Properties: 
      ImageId: ami-01cd4de4363ab6ee8
      KeyName: !Ref ParamKeyName
      AvailabilityZone: !Ref ParamAZName
      InstanceType: !Ref ParamInstanceType
      Tags:
        - Key: Name
          Value: DevInstance
      UserData:
        Fn::Base64: |
          #!/bin/bash -xe
          yum update -y
          yum install -y httpd
          systemctl start httpd
          systemctl enable httpd
          echo '<html><h1>Hello From Your Restart Web Server!</h1></html>' > /var/www/html/index.html
      SecurityGroups: 
        - !Ref HTTpSShSecurityGroup

The instance type of the MyEC2Instance resource uses the !Ref intrinsic function which fetches the value associated with ParamInstanceType parameter

 InstanceType: !Ref ParamInstanceType

Parameter with additional Properties

This category consists of parameters with additional attributes/properties acting as constraints and guidelines for users interacting with your templates. Let's dive into some properties:

AllowedValues- contains the list of values allowed for the parameter

    Parameters:
      DBEngine:
        Description: Database engine (e.g., mysql, postgresql)
        Type: String
        AllowedValues: [mysql, postgresql, sqlserver]
  • ConstraintDescription- You have probably encountered a situation where you're filling out a google form to sign up for a service and you are required to enter your email address. The form probably has validation rules in place to ensure the email address you enter is in the correct format (ensuring the email address includes an "@" symbol and a domain name.)

    That is exactly what ConstraintDescription does. It aids template users in understanding why their input was rejected and how they can correct it.

    This parameter attribute lets you provide a custom error message when the user input fails to meet the specified constraints for a parameter.

      Parameters:
        RDSInstanceIdentifier:
          Description: RDS Database Instance Name
          ConstraintDescription: Allows alphanumerics
          Type: String
          MinLength: '1'
          MaxLength: '64'
          AllowedPattern: '[A-Za-z0-9]*'  # Allows alphanumerics
    

    From the template snippet above, you are required to input a database instance name that allows alphanumeric values. The name I provided includes special characters which are not part of the regular expression[A-Za-z0-9]* hence the validation error highlighted in red in the image below.

    Below is what is displayed when uploading your template alongside the other top-level sections of your template such as resources, metadata etc.

    Below is ConstraintDescription as an error when the database instance name doesn't meet the specified requirements when uploading the template.

    Note that the validation error states that the parameter failed to allow alphanumerics (ConstraintDescription: Allows alphanumerics)

  • AllowedPattern

    In our earlier discussion, we talked about Regular Expressions . The AllowedPattern attribute uses regular expressions to validate parameter values.

    If you want template users to follow strict patterns or rules that text strings must adhere to, then you will need regular expressions/regex in your AllowedPattern attribute. You will need to be understand how to create regular expressions first.

    There are certain scenarios where AllowedPattern would be commonly used:

    1. Validating IP addresses and subnet masks for your AWS VPC configurations

    2. Validating user inputs by enforcing required naming conventions for resources such as EC2 Instance names, s3 Bucket names etc.

Below is a template snippet with different parameters responsible for setting up an AWS VPC with both public and private subnets.

We start by defining the parameter logical name VPCCIDR which expects a string value representing the CIDR block for the entire VPC. Under AllowedPattern, we come up with a regular expression that validates the format required when indicating your VPC CIDR (likely matching four octets separated by periods and a subnet mask e.g. 10.0.0.0/16).

The same pattern is defined for the public and private subnets.

    Parameters:
      VPCCIDR:
        Type: String
        AllowedPattern: "(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})/(\\d{2})"
        ConstraintDescription: Must be a valid IP CIDR range of the form x.x.x.x/x.

      PublicSubnet1CIDR:
        Type: String
        AllowedPattern: "(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})/(\\d{2})"
        ConstraintDescription: Must be a valid IP subnet within the VPCCIDR and not in use by another resource.

      PublicSubnet2CIDR:
        Type: String
        AllowedPattern: "(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})/(\\d{2})"
        ConstraintDescription: Must be a valid IP CIDR range of the form x.x.x.x/x.

      PrivateSubnet1CIDR:
        Type: String
        AllowedPattern: "(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})/(\\d{2})"
        ConstraintDescription: Must be a valid IP CIDR range of the form x.x.x.x/x.

      PrivateSubnet2CIDR:
        Type: String
        AllowedPattern: "(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})/(\\d{2})"
        ConstraintDescription: Must be a valid IP CIDR range of the form x.x.x.x/x.
  • Default- The Default attribute in parameters serves as the default value/fallback value that is automatically displayed and assigned to the parameter if the template user fails to key in a different value during stack creation.

    Below is a template snippet of how the Default attribute is represented in parameters

    ```yaml Parameters: ParamDBInstanceClass: Default: db.t3.micro Description: DB Instance Class for the RDS Instance Type: String

ParamAllocatedStorage: Default: '30' Description: Storage for RDS Instance Type: Number MinValue: '20' MaxValue: '6144'

ParamStorageType: Default: gp2 Description: DB Storage type for the RDS Instance Type: String ```

Below is an image of the default values for the parameters above after uploading your template. If you wish to select other values, simply click on the other options on the dropdown or simply type your desired value.

Other parameter attributes include

  • Description

  • MinLength

  • MaxLength

  • MinValue

  • MaxValue

  • NoEcho

To understand more about these parameter attributes visit the Parameters documentation.