Hands-On with Fn::GetStackOutput: The New AWS CloudFormation Intrinsic Function for Cross-Account…
Introduction
Hands-On with Fn::GetStackOutput: The New AWS CloudFormation Intrinsic Function for Cross-Account and Cross-Region Stack References

Introduction
On May 14, 2026, AWS CloudFormation introduced a new intrinsic function: Fn::GetStackOutput.
The existing Fn::ImportValue was limited to referencing stack outputs within the same account and region. In multi-account architectures, teams had to work around this by manually copying values between templates or coordinating parameter updates across teams — both of which introduce the risk of configuration drift.
Fn::GetStackOutput eliminates these limitations. In this article, we'll walk through the feature hands-on by actually deploying CloudFormation templates.
What we’ll cover:
- Deploy a producer stack (VPC)
- Reference stack outputs within the same account and region
- Reference stack outputs across regions
- Reference stack outputs across accounts
Prerequisites
- AWS CLI configured and ready to use
- IAM permissions to deploy CloudFormation stacks
- Two AWS accounts required for the cross-account portion
Hands-On Architecture
We’ll deploy stacks in the following configuration.
Account A (ap-northeast-1)
├── HandsOnProducerStack # Step 1: Create and output VPC
├── HandsOnConsumerSameRegion # Step 2: Same-region reference
└── HandsOnCrossAccountRole # Step 4: IAM role for cross-account access
Account A (us-east-1)
└── HandsOnConsumerCrossRegion # Step 3: Cross-region reference
Account B (ap-northeast-1)
└── HandsOnConsumerCrossAccount # Step 5: Cross-account reference
The template files used in this hands-on are:
├── 1-producer-stack.yaml
├── 2-consumer-same-region.yaml
├── 3-consumer-cross-region.yaml
├── 4-cross-account-role.yaml
└── 5-consumer-cross-account.yaml
Step 1: Deploy the Producer Stack
First, deploy HandsOnProducerStack — the stack that other stacks will reference. This stack creates a VPC and publishes its ID to the Outputs section.
1-producer-stack.yaml
AWSTemplateFormatVersion: 2010-09-09
Description: >
Producer Stack - Outputs VpcId for Fn::GetStackOutput hands-on.
Deploy this stack first in Account A / ap-northeast-1.
Resources:
VPC:
Type: AWS::EC2::VPC
Properties:
CidrBlock: 10.0.0.0/16
EnableDnsHostnames: true
EnableDnsSupport: true
Tags:
- Key: Name
Value: HandsOnVPC
Outputs:
VpcId:
Description: VPC ID
Value: !Ref VPC
Key point: Unlike Fn::ImportValue, no Export definition is required. Simply writing a value in Outputs makes it referenceable via Fn::GetStackOutput.
Deploy command:
aws cloudformation deploy \
--template-file 1-producer-stack.yaml \
--stack-name HandsOnProducerStack \
--region ap-northeast-1
After deploying, verify the Outputs:
aws cloudformation describe-stacks \
--stack-name HandsOnProducerStack \
--region ap-northeast-1 \
--query 'Stacks[0].Outputs'
Confirm that VpcId appears in the output.
Note: Resource IDs (such as VPC IDs) in the examples below have been masked.
Example output:
$ aws cloudformation deploy \
> --template-file 1-producer-stack.yaml \
> --stack-name HandsOnProducerStack \
> --region ap-northeast-1
Waiting for changeset to be created..
Waiting for stack create/update to complete
Successfully created/updated stack - HandsOnProducerStack
$
$ aws cloudformation describe-stacks \
> --stack-name HandsOnProducerStack \
> --region ap-northeast-1 \
> --query 'Stacks[0].Outputs'
[
{
"OutputKey": "VpcId",
"OutputValue": "vpc-0123456789abcdef0",
"Description": "VPC ID"
}
]
$
Step 2: Same-Account, Same-Region Reference
Using the VPC ID from HandsOnProducerStack deployed in Step 1, we'll create a Security Group.
For a same-account, same-region reference, you only need two parameters: StackName (the name of the stack to reference) and OutputName (the output key ID).
2-consumer-same-region.yaml
AWSTemplateFormatVersion: 2010-09-09
Description: >
Consumer Stack (Same Account, Same Region) - Creates a Security Group in the VPC
from HandsOnProducerStack using Fn::GetStackOutput.
Deploy this stack in the same account and region as HandsOnProducerStack.
Resources:
AppSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: Security group using Fn::GetStackOutput (same region)
VpcId:
Fn::GetStackOutput:
StackName: HandsOnProducerStack
OutputName: VpcId
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 443
ToPort: 443
CidrIp: 0.0.0.0/0
Outputs:
SecurityGroupId:
Description: Security Group ID
Value: !Ref AppSecurityGroup
Deploy command:
aws cloudformation deploy \
--template-file 2-consumer-same-region.yaml \
--stack-name HandsOnConsumerSameRegion \
--region ap-northeast-1
After deploying, verify that the VPC ID of the created Security Group matches the VPC ID from HandsOnProducerStack.
# Get SecurityGroupId from the Consumer stack Outputs
SG_ID=$(aws cloudformation describe-stacks \
--stack-name HandsOnConsumerSameRegion \
--region ap-northeast-1 \
--query 'Stacks[0].Outputs[?OutputKey==`SecurityGroupId`].OutputValue' \
--output text)
# Check the Security Group's VPC ID
aws ec2 describe-security-groups \
--group-ids $SG_ID \
--region ap-northeast-1 \
--query 'SecurityGroups[0].VpcId'
# Compare with the Producer stack's VpcId
aws cloudformation describe-stacks \
--stack-name HandsOnProducerStack \
--region ap-northeast-1 \
--query 'Stacks[0].Outputs[?OutputKey==`VpcId`].OutputValue' \
--output text
If both VPC IDs match, the step is complete.
Example output:
$ aws cloudformation deploy \
> --template-file 2-consumer-same-region.yaml \
> --stack-name HandsOnConsumerSameRegion \
> --region ap-northeast-1
Waiting for changeset to be created..
Waiting for stack create/update to complete
Successfully created/updated stack - HandsOnConsumerSameRegion
$
$ SG_ID=$(aws cloudformation describe-stacks \
> --stack-name HandsOnConsumerSameRegion \
> --region ap-northeast-1 \
> --query 'Stacks[0].Outputs[?OutputKey==`SecurityGroupId`].OutputValue' \
> --output text)
$
$ aws ec2 describe-security-groups \
> --group-ids $SG_ID \
> --region ap-northeast-1 \
> --query 'SecurityGroups[0].VpcId'
"vpc-0123456789abcdef0"
$
$ aws cloudformation describe-stacks \
> --stack-name HandsOnProducerStack \
> --region ap-northeast-1 \
> --query 'Stacks[0].Outputs[?OutputKey==`VpcId`].OutputValue' \
> --output text
vpc-0123456789abcdef0
$
Step 3: Cross-Region Reference
In multi-region architectures, there are cases where a stack in one region needs to reference outputs from a stack in another region.
For example, a secondary-region stack may need resource information from the primary region in a DR setup, or you may want to centralize resource IDs from multiple regions into SSM Parameter Store for global service discovery.
With Fn::GetStackOutput, you simply add the Region parameter. Here, we'll save the VpcId from HandsOnProducerStack in ap-northeast-1 (deployed in Step 1) into SSM Parameter Store in us-east-1.
Note: If you’re referencing between us-east-1 and an opt-in region (such as ap-southeast-3 or me-central-1), you may need to update token compatibility settings for the global STS endpoint. This hands-on uses ap-northeast-1 (a default-enabled region) with us-east-1, so this does not apply here. If you're using opt-in regions, refer to the AWS documentation.
3-consumer-cross-region.yaml
AWSTemplateFormatVersion: 2010-09-09
Description: >
Consumer Stack (Same Account, Cross-Region) - Creates an SSM Parameter storing
the VpcId from HandsOnProducerStack in a different region.
Example: Deploy this stack in us-east-1, referencing HandsOnProducerStack in ap-northeast-1.
Parameters:
ProducerRegion:
Type: String
Default: ap-northeast-1
Description: The region where HandsOnProducerStack is deployed
Resources:
CrossRegionVpcIdParam:
Type: AWS::SSM::Parameter
Properties:
Name: /handson/cross-region/vpc-id
Type: String
Description: VpcId from HandsOnProducerStack in another region
Value:
Fn::GetStackOutput:
StackName: HandsOnProducerStack
OutputName: VpcId
Region: !Ref ProducerRegion
Outputs:
VpcIdParamName:
Description: SSM Parameter name storing cross-region VpcId
Value: !Ref CrossRegionVpcIdParam
Tips: Fn::GetStackOutput supports the YAML short form !GetStackOutput, but it cannot be used when parameter values contain other short form functions like !Ref or !Sub. Since this template uses Region: !Ref ProducerRegion, we use the full function name Fn::GetStackOutput.
Deploy command:
aws cloudformation deploy \
--template-file 3-consumer-cross-region.yaml \
--stack-name HandsOnConsumerCrossRegion \
--region us-east-1 \
--parameter-overrides ProducerRegion=ap-northeast-1
Verify that the VPC ID from ap-northeast-1 is stored in the SSM Parameter:
aws ssm get-parameter \
--name /handson/cross-region/vpc-id \
--region us-east-1 \
--query 'Parameter.Value' \
--output text
If the returned value matches the VpcId output from HandsOnProducerStack in ap-northeast-1, the step is complete.
Example output:
$ aws cloudformation deploy \
> --template-file 3-consumer-cross-region.yaml \
> --stack-name HandsOnConsumerCrossRegion \
> --region us-east-1 \
> --parameter-overrides ProducerRegion=ap-northeast-1
Waiting for changeset to be created..
Waiting for stack create/update to complete
Successfully created/updated stack - HandsOnConsumerCrossRegion
$
$ aws ssm get-parameter \
> --name /handson/cross-region/vpc-id \
> --region us-east-1 \
> --query 'Parameter.Value' \
> --output text
vpc-0123456789abcdef0
$
Step 4: Set Up the IAM Role for Cross-Account Access
In Step 5, a stack in Account B will reference HandsOnProducerStack in Account A. To enable this, we need to create an IAM role in Account A in advance — one that Account B's CloudFormation execution role can use to call DescribeStacks.
The mechanism works as follows: when Account B’s CloudFormation processes the stack, it assumes this role and calls DescribeStacks against HandsOnProducerStack in Account A to retrieve the output value.
4-cross-account-role.yaml (deploy to Account A)
AWSTemplateFormatVersion: 2010-09-09
Description: >
Cross-Account IAM Role for Fn::GetStackOutput.
Deploy this stack in Account A (producer account).
This role allows Account B (consumer account) to call DescribeStacks on HandsOnProducerStack.
Parameters:
ConsumerAccountId:
Type: String
Description: AWS Account ID of the consumer account (Account B)
AllowedPattern: "[0-9]{12}"
Resources:
GetStackOutputRole:
Type: AWS::IAM::Role
Properties:
RoleName: HandsOnGetStackOutputRole
AssumeRolePolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Principal:
# Using :root for this hands-on. In production, specify the CloudFormation execution role ARN of the consuming stack.
# Reference: https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/intrinsic-function-reference-getstackoutput.html#intrinsic-function-reference-getstackoutput-iam
AWS: !Sub "arn:aws:iam::${ConsumerAccountId}:root"
Action: sts:AssumeRole
Policies:
- PolicyName: DescribeHandsOnProducerStack
PolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Action:
- cloudformation:DescribeStacks
Resource: !Sub "arn:aws:cloudformation:${AWS::Region}:${AWS::AccountId}:stack/HandsOnProducerStack/*"
Outputs:
RoleArn:
Description: ARN of the IAM role to specify in RoleArn parameter of Fn::GetStackOutput
Value: !GetAtt GetStackOutputRole.Arn
Point 1: By specifying :root as the Principal, any principal within Account B can assume this role. In production, refer to the AWS documentation and restrict the Principal to the specific CloudFormation execution role ARN.
Point 2: The Resource is scoped to a specific stack ARN. Using * would allow access to all stacks, so we follow the principle of least privilege and restrict it to only the stack being referenced.
Deploy command (run with Account A credentials):
aws cloudformation deploy \
--template-file 4-cross-account-role.yaml \
--stack-name HandsOnCrossAccountRole \
--region ap-northeast-1 \
--capabilities CAPABILITY_NAMED_IAM \
--parameter-overrides ConsumerAccountId=<Account B ID>
After deploying, note down the RoleArn:
aws cloudformation describe-stacks \
--stack-name HandsOnCrossAccountRole \
--region ap-northeast-1 \
--query 'Stacks[0].Outputs[?OutputKey==`RoleArn`].OutputValue' \
--output text
Example output:
$ aws cloudformation deploy \
> --template-file 4-cross-account-role.yaml \
> --stack-name HandsOnCrossAccountRole \
> --region ap-northeast-1 \
> --capabilities CAPABILITY_NAMED_IAM \
> --parameter-overrides ConsumerAccountId=<Account B ID>
Waiting for changeset to be created..
Waiting for stack create/update to complete
Successfully created/updated stack - HandsOnCrossAccountRole
$
$ aws cloudformation describe-stacks \
> --stack-name HandsOnCrossAccountRole \
> --region ap-northeast-1 \
> --query 'Stacks[0].Outputs[?OutputKey==`RoleArn`].OutputValue' \
> --output text
arn:aws:iam::<Account A ID>:role/HandsOnGetStackOutputRole
$
Step 5: Cross-Account Reference
In multi-account architectures, there are cases where you need to reference stack outputs from one account in another account.
Let’s have Account B’s CloudFormation retrieve the VpcId from HandsOnProducerStack in Account A and store it in SSM Parameter Store.
We add RoleArn to the Step 3 configuration (StackName, OutputName, Region), specifying the ARN of the IAM role created in Account A in Step 4.
5-consumer-cross-account.yaml (deploy to Account B)
AWSTemplateFormatVersion: 2010-09-09
Description: >
Consumer Stack (Cross-Account) - Creates an SSM Parameter storing
VpcId from HandsOnProducerStack in Account A.
Deploy this stack in Account B.
Parameters:
ProducerAccountId:
Type: String
Description: AWS Account ID of Account A (producer account)
AllowedPattern: "[0-9]{12}"
ProducerRegion:
Type: String
Default: ap-northeast-1
Description: Region where HandsOnProducerStack is deployed in Account A
Resources:
CrossAccountVpcIdParam:
Type: AWS::SSM::Parameter
Properties:
Name: /handson/cross-account/vpc-id
Type: String
Description: VpcId from HandsOnProducerStack in Account A
Value:
Fn::GetStackOutput:
StackName: HandsOnProducerStack
OutputName: VpcId
Region: !Ref ProducerRegion
RoleArn: !Sub "arn:aws:iam::${ProducerAccountId}:role/HandsOnGetStackOutputRole"
Outputs:
VpcIdParamName:
Description: SSM Parameter name storing cross-account VpcId
Value: !Ref CrossAccountVpcIdParam
Deploy command (run with Account B credentials):
aws cloudformation deploy \
--template-file 5-consumer-cross-account.yaml \
--stack-name HandsOnConsumerCrossAccount \
--region ap-northeast-1 \
--parameter-overrides ProducerAccountId=<Account A ID>
Verify that Account A’s VPC ID is stored in the SSM Parameter:
aws ssm get-parameter \
--name /handson/cross-account/vpc-id \
--region ap-northeast-1 \
--query 'Parameter.Value' \
--output text
If the returned value matches the VpcId output from HandsOnProducerStack in Account A, the step is complete.
Example output:
$ aws cloudformation deploy \
> --template-file 5-consumer-cross-account.yaml \
> --stack-name HandsOnConsumerCrossAccount \
> --region ap-northeast-1 \
> --parameter-overrides ProducerAccountId=<Account A ID>
Waiting for changeset to be created..
Waiting for stack create/update to complete
Successfully created/updated stack - HandsOnConsumerCrossAccount
$
$ aws ssm get-parameter \
> --name /handson/cross-account/vpc-id \
> --region ap-northeast-1 \
> --query 'Parameter.Value' \
> --output text
vpc-0123456789abcdef0
$
Common Errors and How to Fix Them
IAM role cannot be assumed
This occurs during cross-account references. Verify that ConsumerAccountId in the trust policy of 4-cross-account-role.yaml is set to the correct Account B ID.
The following is an example output from intentionally setting an incorrect account ID in ConsumerAccountId to reproduce the error.
Example output:
$ aws cloudformation deploy \
> --template-file 5-consumer-cross-account.yaml \
> --stack-name HandsOnConsumerCrossAccount \
> --region ap-northeast-1 \
> --parameter-overrides ProducerAccountId=<Account A ID>
Waiting for changeset to be created..
Waiting for stack create/update to complete
aws: [ERROR]: Failed to create/update the stack. Run the following command
to fetch the list of events leading up to the failure
aws cloudformation describe-stack-events --stack-name HandsOnConsumerCrossAccount
$
$ aws cloudformation describe-stack-events --stack-name HandsOnConsumerCrossAccount \
> --region ap-northeast-1
{
"StackEvents": [
...
{
"StackId": "arn:aws:cloudformation:ap-northeast-1:<Account B ID>:stack/HandsOnConsumerCrossAccount/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"EventId": "CrossAccountVpcIdParam-CREATE_FAILED-2026-05-29T11:27:11.913Z",
"StackName": "HandsOnConsumerCrossAccount",
"OperationId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"LogicalResourceId": "CrossAccountVpcIdParam",
"PhysicalResourceId": "",
"ResourceType": "AWS::SSM::Parameter",
"Timestamp": "2026-05-29T11:27:11.913000+00:00",
"ResourceStatus": "CREATE_FAILED",
"ResourceStatusReason": "User: arn:aws:sts::<Account B ID>:assumed-role/AWSReservedSSO_AdministratorAccess_xxxxxxxxxxxxxxxx/xxxxxx is not authorized to perform: sts:AssumeRole on resource: arn:aws:iam::<Account A ID>:role/HandsOnGetStackOutputRole (Service: AWSSecurityTokenService; Status Code: 403; Error Code: AccessDenied; Request ID: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx; Proxy: null)",
"ClientRequestToken": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
},
...
]
}
$
When to Use Fn::ImportValue vs. Fn::GetStackOutput
When to Use Fn::ImportValue
- You’re referencing within the same account and region and want to prevent accidental deletion of the referenced stack
- You need referential integrity guaranteed (
Fn::ImportValueuses a strong reference that blocks deletion of the exporting stack)
When to Use Fn::GetStackOutput
- You need cross-account or cross-region references
- You want to avoid managing explicit
Exportdefinitions in the referenced stack - You want to simplify CDK multi-account and multi-region configurations (eliminates the need for custom resources and SSM parameters)
Key difference: Fn::GetStackOutput creates a weak reference. If the referenced stack is deleted, the consuming stack will not immediately fail on create or update. However, the next stack update that re-resolves the reference will fail. Use stack policies, deletion protection, or IAM policies to safeguard referenced stacks.
Known Limitations
At the time of writing, a few usage patterns are not yet supported and will trigger an InternalFailure error. AWS has indicated these will be addressed in a future release.

