cdk-remote-stack
Get outputs from cross-regional AWS CDK stacks
Why
AWS CDK cross-regional cross-stack reference is not easy with the native AWS CDK construct library.
cdk-remote-stack aims to simplify the cross-regional cross-stack reference to help you easily build cross-regional multi-stack AWS CDK apps.
This construct library provides two major constructs:
- RemoteOutputs - cross regional stack outputs reference.
- RemoteParameters - cross regional/account SSM parameters reference.
RemoteOutputs
RemoteOutputs is ideal for one stack referencing the outputs from another across different AWS regions.
Let's say we have two cross-regional CDK stacks in the same cdk app:
- stackJP - cdk stack in
JPto create a SNS topic - stackUS - cdk stack in
USto get the Outputs fromstackJPand print out the SNSTopicNamefromstackJPOutputs.
# Example automatically generated without compilation. See https://github.com/aws/jsii/issues/826
from cdk_remote_stack import RemoteOutputs
import aws_cdk.core as cdk
app = cdk.App()
env_jP = {
"region": "ap-northeast-1",
"account": process.env.CDK_DEFAULT_ACCOUNT
}
env_uS = {
"region": "us-west-2",
"account": process.env.CDK_DEFAULT_ACCOUNT
}
# first stack in JP
stack_jP = cdk.Stack(app, "demo-stack-jp", env=env_jP)
cdk.CfnOutput(stack_jP, "TopicName", value="foo")
# second stack in US
stack_uS = cdk.Stack(app, "demo-stack-us", env=env_uS)
# ensure the dependency
stack_uS.add_dependency(stack_jP)
# get the stackJP stack outputs from stackUS
outputs = RemoteOutputs(stack_uS, "Outputs", stack=stack_jP)
remote_output_value = outputs.get("TopicName")
# the value should be exactly the same with the output value of `TopicName`
cdk.CfnOutput(stack_uS, "RemoteTopicName", value=remote_output_value)
At this moment, RemoteOutputs only supports cross-regional reference in a single AWS account.
always get the latest stack output
By default, the RemoteOutputs construct will always try to get the latest output from the source stack. You may opt out by setting alwaysUpdate to false to turn this feature off.
For example:
# Example automatically generated without compilation. See https://github.com/aws/jsii/issues/826
outputs = RemoteOutputs(stack_uS, "Outputs",
stack=stack_jP,
always_update=False
)
RemoteParameters
AWS SSM Parameter Store is great to store and persist parameters and allow stacks from other regons/accounts to reference. Let's dive into the two major scenarios below:
#1 - Stacks from single account and different regions
In 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 the RemoteParameters construct.
# Example automatically generated without compilation. See https://github.com/aws/jsii/issues/826
env_jP = {"region": "ap-northeast-1", "account": "111111111111"}
env_uS = {"region": "us-west-2", "account": "111111111111"}
# first stack in JP
producer_stack_name = "demo-stack-jp"
stack_jP = cdk.Stack(app, producer_stack_name, env=env_jP)
parameter_path = f"/{envJP.account}/{envJP.region}/{producerStackName}"
ssm.StringParameter(stack_jP, "foo1",
parameter_name=f"{parameterPath}/foo1",
string_value="bar1"
)
ssm.StringParameter(stack_jP, "foo2",
parameter_name=f"{parameterPath}/foo2",
string_value="bar2"
)
ssm.StringParameter(stack_jP, "foo3",
parameter_name=f"{parameterPath}/foo3",
string_value="bar3"
)
# second stack in US
stack_uS = cdk.Stack(app, "demo-stack-us", env=env_uS)
# ensure the dependency
stack_uS.add_dependency(stack_jP)
# get remote parameters by path from SSM parameter store
parameters = RemoteParameters(stack_uS, "Parameters",
path=parameter_path,
region=stack_jP.region
)
foo1 = parameters.get(f"{parameterPath}/foo1")
foo2 = parameters.get(f"{parameterPath}/foo2")
foo3 = parameters.get(f"{parameterPath}/foo3")
cdk.CfnOutput(stack_uS, "foo1Output", value=foo1)
cdk.CfnOutput(stack_uS, "foo2Output", value=foo2)
cdk.CfnOutput(stack_uS, "foo3Output", value=foo3)
#2 - Stacks from differnt accounts and different regions
Similar to the case above, now we are running seperate stacks in seperate account/region. We will need to pass a role to the RemoteParameters construct to get all the parameters from remote.
# Example automatically generated without compilation. See https://github.com/aws/jsii/issues/826
env_jP = {"region": "ap-northeast-1", "account": "111111111111"}
env_uS = {"region": "us-west-2", "account": "222222222222"}
# first stack in JP
producer_stack_name = "demo-stack-jp"
stack_jP = cdk.Stack(app, producer_stack_name, env=env_jP)
parameter_path = f"/{envJP.account}/{envJP.region}/{producerStackName}"
ssm.StringParameter(stack_jP, "foo1",
parameter_name=f"{parameterPath}/foo1",
string_value="bar1"
)
ssm.StringParameter(stack_jP, "foo2",
parameter_name=f"{parameterPath}/foo2",
string_value="bar2"
)
ssm.StringParameter(stack_jP, "foo3",
parameter_name=f"{parameterPath}/foo3",
string_value="bar3"
)
# allow US account to assume this readonly role to get parameters
cdk_read_only_role = iam.Role(stack_jP, "readOnlyRole",
assumed_by=iam.AccountPrincipal(env_uS.account),
role_name=PhysicalName.GENERATE_IF_NEEDED,
managed_policies=[iam.ManagedPolicy.from_aws_managed_policy_name("AmazonSSMReadOnlyAccess")]
)
# second stack in US
stack_uS = cdk.Stack(app, "demo-stack-us", env=env_uS)
# ensure the dependency
stack_uS.add_dependency(stack_jP)
# get remote parameters by path from SSM parameter store
parameters = RemoteParameters(stack_uS, "Parameters",
path=parameter_path,
region=stack_jP.region,
# assume this role for cross-account parameters
role=iam.Role.from_role_arn(stack_uS, "readOnlyRole", cdk_read_only_role.role_arn)
)
foo1 = parameters.get(f"{parameterPath}/foo1")
foo2 = parameters.get(f"{parameterPath}/foo2")
foo3 = parameters.get(f"{parameterPath}/foo3")
cdk.CfnOutput(stack_uS, "foo1Output", value=foo1)
cdk.CfnOutput(stack_uS, "foo2Output", value=foo2)
cdk.CfnOutput(stack_uS, "foo3Output", value=foo3)
#3 - dedicated account for a centralized parameter store
The parameters are stored in a centralized account/region and previously provisioned as a state-of-truth configuration store. All other stacks from different account/region are consuming the parameters from remote.
This scenario is pretty much like #2. The difference is that there's a dedicated account for centralized parameter store being shared across all other accounts.
You will need create RemoteParameters for all the consuming stacks like:
# Example automatically generated without compilation. See https://github.com/aws/jsii/issues/826
# for StackUS
RemoteParameters(stack_uS, "Parameters",
path=parameter_path,
region="eu-central-1",
# assume this role for cross-account parameters
role=iam.Role.from_role_arn(stack_uS, "readOnlyRole", shared_read_only_role_arn)
)
# for StackJP
RemoteParameters(stack_jP, "Parameters",
path=parameter_path,
region="eu-central-1",
# assume this role for cross-account parameters
role=iam.Role.from_role_arn(stack_jP, "readOnlyRole", shared_read_only_role_arn)
)
Tools for multi-account deployment
You will need to install cdk-assume-role-credential-plugin so you can deploy stacks from different accounts. Read this blog post to setup this plugin.
Limitation
- At this moment, the
RemoteParametersconstruct only support theStringdata type from parameter store. - Max number of parameters is
100. Will make it configurable in the future PR when required.
Release files for cdk-remote-stack 0.1.166
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| cdk-remote-stack-0.1.166.tar.gz | 52.7 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| cdk_remote_stack-0.1.166-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 103.8 kB
Release files / cdk-remote-stack-0.1.166.tar.gz
| Download URL | cdk-remote-stack-0.1.166.tar.gz |
|---|---|
| Size | 52.7 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
e9378c10973283306e21d783cbfc546734d9f31178fa9f49526396daf9b72ff4
|
|
BLAKE2b-256 checksum How to use checksums |
bc4c179fd48ae5b58167a53b64badc5e9a1256a4027e23278917d635014d3630
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/3.4.2 importlib_metadata/4.6.4 pkginfo/1.7.1 requests/2.26.0 requests-toolbelt/0.9.1 tqdm/4.62.1 CPython/3.7.10
|
Release files / cdk_remote_stack-0.1.166-py3-none-any.whl
| Download URL | cdk_remote_stack-0.1.166-py3-none-any.whl |
|---|---|
| Size | 51.1 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
4073fa70317125f0901b450fcaff77b6645021b6abf4091b049e9ab393ef332f
|
|
BLAKE2b-256 checksum How to use checksums |
d75fc28e4cc648212765f9d045b2344993c3987449e80780c3c91e57815fce0f
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/3.4.2 importlib_metadata/4.6.4 pkginfo/1.7.1 requests/2.26.0 requests-toolbelt/0.9.1 tqdm/4.62.1 CPython/3.7.10
|