When a resource property in a CloudFormation template, such as the SubjectAlternativeNames property of a an AWS::CertificateManager::Certificate, takes a list of strings, you can use a template parameter with the CommaDelimitedList type to pass the list of values in. CloudFormation will expand the parameter into an array when it is passed to the property with Ref.

Most properties that expect a list will reject empty an CommaDelimitedList parameter (i.e., if the parameter is passed to the property, it must include one or more elements). So simply defining, e.g., SubjectAlternativeNames: !Ref CertificateSubjectAlternativeNames wouldn’t work when the parameter is empty. For these optional parameters, the property must conditionally get passed !Ref AWS::NoValue when the parameter is excluded, so that the property is ignored entirely by CloudFormation.

Within a template condition, there’s no direct way to test the presence or size of a CommaDelimitedList parameter. In order to create a condition that can be used to properly switch between the list and AWS::NoValue, you must first call Fn::Join on the list. You can call Join on a CommaDelimitedList parameter even if it’s blank. Joining an empty CommaDelimitedList will result in an empty string, which is something that the condition can test for with Fn::Equals.

AWSTemplateFormatVersion: "2010-09-09"

Parameters:
  # This is a `CommaDelimitedList` parameter that should be optional.
  CertificateSubjectAlternativeNames:
    Type: CommaDelimitedList
    Description: >-
      A comma-delimited list of alternative domain names to add to the
      certificate (e.g., "www.example.com,beta.example.com,app.example.com")

Conditions:
  # In order to check if any values were included in the template parameter,
  # the parameter is joined. When no values were included, the join operation
  # will result in an empty string. Using the `Fn::Not` condition function
  # along with `Fn::Equals` creates a condition that is FALSE when the
  # parameter is left blank, and TRUE when it contains at least one item.
  HasCertificateSubjectAlternativeNames: !Not [!Equals [!Join ['', !Ref CertificateSubjectAlternativeNames], '']]

Resources:
  Certificate:
    Type: AWS::CertificateManager::Certificate
    Properties:
      DomainName: !Ref CertificateDomainName
      # The `SubjectAlternativeNames` property expects a list of strings. If
      # any values have been added to the template parameter, it should be
      # passed to the property. If the template parameter is not defined, the
      # `AWS::NoValue` pseudo parameter needs to be passed in instead, so that
      # the property doesn't end up with an empty list.
      #
      # Note: When using the inline YAML array syntax, AWS::NoValue must be
      # quoted, or CloudFormation will fail to parse the template.
      SubjectAlternativeNames: !If [HasCertificateSubjectAlternativeNames, !Ref CertificateSubjectAlternativeNames, !Ref 'AWS::NoValue']