DEV Community

Yan Cui
Yan Cui

Posted on • Originally published at theburningmonk.com on

2 2

CloudFormation protip: use !Sub instead of !Join

CloudFormation supports a number of intrinsic functions and Fn::Join (or !Join) is often used to construct parameterised names and paths.

The Serverless framework, for instance, uses it extensively. A quick look in a CloudFormation it generates I can see Fn::Join used for:

  • IAM policy names
  • IAM role names
  • IAM principals
  • API Gateway URIs
  • Resource ARNs

and many more.

But it’s not just the frameworks that are using Fn::Join heavily. They also show up in our own code all the time as well. For example, to construct the ARN for a resource, or the URI for an API Gateway endpoint.

I find these very hard to comprehend, and my protip for you today is to use Fn::Sub (or the !Sub shorthand) instead.

Many folks would use Fn::Sub when they need to reference pseudo parameters such as AWS::Region and AWS::AccountId, for example:

!Sub 'arn:aws:ec2:${AWS::Region}:${AWS::AccountId}:vpc/${vpc}'
Enter fullscreen mode Exit fullscreen mode

But Fn::Sub also lets you provide your own parameters. For example:

!Sub
 - 'arn:aws:s3:::${Bucket}/\*'
 - { Bucket: Ref MyBucket }
Enter fullscreen mode Exit fullscreen mode

The advantage over Fn::Join is that you can see the pattern of the interpolated string. Whereas with Fn::Join you’ll have to construct the pattern in your mind, which requires far more cognitive energy.

!Join
 - ''
 - - 'arn:aws:s3:::'
   - !Ref MyBucket
   - '/*'
Enter fullscreen mode Exit fullscreen mode

Here are a few side-by-side comparisons to drive home the message.

Example 1: IAM role name

RoleName: # hello-world-dev-{region}-lambdaRole
 !Join
   - '-'
   - - 'hello-world'
     - 'dev'
     - !Ref 'AWS::Region'
     - 'lambdaRole'
Enter fullscreen mode Exit fullscreen mode

with Fn::Sub:

PolicyName: !Sub 'hello-world-dev-${AWS::Region}-lambdaRole
Enter fullscreen mode Exit fullscreen mode

Example 2: API Gateway integration URI

Uri: # arn:{partition}:apigateway:{region}:.../{lambda}/invocations
  !Join
    - ''
    - - 'arn:'
      - Ref: AWS::Partition
      - ':apigateway:'
      - Ref: AWS::Region
      - ':lambda:path/2015-03-31/functions/'
      - !GetAtt 'HelloLambdaFunction.Arn'
      - '/invocations'
Enter fullscreen mode Exit fullscreen mode

with Fn::Sub:

Uri:
  !Sub
    - 'arn:${AWS::Partition}:apigateway:${AWS::Region}:lambda:path/2015/03/31/functions/${Function}/invocations'
    - { Function: !GetAtt 'HelloLambdaFunction.Arn' }
Enter fullscreen mode Exit fullscreen mode

Example 3: Lambda permission for API Gateway

SourceArn: # arn:{partition}:execute-api:{region}:.../*/*
  !Join:
    - ''
    - - 'arn:'
      - Ref: AWS::Partition
      - ':execute-api:'
      - Ref: AWS::Region
      - ':'
      - Ref: AWS::AccountId
      - ':'
      - Ref: ApiGatewayRestApi
      - '/*/*'
Enter fullscreen mode Exit fullscreen mode

with Fn::Sub:

SourceArn:
  !Sub
    - 'arn:${AWS::Partition}:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/*'
    - { RestApi: Ref: ApiGatewayRestApi }
Enter fullscreen mode Exit fullscreen mode

Suffice to say that the Fn::Sub version is easier to understand in every case! Now that you have seen what Fn::Sub can do, I hope you will prefer it to Fn::Join going forward.

If you’re using the Serverless framework, keep in mind that Fn::Sub is not natively supported. This is because the Serverless framework also uses the ${} syntax to support its own variables system. However, as is often the case with the Serverless framework, you can work around this issue with a plugin. Check out the serverless-cloudformation-sub-variables plugin which lets you use Fn::Sub in the serverless.yml. You just need to use #{VariableName} instead of ${VariableName}.

Finally, if you’re using the Serverless framework and need more expressive power than the intrinsic functions can offer, then check out this plugin. It lets you use a number of “extrinsic” functions such as Fn::Substring or Fn::StartsWith anywhere in your serverless.yml.

The post CloudFormation protip: use !Sub instead of !Join appeared first on theburningmonk.com.

Qodo Takeover

Introducing Qodo Gen 1.0: Transform Your Workflow with Agentic AI

Rather than just generating snippets, our agents understand your entire project context, can make decisions, use tools, and carry out tasks autonomously.

Read full post →

Top comments (0)

Sentry image

See why 4M developers consider Sentry, “not bad.”

Fixing code doesn’t have to be the worst part of your day. Learn how Sentry can help.

Learn more

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay