Skip to main content

Get outputs and AWS SSM parameters from cross-region AWS CloudFormation stacks

Project description

npm version PyPI version release

This is a maintained fork of @pahud/cdk-remote-stack, as the original project is no longer maintained.

cdk-remote-stack

Get outputs and AWS SSM parameters from cross-region AWS CloudFormation stacks

Install

Use the npm dist tag to opt in CDKv1 or CDKv2:

// for CDKv2
npm install @doceight/cdk-remote-stack
or
npm install @doceight/cdk-remote-stack@latest

// for CDKv1
npm install cdk-remote-stack@cdkv1

Why

Setting up cross-regional cross-stack references requires using multiple constructs from the AWS CDK construct library and is not straightforward.

cdk-remote-stack aims 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.

RemoteOutputs

RemoteOutputs is 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:

  1. stackJP - stack in Japan (JP) to create a SNS topic
  2. stackUS - stack in United States (US) to get the outputs from stackJP and print out the SNS TopicName from stackJP outputs.
import { RemoteOutputs } from '@doceight/cdk-remote-stack';
import * as cdk from 'aws-cdk-lib';

const app = new cdk.App();

const envJP = {
  region: 'ap-northeast-1',
  account: process.env.CDK_DEFAULT_ACCOUNT,
};

const envUS = {
  region: 'us-west-2',
  account: process.env.CDK_DEFAULT_ACCOUNT,
};

// first stack in JP
const stackJP = new cdk.Stack(app, 'demo-stack-jp', { env: envJP })

new cdk.CfnOutput(stackJP, 'TopicName', { value: 'foo' })

// second stack in US
const stackUS = new cdk.Stack(app, 'demo-stack-us', { env: envUS })

// ensure the dependency
stackUS.addDependency(stackJP)

// get the stackJP stack outputs from stackUS
const outputs = new RemoteOutputs(stackUS, 'Outputs', { stack: stackJP })

const remoteOutputValue = outputs.get('TopicName')

// the value should be exactly the same with the output value of `TopicName`
new cdk.CfnOutput(stackUS, 'RemoteTopicName', { value: remoteOutputValue })

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:

const outputs = new RemoteOutputs(stackUS, 'Outputs', {
  stack: stackJP,
  alwaysUpdate: false,
})

RemoteParameters

AWS Systems Manager (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:

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.

    const envJP = { region: 'ap-northeast-1', account: '111111111111' };
    const envUS = { region: 'us-west-2', account: '111111111111' };

    // first stack in JP
    const producerStackName = 'demo-stack-jp';
    const stackJP = new cdk.Stack(app, producerStackName, { env: envJP });
    const parameterPath = `/${envJP.account}/${envJP.region}/${producerStackName}`

    new ssm.StringParameter(stackJP, 'foo1', {
      parameterName: `${parameterPath}/foo1`,
      stringValue: 'bar1',
    });
    new ssm.StringParameter(stackJP, 'foo2', {
      parameterName: `${parameterPath}/foo2`,
      stringValue: 'bar2',
    });
    new ssm.StringParameter(stackJP, 'foo3', {
      parameterName: `${parameterPath}/foo3`,
      stringValue: 'bar3',
    });

    // second stack in US
    const stackUS = new cdk.Stack(app, 'demo-stack-us', { env: envUS });

    // ensure the dependency
    stackUS.addDependency(stackJP);

    // get remote parameters by path from AWS SSM parameter store
    const parameters = new RemoteParameters(stackUS, 'Parameters', {
      path: parameterPath,
      region: stackJP.region,
    })

    const foo1 = parameters.get(`${parameterPath}/foo1`);
    const foo2 = parameters.get(`${parameterPath}/foo2`);
    const foo3 = parameters.get(`${parameterPath}/foo3`);

    new cdk.CfnOutput(stackUS, 'foo1Output', { value: foo1 });
    new cdk.CfnOutput(stackUS, 'foo2Output', { value: foo2 });
    new cdk.CfnOutput(stackUS, 'foo3Output', { value: foo3 });

Stacks from differnt accounts and different regions

Similar 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) role to the RemoteParameters construct to get all the parameters from the remote environment.

    const envJP = { region: 'ap-northeast-1', account: '111111111111' };
    const envUS = { region: 'us-west-2', account: '222222222222' };

    // first stack in JP
    const producerStackName = 'demo-stack-jp';
    const stackJP = new cdk.Stack(app, producerStackName, { env: envJP });
    const parameterPath = `/${envJP.account}/${envJP.region}/${producerStackName}`

    new ssm.StringParameter(stackJP, 'foo1', {
      parameterName: `${parameterPath}/foo1`,
      stringValue: 'bar1',
    });
    new ssm.StringParameter(stackJP, 'foo2', {
      parameterName: `${parameterPath}/foo2`,
      stringValue: 'bar2',
    });
    new ssm.StringParameter(stackJP, 'foo3', {
      parameterName: `${parameterPath}/foo3`,
      stringValue: 'bar3',
    });

    // allow US account to assume this read only role to get parameters
    const cdkReadOnlyRole = new iam.Role(stackJP, 'readOnlyRole', {
      assumedBy: new iam.AccountPrincipal(envUS.account),
      roleName: PhysicalName.GENERATE_IF_NEEDED,
      managedPolicies: [ iam.ManagedPolicy.fromAwsManagedPolicyName('AmazonSSMReadOnlyAccess')],
    })

    // second stack in US
    const stackUS = new cdk.Stack(app, 'demo-stack-us', { env: envUS });

    // ensure the dependency
    stackUS.addDependency(stackJP);

    // get remote parameters by path from AWS SSM parameter store
    const parameters = new RemoteParameters(stackUS, 'Parameters', {
      path: parameterPath,
      region: stackJP.region,
      // assume this role for cross-account parameters
      role: iam.Role.fromRoleArn(stackUS, 'readOnlyRole', cdkReadOnlyRole.roleArn),
    })

    const foo1 = parameters.get(`${parameterPath}/foo1`);
    const foo2 = parameters.get(`${parameterPath}/foo2`);
    const foo3 = parameters.get(`${parameterPath}/foo3`);

    new cdk.CfnOutput(stackUS, 'foo1Output', { value: foo1 });
    new cdk.CfnOutput(stackUS, 'foo2Output', { value: foo2 });
    new cdk.CfnOutput(stackUS, 'foo3Output', { value: foo3 });

Dedicated account for a centralized parameter store

The 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 create RemoteParameters for all the consuming stacks like:

// for StackUS
new RemoteParameters(stackUS, 'Parameters', {
  path: parameterPath,
  region: 'eu-central-1'
  // assume this role for cross-account parameters
  role: iam.Role.fromRoleArn(stackUS, 'readOnlyRole', sharedReadOnlyRoleArn),
})

// for StackJP
new RemoteParameters(stackJP, 'Parameters', {
  path: parameterPath,
  region: 'eu-central-1'
  // assume this role for cross-account parameters
  role: iam.Role.fromRoleArn(stackJP, 'readOnlyRole', sharedReadOnlyRoleArn),
})

Tools for multi-account deployment

You 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. It adds support for cross-account lookups. Alternatively, install cdk-assume-role-credential-plugin. Read this blog post to setup this plugin.

Limitations

  1. At this moment, the RemoteParameters construct only supports the String data type from parameter store.
  2. Maximum number of parameters is 100. Will make it configurable in the future if required.

Contributing

See CONTRIBUTING for more information.

License

This code is licensed under the Apache License 2.0. See the LICENSE file.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

dr8_cdk_remote_stack-2.1.6.tar.gz (71.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

dr8_cdk_remote_stack-2.1.6-py3-none-any.whl (70.0 kB view details)

Uploaded Python 3

File details

Details for the file dr8_cdk_remote_stack-2.1.6.tar.gz.

File metadata

  • Download URL: dr8_cdk_remote_stack-2.1.6.tar.gz
  • Upload date:
  • Size: 71.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.14.0

File hashes

Hashes for dr8_cdk_remote_stack-2.1.6.tar.gz
Algorithm Hash digest
SHA256 e27fa7696b77675320aa078e65c159fb3c7f24782b4a578a5941b5b6ed390d4e
MD5 bb77c12dd1905d2bc71457a015d55c3a
BLAKE2b-256 a90744dde3a20c56867119043edbdae87c6d0482d274eedbdaf65b2a7a711e86

See more details on using hashes here.

Provenance

The following attestation bundles were made for dr8_cdk_remote_stack-2.1.6.tar.gz:

Publisher: release.yml on DocEight/cdk-remote-stack

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file dr8_cdk_remote_stack-2.1.6-py3-none-any.whl.

File metadata

File hashes

Hashes for dr8_cdk_remote_stack-2.1.6-py3-none-any.whl
Algorithm Hash digest
SHA256 a637721c0fe12e25a5276d0d1b06dddbb5e98e2b36d3dcdc775155145a7950df
MD5 fc68312f7a66e72496a4556fdd67c877
BLAKE2b-256 4077a9d90de7a5ab53e6e214c0581ee446fa9c1f56900749f0cd8093cde75b14

See more details on using hashes here.

Provenance

The following attestation bundles were made for dr8_cdk_remote_stack-2.1.6-py3-none-any.whl:

Publisher: release.yml on DocEight/cdk-remote-stack

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page