AWS Step Functions: List Definition Substitutions

Viewed 909

I have a step function defined in CloudFormation that launches an ECS task using arn:aws:states:::ecs:runTask.waitForTaskToken. This task takes a list of subnets as a parameter, and requires at least 1 subnet to be defined. Example:

# Step Function
MyECSTask:
  Type: Task
  Resource: arn:aws:states:::ecs:runTask.waitForTaskToken
  Parameters:
    ...    
    NetworkConfiguration:
      AwsvpcConfiguration:
        ...
        Subnets:
          - <subnet 1>
          - <subnet 2>

I have multiple subnets defined in a StringList SSM parameter, which I'm trying to pass through to the step function using Cloud Formation via the DefinitionSubstitutions attribute. However, I've been unable to pass the SSM StringList parameter as a list to the Step Function workflow. Passing the value as is directly into the Step Functions did not work: it either errored out, or passed it through as a single string value (it was a little while ago so I can't exactly remember the outcome).

Instead, the only solution that has worked for me was to split the StringList value within CloudFormation, and pass each subnet through to the Step Function as separate substitutions:

# Step Function
MyECSTask:
  Type: Task
  Resource: arn:aws:states:::ecs:runTask.waitForTaskToken
  Parameters:
    ...    
    NetworkConfiguration:
      AwsvpcConfiguration:
        ...
        Subnets:
          - ${Subnet1}
          - ${Subnet2}
          - ${Subnet3}
# Cloud Formation
Parameters:
  ListOfSubnets:
    Type: AWS::SSM::Parameter::Value<CommaDelimitedList>

Resources:
  MyStateMachine:
    Type: AWS::Serverless::StateMachine
    Properties:    
      DefinitionUri: step-functions.asl.yaml
      DefinitionSubstitutions:
        Subnet1: !Select ["0", !Ref ListOfSubnets]
        Subnet2: !Select ["1", !Ref ListOfSubnets]
        Subnet3: !Select ["2", !Ref ListOfSubnets]

The main issue with this approach is that it assumes 3 subnets, which will not be true for all regions in which we choose to deploy this workflow.

Is there any way in which I can pass ListOfSubnets directly into the step function as a DefinitionSubstitution? In other words, can a Step Function substitution be treated as a list instead of a string?

1 Answers

I have accomplished what you are trying to do by using the !Join function in the Cloud Formation template, to build a string from the List Parameter that is delimited by the three characters of double-quote comma double-quote (",").

Additionally, I created the Step function Definition file in JSON format.

In your example, your Step function definition would be modified to read like:

# Step Function
"MyECSTask":{
  "Type": "Task",
  "Resource": "arn:aws:states:::ecs:runTask.waitForTaskToken",
  "Parameters": {
    ...    
    "NetworkConfiguration":{
      "AwsvpcConfiguration":{
        ...
        "Subnets": [ "${Subnets}" ],

Then your Cloud Formation template would be modified like follows:

Parameters:
  ListOfSubnets:
    Type: AWS::SSM::Parameter::Value<List<AWS::EC2::Subnet::Id>>
Resources:
  MyStateMachine:
    Type: AWS::Serverless::StateMachine
    Properties:    
      DefinitionUri: step-functions.asl.json
      DefinitionSubstitutions:
        Subnets: !Join ['","', !Ref ListOfSubnets]
Related