@go-to-k/cdkd 0.167.1 → 0.167.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +110 -8
- package/dist/cli.js.map +1 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -62,7 +62,7 @@ import { CreateVectorBucketCommand, DeleteIndexCommand, DeleteVectorBucketComman
|
|
|
62
62
|
import { CreateNamespaceCommand, CreateTableBucketCommand, CreateTableCommand as CreateTableCommand$2, DeleteNamespaceCommand as DeleteNamespaceCommand$1, DeleteTableBucketCommand, DeleteTableCommand as DeleteTableCommand$2, GetTableBucketCommand, GetTableCommand as GetTableCommand$1, ListNamespacesCommand as ListNamespacesCommand$1, ListTableBucketsCommand, ListTablesCommand as ListTablesCommand$1, ListTagsForResourceCommand as ListTagsForResourceCommand$19, NotFoundException as NotFoundException$5, S3TablesClient } from "@aws-sdk/client-s3tables";
|
|
63
63
|
import { AttachLoadBalancerTargetGroupsCommand, AttachLoadBalancersCommand, AttachTrafficSourcesCommand, AutoScalingClient, CreateAutoScalingGroupCommand, CreateOrUpdateTagsCommand, DeleteAutoScalingGroupCommand, DeleteLifecycleHookCommand, DeleteNotificationConfigurationCommand, DeleteTagsCommand as DeleteTagsCommand$1, DescribeAutoScalingGroupsCommand, DescribeLifecycleHooksCommand, DescribeNotificationConfigurationsCommand, DescribeTrafficSourcesCommand, DetachLoadBalancerTargetGroupsCommand, DetachLoadBalancersCommand, DetachTrafficSourcesCommand, DisableMetricsCollectionCommand, EnableMetricsCollectionCommand, PutLifecycleHookCommand, PutNotificationConfigurationCommand, UpdateAutoScalingGroupCommand } from "@aws-sdk/client-auto-scaling";
|
|
64
64
|
import { Document, Pair, Scalar, YAMLMap, YAMLSeq, parse as parse$1, stringify } from "yaml";
|
|
65
|
-
import { mkdir, mkdtemp } from "node:fs/promises";
|
|
65
|
+
import { mkdir, mkdtemp, rm, writeFile } from "node:fs/promises";
|
|
66
66
|
import { Readable } from "node:stream";
|
|
67
67
|
import { pipeline } from "node:stream/promises";
|
|
68
68
|
import { createServer } from "node:net";
|
|
@@ -46520,6 +46520,62 @@ function singleFlight(fn, onError) {
|
|
|
46520
46520
|
};
|
|
46521
46521
|
}
|
|
46522
46522
|
|
|
46523
|
+
//#endregion
|
|
46524
|
+
//#region src/cli/commands/local-profile-credentials-file.ts
|
|
46525
|
+
/**
|
|
46526
|
+
* Path inside the container where the credentials file is mounted. Fixed
|
|
46527
|
+
* (not user-configurable) so the env-var injection is stable. `/cdkd-aws/`
|
|
46528
|
+
* is outside `/var/task` (the Lambda code mount) and outside `/root/`
|
|
46529
|
+
* (which the user's handler may bind-mount or modify), so there is no
|
|
46530
|
+
* collision risk with the user's payload.
|
|
46531
|
+
*/
|
|
46532
|
+
const CONTAINER_AWS_CREDENTIALS_PATH = "/cdkd-aws/credentials";
|
|
46533
|
+
/**
|
|
46534
|
+
* Write a temporary AWS shared-credentials file containing the resolved
|
|
46535
|
+
* `--profile <name>` credentials, ready to bind-mount into a Lambda
|
|
46536
|
+
* container at {@link CONTAINER_AWS_CREDENTIALS_PATH}.
|
|
46537
|
+
*
|
|
46538
|
+
* The file content is the standard `[profile-name]` INI shape:
|
|
46539
|
+
*
|
|
46540
|
+
* [<profileName>]
|
|
46541
|
+
* aws_access_key_id = <accessKeyId>
|
|
46542
|
+
* aws_secret_access_key = <secretAccessKey>
|
|
46543
|
+
* aws_session_token = <sessionToken> ← only when present
|
|
46544
|
+
*
|
|
46545
|
+
* `aws_session_token` is omitted when the resolved profile produced
|
|
46546
|
+
* long-lived (non-STS) credentials, mirroring the same logic
|
|
46547
|
+
* `applyProfileCredentialsOverlay` uses for env-var injection.
|
|
46548
|
+
*
|
|
46549
|
+
* Caller is responsible for invoking `dispose()` when the container pool
|
|
46550
|
+
* tears down (e.g., on `SIGINT` via `singleFlight` cleanup). Leaving the
|
|
46551
|
+
* file behind in `/tmp` is a security smell (temp credentials live on
|
|
46552
|
+
* disk).
|
|
46553
|
+
*/
|
|
46554
|
+
async function writeProfileCredentialsFile(profileName, creds) {
|
|
46555
|
+
if (profileName === "") throw new Error("writeProfileCredentialsFile: profile name must not be empty.");
|
|
46556
|
+
if (/[\r\n[\]]/.test(profileName)) throw new Error(`writeProfileCredentialsFile: profile name '${profileName}' contains a forbidden character (any of CR, LF, '[', ']' would corrupt the INI file or the docker -e env var).`);
|
|
46557
|
+
const dir = await mkdtemp(path.join(tmpdir(), "cdkd-profile-creds-"));
|
|
46558
|
+
const hostPath = path.join(dir, "credentials");
|
|
46559
|
+
const lines = [
|
|
46560
|
+
`[${profileName}]`,
|
|
46561
|
+
`aws_access_key_id = ${creds.accessKeyId}`,
|
|
46562
|
+
`aws_secret_access_key = ${creds.secretAccessKey}`
|
|
46563
|
+
];
|
|
46564
|
+
if (creds.sessionToken) lines.push(`aws_session_token = ${creds.sessionToken}`);
|
|
46565
|
+
await writeFile(hostPath, lines.join("\n") + "\n", { mode: 384 });
|
|
46566
|
+
return {
|
|
46567
|
+
hostPath,
|
|
46568
|
+
containerPath: CONTAINER_AWS_CREDENTIALS_PATH,
|
|
46569
|
+
profileName,
|
|
46570
|
+
dispose: async () => {
|
|
46571
|
+
await rm(dir, {
|
|
46572
|
+
recursive: true,
|
|
46573
|
+
force: true
|
|
46574
|
+
});
|
|
46575
|
+
}
|
|
46576
|
+
};
|
|
46577
|
+
}
|
|
46578
|
+
|
|
46523
46579
|
//#endregion
|
|
46524
46580
|
//#region src/local/intrinsic-lambda-arn.ts
|
|
46525
46581
|
/**
|
|
@@ -50510,6 +50566,11 @@ function createContainerPool(specs, options) {
|
|
|
50510
50566
|
containerPath: "/opt",
|
|
50511
50567
|
readOnly: true
|
|
50512
50568
|
}] : [];
|
|
50569
|
+
const extraMounts = spec.profileCredentialsFile ? [...optMount, {
|
|
50570
|
+
hostPath: spec.profileCredentialsFile.hostPath,
|
|
50571
|
+
containerPath: spec.profileCredentialsFile.containerPath,
|
|
50572
|
+
readOnly: true
|
|
50573
|
+
}] : optMount;
|
|
50513
50574
|
const containerCodePath = resolveRuntimeCodeMountPath(spec.lambda.runtime);
|
|
50514
50575
|
containerId = await runDetached({
|
|
50515
50576
|
image: resolveRuntimeImage(spec.lambda.runtime),
|
|
@@ -50518,7 +50579,7 @@ function createContainerPool(specs, options) {
|
|
|
50518
50579
|
containerPath: containerCodePath,
|
|
50519
50580
|
readOnly: true
|
|
50520
50581
|
}],
|
|
50521
|
-
extraMounts
|
|
50582
|
+
extraMounts,
|
|
50522
50583
|
env: spec.env,
|
|
50523
50584
|
cmd: [spec.lambda.handler],
|
|
50524
50585
|
hostPort,
|
|
@@ -50531,6 +50592,11 @@ function createContainerPool(specs, options) {
|
|
|
50531
50592
|
} else containerId = await runDetached({
|
|
50532
50593
|
image: spec.image,
|
|
50533
50594
|
mounts: [],
|
|
50595
|
+
...spec.profileCredentialsFile && { extraMounts: [{
|
|
50596
|
+
hostPath: spec.profileCredentialsFile.hostPath,
|
|
50597
|
+
containerPath: spec.profileCredentialsFile.containerPath,
|
|
50598
|
+
readOnly: true
|
|
50599
|
+
}] },
|
|
50534
50600
|
env: spec.env,
|
|
50535
50601
|
cmd: spec.command,
|
|
50536
50602
|
hostPort,
|
|
@@ -55023,6 +55089,7 @@ async function localStartApiCommand(target, options) {
|
|
|
55023
55089
|
const perLambdaConcurrency = parsePerLambdaConcurrency(options.perLambdaConcurrency);
|
|
55024
55090
|
const inlineTmpDirs = /* @__PURE__ */ new Set();
|
|
55025
55091
|
const layerTmpDirs = /* @__PURE__ */ new Set();
|
|
55092
|
+
let profileCredsFile;
|
|
55026
55093
|
const lastAssetPaths = { value: [] };
|
|
55027
55094
|
const authorizerCache = createAuthorizerCache();
|
|
55028
55095
|
const jwksCache = createJwksCache();
|
|
@@ -55094,6 +55161,7 @@ async function localStartApiCommand(target, options) {
|
|
|
55094
55161
|
}
|
|
55095
55162
|
const stateByStack = options.fromState || isCfnFlagPresent(options) ? await loadStateForRoutedStacks(targetStacks, routes, routesWithAuth, options) : /* @__PURE__ */ new Map();
|
|
55096
55163
|
const profileCredentials = options.profile ? await resolveProfileCredentials(options.profile) : void 0;
|
|
55164
|
+
if (options.profile && profileCredentials && !profileCredsFile) profileCredsFile = await writeProfileCredentialsFile(options.profile, profileCredentials);
|
|
55097
55165
|
const lambdaIds = uniqueLambdaIds(routes, routesWithAuth, webSocketApis);
|
|
55098
55166
|
const specs = /* @__PURE__ */ new Map();
|
|
55099
55167
|
for (let i = 0; i < lambdaIds.length; i++) {
|
|
@@ -55111,7 +55179,8 @@ async function localStartApiCommand(target, options) {
|
|
|
55111
55179
|
stateByStack,
|
|
55112
55180
|
skipPull: options.pull === false,
|
|
55113
55181
|
...options.layerRoleArn !== void 0 && { layerRoleArn: options.layerRoleArn },
|
|
55114
|
-
...profileCredentials && { profileCredentials }
|
|
55182
|
+
...profileCredentials && { profileCredentials },
|
|
55183
|
+
...profileCredsFile && { profileCredsFile }
|
|
55115
55184
|
});
|
|
55116
55185
|
specs.set(logicalId, spec);
|
|
55117
55186
|
}
|
|
@@ -55387,6 +55456,11 @@ async function localStartApiCommand(target, options) {
|
|
|
55387
55456
|
} catch (err) {
|
|
55388
55457
|
logger.warn(`Failed to remove merged-layers tmpdir ${dir}: ${err instanceof Error ? err.message : String(err)}`);
|
|
55389
55458
|
}
|
|
55459
|
+
if (profileCredsFile) try {
|
|
55460
|
+
await profileCredsFile.dispose();
|
|
55461
|
+
} catch (err) {
|
|
55462
|
+
logger.warn(`Failed to remove profile credentials tmpdir ${profileCredsFile.hostPath}: ${err instanceof Error ? err.message : String(err)}`);
|
|
55463
|
+
}
|
|
55390
55464
|
});
|
|
55391
55465
|
const shutdown = async (signal, exitCode) => {
|
|
55392
55466
|
if (shutdownStarted) {
|
|
@@ -55545,7 +55619,7 @@ function warnIamRoutes(routesWithAuth) {
|
|
|
55545
55619
|
* missing, runtime not supported).
|
|
55546
55620
|
*/
|
|
55547
55621
|
async function buildContainerSpec(args) {
|
|
55548
|
-
const { logicalId, stacks, overrides, assumeRole, containerHost, debugPort, stsRegion, inlineTmpDirs, layerTmpDirs, stateByStack, skipPull, layerRoleArn, profileCredentials } = args;
|
|
55622
|
+
const { logicalId, stacks, overrides, assumeRole, containerHost, debugPort, stsRegion, inlineTmpDirs, layerTmpDirs, stateByStack, skipPull, layerRoleArn, profileCredentials, profileCredsFile } = args;
|
|
55549
55623
|
const lambda = resolveLambdaByLogicalId(logicalId, stacks);
|
|
55550
55624
|
let codeDir;
|
|
55551
55625
|
let optDir;
|
|
@@ -55599,6 +55673,10 @@ async function buildContainerSpec(args) {
|
|
|
55599
55673
|
if (profileCredentials.sessionToken) dockerEnv["AWS_SESSION_TOKEN"] = profileCredentials.sessionToken;
|
|
55600
55674
|
else delete dockerEnv["AWS_SESSION_TOKEN"];
|
|
55601
55675
|
}
|
|
55676
|
+
if (profileCredsFile) {
|
|
55677
|
+
dockerEnv["AWS_SHARED_CREDENTIALS_FILE"] = profileCredsFile.containerPath;
|
|
55678
|
+
dockerEnv["AWS_PROFILE"] = profileCredsFile.profileName;
|
|
55679
|
+
}
|
|
55602
55680
|
}
|
|
55603
55681
|
if (debugPort !== void 0) dockerEnv["NODE_OPTIONS"] = `--inspect-brk=0.0.0.0:${debugPort}`;
|
|
55604
55682
|
const tmpfs = lambda.ephemeralStorageMb !== void 0 ? {
|
|
@@ -55613,7 +55691,11 @@ async function buildContainerSpec(args) {
|
|
|
55613
55691
|
containerHost,
|
|
55614
55692
|
...optDir !== void 0 && { optDir },
|
|
55615
55693
|
...debugPort !== void 0 && { debugPort },
|
|
55616
|
-
...tmpfs !== void 0 && { tmpfs }
|
|
55694
|
+
...tmpfs !== void 0 && { tmpfs },
|
|
55695
|
+
...profileCredsFile && { profileCredentialsFile: {
|
|
55696
|
+
hostPath: profileCredsFile.hostPath,
|
|
55697
|
+
containerPath: profileCredsFile.containerPath
|
|
55698
|
+
} }
|
|
55617
55699
|
};
|
|
55618
55700
|
return {
|
|
55619
55701
|
kind: "image",
|
|
@@ -55626,7 +55708,11 @@ async function buildContainerSpec(args) {
|
|
|
55626
55708
|
env: dockerEnv,
|
|
55627
55709
|
containerHost,
|
|
55628
55710
|
...debugPort !== void 0 && { debugPort },
|
|
55629
|
-
...tmpfs !== void 0 && { tmpfs }
|
|
55711
|
+
...tmpfs !== void 0 && { tmpfs },
|
|
55712
|
+
...profileCredsFile && { profileCredentialsFile: {
|
|
55713
|
+
hostPath: profileCredsFile.hostPath,
|
|
55714
|
+
containerPath: profileCredsFile.containerPath
|
|
55715
|
+
} }
|
|
55630
55716
|
};
|
|
55631
55717
|
}
|
|
55632
55718
|
/**
|
|
@@ -58928,6 +59014,7 @@ async function localInvokeCommand(target, options) {
|
|
|
58928
59014
|
let containerId;
|
|
58929
59015
|
let stopLogs;
|
|
58930
59016
|
let sigintHandler;
|
|
59017
|
+
let profileCredsFile;
|
|
58931
59018
|
/**
|
|
58932
59019
|
* Unified cleanup for both the success / failure unwind path AND the
|
|
58933
59020
|
* SIGINT handler. Idempotent — every step guards on its own undefined
|
|
@@ -58976,6 +59063,11 @@ async function localInvokeCommand(target, options) {
|
|
|
58976
59063
|
} catch (err) {
|
|
58977
59064
|
getLogger().debug(`Failed to remove ARN-layer tmpdir ${dir}: ${err instanceof Error ? err.message : String(err)}`);
|
|
58978
59065
|
}
|
|
59066
|
+
if (profileCredsFile) try {
|
|
59067
|
+
await profileCredsFile.dispose();
|
|
59068
|
+
} catch (err) {
|
|
59069
|
+
getLogger().debug(`Failed to remove profile credentials tmpdir ${profileCredsFile.hostPath}: ${err instanceof Error ? err.message : String(err)}`);
|
|
59070
|
+
}
|
|
58979
59071
|
}, (err) => {
|
|
58980
59072
|
getLogger().debug(`cleanup failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
58981
59073
|
});
|
|
@@ -58986,6 +59078,7 @@ async function localInvokeCommand(target, options) {
|
|
|
58986
59078
|
});
|
|
58987
59079
|
await ensureDockerAvailable();
|
|
58988
59080
|
const profileCredentials = options.profile ? await resolveProfileCredentials(options.profile) : void 0;
|
|
59081
|
+
if (options.profile && profileCredentials) profileCredsFile = await writeProfileCredentialsFile(options.profile, profileCredentials);
|
|
58989
59082
|
const appCmd = resolveApp(options.app);
|
|
58990
59083
|
if (!appCmd) throw new Error("No CDK app specified. Pass --app, set CDKD_APP, or add \"app\" to cdk.json.");
|
|
58991
59084
|
logger.info("Synthesizing CDK app...");
|
|
@@ -59086,6 +59179,10 @@ async function localInvokeCommand(target, options) {
|
|
|
59086
59179
|
if (!assumeSucceeded) {
|
|
59087
59180
|
forwardAwsEnv(dockerEnv);
|
|
59088
59181
|
applyProfileCredentialsOverlay(dockerEnv, profileCredentials, false);
|
|
59182
|
+
if (profileCredsFile) {
|
|
59183
|
+
dockerEnv["AWS_SHARED_CREDENTIALS_FILE"] = profileCredsFile.containerPath;
|
|
59184
|
+
dockerEnv["AWS_PROFILE"] = profileCredsFile.profileName;
|
|
59185
|
+
}
|
|
59089
59186
|
}
|
|
59090
59187
|
let debugPort;
|
|
59091
59188
|
if (options.debugPort) {
|
|
@@ -59098,10 +59195,15 @@ async function localInvokeCommand(target, options) {
|
|
|
59098
59195
|
const containerHost = options.containerHost;
|
|
59099
59196
|
if (lambda.layers.length > 0) logger.info(`Mounting ${lambda.layers.length} Lambda layer${lambda.layers.length === 1 ? "" : "s"} at /opt`);
|
|
59100
59197
|
logger.info(`Starting container (image=${imagePlan.image}, port=${hostPort})...`);
|
|
59198
|
+
const extraMountsWithProfile = profileCredsFile ? [...imagePlan.extraMounts ?? [], {
|
|
59199
|
+
hostPath: profileCredsFile.hostPath,
|
|
59200
|
+
containerPath: profileCredsFile.containerPath,
|
|
59201
|
+
readOnly: true
|
|
59202
|
+
}] : imagePlan.extraMounts;
|
|
59101
59203
|
containerId = await runDetached({
|
|
59102
59204
|
image: imagePlan.image,
|
|
59103
59205
|
mounts: imagePlan.mounts,
|
|
59104
|
-
extraMounts:
|
|
59206
|
+
extraMounts: extraMountsWithProfile,
|
|
59105
59207
|
env: dockerEnv,
|
|
59106
59208
|
cmd: imagePlan.cmd,
|
|
59107
59209
|
hostPort,
|
|
@@ -60780,7 +60882,7 @@ function reorderArgs(argv) {
|
|
|
60780
60882
|
*/
|
|
60781
60883
|
async function main() {
|
|
60782
60884
|
const program = new Command();
|
|
60783
|
-
program.name("cdkd").description("CDK Direct - Deploy AWS CDK apps directly via SDK/Cloud Control API").version("0.167.
|
|
60885
|
+
program.name("cdkd").description("CDK Direct - Deploy AWS CDK apps directly via SDK/Cloud Control API").version("0.167.2");
|
|
60784
60886
|
program.addCommand(createBootstrapCommand());
|
|
60785
60887
|
program.addCommand(createSynthCommand());
|
|
60786
60888
|
program.addCommand(createListCommand());
|