Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: localstack/aws-cdk-local
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: main
Choose a base ref
...
head repository: localstack/aws-cdk-local
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: fix-environment-misconfiguration
Choose a head ref
Can’t automatically merge. Don’t worry, you can still create the pull request.
  • 14 commits
  • 13 files changed
  • 1 contributor

Commits on Mar 18, 2025

  1. Set up testing

    simonrw committed Mar 18, 2025

    Verified

    This commit was signed with the committer’s verified signature.
    simonrw Simon Walker
    Copy the full SHA
    4273be3 View commit details
  2. Extract configureEnvironment and update implementation

    * sanitise environment
    * handle endpoint url configuration misconfiguration
    * add testing
    simonrw committed Mar 18, 2025

    Verified

    This commit was signed with the committer’s verified signature.
    simonrw Simon Walker
    Copy the full SHA
    8e2c62e View commit details
  3. Update readme

    simonrw committed Mar 18, 2025

    Verified

    This commit was signed with the committer’s verified signature.
    simonrw Simon Walker
    Copy the full SHA
    b49fc51 View commit details
  4. Add unit tests to CI

    simonrw committed Mar 18, 2025

    Verified

    This commit was signed with the committer’s verified signature.
    simonrw Simon Walker
    Copy the full SHA
    3d5c37f View commit details
  5. Stop concurrent test runs

    simonrw committed Mar 18, 2025

    Verified

    This commit was signed with the committer’s verified signature.
    simonrw Simon Walker
    Copy the full SHA
    479fb8c View commit details
  6. Don't install packages with npm ci

    We don't track the lockfile
    simonrw committed Mar 18, 2025

    Verified

    This commit was signed with the committer’s verified signature.
    simonrw Simon Walker
    Copy the full SHA
    e30c850 View commit details
  7. Remove weird repo checkout

    simonrw committed Mar 18, 2025

    Verified

    This commit was signed with the committer’s verified signature.
    simonrw Simon Walker
    Copy the full SHA
    04f65b2 View commit details
  8. Take credentials from the environment

    By default, we strip the values so we are overwriting but if the user
    specifies the AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY in their
    AWS_ENVAR_ALLOWLIST then they can read these from the environment
    simonrw committed Mar 18, 2025

    Verified

    This commit was signed with the committer’s verified signature.
    simonrw Simon Walker
    Copy the full SHA
    c8597b5 View commit details
  9. Regression tests allow region configuration

    simonrw committed Mar 18, 2025

    Verified

    This commit was signed with the committer’s verified signature.
    simonrw Simon Walker
    Copy the full SHA
    316a292 View commit details
  10. Add changelog entry

    simonrw committed Mar 18, 2025

    Verified

    This commit was signed with the committer’s verified signature.
    simonrw Simon Walker
    Copy the full SHA
    58a609a View commit details
  11. Propagate region if provided

    simonrw committed Mar 18, 2025

    Verified

    This commit was signed with the committer’s verified signature.
    simonrw Simon Walker
    Copy the full SHA
    56237d4 View commit details
  12. Add main attribute so package install works

    simonrw committed Mar 18, 2025

    Verified

    This commit was signed with the committer’s verified signature.
    simonrw Simon Walker
    Copy the full SHA
    dd3aaf1 View commit details

Commits on Mar 31, 2025

  1. Review changes

    simonrw committed Mar 31, 2025

    Verified

    This commit was signed with the committer’s verified signature.
    simonrw Simon Walker
    Copy the full SHA
    06b3bdc View commit details

Commits on Apr 1, 2025

  1. Apply suggestions

    simonrw committed Apr 1, 2025

    Verified

    This commit was signed with the committer’s verified signature.
    simonrw Simon Walker
    Copy the full SHA
    d58ccca View commit details
6 changes: 6 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
@@ -10,6 +10,12 @@ on:
branches:
- main

# Only one pull-request triggered run should be executed at a time
# (head_ref is only set for PR events, otherwise fallback to run_id which differs for every run).
concurrency:
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
cancel-in-progress: true

jobs:
build-and-lint:
runs-on: ubuntu-latest
8 changes: 8 additions & 0 deletions .github/workflows/integrations.go.yml
Original file line number Diff line number Diff line change
@@ -14,6 +14,13 @@ on:
upstream-version:
description: Upstream aws-cdk version to use in tests
required: false

