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.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).

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 CDKNew

Catenary Cloud

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