Intrinsic functions & pseudo-parameters

Ref, GetAtt, Sub, and friends.

Intermediate12 min · lesson 6 of 12

Intrinsic functions are how a template computes values at deploy time instead of hard-coding them. The everyday ones: !Ref returns a resource’s identifier (or a parameter’s value), !GetAtt reads a specific attribute of a resource (an ARN, a DNS name), !Sub interpolates variables into a string, and !Join concatenates. These are what wire resources together dynamically — a security group referencing a VPC, a policy embedding a bucket ARN.

template.yaml
Resources:
Bucket:
Type: AWS::S3::Bucket
BucketPolicy:
Type: AWS::S3::BucketPolicy
Properties:
Bucket: !Ref Bucket
PolicyDocument:
Statement:
- Effect: Allow
Principal: { AWS: !Sub "arn:aws:iam::${AWS::AccountId}:root" }
Action: s3:GetObject
Resource: !Sub "${Bucket.Arn}/*" # GetAtt via !Sub

Pseudo-parameters and conditions

AWS provides pseudo-parameters — values CloudFormation fills in automatically: AWS::Region, AWS::AccountId, AWS::StackName, AWS::Partition. They let a template adapt to wherever it deploys without hard-coding an account or region. Combined with Conditions (built from !If, !Equals, !And) you get templates that create resources only in certain environments — a prod-only WAF, a dev-only bastion — from one file.

template.yaml
Conditions:
IsProd: !Equals [!Ref Environment, prod]
Resources:
Waf:
Type: AWS::WAFv2::WebACL
Condition: IsProd # only created when Environment=prod
Properties:
Name: !Sub "${AWS::StackName}-waf"
Scope: REGIONAL
Ref vs GetAtt return different things
A frequent bug: !Ref on a resource returns its default identifier (for a bucket, the name; for an instance, the instance ID), while !GetAtt returns a named attribute (Bucket.Arn, Instance.PrivateIp). If a property “won’t take” your reference, you probably need GetAtt for a specific attribute rather than Ref’s default value — check the resource’s documented return values.