# Only one pull-request triggered run should be executed at a time
# (head_ref is only set for PR events, otherwise fallback to run_id which differs for every run).
concurrency:
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
cancel-in-progress: true

env:
AWS_ACCESS_KEY_ID: test
AWS_SECRET_ACCESS_KEY: test
@@ -35,6 +42,7 @@ jobs:
env:
AWS_REGION: ${{ matrix.region }}
AWS_DEFAULT_REGION: ${{ matrix.region }}
AWS_ENVAR_ALLOWLIST: AWS_REGION,AWS_DEFAULT_REGION

steps:
- uses: actions/checkout@v2
8 changes: 8 additions & 0 deletions .github/workflows/integrations.node.yml
Original file line number Diff line number Diff line change
@@ -14,6 +14,13 @@ on:
upstream-version:
description: Upstream aws-cdk version to use in tests
required: false

# Only one pull-request triggered run should be executed at a time
# (head_ref is only set for PR events, otherwise fallback to run_id which differs for every run).
concurrency:
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
cancel-in-progress: true

env:
AWS_ACCESS_KEY_ID: test
AWS_SECRET_ACCESS_KEY: test
@@ -33,6 +40,7 @@ jobs:
env:
AWS_REGION: ${{ matrix.region }}
AWS_DEFAULT_REGION: ${{ matrix.region }}
AWS_ENVAR_ALLOWLIST: AWS_REGION,AWS_DEFAULT_REGION

steps:
- uses: actions/checkout@v2
8 changes: 8 additions & 0 deletions .github/workflows/integrations.python.yml
Original file line number Diff line number Diff line change
@@ -14,6 +14,13 @@ on:
upstream-version:
description: Upstream aws-cdk version to use in tests
required: false

# Only one pull-request triggered run should be executed at a time
# (head_ref is only set for PR events, otherwise fallback to run_id which differs for every run).
concurrency:
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
cancel-in-progress: true

env:
AWS_ACCESS_KEY_ID: test
AWS_SECRET_ACCESS_KEY: test
@@ -33,6 +40,7 @@ jobs:
env:
AWS_REGION: ${{ matrix.region }}
AWS_DEFAULT_REGION: ${{ matrix.region }}
AWS_ENVAR_ALLOWLIST: AWS_REGION,AWS_DEFAULT_REGION

steps:
- uses: actions/checkout@v2
6 changes: 6 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
@@ -20,6 +20,12 @@ on:
type: boolean
default: false

# Only one pull-request triggered run should be executed at a time
# (head_ref is only set for PR events, otherwise fallback to run_id which differs for every run).
concurrency:
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
cancel-in-progress: true

env:
AWS_ACCESS_KEY_ID: test
AWS_SECRET_ACCESS_KEY: test
39 changes: 39 additions & 0 deletions .github/workflows/unit.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
name: Unit tests

on:
push:
branches:
- main
pull_request:
workflow_dispatch:
inputs:
node-version:
required: false
default: "22.x"

# Only one pull-request triggered run should be executed at a time
# (head_ref is only set for PR events, otherwise fallback to run_id which differs for every run).
concurrency:
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
cancel-in-progress: true

jobs:
unit-tests:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: Use Node.js ${{ inputs.node-version }}
uses: actions/setup-node@v4
with:
node-version: ${{ inputs.node-version }}

