cdk-local 0.160.1 → 0.161.0
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/README.md +5 -1
- package/dist/assembly-path-R96uhMm1.js +208 -0
- package/dist/assembly-path-R96uhMm1.js.map +1 -0
- package/dist/cli.js +2 -2
- package/dist/{docker-cmd-CoZdbeos.js → docker-cmd-Cjg3jGYF.js} +5 -223
- package/dist/docker-cmd-Cjg3jGYF.js.map +1 -0
- package/dist/docker-runner-CnXQIUjd.js +1810 -0
- package/dist/docker-runner-CnXQIUjd.js.map +1 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/internal.d.ts +141 -2
- package/dist/internal.d.ts.map +1 -1
- package/dist/internal.js +5 -3
- package/dist/{local-studio-Ur6enHho.js → local-studio-DNWiPLme.js} +310 -2273
- package/dist/local-studio-DNWiPLme.js.map +1 -0
- package/dist/{local-studio-DgWD3_iK.d.ts → local-studio-DYKegdhd.d.ts} +18 -2
- package/dist/local-studio-DYKegdhd.d.ts.map +1 -0
- package/dist/rolldown-runtime-w6R9maHv.js +18 -0
- package/dist/workload-aws-wiring-BIxf0jtl.js +916 -0
- package/dist/workload-aws-wiring-BIxf0jtl.js.map +1 -0
- package/package.json +1 -1
- package/dist/docker-cmd-CoZdbeos.js.map +0 -1
- package/dist/local-studio-DgWD3_iK.d.ts.map +0 -1
- package/dist/local-studio-Ur6enHho.js.map +0 -1
|
@@ -1,21 +1,18 @@
|
|
|
1
|
-
import { C as sanitizeServiceExceptionMessage, S as isAwsServiceException, _ as resolveAssemblyPath, a as isDockerClientEnvKey, b as describeCredentialLoadFailure, c as runDockerStreaming, d as absoluteAssemblyPathEscape, f as assemblyPathEscape, g as renderAssemblyPathEscape, h as namesTheSameDirectory, i as getDockerCmd, l as spawnStreaming, m as isPasteableCommandArg, n as finchSecretArgvRefusal, o as isMalformedEnvKey, p as displayUntrustedValue, r as formatDockerLoginError, s as runDockerForeground, u as warnFinchArgvExposure, v as clampErrorName, w as stringifyThrown, x as flattenToOneLine, y as describeAwsFailureForWarn } from "./docker-cmd-CoZdbeos.js";
|
|
2
1
|
import { a as displayIdent, c as getEmbedConfig, i as STACK_REF_MAX_CODE_POINTS, o as displayStackName, s as displayToolOutput, t as getLogger, u as setEmbedConfig } from "./logger-Co5XVwco.js";
|
|
2
|
+
import { A as warnWorkloadCredentialsStripped, B as formatAuthority, C as accountLookupStsClientConfig, H as hostFromAuthority, I as proxyAwareFetch, M as workloadStsClientConfig, N as buildProxyClientConfig, R as isLoopbackHostname, V as formatHostForAuthority, _ as resolveHostDefaultCredentials, a as activateWorkloadAwsWiring, j as workloadClientConfig, l as effectiveLoopbackPorts, o as applyWorkloadAwsWiringToEnv, s as awsEmulatorEnvName, u as getActiveWorkloadAwsWiring, w as applyWorkloadEnvCredentials, z as isWildcardHostname } from "./workload-aws-wiring-BIxf0jtl.js";
|
|
3
|
+
import { c as clampErrorName, d as flattenToOneLine, f as isAwsServiceException, l as describeAwsFailureForWarn, m as stringifyThrown, o as renderAssemblyPathEscape, p as sanitizeServiceExceptionMessage, r as displayUntrustedValue, s as resolveAssemblyPath, t as absoluteAssemblyPathEscape, u as describeCredentialLoadFailure } from "./assembly-path-R96uhMm1.js";
|
|
4
|
+
import { A as parseEcrRegistryHost, B as RouteDiscoveryError, C as warnIfEmulatedPlatform, D as buildDockerImage, E as pullEcrImage, F as tryResolveImageFnJoin, G as applyRoleArnIfSet, H as withErrorHandling, I as CdkLocalError, J as isIamRoleArn, K as assumeRoleCredentials, L as InteractiveTtyRequiredError, M as derivePseudoParametersFromRegion, N as formatStateRemedy, O as resolveAssetSourcePath, P as substituteImagePlaceholders, R as LocalInvokeBuildError, S as buildContainerImage, T as parseEcrUri, U as defineOwnKey, V as TargetSelectionCancelledError, W as AssumeRoleFailure, X as buildStsClientConfig, Y as refusedRoleArnMessage, Z as resolveProfileCredentials, a as describeRefusedSensitiveEnvKeys, c as execEnvForSecrets, d as pullImage, f as removeContainer, i as attachLoopbackForwarder, j as derivePartitionAndUrlSuffix, k as describeExitWithoutArgv, l as pickFreePort, m as streamLogs, n as SENSITIVE_ENV_KEYS, p as runDetached, q as describeRejectedRoleArn, r as appendEnvFlags, s as ensureDockerAvailable, t as DockerRunnerError, u as prepareLoopbackForwarder, w as isImageInLocalCache, x as architectureToPlatform, z as LocalStartServiceError } from "./docker-runner-CnXQIUjd.js";
|
|
5
|
+
import { a as isDockerClientEnvKey, c as runDockerStreaming, i as getDockerCmd, n as finchSecretArgvRefusal, o as isMalformedEnvKey, u as warnFinchArgvExposure } from "./docker-cmd-Cjg3jGYF.js";
|
|
3
6
|
import { chmodSync, cpSync, createWriteStream, existsSync, lstatSync, mkdirSync, mkdtempSync, promises, readFileSync, readdirSync, readlinkSync, realpathSync, rmSync, statSync, symlinkSync, unlinkSync, writeFileSync } from "node:fs";
|
|
4
|
-
import { homedir, hostname, tmpdir } from "node:os";
|
|
5
|
-
import * as nodePath from "node:path";
|
|
6
|
-
import path, { basename, dirname, isAbsolute, join, normalize, relative, resolve, sep } from "node:path";
|
|
7
7
|
import { Command, InvalidArgumentError, Option } from "commander";
|
|
8
|
-
import {
|
|
8
|
+
import { STSClient } from "@aws-sdk/client-sts";
|
|
9
9
|
import * as nodeCrypto from "node:crypto";
|
|
10
10
|
import { X509Certificate, createHash, createHmac, createPublicKey, createVerify, randomBytes, randomUUID, timingSafeEqual } from "node:crypto";
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
13
|
-
import
|
|
14
|
-
import {
|
|
15
|
-
import {
|
|
16
|
-
import { HttpProxyAgent } from "http-proxy-agent";
|
|
17
|
-
import { HttpsProxyAgent } from "https-proxy-agent";
|
|
18
|
-
import { getProxyForUrl } from "proxy-from-env";
|
|
11
|
+
import { createServer, request } from "node:http";
|
|
12
|
+
import { createServer as createServer$1 } from "node:https";
|
|
13
|
+
import * as nodePath from "node:path";
|
|
14
|
+
import path, { basename, dirname, isAbsolute, join, normalize, relative, resolve, sep } from "node:path";
|
|
15
|
+
import { homedir, hostname, tmpdir } from "node:os";
|
|
19
16
|
import { GetSecretValueCommand, SecretsManagerClient } from "@aws-sdk/client-secrets-manager";
|
|
20
17
|
import { GetParameterCommand, GetParametersCommand, SSMClient } from "@aws-sdk/client-ssm";
|
|
21
18
|
import { unzipSync } from "fflate";
|
|
@@ -25,10 +22,8 @@ import { CloudFormationClient, DescribeStacksCommand, ListExportsCommand, ListSt
|
|
|
25
22
|
import { GetFunctionConfigurationCommand, LambdaClient } from "@aws-sdk/client-lambda";
|
|
26
23
|
import { BedrockAgentCoreControlClient, GetAgentRuntimeCommand } from "@aws-sdk/client-bedrock-agentcore-control";
|
|
27
24
|
import { execFile, spawn } from "node:child_process";
|
|
28
|
-
import { connect
|
|
29
|
-
import { StringDecoder } from "node:string_decoder";
|
|
25
|
+
import { connect } from "node:net";
|
|
30
26
|
import { promisify } from "node:util";
|
|
31
|
-
import { ECRClient, GetAuthorizationTokenCommand } from "@aws-sdk/client-ecr";
|
|
32
27
|
import { readFile } from "fs/promises";
|
|
33
28
|
import { basename as basename$1, dirname as dirname$1, isAbsolute as isAbsolute$1, join as join$1, posix, relative as relative$1, resolve as resolve$1, sep as sep$1 } from "path";
|
|
34
29
|
import { WebSocket, WebSocketServer } from "ws";
|
|
@@ -53,603 +48,6 @@ import { promisify as promisify$1 } from "util";
|
|
|
53
48
|
import { randomUUID as randomUUID$1 } from "crypto";
|
|
54
49
|
import { EventEmitter } from "node:events";
|
|
55
50
|
|
|
56
|
-
//#region src/utils/url-authority.ts
|
|
57
|
-
const IPV6_LITERAL_CHARS = /^[0-9A-Fa-f:.]+$/;
|
|
58
|
-
function formatHostForAuthority(host) {
|
|
59
|
-
const inner = host.length > 1 && host.startsWith("[") && host.endsWith("]") ? host.slice(1, -1) : host;
|
|
60
|
-
if (!inner.includes(":")) return host;
|
|
61
|
-
const zoneAt = inner.indexOf("%");
|
|
62
|
-
const literal = zoneAt === -1 ? inner : inner.slice(0, zoneAt);
|
|
63
|
-
if (!IPV6_LITERAL_CHARS.test(literal)) return host;
|
|
64
|
-
return `[${literal}]`;
|
|
65
|
-
}
|
|
66
|
-
function formatAuthority(host, port) {
|
|
67
|
-
return `${formatHostForAuthority(host)}:${port}`;
|
|
68
|
-
}
|
|
69
|
-
function hostFromAuthority(authority) {
|
|
70
|
-
if (authority.startsWith("[")) {
|
|
71
|
-
const close = authority.indexOf("]");
|
|
72
|
-
if (close === -1) return "";
|
|
73
|
-
const afterBracket = authority.slice(close + 1);
|
|
74
|
-
if (afterBracket !== "" && !/^:\d+$/.test(afterBracket)) return "";
|
|
75
|
-
return authority.slice(1, close);
|
|
76
|
-
}
|
|
77
|
-
const firstColon = authority.indexOf(":");
|
|
78
|
-
if (firstColon === -1) return authority;
|
|
79
|
-
if (authority.includes(":", firstColon + 1)) return "";
|
|
80
|
-
return authority.slice(0, firstColon);
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
//#endregion
|
|
84
|
-
//#region src/utils/loopback-host.ts
|
|
85
|
-
function normaliseHostLiteral(hostname) {
|
|
86
|
-
return hostname.trim().replace(/^\[/, "").replace(/\]$/, "").toLowerCase();
|
|
87
|
-
}
|
|
88
|
-
function isLoopbackLiteral(h) {
|
|
89
|
-
if (h === "localhost") return true;
|
|
90
|
-
if (h === "::1" || h === "0:0:0:0:0:0:0:1") return true;
|
|
91
|
-
const mapped = /^::ffff:([0-9a-f]{1,4}):([0-9a-f]{1,4})$/.exec(h);
|
|
92
|
-
if (mapped) return parseInt(mapped[1], 16) >> 8 === 127;
|
|
93
|
-
const dotted = /^(?:::ffff:)?(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/.exec(h);
|
|
94
|
-
if (!dotted) return false;
|
|
95
|
-
const octets = dotted.slice(1).map(Number);
|
|
96
|
-
if (octets.some((o) => o > 255)) return false;
|
|
97
|
-
return octets[0] === 127;
|
|
98
|
-
}
|
|
99
|
-
function isWildcardLiteral(h) {
|
|
100
|
-
return h === "0.0.0.0" || h === "::" || h === "0:0:0:0:0:0:0:0" || h === "::ffff:0.0.0.0" || h === "::ffff:0:0";
|
|
101
|
-
}
|
|
102
|
-
function isLoopbackHostname(hostname) {
|
|
103
|
-
return isLoopbackLiteral(normaliseHostLiteral(hostname));
|
|
104
|
-
}
|
|
105
|
-
function isWildcardHostname(hostname) {
|
|
106
|
-
return isWildcardLiteral(normaliseHostLiteral(hostname));
|
|
107
|
-
}
|
|
108
|
-
function isLoopbackHost(hostname) {
|
|
109
|
-
const h = normaliseHostLiteral(hostname).replace(/\.$/, "");
|
|
110
|
-
return h.endsWith(".localhost") || isLoopbackLiteral(h) || isWildcardLiteral(h);
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
//#endregion
|
|
114
|
-
//#region src/utils/aws-proxy.ts
|
|
115
|
-
const AGENT_OPTS = {
|
|
116
|
-
keepAlive: true,
|
|
117
|
-
maxSockets: 50
|
|
118
|
-
};
|
|
119
|
-
function isProxyEnvConfigured() {
|
|
120
|
-
return PROXY_ENV_VARIABLES.some((key) => Boolean(process.env[key]));
|
|
121
|
-
}
|
|
122
|
-
const PROXY_ENV_VARIABLES = [
|
|
123
|
-
"https_proxy",
|
|
124
|
-
"HTTPS_PROXY",
|
|
125
|
-
"http_proxy",
|
|
126
|
-
"HTTP_PROXY",
|
|
127
|
-
"all_proxy",
|
|
128
|
-
"ALL_PROXY"
|
|
129
|
-
];
|
|
130
|
-
function isSpeakableProxyEnvValue(value) {
|
|
131
|
-
return !value.includes("://") || isSpeakableProxy(value.trim());
|
|
132
|
-
}
|
|
133
|
-
const AWS_ENDPOINT_PROBES = ["https://sts.amazonaws.com", "http://sts.amazonaws.com"];
|
|
134
|
-
function everySetProxyEnvValueIsUnspeakable() {
|
|
135
|
-
const set = PROXY_ENV_VARIABLES.map((key) => process.env[key] ?? "").filter((v) => v !== "");
|
|
136
|
-
return set.length > 0 && !set.some(isSpeakableProxyEnvValue);
|
|
137
|
-
}
|
|
138
|
-
const warnedProxySchemes = /* @__PURE__ */ new Set();
|
|
139
|
-
function proxySchemeOf(proxyUrl) {
|
|
140
|
-
const match = /^([a-z][a-z0-9+.-]{0,31}):\/\//i.exec(proxyUrl);
|
|
141
|
-
return match ? match[1].toLowerCase() : "(unrecognized)";
|
|
142
|
-
}
|
|
143
|
-
function isSpeakableProxy(proxyUrl) {
|
|
144
|
-
return /^https?:\/\//i.test(proxyUrl);
|
|
145
|
-
}
|
|
146
|
-
function warnUnspeakableProxy(proxyUrl) {
|
|
147
|
-
const scheme = proxySchemeOf(proxyUrl);
|
|
148
|
-
if (warnedProxySchemes.has(scheme)) return;
|
|
149
|
-
try {
|
|
150
|
-
getLogger().child("aws-proxy").warn(`Unsupported proxy scheme "${scheme}" — cdk-local speaks HTTP CONNECT proxies only, so requests it would carry go DIRECT instead of through the proxy. Set HTTPS_PROXY / HTTP_PROXY / ALL_PROXY to an http:// or https:// proxy URL. (The proxy URL is withheld here: it can carry credentials.)`);
|
|
151
|
-
} catch {
|
|
152
|
-
return;
|
|
153
|
-
}
|
|
154
|
-
warnedProxySchemes.add(scheme);
|
|
155
|
-
}
|
|
156
|
-
function resolveProxyForTarget(targetHref) {
|
|
157
|
-
const proxyUrl = getProxyForUrl(targetHref).trim();
|
|
158
|
-
if (proxyUrl === "") return "";
|
|
159
|
-
if (isSpeakableProxy(proxyUrl)) return proxyUrl;
|
|
160
|
-
warnUnspeakableProxy(proxyUrl);
|
|
161
|
-
return "";
|
|
162
|
-
}
|
|
163
|
-
var EnvRoutingProxyAgent = class extends Agent$2 {
|
|
164
|
-
proxyAgents = /* @__PURE__ */ new Map();
|
|
165
|
-
directHttpAgent = new Agent(AGENT_OPTS);
|
|
166
|
-
directHttpsAgent = new Agent$1(AGENT_OPTS);
|
|
167
|
-
constructor() {
|
|
168
|
-
super(AGENT_OPTS);
|
|
169
|
-
}
|
|
170
|
-
connect(_req, options) {
|
|
171
|
-
const secure = options.secureEndpoint;
|
|
172
|
-
const host = options.host ?? "localhost";
|
|
173
|
-
const port = options.port || (secure ? 443 : 80);
|
|
174
|
-
const proxyUrl = resolveProxyForTarget(`${secure ? "https" : "http"}://${formatAuthority(host, port)}`);
|
|
175
|
-
if (!proxyUrl) return secure ? this.directHttpsAgent : this.directHttpAgent;
|
|
176
|
-
const key = `${secure ? "https" : "http"}|${proxyUrl}`;
|
|
177
|
-
let agent = this.proxyAgents.get(key);
|
|
178
|
-
if (!agent) {
|
|
179
|
-
agent = secure ? new HttpsProxyAgent(proxyUrl, AGENT_OPTS) : new HttpProxyAgent(proxyUrl, AGENT_OPTS);
|
|
180
|
-
this.proxyAgents.set(key, agent);
|
|
181
|
-
}
|
|
182
|
-
return agent;
|
|
183
|
-
}
|
|
184
|
-
destroy() {
|
|
185
|
-
for (const agent of this.proxyAgents.values()) agent.destroy();
|
|
186
|
-
this.proxyAgents.clear();
|
|
187
|
-
this.directHttpAgent.destroy();
|
|
188
|
-
this.directHttpsAgent.destroy();
|
|
189
|
-
super.destroy();
|
|
190
|
-
}
|
|
191
|
-
};
|
|
192
|
-
function buildProxyRequestHandler() {
|
|
193
|
-
const agent = new EnvRoutingProxyAgent();
|
|
194
|
-
return new NodeHttpHandler({
|
|
195
|
-
httpAgent: agent,
|
|
196
|
-
httpsAgent: agent
|
|
197
|
-
});
|
|
198
|
-
}
|
|
199
|
-
function buildProxyClientConfig(opts = {}) {
|
|
200
|
-
if (!isProxyEnvConfigured()) return {};
|
|
201
|
-
if (everySetProxyEnvValueIsUnspeakable()) {
|
|
202
|
-
for (const probe of AWS_ENDPOINT_PROBES) resolveProxyForTarget(probe);
|
|
203
|
-
return {};
|
|
204
|
-
}
|
|
205
|
-
const profile = opts.profile;
|
|
206
|
-
let chain;
|
|
207
|
-
const credentials = async (identityProperties) => {
|
|
208
|
-
chain ??= (async () => {
|
|
209
|
-
const { defaultProvider } = await import("@aws-sdk/credential-provider-node");
|
|
210
|
-
return defaultProvider({
|
|
211
|
-
...profile ? { profile } : {},
|
|
212
|
-
clientConfig: { requestHandler: buildProxyRequestHandler() }
|
|
213
|
-
});
|
|
214
|
-
})().catch((err) => {
|
|
215
|
-
chain = void 0;
|
|
216
|
-
throw err;
|
|
217
|
-
});
|
|
218
|
-
return (await chain)(identityProperties);
|
|
219
|
-
};
|
|
220
|
-
return {
|
|
221
|
-
requestHandler: buildProxyRequestHandler(),
|
|
222
|
-
credentials
|
|
223
|
-
};
|
|
224
|
-
}
|
|
225
|
-
const MAX_FETCH_REDIRECTS = 20;
|
|
226
|
-
const NULL_BODY_STATUSES = /* @__PURE__ */ new Set([
|
|
227
|
-
204,
|
|
228
|
-
205,
|
|
229
|
-
304
|
|
230
|
-
]);
|
|
231
|
-
const REQUEST_STALL_TIMEOUT_MS = 3e5;
|
|
232
|
-
function isRedirectStatus(status) {
|
|
233
|
-
return status === 301 || status === 302 || status === 303 || status === 307 || status === 308;
|
|
234
|
-
}
|
|
235
|
-
function parseHttpUrl(href) {
|
|
236
|
-
const parsed = new URL(href);
|
|
237
|
-
if (parsed.protocol !== "http:" && parsed.protocol !== "https:") throw new TypeError(`Unsupported protocol for a proxied request: "${parsed.protocol}"`);
|
|
238
|
-
return parsed;
|
|
239
|
-
}
|
|
240
|
-
function getThroughAgent(url, agent, timeoutMs = REQUEST_STALL_TIMEOUT_MS) {
|
|
241
|
-
return new Promise((resolve, reject) => {
|
|
242
|
-
let settled = false;
|
|
243
|
-
let timer;
|
|
244
|
-
let rearm = () => void 0;
|
|
245
|
-
const succeed = (value) => {
|
|
246
|
-
if (settled) return;
|
|
247
|
-
settled = true;
|
|
248
|
-
if (timer) clearTimeout(timer);
|
|
249
|
-
resolve(value);
|
|
250
|
-
};
|
|
251
|
-
const fail = (err) => {
|
|
252
|
-
if (settled) return;
|
|
253
|
-
settled = true;
|
|
254
|
-
if (timer) clearTimeout(timer);
|
|
255
|
-
reject(err);
|
|
256
|
-
};
|
|
257
|
-
const req = (url.protocol === "https:" ? request$1 : request)(url, {
|
|
258
|
-
agent,
|
|
259
|
-
headers: {
|
|
260
|
-
accept: "*/*",
|
|
261
|
-
"accept-encoding": "identity"
|
|
262
|
-
}
|
|
263
|
-
}, (res) => {
|
|
264
|
-
rearm();
|
|
265
|
-
const chunks = [];
|
|
266
|
-
res.on("data", (chunk) => {
|
|
267
|
-
rearm();
|
|
268
|
-
chunks.push(chunk);
|
|
269
|
-
});
|
|
270
|
-
res.on("error", fail);
|
|
271
|
-
res.on("end", () => {
|
|
272
|
-
if (res.statusCode === void 0) {
|
|
273
|
-
fail(/* @__PURE__ */ new Error("Malformed HTTP response: no status code"));
|
|
274
|
-
return;
|
|
275
|
-
}
|
|
276
|
-
succeed({
|
|
277
|
-
status: res.statusCode,
|
|
278
|
-
statusText: res.statusMessage ?? "",
|
|
279
|
-
headers: res.headers,
|
|
280
|
-
body: Buffer.concat(chunks)
|
|
281
|
-
});
|
|
282
|
-
});
|
|
283
|
-
});
|
|
284
|
-
req.on("error", fail);
|
|
285
|
-
rearm = () => {
|
|
286
|
-
if (settled) return;
|
|
287
|
-
if (timer) clearTimeout(timer);
|
|
288
|
-
timer = setTimeout(() => {
|
|
289
|
-
req.destroy();
|
|
290
|
-
fail(/* @__PURE__ */ new Error(`Proxied request stalled for ${timeoutMs} ms with no progress`));
|
|
291
|
-
}, timeoutMs);
|
|
292
|
-
timer.unref?.();
|
|
293
|
-
};
|
|
294
|
-
rearm();
|
|
295
|
-
req.end();
|
|
296
|
-
});
|
|
297
|
-
}
|
|
298
|
-
function decodeContentEncoding(raw) {
|
|
299
|
-
const header = raw.headers["content-encoding"];
|
|
300
|
-
const encoding = (Array.isArray(header) ? header.join(",") : header ?? "").trim().toLowerCase();
|
|
301
|
-
if (encoding === "" || encoding === "identity") return {
|
|
302
|
-
body: raw.body,
|
|
303
|
-
decoded: false
|
|
304
|
-
};
|
|
305
|
-
try {
|
|
306
|
-
if (encoding === "gzip" || encoding === "x-gzip") return {
|
|
307
|
-
body: gunzipSync(raw.body),
|
|
308
|
-
decoded: true
|
|
309
|
-
};
|
|
310
|
-
if (encoding === "deflate" || encoding === "x-deflate") return {
|
|
311
|
-
body: inflateSync(raw.body),
|
|
312
|
-
decoded: true
|
|
313
|
-
};
|
|
314
|
-
if (encoding === "br") return {
|
|
315
|
-
body: brotliDecompressSync(raw.body),
|
|
316
|
-
decoded: true
|
|
317
|
-
};
|
|
318
|
-
} catch {
|
|
319
|
-
return {
|
|
320
|
-
body: raw.body,
|
|
321
|
-
decoded: false
|
|
322
|
-
};
|
|
323
|
-
}
|
|
324
|
-
return {
|
|
325
|
-
body: raw.body,
|
|
326
|
-
decoded: false
|
|
327
|
-
};
|
|
328
|
-
}
|
|
329
|
-
function toWebResponse(raw) {
|
|
330
|
-
if (raw.status < 200 || raw.status > 599) throw new Error(`Unsupported HTTP status in response: ${raw.status}`);
|
|
331
|
-
const { body, decoded } = decodeContentEncoding(raw);
|
|
332
|
-
const headers = new Headers();
|
|
333
|
-
for (const [name, value] of Object.entries(raw.headers)) {
|
|
334
|
-
if (value === void 0) continue;
|
|
335
|
-
if (decoded && (name === "content-encoding" || name === "content-length")) continue;
|
|
336
|
-
if (Array.isArray(value)) for (const one of value) headers.append(name, one);
|
|
337
|
-
else headers.append(name, value);
|
|
338
|
-
}
|
|
339
|
-
return new Response(NULL_BODY_STATUSES.has(raw.status) ? null : body, {
|
|
340
|
-
status: raw.status,
|
|
341
|
-
statusText: raw.statusText.replace(/[^\t\x20-\x7e\x80-\xff]/g, ""),
|
|
342
|
-
headers
|
|
343
|
-
});
|
|
344
|
-
}
|
|
345
|
-
async function proxyAwareFetch(url, opts = {}) {
|
|
346
|
-
if (!isProxyEnvConfigured()) return globalThis.fetch(url);
|
|
347
|
-
let target = parseHttpUrl(url);
|
|
348
|
-
for (let hop = 0;; hop++) {
|
|
349
|
-
if (isLoopbackHost(target.hostname) || resolveProxyForTarget(target.href) === "") return globalThis.fetch(target.href);
|
|
350
|
-
const agent = new EnvRoutingProxyAgent();
|
|
351
|
-
let raw;
|
|
352
|
-
try {
|
|
353
|
-
raw = await getThroughAgent(target, agent, opts.timeoutMs);
|
|
354
|
-
} finally {
|
|
355
|
-
agent.destroy();
|
|
356
|
-
}
|
|
357
|
-
const location = raw.headers["location"];
|
|
358
|
-
if (!isRedirectStatus(raw.status) || typeof location !== "string" || location === "") return toWebResponse(raw);
|
|
359
|
-
if (hop >= MAX_FETCH_REDIRECTS) throw new Error(`Too many redirects (more than ${MAX_FETCH_REDIRECTS})`);
|
|
360
|
-
target = parseHttpUrl(new URL(location, target).href);
|
|
361
|
-
}
|
|
362
|
-
}
|
|
363
|
-
|
|
364
|
-
//#endregion
|
|
365
|
-
//#region src/utils/profile-resolver.ts
|
|
366
|
-
async function resolveProfileCredentials(profile) {
|
|
367
|
-
const sts = new STSClient(buildStsClientConfig({ profile }));
|
|
368
|
-
try {
|
|
369
|
-
const credsProvider = sts.config.credentials;
|
|
370
|
-
const creds = typeof credsProvider === "function" ? await credsProvider() : credsProvider;
|
|
371
|
-
if (!creds || !creds.accessKeyId || !creds.secretAccessKey) {
|
|
372
|
-
const ssoHint = isPasteableCommandArg(profile) ? "Check `aws sso login --profile " + profile + "` for SSO profiles" : "For an SSO profile, run `aws sso login` for that profile (the command is not written out because the name as rendered may not be the one your shell would act on)";
|
|
373
|
-
throw new Error(`--profile ${displayUntrustedValue(profile)}: credential provider chain resolved without usable credentials. ${ssoHint}, or check \`~/.aws/credentials\` / \`~/.aws/config\` for regular profiles.`);
|
|
374
|
-
}
|
|
375
|
-
let region;
|
|
376
|
-
try {
|
|
377
|
-
const regionProvider = sts.config.region;
|
|
378
|
-
const resolved = typeof regionProvider === "function" ? await regionProvider() : regionProvider;
|
|
379
|
-
if (typeof resolved === "string" && resolved.length > 0) region = resolved;
|
|
380
|
-
} catch (err) {
|
|
381
|
-
const msg = err instanceof Error ? err.message : String(err);
|
|
382
|
-
if (!(/region is missing/i.test(msg) || /could not resolve region/i.test(msg) || /no region in config/i.test(msg) || /region.*not.*set/i.test(msg))) throw err;
|
|
383
|
-
region = void 0;
|
|
384
|
-
}
|
|
385
|
-
return {
|
|
386
|
-
accessKeyId: creds.accessKeyId,
|
|
387
|
-
secretAccessKey: creds.secretAccessKey,
|
|
388
|
-
...creds.sessionToken && { sessionToken: creds.sessionToken },
|
|
389
|
-
...region && { region }
|
|
390
|
-
};
|
|
391
|
-
} finally {
|
|
392
|
-
sts.destroy();
|
|
393
|
-
}
|
|
394
|
-
}
|
|
395
|
-
function buildStsClientConfig(args) {
|
|
396
|
-
return {
|
|
397
|
-
...buildProxyClientConfig({ profile: args.profile }),
|
|
398
|
-
...args.region && { region: args.region },
|
|
399
|
-
...args.profile && { profile: args.profile }
|
|
400
|
-
};
|
|
401
|
-
}
|
|
402
|
-
|
|
403
|
-
//#endregion
|
|
404
|
-
//#region src/utils/workload-identity.ts
|
|
405
|
-
function copyCredentials(c) {
|
|
406
|
-
return c ? {
|
|
407
|
-
accessKeyId: c.accessKeyId,
|
|
408
|
-
secretAccessKey: c.secretAccessKey,
|
|
409
|
-
...c.sessionToken ? { sessionToken: c.sessionToken } : {}
|
|
410
|
-
} : void 0;
|
|
411
|
-
}
|
|
412
|
-
let record;
|
|
413
|
-
let stripWarned = false;
|
|
414
|
-
const SECOND_ASSUME_MESSAGE = "A role was already assumed in this process; refusing to assume a second one. Pass --role-arn once.";
|
|
415
|
-
function recordAssumedRole(caller, role) {
|
|
416
|
-
if (record !== void 0) throw new Error(SECOND_ASSUME_MESSAGE);
|
|
417
|
-
record = {
|
|
418
|
-
caller: copyCredentials(caller),
|
|
419
|
-
role: copyCredentials(role)
|
|
420
|
-
};
|
|
421
|
-
}
|
|
422
|
-
function assumedRoleRecorded() {
|
|
423
|
-
return record !== void 0;
|
|
424
|
-
}
|
|
425
|
-
function readEnvCallerCredentials(env = process.env) {
|
|
426
|
-
const accessKeyId = env["AWS_ACCESS_KEY_ID"];
|
|
427
|
-
const secretAccessKey = env["AWS_SECRET_ACCESS_KEY"];
|
|
428
|
-
if (!accessKeyId || !secretAccessKey) return void 0;
|
|
429
|
-
const sessionToken = env["AWS_SESSION_TOKEN"];
|
|
430
|
-
return {
|
|
431
|
-
accessKeyId,
|
|
432
|
-
secretAccessKey,
|
|
433
|
-
...sessionToken ? { sessionToken } : {}
|
|
434
|
-
};
|
|
435
|
-
}
|
|
436
|
-
function resetWorkloadIdentity() {
|
|
437
|
-
record = void 0;
|
|
438
|
-
stripWarned = false;
|
|
439
|
-
}
|
|
440
|
-
function callerRecord() {
|
|
441
|
-
return getEmbedConfig().workloadIdentity === "caller" ? record : void 0;
|
|
442
|
-
}
|
|
443
|
-
const MULTIPLE_CREDENTIAL_SOURCES_WARNING = "Multiple credential sources detected";
|
|
444
|
-
const chainLogger = {
|
|
445
|
-
debug: () => {},
|
|
446
|
-
info: () => {},
|
|
447
|
-
warn: (...args) => {
|
|
448
|
-
const text = args.map(String).join(" ");
|
|
449
|
-
if (text.includes(MULTIPLE_CREDENTIAL_SOURCES_WARNING)) return;
|
|
450
|
-
getLogger().warn(text);
|
|
451
|
-
},
|
|
452
|
-
error: (...args) => {
|
|
453
|
-
getLogger().error(args.map(String).join(" "));
|
|
454
|
-
}
|
|
455
|
-
};
|
|
456
|
-
function callerChainWithoutEnv(proxied) {
|
|
457
|
-
let chain;
|
|
458
|
-
return async (identityProperties) => {
|
|
459
|
-
chain ??= (async () => {
|
|
460
|
-
const { defaultProvider } = await import("@aws-sdk/credential-provider-node");
|
|
461
|
-
return defaultProvider({
|
|
462
|
-
profile: "default",
|
|
463
|
-
logger: chainLogger,
|
|
464
|
-
...proxied ? { clientConfig: { requestHandler: buildProxyRequestHandler() } } : {}
|
|
465
|
-
});
|
|
466
|
-
})().catch((err) => {
|
|
467
|
-
chain = void 0;
|
|
468
|
-
throw err;
|
|
469
|
-
});
|
|
470
|
-
return (await chain)(identityProperties);
|
|
471
|
-
};
|
|
472
|
-
}
|
|
473
|
-
function workloadClientConfig(opts = {}) {
|
|
474
|
-
const base = buildProxyClientConfig({ profile: opts.profile });
|
|
475
|
-
const rec = callerRecord();
|
|
476
|
-
if (!rec) return base;
|
|
477
|
-
if (opts.profile || process.env["AWS_PROFILE"]) return base;
|
|
478
|
-
if (rec.caller) {
|
|
479
|
-
const caller = rec.caller;
|
|
480
|
-
const credentials = async () => ({
|
|
481
|
-
accessKeyId: caller.accessKeyId,
|
|
482
|
-
secretAccessKey: caller.secretAccessKey,
|
|
483
|
-
...caller.sessionToken ? { sessionToken: caller.sessionToken } : {}
|
|
484
|
-
});
|
|
485
|
-
return {
|
|
486
|
-
...base,
|
|
487
|
-
credentials
|
|
488
|
-
};
|
|
489
|
-
}
|
|
490
|
-
return {
|
|
491
|
-
...base,
|
|
492
|
-
credentials: callerChainWithoutEnv(base.requestHandler !== void 0)
|
|
493
|
-
};
|
|
494
|
-
}
|
|
495
|
-
function workloadStsClientConfig(args) {
|
|
496
|
-
return {
|
|
497
|
-
...workloadClientConfig({ profile: args.profile }),
|
|
498
|
-
...args.region && { region: args.region },
|
|
499
|
-
...args.profile && { profile: args.profile }
|
|
500
|
-
};
|
|
501
|
-
}
|
|
502
|
-
function deployAccountStsClientConfig(args) {
|
|
503
|
-
const role = callerRecord()?.role;
|
|
504
|
-
if (!role) return {
|
|
505
|
-
...buildProxyClientConfig({ profile: args.profile }),
|
|
506
|
-
...args.region && { region: args.region },
|
|
507
|
-
...args.profile && { profile: args.profile }
|
|
508
|
-
};
|
|
509
|
-
const credentials = async () => ({
|
|
510
|
-
accessKeyId: role.accessKeyId,
|
|
511
|
-
secretAccessKey: role.secretAccessKey,
|
|
512
|
-
...role.sessionToken ? { sessionToken: role.sessionToken } : {}
|
|
513
|
-
});
|
|
514
|
-
return {
|
|
515
|
-
...buildProxyClientConfig(),
|
|
516
|
-
...args.region && { region: args.region },
|
|
517
|
-
...args.profile && { profile: args.profile },
|
|
518
|
-
credentials
|
|
519
|
-
};
|
|
520
|
-
}
|
|
521
|
-
function accountLookupStsClientConfig(args) {
|
|
522
|
-
return args.readFromCfnStack ? workloadStsClientConfig({
|
|
523
|
-
region: args.region,
|
|
524
|
-
profile: args.profile
|
|
525
|
-
}) : deployAccountStsClientConfig({
|
|
526
|
-
region: args.region,
|
|
527
|
-
profile: args.profile
|
|
528
|
-
});
|
|
529
|
-
}
|
|
530
|
-
function applyWorkloadEnvCredentials(env) {
|
|
531
|
-
const rec = callerRecord();
|
|
532
|
-
if (!rec) return "unchanged";
|
|
533
|
-
if (rec.caller) {
|
|
534
|
-
env["AWS_ACCESS_KEY_ID"] = rec.caller.accessKeyId;
|
|
535
|
-
env["AWS_SECRET_ACCESS_KEY"] = rec.caller.secretAccessKey;
|
|
536
|
-
if (rec.caller.sessionToken) env["AWS_SESSION_TOKEN"] = rec.caller.sessionToken;
|
|
537
|
-
else delete env["AWS_SESSION_TOKEN"];
|
|
538
|
-
return "restored";
|
|
539
|
-
}
|
|
540
|
-
delete env["AWS_ACCESS_KEY_ID"];
|
|
541
|
-
delete env["AWS_SECRET_ACCESS_KEY"];
|
|
542
|
-
delete env["AWS_SESSION_TOKEN"];
|
|
543
|
-
return "stripped";
|
|
544
|
-
}
|
|
545
|
-
function warnWorkloadCredentialsStripped() {
|
|
546
|
-
if (stripWarned) return;
|
|
547
|
-
stripWarned = true;
|
|
548
|
-
getLogger().warn("The --role-arn role is not handed to the emulated workload, and your shell had no static AWS credentials to hand it instead, so the container receives none. Pass --profile <name>, or export static credentials, to give it an identity.");
|
|
549
|
-
}
|
|
550
|
-
|
|
551
|
-
//#endregion
|
|
552
|
-
//#region src/utils/role-arn.ts
|
|
553
|
-
const IAM_ROLE_ARN_MAX_LENGTH = 2048;
|
|
554
|
-
const IAM_ROLE_ARN_PATTERN = /^arn:[A-Za-z0-9-]+:iam::[0-9]+:role\/[!-~]+$/;
|
|
555
|
-
function isIamRoleArn(value) {
|
|
556
|
-
if (typeof value !== "string") return false;
|
|
557
|
-
if (value.length > 2048) return false;
|
|
558
|
-
return IAM_ROLE_ARN_PATTERN.test(value);
|
|
559
|
-
}
|
|
560
|
-
const REJECTED_ARN_PREVIEW_MAX = 128;
|
|
561
|
-
function describeRejectedRoleArn(value) {
|
|
562
|
-
if (typeof value !== "string") return `a non-string ${typeof value} value`;
|
|
563
|
-
const points = [...flattenToOneLine(value)];
|
|
564
|
-
return `"${points.length <= REJECTED_ARN_PREVIEW_MAX ? points.join("") : `${points.slice(0, REJECTED_ARN_PREVIEW_MAX).join("")}...`}" (${points.length} characters)`;
|
|
565
|
-
}
|
|
566
|
-
function refusedRoleArnMessage(value) {
|
|
567
|
-
return `AssumeRole refused: the role ARN is not a well-formed IAM role ARN (expected arn:<partition>:iam::<account>:role/<name>, at most ${IAM_ROLE_ARN_MAX_LENGTH} characters): ${describeRejectedRoleArn(value)}. Nothing was sent to STS.`;
|
|
568
|
-
}
|
|
569
|
-
var AssumeRoleFailure = class AssumeRoleFailure extends Error {
|
|
570
|
-
detail;
|
|
571
|
-
constructor(message, detail) {
|
|
572
|
-
super(message);
|
|
573
|
-
this.name = "AssumeRoleFailure";
|
|
574
|
-
this.detail = detail;
|
|
575
|
-
Object.setPrototypeOf(this, AssumeRoleFailure.prototype);
|
|
576
|
-
}
|
|
577
|
-
};
|
|
578
|
-
async function assumeRoleCredentials(opts) {
|
|
579
|
-
if (!isIamRoleArn(opts.roleArn)) {
|
|
580
|
-
const detail = `the role ARN is not well-formed: ${describeRejectedRoleArn(opts.roleArn)}`;
|
|
581
|
-
const message = refusedRoleArnMessage(opts.roleArn);
|
|
582
|
-
throw opts.makeError ? opts.makeError(message) : new AssumeRoleFailure(message, detail);
|
|
583
|
-
}
|
|
584
|
-
const sts = new STSClient(workloadStsClientConfig({
|
|
585
|
-
region: opts.region,
|
|
586
|
-
profile: opts.profile
|
|
587
|
-
}));
|
|
588
|
-
const shownArn = flattenToOneLine(opts.roleArn);
|
|
589
|
-
let response;
|
|
590
|
-
try {
|
|
591
|
-
response = await sts.send(new AssumeRoleCommand({
|
|
592
|
-
RoleArn: opts.roleArn,
|
|
593
|
-
RoleSessionName: `${getEmbedConfig().resourceNamePrefix}-${opts.sessionNameSuffix}-${Date.now()}`,
|
|
594
|
-
DurationSeconds: 3600
|
|
595
|
-
}));
|
|
596
|
-
} catch (err) {
|
|
597
|
-
const detail = describeAwsFailureForWarn(err, "STS AssumeRole");
|
|
598
|
-
const message = `AssumeRole(${shownArn}) failed: ${detail}`;
|
|
599
|
-
throw opts.makeError ? opts.makeError(message) : new AssumeRoleFailure(message, detail);
|
|
600
|
-
} finally {
|
|
601
|
-
sts.destroy();
|
|
602
|
-
}
|
|
603
|
-
const creds = response.Credentials;
|
|
604
|
-
if (!creds?.AccessKeyId || !creds.SecretAccessKey || !creds.SessionToken) {
|
|
605
|
-
const message = `AssumeRole(${shownArn}) returned no usable credentials.`;
|
|
606
|
-
throw opts.makeError ? opts.makeError(message) : new AssumeRoleFailure(message, "the response carried no usable credentials");
|
|
607
|
-
}
|
|
608
|
-
return {
|
|
609
|
-
accessKeyId: creds.AccessKeyId,
|
|
610
|
-
secretAccessKey: creds.SecretAccessKey,
|
|
611
|
-
sessionToken: creds.SessionToken
|
|
612
|
-
};
|
|
613
|
-
}
|
|
614
|
-
async function applyRoleArnIfSet(opts) {
|
|
615
|
-
const roleArn = opts.roleArn || process.env[`${getEmbedConfig().envPrefix}_ROLE_ARN`];
|
|
616
|
-
if (!roleArn) return;
|
|
617
|
-
if (!isIamRoleArn(roleArn)) throw new Error(refusedRoleArnMessage(roleArn));
|
|
618
|
-
if (assumedRoleRecorded() && getEmbedConfig().workloadIdentity === "caller") throw new Error(SECOND_ASSUME_MESSAGE);
|
|
619
|
-
const logger = getLogger().child("role-arn");
|
|
620
|
-
const shownArn = flattenToOneLine(roleArn);
|
|
621
|
-
logger.debug(`Assuming role ${shownArn}...`);
|
|
622
|
-
const sts = new STSClient(buildStsClientConfig({
|
|
623
|
-
region: opts.region,
|
|
624
|
-
profile: opts.profile
|
|
625
|
-
}));
|
|
626
|
-
let response;
|
|
627
|
-
try {
|
|
628
|
-
response = await sts.send(new AssumeRoleCommand({
|
|
629
|
-
RoleArn: roleArn,
|
|
630
|
-
RoleSessionName: `${getEmbedConfig().binaryName}-${Date.now()}`,
|
|
631
|
-
DurationSeconds: 3600
|
|
632
|
-
}));
|
|
633
|
-
} catch (err) {
|
|
634
|
-
throw new Error(`AssumeRole(${shownArn}) failed: ${describeAwsFailureForWarn(err, "STS AssumeRole")}`);
|
|
635
|
-
} finally {
|
|
636
|
-
sts.destroy();
|
|
637
|
-
}
|
|
638
|
-
if (!response.Credentials) throw new Error(`AssumeRole returned no credentials for role ${shownArn}`);
|
|
639
|
-
const { AccessKeyId, SecretAccessKey, SessionToken, Expiration } = response.Credentials;
|
|
640
|
-
if (!AccessKeyId || !SecretAccessKey || !SessionToken) throw new Error(`AssumeRole response missing credentials fields for role ${shownArn}`);
|
|
641
|
-
if (!assumedRoleRecorded()) recordAssumedRole(readEnvCallerCredentials(), {
|
|
642
|
-
accessKeyId: AccessKeyId,
|
|
643
|
-
secretAccessKey: SecretAccessKey,
|
|
644
|
-
sessionToken: SessionToken
|
|
645
|
-
});
|
|
646
|
-
process.env["AWS_ACCESS_KEY_ID"] = AccessKeyId;
|
|
647
|
-
process.env["AWS_SECRET_ACCESS_KEY"] = SecretAccessKey;
|
|
648
|
-
process.env["AWS_SESSION_TOKEN"] = SessionToken;
|
|
649
|
-
logger.info(`Assumed role ${shownArn} (session expires ${Expiration?.toISOString() ?? "unknown"})`);
|
|
650
|
-
}
|
|
651
|
-
|
|
652
|
-
//#endregion
|
|
653
51
|
//#region src/cli/options.ts
|
|
654
52
|
function parseContextOptions(contextArgs) {
|
|
655
53
|
const context = {};
|
|
@@ -668,6 +66,13 @@ function commonOptions() {
|
|
|
668
66
|
new Option("-y, --yes", "Automatically answer interactive prompts with the recommended response").default(false)
|
|
669
67
|
];
|
|
670
68
|
}
|
|
69
|
+
function awsEndpointOptions() {
|
|
70
|
+
return [new Option("--aws-emulator [url]", `Run against a local AWS Emulator (default https://127.0.0.1:9297; the port selects ~/.aws/emulator/<port>/): this command's own AWS calls (--from-cfn-stack included) and every workload container use it, and containers get only its credentials and trust its CA (env: ${awsEmulatorEnvName()})`), new Option("--ca-bundle <file>", "PEM CA bundle mounted read-only into every workload container, with AWS_CA_BUNDLE / NODE_EXTRA_CA_CERTS / REQUESTS_CA_BUNDLE / SSL_CERT_FILE pointed at it (default: the host AWS_CA_BUNDLE)")];
|
|
71
|
+
}
|
|
72
|
+
function addAwsEndpointOptions(cmd) {
|
|
73
|
+
for (const opt of awsEndpointOptions()) cmd.addOption(opt);
|
|
74
|
+
return cmd;
|
|
75
|
+
}
|
|
671
76
|
const regionOption = new Option("--region <region>", "AWS region for SDK calls; defaults to AWS_REGION env, the synthesized stack region, or the resolved profile region");
|
|
672
77
|
function appOptions() {
|
|
673
78
|
const { envPrefix } = getEmbedConfig();
|
|
@@ -705,17 +110,6 @@ function effectiveAssumeRoleArn(logicalId, opt) {
|
|
|
705
110
|
return opt.perLambda?.[logicalId] ?? opt.globalArn;
|
|
706
111
|
}
|
|
707
112
|
|
|
708
|
-
//#endregion
|
|
709
|
-
//#region src/utils/own-keys.ts
|
|
710
|
-
function defineOwnKey(target, key, value) {
|
|
711
|
-
Object.defineProperty(target, key, {
|
|
712
|
-
value,
|
|
713
|
-
writable: true,
|
|
714
|
-
enumerable: true,
|
|
715
|
-
configurable: true
|
|
716
|
-
});
|
|
717
|
-
}
|
|
718
|
-
|
|
719
113
|
//#endregion
|
|
720
114
|
//#region src/local/dynamic-reference-resolver.ts
|
|
721
115
|
var DynamicReferenceResolutionError = class DynamicReferenceResolutionError extends Error {
|
|
@@ -1054,86 +448,6 @@ async function resolveDynamicReferencesInEnv(env, options) {
|
|
|
1054
448
|
}
|
|
1055
449
|
}
|
|
1056
450
|
|
|
1057
|
-
//#endregion
|
|
1058
|
-
//#region src/utils/error-handler.ts
|
|
1059
|
-
var CdkLocalError = class CdkLocalError extends Error {
|
|
1060
|
-
code;
|
|
1061
|
-
cause;
|
|
1062
|
-
constructor(message, code, cause) {
|
|
1063
|
-
super(message);
|
|
1064
|
-
this.code = code;
|
|
1065
|
-
this.cause = cause;
|
|
1066
|
-
this.name = "CdkLocalError";
|
|
1067
|
-
Object.setPrototypeOf(this, CdkLocalError.prototype);
|
|
1068
|
-
}
|
|
1069
|
-
};
|
|
1070
|
-
var LocalInvokeBuildError = class LocalInvokeBuildError extends CdkLocalError {
|
|
1071
|
-
constructor(message, cause) {
|
|
1072
|
-
super(message, "LOCAL_INVOKE_BUILD_ERROR", cause);
|
|
1073
|
-
this.name = "LocalInvokeBuildError";
|
|
1074
|
-
Object.setPrototypeOf(this, LocalInvokeBuildError.prototype);
|
|
1075
|
-
}
|
|
1076
|
-
};
|
|
1077
|
-
var RouteDiscoveryError = class RouteDiscoveryError extends CdkLocalError {
|
|
1078
|
-
constructor(message, cause) {
|
|
1079
|
-
super(message, "ROUTE_DISCOVERY_ERROR", cause);
|
|
1080
|
-
this.name = "RouteDiscoveryError";
|
|
1081
|
-
Object.setPrototypeOf(this, RouteDiscoveryError.prototype);
|
|
1082
|
-
}
|
|
1083
|
-
};
|
|
1084
|
-
var LocalStartServiceError = class LocalStartServiceError extends CdkLocalError {
|
|
1085
|
-
constructor(message, cause) {
|
|
1086
|
-
super(message, "LOCAL_START_SERVICE_ERROR", cause);
|
|
1087
|
-
this.name = "LocalStartServiceError";
|
|
1088
|
-
Object.setPrototypeOf(this, LocalStartServiceError.prototype);
|
|
1089
|
-
}
|
|
1090
|
-
};
|
|
1091
|
-
var TargetSelectionCancelledError = class TargetSelectionCancelledError extends CdkLocalError {
|
|
1092
|
-
silent = true;
|
|
1093
|
-
exitCode = 130;
|
|
1094
|
-
constructor() {
|
|
1095
|
-
super("Target selection cancelled.", "TARGET_SELECTION_CANCELLED");
|
|
1096
|
-
this.name = "TargetSelectionCancelledError";
|
|
1097
|
-
Object.setPrototypeOf(this, TargetSelectionCancelledError.prototype);
|
|
1098
|
-
}
|
|
1099
|
-
};
|
|
1100
|
-
var InteractiveTtyRequiredError = class InteractiveTtyRequiredError extends CdkLocalError {
|
|
1101
|
-
constructor(message) {
|
|
1102
|
-
super(message, "INTERACTIVE_TTY_REQUIRED");
|
|
1103
|
-
this.name = "InteractiveTtyRequiredError";
|
|
1104
|
-
Object.setPrototypeOf(this, InteractiveTtyRequiredError.prototype);
|
|
1105
|
-
}
|
|
1106
|
-
};
|
|
1107
|
-
function isCdkLocalError(error) {
|
|
1108
|
-
return error instanceof CdkLocalError;
|
|
1109
|
-
}
|
|
1110
|
-
function formatError(error) {
|
|
1111
|
-
if (isCdkLocalError(error)) {
|
|
1112
|
-
let message = `${error.name}: ${error.message}`;
|
|
1113
|
-
if (error.cause) message += `\nCaused by: ${error.cause.message}`;
|
|
1114
|
-
return message;
|
|
1115
|
-
}
|
|
1116
|
-
if (error instanceof Error) return `${error.name}: ${error.message}`;
|
|
1117
|
-
return String(error);
|
|
1118
|
-
}
|
|
1119
|
-
function handleError(error) {
|
|
1120
|
-
const logger = getLogger();
|
|
1121
|
-
if (!(error instanceof CdkLocalError && error.silent)) logger.error(formatError(error));
|
|
1122
|
-
if (error instanceof Error && error.stack) logger.debug("Stack trace:", error.stack);
|
|
1123
|
-
const customExitCode = error instanceof CdkLocalError ? error.exitCode : void 0;
|
|
1124
|
-
const exitCode = typeof customExitCode === "number" ? customExitCode : 1;
|
|
1125
|
-
process.exit(exitCode);
|
|
1126
|
-
}
|
|
1127
|
-
function withErrorHandling(fn) {
|
|
1128
|
-
return async (...args) => {
|
|
1129
|
-
try {
|
|
1130
|
-
await fn(...args);
|
|
1131
|
-
} catch (error) {
|
|
1132
|
-
handleError(error);
|
|
1133
|
-
}
|
|
1134
|
-
};
|
|
1135
|
-
}
|
|
1136
|
-
|
|
1137
451
|
//#endregion
|
|
1138
452
|
//#region src/cli/cdk-path.ts
|
|
1139
453
|
function readCdkPath(resource) {
|
|
@@ -1269,301 +583,37 @@ function pathGlobMatches(pattern, subject) {
|
|
|
1269
583
|
}
|
|
1270
584
|
|
|
1271
585
|
//#endregion
|
|
1272
|
-
//#region src/
|
|
1273
|
-
function
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
regionPrefix: "us-isob-",
|
|
1290
|
-
partition: "aws-iso-b",
|
|
1291
|
-
urlSuffix: "sc2s.sgov.gov"
|
|
1292
|
-
},
|
|
1293
|
-
{
|
|
1294
|
-
regionPrefix: "us-isof-",
|
|
1295
|
-
partition: "aws-iso-f",
|
|
1296
|
-
urlSuffix: "csp.hci.ic.gov"
|
|
1297
|
-
},
|
|
1298
|
-
{
|
|
1299
|
-
regionPrefix: "us-iso-",
|
|
1300
|
-
partition: "aws-iso",
|
|
1301
|
-
urlSuffix: "c2s.ic.gov"
|
|
1302
|
-
},
|
|
1303
|
-
{
|
|
1304
|
-
regionPrefix: "eu-isoe-",
|
|
1305
|
-
partition: "aws-iso-e",
|
|
1306
|
-
urlSuffix: "cloud.adc-e.uk"
|
|
1307
|
-
},
|
|
1308
|
-
{
|
|
1309
|
-
regionPrefix: "eusc-",
|
|
1310
|
-
partition: "aws-eusc",
|
|
1311
|
-
urlSuffix: "amazonaws.eu"
|
|
586
|
+
//#region src/utils/stringify.ts
|
|
587
|
+
function stringifyValue(value) {
|
|
588
|
+
switch (typeof value) {
|
|
589
|
+
case "string": return value;
|
|
590
|
+
case "number":
|
|
591
|
+
case "boolean":
|
|
592
|
+
case "bigint": return String(value);
|
|
593
|
+
case "symbol": return value.toString();
|
|
594
|
+
case "undefined": return "undefined";
|
|
595
|
+
case "function": return value.name ? `[Function: ${value.name}]` : "[Function]";
|
|
596
|
+
case "object":
|
|
597
|
+
if (value === null) return "null";
|
|
598
|
+
try {
|
|
599
|
+
const json = JSON.stringify(value);
|
|
600
|
+
if (json !== void 0) return json;
|
|
601
|
+
} catch {}
|
|
602
|
+
return Object.prototype.toString.call(value);
|
|
1312
603
|
}
|
|
1313
|
-
];
|
|
1314
|
-
function derivePartitionAndUrlSuffix(region) {
|
|
1315
|
-
const normalized = region.toLowerCase();
|
|
1316
|
-
for (const row of PARTITION_TABLE) if (normalized.startsWith(row.regionPrefix)) return {
|
|
1317
|
-
partition: row.partition,
|
|
1318
|
-
urlSuffix: row.urlSuffix
|
|
1319
|
-
};
|
|
1320
|
-
return {
|
|
1321
|
-
partition: "aws",
|
|
1322
|
-
urlSuffix: "amazonaws.com"
|
|
1323
|
-
};
|
|
1324
604
|
}
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
}
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
const arg = raw["Fn::Join"];
|
|
1338
|
-
if (arg === void 0) return { kind: "not-applicable" };
|
|
1339
|
-
if (!Array.isArray(arg) || arg.length !== 2 || !Array.isArray(arg[1])) return {
|
|
1340
|
-
kind: "unsupported-join",
|
|
1341
|
-
reason: "Fn::Join must be [delimiter, [elements]]"
|
|
1342
|
-
};
|
|
1343
|
-
const [delimiter, elements] = arg;
|
|
1344
|
-
if (typeof delimiter !== "string") return {
|
|
1345
|
-
kind: "unsupported-join",
|
|
1346
|
-
reason: `Fn::Join delimiter must be a string, got ${typeof delimiter}`
|
|
1347
|
-
};
|
|
1348
|
-
const repoLogicalId = findEcrRepositoryRefInTree(elements, resources);
|
|
1349
|
-
const stateResources = context?.stateResources;
|
|
1350
|
-
if (repoLogicalId && !stateResources) return {
|
|
1351
|
-
kind: "needs-state",
|
|
1352
|
-
repoLogicalId
|
|
1353
|
-
};
|
|
1354
|
-
const parts = [];
|
|
1355
|
-
for (const element of elements) {
|
|
1356
|
-
const r = resolveImageIntrinsic(element, resources, context);
|
|
1357
|
-
if (r === void 0) {
|
|
1358
|
-
if (!repoLogicalId) return { kind: "not-applicable" };
|
|
1359
|
-
return {
|
|
1360
|
-
kind: "unsupported-join",
|
|
1361
|
-
reason: "one or more Fn::Join elements could not be resolved"
|
|
1362
|
-
};
|
|
1363
|
-
}
|
|
1364
|
-
parts.push(r);
|
|
1365
|
-
}
|
|
1366
|
-
return {
|
|
1367
|
-
kind: "resolved",
|
|
1368
|
-
uri: parts.join(delimiter)
|
|
1369
|
-
};
|
|
1370
|
-
}
|
|
1371
|
-
function findEcrRepositoryRefInTree(node, resources) {
|
|
1372
|
-
if (node === null || node === void 0) return void 0;
|
|
1373
|
-
if (typeof node === "string" || typeof node === "number" || typeof node === "boolean") return;
|
|
1374
|
-
if (Array.isArray(node)) {
|
|
1375
|
-
for (const item of node) {
|
|
1376
|
-
const hit = findEcrRepositoryRefInTree(item, resources);
|
|
1377
|
-
if (hit) return hit;
|
|
1378
|
-
}
|
|
1379
|
-
return;
|
|
1380
|
-
}
|
|
1381
|
-
if (typeof node !== "object") return void 0;
|
|
1382
|
-
const obj = node;
|
|
1383
|
-
if (typeof obj["Ref"] === "string") {
|
|
1384
|
-
const target = obj["Ref"];
|
|
1385
|
-
if (resources[target]?.Type === "AWS::ECR::Repository") return target;
|
|
1386
|
-
return;
|
|
1387
|
-
}
|
|
1388
|
-
const getAtt = obj["Fn::GetAtt"];
|
|
1389
|
-
if (getAtt !== void 0) {
|
|
1390
|
-
let lid;
|
|
1391
|
-
if (Array.isArray(getAtt) && typeof getAtt[0] === "string") lid = getAtt[0];
|
|
1392
|
-
else if (typeof getAtt === "string") lid = getAtt.split(".")[0];
|
|
1393
|
-
if (lid && resources[lid]?.Type === "AWS::ECR::Repository") return lid;
|
|
1394
|
-
return;
|
|
1395
|
-
}
|
|
1396
|
-
for (const value of Object.values(obj)) {
|
|
1397
|
-
const hit = findEcrRepositoryRefInTree(value, resources);
|
|
1398
|
-
if (hit) return hit;
|
|
1399
|
-
}
|
|
1400
|
-
}
|
|
1401
|
-
function resolveImageIntrinsic(node, resources, context) {
|
|
1402
|
-
const v = resolveImageIntrinsicAny(node, resources, context);
|
|
1403
|
-
if (typeof v === "string") return v;
|
|
1404
|
-
if (typeof v === "number" || typeof v === "boolean") return String(v);
|
|
1405
|
-
}
|
|
1406
|
-
function resolveImageIntrinsicAny(node, resources, context) {
|
|
1407
|
-
if (node === null || node === void 0) return void 0;
|
|
1408
|
-
if (typeof node === "string" || typeof node === "number" || typeof node === "boolean") return node;
|
|
1409
|
-
if (Array.isArray(node)) return;
|
|
1410
|
-
if (typeof node !== "object") return void 0;
|
|
1411
|
-
const obj = node;
|
|
1412
|
-
const keys = Object.keys(obj);
|
|
1413
|
-
if (keys.length !== 1) return void 0;
|
|
1414
|
-
const intrinsic = keys[0];
|
|
1415
|
-
const arg = obj[intrinsic];
|
|
1416
|
-
if (intrinsic === "Ref") {
|
|
1417
|
-
if (typeof arg !== "string") return void 0;
|
|
1418
|
-
if (arg.startsWith("AWS::")) {
|
|
1419
|
-
const p = context?.pseudoParameters;
|
|
1420
|
-
if (!p) return void 0;
|
|
1421
|
-
if (arg === "AWS::URLSuffix") return p.urlSuffix;
|
|
1422
|
-
if (arg === "AWS::Partition") return p.partition;
|
|
1423
|
-
if (arg === "AWS::Region") return p.region;
|
|
1424
|
-
if (arg === "AWS::AccountId") return p.accountId;
|
|
1425
|
-
return;
|
|
1426
|
-
}
|
|
1427
|
-
if (resources[arg]?.Type !== "AWS::ECR::Repository") return void 0;
|
|
1428
|
-
const stateEntry = context?.stateResources?.[arg];
|
|
1429
|
-
if (!stateEntry) return void 0;
|
|
1430
|
-
return stateEntry.physicalId;
|
|
1431
|
-
}
|
|
1432
|
-
if (intrinsic === "Fn::GetAtt") {
|
|
1433
|
-
let logicalId;
|
|
1434
|
-
let attr;
|
|
1435
|
-
if (Array.isArray(arg) && arg.length === 2 && typeof arg[0] === "string" && typeof arg[1] === "string") {
|
|
1436
|
-
logicalId = arg[0];
|
|
1437
|
-
attr = arg[1];
|
|
1438
|
-
} else if (typeof arg === "string") {
|
|
1439
|
-
const dot = arg.indexOf(".");
|
|
1440
|
-
if (dot > 0 && dot < arg.length - 1) {
|
|
1441
|
-
logicalId = arg.slice(0, dot);
|
|
1442
|
-
attr = arg.slice(dot + 1);
|
|
1443
|
-
}
|
|
1444
|
-
}
|
|
1445
|
-
if (!logicalId || !attr) return void 0;
|
|
1446
|
-
if (resources[logicalId]?.Type !== "AWS::ECR::Repository") return void 0;
|
|
1447
|
-
const cached = context?.stateResources?.[logicalId]?.attributes?.[attr];
|
|
1448
|
-
if (typeof cached === "string" && cached.length > 0) return cached;
|
|
1449
|
-
const physicalId = context?.stateResources?.[logicalId]?.physicalId;
|
|
1450
|
-
const p = context?.pseudoParameters;
|
|
1451
|
-
if (physicalId && p?.region && p.accountId) {
|
|
1452
|
-
if (attr === "Arn" && p.partition) return `arn:${p.partition}:ecr:${p.region}:${p.accountId}:repository/${physicalId}`;
|
|
1453
|
-
if (attr === "RepositoryUri" && p.urlSuffix) return `${p.accountId}.dkr.ecr.${p.region}.${p.urlSuffix}/${physicalId}`;
|
|
1454
|
-
}
|
|
1455
|
-
return;
|
|
1456
|
-
}
|
|
1457
|
-
if (intrinsic === "Fn::Split") {
|
|
1458
|
-
if (!Array.isArray(arg) || arg.length !== 2) return void 0;
|
|
1459
|
-
const argArr = arg;
|
|
1460
|
-
const delim = argArr[0];
|
|
1461
|
-
if (typeof delim !== "string") return void 0;
|
|
1462
|
-
const src = resolveImageIntrinsicAny(argArr[1], resources, context);
|
|
1463
|
-
if (typeof src !== "string") return void 0;
|
|
1464
|
-
return src.split(delim);
|
|
1465
|
-
}
|
|
1466
|
-
if (intrinsic === "Fn::Select") {
|
|
1467
|
-
if (!Array.isArray(arg) || arg.length !== 2) return void 0;
|
|
1468
|
-
const argArr = arg;
|
|
1469
|
-
const rawIndex = argArr[0];
|
|
1470
|
-
let index;
|
|
1471
|
-
if (typeof rawIndex === "number") index = rawIndex;
|
|
1472
|
-
else if (typeof rawIndex === "string" && /^-?\d+$/.test(rawIndex)) index = Number.parseInt(rawIndex, 10);
|
|
1473
|
-
if (index === void 0 || !Number.isFinite(index)) return void 0;
|
|
1474
|
-
const list = resolveImageIntrinsicAny(argArr[1], resources, context);
|
|
1475
|
-
if (Array.isArray(list)) {
|
|
1476
|
-
if (index < 0 || index >= list.length) return void 0;
|
|
1477
|
-
const picked = list[index];
|
|
1478
|
-
if (typeof picked === "string") return picked;
|
|
1479
|
-
return;
|
|
1480
|
-
}
|
|
1481
|
-
if (Array.isArray(argArr[1])) {
|
|
1482
|
-
const listLiteral = argArr[1];
|
|
1483
|
-
if (index < 0 || index >= listLiteral.length) return void 0;
|
|
1484
|
-
return resolveImageIntrinsic(listLiteral[index], resources, context);
|
|
1485
|
-
}
|
|
1486
|
-
return;
|
|
1487
|
-
}
|
|
1488
|
-
if (intrinsic === "Fn::Join") {
|
|
1489
|
-
if (!Array.isArray(arg) || arg.length !== 2) return void 0;
|
|
1490
|
-
const [delim, parts] = arg;
|
|
1491
|
-
if (typeof delim !== "string" || !Array.isArray(parts)) return void 0;
|
|
1492
|
-
const resolved = [];
|
|
1493
|
-
for (const part of parts) {
|
|
1494
|
-
const r = resolveImageIntrinsic(part, resources, context);
|
|
1495
|
-
if (r === void 0) return void 0;
|
|
1496
|
-
resolved.push(r);
|
|
1497
|
-
}
|
|
1498
|
-
return resolved.join(delim);
|
|
1499
|
-
}
|
|
1500
|
-
if (intrinsic === "Fn::Sub") {
|
|
1501
|
-
let template;
|
|
1502
|
-
if (typeof arg === "string") template = arg;
|
|
1503
|
-
else if (Array.isArray(arg) && typeof arg[0] === "string") template = arg[0];
|
|
1504
|
-
if (template === void 0) return void 0;
|
|
1505
|
-
const out = substituteImagePlaceholders(template, resources, context);
|
|
1506
|
-
if (out.includes("${")) return void 0;
|
|
1507
|
-
return out;
|
|
1508
|
-
}
|
|
1509
|
-
}
|
|
1510
|
-
function substituteImagePlaceholders(flat, resources, context) {
|
|
1511
|
-
if (!flat.includes("${")) return flat;
|
|
1512
|
-
return flat.replace(/\$\{([^}]+)\}/g, (full, key) => {
|
|
1513
|
-
if (context?.pseudoParameters) {
|
|
1514
|
-
if (key === "AWS::AccountId" && context.pseudoParameters.accountId) return context.pseudoParameters.accountId;
|
|
1515
|
-
if (key === "AWS::Region" && context.pseudoParameters.region) return context.pseudoParameters.region;
|
|
1516
|
-
if (key === "AWS::Partition" && context.pseudoParameters.partition) return context.pseudoParameters.partition;
|
|
1517
|
-
if (key === "AWS::URLSuffix" && context.pseudoParameters.urlSuffix) return context.pseudoParameters.urlSuffix;
|
|
1518
|
-
}
|
|
1519
|
-
if (context?.stateResources) {
|
|
1520
|
-
const dot = key.indexOf(".");
|
|
1521
|
-
const logicalId = dot === -1 ? key : key.slice(0, dot);
|
|
1522
|
-
const refResource = resources[logicalId];
|
|
1523
|
-
const stateEntry = context.stateResources[logicalId];
|
|
1524
|
-
if (refResource?.Type === "AWS::ECR::Repository" && stateEntry) {
|
|
1525
|
-
if (dot === -1) return stateEntry.physicalId;
|
|
1526
|
-
const attr = key.slice(dot + 1);
|
|
1527
|
-
const cached = stateEntry.attributes?.[attr];
|
|
1528
|
-
if (typeof cached === "string") return cached;
|
|
1529
|
-
}
|
|
1530
|
-
}
|
|
1531
|
-
return full;
|
|
1532
|
-
});
|
|
1533
|
-
}
|
|
1534
|
-
|
|
1535
|
-
//#endregion
|
|
1536
|
-
//#region src/utils/stringify.ts
|
|
1537
|
-
function stringifyValue(value) {
|
|
1538
|
-
switch (typeof value) {
|
|
1539
|
-
case "string": return value;
|
|
1540
|
-
case "number":
|
|
1541
|
-
case "boolean":
|
|
1542
|
-
case "bigint": return String(value);
|
|
1543
|
-
case "symbol": return value.toString();
|
|
1544
|
-
case "undefined": return "undefined";
|
|
1545
|
-
case "function": return value.name ? `[Function: ${value.name}]` : "[Function]";
|
|
1546
|
-
case "object":
|
|
1547
|
-
if (value === null) return "null";
|
|
1548
|
-
try {
|
|
1549
|
-
const json = JSON.stringify(value);
|
|
1550
|
-
if (json !== void 0) return json;
|
|
1551
|
-
} catch {}
|
|
1552
|
-
return Object.prototype.toString.call(value);
|
|
1553
|
-
}
|
|
1554
|
-
}
|
|
1555
|
-
|
|
1556
|
-
//#endregion
|
|
1557
|
-
//#region src/local/lambda-resolver.ts
|
|
1558
|
-
function resolveLambdaArchitecture(props, logicalId) {
|
|
1559
|
-
const arches = props["Architectures"];
|
|
1560
|
-
if (Array.isArray(arches) && arches.length > 0) {
|
|
1561
|
-
const first = arches[0];
|
|
1562
|
-
if (first === "arm64") return "arm64";
|
|
1563
|
-
if (first === "x86_64") return "x86_64";
|
|
1564
|
-
throw new LocalInvokeResolutionError(`Lambda ${displayIdent(logicalId)} has unsupported Architectures value ${displayIdent(String(first))}. ${getEmbedConfig().cliName} supports x86_64 and arm64.`);
|
|
1565
|
-
}
|
|
1566
|
-
return "x86_64";
|
|
605
|
+
|
|
606
|
+
//#endregion
|
|
607
|
+
//#region src/local/lambda-resolver.ts
|
|
608
|
+
function resolveLambdaArchitecture(props, logicalId) {
|
|
609
|
+
const arches = props["Architectures"];
|
|
610
|
+
if (Array.isArray(arches) && arches.length > 0) {
|
|
611
|
+
const first = arches[0];
|
|
612
|
+
if (first === "arm64") return "arm64";
|
|
613
|
+
if (first === "x86_64") return "x86_64";
|
|
614
|
+
throw new LocalInvokeResolutionError(`Lambda ${displayIdent(logicalId)} has unsupported Architectures value ${displayIdent(String(first))}. ${getEmbedConfig().cliName} supports x86_64 and arm64.`);
|
|
615
|
+
}
|
|
616
|
+
return "x86_64";
|
|
1567
617
|
}
|
|
1568
618
|
var LocalInvokeResolutionError = class LocalInvokeResolutionError extends Error {
|
|
1569
619
|
constructor(message) {
|
|
@@ -4838,69 +3888,6 @@ function applyDeployedEnvFallback(resolvedEnv, unresolved, deployedEnv) {
|
|
|
4838
3888
|
};
|
|
4839
3889
|
}
|
|
4840
3890
|
|
|
4841
|
-
//#endregion
|
|
4842
|
-
//#region src/local/ecr-uri.ts
|
|
4843
|
-
const FIPS_AND_DUAL_STACK_PARTITIONS = ["aws", "aws-us-gov"];
|
|
4844
|
-
const ECR_REGISTRY_HOST_FORMS = [
|
|
4845
|
-
{ labels: "dkr.ecr" },
|
|
4846
|
-
{
|
|
4847
|
-
labels: "dkr.ecr-fips",
|
|
4848
|
-
partitions: FIPS_AND_DUAL_STACK_PARTITIONS
|
|
4849
|
-
},
|
|
4850
|
-
{
|
|
4851
|
-
labels: "dkr-ecr",
|
|
4852
|
-
fixedUrlSuffix: "on.aws",
|
|
4853
|
-
partitions: FIPS_AND_DUAL_STACK_PARTITIONS
|
|
4854
|
-
},
|
|
4855
|
-
{
|
|
4856
|
-
labels: "dkr-ecr-fips",
|
|
4857
|
-
fixedUrlSuffix: "on.aws",
|
|
4858
|
-
partitions: FIPS_AND_DUAL_STACK_PARTITIONS
|
|
4859
|
-
}
|
|
4860
|
-
];
|
|
4861
|
-
const ECR_HOST_FORM_BY_LABELS = new Map(ECR_REGISTRY_HOST_FORMS.map((f) => [f.labels, f]));
|
|
4862
|
-
function escapeRegExp(value) {
|
|
4863
|
-
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
4864
|
-
}
|
|
4865
|
-
const ECR_URI_HOST_REGEX = new RegExp(`^(\\d{12})\\.(${[...ECR_REGISTRY_HOST_FORMS].sort((a, b) => b.labels.length - a.labels.length).map((f) => escapeRegExp(f.labels)).join("|")})\\.([^./]+)\\.([^/]+)/`, "i");
|
|
4866
|
-
const CANONICAL_REGION_SEGMENT = /^[A-Za-z0-9][A-Za-z0-9-]*$/;
|
|
4867
|
-
const REGION_SHAPE = /^(?:(?:us|eu|ap|sa|ca|me|af|il|mx)-[a-z0-9]+-[0-9]+|cn-[a-z0-9]+-[0-9]+|us-gov-[a-z0-9]+-[0-9]+|us-iso-[a-z0-9]+-[0-9]+|us-isob-[a-z0-9]+-[0-9]+|eu-isoe-[a-z0-9]+-[0-9]+|us-isof-[a-z0-9]+-[0-9]+|eusc-[a-z]+-[a-z0-9]+-[0-9]+)$/;
|
|
4868
|
-
const CANONICAL_URL_SUFFIX = /^[A-Za-z0-9][A-Za-z0-9.-]*$/;
|
|
4869
|
-
function foldAsciiUpperCase(value) {
|
|
4870
|
-
return value.replace(/[A-Z]+/g, (run) => run.toLowerCase());
|
|
4871
|
-
}
|
|
4872
|
-
function isRegistryHostComponent(component) {
|
|
4873
|
-
return component.includes(".") || component.includes(":") || component === "localhost";
|
|
4874
|
-
}
|
|
4875
|
-
function canonicalizeImageUriHost(imageUri) {
|
|
4876
|
-
const slash = imageUri.indexOf("/");
|
|
4877
|
-
if (slash < 0) return imageUri;
|
|
4878
|
-
const host = imageUri.slice(0, slash);
|
|
4879
|
-
if (!isRegistryHostComponent(host)) return imageUri;
|
|
4880
|
-
return foldAsciiUpperCase(host) + imageUri.slice(slash);
|
|
4881
|
-
}
|
|
4882
|
-
function parseEcrRegistryHost(imageUri) {
|
|
4883
|
-
const m = ECR_URI_HOST_REGEX.exec(imageUri);
|
|
4884
|
-
if (!m) return void 0;
|
|
4885
|
-
const [, accountId, rawLabels, rawRegion, rawSuffix] = m;
|
|
4886
|
-
if (!CANONICAL_REGION_SEGMENT.test(rawRegion)) return void 0;
|
|
4887
|
-
if (!CANONICAL_URL_SUFFIX.test(rawSuffix)) return void 0;
|
|
4888
|
-
const form = ECR_HOST_FORM_BY_LABELS.get(foldAsciiUpperCase(rawLabels));
|
|
4889
|
-
if (!form) return void 0;
|
|
4890
|
-
const region = foldAsciiUpperCase(rawRegion);
|
|
4891
|
-
if (!REGION_SHAPE.test(region)) return void 0;
|
|
4892
|
-
const suffix = foldAsciiUpperCase(rawSuffix);
|
|
4893
|
-
const partition = derivePartitionAndUrlSuffix(region);
|
|
4894
|
-
if (form.partitions && !form.partitions.includes(partition.partition)) return void 0;
|
|
4895
|
-
if (suffix !== (form.fixedUrlSuffix ?? partition.urlSuffix)) return void 0;
|
|
4896
|
-
return {
|
|
4897
|
-
accountId,
|
|
4898
|
-
region,
|
|
4899
|
-
registryHost: `${accountId}.${form.labels}.${region}.${suffix}`,
|
|
4900
|
-
form
|
|
4901
|
-
};
|
|
4902
|
-
}
|
|
4903
|
-
|
|
4904
3891
|
//#endregion
|
|
4905
3892
|
//#region src/local/ecs-task-resolver.ts
|
|
4906
3893
|
var EcsTaskResolutionError = class EcsTaskResolutionError extends Error {
|
|
@@ -5556,1215 +4543,219 @@ function resolveRoleArn(value, resources, subContext) {
|
|
|
5556
4543
|
if (attr === "" || attr === "Arn") refLogicalId = arg[0];
|
|
5557
4544
|
}
|
|
5558
4545
|
}
|
|
5559
|
-
if (refLogicalId !== void 0) {
|
|
5560
|
-
if (resources[refLogicalId]?.Type !== "AWS::IAM::Role") return void 0;
|
|
5561
|
-
return `arn:aws:iam::${TASK_ROLE_ACCOUNT_PLACEHOLDER}:role/${refLogicalId}`;
|
|
5562
|
-
}
|
|
5563
|
-
if ("Fn::Join" in obj || "Fn::Sub" in obj) {
|
|
5564
|
-
if (!subContext) return void 0;
|
|
5565
|
-
const sub = substituteAgainstState(value, subContext);
|
|
5566
|
-
if (sub.kind === "literal" && typeof sub.value === "string" && sub.value.length > 0) return sub.value;
|
|
5567
|
-
return;
|
|
5568
|
-
}
|
|
5569
|
-
}
|
|
5570
|
-
function pickString(value) {
|
|
5571
|
-
return typeof value === "string" && value.length > 0 ? value : void 0;
|
|
5572
|
-
}
|
|
5573
|
-
function pickStringArray$1(value) {
|
|
5574
|
-
if (!Array.isArray(value)) return void 0;
|
|
5575
|
-
const out = [];
|
|
5576
|
-
for (const v of value) if (typeof v === "string") out.push(v);
|
|
5577
|
-
return out;
|
|
5578
|
-
}
|
|
5579
|
-
function notFoundError$2(target, stack, resources) {
|
|
5580
|
-
const tasks = [];
|
|
5581
|
-
for (const [logicalId, resource] of Object.entries(resources)) {
|
|
5582
|
-
if (resource.Type !== "AWS::ECS::TaskDefinition") continue;
|
|
5583
|
-
const meta = resource.Metadata;
|
|
5584
|
-
const cdkPath = typeof meta?.["aws:cdk:path"] === "string" ? meta["aws:cdk:path"] : "";
|
|
5585
|
-
tasks.push({
|
|
5586
|
-
displayPath: cdkPath || logicalId,
|
|
5587
|
-
logicalId
|
|
5588
|
-
});
|
|
5589
|
-
}
|
|
5590
|
-
let msg = `target '${target}' did not match any ECS task definition in ${stack.stackName}.\n\n`;
|
|
5591
|
-
if (tasks.length === 0) msg += `Stack ${stack.stackName} has no AWS::ECS::TaskDefinition resources.`;
|
|
5592
|
-
else {
|
|
5593
|
-
const width = Math.max(...tasks.map((t) => t.displayPath.length));
|
|
5594
|
-
msg += `Available task definitions in ${stack.stackName}:\n`;
|
|
5595
|
-
for (const t of tasks) msg += ` ${t.displayPath.padEnd(width)} (${displayIdent(t.logicalId)})\n`;
|
|
5596
|
-
}
|
|
5597
|
-
return new EcsTaskResolutionError(msg.trimEnd());
|
|
5598
|
-
}
|
|
5599
|
-
function checkVolumeHostPath(hostPath) {
|
|
5600
|
-
try {
|
|
5601
|
-
return existsSync(hostPath) && statSync(hostPath).isDirectory();
|
|
5602
|
-
} catch {
|
|
5603
|
-
return false;
|
|
5604
|
-
}
|
|
5605
|
-
}
|
|
5606
|
-
async function applyCrossStackResolverToTask(task, context) {
|
|
5607
|
-
if (!context.crossStackResolver) return;
|
|
5608
|
-
const { resolveDynamicReferences: _envOnly, ...secretContext } = context;
|
|
5609
|
-
const rawContainers = (task.resource.Properties ?? {})["ContainerDefinitions"];
|
|
5610
|
-
if (!Array.isArray(rawContainers)) return;
|
|
5611
|
-
for (let idx = 0; idx < task.containers.length; idx += 1) {
|
|
5612
|
-
const container = task.containers[idx];
|
|
5613
|
-
const raw = rawContainers[idx];
|
|
5614
|
-
if (!raw || typeof raw !== "object") continue;
|
|
5615
|
-
const c = raw;
|
|
5616
|
-
const containerName = pickString(c["Name"]) ?? container.name;
|
|
5617
|
-
const resolvedEnvKeys = /* @__PURE__ */ new Set();
|
|
5618
|
-
const resolvedSecretNames = /* @__PURE__ */ new Set();
|
|
5619
|
-
if (Array.isArray(c["Environment"])) for (const entry of c["Environment"]) {
|
|
5620
|
-
if (!entry || typeof entry !== "object") continue;
|
|
5621
|
-
const e = entry;
|
|
5622
|
-
const key = pickString(e["Name"]);
|
|
5623
|
-
const value = e["Value"];
|
|
5624
|
-
if (!key) continue;
|
|
5625
|
-
if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") continue;
|
|
5626
|
-
if (Object.hasOwn(container.environment, key)) continue;
|
|
5627
|
-
if (!isCrossStackIntrinsic(value)) continue;
|
|
5628
|
-
const { result: sub, consumedSensitive } = await resolveWithSensitivityAsync(value, context);
|
|
5629
|
-
if (sub.kind === "literal") {
|
|
5630
|
-
defineOwnKey(container.environment, key, String(sub.value));
|
|
5631
|
-
resolvedEnvKeys.add(key);
|
|
5632
|
-
if (consumedSensitive && !container.sensitiveEnvKeys.includes(key)) container.sensitiveEnvKeys.push(key);
|
|
5633
|
-
}
|
|
5634
|
-
}
|
|
5635
|
-
if (Array.isArray(c["Secrets"])) for (const entry of c["Secrets"]) {
|
|
5636
|
-
if (!entry || typeof entry !== "object") continue;
|
|
5637
|
-
const e = entry;
|
|
5638
|
-
const sName = pickString(e["Name"]);
|
|
5639
|
-
const valueFromRaw = e["ValueFrom"];
|
|
5640
|
-
if (!sName) continue;
|
|
5641
|
-
if (typeof valueFromRaw === "string" && valueFromRaw.length > 0) continue;
|
|
5642
|
-
if (container.secrets.some((s) => s.name === sName)) continue;
|
|
5643
|
-
if (!isCrossStackIntrinsic(valueFromRaw)) continue;
|
|
5644
|
-
const sub = await substituteAgainstStateAsync(valueFromRaw, secretContext);
|
|
5645
|
-
if (sub.kind === "literal" && typeof sub.value === "string" && sub.value.length > 0) {
|
|
5646
|
-
container.secrets.push({
|
|
5647
|
-
name: sName,
|
|
5648
|
-
valueFrom: sub.value
|
|
5649
|
-
});
|
|
5650
|
-
resolvedSecretNames.add(sName);
|
|
5651
|
-
}
|
|
5652
|
-
}
|
|
5653
|
-
if (resolvedEnvKeys.size > 0 || resolvedSecretNames.size > 0) {
|
|
5654
|
-
container.warnings = container.warnings.filter((w) => {
|
|
5655
|
-
for (const k of resolvedEnvKeys) if (w.startsWith(`Environment ${displayIdent(k)} dropped:`)) return false;
|
|
5656
|
-
for (const k of resolvedSecretNames) if (w.startsWith(`Secret ${displayIdent(k)} dropped:`)) return false;
|
|
5657
|
-
return true;
|
|
5658
|
-
});
|
|
5659
|
-
task.warnings = task.warnings.filter((w) => {
|
|
5660
|
-
for (const k of resolvedEnvKeys) if (w.startsWith(`Container ${displayIdent(containerName)}: Environment ${displayIdent(k)} dropped:`)) return false;
|
|
5661
|
-
for (const k of resolvedSecretNames) if (w.startsWith(`Container ${displayIdent(containerName)}: Secret ${displayIdent(k)} dropped:`)) return false;
|
|
5662
|
-
return true;
|
|
5663
|
-
});
|
|
5664
|
-
}
|
|
5665
|
-
}
|
|
5666
|
-
}
|
|
5667
|
-
|
|
5668
|
-
//#endregion
|
|
5669
|
-
//#region src/local/runtime-image.ts
|
|
5670
|
-
const SUPPORTED_RUNTIMES = {
|
|
5671
|
-
"nodejs18.x": {
|
|
5672
|
-
image: "public.ecr.aws/lambda/nodejs:18",
|
|
5673
|
-
fileExtension: ".js"
|
|
5674
|
-
},
|
|
5675
|
-
"nodejs20.x": {
|
|
5676
|
-
image: "public.ecr.aws/lambda/nodejs:20",
|
|
5677
|
-
fileExtension: ".js"
|
|
5678
|
-
},
|
|
5679
|
-
"nodejs22.x": {
|
|
5680
|
-
image: "public.ecr.aws/lambda/nodejs:22",
|
|
5681
|
-
fileExtension: ".js"
|
|
5682
|
-
},
|
|
5683
|
-
"nodejs24.x": {
|
|
5684
|
-
image: "public.ecr.aws/lambda/nodejs:24",
|
|
5685
|
-
fileExtension: ".js"
|
|
5686
|
-
},
|
|
5687
|
-
"python3.11": {
|
|
5688
|
-
image: "public.ecr.aws/lambda/python:3.11",
|
|
5689
|
-
fileExtension: ".py"
|
|
5690
|
-
},
|
|
5691
|
-
"python3.12": {
|
|
5692
|
-
image: "public.ecr.aws/lambda/python:3.12",
|
|
5693
|
-
fileExtension: ".py"
|
|
5694
|
-
},
|
|
5695
|
-
"python3.13": {
|
|
5696
|
-
image: "public.ecr.aws/lambda/python:3.13",
|
|
5697
|
-
fileExtension: ".py"
|
|
5698
|
-
},
|
|
5699
|
-
"python3.14": {
|
|
5700
|
-
image: "public.ecr.aws/lambda/python:3.14",
|
|
5701
|
-
fileExtension: ".py"
|
|
5702
|
-
},
|
|
5703
|
-
"ruby3.2": {
|
|
5704
|
-
image: "public.ecr.aws/lambda/ruby:3.2",
|
|
5705
|
-
fileExtension: ".rb"
|
|
5706
|
-
},
|
|
5707
|
-
"ruby3.3": {
|
|
5708
|
-
image: "public.ecr.aws/lambda/ruby:3.3",
|
|
5709
|
-
fileExtension: ".rb"
|
|
5710
|
-
},
|
|
5711
|
-
"java8.al2": {
|
|
5712
|
-
image: "public.ecr.aws/lambda/java:8.al2",
|
|
5713
|
-
fileExtension: null
|
|
5714
|
-
},
|
|
5715
|
-
java11: {
|
|
5716
|
-
image: "public.ecr.aws/lambda/java:11",
|
|
5717
|
-
fileExtension: null
|
|
5718
|
-
},
|
|
5719
|
-
java17: {
|
|
5720
|
-
image: "public.ecr.aws/lambda/java:17",
|
|
5721
|
-
fileExtension: null
|
|
5722
|
-
},
|
|
5723
|
-
java21: {
|
|
5724
|
-
image: "public.ecr.aws/lambda/java:21",
|
|
5725
|
-
fileExtension: null
|
|
5726
|
-
},
|
|
5727
|
-
dotnet6: {
|
|
5728
|
-
image: "public.ecr.aws/lambda/dotnet:6",
|
|
5729
|
-
fileExtension: null
|
|
5730
|
-
},
|
|
5731
|
-
dotnet8: {
|
|
5732
|
-
image: "public.ecr.aws/lambda/dotnet:8",
|
|
5733
|
-
fileExtension: null
|
|
5734
|
-
},
|
|
5735
|
-
"provided.al2": {
|
|
5736
|
-
image: "public.ecr.aws/lambda/provided:al2",
|
|
5737
|
-
fileExtension: null
|
|
5738
|
-
},
|
|
5739
|
-
"provided.al2023": {
|
|
5740
|
-
image: "public.ecr.aws/lambda/provided:al2023",
|
|
5741
|
-
fileExtension: null
|
|
5742
|
-
}
|
|
5743
|
-
};
|
|
5744
|
-
var UnsupportedRuntimeError = class UnsupportedRuntimeError extends Error {
|
|
5745
|
-
runtime;
|
|
5746
|
-
constructor(runtime, message) {
|
|
5747
|
-
super(message);
|
|
5748
|
-
this.runtime = runtime;
|
|
5749
|
-
this.name = "UnsupportedRuntimeError";
|
|
5750
|
-
Object.setPrototypeOf(this, UnsupportedRuntimeError.prototype);
|
|
5751
|
-
}
|
|
5752
|
-
};
|
|
5753
|
-
function resolveRuntimeImage(runtime) {
|
|
5754
|
-
return resolveRuntimeSpec(runtime).image;
|
|
5755
|
-
}
|
|
5756
|
-
function resolveRuntimeFileExtension(runtime) {
|
|
5757
|
-
const spec = resolveRuntimeSpec(runtime);
|
|
5758
|
-
if (spec.fileExtension === null) throw new UnsupportedRuntimeError(runtime, `Inline 'Code.ZipFile' is not supported for runtime ${displayIdent(runtime)}. The Lambda Handler shape for this runtime names a compiled artifact (a JVM class, a .NET assembly, or — for the OS-only \`provided.*\` runtimes — an arbitrary \`bootstrap\` binary) that cannot be expressed as a single inline source file. Use \`lambda.Code.fromAsset(<dir>)\` with a directory containing the compiled output (.class hierarchy / JAR / DLL / native binary).`);
|
|
5759
|
-
return spec.fileExtension;
|
|
5760
|
-
}
|
|
5761
|
-
function resolveRuntimeSpec(runtime) {
|
|
5762
|
-
if (typeof runtime !== "string" || runtime.length === 0) throw new UnsupportedRuntimeError(String(runtime), "Lambda function has no Runtime property. This branch is only reached for ZIP Lambdas; container-image Lambdas (Code.ImageUri) take a different code path that does not consult the Runtime property.");
|
|
5763
|
-
const spec = SUPPORTED_RUNTIMES[runtime];
|
|
5764
|
-
if (spec) return spec;
|
|
5765
|
-
if (runtime === "go1.x") throw new UnsupportedRuntimeError(runtime, "Runtime 'go1.x' was deprecated by AWS Lambda on 2024-01-08 and is no longer available. Migrate to the OS-only runtime: build your Go program as a `bootstrap` binary and set the CDK runtime to `lambda.Runtime.PROVIDED_AL2023` (or `lambda.Runtime.PROVIDED_AL2`). See https://docs.aws.amazon.com/lambda/latest/dg/lambda-golang.html");
|
|
5766
|
-
throw new UnsupportedRuntimeError(runtime, `Unknown runtime ${displayIdent(runtime)}. ${getEmbedConfig().cliName} invoke supports nodejs18.x / nodejs20.x / nodejs22.x / nodejs24.x / python3.11 / python3.12 / python3.13 / python3.14 / ruby3.2 / ruby3.3 / java8.al2 / java11 / java17 / java21 / dotnet6 / dotnet8 / provided.al2 / provided.al2023.`);
|
|
5767
|
-
}
|
|
5768
|
-
function resolveRuntimeCodeMountPath(runtime) {
|
|
5769
|
-
resolveRuntimeSpec(runtime);
|
|
5770
|
-
if (runtime === "provided.al2" || runtime === "provided.al2023") return "/var/runtime";
|
|
5771
|
-
return "/var/task";
|
|
5772
|
-
}
|
|
5773
|
-
|
|
5774
|
-
//#endregion
|
|
5775
|
-
//#region src/utils/docker-argv-redaction.ts
|
|
5776
|
-
const REDACTED_ARGV_VALUE = "***";
|
|
5777
|
-
const ARGV_VALUE_BEARING_FLAGS = /* @__PURE__ */ new Set([
|
|
5778
|
-
"-e",
|
|
5779
|
-
"--env",
|
|
5780
|
-
"--opt",
|
|
5781
|
-
"--label",
|
|
5782
|
-
"--build-arg"
|
|
5783
|
-
]);
|
|
5784
|
-
const ARGV_PARAM_LIST_FLAGS = /* @__PURE__ */ new Set(["--cache-from", "--cache-to"]);
|
|
5785
|
-
const ARGV_PARAM_LIST_LOCATOR_PARAMS = /* @__PURE__ */ new Set([
|
|
5786
|
-
"type",
|
|
5787
|
-
"mode",
|
|
5788
|
-
"compression",
|
|
5789
|
-
"compression-level",
|
|
5790
|
-
"force-compression",
|
|
5791
|
-
"ignore-error",
|
|
5792
|
-
"image-manifest",
|
|
5793
|
-
"oci-mediatypes",
|
|
5794
|
-
"timeout",
|
|
5795
|
-
"ref",
|
|
5796
|
-
"dest",
|
|
5797
|
-
"src",
|
|
5798
|
-
"digest",
|
|
5799
|
-
"tag",
|
|
5800
|
-
"region",
|
|
5801
|
-
"bucket",
|
|
5802
|
-
"name",
|
|
5803
|
-
"prefix",
|
|
5804
|
-
"manifests_prefix",
|
|
5805
|
-
"blobs_prefix",
|
|
5806
|
-
"use_path_style",
|
|
5807
|
-
"upload_parallelism",
|
|
5808
|
-
"touch_refresh",
|
|
5809
|
-
"account_name",
|
|
5810
|
-
"scope"
|
|
5811
|
-
]);
|
|
5812
|
-
const ARGV_PARAM_LIST_URL_PARAMS = /* @__PURE__ */ new Set([
|
|
5813
|
-
"account_url",
|
|
5814
|
-
"endpoint_url",
|
|
5815
|
-
"url",
|
|
5816
|
-
"url_v2"
|
|
5817
|
-
]);
|
|
5818
|
-
function redactUrlLocator(value) {
|
|
5819
|
-
if (value === "") return value;
|
|
5820
|
-
const authority = /^(?:[a-zA-Z][a-zA-Z0-9+.-]*:)?\/\//.exec(value);
|
|
5821
|
-
if (authority === null) return REDACTED_ARGV_VALUE;
|
|
5822
|
-
const prefix = authority[0];
|
|
5823
|
-
let rest = value.slice(prefix.length);
|
|
5824
|
-
const lastAt = rest.lastIndexOf("@");
|
|
5825
|
-
if (lastAt >= 0) rest = `${REDACTED_ARGV_VALUE}${rest.slice(lastAt)}`;
|
|
5826
|
-
else {
|
|
5827
|
-
const host = rest.split(/[/?#]/)[0];
|
|
5828
|
-
const ipv6 = /^\[[0-9A-Fa-f:.]+\]/.exec(host);
|
|
5829
|
-
const bare = ipv6 ? host.slice(ipv6[0].length) : host;
|
|
5830
|
-
if (/:(?!\d{1,5}$)/.test(bare)) return REDACTED_ARGV_VALUE;
|
|
5831
|
-
}
|
|
5832
|
-
for (const delimiter of ["?", "#"]) {
|
|
5833
|
-
const at = rest.indexOf(delimiter);
|
|
5834
|
-
if (at >= 0) rest = `${rest.slice(0, at)}${delimiter}${REDACTED_ARGV_VALUE}`;
|
|
5835
|
-
}
|
|
5836
|
-
return `${prefix}${rest}`;
|
|
5837
|
-
}
|
|
5838
|
-
function maskArgvFlagValue(flag, value) {
|
|
5839
|
-
if (ARGV_VALUE_BEARING_FLAGS.has(flag)) {
|
|
5840
|
-
const eqIdx = value.indexOf("=");
|
|
5841
|
-
return eqIdx >= 0 ? `${value.substring(0, eqIdx)}=${REDACTED_ARGV_VALUE}` : void 0;
|
|
5842
|
-
}
|
|
5843
|
-
if (ARGV_PARAM_LIST_FLAGS.has(flag)) {
|
|
5844
|
-
let masked = false;
|
|
5845
|
-
const rawParts = value.split(",");
|
|
5846
|
-
const parts = rawParts.map((part, index) => {
|
|
5847
|
-
if (part === "") return part;
|
|
5848
|
-
if (masked) return REDACTED_ARGV_VALUE;
|
|
5849
|
-
const eqIdx = part.indexOf("=");
|
|
5850
|
-
if (eqIdx < 0) {
|
|
5851
|
-
if (index === 0) return part;
|
|
5852
|
-
masked = true;
|
|
5853
|
-
return REDACTED_ARGV_VALUE;
|
|
5854
|
-
}
|
|
5855
|
-
const name = part.substring(0, eqIdx);
|
|
5856
|
-
const normalized = name.trim().toLowerCase();
|
|
5857
|
-
if (ARGV_PARAM_LIST_URL_PARAMS.has(normalized)) {
|
|
5858
|
-
if (rawParts.slice(index + 1).some((later) => later.includes("@"))) {
|
|
5859
|
-
masked = true;
|
|
5860
|
-
return `${name}=${REDACTED_ARGV_VALUE}`;
|
|
5861
|
-
}
|
|
5862
|
-
const rawUrl = part.substring(eqIdx + 1);
|
|
5863
|
-
const safeUrl = redactUrlLocator(rawUrl);
|
|
5864
|
-
if (safeUrl === rawUrl) return part;
|
|
5865
|
-
masked = true;
|
|
5866
|
-
return `${name}=${safeUrl}`;
|
|
5867
|
-
}
|
|
5868
|
-
if (ARGV_PARAM_LIST_LOCATOR_PARAMS.has(normalized)) return part;
|
|
5869
|
-
masked = true;
|
|
5870
|
-
return `${name}=${REDACTED_ARGV_VALUE}`;
|
|
5871
|
-
});
|
|
5872
|
-
return masked ? parts.join(",") : void 0;
|
|
5873
|
-
}
|
|
5874
|
-
}
|
|
5875
|
-
function maskAttachedShortFlag(arg) {
|
|
5876
|
-
if (arg.startsWith("--") || !arg.startsWith("-")) return void 0;
|
|
5877
|
-
let chosen;
|
|
5878
|
-
for (const flag of ARGV_VALUE_BEARING_FLAGS) {
|
|
5879
|
-
if (flag.length !== 2 || !flag.startsWith("-") || flag[1] === "-") continue;
|
|
5880
|
-
const at = arg.indexOf(flag[1], 1);
|
|
5881
|
-
if (at < 0 || at === arg.length - 1) continue;
|
|
5882
|
-
if (chosen === void 0 || at < chosen.at) chosen = {
|
|
5883
|
-
at,
|
|
5884
|
-
flag
|
|
5885
|
-
};
|
|
5886
|
-
}
|
|
5887
|
-
if (chosen === void 0) return void 0;
|
|
5888
|
-
const masked = maskArgvFlagValue(chosen.flag, arg.slice(chosen.at + 1));
|
|
5889
|
-
return masked === void 0 ? void 0 : `${arg.slice(0, chosen.at + 1)}${masked}`;
|
|
5890
|
-
}
|
|
5891
|
-
function trailingShortFlagOfCluster(arg) {
|
|
5892
|
-
if (arg.startsWith("--") || !arg.startsWith("-")) return void 0;
|
|
5893
|
-
const last = arg[arg.length - 1];
|
|
5894
|
-
for (const flag of ARGV_VALUE_BEARING_FLAGS) if (flag.length === 2 && flag.startsWith("-") && flag[1] !== "-" && flag[1] === last) return flag;
|
|
5895
|
-
}
|
|
5896
|
-
function redactDockerArgvValues(args) {
|
|
5897
|
-
const out = [];
|
|
5898
|
-
for (let i = 0; i < args.length; i++) {
|
|
5899
|
-
const cur = args[i];
|
|
5900
|
-
const joinedEq = cur.indexOf("=");
|
|
5901
|
-
if (joinedEq > 0) {
|
|
5902
|
-
const maskedJoined = maskArgvFlagValue(cur.substring(0, joinedEq), cur.substring(joinedEq + 1));
|
|
5903
|
-
if (maskedJoined !== void 0) {
|
|
5904
|
-
out.push(`${cur.substring(0, joinedEq)}=${maskedJoined}`);
|
|
5905
|
-
continue;
|
|
5906
|
-
}
|
|
5907
|
-
}
|
|
5908
|
-
const maskedAttached = maskAttachedShortFlag(cur);
|
|
5909
|
-
if (maskedAttached !== void 0) {
|
|
5910
|
-
out.push(maskedAttached);
|
|
5911
|
-
continue;
|
|
5912
|
-
}
|
|
5913
|
-
const next = args[i + 1];
|
|
5914
|
-
if (typeof next === "string") {
|
|
5915
|
-
const maskedNext = maskArgvFlagValue(ARGV_VALUE_BEARING_FLAGS.has(cur) ? cur : trailingShortFlagOfCluster(cur) ?? cur, next);
|
|
5916
|
-
if (maskedNext !== void 0) {
|
|
5917
|
-
out.push(cur, maskedNext);
|
|
5918
|
-
i++;
|
|
5919
|
-
continue;
|
|
5920
|
-
}
|
|
5921
|
-
}
|
|
5922
|
-
out.push(cur);
|
|
5923
|
-
}
|
|
5924
|
-
return out;
|
|
5925
|
-
}
|
|
5926
|
-
function describeExitWithoutArgv(err) {
|
|
5927
|
-
const e = err;
|
|
5928
|
-
if (typeof e?.signal === "string" && e.signal !== "") return `killed by ${e.signal}`;
|
|
5929
|
-
if (typeof e?.code === "number") return `exited with code ${e.code}`;
|
|
5930
|
-
if (typeof e?.code === "string" && e.code !== "") return `failed (${e.code})`;
|
|
5931
|
-
return "failed with no output";
|
|
5932
|
-
}
|
|
5933
|
-
|
|
5934
|
-
//#endregion
|
|
5935
|
-
//#region src/assets/asset-source-path.ts
|
|
5936
|
-
function resolveAssetSourcePath(opts) {
|
|
5937
|
-
const { manifestDir, value, assetOutdir, field, subject, action, wrapError } = opts;
|
|
5938
|
-
const shownValue = displayUntrustedValue(value);
|
|
5939
|
-
if (isAbsolute(value) && opts.absolute !== "fold") {
|
|
5940
|
-
const absolute = resolve(value);
|
|
5941
|
-
const escape = absoluteAssemblyPathEscape(assetOutdir, absolute);
|
|
5942
|
-
if (escape !== void 0 && opts.absolute === "honour") throw wrapError(`${subject} has an absolute ${field}=${shownValue} which ` + renderAssemblyPathEscape(escape, assetOutdir, action));
|
|
5943
|
-
if (escape !== void 0) {
|
|
5944
|
-
const refusal = originScopeRefusal(absolute, assetOutdir);
|
|
5945
|
-
if (refusal !== void 0) throw wrapError(`${subject} has an absolute ${field}=${shownValue} which ${refusal}. An absolute ${field} is accepted only as a cdk synth --no-staging source folder: a directory inside your project (the git work tree holding the output directory, or the current directory when it contains the output directory or is a git work-tree root), not under a credential or version-control directory. Refusing to ${action}.`);
|
|
5946
|
-
warnAbsoluteOutsideAssembly(opts, absolute, escape);
|
|
5947
|
-
return absolute;
|
|
5948
|
-
}
|
|
5949
|
-
if (namesTheSameDirectory(assetOutdir, absolute)) warnWholeAssemblyAsSource(opts, absolute);
|
|
5950
|
-
return absolute;
|
|
5951
|
-
}
|
|
5952
|
-
const resolved = resolveAssemblyPath(manifestDir, value, { containWithin: assetOutdir });
|
|
5953
|
-
if (resolved.contained) return resolved.path;
|
|
5954
|
-
if (namesTheSameDirectory(assetOutdir, resolved.path)) {
|
|
5955
|
-
warnWholeAssemblyAsSource(opts, resolved.path);
|
|
5956
|
-
return resolved.path;
|
|
5957
|
-
}
|
|
5958
|
-
throw wrapError(`${subject} has ${field}=${shownValue} which ` + renderAssemblyPathEscape(resolved, assetOutdir, action));
|
|
5959
|
-
}
|
|
5960
|
-
function broadRootReason(root, assetOutdir) {
|
|
5961
|
-
if (root === resolve("/")) return "names the filesystem root";
|
|
5962
|
-
if (containsOrIs(root, realPath(homedir()))) return "names your home directory or a directory containing it";
|
|
5963
|
-
if (containsOrIs(root, realPath(assetOutdir))) return "names a directory containing the app's output directory";
|
|
5964
|
-
}
|
|
5965
|
-
function originScopeRefusal(absolute, assetOutdir) {
|
|
5966
|
-
const root = realPath(absolute);
|
|
5967
|
-
const broad = broadRootReason(root, assetOutdir);
|
|
5968
|
-
if (broad !== void 0) return broad;
|
|
5969
|
-
const projects = projectRoots(assetOutdir);
|
|
5970
|
-
let hidden;
|
|
5971
|
-
let isProjectRoot = false;
|
|
5972
|
-
for (const project of projects) {
|
|
5973
|
-
const rel = relative(project, root);
|
|
5974
|
-
if (rel === "") isProjectRoot = true;
|
|
5975
|
-
if (rel === "" || rel === ".." || rel.startsWith(`..${sep}`) || isAbsolute(rel)) continue;
|
|
5976
|
-
const dotted = rel.split(sep).find((c) => CREDENTIAL_DIR_NAMES.has(c.toLowerCase()));
|
|
5977
|
-
if (dotted === void 0) return void 0;
|
|
5978
|
-
hidden = dotted;
|
|
5979
|
-
}
|
|
5980
|
-
if (isProjectRoot) return "is your project root itself; name a folder inside it";
|
|
5981
|
-
if (hidden !== void 0) return `passes through the credential / version-control directory ${displayUntrustedValue(hidden)} inside your project`;
|
|
5982
|
-
const shown = projects.map((p) => displayUntrustedValue(p)).join(" or ");
|
|
5983
|
-
return projects.length === 0 ? "is outside any usable project root (the current directory and the git work tree are too broad to scope it)" : `resolves to ${displayUntrustedValue(root)}, outside your project (${shown})`;
|
|
5984
|
-
}
|
|
5985
|
-
const CREDENTIAL_DIR_NAMES = /* @__PURE__ */ new Set([
|
|
5986
|
-
".git",
|
|
5987
|
-
".hg",
|
|
5988
|
-
".svn",
|
|
5989
|
-
".ssh",
|
|
5990
|
-
".aws",
|
|
5991
|
-
".gnupg",
|
|
5992
|
-
".docker",
|
|
5993
|
-
".kube",
|
|
5994
|
-
".config",
|
|
5995
|
-
".azure",
|
|
5996
|
-
".gcloud",
|
|
5997
|
-
".terraform",
|
|
5998
|
-
".npm",
|
|
5999
|
-
".pnpm-store",
|
|
6000
|
-
".yarn",
|
|
6001
|
-
".cache",
|
|
6002
|
-
".local"
|
|
6003
|
-
]);
|
|
6004
|
-
function projectRoots(assetOutdir) {
|
|
6005
|
-
const roots = [];
|
|
6006
|
-
const usable = (p) => p !== resolve("/") && !containsOrIs(p, realPath(homedir()));
|
|
6007
|
-
const cwd = realPath(process.cwd());
|
|
6008
|
-
const outdir = realPath(assetOutdir);
|
|
6009
|
-
if (usable(cwd) && (containsOrIs(cwd, outdir) || existsSync(join(cwd, ".git")))) roots.push(cwd);
|
|
6010
|
-
let dir = outdir;
|
|
6011
|
-
for (;;) {
|
|
6012
|
-
if (existsSync(join(dir, ".git"))) {
|
|
6013
|
-
if (usable(dir) && !roots.includes(dir)) roots.push(dir);
|
|
6014
|
-
break;
|
|
6015
|
-
}
|
|
6016
|
-
const parent = dirname(dir);
|
|
6017
|
-
if (parent === dir) break;
|
|
6018
|
-
dir = parent;
|
|
6019
|
-
}
|
|
6020
|
-
return roots;
|
|
6021
|
-
}
|
|
6022
|
-
function containsOrIs(outer, inner) {
|
|
6023
|
-
const rel = relative(outer, inner);
|
|
6024
|
-
return rel === "" || rel !== ".." && !rel.startsWith(`..${sep}`) && !isAbsolute(rel);
|
|
6025
|
-
}
|
|
6026
|
-
function realPath(p, hops = 0) {
|
|
6027
|
-
const abs = resolve(p);
|
|
6028
|
-
try {
|
|
6029
|
-
return realpathSync.native(abs);
|
|
6030
|
-
} catch {
|
|
6031
|
-
const parent = dirname(abs);
|
|
6032
|
-
if (parent === abs) return abs;
|
|
6033
|
-
const realParent = realPath(parent, hops);
|
|
6034
|
-
let link;
|
|
6035
|
-
try {
|
|
6036
|
-
link = readlinkSync(abs);
|
|
6037
|
-
} catch {
|
|
6038
|
-
link = void 0;
|
|
6039
|
-
}
|
|
6040
|
-
if (link !== void 0 && hops < 40) return realPath(resolve(realParent, link), hops + 1);
|
|
6041
|
-
return join(realParent, basename(abs));
|
|
6042
|
-
}
|
|
6043
|
-
}
|
|
6044
|
-
const warnedAbsoluteOutside = /* @__PURE__ */ new Set();
|
|
6045
|
-
function warnAbsoluteOutsideAssembly(opts, absolute, escape) {
|
|
6046
|
-
const logger = getLogger().child("assets");
|
|
6047
|
-
const line = `${opts.subject} has an absolute ${opts.field} pointing outside the assembly: ` + displayUntrustedValue(absolute) + (escape.escape === "symlink" ? ` (through a symbolic link to ${displayUntrustedValue(escape.realPath)})` : "") + `. ${getEmbedConfig().productName} will ${opts.sink}. ` + (escape.escape === "lexical" ? "This is what cdk synth --no-staging emits, and is expected for it; if you did not synthesize with that flag, treat this assembly as untrusted." : "No CDK synth writes this, so treat this assembly as untrusted unless you made that link yourself.");
|
|
6048
|
-
if (warnedAbsoluteOutside.has(line)) {
|
|
6049
|
-
logger.debug(line);
|
|
6050
|
-
return;
|
|
6051
|
-
}
|
|
6052
|
-
warnedAbsoluteOutside.add(line);
|
|
6053
|
-
logger.warn(line);
|
|
6054
|
-
}
|
|
6055
|
-
const warnedWholeAssembly = /* @__PURE__ */ new Set();
|
|
6056
|
-
function warnWholeAssemblyAsSource(opts, outdir) {
|
|
6057
|
-
const logger = getLogger().child("assets");
|
|
6058
|
-
const line = `${opts.subject} has ${opts.field} naming the assembly's output directory ITSELF: ${displayUntrustedValue(outdir)}. ${getEmbedConfig().productName} will ${opts.sink} — that is the WHOLE assembly, every template and every staged asset, not one asset directory. No CDK synth emits this, so treat this assembly as untrusted unless you wrote that path yourself.`;
|
|
6059
|
-
if (warnedWholeAssembly.has(line)) {
|
|
6060
|
-
logger.debug(line);
|
|
6061
|
-
return;
|
|
6062
|
-
}
|
|
6063
|
-
warnedWholeAssembly.add(line);
|
|
6064
|
-
logger.warn(line);
|
|
6065
|
-
}
|
|
6066
|
-
|
|
6067
|
-
//#endregion
|
|
6068
|
-
//#region src/assets/docker-cache-option.ts
|
|
6069
|
-
function cacheOptionToFlag(option) {
|
|
6070
|
-
let flag = `type=${option.type}`;
|
|
6071
|
-
if (option.params) for (const [k, v] of Object.entries(option.params)) flag += `,${k}=${v}`;
|
|
6072
|
-
return flag;
|
|
6073
|
-
}
|
|
6074
|
-
|
|
6075
|
-
//#endregion
|
|
6076
|
-
//#region src/assets/buildkit-passthrough-warnings.ts
|
|
6077
|
-
function candidateHostPaths(value, opts) {
|
|
6078
|
-
const out = [];
|
|
6079
|
-
for (const part of value.split(",")) {
|
|
6080
|
-
const eq = part.indexOf("=");
|
|
6081
|
-
if (eq < 0) {
|
|
6082
|
-
const bare = part.trim();
|
|
6083
|
-
if (bare.length > 0) out.push({
|
|
6084
|
-
path: bare,
|
|
6085
|
-
write: opts.bareIsWrite
|
|
6086
|
-
});
|
|
6087
|
-
continue;
|
|
6088
|
-
}
|
|
6089
|
-
const key = part.slice(0, eq).trim().toLowerCase();
|
|
6090
|
-
const v = part.slice(eq + 1).trim();
|
|
6091
|
-
if (v.length === 0) continue;
|
|
6092
|
-
if (key !== "src" && key !== "source" && key !== "dest") continue;
|
|
6093
|
-
out.push({
|
|
6094
|
-
path: v,
|
|
6095
|
-
write: key === "dest"
|
|
6096
|
-
});
|
|
6097
|
-
}
|
|
6098
|
-
return out;
|
|
6099
|
-
}
|
|
6100
|
-
function hostPathsOf(source) {
|
|
6101
|
-
const refs = [];
|
|
6102
|
-
if (source.dockerFile) refs.push({
|
|
6103
|
-
field: "dockerFile",
|
|
6104
|
-
where: "dockerFile",
|
|
6105
|
-
path: source.dockerFile,
|
|
6106
|
-
write: false
|
|
6107
|
-
});
|
|
6108
|
-
for (const [k, v] of Object.entries(source.dockerBuildContexts ?? {})) {
|
|
6109
|
-
const rendered = `${k}=${v}`;
|
|
6110
|
-
const contextPath = rendered.slice(rendered.indexOf("=") + 1).trim().replace(/^oci-layout:\/\//, "");
|
|
6111
|
-
if (contextPath.length === 0) continue;
|
|
6112
|
-
refs.push({
|
|
6113
|
-
field: "dockerBuildContexts",
|
|
6114
|
-
where: k,
|
|
6115
|
-
path: contextPath,
|
|
6116
|
-
write: false
|
|
6117
|
-
});
|
|
6118
|
-
}
|
|
6119
|
-
const ssh = source.dockerBuildSsh ?? "";
|
|
6120
|
-
const sshEq = ssh.indexOf("=");
|
|
6121
|
-
(sshEq < 0 ? [] : ssh.slice(sshEq + 1).split(",")).forEach((entry, i) => {
|
|
6122
|
-
const p = entry.trim();
|
|
6123
|
-
if (p.length > 0) refs.push({
|
|
6124
|
-
field: "dockerBuildSsh",
|
|
6125
|
-
where: String(i),
|
|
6126
|
-
path: p,
|
|
6127
|
-
write: false
|
|
6128
|
-
});
|
|
6129
|
-
});
|
|
6130
|
-
for (const [k, v] of Object.entries(source.dockerBuildSecrets ?? {})) for (const { path: p, write } of candidateHostPaths(`id=${k},${v}`, { bareIsWrite: false })) refs.push({
|
|
6131
|
-
field: "dockerBuildSecrets",
|
|
6132
|
-
where: k,
|
|
6133
|
-
path: p,
|
|
6134
|
-
write
|
|
6135
|
-
});
|
|
6136
|
-
(source.cacheFrom ?? []).forEach((c, i) => {
|
|
6137
|
-
for (const { path: p, write } of candidateHostPaths(cacheOptionToFlag(c), { bareIsWrite: false })) refs.push({
|
|
6138
|
-
field: "cacheFrom",
|
|
6139
|
-
where: String(i),
|
|
6140
|
-
path: p,
|
|
6141
|
-
write
|
|
6142
|
-
});
|
|
6143
|
-
});
|
|
6144
|
-
if (source.cacheTo) for (const { path: p, write } of candidateHostPaths(cacheOptionToFlag(source.cacheTo), { bareIsWrite: false })) refs.push({
|
|
6145
|
-
field: "cacheTo",
|
|
6146
|
-
where: "cacheTo",
|
|
6147
|
-
path: p,
|
|
6148
|
-
write
|
|
6149
|
-
});
|
|
6150
|
-
(source.dockerOutputs ?? []).forEach((o, i) => {
|
|
6151
|
-
for (const { path: p, write } of candidateHostPaths(o, { bareIsWrite: true })) refs.push({
|
|
6152
|
-
field: "dockerOutputs",
|
|
6153
|
-
where: String(i),
|
|
6154
|
-
path: p,
|
|
6155
|
-
write
|
|
6156
|
-
});
|
|
6157
|
-
});
|
|
6158
|
-
return refs;
|
|
6159
|
-
}
|
|
6160
|
-
const warnedPassthroughs = /* @__PURE__ */ new Set();
|
|
6161
|
-
function warnEscapingBuildKitPaths(source, base, bound) {
|
|
6162
|
-
const logger = getLogger().child("assets");
|
|
6163
|
-
for (const ref of hostPathsOf(source)) {
|
|
6164
|
-
const escape = assemblyPathEscape(base, bound, ref.path);
|
|
6165
|
-
if (escape === void 0) continue;
|
|
6166
|
-
const verb = ref.write ? "WRITE to" : "read";
|
|
6167
|
-
const line = `Docker asset ${ref.field}` + (ref.where === ref.field ? "" : `[${displayUntrustedValue(ref.where)}]`) + ` names a host path outside the assembly, which ` + renderAssemblyPathEscape(escape, bound, "load", `${getEmbedConfig().productName} will ${verb} it during the image build, matching the CDK CLI — a pre-synthesized assembly is trusted input. If you did not produce this assembly, that is a host path it chose and the CloudFormation template does not show.`);
|
|
6168
|
-
if (warnedPassthroughs.has(line)) {
|
|
6169
|
-
logger.debug(line);
|
|
6170
|
-
continue;
|
|
6171
|
-
}
|
|
6172
|
-
warnedPassthroughs.add(line);
|
|
6173
|
-
logger.warn(line);
|
|
6174
|
-
}
|
|
6175
|
-
}
|
|
6176
|
-
|
|
6177
|
-
//#endregion
|
|
6178
|
-
//#region src/assets/docker-build.ts
|
|
6179
|
-
const warnedExecutables = /* @__PURE__ */ new Set();
|
|
6180
|
-
function warnManifestExecutable(cmd, executable, cwd) {
|
|
6181
|
-
const logger = getLogger().child("docker-build");
|
|
6182
|
-
const key = JSON.stringify([cwd, executable]);
|
|
6183
|
-
if (warnedExecutables.has(key)) {
|
|
6184
|
-
logger.debug(`source.executable already announced this process: ${displayUntrustedValue(cmd)} (cwd=${displayUntrustedValue(cwd)})`);
|
|
6185
|
-
return;
|
|
6186
|
-
}
|
|
6187
|
-
warnedExecutables.add(key);
|
|
6188
|
-
const argCount = executable.length - 1;
|
|
6189
|
-
logger.warn(`Docker asset source.executable runs a command this asset manifest chose, on this machine: ${displayUntrustedValue(cmd)}` + (argCount > 0 ? ` (with ${argCount} argument(s); --verbose shows them)` : "") + `. ${getEmbedConfig().productName} runs it, matching the CDK CLI — a pre-synthesized assembly is trusted input. Note that this means running a local command against a pre-synthesized assembly DOES execute code from it, which the CloudFormation template does not show.`);
|
|
6190
|
-
}
|
|
6191
|
-
async function buildDockerImage(asset, cdkOutDir, options) {
|
|
6192
|
-
const source = asset.source;
|
|
6193
|
-
const logger = getLogger().child("docker-build");
|
|
6194
|
-
const assetOutdir = options.assetOutdir ?? cdkOutDir;
|
|
6195
|
-
const contextDirectory = (directory, sink) => resolveAssetSourcePath({
|
|
6196
|
-
manifestDir: cdkOutDir,
|
|
6197
|
-
value: directory,
|
|
6198
|
-
assetOutdir,
|
|
6199
|
-
absolute: "fold",
|
|
6200
|
-
field: "source.directory",
|
|
6201
|
-
subject: "Docker image asset",
|
|
6202
|
-
action: "build it",
|
|
6203
|
-
sink,
|
|
6204
|
-
wrapError: (message) => new LocalInvokeBuildError(message)
|
|
6205
|
-
});
|
|
6206
|
-
if (source.executable && source.executable.length > 0) {
|
|
6207
|
-
const [cmd, ...args] = source.executable;
|
|
6208
|
-
if (!cmd) throw options.wrapError("asset source.executable[] is empty");
|
|
6209
|
-
const cwd = source.directory ? contextDirectory(source.directory, "run this asset's source.executable with that directory as its working directory") : cdkOutDir;
|
|
6210
|
-
logger.debug(`Building Docker image via executable: ${displayUntrustedValue(redactDockerArgvValues(source.executable).join(" "))} (cwd=${displayUntrustedValue(cwd)})`);
|
|
6211
|
-
warnManifestExecutable(cmd, source.executable, cwd);
|
|
6212
|
-
let result;
|
|
6213
|
-
try {
|
|
6214
|
-
result = await spawnStreaming(cmd, args, { cwd });
|
|
6215
|
-
} catch (err) {
|
|
6216
|
-
const e = err;
|
|
6217
|
-
throw options.wrapError(displayToolOutput(e.stderr || e.message || String(err)));
|
|
6218
|
-
}
|
|
6219
|
-
const tag = result.stdout.trim();
|
|
6220
|
-
if (!tag) throw options.wrapError(`docker build executable produced no output (expected the local image tag on stdout): ${displayUntrustedValue(cmd)}`);
|
|
6221
|
-
return tag;
|
|
6222
|
-
}
|
|
6223
|
-
if (!source.directory) throw options.wrapError(`DockerImageAssetSource must set either 'directory' or 'executable' (fields present: ${displayUntrustedValue(Object.keys(source).join(", ") || "none")})`);
|
|
6224
|
-
if (!options.tag) throw options.wrapError("buildDockerImage(directory mode) requires options.tag");
|
|
6225
|
-
const buildArgs = buildDockerBuildCommand(source, options.tag, options.platform);
|
|
6226
|
-
const contextDir = contextDirectory(source.directory, `send that directory to docker build as the context of an image ${getEmbedConfig().productName} then runs locally`);
|
|
6227
|
-
buildArgs.push(".");
|
|
6228
|
-
warnEscapingBuildKitPaths(source, contextDir, assetOutdir);
|
|
6229
|
-
logger.debug(`${getDockerCmd()} ${redactDockerArgvValues(buildArgs).map((a) => displayUntrustedValue(a)).join(" ")} (cwd=${displayUntrustedValue(contextDir)})`);
|
|
6230
|
-
try {
|
|
6231
|
-
await runDockerStreaming(buildArgs, {
|
|
6232
|
-
cwd: contextDir,
|
|
6233
|
-
env: { BUILDX_NO_DEFAULT_ATTESTATIONS: "1" },
|
|
6234
|
-
...options.progressLabel !== void 0 && { progressLabel: options.progressLabel }
|
|
6235
|
-
});
|
|
6236
|
-
} catch (err) {
|
|
6237
|
-
const e = err;
|
|
6238
|
-
throw options.wrapError(displayToolOutput(e.stderr || e.message || String(err)));
|
|
6239
|
-
}
|
|
6240
|
-
return options.tag;
|
|
6241
|
-
}
|
|
6242
|
-
function buildDockerBuildCommand(source, tag, platformOverride) {
|
|
6243
|
-
const args = [
|
|
6244
|
-
"build",
|
|
6245
|
-
"--tag",
|
|
6246
|
-
tag
|
|
6247
|
-
];
|
|
6248
|
-
if (source.dockerBuildArgs) for (const [k, v] of Object.entries(source.dockerBuildArgs)) args.push("--build-arg", `${k}=${v}`);
|
|
6249
|
-
if (source.dockerBuildContexts) for (const [k, v] of Object.entries(source.dockerBuildContexts)) args.push("--build-context", `${k}=${v}`);
|
|
6250
|
-
if (source.dockerBuildSecrets) for (const [k, v] of Object.entries(source.dockerBuildSecrets)) args.push("--secret", `id=${k},${v}`);
|
|
6251
|
-
if (source.dockerBuildSsh) args.push("--ssh", source.dockerBuildSsh);
|
|
6252
|
-
if (source.dockerBuildTarget) args.push("--target", source.dockerBuildTarget);
|
|
6253
|
-
if (source.dockerFile) args.push("--file", source.dockerFile);
|
|
6254
|
-
if (source.networkMode) args.push("--network", source.networkMode);
|
|
6255
|
-
const platform = platformOverride ?? source.platform;
|
|
6256
|
-
if (platform) args.push("--platform", platform);
|
|
6257
|
-
if (source.dockerOutputs) for (const output of source.dockerOutputs) args.push(`--output=${output}`);
|
|
6258
|
-
if (source.cacheFrom) for (const c of source.cacheFrom) args.push("--cache-from", cacheOptionToFlag(c));
|
|
6259
|
-
if (source.cacheTo) args.push("--cache-to", cacheOptionToFlag(source.cacheTo));
|
|
6260
|
-
if (source.cacheDisabled) args.push("--no-cache");
|
|
6261
|
-
return args;
|
|
6262
|
-
}
|
|
6263
|
-
|
|
6264
|
-
//#endregion
|
|
6265
|
-
//#region src/local/ecr-puller.ts
|
|
6266
|
-
function parseEcrUri(imageUri) {
|
|
6267
|
-
const host = parseEcrRegistryHost(imageUri);
|
|
6268
|
-
if (!host) return void 0;
|
|
6269
|
-
const canonicalUri = canonicalizeImageUriHost(imageUri);
|
|
6270
|
-
const m = /^([^:]+):(.+)$/.exec(canonicalUri.slice(canonicalUri.indexOf("/") + 1));
|
|
6271
|
-
if (!m) return void 0;
|
|
6272
|
-
return {
|
|
6273
|
-
accountId: host.accountId,
|
|
6274
|
-
region: host.region,
|
|
6275
|
-
repository: m[1],
|
|
6276
|
-
tag: m[2],
|
|
6277
|
-
canonicalUri,
|
|
6278
|
-
registryHost: host.registryHost
|
|
6279
|
-
};
|
|
6280
|
-
}
|
|
6281
|
-
const ASSUMED_ROLE_CACHE = /* @__PURE__ */ new Map();
|
|
6282
|
-
const CALLER_IDENTITY_CACHE = /* @__PURE__ */ new Map();
|
|
6283
|
-
const STS_CREDENTIAL_SAFETY_MARGIN_MS = 300 * 1e3;
|
|
6284
|
-
function isCredentialFresh(creds) {
|
|
6285
|
-
if (!creds.expiration) return false;
|
|
6286
|
-
return creds.expiration.getTime() - Date.now() > STS_CREDENTIAL_SAFETY_MARGIN_MS;
|
|
6287
|
-
}
|
|
6288
|
-
async function pullEcrImage(imageUri, options) {
|
|
6289
|
-
const logger = getLogger().child("ecr-puller");
|
|
6290
|
-
const parsed = parseEcrUri(imageUri);
|
|
6291
|
-
if (!parsed) throw new LocalInvokeBuildError(`Image URI ${displayUntrustedValue(imageUri)} is not an ECR URI. ${getEmbedConfig().cliName} invoke v1 only authenticates against ECR for the deployed-image fallback path.`);
|
|
6292
|
-
const canonicalUri = parsed.canonicalUri;
|
|
6293
|
-
const callerRegion = options.region ?? process.env["AWS_REGION"] ?? process.env["AWS_DEFAULT_REGION"];
|
|
6294
|
-
if (options.skipPull) {
|
|
6295
|
-
logger.info(`Skipping ECR pull (--no-pull). Verifying ${canonicalUri} is in local cache...`);
|
|
6296
|
-
await verifyImageInLocalCache(canonicalUri);
|
|
6297
|
-
return canonicalUri;
|
|
6298
|
-
}
|
|
6299
|
-
const callerIdentityKey = `${options.profile ?? "_noprofile"}|${callerRegion ?? "_unset"}`;
|
|
6300
|
-
let callerAccount = CALLER_IDENTITY_CACHE.get(callerIdentityKey);
|
|
6301
|
-
if (callerAccount === void 0) {
|
|
6302
|
-
const sts = new STSClient(buildStsClientConfig({
|
|
6303
|
-
region: callerRegion,
|
|
6304
|
-
profile: options.profile
|
|
6305
|
-
}));
|
|
6306
|
-
try {
|
|
6307
|
-
const identity = await sts.send(new GetCallerIdentityCommand({}));
|
|
6308
|
-
if (!identity.Account) throw new LocalInvokeBuildError("STS GetCallerIdentity returned no Account. Verify your AWS credentials.");
|
|
6309
|
-
callerAccount = identity.Account;
|
|
6310
|
-
CALLER_IDENTITY_CACHE.set(callerIdentityKey, callerAccount);
|
|
6311
|
-
} catch (err) {
|
|
6312
|
-
if (err instanceof LocalInvokeBuildError) throw err;
|
|
6313
|
-
throw new LocalInvokeBuildError(`STS GetCallerIdentity failed while preparing the ECR pull: ${describeAwsFailureForWarn(err, "STS GetCallerIdentity (ECR pull)")}. Verify your AWS credentials.`);
|
|
6314
|
-
} finally {
|
|
6315
|
-
sts.destroy();
|
|
6316
|
-
}
|
|
6317
|
-
}
|
|
6318
|
-
const crossAccount = callerAccount !== parsed.accountId;
|
|
6319
|
-
const crossRegion = callerRegion !== void 0 && callerRegion !== parsed.region;
|
|
6320
|
-
let assumed;
|
|
6321
|
-
if (options.ecrRoleArn) {
|
|
6322
|
-
const cacheKey = `${options.profile ?? "_noprofile"}|${options.ecrRoleArn}|${callerRegion ?? "_unset"}`;
|
|
6323
|
-
const cached = ASSUMED_ROLE_CACHE.get(cacheKey);
|
|
6324
|
-
if (cached && isCredentialFresh(cached)) {
|
|
6325
|
-
assumed = cached;
|
|
6326
|
-
logger.debug(`Reusing cached AssumeRole credentials for ${options.ecrRoleArn}`);
|
|
6327
|
-
} else {
|
|
6328
|
-
assumed = await assumeRoleForEcr(options.ecrRoleArn, callerRegion, options.profile, logger);
|
|
6329
|
-
ASSUMED_ROLE_CACHE.set(cacheKey, assumed);
|
|
6330
|
-
logger.info(`Assumed role ${options.ecrRoleArn} for ECR pull (account=${parsed.accountId}, region=${parsed.region})`);
|
|
6331
|
-
}
|
|
6332
|
-
} else if (crossAccount) logger.info(`Cross-account ECR pull: image account ${parsed.accountId} != caller ${callerAccount}. Using the caller's credentials; pass --ecr-role-arn <arn> if AWS rejects with AccessDenied.`);
|
|
6333
|
-
if (crossRegion) logger.info(`Cross-region ECR pull: image region ${parsed.region} != caller ${callerRegion ?? "(unset)"}. Authenticating against the image region directly.`);
|
|
6334
|
-
const ecr = new ECRClient({
|
|
6335
|
-
...buildProxyClientConfig({ profile: options.profile }),
|
|
6336
|
-
region: parsed.region,
|
|
6337
|
-
...assumed ? { credentials: assumed } : options.profile ? { profile: options.profile } : {}
|
|
6338
|
-
});
|
|
6339
|
-
try {
|
|
6340
|
-
await ecrLogin(ecr, {
|
|
6341
|
-
accountId: parsed.accountId,
|
|
6342
|
-
region: parsed.region,
|
|
6343
|
-
registryHost: parsed.registryHost
|
|
6344
|
-
});
|
|
6345
|
-
} finally {
|
|
6346
|
-
ecr.destroy();
|
|
6347
|
-
}
|
|
6348
|
-
logger.info(`Pulling ${canonicalUri}...`);
|
|
6349
|
-
try {
|
|
6350
|
-
await runDockerForeground(["pull", canonicalUri]);
|
|
6351
|
-
} catch (err) {
|
|
6352
|
-
throw new LocalInvokeBuildError(`docker pull ${canonicalUri} failed: ${err.message}`);
|
|
6353
|
-
}
|
|
6354
|
-
return canonicalUri;
|
|
6355
|
-
}
|
|
6356
|
-
async function assumeRoleForEcr(roleArn, callerRegion, profile, logger) {
|
|
6357
|
-
if (!isIamRoleArn(roleArn)) throw new LocalInvokeBuildError(refusedRoleArnMessage(roleArn));
|
|
6358
|
-
logger.debug(`Assuming role ${roleArn} for ECR pull...`);
|
|
6359
|
-
const sts = new STSClient(workloadStsClientConfig({
|
|
6360
|
-
region: callerRegion,
|
|
6361
|
-
profile
|
|
6362
|
-
}));
|
|
6363
|
-
try {
|
|
6364
|
-
const creds = (await sts.send(new AssumeRoleCommand({
|
|
6365
|
-
RoleArn: roleArn,
|
|
6366
|
-
RoleSessionName: `${getEmbedConfig().resourceNamePrefix}-ecr-${Date.now()}`,
|
|
6367
|
-
DurationSeconds: 3600
|
|
6368
|
-
}))).Credentials;
|
|
6369
|
-
if (!creds || !creds.AccessKeyId || !creds.SecretAccessKey || !creds.SessionToken) throw new LocalInvokeBuildError(`AssumeRole(${roleArn}) returned no usable credentials. Verify the role's trust policy allows your identity to assume it.`);
|
|
6370
|
-
return {
|
|
6371
|
-
accessKeyId: creds.AccessKeyId,
|
|
6372
|
-
secretAccessKey: creds.SecretAccessKey,
|
|
6373
|
-
sessionToken: creds.SessionToken,
|
|
6374
|
-
...creds.Expiration && { expiration: creds.Expiration }
|
|
6375
|
-
};
|
|
6376
|
-
} catch (err) {
|
|
6377
|
-
if (err instanceof LocalInvokeBuildError) throw err;
|
|
6378
|
-
const reason = describeAwsFailureForWarn(err, "STS AssumeRole (ECR pull)");
|
|
6379
|
-
throw new LocalInvokeBuildError(`Failed to assume role ${flattenToOneLine(roleArn)} for ECR pull: ${reason}. Verify the role exists and its trust policy permits the caller's identity to assume it.`);
|
|
6380
|
-
} finally {
|
|
6381
|
-
sts.destroy();
|
|
6382
|
-
}
|
|
6383
|
-
}
|
|
6384
|
-
async function ecrLogin(client, target) {
|
|
6385
|
-
const { accountId, region, registryHost } = target;
|
|
6386
|
-
getLogger().child("ecr-puller").debug(`ECR login (account=${accountId}, region=${region}, host=${registryHost})`);
|
|
6387
|
-
const authData = (await client.send(new GetAuthorizationTokenCommand({})).catch((err) => {
|
|
6388
|
-
throw new LocalInvokeBuildError(`ECR GetAuthorizationToken failed (account=${accountId}, region=${region}): ${describeAwsFailureForWarn(err, "ECR GetAuthorizationToken")}. Verify the credentials can call ecr:GetAuthorizationToken.`);
|
|
6389
|
-
})).authorizationData?.[0];
|
|
6390
|
-
if (!authData?.authorizationToken) throw new LocalInvokeBuildError("Failed to get ECR authorization token");
|
|
6391
|
-
const [username, password] = Buffer.from(authData.authorizationToken, "base64").toString().split(":");
|
|
6392
|
-
if (!username || password === void 0) throw new LocalInvokeBuildError("ECR authorization token has unexpected shape (missing username/password)");
|
|
6393
|
-
const endpoint = `https://${registryHost}`;
|
|
6394
|
-
try {
|
|
6395
|
-
await runDockerStreaming([
|
|
6396
|
-
"login",
|
|
6397
|
-
"--username",
|
|
6398
|
-
username,
|
|
6399
|
-
"--password-stdin",
|
|
6400
|
-
endpoint
|
|
6401
|
-
], { input: password });
|
|
6402
|
-
} catch (err) {
|
|
6403
|
-
const e = err;
|
|
6404
|
-
throw new LocalInvokeBuildError(`ECR login failed: ${formatDockerLoginError(e.stderr || e.message || String(err), endpoint)}`);
|
|
6405
|
-
}
|
|
6406
|
-
}
|
|
6407
|
-
async function verifyImageInLocalCache(imageUri) {
|
|
6408
|
-
try {
|
|
6409
|
-
await runDockerStreaming([
|
|
6410
|
-
"image",
|
|
6411
|
-
"inspect",
|
|
6412
|
-
imageUri
|
|
6413
|
-
]);
|
|
6414
|
-
} catch {
|
|
6415
|
-
throw new LocalInvokeBuildError(`Image ${displayUntrustedValue(imageUri)} is not in the local docker cache and --no-pull was set. Either remove --no-pull (${getEmbedConfig().productName} will pull from ECR) or pre-pull the image manually with \`docker pull\`.`);
|
|
6416
|
-
}
|
|
6417
|
-
}
|
|
6418
|
-
async function isImageInLocalCache(imageRef) {
|
|
6419
|
-
try {
|
|
6420
|
-
await runDockerStreaming([
|
|
6421
|
-
"image",
|
|
6422
|
-
"inspect",
|
|
6423
|
-
imageRef
|
|
6424
|
-
]);
|
|
6425
|
-
return true;
|
|
6426
|
-
} catch {
|
|
6427
|
-
return false;
|
|
6428
|
-
}
|
|
6429
|
-
}
|
|
6430
|
-
|
|
6431
|
-
//#endregion
|
|
6432
|
-
//#region src/local/docker-image-builder.ts
|
|
6433
|
-
async function buildContainerImage(asset, cdkOutDir, options) {
|
|
6434
|
-
const tag = computeLocalTag(asset.source);
|
|
6435
|
-
const platform = architectureToPlatform(options.architecture);
|
|
6436
|
-
const logger = getLogger().child("local-invoke-build");
|
|
6437
|
-
if (options.noBuild === true) {
|
|
6438
|
-
logger.info(`Skipping docker build (--no-build). Verifying ${tag} is in local registry...`);
|
|
6439
|
-
if (!await isImageInLocalCache(tag)) throw new LocalInvokeBuildError(`image ${displayIdent(tag)} not in local registry and --no-build is set; remove --no-build or run \`docker build\` manually first.`);
|
|
6440
|
-
logger.debug(`Local tag ${tag} is cached; skipping build.`);
|
|
6441
|
-
return tag;
|
|
6442
|
-
}
|
|
6443
|
-
logger.info(`Building container image (platform=${platform})...`);
|
|
6444
|
-
logger.debug(`Local tag: ${tag}`);
|
|
6445
|
-
const actualTag = await buildDockerImage(asset, cdkOutDir, {
|
|
6446
|
-
tag,
|
|
6447
|
-
platform,
|
|
6448
|
-
wrapError: (stderr) => new LocalInvokeBuildError(`docker build failed for container Lambda asset (${displayUntrustedValue(asset.source.directory ?? asset.source.executable?.[0] ?? "")}): ${stderr}`),
|
|
6449
|
-
progressLabel: `Building container image (platform=${platform})`,
|
|
6450
|
-
...options.assetOutdir !== void 0 && { assetOutdir: options.assetOutdir }
|
|
6451
|
-
});
|
|
6452
|
-
if (actualTag !== tag) {
|
|
6453
|
-
logger.debug(`Re-tagging executable-built image ${displayIdent(actualTag)} → ${displayIdent(tag)}`);
|
|
6454
|
-
try {
|
|
6455
|
-
await runDockerStreaming([
|
|
6456
|
-
"tag",
|
|
6457
|
-
actualTag,
|
|
6458
|
-
tag
|
|
6459
|
-
]);
|
|
6460
|
-
} catch (err) {
|
|
6461
|
-
const e = err;
|
|
6462
|
-
throw new LocalInvokeBuildError(`docker tag failed re-tagging ${displayIdent(actualTag)} → ${displayIdent(tag)}: ${displayToolOutput(e.stderr?.trim() || e.message || String(err))}`);
|
|
6463
|
-
}
|
|
6464
|
-
}
|
|
6465
|
-
return tag;
|
|
6466
|
-
}
|
|
6467
|
-
function architectureToPlatform(architecture) {
|
|
6468
|
-
return architecture === "arm64" ? "linux/arm64" : "linux/amd64";
|
|
6469
|
-
}
|
|
6470
|
-
function hostPlatform() {
|
|
6471
|
-
return process.arch === "arm64" ? "linux/arm64" : "linux/amd64";
|
|
6472
|
-
}
|
|
6473
|
-
const warnedEmulatedPlatforms = /* @__PURE__ */ new Set();
|
|
6474
|
-
function warnIfEmulatedPlatform(platform, opts = {}) {
|
|
6475
|
-
if (!platform) return;
|
|
6476
|
-
const host = hostPlatform();
|
|
6477
|
-
if (platform === host) return;
|
|
6478
|
-
if (warnedEmulatedPlatforms.has(platform)) return;
|
|
6479
|
-
warnedEmulatedPlatforms.add(platform);
|
|
6480
|
-
const logger = opts.logger ?? getLogger();
|
|
6481
|
-
const what = opts.label ? `${displayIdent(opts.label)} ` : "";
|
|
6482
|
-
logger.warn(`Running ${what}under ${platform} emulation on a ${host} host (the declared architecture differs from the host). Emulation is slower and some compiled binaries can fail under it. If the container does not run correctly, enable Rosetta for x86/amd64 emulation in your Docker engine settings, or build the function for ${host}.`);
|
|
6483
|
-
}
|
|
6484
|
-
function computeLocalTag(source) {
|
|
6485
|
-
const hash = createHash("sha256");
|
|
6486
|
-
pushField(hash, "directory", source.directory ?? "");
|
|
6487
|
-
pushField(hash, "executable", (source.executable ?? []).join(" "));
|
|
6488
|
-
pushField(hash, "dockerFile", source.dockerFile ?? "");
|
|
6489
|
-
pushField(hash, "dockerBuildTarget", source.dockerBuildTarget ?? "");
|
|
6490
|
-
pushField(hash, "networkMode", source.networkMode ?? "");
|
|
6491
|
-
pushField(hash, "platform", source.platform ?? "");
|
|
6492
|
-
pushField(hash, "dockerBuildSsh", source.dockerBuildSsh ?? "");
|
|
6493
|
-
pushField(hash, "cacheDisabled", source.cacheDisabled ? "1" : "0");
|
|
6494
|
-
pushMap(hash, "dockerBuildArgs", source.dockerBuildArgs);
|
|
6495
|
-
pushMap(hash, "dockerBuildContexts", source.dockerBuildContexts);
|
|
6496
|
-
pushMap(hash, "dockerBuildSecrets", source.dockerBuildSecrets);
|
|
6497
|
-
pushField(hash, "dockerOutputs", (source.dockerOutputs ?? []).join(""));
|
|
6498
|
-
pushField(hash, "cacheFrom", (source.cacheFrom ?? []).map((o) => JSON.stringify(o)).join(""));
|
|
6499
|
-
pushField(hash, "cacheTo", source.cacheTo ? JSON.stringify(source.cacheTo) : "");
|
|
6500
|
-
return `${getEmbedConfig().resourceNamePrefix}-invoke-${hash.digest("hex").slice(0, 16)}`;
|
|
6501
|
-
}
|
|
6502
|
-
function pushField(hash, name, value) {
|
|
6503
|
-
hash.update(name);
|
|
6504
|
-
hash.update("=");
|
|
6505
|
-
hash.update(value);
|
|
6506
|
-
hash.update("\0");
|
|
6507
|
-
}
|
|
6508
|
-
function pushMap(hash, name, value) {
|
|
6509
|
-
hash.update(name);
|
|
6510
|
-
hash.update("={");
|
|
6511
|
-
if (value) for (const [k, v] of Object.entries(value)) {
|
|
6512
|
-
hash.update(k);
|
|
6513
|
-
hash.update("=");
|
|
6514
|
-
hash.update(v);
|
|
6515
|
-
hash.update(";");
|
|
6516
|
-
}
|
|
6517
|
-
hash.update("}\0");
|
|
6518
|
-
}
|
|
6519
|
-
|
|
6520
|
-
//#endregion
|
|
6521
|
-
//#region src/local/docker-runner.ts
|
|
6522
|
-
const execFileAsync$7 = promisify(execFile);
|
|
6523
|
-
var DockerRunnerError = class DockerRunnerError extends Error {
|
|
6524
|
-
constructor(message) {
|
|
6525
|
-
super(message);
|
|
6526
|
-
this.name = "DockerRunnerError";
|
|
6527
|
-
Object.setPrototypeOf(this, DockerRunnerError.prototype);
|
|
6528
|
-
}
|
|
6529
|
-
};
|
|
6530
|
-
async function pullImage(image, skipPull, platform) {
|
|
6531
|
-
const logger = getLogger().child("docker");
|
|
6532
|
-
if (skipPull) {
|
|
6533
|
-
logger.debug(`Skipping docker pull for ${displayIdent(image)} (--no-pull)`);
|
|
6534
|
-
return;
|
|
6535
|
-
}
|
|
6536
|
-
const platformArgs = platform ? ["--platform", platform] : [];
|
|
6537
|
-
if (getLogger().getLevel() === "debug") {
|
|
6538
|
-
logger.info(`Pulling ${displayIdent(image)}${platform ? ` (${displayIdent(platform)})` : ""}...`);
|
|
6539
|
-
try {
|
|
6540
|
-
await runDockerForeground([
|
|
6541
|
-
"pull",
|
|
6542
|
-
...platformArgs,
|
|
6543
|
-
image
|
|
6544
|
-
]);
|
|
6545
|
-
} catch (err) {
|
|
6546
|
-
const e = err;
|
|
6547
|
-
throw new DockerRunnerError(`docker pull ${displayIdent(image)} failed: ${e.message}`);
|
|
6548
|
-
}
|
|
4546
|
+
if (refLogicalId !== void 0) {
|
|
4547
|
+
if (resources[refLogicalId]?.Type !== "AWS::IAM::Role") return void 0;
|
|
4548
|
+
return `arn:aws:iam::${TASK_ROLE_ACCOUNT_PLACEHOLDER}:role/${refLogicalId}`;
|
|
4549
|
+
}
|
|
4550
|
+
if ("Fn::Join" in obj || "Fn::Sub" in obj) {
|
|
4551
|
+
if (!subContext) return void 0;
|
|
4552
|
+
const sub = substituteAgainstState(value, subContext);
|
|
4553
|
+
if (sub.kind === "literal" && typeof sub.value === "string" && sub.value.length > 0) return sub.value;
|
|
6549
4554
|
return;
|
|
6550
4555
|
}
|
|
6551
|
-
|
|
6552
|
-
|
|
6553
|
-
|
|
6554
|
-
|
|
6555
|
-
|
|
6556
|
-
|
|
6557
|
-
|
|
6558
|
-
|
|
6559
|
-
|
|
4556
|
+
}
|
|
4557
|
+
function pickString(value) {
|
|
4558
|
+
return typeof value === "string" && value.length > 0 ? value : void 0;
|
|
4559
|
+
}
|
|
4560
|
+
function pickStringArray$1(value) {
|
|
4561
|
+
if (!Array.isArray(value)) return void 0;
|
|
4562
|
+
const out = [];
|
|
4563
|
+
for (const v of value) if (typeof v === "string") out.push(v);
|
|
4564
|
+
return out;
|
|
4565
|
+
}
|
|
4566
|
+
function notFoundError$2(target, stack, resources) {
|
|
4567
|
+
const tasks = [];
|
|
4568
|
+
for (const [logicalId, resource] of Object.entries(resources)) {
|
|
4569
|
+
if (resource.Type !== "AWS::ECS::TaskDefinition") continue;
|
|
4570
|
+
const meta = resource.Metadata;
|
|
4571
|
+
const cdkPath = typeof meta?.["aws:cdk:path"] === "string" ? meta["aws:cdk:path"] : "";
|
|
4572
|
+
tasks.push({
|
|
4573
|
+
displayPath: cdkPath || logicalId,
|
|
4574
|
+
logicalId
|
|
6560
4575
|
});
|
|
6561
|
-
} catch (err) {
|
|
6562
|
-
const e = err;
|
|
6563
|
-
if (e.exitCode === void 0 || e.exitCode === null) throw new DockerRunnerError(`docker pull ${displayIdent(image)} failed: ${displayToolOutput(e.message ?? String(err))}`);
|
|
6564
|
-
const detail = e.stderr?.trim() || e.stdout?.trim() || "(no output)";
|
|
6565
|
-
throw new DockerRunnerError(`docker pull ${displayIdent(image)} exited with code ${e.exitCode}: ${displayToolOutput(detail)}`);
|
|
6566
4576
|
}
|
|
6567
|
-
}
|
|
6568
|
-
|
|
6569
|
-
|
|
6570
|
-
|
|
6571
|
-
|
|
6572
|
-
|
|
6573
|
-
];
|
|
6574
|
-
if (opts.name) args.push("--name", opts.name);
|
|
6575
|
-
if (opts.network) args.push("--network", opts.network);
|
|
6576
|
-
if (opts.platform) {
|
|
6577
|
-
args.push("--platform", opts.platform);
|
|
6578
|
-
warnIfEmulatedPlatform(opts.platform, opts.name ? { label: opts.name } : {});
|
|
4577
|
+
let msg = `target '${target}' did not match any ECS task definition in ${stack.stackName}.\n\n`;
|
|
4578
|
+
if (tasks.length === 0) msg += `Stack ${stack.stackName} has no AWS::ECS::TaskDefinition resources.`;
|
|
4579
|
+
else {
|
|
4580
|
+
const width = Math.max(...tasks.map((t) => t.displayPath.length));
|
|
4581
|
+
msg += `Available task definitions in ${stack.stackName}:\n`;
|
|
4582
|
+
for (const t of tasks) msg += ` ${t.displayPath.padEnd(width)} (${displayIdent(t.logicalId)})\n`;
|
|
6579
4583
|
}
|
|
6580
|
-
|
|
6581
|
-
|
|
6582
|
-
|
|
6583
|
-
if (opts.debugPort !== void 0) args.push("-p", `${host}:${opts.debugPort}:${opts.debugPort}`);
|
|
6584
|
-
for (const extra of opts.extraPorts ?? []) args.push("-p", `${host}:${extra.hostPort}:${extra.containerPort}`);
|
|
6585
|
-
for (const mount of opts.mounts) {
|
|
6586
|
-
const ro = mount.readOnly ? ":ro" : "";
|
|
6587
|
-
args.push("-v", `${mount.hostPath}:${mount.containerPath}${ro}`);
|
|
6588
|
-
}
|
|
6589
|
-
if (opts.extraMounts) for (const mount of opts.extraMounts) {
|
|
6590
|
-
const ro = mount.readOnly ? ":ro" : "";
|
|
6591
|
-
args.push("-v", `${mount.hostPath}:${mount.containerPath}${ro}`);
|
|
6592
|
-
}
|
|
6593
|
-
const sensitiveKeys = opts.sensitiveEnvKeys && opts.sensitiveEnvKeys.size > 0 ? /* @__PURE__ */ new Set([...SENSITIVE_ENV_KEYS, ...opts.sensitiveEnvKeys]) : SENSITIVE_ENV_KEYS;
|
|
6594
|
-
const { passthrough: passthroughEnv, collisions } = appendEnvFlags(args, opts.env, sensitiveKeys);
|
|
6595
|
-
if (opts.tmpfs) args.push("--tmpfs", `${opts.tmpfs.target}:rw,size=${opts.tmpfs.sizeMb}m`);
|
|
6596
|
-
if (opts.workingDir) args.push("--workdir", opts.workingDir);
|
|
6597
|
-
let entryPointTail = [];
|
|
6598
|
-
if (opts.entryPoint && opts.entryPoint.length > 0) {
|
|
6599
|
-
args.push("--entrypoint", opts.entryPoint[0]);
|
|
6600
|
-
entryPointTail = opts.entryPoint.slice(1);
|
|
6601
|
-
}
|
|
6602
|
-
args.push(opts.image, ...entryPointTail, ...opts.cmd);
|
|
6603
|
-
const logger = getLogger().child("docker");
|
|
6604
|
-
logger.debug(`${getDockerCmd()} ${redactDockerArgvValues(args).map((a) => displayUntrustedValue(a)).join(" ")}`);
|
|
6605
|
-
if (collisions.length > 0) logger.warn(describeRefusedSensitiveEnvKeys(`Container for image ${displayUntrustedValue(opts.image)}`, collisions));
|
|
6606
|
-
const forwardedKeys = Object.keys(passthroughEnv);
|
|
6607
|
-
const refusal = finchSecretArgvRefusal(forwardedKeys.filter((k) => opts.sensitiveEnvKeys?.has(k)), {
|
|
6608
|
-
label: "Container for image",
|
|
6609
|
-
name: opts.image
|
|
6610
|
-
});
|
|
6611
|
-
if (refusal !== void 0) throw new DockerRunnerError(refusal);
|
|
6612
|
-
warnFinchArgvExposure(forwardedKeys);
|
|
4584
|
+
return new EcsTaskResolutionError(msg.trimEnd());
|
|
4585
|
+
}
|
|
4586
|
+
function checkVolumeHostPath(hostPath) {
|
|
6613
4587
|
try {
|
|
6614
|
-
|
|
6615
|
-
|
|
6616
|
-
|
|
6617
|
-
|
|
6618
|
-
|
|
6619
|
-
|
|
6620
|
-
|
|
6621
|
-
}
|
|
6622
|
-
}
|
|
6623
|
-
|
|
6624
|
-
|
|
6625
|
-
|
|
6626
|
-
|
|
6627
|
-
|
|
6628
|
-
|
|
6629
|
-
|
|
6630
|
-
|
|
6631
|
-
|
|
6632
|
-
|
|
6633
|
-
|
|
6634
|
-
|
|
6635
|
-
|
|
6636
|
-
|
|
6637
|
-
|
|
6638
|
-
|
|
6639
|
-
|
|
6640
|
-
|
|
6641
|
-
|
|
4588
|
+
return existsSync(hostPath) && statSync(hostPath).isDirectory();
|
|
4589
|
+
} catch {
|
|
4590
|
+
return false;
|
|
4591
|
+
}
|
|
4592
|
+
}
|
|
4593
|
+
async function applyCrossStackResolverToTask(task, context) {
|
|
4594
|
+
if (!context.crossStackResolver) return;
|
|
4595
|
+
const { resolveDynamicReferences: _envOnly, ...secretContext } = context;
|
|
4596
|
+
const rawContainers = (task.resource.Properties ?? {})["ContainerDefinitions"];
|
|
4597
|
+
if (!Array.isArray(rawContainers)) return;
|
|
4598
|
+
for (let idx = 0; idx < task.containers.length; idx += 1) {
|
|
4599
|
+
const container = task.containers[idx];
|
|
4600
|
+
const raw = rawContainers[idx];
|
|
4601
|
+
if (!raw || typeof raw !== "object") continue;
|
|
4602
|
+
const c = raw;
|
|
4603
|
+
const containerName = pickString(c["Name"]) ?? container.name;
|
|
4604
|
+
const resolvedEnvKeys = /* @__PURE__ */ new Set();
|
|
4605
|
+
const resolvedSecretNames = /* @__PURE__ */ new Set();
|
|
4606
|
+
if (Array.isArray(c["Environment"])) for (const entry of c["Environment"]) {
|
|
4607
|
+
if (!entry || typeof entry !== "object") continue;
|
|
4608
|
+
const e = entry;
|
|
4609
|
+
const key = pickString(e["Name"]);
|
|
4610
|
+
const value = e["Value"];
|
|
4611
|
+
if (!key) continue;
|
|
4612
|
+
if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") continue;
|
|
4613
|
+
if (Object.hasOwn(container.environment, key)) continue;
|
|
4614
|
+
if (!isCrossStackIntrinsic(value)) continue;
|
|
4615
|
+
const { result: sub, consumedSensitive } = await resolveWithSensitivityAsync(value, context);
|
|
4616
|
+
if (sub.kind === "literal") {
|
|
4617
|
+
defineOwnKey(container.environment, key, String(sub.value));
|
|
4618
|
+
resolvedEnvKeys.add(key);
|
|
4619
|
+
if (consumedSensitive && !container.sensitiveEnvKeys.includes(key)) container.sensitiveEnvKeys.push(key);
|
|
4620
|
+
}
|
|
6642
4621
|
}
|
|
6643
|
-
|
|
6644
|
-
|
|
6645
|
-
|
|
6646
|
-
|
|
6647
|
-
|
|
6648
|
-
if (
|
|
6649
|
-
|
|
6650
|
-
|
|
4622
|
+
if (Array.isArray(c["Secrets"])) for (const entry of c["Secrets"]) {
|
|
4623
|
+
if (!entry || typeof entry !== "object") continue;
|
|
4624
|
+
const e = entry;
|
|
4625
|
+
const sName = pickString(e["Name"]);
|
|
4626
|
+
const valueFromRaw = e["ValueFrom"];
|
|
4627
|
+
if (!sName) continue;
|
|
4628
|
+
if (typeof valueFromRaw === "string" && valueFromRaw.length > 0) continue;
|
|
4629
|
+
if (container.secrets.some((s) => s.name === sName)) continue;
|
|
4630
|
+
if (!isCrossStackIntrinsic(valueFromRaw)) continue;
|
|
4631
|
+
const sub = await substituteAgainstStateAsync(valueFromRaw, secretContext);
|
|
4632
|
+
if (sub.kind === "literal" && typeof sub.value === "string" && sub.value.length > 0) {
|
|
4633
|
+
container.secrets.push({
|
|
4634
|
+
name: sName,
|
|
4635
|
+
valueFrom: sub.value
|
|
4636
|
+
});
|
|
4637
|
+
resolvedSecretNames.add(sName);
|
|
6651
4638
|
}
|
|
6652
4639
|
}
|
|
6653
|
-
|
|
6654
|
-
|
|
6655
|
-
|
|
6656
|
-
|
|
6657
|
-
|
|
6658
|
-
|
|
6659
|
-
|
|
6660
|
-
|
|
6661
|
-
|
|
6662
|
-
|
|
6663
|
-
|
|
6664
|
-
|
|
6665
|
-
if (opts.onOutput) {
|
|
6666
|
-
const tap = opts.onOutput;
|
|
6667
|
-
proc.stdout?.on("data", (chunk) => tap(chunk));
|
|
6668
|
-
proc.stderr?.on("data", (chunk) => tap(chunk));
|
|
6669
|
-
}
|
|
6670
|
-
let flush = () => void 0;
|
|
6671
|
-
if (opts.prefix !== void 0 || process.env["CDKL_PREFIX_CONTAINER_OUTPUT"] === "1") {
|
|
6672
|
-
const tag = opts.prefix ?? `[${flattenToOneLine(containerId.slice(0, 12)).replace(/[\]\s]/g, "_")}] `;
|
|
6673
|
-
const stdoutRelay = createPrefixedLineRelay(tag, process.stdout);
|
|
6674
|
-
const stderrRelay = createPrefixedLineRelay(tag, process.stderr);
|
|
6675
|
-
proc.stdout?.on("data", (chunk) => stdoutRelay.push(chunk));
|
|
6676
|
-
proc.stderr?.on("data", (chunk) => stderrRelay.push(chunk));
|
|
6677
|
-
flush = () => {
|
|
6678
|
-
stdoutRelay.flush();
|
|
6679
|
-
stderrRelay.flush();
|
|
6680
|
-
};
|
|
6681
|
-
proc.on("close", () => flush());
|
|
6682
|
-
} else {
|
|
6683
|
-
proc.stdout?.on("data", (chunk) => process.stdout.write(chunk));
|
|
6684
|
-
proc.stderr?.on("data", (chunk) => process.stderr.write(chunk));
|
|
4640
|
+
if (resolvedEnvKeys.size > 0 || resolvedSecretNames.size > 0) {
|
|
4641
|
+
container.warnings = container.warnings.filter((w) => {
|
|
4642
|
+
for (const k of resolvedEnvKeys) if (w.startsWith(`Environment ${displayIdent(k)} dropped:`)) return false;
|
|
4643
|
+
for (const k of resolvedSecretNames) if (w.startsWith(`Secret ${displayIdent(k)} dropped:`)) return false;
|
|
4644
|
+
return true;
|
|
4645
|
+
});
|
|
4646
|
+
task.warnings = task.warnings.filter((w) => {
|
|
4647
|
+
for (const k of resolvedEnvKeys) if (w.startsWith(`Container ${displayIdent(containerName)}: Environment ${displayIdent(k)} dropped:`)) return false;
|
|
4648
|
+
for (const k of resolvedSecretNames) if (w.startsWith(`Container ${displayIdent(containerName)}: Secret ${displayIdent(k)} dropped:`)) return false;
|
|
4649
|
+
return true;
|
|
4650
|
+
});
|
|
4651
|
+
}
|
|
6685
4652
|
}
|
|
6686
|
-
proc.on("error", () => {});
|
|
6687
|
-
return () => {
|
|
6688
|
-
flush();
|
|
6689
|
-
if (!proc.killed) proc.kill("SIGTERM");
|
|
6690
|
-
};
|
|
6691
4653
|
}
|
|
6692
|
-
|
|
6693
|
-
|
|
6694
|
-
|
|
6695
|
-
|
|
6696
|
-
|
|
6697
|
-
|
|
6698
|
-
|
|
6699
|
-
|
|
6700
|
-
|
|
6701
|
-
|
|
6702
|
-
|
|
6703
|
-
|
|
6704
|
-
|
|
4654
|
+
|
|
4655
|
+
//#endregion
|
|
4656
|
+
//#region src/local/runtime-image.ts
|
|
4657
|
+
const SUPPORTED_RUNTIMES = {
|
|
4658
|
+
"nodejs18.x": {
|
|
4659
|
+
image: "public.ecr.aws/lambda/nodejs:18",
|
|
4660
|
+
fileExtension: ".js"
|
|
4661
|
+
},
|
|
4662
|
+
"nodejs20.x": {
|
|
4663
|
+
image: "public.ecr.aws/lambda/nodejs:20",
|
|
4664
|
+
fileExtension: ".js"
|
|
4665
|
+
},
|
|
4666
|
+
"nodejs22.x": {
|
|
4667
|
+
image: "public.ecr.aws/lambda/nodejs:22",
|
|
4668
|
+
fileExtension: ".js"
|
|
4669
|
+
},
|
|
4670
|
+
"nodejs24.x": {
|
|
4671
|
+
image: "public.ecr.aws/lambda/nodejs:24",
|
|
4672
|
+
fileExtension: ".js"
|
|
4673
|
+
},
|
|
4674
|
+
"python3.11": {
|
|
4675
|
+
image: "public.ecr.aws/lambda/python:3.11",
|
|
4676
|
+
fileExtension: ".py"
|
|
4677
|
+
},
|
|
4678
|
+
"python3.12": {
|
|
4679
|
+
image: "public.ecr.aws/lambda/python:3.12",
|
|
4680
|
+
fileExtension: ".py"
|
|
4681
|
+
},
|
|
4682
|
+
"python3.13": {
|
|
4683
|
+
image: "public.ecr.aws/lambda/python:3.13",
|
|
4684
|
+
fileExtension: ".py"
|
|
4685
|
+
},
|
|
4686
|
+
"python3.14": {
|
|
4687
|
+
image: "public.ecr.aws/lambda/python:3.14",
|
|
4688
|
+
fileExtension: ".py"
|
|
4689
|
+
},
|
|
4690
|
+
"ruby3.2": {
|
|
4691
|
+
image: "public.ecr.aws/lambda/ruby:3.2",
|
|
4692
|
+
fileExtension: ".rb"
|
|
4693
|
+
},
|
|
4694
|
+
"ruby3.3": {
|
|
4695
|
+
image: "public.ecr.aws/lambda/ruby:3.3",
|
|
4696
|
+
fileExtension: ".rb"
|
|
4697
|
+
},
|
|
4698
|
+
"java8.al2": {
|
|
4699
|
+
image: "public.ecr.aws/lambda/java:8.al2",
|
|
4700
|
+
fileExtension: null
|
|
4701
|
+
},
|
|
4702
|
+
java11: {
|
|
4703
|
+
image: "public.ecr.aws/lambda/java:11",
|
|
4704
|
+
fileExtension: null
|
|
4705
|
+
},
|
|
4706
|
+
java17: {
|
|
4707
|
+
image: "public.ecr.aws/lambda/java:17",
|
|
4708
|
+
fileExtension: null
|
|
4709
|
+
},
|
|
4710
|
+
java21: {
|
|
4711
|
+
image: "public.ecr.aws/lambda/java:21",
|
|
4712
|
+
fileExtension: null
|
|
4713
|
+
},
|
|
4714
|
+
dotnet6: {
|
|
4715
|
+
image: "public.ecr.aws/lambda/dotnet:6",
|
|
4716
|
+
fileExtension: null
|
|
4717
|
+
},
|
|
4718
|
+
dotnet8: {
|
|
4719
|
+
image: "public.ecr.aws/lambda/dotnet:8",
|
|
4720
|
+
fileExtension: null
|
|
4721
|
+
},
|
|
4722
|
+
"provided.al2": {
|
|
4723
|
+
image: "public.ecr.aws/lambda/provided:al2",
|
|
4724
|
+
fileExtension: null
|
|
4725
|
+
},
|
|
4726
|
+
"provided.al2023": {
|
|
4727
|
+
image: "public.ecr.aws/lambda/provided:al2023",
|
|
4728
|
+
fileExtension: null
|
|
6705
4729
|
}
|
|
6706
|
-
}
|
|
6707
|
-
|
|
6708
|
-
|
|
6709
|
-
|
|
6710
|
-
|
|
6711
|
-
|
|
6712
|
-
|
|
6713
|
-
|
|
6714
|
-
]);
|
|
6715
|
-
} catch (error) {
|
|
6716
|
-
const err = error;
|
|
6717
|
-
if (err.code === "ENOENT") throw new DockerRunnerError(`${cmd} is not installed or not on PATH. ${getEmbedConfig().cliName} invoke needs Docker (or a compatible CLI specified via CDK_DOCKER) — install it and retry.`);
|
|
6718
|
-
throw new DockerRunnerError(`${cmd} daemon is not reachable: ${err.stderr?.trim() || err.message || String(error)}. Start Docker Desktop / the docker daemon and retry.`);
|
|
4730
|
+
};
|
|
4731
|
+
var UnsupportedRuntimeError = class UnsupportedRuntimeError extends Error {
|
|
4732
|
+
runtime;
|
|
4733
|
+
constructor(runtime, message) {
|
|
4734
|
+
super(message);
|
|
4735
|
+
this.runtime = runtime;
|
|
4736
|
+
this.name = "UnsupportedRuntimeError";
|
|
4737
|
+
Object.setPrototypeOf(this, UnsupportedRuntimeError.prototype);
|
|
6719
4738
|
}
|
|
4739
|
+
};
|
|
4740
|
+
function resolveRuntimeImage(runtime) {
|
|
4741
|
+
return resolveRuntimeSpec(runtime).image;
|
|
6720
4742
|
}
|
|
6721
|
-
function
|
|
6722
|
-
|
|
6723
|
-
|
|
6724
|
-
|
|
6725
|
-
server.on("error", rejectPort);
|
|
6726
|
-
server.listen(0, "127.0.0.1", () => {
|
|
6727
|
-
const address = server.address();
|
|
6728
|
-
if (!address || typeof address === "string") {
|
|
6729
|
-
server.close();
|
|
6730
|
-
rejectPort(/* @__PURE__ */ new Error("Could not allocate a host port"));
|
|
6731
|
-
return;
|
|
6732
|
-
}
|
|
6733
|
-
const port = address.port;
|
|
6734
|
-
server.close(() => resolvePort(port));
|
|
6735
|
-
});
|
|
6736
|
-
});
|
|
6737
|
-
}
|
|
6738
|
-
const SENSITIVE_ENV_KEYS = /* @__PURE__ */ new Set([
|
|
6739
|
-
"AWS_ACCESS_KEY_ID",
|
|
6740
|
-
"AWS_SECRET_ACCESS_KEY",
|
|
6741
|
-
"AWS_SESSION_TOKEN"
|
|
6742
|
-
]);
|
|
6743
|
-
function appendEnvFlags(args, env, sensitiveKeys) {
|
|
6744
|
-
const passthrough = {};
|
|
6745
|
-
const collisions = [];
|
|
6746
|
-
for (const [k, v] of Object.entries(env)) if (sensitiveKeys.has(k)) {
|
|
6747
|
-
if (isMalformedEnvKey(k) || isDockerClientEnvKey(k)) {
|
|
6748
|
-
collisions.push(k);
|
|
6749
|
-
continue;
|
|
6750
|
-
}
|
|
6751
|
-
args.push("-e", k);
|
|
6752
|
-
defineOwnKey(passthrough, k, v);
|
|
6753
|
-
} else args.push("-e", `${k}=${v}`);
|
|
6754
|
-
return {
|
|
6755
|
-
passthrough,
|
|
6756
|
-
collisions
|
|
6757
|
-
};
|
|
4743
|
+
function resolveRuntimeFileExtension(runtime) {
|
|
4744
|
+
const spec = resolveRuntimeSpec(runtime);
|
|
4745
|
+
if (spec.fileExtension === null) throw new UnsupportedRuntimeError(runtime, `Inline 'Code.ZipFile' is not supported for runtime ${displayIdent(runtime)}. The Lambda Handler shape for this runtime names a compiled artifact (a JVM class, a .NET assembly, or — for the OS-only \`provided.*\` runtimes — an arbitrary \`bootstrap\` binary) that cannot be expressed as a single inline source file. Use \`lambda.Code.fromAsset(<dir>)\` with a directory containing the compiled output (.class hierarchy / JAR / DLL / native binary).`);
|
|
4746
|
+
return spec.fileExtension;
|
|
6758
4747
|
}
|
|
6759
|
-
function
|
|
6760
|
-
|
|
4748
|
+
function resolveRuntimeSpec(runtime) {
|
|
4749
|
+
if (typeof runtime !== "string" || runtime.length === 0) throw new UnsupportedRuntimeError(String(runtime), "Lambda function has no Runtime property. This branch is only reached for ZIP Lambdas; container-image Lambdas (Code.ImageUri) take a different code path that does not consult the Runtime property.");
|
|
4750
|
+
const spec = SUPPORTED_RUNTIMES[runtime];
|
|
4751
|
+
if (spec) return spec;
|
|
4752
|
+
if (runtime === "go1.x") throw new UnsupportedRuntimeError(runtime, "Runtime 'go1.x' was deprecated by AWS Lambda on 2024-01-08 and is no longer available. Migrate to the OS-only runtime: build your Go program as a `bootstrap` binary and set the CDK runtime to `lambda.Runtime.PROVIDED_AL2023` (or `lambda.Runtime.PROVIDED_AL2`). See https://docs.aws.amazon.com/lambda/latest/dg/lambda-golang.html");
|
|
4753
|
+
throw new UnsupportedRuntimeError(runtime, `Unknown runtime ${displayIdent(runtime)}. ${getEmbedConfig().cliName} invoke supports nodejs18.x / nodejs20.x / nodejs22.x / nodejs24.x / python3.11 / python3.12 / python3.13 / python3.14 / ruby3.2 / ruby3.3 / java8.al2 / java11 / java17 / java21 / dotnet6 / dotnet8 / provided.al2 / provided.al2023.`);
|
|
6761
4754
|
}
|
|
6762
|
-
function
|
|
6763
|
-
|
|
6764
|
-
if (
|
|
6765
|
-
|
|
6766
|
-
for (const k of keys) defineOwnKey(env, k, passthrough[k]);
|
|
6767
|
-
return { env };
|
|
4755
|
+
function resolveRuntimeCodeMountPath(runtime) {
|
|
4756
|
+
resolveRuntimeSpec(runtime);
|
|
4757
|
+
if (runtime === "provided.al2" || runtime === "provided.al2023") return "/var/runtime";
|
|
4758
|
+
return "/var/task";
|
|
6768
4759
|
}
|
|
6769
4760
|
|
|
6770
4761
|
//#endregion
|
|
@@ -12594,6 +10585,7 @@ async function localStartApiCommand(targets, options, extraStateProviders) {
|
|
|
12594
10585
|
const normalizedAssumeRole = normalizeStartApiAssumeRole(options.assumeRole, options.assumeRoleAuto ?? false);
|
|
12595
10586
|
if (normalizedAssumeRole === void 0) delete options.assumeRole;
|
|
12596
10587
|
else options.assumeRole = normalizedAssumeRole;
|
|
10588
|
+
await activateWorkloadAwsWiring(options);
|
|
12597
10589
|
await applyRoleArnIfSet({
|
|
12598
10590
|
roleArn: options.roleArn,
|
|
12599
10591
|
region: options.region,
|
|
@@ -13885,6 +11877,7 @@ function createLocalStartApiCommand(opts = {}) {
|
|
|
13885
11877
|
return startApi;
|
|
13886
11878
|
}
|
|
13887
11879
|
function addStartApiSpecificOptions(cmd) {
|
|
11880
|
+
addAwsEndpointOptions(cmd);
|
|
13888
11881
|
return cmd.addOption(new Option("--port <port>", "HTTP server port (default: auto-allocate)").default("0")).addOption(new Option("--host <host>", "Bind address").default("127.0.0.1")).addOption(new Option("--stack <name>", "Stack to start (single-stack apps auto-detect)")).addOption(new Option("--all-stacks", "Serve every stack's API in a multi-stack app (each API on its own port) instead of erroring out. Mutually exclusive with a positional target subset, --stack, and an explicit --from-cfn-stack <name>; the bare --from-cfn-stack flag stays compatible (binds each routed stack to its own CFn stack).").default(false)).addOption(new Option("--warm", "Pre-start one container per Lambda at server boot").default(false)).addOption(new Option("--per-lambda-concurrency <n>", "Pool size cap per Lambda (default 2, max 4)").default("2")).addOption(new Option("--no-pull", "Skip docker pull (cached image)")).addOption(new Option("--no-build", "Skip docker build on every container Lambda local-asset build (use the previously-built tag). Requires the deterministic tag to already be in the local registry; errors with an actionable message when missing. No-op for ZIP Lambdas and the IMAGE ECR-pull path. Compatible with --no-pull.")).addOption(new Option("--container-host <host>", "IP the host uses to bind/probe the RIE port (must be a numeric IP — `docker run -p <ip>:<port>:8080` rejects hostnames). Defaults to 127.0.0.1.").default("127.0.0.1")).addOption(new Option("--debug-port-base <port>", "Reserve a contiguous --debug-port range (one per Lambda)")).addOption(new Option("--debug-port <port>", "Alias of --debug-port-base for parity with `cdkl invoke --debug-port`. Reserves a contiguous --debug-port range (one per Lambda) starting at <port>.")).addOption(new Option("--ecr-role-arn <arn>", "Role ARN to assume before authenticating against ECR for cross-account / centralized registries on the container-Lambda ECR-pull fallback. Issues sts:AssumeRole via the default credential chain and uses the temporary credentials for ecr:GetAuthorizationToken + docker pull. Required when the caller does not have direct cross-account access to the target repository. Same-account / same-region pulls do not need this flag.")).addOption(new Option("--env-vars <file>", "JSON env-var overrides (SAM-compatible: {\"LogicalId\":{\"KEY\":\"VALUE\"}, \"Parameters\": {...}})")).addOption(new Option("--assume-role <arn-or-pair>", "Assume the Lambda's execution role and forward STS-issued temp creds. Two forms: (1) `--assume-role <arn>` sets a single global default ARN used for every routed Lambda; (2) `--assume-role <LogicalId>=<arn>` (repeatable) is a per-Lambda override (wins over the global default and over --assume-role-auto for the named Lambda). Pair with --assume-role-auto to auto-resolve every other Lambda. Precedence: per-Lambda > (--assume-role-auto OR global default) > unset (developer creds passed through).").argParser((raw, prev) => parseAssumeRoleToken(raw, prev))).addOption(new Option("--assume-role-auto", "Auto-resolve EACH routed Lambda's own execution role per-Lambda (literal ARN / Fn::GetAtt against template / --from-cfn-stack state). Slower boot — one STS call per Lambda — but the right shape when each Lambda's deployed role differs. Mutually exclusive with `--assume-role <arn>` (global default); errors at boot. Compatible with `--assume-role <LogicalId>=<arn>` per-Lambda overrides — the map wins for named Lambdas, auto-resolve handles the rest.").default(false)).addOption(new Option("--watch", "Hot-reload: re-synth + re-discover routes when the CDK app's source changes (honors cdk.json watch.include/exclude; cdk.out, node_modules, .git are always excluded). Off by default; the server keeps the previous version serving when synth fails mid-reload.").default(false)).addOption(new Option("--stage <name>", "Select an API Gateway Stage by its 'StageName'. Default: the first Stage attached to each API. Drives event.stageVariables for both REST v1 and HTTP API v2. NOTE: For HTTP API v2 routes, requestContext.stage is always '$default' regardless of this flag (AWS-side limitation — HTTP API only exposes one stage to the integration event); only event.stageVariables is affected for v2 routes. For REST v1 routes the selected StageName is also threaded into requestContext.stage.")).addOption(new Option("--api <id>", "DEPRECATED — use the positional <targets...> argument instead. Accepts a SINGLE identifier; for a subset pass multiple positional targets. Same accepted forms (bare logical id, stack-qualified, Construct path, ancestor prefix). Will be removed in a future major release.")).addOption(new Option("--layer-role-arn <arn>", "Role to sts:AssumeRole before calling lambda:GetLayerVersion on every literal-ARN entry in Properties.Layers (issue #448). Use only when the dev credentials cannot read the layer — typically cross-account layers. AWS-published public layers (e.g. Lambda Powertools) are readable from every account and need no role.")).addOption(new Option("--from-cfn-stack [cfn-stack-name]", "Read a deployed CloudFormation stack via ListStackResources and substitute Ref / Fn::ImportValue in Lambda env vars with the deployed physical IDs / exports. Use for CDK apps deployed via the upstream CDK CLI (`cdk deploy`). Bare form uses the resolved stack name per routed stack; pass an explicit value when a single CFn stack should serve every routed stack. Fn::GetAtt is warn-and-dropped in v1 (CFn ListStackResources does not return per-attribute values).")).addOption(new Option("--stack-region <region>", "Region of the state record to read. Used with --from-cfn-stack as the CFn client region.")).addOption(new Option("--mtls-truststore <path>", `PEM-encoded CA bundle for client-certificate verification (mutual TLS). When set, the local server switches from HTTP to HTTPS and the TLS handshake rejects clients whose certificate doesn't chain to one of these CAs. Verified certs are surfaced on the Lambda event under requestContext.identity.clientCert (REST v1) / requestContext.authentication.clientCert (HTTP API v2). Must be set together with --mtls-cert + --mtls-key; partial flag sets are rejected. Generate a CA + server + client cert for local dev: openssl req -x509 -newkey rsa:2048 -nodes -keyout ca-key.pem -out ca.pem -subj "/CN=${getEmbedConfig().resourceNamePrefix}-ca" -days 365; openssl req -newkey rsa:2048 -nodes -keyout server-key.pem -out server-csr.pem -subj "/CN=localhost"; openssl x509 -req -in server-csr.pem -CA ca.pem -CAkey ca-key.pem -CAcreateserial -out server-cert.pem -days 365; openssl req -newkey rsa:2048 -nodes -keyout client-key.pem -out client-csr.pem -subj "/CN=client"; openssl x509 -req -in client-csr.pem -CA ca.pem -CAkey ca-key.pem -CAcreateserial -out client-cert.pem -days 365; curl --cacert ca.pem --cert client-cert.pem --key client-key.pem https://localhost:<port>/...`)).addOption(new Option("--mtls-cert <path>", "PEM-encoded server certificate for mutual TLS. Self-signed is fine for local dev. Must be set together with --mtls-truststore + --mtls-key.")).addOption(new Option("--mtls-key <path>", "PEM-encoded server private key matching --mtls-cert. Must be set together with --mtls-truststore + --mtls-cert.")).addOption(new Option("--strict-sigv4", "Opt-in: DENY AWS_IAM SigV4 requests that cannot be cryptographically verified (foreign access-key-id — e.g. a federated / Cognito Identity Pool / cross-account signer — OR no local AWS credentials configured) instead of the default warn-and-pass. DEFAULT off: cdk-local warn-and-passes unverifiable IAM requests with a placeholder principalId so local dev exercises app logic without reproducing an auth boundary it cannot fully emulate. OAC-fronted Function URLs always warn-and-pass regardless.").default(false));
|
|
13889
11882
|
}
|
|
13890
11883
|
|
|
@@ -13950,6 +11943,7 @@ async function localInvokeCommand(target, options, extraStateProviders) {
|
|
|
13950
11943
|
getLogger().debug(`cleanup failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
13951
11944
|
});
|
|
13952
11945
|
try {
|
|
11946
|
+
await activateWorkloadAwsWiring(options);
|
|
13953
11947
|
await applyRoleArnIfSet({
|
|
13954
11948
|
roleArn: options.roleArn,
|
|
13955
11949
|
region: options.region,
|
|
@@ -14564,6 +12558,7 @@ function createLocalInvokeCommand(opts = {}) {
|
|
|
14564
12558
|
return invoke;
|
|
14565
12559
|
}
|
|
14566
12560
|
function addInvokeSpecificOptions(cmd) {
|
|
12561
|
+
addAwsEndpointOptions(cmd);
|
|
14567
12562
|
return cmd.addOption(new Option("-e, --event <file>", "JSON event payload file (default: {})")).addOption(new Option("--event-stdin", "Read event JSON from stdin").default(false)).addOption(new Option("--env-vars <file>", "JSON env-var overrides (SAM-compatible: {\"LogicalId\":{\"KEY\":\"VALUE\"}, \"Parameters\": {...}})")).addOption(new Option("--no-pull", "Skip docker pull. Semantics differ by code path: ZIP Lambdas skip pulling the public Lambda base image; Container Lambdas on the local-build path are a no-op (docker build does not refresh the FROM cache by default); Container Lambdas on the ECR-pull fallback skip docker pull AND error if the image is not in the local cache (re-run without --no-pull or pre-pull manually).")).addOption(new Option("--no-build", "Skip docker build on the IMAGE local-build path (use the previously-built tag). Requires the deterministic tag to already be in the local registry; errors with an actionable message when missing. No-op for ZIP Lambdas and the IMAGE ECR-pull path. Compatible with --no-pull.")).addOption(new Option("--debug-port <port>", "Node --inspect-brk port (default: off)")).addOption(new Option("--container-host <host>", "Host IP the host uses to bind the RIE port to. Must be a numeric IP (Docker rejects hostnames here). Defaults to 127.0.0.1.").default("127.0.0.1")).addOption(new Option("--assume-role [arn]", "Assume the Lambda's deployed execution role and forward STS-issued temp credentials to the container so the handler runs with the deployed function's narrow permissions. Three forms: (1) `--assume-role <arn>` assumes the explicit ARN; (2) `--assume-role` (bare) auto-resolves the function's execution role ARN from state (requires an active state source); (3) `--no-assume-role` explicitly opts out. Off by default — when omitted, the developer's shell credentials are forwarded unchanged (SAM-compatible default). STS failures degrade to a warn + dev-creds fallback.")).addOption(new Option("--layer-role-arn <arn>", "Role to sts:AssumeRole before calling lambda:GetLayerVersion on every literal-ARN entry in Properties.Layers. Use only when the dev credentials cannot read the layer — typically cross-account layers. AWS-published public layers (e.g. Lambda Powertools) are readable from every account and need no role.")).addOption(new Option("--ecr-role-arn <arn>", "Role ARN to assume before authenticating against ECR for cross-account / centralized registries. Issues sts:AssumeRole via the default credential chain and uses the temporary credentials for ecr:GetAuthorizationToken + docker pull. Required when the caller does not have direct cross-account access to the target repository. Same-account / same-region pulls do not need this flag.")).addOption(new Option("--from-cfn-stack [cfn-stack-name]", "Read a deployed CloudFormation stack via ListStackResources and substitute Ref / Fn::ImportValue in env vars with the deployed physical IDs / exports. Use for CDK apps deployed via the upstream CDK CLI (`cdk deploy`). Bare form uses the resolved stack name; pass an explicit value when CFn stack name differs. Fn::GetAtt is warn-and-dropped in v1 (CFn ListStackResources does not return per-attribute values).")).addOption(new Option("--stack-region <region>", "Region of the state record to read. Used with --from-cfn-stack as the CFn client region.")).addOption(new Option("--response-file <path>", "Also write the raw Lambda response payload to this file. Lets a programmatic caller recover the response without parsing it out of stdout (where it interleaves with synth progress + streamed container logs). stdout output is unchanged."));
|
|
14568
12563
|
}
|
|
14569
12564
|
|
|
@@ -15429,6 +13424,7 @@ async function localInvokeAgentCoreCommand(target, options, extraStateProviders)
|
|
|
15429
13424
|
getLogger().debug(`cleanup failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
15430
13425
|
});
|
|
15431
13426
|
try {
|
|
13427
|
+
await activateWorkloadAwsWiring(options);
|
|
15432
13428
|
await applyRoleArnIfSet({
|
|
15433
13429
|
roleArn: options.roleArn,
|
|
15434
13430
|
region: options.region,
|
|
@@ -16324,6 +14320,8 @@ async function softReloadAgentContainer(containerId, newAssetSourceDir) {
|
|
|
16324
14320
|
}
|
|
16325
14321
|
try {
|
|
16326
14322
|
await execFileAsync$6(dockerCmd, ["restart", containerId]);
|
|
14323
|
+
const wiring = getActiveWorkloadAwsWiring();
|
|
14324
|
+
if (wiring) await attachLoopbackForwarder(containerId, wiring);
|
|
16327
14325
|
} catch (err) {
|
|
16328
14326
|
throw new CdkLocalError(`softReloadAgentContainer: docker restart of '${containerId}' failed: ${describeExecError(err)}.`, "LOCAL_INVOKE_AGENTCORE_WATCH_SOFT_RELOAD_RESTART_FAILED");
|
|
16329
14327
|
}
|
|
@@ -16401,6 +14399,7 @@ function createLocalInvokeAgentCoreCommand(opts = {}) {
|
|
|
16401
14399
|
return cmd;
|
|
16402
14400
|
}
|
|
16403
14401
|
function addInvokeAgentCoreSpecificOptions(cmd) {
|
|
14402
|
+
addAwsEndpointOptions(cmd);
|
|
16404
14403
|
return cmd.addOption(new Option("-e, --event <file>", "JSON event payload file (default: {})")).addOption(new Option("--event-stdin", "Read event JSON from stdin").default(false)).addOption(new Option("--env-vars <file>", "JSON env-var overrides (SAM-compatible: {\"LogicalId\":{\"KEY\":\"VALUE\"}, \"Parameters\": {...}})")).addOption(new Option("--session-id <id>", "AgentCore runtime session id header value (default: a random UUID)")).addOption(new Option("--ws", "Stream over the HTTP-protocol agent's bidirectional /ws WebSocket endpoint (on 8080) instead of POST /invocations: send --event as the first frame and print every received frame to stdout until the agent closes. When stdin is a TTY, additionally reads stdin lines as follow-up text frames (multi-turn REPL; Ctrl-D to end). When stdin is piped / redirected / non-TTY (CI), only the initial --event frame is sent (one-shot). Force one-shot in a TTY with `cdkl ... --ws </dev/null`. Ignored for an MCP runtime.").default(false)).addOption(new Option("--bearer-token <jwt>", "Bearer JWT this command SUPPLIES (the supplier role) when the runtime declares a customJwtAuthorizer — `cdkl invoke-agentcore` is the local-dev client making the outbound call, so it always presents this token to its own invocation. Verified against the runtime's OIDC discovery URL (signature / issuer / expiry / audience) before the container starts, then forwarded to /invocations as Authorization: Bearer <jwt>. Contrast with `cdkl start-alb --bearer-token`, where the role is reversed — the ALB front-door RECEIVES inbound requests and injects this token only as a default when an inbound request has none (default-when-missing).")).addOption(new Option("--no-verify-auth", "Skip inbound JWT verification even when the runtime declares a customJwtAuthorizer (local-dev escape hatch). A --bearer-token, if given, is still forwarded.")).addOption(new Option("--sigv4", "Sign the /invocations POST with AWS SigV4 (service bedrock-agentcore) using the resolved credentials, matching the cloud default when the runtime declares no customJwtAuthorizer. Opt-in: default unsigned. Mutually exclusive with --bearer-token; ignored on a JWT-protected runtime.").default(false)).addOption(new Option("--platform <platform>", "docker --platform for the agent container (linux/amd64 or linux/arm64). Defaults to linux/arm64 because the cloud AgentCore Runtime requires arm64. Override to linux/amd64 only when iterating against an amd64 dev container locally; note the image will not run on the cloud runtime as-is.").choices(["linux/amd64", "linux/arm64"]).default("linux/arm64")).addOption(new Option("--no-pull", "Skip docker pull (use cached image) — no-op for the local-build path")).addOption(new Option("--no-build", "Skip docker build on the local-asset path (use the previously-built tag). No-op for the ECR / registry pull paths.")).addOption(new Option("--container-host <host>", "Host IP the host uses to bind the agent port to. Must be a numeric IP (Docker rejects hostnames here). Defaults to 127.0.0.1.").default("127.0.0.1")).addOption(new Option("--timeout <ms>", "Per-request timeout in milliseconds. Applied to POST /invocations, POST /mcp, and the /ws open-to-close window. Raise this for long-running agent calls that exceed the default.").default(12e4).argParser(parseTimeoutMs)).addOption(new Option("--assume-role [arn]", "Assume the runtime's execution role and forward STS-issued temp credentials to the container so the agent runs with the deployed role. Three forms: (1) `--assume-role <arn>` assumes the explicit ARN; (2) `--assume-role` (bare) uses the runtime's RoleArn when it is a literal ARN; (3) `--no-assume-role` opts out. Off by default — the developer's shell credentials are forwarded unchanged.")).addOption(new Option("--ecr-role-arn <arn>", "Role ARN to assume before authenticating against ECR for cross-account / centralized registries. Same-account / same-region pulls do not need this flag.")).addOption(new Option("--from-cfn-stack [cfn-stack-name]", "Read a deployed CloudFormation stack via ListStackResources and substitute Ref / Fn::ImportValue in env vars with the deployed physical IDs / exports. Bare form uses the resolved stack name; pass an explicit value when the CFn stack name differs.")).addOption(new Option("--stack-region <region>", "Region of the state record to read. Used with --from-cfn-stack as the CFn client region.")).addOption(new Option("--watch", "Re-synth and reload the agent container on CDK source changes. Only meaningful with the long-running --ws session path; single-shot POST /invocations, MCP, and A2A invocations run once and exit, so --watch is logged as a no-op WARN for them and the single shot proceeds. The active /ws socket is closed cleanly on every reload firing so the next session connects to the rebuilt container — the honest local-dev semantic.").default(false));
|
|
16405
14404
|
}
|
|
16406
14405
|
|
|
@@ -17106,7 +15105,8 @@ async function runEcsTask(task, options, state) {
|
|
|
17106
15105
|
});
|
|
17107
15106
|
dockerCmds.set(container.name, {
|
|
17108
15107
|
args: built.args,
|
|
17109
|
-
sensitiveEnv: built.sensitiveEnv
|
|
15108
|
+
sensitiveEnv: built.sensitiveEnv,
|
|
15109
|
+
loopbackPorts: built.loopbackPorts
|
|
17110
15110
|
});
|
|
17111
15111
|
if (built.collisions.length > 0) logger.warn(describeRefusedSensitiveEnvKeys(`Container ${displayUntrustedValue(container.name)}`, built.collisions));
|
|
17112
15112
|
for (const ep of built.publishedEndpoints) state.publishedEndpoints.push(ep);
|
|
@@ -17115,7 +15115,9 @@ async function runEcsTask(task, options, state) {
|
|
|
17115
15115
|
for (const containerName of startOrder) {
|
|
17116
15116
|
const container = task.containers.find((c) => c.name === containerName);
|
|
17117
15117
|
await awaitDependencies(container, startedByName);
|
|
17118
|
-
const { args, sensitiveEnv } = dockerCmds.get(container.name);
|
|
15118
|
+
const { args, sensitiveEnv, loopbackPorts } = dockerCmds.get(container.name);
|
|
15119
|
+
const forwarderWiring = getActiveWorkloadAwsWiring();
|
|
15120
|
+
if (loopbackPorts.length > 0 && forwarderWiring) await prepareLoopbackForwarder(forwarderWiring);
|
|
17119
15121
|
logger.info(`Starting container ${displayIdent(container.name)} (image=${displayIdent(imagePlan.get(container.name))})`);
|
|
17120
15122
|
let id;
|
|
17121
15123
|
warnFinchArgvExposure(Object.keys(sensitiveEnv));
|
|
@@ -17137,6 +15139,8 @@ async function runEcsTask(task, options, state) {
|
|
|
17137
15139
|
id,
|
|
17138
15140
|
container
|
|
17139
15141
|
});
|
|
15142
|
+
const wiring = getActiveWorkloadAwsWiring();
|
|
15143
|
+
if (wiring) await attachLoopbackForwarder(id, wiring, loopbackPorts);
|
|
17140
15144
|
if (!options.detach) state.logStoppers.push(attachContainerLogStreamer(`[${displayIdent(container.name)}] `, id));
|
|
17141
15145
|
}
|
|
17142
15146
|
if (options.detach) return {
|
|
@@ -17460,7 +15464,10 @@ function buildDockerRunArgs(opts) {
|
|
|
17460
15464
|
args.push("-p", `${containerHost}::${pm.containerPort}/${pm.protocol}`);
|
|
17461
15465
|
}
|
|
17462
15466
|
}
|
|
17463
|
-
|
|
15467
|
+
const wiring = getActiveWorkloadAwsWiring();
|
|
15468
|
+
const profileCredentialsFile = wiring?.mode === "emulator" ? void 0 : opts.profileCredentialsFile;
|
|
15469
|
+
if (profileCredentialsFile) args.push("-v", `${profileCredentialsFile.hostPath}:${profileCredentialsFile.containerPath}:ro`);
|
|
15470
|
+
for (const m of wiring?.mounts ?? []) if (!container.mountPoints.some((mp) => mp.containerPath === m.containerPath)) args.push("-v", `${m.hostPath}:${m.containerPath}:ro`);
|
|
17464
15471
|
for (const mp of container.mountPoints) {
|
|
17465
15472
|
const v = volumeByName.get(mp.sourceVolume);
|
|
17466
15473
|
if (!v) continue;
|
|
@@ -17474,7 +15481,7 @@ function buildDockerRunArgs(opts) {
|
|
|
17474
15481
|
args.push("-v", `${name}:${mp.containerPath}${ro}`);
|
|
17475
15482
|
}
|
|
17476
15483
|
}
|
|
17477
|
-
|
|
15484
|
+
let finalEnv = {};
|
|
17478
15485
|
const metaEnv = buildMetadataEnv({
|
|
17479
15486
|
containerName: container.name,
|
|
17480
15487
|
...roleArn !== void 0 && { roleArn },
|
|
@@ -17482,10 +15489,11 @@ function buildDockerRunArgs(opts) {
|
|
|
17482
15489
|
...opts.sidecarIp !== void 0 && { sidecarIp: opts.sidecarIp }
|
|
17483
15490
|
});
|
|
17484
15491
|
Object.assign(finalEnv, metaEnv);
|
|
17485
|
-
if (
|
|
17486
|
-
finalEnv["AWS_SHARED_CREDENTIALS_FILE"] =
|
|
17487
|
-
finalEnv["AWS_PROFILE"] =
|
|
15492
|
+
if (profileCredentialsFile) {
|
|
15493
|
+
finalEnv["AWS_SHARED_CREDENTIALS_FILE"] = profileCredentialsFile.containerPath;
|
|
15494
|
+
finalEnv["AWS_PROFILE"] = profileCredentialsFile.profileName;
|
|
17488
15495
|
}
|
|
15496
|
+
if (wiring?.mode === "forward") for (const [k, v] of Object.entries(wiring.env)) defineOwnKey(finalEnv, k, v);
|
|
17489
15497
|
for (const [k, v] of Object.entries(container.environment)) defineOwnKey(finalEnv, k, v);
|
|
17490
15498
|
for (const s of secrets) defineOwnKey(finalEnv, s.name, s.value);
|
|
17491
15499
|
const overrides = opts.envOverrides;
|
|
@@ -17493,6 +15501,10 @@ function buildDockerRunArgs(opts) {
|
|
|
17493
15501
|
applyEnvOverrideMap(finalEnv, overrides["Parameters"]);
|
|
17494
15502
|
applyEnvOverrideMap(finalEnv, overrides[container.name]);
|
|
17495
15503
|
}
|
|
15504
|
+
if (wiring) finalEnv = applyWorkloadAwsWiringToEnv(finalEnv, wiring.mode === "emulator" ? wiring : {
|
|
15505
|
+
...wiring,
|
|
15506
|
+
env: {}
|
|
15507
|
+
});
|
|
17496
15508
|
const sensitiveEnvKeys = new Set(SENSITIVE_ENV_KEYS);
|
|
17497
15509
|
for (const s of secrets) sensitiveEnvKeys.add(s.name);
|
|
17498
15510
|
for (const s of container.secrets) sensitiveEnvKeys.add(s.name);
|
|
@@ -17522,7 +15534,8 @@ function buildDockerRunArgs(opts) {
|
|
|
17522
15534
|
args,
|
|
17523
15535
|
sensitiveEnv,
|
|
17524
15536
|
collisions,
|
|
17525
|
-
publishedEndpoints
|
|
15537
|
+
publishedEndpoints,
|
|
15538
|
+
loopbackPorts: wiring ? effectiveLoopbackPorts(finalEnv, wiring) : []
|
|
17526
15539
|
};
|
|
17527
15540
|
}
|
|
17528
15541
|
function shellJoin(parts) {
|
|
@@ -18334,7 +16347,7 @@ async function softReloadReplica(args) {
|
|
|
18334
16347
|
const defaultDockerInspectWorkdirImpl = async (containerId) => {
|
|
18335
16348
|
const { execFile } = await import("node:child_process");
|
|
18336
16349
|
const { promisify } = await import("node:util");
|
|
18337
|
-
const { getDockerCmd } = await import("./docker-cmd-
|
|
16350
|
+
const { getDockerCmd } = await import("./docker-cmd-Cjg3jGYF.js").then((n) => n.t);
|
|
18338
16351
|
const { stdout } = await promisify(execFile)(getDockerCmd(), [
|
|
18339
16352
|
"inspect",
|
|
18340
16353
|
"--format",
|
|
@@ -18347,7 +16360,7 @@ let dockerInspectWorkdirImpl = defaultDockerInspectWorkdirImpl;
|
|
|
18347
16360
|
const defaultDockerCpImpl = async (src, dst) => {
|
|
18348
16361
|
const { execFile } = await import("node:child_process");
|
|
18349
16362
|
const { promisify } = await import("node:util");
|
|
18350
|
-
const { getDockerCmd } = await import("./docker-cmd-
|
|
16363
|
+
const { getDockerCmd } = await import("./docker-cmd-Cjg3jGYF.js").then((n) => n.t);
|
|
18351
16364
|
await promisify(execFile)(getDockerCmd(), [
|
|
18352
16365
|
"cp",
|
|
18353
16366
|
src,
|
|
@@ -18358,14 +16371,20 @@ let dockerCpImpl = defaultDockerCpImpl;
|
|
|
18358
16371
|
const defaultDockerStopImpl = async (containerId) => {
|
|
18359
16372
|
const { execFile } = await import("node:child_process");
|
|
18360
16373
|
const { promisify } = await import("node:util");
|
|
18361
|
-
const { getDockerCmd } = await import("./docker-cmd-
|
|
16374
|
+
const { getDockerCmd } = await import("./docker-cmd-Cjg3jGYF.js").then((n) => n.t);
|
|
18362
16375
|
await promisify(execFile)(getDockerCmd(), ["stop", containerId]);
|
|
18363
16376
|
};
|
|
18364
16377
|
const defaultDockerStartImpl = async (containerId) => {
|
|
18365
16378
|
const { execFile } = await import("node:child_process");
|
|
18366
16379
|
const { promisify } = await import("node:util");
|
|
18367
|
-
const { getDockerCmd } = await import("./docker-cmd-
|
|
16380
|
+
const { getDockerCmd } = await import("./docker-cmd-Cjg3jGYF.js").then((n) => n.t);
|
|
18368
16381
|
await promisify(execFile)(getDockerCmd(), ["start", containerId]);
|
|
16382
|
+
const { getActiveWorkloadAwsWiring } = await import("./workload-aws-wiring-BIxf0jtl.js").then((n) => n.b);
|
|
16383
|
+
const wiring = getActiveWorkloadAwsWiring();
|
|
16384
|
+
if (wiring) {
|
|
16385
|
+
const { attachLoopbackForwarder } = await import("./docker-runner-CnXQIUjd.js").then((n) => n.o);
|
|
16386
|
+
await attachLoopbackForwarder(containerId, wiring);
|
|
16387
|
+
}
|
|
18369
16388
|
};
|
|
18370
16389
|
let dockerStopImpl = defaultDockerStopImpl;
|
|
18371
16390
|
let dockerStartImpl = defaultDockerStartImpl;
|
|
@@ -18425,7 +16444,7 @@ async function attachToSharedNetwork(containerId, plan, withAliases) {
|
|
|
18425
16444
|
const defaultDockerNetworkConnectImpl = async (networkName, containerId, opts) => {
|
|
18426
16445
|
const { execFile } = await import("node:child_process");
|
|
18427
16446
|
const { promisify } = await import("node:util");
|
|
18428
|
-
const { getDockerCmd } = await import("./docker-cmd-
|
|
16447
|
+
const { getDockerCmd } = await import("./docker-cmd-Cjg3jGYF.js").then((n) => n.t);
|
|
18429
16448
|
const args = ["network", "connect"];
|
|
18430
16449
|
if (opts.ip) args.push("--ip", opts.ip);
|
|
18431
16450
|
for (const a of opts.aliases) args.push("--alias", a);
|
|
@@ -18436,7 +16455,7 @@ let dockerNetworkConnectImpl = defaultDockerNetworkConnectImpl;
|
|
|
18436
16455
|
const defaultDockerInspectPublishesHostPortsImpl = async (containerId) => {
|
|
18437
16456
|
const { execFile } = await import("node:child_process");
|
|
18438
16457
|
const { promisify } = await import("node:util");
|
|
18439
|
-
const { getDockerCmd } = await import("./docker-cmd-
|
|
16458
|
+
const { getDockerCmd } = await import("./docker-cmd-Cjg3jGYF.js").then((n) => n.t);
|
|
18440
16459
|
const { stdout } = await promisify(execFile)(getDockerCmd(), [
|
|
18441
16460
|
"inspect",
|
|
18442
16461
|
"--format",
|
|
@@ -18475,7 +16494,7 @@ async function disconnectOldFromSharedNetwork(oldInstance, opts = {}) {
|
|
|
18475
16494
|
const defaultDockerNetworkDisconnectImpl = async (networkName, containerId) => {
|
|
18476
16495
|
const { execFile } = await import("node:child_process");
|
|
18477
16496
|
const { promisify } = await import("node:util");
|
|
18478
|
-
const { getDockerCmd } = await import("./docker-cmd-
|
|
16497
|
+
const { getDockerCmd } = await import("./docker-cmd-Cjg3jGYF.js").then((n) => n.t);
|
|
18479
16498
|
await promisify(execFile)(getDockerCmd(), [
|
|
18480
16499
|
"network",
|
|
18481
16500
|
"disconnect",
|
|
@@ -18566,7 +16585,7 @@ const LISTEN_PROBE_SCRIPT = [
|
|
|
18566
16585
|
async function dockerExecListenProbe(containerId, port, timeoutMs = 1e4) {
|
|
18567
16586
|
const { execFile } = await import("node:child_process");
|
|
18568
16587
|
const { promisify } = await import("node:util");
|
|
18569
|
-
const { getDockerCmd } = await import("./docker-cmd-
|
|
16588
|
+
const { getDockerCmd } = await import("./docker-cmd-Cjg3jGYF.js").then((n) => n.t);
|
|
18570
16589
|
try {
|
|
18571
16590
|
await promisify(execFile)(getDockerCmd(), [
|
|
18572
16591
|
"exec",
|
|
@@ -18720,7 +16739,7 @@ function pickEssentialContainerId(instance, service) {
|
|
|
18720
16739
|
const defaultWaitForExitImpl = async (containerId) => {
|
|
18721
16740
|
const { execFile } = await import("node:child_process");
|
|
18722
16741
|
const { promisify } = await import("node:util");
|
|
18723
|
-
const { getDockerCmd } = await import("./docker-cmd-
|
|
16742
|
+
const { getDockerCmd } = await import("./docker-cmd-Cjg3jGYF.js").then((n) => n.t);
|
|
18724
16743
|
const { stdout } = await promisify(execFile)(getDockerCmd(), ["wait", containerId], { maxBuffer: 1024 * 1024 });
|
|
18725
16744
|
const code = parseInt(stdout.trim(), 10);
|
|
18726
16745
|
return Number.isFinite(code) ? code : -1;
|
|
@@ -18730,7 +16749,7 @@ const EXIT_LOG_TAIL_LINES = 50;
|
|
|
18730
16749
|
const defaultReadContainerLogsImpl = async (containerId) => {
|
|
18731
16750
|
const { execFile } = await import("node:child_process");
|
|
18732
16751
|
const { promisify } = await import("node:util");
|
|
18733
|
-
const { getDockerCmd } = await import("./docker-cmd-
|
|
16752
|
+
const { getDockerCmd } = await import("./docker-cmd-Cjg3jGYF.js").then((n) => n.t);
|
|
18734
16753
|
const { stdout, stderr } = await promisify(execFile)(getDockerCmd(), [
|
|
18735
16754
|
"logs",
|
|
18736
16755
|
"--tail",
|
|
@@ -20923,6 +18942,7 @@ async function runEcsServiceEmulator(targets, options, strategy, extraStateProvi
|
|
|
20923
18942
|
}
|
|
20924
18943
|
}, (err) => getLogger().warn(`service cleanup failed: ${err instanceof Error ? err.message : String(err)}`));
|
|
20925
18944
|
try {
|
|
18945
|
+
await activateWorkloadAwsWiring(options);
|
|
20926
18946
|
await applyRoleArnIfSet({
|
|
20927
18947
|
roleArn: options.roleArn,
|
|
20928
18948
|
region: options.region,
|
|
@@ -21832,7 +19852,10 @@ function resolveShadowReadyTimeoutMs(options, envPrefix, env = process.env) {
|
|
|
21832
19852
|
return DEFAULT_SHADOW_READY_TIMEOUT_MS;
|
|
21833
19853
|
}
|
|
21834
19854
|
async function resolveSharedSidecarCredentials(options) {
|
|
19855
|
+
const wiring = getActiveWorkloadAwsWiring();
|
|
19856
|
+
if (wiring?.mode === "emulator") return wiring.emulatorCredentials;
|
|
21835
19857
|
if (options.profile) return resolveProfileCredentials(options.profile);
|
|
19858
|
+
return resolveHostDefaultCredentials();
|
|
21836
19859
|
}
|
|
21837
19860
|
async function resolveAndBuildImageOverrides(args) {
|
|
21838
19861
|
const { perTarget, stacks, options, extraStateProviders, logger } = args;
|
|
@@ -21921,6 +19944,7 @@ function resolveEcsAssumeRoleOption(options) {
|
|
|
21921
19944
|
}
|
|
21922
19945
|
}
|
|
21923
19946
|
function addCommonEcsServiceOptions(cmd) {
|
|
19947
|
+
addAwsEndpointOptions(cmd);
|
|
21924
19948
|
cmd.addOption(ecsClusterOption()).addOption(new Option("--env-vars <file>", "JSON env-var overrides (SAM-compatible: {\"ContainerName\":{\"KEY\":\"VALUE\"}, \"Parameters\":{}})")).addOption(new Option("--container-host <ip>", "Host IP to bind published container ports to. Must be a numeric IP (Docker rejects hostnames here)").default("127.0.0.1"));
|
|
21925
19949
|
addEcsAssumeRoleOptions(cmd);
|
|
21926
19950
|
cmd.addOption(new Option("--no-pull", "Skip docker pull for every container image and the metadata sidecar")).addOption(new Option("--no-build", "Skip docker build on the local CDK-asset path for every container (use the previously-built tag). Requires the deterministic tag to already be in the local registry; errors with an actionable message when missing. No-op for ECR-pull / public-registry images. Per-container --image-override mappings take precedence (the override tag is used as-is, --no-build does not apply). Compatible with --no-pull.")).addOption(new Option("--ecr-role-arn <arn>", "Role ARN to assume before authenticating against ECR for cross-account / centralized registries.")).addOption(new Option("--platform <platform>", "Force docker --platform (linux/amd64 or linux/arm64). Default: inferred from task RuntimePlatform.CpuArchitecture")).addOption(new Option("--max-tasks <n>", `Hard cap on local replica count. Caps the template DesiredCount so local dev machines don't run an unbounded number of containers. Cannot exceed ${83} due to the per-replica link-local /24 subnet allocator's range.`).default(3).argParser(parseMaxTasks)).addOption(new Option("--restart-policy <policy>", "How to react when an essential container exits. 'on-failure' (default) restarts only on non-zero exit; 'always' restarts on every exit; 'none' shuts the replica down and runs the service degraded.").default("on-failure").argParser(parseRestartPolicy)).addOption(new Option("--from-cfn-stack [cfn-stack-name]", `Read a deployed CloudFormation stack via ListStackResources and substitute Ref / Fn::ImportValue in container env vars / secrets / image URIs with the deployed physical IDs / exports. Use for CDK apps deployed via the upstream CDK CLI (\`cdk deploy\`). Bare form uses the ${getEmbedConfig().binaryName} stack name; pass an explicit value when the CFn stack name differs. Fn::GetAtt in container Environment[].Value is warn-and-dropped: CFn ListStackResources does not return per-attribute values, and unlike Lambda (where \`cdkl invoke --from-cfn-stack\` recovers Fn::GetAtt from the deployed function via lambda:GetFunctionConfiguration), no ECS-side equivalent resolves attributes off a deployed task / service.`)).addOption(new Option("--stack-region <region>", "Region of the state record to read. Used with --from-cfn-stack as the CFn client region.")).addOption(new Option("--no-logs", "Disable foreground streaming of each replica container stdout/stderr. By default every booted replica streams its docker logs to the host terminal with a [svc=<service> r=<replica-index> c=<container>] prefix (parity with `run-task`). Pass --no-logs for multi-replica / multi-service runs whose interleaved log volume is unreadable; `docker logs -f <id>` in a separate terminal stays available.")).addOption(new Option("--shadow-ready-timeout <ms>", `Issue #265 — milliseconds the \`--watch\` rolling primitive waits for a shadow replica's first essential-container port to accept a TCP connection before swapping Cloud Map + front-door registrations off the old replica. Defaults to 60000 (60s) which covers realistic prod-shaped Node app cold-starts (TS->JS compile, full node_modules graph, framework boot, DB pool init). Bump higher when the reload log surfaces "TCP probe <ip>:<port> did not accept within <N>ms" — typical for Java / heavy ORM init / \`--inspect-brk\` attach pauses. Honored by --watch on \`${getEmbedConfig().binaryName} start-service\` and \`${getEmbedConfig().binaryName} start-alb\`. Env var: \`${getEmbedConfig().envPrefix}_SHADOW_READY_TIMEOUT_MS\` (flag wins over env).`).argParser(parseShadowReadyTimeout));
|
|
@@ -21963,6 +19987,7 @@ async function localRunTaskCommand(target, options, extraStateProviders) {
|
|
|
21963
19987
|
await cleanupPromise;
|
|
21964
19988
|
};
|
|
21965
19989
|
try {
|
|
19990
|
+
await activateWorkloadAwsWiring(options);
|
|
21966
19991
|
await applyRoleArnIfSet({
|
|
21967
19992
|
roleArn: options.roleArn,
|
|
21968
19993
|
region: options.region,
|
|
@@ -22216,8 +20241,11 @@ function readEnvOverridesFile(filePath) {
|
|
|
22216
20241
|
return parsed;
|
|
22217
20242
|
}
|
|
22218
20243
|
async function resolveSidecarCredentials(options, assumedCredentials) {
|
|
20244
|
+
const wiring = getActiveWorkloadAwsWiring();
|
|
20245
|
+
if (wiring?.mode === "emulator") return wiring.emulatorCredentials;
|
|
22219
20246
|
if (assumedCredentials) return assumedCredentials;
|
|
22220
20247
|
if (options.profile) return resolveProfileCredentials(options.profile);
|
|
20248
|
+
return resolveHostDefaultCredentials();
|
|
22221
20249
|
}
|
|
22222
20250
|
function createLocalRunTaskCommand(opts = {}) {
|
|
22223
20251
|
setEmbedConfig(opts.embedConfig);
|
|
@@ -22277,6 +20305,7 @@ async function resolveRunTaskImageOverride(args) {
|
|
|
22277
20305
|
return { pinnedUncovered: pinned && uncovered.length > 0 };
|
|
22278
20306
|
}
|
|
22279
20307
|
function addRunTaskSpecificOptions(cmd) {
|
|
20308
|
+
addAwsEndpointOptions(cmd);
|
|
22280
20309
|
cmd.addOption(ecsClusterOption()).addOption(new Option("--env-vars <file>", "JSON env-var overrides (SAM-compatible: {\"ContainerName\":{\"KEY\":\"VALUE\"}, \"Parameters\":{}})")).addOption(new Option("--container-host <ip>", "Host IP to bind published container ports to. Must be a numeric IP (Docker rejects hostnames here)").default("127.0.0.1")).addOption(new Option("--host-port <containerPort=hostPort...>", "Publish a container port on a specific host port (e.g. 80=8080); repeatable. Default: host port == container port. Use this on macOS to map a privileged container port (< 1024) to a non-privileged host port and avoid the Docker Desktop admin-password prompt."));
|
|
22281
20310
|
addEcsAssumeRoleOptions(cmd);
|
|
22282
20311
|
cmd.addOption(new Option("--no-pull", "Skip docker pull for every container image and the metadata sidecar")).addOption(new Option("--no-build", "Skip docker build on every CDK-asset container (use the previously-built tag). Requires the deterministic tag to already be in the local registry; errors with an actionable message when missing. No-op for ECR-pull / public-registry containers. Compatible with --no-pull.")).addOption(new Option("--ecr-role-arn <arn>", "Role ARN to assume before authenticating against ECR for cross-account / centralized registries. Issues sts:AssumeRole via the default credential chain and uses the temporary credentials for ecr:GetAuthorizationToken + docker pull. Required when the caller does not have direct cross-account access to the target repository. Same-account / same-region pulls do not need this flag.")).addOption(new Option("--platform <platform>", "Force docker --platform (linux/amd64 or linux/arm64). Default: inferred from task RuntimePlatform.CpuArchitecture")).addOption(new Option("--keep-running", "Don't docker rm -f the user containers on task exit (network + sidecar are still torn down). Use when you want to docker exec into a stopped container for post-mortems.").default(false)).addOption(new Option("--detach", "Start the containers in the background and exit (skip log streaming + auto teardown). Useful in CI smoke tests; caller manages container lifecycle.").default(false)).addOption(new Option("--from-cfn-stack [cfn-stack-name]", `Read a deployed CloudFormation stack via ListStackResources and substitute Ref / Fn::ImportValue in container env vars / secrets / image URIs with the deployed physical IDs / exports. Use for CDK apps deployed via the upstream CDK CLI (\`cdk deploy\`). Bare form uses the ${getEmbedConfig().binaryName} stack name; pass an explicit value when the CFn stack name differs. Fn::GetAtt in container Environment[].Value is warn-and-dropped: CFn ListStackResources does not return per-attribute values, and unlike Lambda (where \`cdkl invoke --from-cfn-stack\` recovers Fn::GetAtt from the deployed function via lambda:GetFunctionConfiguration), no ECS-side equivalent resolves attributes off a deployed task / service.`)).addOption(new Option("--stack-region <region>", "Region of the state record to read. Used with --from-cfn-stack as the CFn client region."));
|
|
@@ -26163,6 +24192,7 @@ async function localStartCloudFrontCommand(target, options, extraStateProviders,
|
|
|
26163
24192
|
if (options.verbose) logger.setLevel("debug");
|
|
26164
24193
|
const originOverrides = parseOriginOverrides(options.origin);
|
|
26165
24194
|
const tlsRequested = options.tls === true || options.tlsCert !== void 0 || options.tlsKey !== void 0;
|
|
24195
|
+
await activateWorkloadAwsWiring(options);
|
|
26166
24196
|
await applyRoleArnIfSet({
|
|
26167
24197
|
roleArn: options.roleArn,
|
|
26168
24198
|
region: options.region,
|
|
@@ -26331,6 +24361,7 @@ function createLocalStartCloudFrontCommand(opts = {}) {
|
|
|
26331
24361
|
return cmd;
|
|
26332
24362
|
}
|
|
26333
24363
|
function addStartCloudFrontSpecificOptions(cmd) {
|
|
24364
|
+
addAwsEndpointOptions(cmd);
|
|
26334
24365
|
return cmd.addOption(new Option("--port <port>", "HTTP server port (default: auto-allocate)").default("0")).addOption(new Option("--host <host>", "Bind address").default("127.0.0.1")).addOption(new Option("--origin <originId=dir>", "Point a distribution origin at a local directory (repeatable). Use when cdk-local cannot resolve the origin's BucketDeployment source automatically (content uploaded out of band, or a non-CDK bucket).").argParser((value, prev) => [...prev ?? [], value])).addOption(new Option("--kvs-file <key=file.json>", "Back a CloudFront Function's KeyValueStore reads (cf.kvs().get()) with a local JSON map (repeatable). The key is a KeyValueStore handle — its AWS::CloudFront::KeyValueStore resource logical id, its construct path, or its bare construct id; the file is a flat { \"key\": \"value\" } object. The AWS-free alternative to --from-cfn-stack, which instead reads the deployed store via the GetKey API.").argParser((value, prev) => [...prev ?? [], value])).addOption(new Option("--tls", "Terminate real TLS (HTTPS). Uses --tls-cert / --tls-key when supplied, else an auto-generated self-signed cert.").default(false)).addOption(new Option("--tls-cert <path>", "PEM server certificate for --tls (implies --tls).")).addOption(new Option("--tls-key <path>", "PEM server private key for --tls (implies --tls).")).addOption(new Option("--no-pull", "Skip 'docker pull' for a Lambda Function URL / Web Function origin's base image (use the locally cached image).")).addOption(new Option("--from-cfn-stack [cfn-stack-name]", "Bind to a deployed CloudFormation stack (ListStackResources). Resolves an S3 origin that has no local BucketDeployment source to its deployed bucket and serves it from real S3 on demand (the front/back-split case: files uploaded out of band), and resolves a Lambda Function URL / Lambda@Edge function's or a Web Function origin revision's env vars to the deployed physical IDs / exports. Use for CDK apps deployed via the upstream CDK CLI (`cdk deploy`). Bare form uses the resolved stack name; pass a value when the CFn stack name differs.")).addOption(new Option("--cache-origin", "For a deployed-S3 origin (served from real S3 under --from-cfn-stack): keep fetched objects in memory for the session instead of re-reading on every request. Faster repeat reads / fewer S3 GETs, but an out-of-band S3 content change is not reflected until a --watch reload (which clears the cache) or a restart. Off by default (every request re-reads, always current). Not CloudFront CDN caching.").default(false)).addOption(new Option("--stack-region <region>", "Region of the state record to read. Used with --from-cfn-stack as the CFn client region.")).addOption(new Option("--assume-role [arn]", "Assume a Lambda Function URL origin's (or a Web Function origin revision's) execution role and forward STS-issued temp credentials into its container so the handler runs with the deployed permissions. Three forms: `--assume-role <arn>` (explicit ARN); `--assume-role` (bare, auto-resolves from state — requires --from-cfn-stack); `--no-assume-role` (opt out). Off by default (the dev shell credentials are forwarded).")).addOption(new Option("--env-vars <file>", "JSON env-var overrides for the Lambda Function URL and Lambda Web Function endpoint origins (SAM-compatible, the same file as the other commands: {\"Parameters\": {...}} for every origin, {\"<LogicalId or construct path>\": {\"KEY\": \"VALUE\"}} for one — the backing function, or the Web Function revision the endpoint serves; a null value removes the variable). Not applied to Lambda@Edge functions, which cannot carry environment variables in AWS.")).addOption(new Option("--watch", "Hot-reload: re-synth + re-resolve the distribution when the CDK app's source changes (honors cdk.json watch.include/exclude; cdk.out, node_modules, .git are always excluded). The server keeps the previous version serving when synth fails mid-reload.").default(false));
|
|
26335
24366
|
}
|
|
26336
24367
|
|
|
@@ -26719,6 +24750,7 @@ async function localStartAgentCoreCommand(target, options, extraStateProviders,
|
|
|
26719
24750
|
await profileCredsFile.dispose();
|
|
26720
24751
|
} catch {}
|
|
26721
24752
|
};
|
|
24753
|
+
await activateWorkloadAwsWiring(options);
|
|
26722
24754
|
await applyRoleArnIfSet({
|
|
26723
24755
|
roleArn: options.roleArn,
|
|
26724
24756
|
region: options.region,
|
|
@@ -26966,6 +24998,7 @@ function createLocalStartAgentCoreCommand(opts = {}) {
|
|
|
26966
24998
|
return cmd;
|
|
26967
24999
|
}
|
|
26968
25000
|
function addStartAgentCoreSpecificOptions(cmd) {
|
|
25001
|
+
addAwsEndpointOptions(cmd);
|
|
26969
25002
|
return cmd.addOption(new Option("--port <n>", "Serve bind port the client connects to (HTTP contract + /ws on the same port). Default 0 (OS-assigned).").default(0).argParser(parsePort$2)).addOption(new Option("--host <ip>", "Serve bind host. Default 127.0.0.1.").default("127.0.0.1")).addOption(new Option("--session-id <id>", "Pin one AgentCore runtime session id header value for every forwarded request / /ws connection (default: a fresh random UUID each, so each is its own session).")).addOption(new Option("--bearer-token <jwt>", "Bearer JWT to present when the runtime declares a customJwtAuthorizer. Verified against the runtime's OIDC discovery URL before the container starts, then injected as Authorization: Bearer <jwt> on every forwarded request and the container /ws upgrade.")).addOption(new Option("--no-verify-auth", "Skip inbound JWT verification even when the runtime declares a customJwtAuthorizer (local-dev escape hatch). A --bearer-token, if given, is still forwarded.")).addOption(new Option("--sigv4", "Sign each forwarded request with AWS SigV4 (service bedrock-agentcore) when the runtime declares NO customJwtAuthorizer, so the warm container sees the same Authorization / X-Amz-* headers the cloud receives. Mutually exclusive with --bearer-token; ignored (with a warning) when a customJwtAuthorizer is declared.")).addOption(new Option("--env-vars <file>", "JSON env-var overrides (SAM-compatible: {\"LogicalId\":{\"KEY\":\"VALUE\"}, \"Parameters\": {...}})")).addOption(new Option("--platform <platform>", "docker --platform for the agent container (linux/amd64 or linux/arm64). Defaults to linux/arm64 because the cloud AgentCore Runtime requires arm64.").choices(["linux/amd64", "linux/arm64"]).default("linux/arm64")).addOption(new Option("--watch", "Re-synth + reload the warm container in place on a CDK source change, keeping the serve up. A per-firing classifier picks rebuild (boot a fresh container, re-point the serve) vs soft-reload (docker cp + docker restart the same container) — the same pattern as start-service / invoke-agentcore --ws --watch.")).addOption(new Option("--no-pull", "Skip docker pull (use cached image) — no-op for the local-build path")).addOption(new Option("--no-build", "Skip docker build on the local-asset path (use the previously-built tag). No-op for the ECR / registry pull paths.")).addOption(new Option("--container-host <host>", "Host IP used to bind the agent container port. Must be a numeric IP. Defaults to 127.0.0.1.").default("127.0.0.1")).addOption(new Option("--timeout <ms>", "Maximum time in milliseconds to wait for the container to become ready (the GET /ping readiness deadline). Default 120000.").default(12e4).argParser(parseTimeoutMs)).addOption(new Option("--assume-role [arn]", "Assume the runtime's execution role and forward STS-issued temp credentials to the container. (1) `--assume-role <arn>` assumes the explicit ARN; (2) `--assume-role` (bare) uses the runtime's literal RoleArn; (3) `--no-assume-role` opts out. Off by default.")).addOption(new Option("--ecr-role-arn <arn>", "Role ARN to assume before authenticating against ECR for cross-account / centralized registries.")).addOption(new Option("--from-cfn-stack [cfn-stack-name]", "Read a deployed CloudFormation stack and substitute Ref / Fn::ImportValue in env vars / image URIs with the deployed physical IDs / exports. Bare form uses the resolved stack name.")).addOption(new Option("--stack-region <region>", "Region of the state record to read. Used with --from-cfn-stack as the CFn client region."));
|
|
26970
25003
|
}
|
|
26971
25004
|
|
|
@@ -26980,6 +25013,7 @@ async function localStartWebFunctionCommand(target, options, extraStateProviders
|
|
|
26980
25013
|
const logger = getLogger();
|
|
26981
25014
|
if (options.verbose) logger.setLevel("debug");
|
|
26982
25015
|
const forever = () => new Promise(() => void 0);
|
|
25016
|
+
await activateWorkloadAwsWiring(options);
|
|
26983
25017
|
await applyRoleArnIfSet({
|
|
26984
25018
|
roleArn: options.roleArn,
|
|
26985
25019
|
region: options.region,
|
|
@@ -27078,6 +25112,7 @@ function createLocalStartWebFunctionCommand(opts = {}) {
|
|
|
27078
25112
|
return cmd;
|
|
27079
25113
|
}
|
|
27080
25114
|
function addStartWebFunctionSpecificOptions(cmd) {
|
|
25115
|
+
addAwsEndpointOptions(cmd);
|
|
27081
25116
|
return cmd.addOption(new Option("--revision <logicalId>", "Serve this WebFunctionRevision (logical ID) instead of the one the endpoint weights pick.")).addOption(new Option("--port <n>", "Local port to serve on. Default 0 (OS-assigned).").default(0).argParser(parsePort$1)).addOption(new Option("--host <ip>", "Address to publish the port on.").default("127.0.0.1")).addOption(new Option("--platform <platform>", "docker --platform for the server container. Defaults to the runtime's cloud architecture (linux/arm64 for nodejs24.x).").choices(["linux/amd64", "linux/arm64"])).addOption(new Option("--env-vars <file>", "JSON env-var overrides (SAM-compatible: {\"RevisionLogicalId\":{\"KEY\":\"VALUE\"}, \"Parameters\": {...}})")).addOption(new Option("--no-pull", "Skip docker pull of the runtime base image (use the cached image)")).addOption(new Option("--timeout <ms>", "Maximum time in milliseconds to wait for the server to answer HTTP. Default 60000.").default(6e4).argParser(parseTimeoutMs)).addOption(new Option("--assume-role [arn]", "Assume the revision's execution role and forward STS-issued temp credentials to the container. (1) `--assume-role <arn>` assumes the explicit ARN; (2) `--assume-role` (bare) uses the revision's ServiceConfig.ExecutionRoleArn: a literal ARN as written, or the Fn::GetAtt / Ref CDK synthesizes resolved against --from-cfn-stack deployed state; (3) `--no-assume-role` opts out. Off by default.")).addOption(new Option("--from-cfn-stack [cfn-stack-name]", "Read a deployed CloudFormation stack and substitute Ref / Fn::ImportValue in env vars with the deployed physical IDs / exports. Bare form uses the resolved stack name.")).addOption(new Option("--stack-region <region>", "Region of the state record to read. Used with --from-cfn-stack as the CFn client region."));
|
|
27082
25117
|
}
|
|
27083
25118
|
|
|
@@ -28088,6 +26123,7 @@ async function localStartMicrovmCommand(target, options, extraStateProviders, ho
|
|
|
28088
26123
|
disposeMicrovmCodeArtifact(artifact);
|
|
28089
26124
|
};
|
|
28090
26125
|
const teardown = () => teardownPromise ??= doTeardown();
|
|
26126
|
+
await activateWorkloadAwsWiring(options);
|
|
28091
26127
|
await applyRoleArnIfSet({
|
|
28092
26128
|
roleArn: options.roleArn,
|
|
28093
26129
|
region: options.region,
|
|
@@ -28267,6 +26303,7 @@ function createLocalStartMicrovmCommand(opts = {}) {
|
|
|
28267
26303
|
return cmd;
|
|
28268
26304
|
}
|
|
28269
26305
|
function addStartMicrovmSpecificOptions(cmd) {
|
|
26306
|
+
addAwsEndpointOptions(cmd);
|
|
28270
26307
|
return cmd.addOption(new Option("--count <n>", "Number of independent MicroVMs to run, each with its own URL.").default(1).argParser(parseCount)).addOption(new Option("--run-hook-payload <string>", "The runHookPayload string delivered to each MicroVM's /run hook (max 16 KB).")).addOption(new Option("--run-hook-payload-file <path>", "Read the runHookPayload from a file (mutually exclusive with --run-hook-payload).")).addOption(new Option("--port <n>", "Local port of the first MicroVM; MicroVM i listens on <n>+i. Default 0 (OS-assigned).").default(0).argParser(parsePort)).addOption(new Option("--host <ip>", "Address the MicroVM URLs listen on.").default("127.0.0.1")).addOption(new Option("--platform <platform>", "docker --platform for the build and the containers. Defaults to the image's CpuConfigurations architecture.").choices(["linux/amd64", "linux/arm64"])).addOption(new Option("--proxy-port <port>", "An extra container port X-aws-proxy-port may route to (repeatable). 8080, Hooks.Port and the image's EXPOSE ports are always routable.").argParser(parseProxyPort)).addOption(new Option("--auto-resume", "Resume a suspended MicroVM on its next request instead of answering 503 (autoResumeEnabled).")).addOption(new Option("--no-build-cache", "Build the image with docker build --no-cache.")).addOption(new Option("--env-vars <file>", "JSON env-var overrides (SAM-compatible: {\"MicrovmImageLogicalId\":{\"KEY\":\"VALUE\"}, \"Parameters\": {...}})")).addOption(new Option("--timeout <ms>", "Default deadline in milliseconds for each hook without its own <Hook>TimeoutInSeconds (/terminate defaults to 10000), and for the app to answer HTTP when there is no /ready hook. Default 60000.").default(6e4).argParser(parseTimeoutMs)).addOption(new Option("--assume-role <arn>", "Assume this role (the MicroVM's execution role, a run-microvm parameter rather than part of the template) and forward STS-issued temp credentials to the containers. Off by default: the shell credentials are forwarded.")).addOption(new Option("--from-cfn-stack [cfn-stack-name]", "Read a deployed CloudFormation stack and substitute Ref / Fn::ImportValue in env vars with the deployed physical IDs / exports. Bare form uses the resolved stack name.")).addOption(new Option("--stack-region <region>", "Region of the state record to read. Used with --from-cfn-stack as the CFn client region."));
|
|
28271
26308
|
}
|
|
28272
26309
|
|
|
@@ -33599,5 +31636,5 @@ function addStudioSpecificOptions(cmd) {
|
|
|
33599
31636
|
}
|
|
33600
31637
|
|
|
33601
31638
|
//#endregion
|
|
33602
|
-
export { postHook as $, deployedFillMayBeSecret as $a, parseConnectionsPath as $i, addImageOverrideOptions as $n, addStartApiSpecificOptions as $r, classifyS3Error as $t, microvmFidelityWarnings as A, discoverWebSocketApisOrThrow as Aa, applyCorsResponseHeaders as Ai, stripCloudFrontImport as An, A2A_CONTAINER_PORT as Ar, readContainerLogTail as At, MICROVM_WS_BASE_PROTOCOL as B, AGENTCORE_MCP_PROTOCOL as Ba, evaluateResponseParameters as Bi, createLocalStartAlbCommand as Bn, AGENTCORE_SESSION_ID_HEADER as Br, parseWebFunctionBuildConfig as Bt, addListSpecificOptions as C, resolveSsmParameters as Ca, verifyJwtViaDiscovery as Ci, WEB_FUNCTION_REVISION_TYPE as Cn, setShadowReadyTimeoutMs as Cr, parseKvsFileOverrides as Ct, buildMicrovmLambdaView as D, listTargets as Da, invokeRequestAuthorizer as Di, compileCloudFrontFunction as Dn, createLocalInvokeAgentCoreCommand as Dr, WEB_FUNCTION_CONTAINER_PORT as Dt, addStartMicrovmSpecificOptions as E, countTargets as Ea, evaluateCachedLambdaPolicy as Ei, resolveWebFunctionTarget as En, addInvokeAgentCoreSpecificOptions as Er, RecentOutput as Et, microvmImageTag as F, pickRefLogicalId as Fa, matchRoute as Fi, findFileAssetForObjectKey as Fn, MCP_PROTOCOL_VERSION as Fr, buildNodeEntryFileStart as Ft, startMicrovmFrontDoor as G, derivePseudoParametersFromRegion as Ga, HOST_DOCKER_INTERNAL_GATEWAY as Gi, addStartServiceSpecificOptions as Gn, SUPPORTED_CODE_RUNTIMES as Gr, readWebFunctionServiceConfig as Gt, PROXY_PORT_HEADER as H, AgentCoreResolutionError as Ha, selectIntegrationResponse as Hi, resolveAlbTarget as Hn, waitForAgentCoreHttpReady as Hr, WEB_FUNCTION_HTTP_ENDPOINT_ENV as Ht, planMicrovmPorts as I, resolveLambdaArnIntrinsic as Ia, translateLambdaResponse as Ii, isBucketDeploymentResource as In, mcpInvokeOnce as Ir, defaultWebFunctionPlatform as It, MICROVM_HOOK_PATH_PREFIX as J, tryResolveImageFnJoin as Ja, resolveHostGatewayExtraHosts as Ji, addRunTaskSpecificOptions as Jn, renderCodeDockerfile as Jr, idFromArn as Jt, stripMicrovmProxyHeaders as K, formatStateRemedy as Ka, HOST_GATEWAY_MIN_VERSION as Ki, createLocalStartServiceCommand as Kn, buildAgentCoreCodeImage as Kr, webFunctionAssumeRole as Kt, readExposedPorts as L, AGENTCORE_A2A_PROTOCOL as La, applyAuthorizerOverlay as Li, resolveBucketDeploymentObjectKey as Ln, parseSseForJsonRpc as Lr, resolveWebFunctionRuntime as Lt, DEFAULT_TERMINATE_HOOK_TIMEOUT_MS as M, parseSelectionExpressionPath as Ma, buildCorsConfigFromCloudFrontChain as Mi, createLocalFileKvsDataSource as Mn, a2aInvokeOnce as Mr, waitForWebFunctionReady as Mt, LocalMicrovm as N, webSocketApiMatchesIdentifier as Na, isFunctionUrlOacFronted as Ni, createUnboundCloudFrontModule as Nn, MCP_CONTAINER_PORT as Nr, watchContainerExit as Nt, createLocalStartMicrovmCommand as O, availableWebSocketApiIdentifiers as Oa, invokeTokenAuthorizer as Oi, runViewerRequest as On, bridgeAgentCoreWs as Or, containerFailure as Ot, buildMicrovmImage as P, discoverRoutes as Pa, matchPreflight as Pi, bucketDeploymentSourceObjectKeys as Pn, MCP_PATH as Pr, WEB_FUNCTION_RUNTIMES as Pt, pollBuildHook as Q, containsDynamicReference as Qa, handleConnectionsRequest as Qi, addEcsAssumeRoleOptions as Qn, createLocalInvokeCommand as Qr, resolveDeployedOriginBucket as Qt, setContainerPaused as R, AGENTCORE_AGUI_PROTOCOL as Ra, buildHttpApiV2Event as Ri, addAlbSpecificOptions as Rn, AGENTCORE_SIGV4_SERVICE as Rr, supportedWebFunctionRuntimes as Rt, StudioEventBus as S, collectSsmParameterRefs as Sa, verifyJwtAuthorizer as Si, WEB_FUNCTION_ENDPOINT_TYPE as Sn, SOFT_RELOAD_COMPLETION_LOG_SUFFIX as Sr, normalizeKvsFileKeys as St, formatTargetListing as T, resolveSingleTarget as Ta, computeRequestIdentityHash as Ti, WebFunctionResolutionError as Tn, attachContainerLogStreamer as Tr, resolveCloudFrontTarget as Tt, rewriteUpgradeResponseHead as U, pickAgentCoreCandidateStack as Ua, tryParseStatus as Ui, isApplicationLoadBalancer as Un, waitForAgentCorePing as Ur, buildWebFunctionLambdaView as Ut, MicrovmStateError as V, AGENTCORE_RUNTIME_TYPE as Va, pickResponseTemplate as Vi, parseLbPortOverrides as Vn, invokeAgentCore as Vr, resolveWebFunctionArtifact as Vt, selectTargetPort as W, resolveAgentCoreTarget as Wa, VtlEvaluationError as Wi, resolveAlbFrontDoor as Wn, downloadAndExtractS3Bundle as Wr, finalizeWebFunctionEnv as Wt, callRuntimeHook as X, DynamicReferenceResolutionError as Xa, ConnectionRegistry as Xi, MAX_TASKS_SUBNET_RANGE_CAP as Xn, classifySourceChange as Xr, createDeployedKvsDataSource as Xt, MicrovmHookError as Y, LocalInvokeBuildError as Ya, bufferToBody as Yi, createLocalRunTaskCommand as Yn, toCmdArgv as Yr, resolveKvsModulesForDistribution as Yt, generateMicrovmId as Z, DynamicReferenceResolver as Za, buildMgmtEndpointEnvUrl as Zi, addCommonEcsServiceOptions as Zn, addInvokeSpecificOptions as Zr, resolveDeployedKvsArnByName as Zt, filterStudioTargetGroups as _, rejectExplicitCfnStackWithMultipleStacks as _a, defaultCredentialsLoader as _i, pickKvsLogicalIdFromArn as _n, isProxyEnvConfigured as _o, isLocalCdkAssetImage as _r, attachAgentCoreWsBridge as _t, createLocalStudioCommand as a, resolveRuntimeCodeMountPath as aa, attachStageContext as ai, serveLambdaUrlOrigin as an, withoutKeys as ao, resolveSharedSidecarCredentials as ar, disposeMicrovmCodeArtifact as at, renderStudioHtml as b, resolveCfnStackName as ba, createJwksCache as bi, pickWebFunctionEndpointLogicalIdFromOrigin as bn, CloudMapRegistry as br, addStartCloudFrontSpecificOptions as bt, startStudioProxy as c, EcsTaskResolutionError as ca, resolveEnvVars$1 as ci, buildEdgeRequestEvent as cn, deployAccountStsClientConfig as co, buildImageOverrideTag as cr, resolveMicrovmImageTarget as ct, createStudioDispatcher as d, substituteAgainstStateAsync as da, filterRoutesByApiIdentifiers as di, httpHeadersToEdge as dn, resetWorkloadIdentity as do, mergeForService as dr, createLocalStartWebFunctionCommand as dt, buildConnectEvent as ea, createLocalStartApiCommand as ei, createS3OriginReader as en, firstUsableRegion as eo, buildEcsImageResolutionContext$1 as er, runHookBody as et, filterStudioCustomResources as f, substituteEnvVarsFromState as fa, groupRoutesByServer as fi, CLOUDFRONT_DISTRIBUTION_TYPE as fn, workloadClientConfig as fo, parseImageOverrideFlags as fr, addStartAgentCoreSpecificOptions as ft, annotatePinnedEcsTargets as g, isCfnFlagPresent as ga, resolveServiceIntegrationParameters as gi, pickFunctionUrlLogicalIdFromOrigin as gn, buildProxyClientConfig as go, imageOverrideKeyAliases as gr, startAgentCoreHttpServer as gt, annotateEcsTaskPinnedTargets as h, createLocalStateProvider as ha, resolveSelectionExpression as hi, isCloudFrontDistribution as hn, resolveProfileCredentials as ho, describePinnedImageUri as hr, selectServeInboundAuth as ht, coerceStopRequest as i, buildContainerImage as ia, createFileWatcher as ii, serveFromStaticOrigin as in, resolveDynamicReferencesInEnv as io, resolveEcsAssumeRoleOption as ir, MicrovmResolutionError as it, readRunHookPayload as j, filterWebSocketApisByIdentifiers as ja, buildCorsConfigByApiId as ji, createCloudFrontModule as jn, A2A_PATH as jr, startWebFunctionContainer as jt, finalizeMicrovmEnv as k, discoverWebSocketApis as ka, attachAuthorizers as ki, runViewerResponse as kn, invokeAgentCoreWs as kr, planWebFunctionContainer as kt, relayServeRequest as l, assertEcsTaskImagesResolvable as la, availableApiIdentifiers as li, buildEdgeResponseEvent as ln, readEnvCallerCredentials as lo, canonicalizeImageOverrideKeys as lr, s3KeyOfUri as lt, annotateAlbPinnedBackingServices as m, LocalStateSourceError as ma, startApiServer as mi, extractKvsAssociations as mn, buildStsClientConfig as mo, runImageOverrideBuilds as mr, buildAgentCoreServeAuthCheck as mt, coerceRunRequest as n, buildMessageEvent as na, resolveApiTargetSubset as ni, startCloudFrontServer as nn, keysOverriddenBy as no, parseMaxTasks as nr, MICROVM_DEFAULT_INGRESS_PORT as nt, resolveServeBaseUrl as o, resolveRuntimeFileExtension as oa, buildStageMap as oi, applyEdgeRequestResult as on, SECOND_ASSUME_MESSAGE as oo, runEcsServiceEmulator as or, readMicrovmImageConfig as ot, isCustomResourceLambdaTarget as p, substituteEnvVarsFromStateAsync as pa, readMtlsMaterialsFromDisk as pi, describeS3OriginDomain as pn, workloadStsClientConfig as po, resolveImageOverrides as pr, createLocalStartAgentCoreCommand as pt, MAX_RUN_HOOK_PAYLOAD_BYTES as q, substituteImagePlaceholders as qa, probeHostGatewaySupport as qi, serviceStrategy as qn, computeCodeImageTag as qr, webFunctionFidelityWarnings as qt, coerceServeRequest as r, architectureToPlatform as ra, createAuthorizerCache as ri, resolveErrorResponseCandidates as rn, parseDynamicReference as ro, parseRestartPolicy as rr, MICROVM_IMAGE_TYPE as rt, createStudioServeManager as s, resolveRuntimeImage as sa, materializeLayerFromArn as si, applyEdgeResponseResult as sn, assumedRoleRecorded as so, ImageOverrideError as sr, resolveMicrovmCodeArtifact as st, addStudioSpecificOptions as t, buildDisconnectEvent as ta, createWatchPredicates as ti, matchBehavior as tn, keysNotFromTemplate as to, ecsClusterOption as tr, waitForAppAnswer as tt, reinvoke as u, substituteAgainstState as ua, filterRoutesByApiIdentifier as ui, edgeHeadersToHttp as un, recordAssumedRole as uo, enforceImageOverrideOrphans as ur, addStartWebFunctionSpecificOptions as ut, startStudioServer as v, resolveCfnFallbackRegion as va, buildCognitoJwksUrl as vi, pickLambdaEdgeFunctionLogicalId as vn, listPinnedTargets as vr, startAgentCoreWsBridge as vt, createLocalListCommand as w, resolveWatchConfig as wa, buildMethodArn as wi, WEB_FUNCTION_TYPE as wn, getContainerNetworkIp as wr, parseOriginOverrides as wt, createStudioStore as x, CfnLocalStateProvider as xa, verifyCognitoJwt as xi, resolveCloudFrontDistribution as xn, DEFAULT_SHADOW_READY_TIMEOUT_MS as xr, createLocalStartCloudFrontCommand as xt, toStudioTargetGroups as y, resolveCfnRegion as ya, buildJwksUrlFromIssuer as yi, pickTargetFunctionLogicalId as yn, buildCloudMapIndex as yr, LocalStartCloudFrontError as yt, MICROVM_CONTROL_PATH as z, AGENTCORE_HTTP_PROTOCOL as za, buildRestV1Event as zi, albStrategy as zn, signAgentCoreInvocation as zr, disposeWebFunctionArtifact as zt };
|
|
33603
|
-
//# sourceMappingURL=local-studio-
|
|
31639
|
+
export { postHook as $, addAwsEndpointOptions as $a, parseConnectionsPath as $i, addImageOverrideOptions as $n, addStartApiSpecificOptions as $r, classifyS3Error as $t, microvmFidelityWarnings as A, parseSelectionExpressionPath as Aa, applyCorsResponseHeaders as Ai, stripCloudFrontImport as An, A2A_CONTAINER_PORT as Ar, readContainerLogTail as At, MICROVM_WS_BASE_PROTOCOL as B, AgentCoreResolutionError as Ba, evaluateResponseParameters as Bi, createLocalStartAlbCommand as Bn, AGENTCORE_SESSION_ID_HEADER as Br, parseWebFunctionBuildConfig as Bt, addListSpecificOptions as C, resolveSingleTarget as Ca, verifyJwtViaDiscovery as Ci, WEB_FUNCTION_REVISION_TYPE as Cn, setShadowReadyTimeoutMs as Cr, parseKvsFileOverrides as Ct, buildMicrovmLambdaView as D, discoverWebSocketApis as Da, invokeRequestAuthorizer as Di, compileCloudFrontFunction as Dn, createLocalInvokeAgentCoreCommand as Dr, WEB_FUNCTION_CONTAINER_PORT as Dt, addStartMicrovmSpecificOptions as E, availableWebSocketApiIdentifiers as Ea, evaluateCachedLambdaPolicy as Ei, resolveWebFunctionTarget as En, addInvokeAgentCoreSpecificOptions as Er, RecentOutput as Et, microvmImageTag as F, AGENTCORE_A2A_PROTOCOL as Fa, matchRoute as Fi, findFileAssetForObjectKey as Fn, MCP_PROTOCOL_VERSION as Fr, buildNodeEntryFileStart as Ft, startMicrovmFrontDoor as G, containsDynamicReference as Ga, HOST_DOCKER_INTERNAL_GATEWAY as Gi, addStartServiceSpecificOptions as Gn, SUPPORTED_CODE_RUNTIMES as Gr, readWebFunctionServiceConfig as Gt, PROXY_PORT_HEADER as H, resolveAgentCoreTarget as Ha, selectIntegrationResponse as Hi, resolveAlbTarget as Hn, waitForAgentCoreHttpReady as Hr, WEB_FUNCTION_HTTP_ENDPOINT_ENV as Ht, planMicrovmPorts as I, AGENTCORE_AGUI_PROTOCOL as Ia, translateLambdaResponse as Ii, isBucketDeploymentResource as In, mcpInvokeOnce as Ir, defaultWebFunctionPlatform as It, MICROVM_HOOK_PATH_PREFIX as J, keysNotFromTemplate as Ja, resolveHostGatewayExtraHosts as Ji, addRunTaskSpecificOptions as Jn, renderCodeDockerfile as Jr, idFromArn as Jt, stripMicrovmProxyHeaders as K, deployedFillMayBeSecret as Ka, HOST_GATEWAY_MIN_VERSION as Ki, createLocalStartServiceCommand as Kn, buildAgentCoreCodeImage as Kr, webFunctionAssumeRole as Kt, readExposedPorts as L, AGENTCORE_HTTP_PROTOCOL as La, applyAuthorizerOverlay as Li, resolveBucketDeploymentObjectKey as Ln, parseSseForJsonRpc as Lr, resolveWebFunctionRuntime as Lt, DEFAULT_TERMINATE_HOOK_TIMEOUT_MS as M, discoverRoutes as Ma, buildCorsConfigFromCloudFrontChain as Mi, createLocalFileKvsDataSource as Mn, a2aInvokeOnce as Mr, waitForWebFunctionReady as Mt, LocalMicrovm as N, pickRefLogicalId as Na, isFunctionUrlOacFronted as Ni, createUnboundCloudFrontModule as Nn, MCP_CONTAINER_PORT as Nr, watchContainerExit as Nt, createLocalStartMicrovmCommand as O, discoverWebSocketApisOrThrow as Oa, invokeTokenAuthorizer as Oi, runViewerRequest as On, bridgeAgentCoreWs as Or, containerFailure as Ot, buildMicrovmImage as P, resolveLambdaArnIntrinsic as Pa, matchPreflight as Pi, bucketDeploymentSourceObjectKeys as Pn, MCP_PATH as Pr, WEB_FUNCTION_RUNTIMES as Pt, pollBuildHook as Q, withoutKeys as Qa, handleConnectionsRequest as Qi, addEcsAssumeRoleOptions as Qn, createLocalInvokeCommand as Qr, resolveDeployedOriginBucket as Qt, setContainerPaused as R, AGENTCORE_MCP_PROTOCOL as Ra, buildHttpApiV2Event as Ri, addAlbSpecificOptions as Rn, AGENTCORE_SIGV4_SERVICE as Rr, supportedWebFunctionRuntimes as Rt, StudioEventBus as S, resolveWatchConfig as Sa, verifyJwtAuthorizer as Si, WEB_FUNCTION_ENDPOINT_TYPE as Sn, SOFT_RELOAD_COMPLETION_LOG_SUFFIX as Sr, normalizeKvsFileKeys as St, formatTargetListing as T, listTargets as Ta, computeRequestIdentityHash as Ti, WebFunctionResolutionError as Tn, attachContainerLogStreamer as Tr, resolveCloudFrontTarget as Tt, rewriteUpgradeResponseHead as U, DynamicReferenceResolutionError as Ua, tryParseStatus as Ui, isApplicationLoadBalancer as Un, waitForAgentCorePing as Ur, buildWebFunctionLambdaView as Ut, MicrovmStateError as V, pickAgentCoreCandidateStack as Va, pickResponseTemplate as Vi, parseLbPortOverrides as Vn, invokeAgentCore as Vr, resolveWebFunctionArtifact as Vt, selectTargetPort as W, DynamicReferenceResolver as Wa, VtlEvaluationError as Wi, resolveAlbFrontDoor as Wn, downloadAndExtractS3Bundle as Wr, finalizeWebFunctionEnv as Wt, callRuntimeHook as X, parseDynamicReference as Xa, ConnectionRegistry as Xi, MAX_TASKS_SUBNET_RANGE_CAP as Xn, classifySourceChange as Xr, createDeployedKvsDataSource as Xt, MicrovmHookError as Y, keysOverriddenBy as Ya, bufferToBody as Yi, createLocalRunTaskCommand as Yn, toCmdArgv as Yr, resolveKvsModulesForDistribution as Yt, generateMicrovmId as Z, resolveDynamicReferencesInEnv as Za, buildMgmtEndpointEnvUrl as Zi, addCommonEcsServiceOptions as Zn, addInvokeSpecificOptions as Zr, resolveDeployedKvsArnByName as Zt, filterStudioTargetGroups as _, resolveCfnRegion as _a, defaultCredentialsLoader as _i, pickKvsLogicalIdFromArn as _n, isLocalCdkAssetImage as _r, attachAgentCoreWsBridge as _t, createLocalStudioCommand as a, resolveRuntimeImage as aa, attachStageContext as ai, serveLambdaUrlOrigin as an, resolveSharedSidecarCredentials as ar, disposeMicrovmCodeArtifact as at, renderStudioHtml as b, collectSsmParameterRefs as ba, createJwksCache as bi, pickWebFunctionEndpointLogicalIdFromOrigin as bn, CloudMapRegistry as br, addStartCloudFrontSpecificOptions as bt, startStudioProxy as c, substituteAgainstState as ca, resolveEnvVars$1 as ci, buildEdgeRequestEvent as cn, buildImageOverrideTag as cr, resolveMicrovmImageTarget as ct, createStudioDispatcher as d, substituteEnvVarsFromStateAsync as da, filterRoutesByApiIdentifiers as di, httpHeadersToEdge as dn, mergeForService as dr, createLocalStartWebFunctionCommand as dt, buildConnectEvent as ea, createLocalStartApiCommand as ei, createS3OriginReader as en, awsEndpointOptions as eo, buildEcsImageResolutionContext$1 as er, runHookBody as et, filterStudioCustomResources as f, LocalStateSourceError as fa, groupRoutesByServer as fi, CLOUDFRONT_DISTRIBUTION_TYPE as fn, parseImageOverrideFlags as fr, addStartAgentCoreSpecificOptions as ft, annotatePinnedEcsTargets as g, resolveCfnFallbackRegion as ga, resolveServiceIntegrationParameters as gi, pickFunctionUrlLogicalIdFromOrigin as gn, imageOverrideKeyAliases as gr, startAgentCoreHttpServer as gt, annotateEcsTaskPinnedTargets as h, rejectExplicitCfnStackWithMultipleStacks as ha, resolveSelectionExpression as hi, isCloudFrontDistribution as hn, describePinnedImageUri as hr, selectServeInboundAuth as ht, coerceStopRequest as i, resolveRuntimeFileExtension as ia, createFileWatcher as ii, serveFromStaticOrigin as in, resolveEcsAssumeRoleOption as ir, MicrovmResolutionError as it, readRunHookPayload as j, webSocketApiMatchesIdentifier as ja, buildCorsConfigByApiId as ji, createCloudFrontModule as jn, A2A_PATH as jr, startWebFunctionContainer as jt, finalizeMicrovmEnv as k, filterWebSocketApisByIdentifiers as ka, attachAuthorizers as ki, runViewerResponse as kn, invokeAgentCoreWs as kr, planWebFunctionContainer as kt, relayServeRequest as l, substituteAgainstStateAsync as la, availableApiIdentifiers as li, buildEdgeResponseEvent as ln, canonicalizeImageOverrideKeys as lr, s3KeyOfUri as lt, annotateAlbPinnedBackingServices as m, isCfnFlagPresent as ma, startApiServer as mi, extractKvsAssociations as mn, runImageOverrideBuilds as mr, buildAgentCoreServeAuthCheck as mt, coerceRunRequest as n, buildMessageEvent as na, resolveApiTargetSubset as ni, startCloudFrontServer as nn, parseMaxTasks as nr, MICROVM_DEFAULT_INGRESS_PORT as nt, resolveServeBaseUrl as o, EcsTaskResolutionError as oa, buildStageMap as oi, applyEdgeRequestResult as on, runEcsServiceEmulator as or, readMicrovmImageConfig as ot, isCustomResourceLambdaTarget as p, createLocalStateProvider as pa, readMtlsMaterialsFromDisk as pi, describeS3OriginDomain as pn, resolveImageOverrides as pr, createLocalStartAgentCoreCommand as pt, MAX_RUN_HOOK_PAYLOAD_BYTES as q, firstUsableRegion as qa, probeHostGatewaySupport as qi, serviceStrategy as qn, computeCodeImageTag as qr, webFunctionFidelityWarnings as qt, coerceServeRequest as r, resolveRuntimeCodeMountPath as ra, createAuthorizerCache as ri, resolveErrorResponseCandidates as rn, parseRestartPolicy as rr, MICROVM_IMAGE_TYPE as rt, createStudioServeManager as s, assertEcsTaskImagesResolvable as sa, materializeLayerFromArn as si, applyEdgeResponseResult as sn, ImageOverrideError as sr, resolveMicrovmCodeArtifact as st, addStudioSpecificOptions as t, buildDisconnectEvent as ta, createWatchPredicates as ti, matchBehavior as tn, ecsClusterOption as tr, waitForAppAnswer as tt, reinvoke as u, substituteEnvVarsFromState as ua, filterRoutesByApiIdentifier as ui, edgeHeadersToHttp as un, enforceImageOverrideOrphans as ur, addStartWebFunctionSpecificOptions as ut, startStudioServer as v, resolveCfnStackName as va, buildCognitoJwksUrl as vi, pickLambdaEdgeFunctionLogicalId as vn, listPinnedTargets as vr, startAgentCoreWsBridge as vt, createLocalListCommand as w, countTargets as wa, buildMethodArn as wi, WEB_FUNCTION_TYPE as wn, getContainerNetworkIp as wr, parseOriginOverrides as wt, createStudioStore as x, resolveSsmParameters as xa, verifyCognitoJwt as xi, resolveCloudFrontDistribution as xn, DEFAULT_SHADOW_READY_TIMEOUT_MS as xr, createLocalStartCloudFrontCommand as xt, toStudioTargetGroups as y, CfnLocalStateProvider as ya, buildJwksUrlFromIssuer as yi, pickTargetFunctionLogicalId as yn, buildCloudMapIndex as yr, LocalStartCloudFrontError as yt, MICROVM_CONTROL_PATH as z, AGENTCORE_RUNTIME_TYPE as za, buildRestV1Event as zi, albStrategy as zn, signAgentCoreInvocation as zr, disposeWebFunctionArtifact as zt };
|
|
31640
|
+
//# sourceMappingURL=local-studio-DNWiPLme.js.map
|