AWS Cloudformation with Optional Resources
I had a situation where I had to bypass creation of some resources in CloudFormation. Either the resources already exist, or I just don’t want to create things depending on conditions.
To achieve this it turns out that CloudFormation actually has a nice facility, although it is a bit awkward.
In this particular case, I have a stack that creates a CloudFront distribution for a wildcard domain. It creates an SSL certificate using ACM (Amazon Certificate Manager). I discovered that in production there is an existing certificate that will be used. That would mean that either the creation would fail, or we’d end up with duplicate resources.
So in my stack, I added a parameter for the ARN of an existing certificate which looks like:
ACMARN: Type: String Default: "" Description: Enter the ARN of an existing certificate in ACM. If this is left empty, we will create a new cert
If nothing is entered in that parameter, the value will be that empty string. This lets me set up a condition statement which I can use later in the stack.
Conditions: CreateCertificate: !Equals [!Ref ACMARN, ""]
The above condition will be true if nothing is entered in the ACMARN parameter. I named it CreateCertificate to make it descriptive to the action that this will have. So if there is a value in ACMARN, then CreateCertificate will be false.
With that I update my certificate creation in the Resources section to be optional.
## Generates the certificate for our zone ... ## NOTE: this zone must exist, and the DNS validation must already be there WildCardCertificate: Type: "AWS::CertificateManager::Certificate" # Only create if we didn't get an ARN passed in as a parameter Condition: CreateCertificate Properties: DomainName: !Sub "*.${WildCardZone}" DomainValidationOptions: - DomainName: !Sub "*.${WildCardZone}" ValidationDomain: !Sub "${WildCardZone}"
The “Condition” will only create the certificate if the ARN was not set.
Finally I put a condition in the distribution creation using and Fn::If which will use the certificate WildCardCertificate. The Fn::If will use the ACMARN parameter instead if it is not the empty string. If I pass in an ARN value for ACMARN, it will use that ARN instead of creating a new one.
## The certificate to use when viewers use HTTPS to request objects. ViewerCertificate: AcmCertificateArn: Fn::If: - CreateCertificate - !Ref WildCardCertificate - !Ref ACMARN