- name: Install project
run: |
npm install
- name: Run tests
run: |
npm run test
11 changes: 11 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -28,12 +28,22 @@ To resolve this, set the `NODE_PATH` variable pointing to your AWS CDK's `node_m
$ export NODE_PATH=$NODE_PATH:/opt/homebrew/Cellar/aws-cdk/<CDK_VERSION>/libexec/lib/node_modules
```

## Version support

`cdklocal` supports all installed versions of the node `aws-cdk` package, however some complications are present for `aws-cdk >= 2.177.0`.

For these CDK versions, we remove AWS configuration environment variables like `AWS_PROFILE` from the shell environment before invoking the `cdk` command, and explicitly set `AWS_ENDPOINT_URL` and `AWS_ENDPOINT_URL_S3` to target LocalStack.

1. We do this because other environment variables may lead to a conflicting set of configuration options, where the wrong region is used to target LocalStack, or `cdklocal` tries to deploy into upstream AWS by mistake. If individual configuration variables are needed for the deploy process (e.g. `AWS_REGION`) these configuration variables can be propagated to the `cdk` command by configuring `AWS_ENVAR_ALLOWLIST`, for example: `AWS_ENVAR_ALLOWLIST=AWS_REGION,AWS_DEFAULT_REGION AWS_DEFAULT_REGION=eu-central-1 AWS_REGION=eu-central-1 cdklocal ...`.
2. If you are manually setting `AWS_ENDPOINT_URL`, the new value will continue to be read from the environment, however `AWS_ENDPOINT_URL_S3` _must_ also be set and should include a `.s3.` component to ensure we correctly detect S3 requests.

## Configurations

The following environment variables can be configured:

* `AWS_ENDPOINT_URL`: The endpoint URL to connect to (combination of `USE_SSL`/`LOCALSTACK_HOSTNAME`/`EDGE_PORT` below)
* `AWS_ENDPOINT_URL_S3`: The endpoint URL to connect to (combination of `USE_SSL`/`LOCALSTACK_HOSTNAME`/`EDGE_PORT` below) for S3 requests
* `AWS_ENVAR_ALLOWLIST`: Allow specific `AWS_*` environment variables to be used by the CDK
* `EDGE_PORT` (deprecated): Port under which LocalStack edge service is accessible (default: `4566`)
* `LOCALSTACK_HOSTNAME` (deprecated): Target host under which LocalStack edge service is accessible (default: `localhost`)
* `USE_SSL` (deprecated): Whether to use SSL to connect to the LocalStack endpoint, i.e., connect via HTTPS.
@@ -78,6 +88,7 @@ $ awslocal sns list-topics

## Change Log

* 3.0.0: Sanitise environment of configuration environment variables before deployment
* 2.19.2: Fix SDK compatibility with aws-cdk versions >= 2.177.0
* 2.19.1: Fix SDK compatibility with older CDK versions; Fix patched bucket location in TemplateURL
* 2.19.0: Add support for aws-cdk versions >= `2.167.0`
109 changes: 109 additions & 0 deletions __tests__/index.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
const { configureEnvironment, EnvironmentMisconfigurationError } = require("../src");

describe("configureEnvironment", () => {
test("empty environment", () => {
const env = {};
const allowListStr = "";
configureEnvironment(env, allowListStr);
expect(env).toEqual({
AWS_ACCESS_KEY_ID: "test",
AWS_SECRET_ACCESS_KEY: "test",
AWS_REGION: "us-east-1",
AWS_DEFAULT_REGION: "us-east-1",
AWS_ENDPOINT_URL: "http://localhost.localstack.cloud:4566",
AWS_ENDPOINT_URL_S3: "http://s3.localhost.localstack.cloud:4566",
});
});

test("custom endpoint url", () => {
const env = {
AWS_ENDPOINT_URL: "http://foo.bar:4567",
AWS_ENDPOINT_URL_S3: "http://foo.bar:4567",
};
const allowListStr = "";
configureEnvironment(env, allowListStr);
expect(env).toEqual({
AWS_ACCESS_KEY_ID: "test",
AWS_SECRET_ACCESS_KEY: "test",
AWS_REGION: "us-east-1",
AWS_DEFAULT_REGION: "us-east-1",
AWS_ENDPOINT_URL: "http://foo.bar:4567",
AWS_ENDPOINT_URL_S3: "http://foo.bar:4567",
});
});

test("custom endpoint url without specifying s3 url", () => {
const env = {
AWS_ENDPOINT_URL: "http://foo.bar:4567",
};
const allowListStr = "";
expect(() => configureEnvironment(env, allowListStr)).toThrow(EnvironmentMisconfigurationError);
});

test("strip extra configuration envars", () => {
const env = {
AWS_PROFILE: "my-profile",
};
const allowListStr = "";
configureEnvironment(env, allowListStr);
expect(env).toEqual({
AWS_ACCESS_KEY_ID: "test",
AWS_SECRET_ACCESS_KEY: "test",
AWS_REGION: "us-east-1",
AWS_DEFAULT_REGION: "us-east-1",
AWS_ENDPOINT_URL: "http://localhost.localstack.cloud:4566",
AWS_ENDPOINT_URL_S3: "http://s3.localhost.localstack.cloud:4566",
});
});

test("allowlist of profile", () => {
const env = {
AWS_PROFILE: "my-profile",
};
const allowListStr = "AWS_PROFILE";
configureEnvironment(env, allowListStr);
expect(env).toEqual({
AWS_ACCESS_KEY_ID: "test",
AWS_SECRET_ACCESS_KEY: "test",
AWS_PROFILE: "my-profile",
AWS_REGION: "us-east-1",
AWS_DEFAULT_REGION: "us-east-1",
AWS_ENDPOINT_URL: "http://localhost.localstack.cloud:4566",
AWS_ENDPOINT_URL_S3: "http://s3.localhost.localstack.cloud:4566",
});
});

test("credentials overriding", () => {
const env = {
AWS_ACCESS_KEY_ID: "something",
AWS_SECRET_ACCESS_KEY: "else",
};
const allowListStr = "AWS_PROFILE,AWS_SECRET_ACCESS_KEY,AWS_ACCESS_KEY_ID";
configureEnvironment(env, allowListStr);
expect(env).toEqual({
AWS_ACCESS_KEY_ID: "something",
AWS_SECRET_ACCESS_KEY: "else",
AWS_REGION: "us-east-1",
AWS_DEFAULT_REGION: "us-east-1",
AWS_ENDPOINT_URL: "http://localhost.localstack.cloud:4566",
AWS_ENDPOINT_URL_S3: "http://s3.localhost.localstack.cloud:4566",
});
});

test("region overriding", () => {
const env = {
AWS_REGION: "eu-central-1",
AWS_DEFAULT_REGION: "eu-central-1",
};
const allowListStr = "AWS_REGION,AWS_DEFAULT_REGION";
configureEnvironment(env, allowListStr);
expect(env).toEqual({
AWS_ACCESS_KEY_ID: "test",
AWS_SECRET_ACCESS_KEY: "test",
AWS_REGION: "eu-central-1",
AWS_DEFAULT_REGION: "eu-central-1",
AWS_ENDPOINT_URL: "http://localhost.localstack.cloud:4566",
AWS_ENDPOINT_URL_S3: "http://s3.localhost.localstack.cloud:4566",
});
});
});
17 changes: 4 additions & 13 deletions bin/cdklocal
Original file line number Diff line number Diff line change
@@ -9,15 +9,13 @@ const https = require("https");
const crypto = require("crypto");
const net = require('net');

// constants and custom config values
const { isEnvTrue, EDGE_PORT, PROTOCOL, configureEnvironment } = require("../src");

const isEnvTrue = (envName) => ["1", "true"].includes(process.env[envName]);
// constants and custom config values

const DEFAULT_EDGE_PORT = 4566;
const EDGE_PORT = process.env.EDGE_PORT || DEFAULT_EDGE_PORT;
const DEFAULT_HOSTNAME = "localhost";
const LAMBDA_MOUNT_CODE = isEnvTrue("LAMBDA_MOUNT_CODE");
const PROTOCOL = isEnvTrue("USE_SSL") ? "https" : "http";
const AWS_ENVAR_ALLOWLIST = process.env.AWS_ENVAR_ALLOWLIST || "";


//----------------
@@ -451,13 +449,6 @@ const patchPre_2_14 = () => {
applyPatches(provider, CdkToolkit, SDK, ToolkitInfo);
};

const configureEnvironment = () => {
// This _must_ use localhost.localstack.cloud as we require valid subdomains of these paths to
// resolve. Unfortunately though `curl` seems to support subdomains of localhost, the CDK does not.
process.env.AWS_ENDPOINT_URL_S3 = process.env.AWS_ENDPOINT_URL_S3 || `${PROTOCOL}://s3.localhost.localstack.cloud:${EDGE_PORT}`;
process.env.AWS_ENDPOINT_URL = process.env.AWS_ENDPOINT_URL || `${PROTOCOL}://localhost.localstack.cloud:${EDGE_PORT}`;
};

const patchPost_2_14 = () => {
var lib = null;
try {
@@ -484,7 +475,7 @@ const patchPost_2_14 = () => {
break;
case "ERR_PACKAGE_PATH_NOT_EXPORTED":
// post 2.177
configureEnvironment();
configureEnvironment(process.env, AWS_ENVAR_ALLOWLIST);
break;
default:
// a different error
8 changes: 8 additions & 0 deletions jest.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
module.exports = {
testEnvironment: "node",
verbose: true,
coverageDirectory: "coverage",
collectCoverageFrom: ["src/**/*.{js,jsx,ts,tsx}"],
testMatch: ["**/__tests__/**/*.[jt]s?(x)", "**/?(*.)+(spec|test).[jt]s?(x)"],
};

Loading