Security News
Research
Data Theft Repackaged: A Case Study in Malicious Wrapper Packages on npm
The Socket Research Team breaks down a malicious wrapper package that uses obfuscation to harvest credentials and exfiltrate sensitive data.
cdk-remote-stack
Advanced tools
Get outputs and AWS SSM parameters from cross-region AWS CloudFormation stacks
Get outputs and AWS SSM parameters from cross-region AWS CloudFormation stacks
Use the npm dist tag to opt in CDKv1 or CDKv2:
// for CDKv2
npm install cdk-remote-stack
or
npm install cdk-remote-stack@latest
// for CDKv1
npm install cdk-remote-stack@cdkv1
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
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:
JP
) to create a SNS topicUS
) to get the outputs from stackJP
and print out the SNS TopicName
from stackJP
outputs.import { RemoteOutputs } from '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.
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,
})
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:
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 });
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 });
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),
})
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.
RemoteParameters
construct only supports the String
data type from parameter store.100
. Will make it configurable in the future if required.See CONTRIBUTING for more information.
This code is licensed under the Apache License 2.0. See the LICENSE file.
FAQs
Get outputs and AWS SSM parameters from cross-region AWS CloudFormation stacks
The npm package cdk-remote-stack receives a total of 1,696 weekly downloads. As such, cdk-remote-stack popularity was classified as popular.
We found that cdk-remote-stack demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 0 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
Research
The Socket Research Team breaks down a malicious wrapper package that uses obfuscation to harvest credentials and exfiltrate sensitive data.
Research
Security News
Attackers used a malicious npm package typosquatting a popular ESLint plugin to steal sensitive data, execute commands, and exploit developer systems.
Security News
The Ultralytics' PyPI Package was compromised four times in one weekend through GitHub Actions cache poisoning and failure to rotate previously compromised API tokens.