← Back to list

Hands-On with Fn::GetStackOutput: The New AWS CloudFormation Intrinsic Function for Cross-Account…

Introduction

Yoshiyuki Watanabe · 2026-05-29 14:26 · 23 claps · 10.3 min read
#aws #aws-cloudformation #infrastructure-as-code #devops #cloud-computing
Open on Medium ↗
Wiki topics: ☁️ · DevOps & Cloud

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.

[embed]Reference stack outputs across accounts and Regions with AWS CloudFormation and CDK - AWS Discover more about what's new at AWS with Reference stack outputs across accounts and Regions with AWS CloudFormation…aws.amazon.com

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::ImportValue uses 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 Export definitions 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.

Reference: https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/intrinsic-function-reference-getstackoutput.html#intrinsic-function-reference-getstackoutput-limitations

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

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