Home
Published on

Science question about Cloudformation

Author
    Roman Naumenko
    Name
    Roman Naumenko

Today is Nemo's first day at the DevOps school! The day starts with a stunning trip across production AWS accounts, lovely CI/CD pipelines, and other DevOps gems.

Finally, they are ready for the exciting trip to the drop-off - also known as the on-prem trench.

The teacher asks how to implement a conditional parameter for the Cloudformation template that manages SSL certs for the critical application.

Yes, Nemo, we know!

That is not a fun question. Usually, developers end up implementing something in YAML the half-Turing way. Check template below, it is not easy to grasp the logic and conditions in YAML.

CloudFormation has special way to set properties with non-empty value requirements from a parameter.

cloudformation.yaml
AWSTemplateFormatVersion: "2010-09-09"

Parameters:
  # This is an optional `CommaDelimitedList` parameter
  CertificateSANs:
    Type: CommaDelimitedList
    Description: >-
      A list of alternative domain names 
      for a certificate (e.g., "www.example.com,test.example.com")

Conditions:
  # If list is empty, the join produce an empty string.
  # `Fn::Not` function with `Fn::Equals` one mae a condition
  # It is FALSE when CertificateSANs is empty
  # TRUE when it contains at least one item.
  HasCertificateSANs: !Not [!Equals [!Join ['', !Ref CertificateSANs], '']]

Resources:
  Certificate:
    Type: AWS::CertificateManager::Certificate
    Properties:
      DomainName: !Ref DomainName
      # The `SubjectAlternativeNames` property expects 
      # a list of strings or pseudo parameter 'AWS::NoValue'.
      # If parameter is not defined, the Fn::If will pass `AWS::NoValue`
      # This way the SubjectAlternativeNames property set correctly.
      #
      # Note quoted AWS::NoValue. otherwise CloudFormation fails 
      # to parse the template with inline YAML array syntax
      SubjectAlternativeNames: 
        !If [HasCertificateSANs, !Ref CertificateSANs, !Ref 'AWS::NoValue']

Ok, Nemo! Don't hurt yourself and welcome aboard of AWS CDK - where the whole class of problem like this simple does not exist.

Here is CDK app that creates same resource (source code is available in GitHub).

CDK constructs can handle non-empty parameters without hassle.

main.ts
import { App, Stack, StackProps } from 'aws-cdk-lib';
import { CertificateValidation, Certificate } from 'aws-cdk-lib/aws-certificatemanager';
import { HostedZone } from 'aws-cdk-lib/aws-route53';
import { Construct } from 'constructs';


export class CertValidation extends Stack {
  constructor(scope: Construct, id: string, props: StackProps = {}) {
    super(scope, id, props);

    const myHostedZone = new HostedZone(this, 'HostedZone', {
      zoneName: 'thesite.com',
    });

    new Certificate(this, 'Certificate', {
      domainName: 'dev.thesite.com',
      subjectAlternativeNames: [],
      validation: CertificateValidation.fromDns(myHostedZone),
    });
  }
}

const app = new App();

new CertValidation(app, 'cetificate-validation');

app.synth();

`subjectAlternativeNames: []` can be an empty array - no problem. The Certificate construct will handle it.

Conclusion: if you're a small Dev fish, the CDK will increase your productivity (along with curiosity). It makes writing Cloudformation a breeze with a familiar programming language.

The real adventure begins when the CDK development pattern is applied to a Cloud coral reef with a massive ecosystem of templates, applications, Dev- and other types of fishes. There might be even some security sharks coming to a party!

Next Post

← Back to the blog

Services

Overview
AWS CDK CourseNew

Catenary Cloud

© 2021 Catenary Cloud LLC. Made with ❤️ in Philadelphia