Package: cdk-remote-stack
cdk-remote-stackGet outputs and AWS SSM parameters from cross-region AWS CloudFormation stacksInstallUse the npm dist tag to opt in CDKv1 or CDKv2://forCDKv2
npminstallcdk-remote-stack
or
npminstallcdk-remote-stack@latest

//forCDKv1
npminstallcdk-remote-stack@cdkv1WhySetting up cross-regional cross-stack references requires using multiple constructs from the AWS CDK construct library and is not straightforward.cdk-remote-stackaims to simplify the cross-regional cross-stack references to help you easily build cross-regional multi-stack AWS CDK applications.This construct library provides two main constructs:RemoteOutputs- cross regional stack outputs reference.RemoteParameters- cross regional/account SSM parameters reference.RemoteOutputsRemoteOutputsis ideal for one stack referencing the outputs from another across different AWS regions.Let's say we have two cross-regional stacks in the same AWS CDK application:stackJP- stack in Japan (JP) to create a SNS topicstackUS- stack in United States (US) to get the outputs fromstackJPand print out the SNSTopicNamefromstackJPoutputs.import{RemoteOutputs}from'cdk-remote-stack';import*ascdkfrom'aws-cdk-lib';constapp=newcdk.App();constenvJP={region:'ap-northeast-1',account:process.env.CDK_DEFAULT_ACCOUNT,};constenvUS={region:'us-west-2',account:process.env.CDK_DEFAULT_ACCOUNT,};//firststackinJPconststackJP=newcdk.Stack(app,'demo-stack-jp',{env:envJP})newcdk.CfnOutput(stackJP,'TopicName',{value:'foo'})//secondstackinUSconststackUS=newcdk.Stack(app,'demo-stack-us',{env:envUS})//ensurethedependencystackUS.addDependency(stackJP)//getthestackJPstackoutputsfromstackUSconstoutputs=newRemoteOutputs(stackUS,'Outputs',{stack:stackJP})constremoteOutputValue=outputs.get('TopicName')//thevalueshouldbeexactlythesamewiththeoutputvalueof`TopicName`newcdk.CfnOutput(stackUS,'RemoteTopicName',{value:remoteOutputValue})At this moment,RemoteOutputsonly supports cross-regional reference in a single AWS account.Always get the latest stack outputBy default, theRemoteOutputsconstruct will always try to get the latest output from the source stack. You may opt out by settingalwaysUpdatetofalseto turn this feature off.For example:constoutputs=newRemoteOutputs(stackUS,'Outputs',{stack:stackJP,alwaysUpdate:false,})RemoteParametersAWS Systems Manager (AWS SSM) Parameter Storeis great to store and persist parameters and allow stacks from other regons/accounts to reference. Let's dive into the two major scenarios below:Stacks from single account and different regionsIn this sample, we create two stacks from JP (ap-northeast-1) and US (us-west-2). The JP stack will produce and update parameters in its parameter store, while the US stack will consume the parameters across differnt regions with theRemoteParametersconstruct.constenvJP={region:'ap-northeast-1',account:'111111111111'};constenvUS={region:'us-west-2',account:'111111111111'};//firststackinJPconstproducerStackName='demo-stack-jp';conststackJP=newcdk.Stack(app,producerStackName,{env:envJP});constparameterPath=`/${envJP.account}/${envJP.region}/${producerStackName}`newssm.StringParameter(stackJP,'foo1',{parameterName:`${parameterPath}/foo1`,stringValue:'bar1',});newssm.StringParameter(stackJP,'foo2',{parameterName:`${parameterPath}/foo2`,stringValue:'bar2',});newssm.StringParameter(stackJP,'foo3',{parameterName:`${parameterPath}/foo3`,stringValue:'bar3',});//secondstackinUSconststackUS=newcdk.Stack(app,'demo-stack-us',{env:envUS});//ensurethedependencystackUS.addDependency(stackJP);//getremoteparametersbypathfromAWSSSMparameterstoreconstparameters=newRemoteParameters(stackUS,'Parameters',{path:parameterPath,region:stackJP.region,})constfoo1=parameters.get(`${parameterPath}/foo1`);constfoo2=parameters.get(`${parameterPath}/foo2`);constfoo3=parameters.get(`${parameterPath}/foo3`);newcdk.CfnOutput(stackUS,'foo1Output',{value:foo1});newcdk.CfnOutput(stackUS,'foo2Output',{value:foo2});newcdk.CfnOutput(stackUS,'foo3Output',{value:foo3});Stacks from differnt accounts and different regionsSimilar to the use case above, but now we deploy stacks in separate accounts and regions.  We will need to pass an AWS Identity and Access Management (AWS IAM)roleto theRemoteParametersconstruct to get all the parameters from the remote environment.constenvJP={region:'ap-northeast-1',account:'111111111111'};constenvUS={region:'us-west-2',account:'222222222222'};//firststackinJPconstproducerStackName='demo-stack-jp';conststackJP=newcdk.Stack(app,producerStackName,{env:envJP});constparameterPath=`/${envJP.account}/${envJP.region}/${producerStackName}`newssm.StringParameter(stackJP,'foo1',{parameterName:`${parameterPath}/foo1`,stringValue:'bar1',});newssm.StringParameter(stackJP,'foo2',{parameterName:`${parameterPath}/foo2`,stringValue:'bar2',});newssm.StringParameter(stackJP,'foo3',{parameterName:`${parameterPath}/foo3`,stringValue:'bar3',});//allowUSaccounttoassumethisreadonlyroletogetparametersconstcdkReadOnlyRole=newiam.Role(stackJP,'readOnlyRole',{assumedBy:newiam.AccountPrincipal(envUS.account),roleName:PhysicalName.GENERATE_IF_NEEDED,managedPolicies:[iam.ManagedPolicy.fromAwsManagedPolicyName('AmazonSSMReadOnlyAccess')],})//secondstackinUSconststackUS=newcdk.Stack(app,'demo-stack-us',{env:envUS});//ensurethedependencystackUS.addDependency(stackJP);//getremoteparametersbypathfromAWSSSMparameterstoreconstparameters=newRemoteParameters(stackUS,'Parameters',{path:parameterPath,region:stackJP.region,//assumethisroleforcross-accountparametersrole:iam.Role.fromRoleArn(stackUS,'readOnlyRole',cdkReadOnlyRole.roleArn),})constfoo1=parameters.get(`${parameterPath}/foo1`);constfoo2=parameters.get(`${parameterPath}/foo2`);constfoo3=parameters.get(`${parameterPath}/foo3`);newcdk.CfnOutput(stackUS,'foo1Output',{value:foo1});newcdk.CfnOutput(stackUS,'foo2Output',{value:foo2});newcdk.CfnOutput(stackUS,'foo3Output',{value:foo3});Dedicated account for a centralized parameter storeThe parameters are stored in a centralized account/region and previously provisioned as a source-of-truth configuration store. All other stacks from different accounts/regions are consuming the parameters from the central configuration store.This scenario is pretty much like #2. The difference is that there's a dedicated account for centralized configuration store being shared with all other accounts.You will need createRemoteParametersfor all the consuming stacks like://forStackUSnewRemoteParameters(stackUS,'Parameters',{path:parameterPath,region:'eu-central-1'//assumethisroleforcross-accountparametersrole:iam.Role.fromRoleArn(stackUS,'readOnlyRole',sharedReadOnlyRoleArn),})//forStackJPnewRemoteParameters(stackJP,'Parameters',{path:parameterPath,region:'eu-central-1'//assumethisroleforcross-accountparametersrole:iam.Role.fromRoleArn(stackJP,'readOnlyRole',sharedReadOnlyRoleArn),})Tools for multi-account deploymentYou will need to install and bootstrap your target accounts with AWS CDK 1.108.0 or later, so you can deploy stacks from different accounts. Itadds supportfor cross-account lookups. Alternatively, installcdk-assume-role-credential-plugin. Read thisblog postto setup this plugin.LimitationsAt this moment, theRemoteParametersconstruct only supports theStringdata type from parameter store.Maximum number of parameters is100. Will make it configurable in the future if required.ContributingSeeCONTRIBUTINGfor more information.LicenseThis code is licensed under the Apache License 2.0. See theLICENSEfile.