@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 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: optMount,
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: imagePlan.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.1");
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());