Conclusion
With Fn::GetStackOutput, passing values between stacks in multi-account and multi-region CloudFormation architectures has become significantly simpler.
As confirmed in this hands-on, same-region references require only StackName and OutputName. Cross-region adds Region. Cross-account adds RoleArn. No Export definition is needed on the producer side.
If your team operates CloudFormation or CDK in a multi-account setup, this is an update well worth trying right away.
References
- Reference stack outputs across accounts and Regions with AWS CloudFormation and CDK
- Fn::GetStackOutput
Thank you for reading this far!
메타데이터
- post_id
- 46db1a13b3b8
- slug
- hands-on-with-fn-getstackoutput-the-new-aws-cloudformation-intrinsic-function-for-cross-account-46db1a13b3b8
- url
- https://medium.com/@yoshiyuki.watanabe/hands-on-with-fn-getstackoutput-the-new-aws-cloudformation-intrinsic-function-for-cross-account-46db1a13b3b8
- canonical_url
- https://medium.com/@yoshiyuki.watanabe/hands-on-with-fn-getstackoutput-the-new-aws-cloudformation-intrinsic-function-for-cross-account-46db1a13b3b8
- author_url
- https://medium.com/@yoshiyuki.watanabe
- status
- ok
- fetched_at
- 2026-06-09 15:37:30