cdk-local 0.148.0 → 0.148.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +7 -2
- package/dist/cli.js +2 -2
- package/dist/index.js +1 -1
- package/dist/internal.d.ts.map +1 -1
- package/dist/internal.js +1 -1
- package/dist/local-studio-9bZLFQqv.d.ts.map +1 -1
- package/dist/{local-studio-DoyRYZf6.js → local-studio-BVxRUfQV.js} +334 -18
- package/dist/local-studio-BVxRUfQV.js.map +1 -0
- package/package.json +1 -1
- package/dist/local-studio-DoyRYZf6.js.map +0 -1
|
@@ -6,7 +6,8 @@ import path, { dirname, isAbsolute, join, normalize, relative, resolve, sep } fr
|
|
|
6
6
|
import { Command, Option } from "commander";
|
|
7
7
|
import { AssumeRoleCommand, GetCallerIdentityCommand, STSClient } from "@aws-sdk/client-sts";
|
|
8
8
|
import { Agent, createServer, request } from "node:http";
|
|
9
|
-
import { Agent as Agent$1, createServer as createServer$1 } from "node:https";
|
|
9
|
+
import { Agent as Agent$1, createServer as createServer$1, request as request$1 } from "node:https";
|
|
10
|
+
import { brotliDecompressSync, gunzipSync, inflateSync } from "node:zlib";
|
|
10
11
|
import { NodeHttpHandler } from "@smithy/node-http-handler";
|
|
11
12
|
import { Agent as Agent$2 } from "agent-base";
|
|
12
13
|
import { HttpProxyAgent } from "http-proxy-agent";
|
|
@@ -195,6 +196,13 @@ function hostFromAuthority(authority) {
|
|
|
195
196
|
* via `buildStsClientConfig` for the STS sites);
|
|
196
197
|
* `tests/unit/utils/aws-proxy-client-audit.test.ts` fences the sweep so a new
|
|
197
198
|
* construction site cannot silently skip it.
|
|
199
|
+
*
|
|
200
|
+
* Not every AWS-bound request is an SDK call, though — and the global
|
|
201
|
+
* `fetch` (undici) reads no proxy variable either (issue #647). The layer
|
|
202
|
+
* ZIP download and the Cognito JWKS / OIDC discovery reads are plain GETs,
|
|
203
|
+
* so `proxyAwareFetch()` is the second seam: same `NO_PROXY` decision, same
|
|
204
|
+
* "empty when unconfigured" contract, fenced by
|
|
205
|
+
* `tests/unit/utils/aws-proxy-fetch-audit.test.ts`.
|
|
198
206
|
*/
|
|
199
207
|
/**
|
|
200
208
|
* The SDK applies these defaults only when it builds its OWN agents from a
|
|
@@ -312,23 +320,305 @@ function buildProxyRequestHandler() {
|
|
|
312
320
|
function buildProxyClientConfig(opts = {}) {
|
|
313
321
|
if (!isProxyEnvConfigured()) return {};
|
|
314
322
|
const profile = opts.profile;
|
|
315
|
-
const chainHandler = buildProxyRequestHandler();
|
|
316
323
|
let chain;
|
|
317
324
|
const credentials = async (identityProperties) => {
|
|
318
|
-
|
|
325
|
+
chain ??= (async () => {
|
|
319
326
|
const { defaultProvider } = await import("@aws-sdk/credential-provider-node");
|
|
320
|
-
|
|
327
|
+
return defaultProvider({
|
|
321
328
|
...profile ? { profile } : {},
|
|
322
|
-
clientConfig: { requestHandler:
|
|
329
|
+
clientConfig: { requestHandler: buildProxyRequestHandler() }
|
|
323
330
|
});
|
|
324
|
-
}
|
|
325
|
-
|
|
331
|
+
})().catch((err) => {
|
|
332
|
+
chain = void 0;
|
|
333
|
+
throw err;
|
|
334
|
+
});
|
|
335
|
+
return (await chain)(identityProperties);
|
|
326
336
|
};
|
|
327
337
|
return {
|
|
328
338
|
requestHandler: buildProxyRequestHandler(),
|
|
329
339
|
credentials
|
|
330
340
|
};
|
|
331
341
|
}
|
|
342
|
+
/**
|
|
343
|
+
* The fetch spec's redirect budget. Reached only by a redirect loop, which
|
|
344
|
+
* neither call site's endpoint produces — the bound exists so a
|
|
345
|
+
* misconfigured origin cannot spin forever.
|
|
346
|
+
*/
|
|
347
|
+
const MAX_FETCH_REDIRECTS = 20;
|
|
348
|
+
/** Statuses whose response carries a null body per the fetch spec. */
|
|
349
|
+
const NULL_BODY_STATUSES = /* @__PURE__ */ new Set([
|
|
350
|
+
204,
|
|
351
|
+
205,
|
|
352
|
+
304
|
|
353
|
+
]);
|
|
354
|
+
/**
|
|
355
|
+
* Socket-inactivity bound for a proxied request, matching undici's
|
|
356
|
+
* `headersTimeout` / `bodyTimeout` defaults — because `node:http` has NO
|
|
357
|
+
* default timeout at all, and without one a proxy that accepts the
|
|
358
|
+
* connection and never answers hangs `cdkl` forever. That is strictly worse
|
|
359
|
+
* than the pre-#647 direct connection it replaced, and it would hang exactly
|
|
360
|
+
* the fallback (`docs/cli-reference.md`, "JWKS / OIDC discovery
|
|
361
|
+
* unreachable") that exists to keep local dev moving.
|
|
362
|
+
*
|
|
363
|
+
* Undici's separate 10 s CONNECT timeout is not reproduced: a black-holed
|
|
364
|
+
* proxy fails here in 300 s rather than 10. Bounded is the property that
|
|
365
|
+
* matters; the exempt path keeps undici's own timers (see the short-circuit
|
|
366
|
+
* in {@link proxyAwareFetch}). Enforced by a timer `getThroughAgent` re-arms
|
|
367
|
+
* on every byte — INACTIVITY, like undici's, not a wall-clock TOTAL, which
|
|
368
|
+
* would abort a slow-but-progressing transfer that `fetch` would have
|
|
369
|
+
* completed (a Lambda layer ZIP is up to 250 MB, and the whole point is that
|
|
370
|
+
* it is crossing a corporate proxy). See `getThroughAgent` for why a
|
|
371
|
+
* socket-level timer cannot bound the CONNECT tunnel.
|
|
372
|
+
*/
|
|
373
|
+
const REQUEST_STALL_TIMEOUT_MS = 3e5;
|
|
374
|
+
function isRedirectStatus(status) {
|
|
375
|
+
return status === 301 || status === 302 || status === 303 || status === 307 || status === 308;
|
|
376
|
+
}
|
|
377
|
+
/**
|
|
378
|
+
* Whether `hostname` names THIS machine. `proxy-from-env` implements the
|
|
379
|
+
* standard `NO_PROXY` semantics faithfully, and the standard exempts nothing
|
|
380
|
+
* by default — so with `HTTP_PROXY` exported and no matching `NO_PROXY`
|
|
381
|
+
* entry, a request to `127.0.0.1` is sent to the corporate proxy, which
|
|
382
|
+
* cannot reach the caller's own loopback and refuses it.
|
|
383
|
+
*
|
|
384
|
+
* For an AWS SDK client that is unreachable in practice (every endpoint is a
|
|
385
|
+
* public AWS host), which is why {@link EnvRoutingProxyAgent} does not carry
|
|
386
|
+
* this rule. For `proxyAwareFetch` it is not: a JWT authorizer's issuer is
|
|
387
|
+
* routinely a loopback IdP in local dev — this repo's own
|
|
388
|
+
* `local-start-api-cognito-jwt` fixture is exactly that shape — and an
|
|
389
|
+
* unreachable JWKS does not fail the request, it degrades the verifier to
|
|
390
|
+
* ACCEPT EVERY TOKEN with a warn. So proxying loopback here converts a
|
|
391
|
+
* working local setup into a silent auth downgrade, and it cannot buy
|
|
392
|
+
* anything in exchange: a forward proxy has no route to the client's
|
|
393
|
+
* loopback. Every other loopback request in cdk-local (the RIE and AgentCore
|
|
394
|
+
* container clients) is unproxied for the same reason.
|
|
395
|
+
*
|
|
396
|
+
* Deliberately NOT extended to RFC 1918 / private ranges: a corporate proxy
|
|
397
|
+
* plausibly does reach those, so exempting them would be a guess rather
|
|
398
|
+
* than an impossibility. `NO_PROXY` remains the control for that case.
|
|
399
|
+
*/
|
|
400
|
+
/**
|
|
401
|
+
* Whether `proxyUrl` names a proxy these agents can actually SPEAK to.
|
|
402
|
+
*
|
|
403
|
+
* `getProxyForUrl` honours `ALL_PROXY`, and `ALL_PROXY=socks5://...` is an
|
|
404
|
+
* ordinary spelling — but `http-proxy-agent` / `https-proxy-agent` speak HTTP
|
|
405
|
+
* `CONNECT`, not SOCKS. Measured: `new HttpsProxyAgent('socks5://127.0.0.1:1080')`
|
|
406
|
+
* constructs happily and then talks HTTP at a SOCKS port, so every request
|
|
407
|
+
* through it fails.
|
|
408
|
+
*
|
|
409
|
+
* Falling back to a DIRECT request is the right answer rather than a
|
|
410
|
+
* best-effort attempt, for a reason specific to this seam: before issue #647
|
|
411
|
+
* these reads went direct through undici and WORKED for a SOCKS user, and an
|
|
412
|
+
* unreachable JWKS does not deny requests — it caches `passThrough` and
|
|
413
|
+
* accepts every token for the failure TTL. Trying and failing would turn a
|
|
414
|
+
* working setup into a silent auth downgrade, which is the outcome the
|
|
415
|
+
* loopback rule below exists to prevent.
|
|
416
|
+
*
|
|
417
|
+
* The SDK-client half of this — `EnvRoutingProxyAgent`, which PR 646 built
|
|
418
|
+
* with the same blind spot, and whose failures are at least loud — is tracked
|
|
419
|
+
* in https://github.com/go-to-k/cdk-local/issues/663.
|
|
420
|
+
*/
|
|
421
|
+
function isSpeakableProxy(proxyUrl) {
|
|
422
|
+
return /^https?:\/\//i.test(proxyUrl);
|
|
423
|
+
}
|
|
424
|
+
function isLoopbackHost(hostname) {
|
|
425
|
+
const host = hostname.trim().replace(/^\[|\]$/g, "").replace(/\.$/, "").toLowerCase();
|
|
426
|
+
if (host === "localhost" || host.endsWith(".localhost")) return true;
|
|
427
|
+
if (host === "::1" || host === "0:0:0:0:0:0:0:1") return true;
|
|
428
|
+
if (host === "0.0.0.0" || host === "::" || host === "0:0:0:0:0:0:0:0" || host === "::ffff:0.0.0.0" || host === "::ffff:0:0") return true;
|
|
429
|
+
const mapped = /^::ffff:([0-9a-f]{1,4}):([0-9a-f]{1,4})$/.exec(host);
|
|
430
|
+
if (mapped) return parseInt(mapped[1], 16) >> 8 === 127;
|
|
431
|
+
const dotted = /^(?:::ffff:)?(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/.exec(host);
|
|
432
|
+
if (!dotted) return false;
|
|
433
|
+
const octets = dotted.slice(1).map(Number);
|
|
434
|
+
if (octets.some((o) => o > 255)) return false;
|
|
435
|
+
return octets[0] === 127;
|
|
436
|
+
}
|
|
437
|
+
/**
|
|
438
|
+
* `http:` / `https:` only. The rejection names the PROTOCOL and never the
|
|
439
|
+
* URL: the presigned layer `Content.Location` carries an `X-Amz-Signature`
|
|
440
|
+
* in its query string, so a URL in an error message is a credential in a log
|
|
441
|
+
* line (the same reasoning `downloadPresignedZip`'s own HTTP-status throw
|
|
442
|
+
* applies).
|
|
443
|
+
*/
|
|
444
|
+
function parseHttpUrl(href) {
|
|
445
|
+
const parsed = new URL(href);
|
|
446
|
+
if (parsed.protocol !== "http:" && parsed.protocol !== "https:") throw new TypeError(`Unsupported protocol for a proxied request: "${parsed.protocol}"`);
|
|
447
|
+
return parsed;
|
|
448
|
+
}
|
|
449
|
+
/**
|
|
450
|
+
* One GET through `agent`, with the whole body buffered. Buffering is what
|
|
451
|
+
* lets the result become a real `Response` (and is what both call sites do
|
|
452
|
+
* with the body anyway: `text()` for JWKS / discovery, `arrayBuffer()` for
|
|
453
|
+
* the layer ZIP).
|
|
454
|
+
*/
|
|
455
|
+
function getThroughAgent(url, agent, timeoutMs = REQUEST_STALL_TIMEOUT_MS) {
|
|
456
|
+
return new Promise((resolve, reject) => {
|
|
457
|
+
let settled = false;
|
|
458
|
+
let timer;
|
|
459
|
+
let rearm = () => void 0;
|
|
460
|
+
const succeed = (value) => {
|
|
461
|
+
if (settled) return;
|
|
462
|
+
settled = true;
|
|
463
|
+
if (timer) clearTimeout(timer);
|
|
464
|
+
resolve(value);
|
|
465
|
+
};
|
|
466
|
+
const fail = (err) => {
|
|
467
|
+
if (settled) return;
|
|
468
|
+
settled = true;
|
|
469
|
+
if (timer) clearTimeout(timer);
|
|
470
|
+
reject(err);
|
|
471
|
+
};
|
|
472
|
+
const req = (url.protocol === "https:" ? request$1 : request)(url, {
|
|
473
|
+
agent,
|
|
474
|
+
headers: {
|
|
475
|
+
accept: "*/*",
|
|
476
|
+
"accept-encoding": "identity"
|
|
477
|
+
}
|
|
478
|
+
}, (res) => {
|
|
479
|
+
rearm();
|
|
480
|
+
const chunks = [];
|
|
481
|
+
res.on("data", (chunk) => {
|
|
482
|
+
rearm();
|
|
483
|
+
chunks.push(chunk);
|
|
484
|
+
});
|
|
485
|
+
res.on("error", fail);
|
|
486
|
+
res.on("end", () => {
|
|
487
|
+
if (res.statusCode === void 0) {
|
|
488
|
+
fail(/* @__PURE__ */ new Error("Malformed HTTP response: no status code"));
|
|
489
|
+
return;
|
|
490
|
+
}
|
|
491
|
+
succeed({
|
|
492
|
+
status: res.statusCode,
|
|
493
|
+
statusText: res.statusMessage ?? "",
|
|
494
|
+
headers: res.headers,
|
|
495
|
+
body: Buffer.concat(chunks)
|
|
496
|
+
});
|
|
497
|
+
});
|
|
498
|
+
});
|
|
499
|
+
req.on("error", fail);
|
|
500
|
+
rearm = () => {
|
|
501
|
+
if (settled) return;
|
|
502
|
+
if (timer) clearTimeout(timer);
|
|
503
|
+
timer = setTimeout(() => {
|
|
504
|
+
req.destroy();
|
|
505
|
+
fail(/* @__PURE__ */ new Error(`Proxied request stalled for ${timeoutMs} ms with no progress`));
|
|
506
|
+
}, timeoutMs);
|
|
507
|
+
timer.unref?.();
|
|
508
|
+
};
|
|
509
|
+
rearm();
|
|
510
|
+
req.end();
|
|
511
|
+
});
|
|
512
|
+
}
|
|
513
|
+
/**
|
|
514
|
+
* `fetch` decodes a `Content-Encoding` body before handing it to the caller;
|
|
515
|
+
* `node:http` does not. Node sends no `Accept-Encoding` of its own, so a
|
|
516
|
+
* compliant origin answers identity — but S3 replays an object's STORED
|
|
517
|
+
* `Content-Encoding`, so the case is reachable and a silently-still-
|
|
518
|
+
* compressed body would be a corrupt layer ZIP rather than an error.
|
|
519
|
+
*
|
|
520
|
+
* An encoding this cannot decode (or one that fails to decode) leaves the
|
|
521
|
+
* body and the header untouched, so the caller sees exactly what the origin
|
|
522
|
+
* sent instead of a truncated one.
|
|
523
|
+
*/
|
|
524
|
+
function decodeContentEncoding(raw) {
|
|
525
|
+
const header = raw.headers["content-encoding"];
|
|
526
|
+
const encoding = (Array.isArray(header) ? header.join(",") : header ?? "").trim().toLowerCase();
|
|
527
|
+
if (encoding === "" || encoding === "identity") return {
|
|
528
|
+
body: raw.body,
|
|
529
|
+
decoded: false
|
|
530
|
+
};
|
|
531
|
+
try {
|
|
532
|
+
if (encoding === "gzip" || encoding === "x-gzip") return {
|
|
533
|
+
body: gunzipSync(raw.body),
|
|
534
|
+
decoded: true
|
|
535
|
+
};
|
|
536
|
+
if (encoding === "deflate" || encoding === "x-deflate") return {
|
|
537
|
+
body: inflateSync(raw.body),
|
|
538
|
+
decoded: true
|
|
539
|
+
};
|
|
540
|
+
if (encoding === "br") return {
|
|
541
|
+
body: brotliDecompressSync(raw.body),
|
|
542
|
+
decoded: true
|
|
543
|
+
};
|
|
544
|
+
} catch {
|
|
545
|
+
return {
|
|
546
|
+
body: raw.body,
|
|
547
|
+
decoded: false
|
|
548
|
+
};
|
|
549
|
+
}
|
|
550
|
+
return {
|
|
551
|
+
body: raw.body,
|
|
552
|
+
decoded: false
|
|
553
|
+
};
|
|
554
|
+
}
|
|
555
|
+
function toWebResponse(raw) {
|
|
556
|
+
if (raw.status < 200 || raw.status > 599) throw new Error(`Unsupported HTTP status in response: ${raw.status}`);
|
|
557
|
+
const { body, decoded } = decodeContentEncoding(raw);
|
|
558
|
+
const headers = new Headers();
|
|
559
|
+
for (const [name, value] of Object.entries(raw.headers)) {
|
|
560
|
+
if (value === void 0) continue;
|
|
561
|
+
if (decoded && (name === "content-encoding" || name === "content-length")) continue;
|
|
562
|
+
if (Array.isArray(value)) for (const one of value) headers.append(name, one);
|
|
563
|
+
else headers.append(name, value);
|
|
564
|
+
}
|
|
565
|
+
return new Response(NULL_BODY_STATUSES.has(raw.status) ? null : body, {
|
|
566
|
+
status: raw.status,
|
|
567
|
+
statusText: raw.statusText.replace(/[^\t\x20-\x7e\x80-\xff]/g, ""),
|
|
568
|
+
headers
|
|
569
|
+
});
|
|
570
|
+
}
|
|
571
|
+
/**
|
|
572
|
+
* GET a URL, honoring the standard proxy environment (issue #647).
|
|
573
|
+
*
|
|
574
|
+
* The global `fetch` (undici) reads no proxy variable, so cdk-local's
|
|
575
|
+
* non-SDK AWS-bound reads — the Lambda layer ZIP download from its
|
|
576
|
+
* presigned `Content.Location`, and the Cognito JWKS / OIDC discovery
|
|
577
|
+
* documents — connected DIRECT even where every SDK call was tunneled. On a
|
|
578
|
+
* machine whose only egress is a forward proxy that is a hang or a
|
|
579
|
+
* self-signed-certificate failure one step after `GetLayerVersion`
|
|
580
|
+
* succeeded.
|
|
581
|
+
*
|
|
582
|
+
* Contract mirrors {@link buildProxyClientConfig}: with no proxy variable
|
|
583
|
+
* set this IS `globalThis.fetch` (zero behavior change), and with one set
|
|
584
|
+
* the request goes through {@link EnvRoutingProxyAgent} — the same
|
|
585
|
+
* `NO_PROXY` decision, evaluated per request against the target host, that
|
|
586
|
+
* the SDK clients get. A target that `NO_PROXY` exempts is ALSO handed back
|
|
587
|
+
* to `globalThis.fetch`, so the hand-rolled path is entered only when it
|
|
588
|
+
* has something to add, and every direct request keeps undici's semantics
|
|
589
|
+
* (its timers included) exactly as before. A fresh agent per proxied
|
|
590
|
+
* request, destroyed the moment that request's body is in hand — see the
|
|
591
|
+
* loop below for why that is a correctness requirement and not only
|
|
592
|
+
* tidiness.
|
|
593
|
+
*
|
|
594
|
+
* `opts.timeoutMs` is a TEST SEAM only — production callers pass one
|
|
595
|
+
* argument and get {@link REQUEST_STALL_TIMEOUT_MS}, which no test can
|
|
596
|
+
* afford to wait out.
|
|
597
|
+
*
|
|
598
|
+
* GET-only by construction: both call sites are GETs, and a method with a
|
|
599
|
+
* request body needs redirect-replay semantics this deliberately does not
|
|
600
|
+
* guess at. A future POST caller extends this (with its tests) rather than
|
|
601
|
+
* falling back to a bare `fetch` —
|
|
602
|
+
* `tests/unit/utils/aws-proxy-fetch-audit.test.ts` refuses the fallback.
|
|
603
|
+
*/
|
|
604
|
+
async function proxyAwareFetch(url, opts = {}) {
|
|
605
|
+
if (!isProxyEnvConfigured()) return globalThis.fetch(url);
|
|
606
|
+
let target = parseHttpUrl(url);
|
|
607
|
+
for (let hop = 0;; hop++) {
|
|
608
|
+
if (isLoopbackHost(target.hostname) || !isSpeakableProxy(getProxyForUrl(target.href))) return globalThis.fetch(target.href);
|
|
609
|
+
const agent = new EnvRoutingProxyAgent();
|
|
610
|
+
let raw;
|
|
611
|
+
try {
|
|
612
|
+
raw = await getThroughAgent(target, agent, opts.timeoutMs);
|
|
613
|
+
} finally {
|
|
614
|
+
agent.destroy();
|
|
615
|
+
}
|
|
616
|
+
const location = raw.headers["location"];
|
|
617
|
+
if (!isRedirectStatus(raw.status) || typeof location !== "string" || location === "") return toWebResponse(raw);
|
|
618
|
+
if (hop >= MAX_FETCH_REDIRECTS) throw new Error(`Too many redirects (more than ${MAX_FETCH_REDIRECTS})`);
|
|
619
|
+
target = parseHttpUrl(new URL(location, target).href);
|
|
620
|
+
}
|
|
621
|
+
}
|
|
332
622
|
|
|
333
623
|
//#endregion
|
|
334
624
|
//#region src/utils/profile-resolver.ts
|
|
@@ -14066,8 +14356,26 @@ const DEFAULT_JWKS_TTL_MS = 3600 * 1e3;
|
|
|
14066
14356
|
* suppressing the per-request fetch storm a 0s TTL would cause.
|
|
14067
14357
|
*/
|
|
14068
14358
|
const FAILURE_JWKS_TTL_MS = 60 * 1e3;
|
|
14359
|
+
/**
|
|
14360
|
+
* Stall bound for the JWKS / discovery reads specifically, well under
|
|
14361
|
+
* `proxyAwareFetch`'s 300 s default.
|
|
14362
|
+
*
|
|
14363
|
+
* Those reads are small documents, and — unlike the layer ZIP, which is up to
|
|
14364
|
+
* 250 MB and wants the long default — one of them sits on a PER-REQUEST path:
|
|
14365
|
+
* `agentcore-serve-auth`'s `buildAgentCoreServeAuthCheck` calls
|
|
14366
|
+
* `verifyJwtViaDiscovery` for every inbound request, and that function holds
|
|
14367
|
+
* no discovery cache. Behind a black-holed proxy each in-flight request would
|
|
14368
|
+
* otherwise hold a socket for 300 s where the pre-#647 direct read gave up in
|
|
14369
|
+
* about undici's 10 s connect timeout.
|
|
14370
|
+
*
|
|
14371
|
+
* Failing FAST is also the right bias here in a way it is not for a download:
|
|
14372
|
+
* an unreachable JWKS lands in the documented pass-through fallback
|
|
14373
|
+
* (`docs/cli-reference.md`), so a long hold buys nothing and costs a stuck
|
|
14374
|
+
* request.
|
|
14375
|
+
*/
|
|
14376
|
+
const JWKS_FETCH_TIMEOUT_MS = 1e4;
|
|
14069
14377
|
function createJwksCache(opts = {}) {
|
|
14070
|
-
const fetchImpl = opts.fetchImpl ?? (
|
|
14378
|
+
const fetchImpl = opts.fetchImpl ?? ((url) => proxyAwareFetch(url, { timeoutMs: JWKS_FETCH_TIMEOUT_MS }));
|
|
14071
14379
|
const now = opts.now ?? (() => Date.now());
|
|
14072
14380
|
const ttlMs = opts.ttlMs ?? DEFAULT_JWKS_TTL_MS;
|
|
14073
14381
|
const failureTtlMs = opts.failureTtlMs ?? FAILURE_JWKS_TTL_MS;
|
|
@@ -14104,7 +14412,7 @@ function createJwksCache(opts = {}) {
|
|
|
14104
14412
|
map.set(jwksUrl, entry);
|
|
14105
14413
|
return entry;
|
|
14106
14414
|
} catch (err) {
|
|
14107
|
-
logger.warn(`JWKS unreachable at ${jwksUrl}: ${err instanceof Error ? err.message : String(err)}. JWT validation will allow all tokens — local dev fallback. Configure network access to the JWKS URL to enable real signature verification.`);
|
|
14415
|
+
logger.warn(`JWKS unreachable at ${jwksUrl}: ${sanitizeServiceExceptionMessage(err instanceof Error ? err.message : String(err))}. JWT validation will allow all tokens — local dev fallback. Configure network access to the JWKS URL to enable real signature verification.`);
|
|
14108
14416
|
const entry = {
|
|
14109
14417
|
byKid: /* @__PURE__ */ new Map(),
|
|
14110
14418
|
expiresAt: now() + failureTtlMs,
|
|
@@ -14241,7 +14549,7 @@ async function verifyJwtViaDiscovery(authorizer, authorizationHeader, jwksCache,
|
|
|
14241
14549
|
identityHash: void 0,
|
|
14242
14550
|
ttlSeconds: 0
|
|
14243
14551
|
};
|
|
14244
|
-
const fetchImpl = opts.fetchImpl ?? (
|
|
14552
|
+
const fetchImpl = opts.fetchImpl ?? ((url) => proxyAwareFetch(url, { timeoutMs: JWKS_FETCH_TIMEOUT_MS }));
|
|
14245
14553
|
let issuer;
|
|
14246
14554
|
let jwksUri;
|
|
14247
14555
|
try {
|
|
@@ -14252,7 +14560,7 @@ async function verifyJwtViaDiscovery(authorizer, authorizationHeader, jwksCache,
|
|
|
14252
14560
|
issuer = doc.issuer;
|
|
14253
14561
|
jwksUri = doc.jwks_uri;
|
|
14254
14562
|
} catch (err) {
|
|
14255
|
-
if (shouldWarn(authorizer.discoveryUrl, opts.warnedAt, now)) getLogger().child("cognito-jwt").warn(`OIDC discovery unreachable at ${authorizer.discoveryUrl}: ${err instanceof Error ? err.message : String(err)}. Token accepted without verification — local dev fallback.`);
|
|
14563
|
+
if (shouldWarn(authorizer.discoveryUrl, opts.warnedAt, now)) getLogger().child("cognito-jwt").warn(`OIDC discovery unreachable at ${authorizer.discoveryUrl}: ${sanitizeServiceExceptionMessage(err instanceof Error ? err.message : String(err))}. Token accepted without verification — local dev fallback.`);
|
|
14256
14564
|
const identityHash = buildIdentityHash([token]);
|
|
14257
14565
|
const parsed = parseJwt(token);
|
|
14258
14566
|
if (parsed) return shapeAllowResult(parsed, identityHash, now);
|
|
@@ -16645,7 +16953,7 @@ async function materializeLayerFromArn(layer, options = {}) {
|
|
|
16645
16953
|
try {
|
|
16646
16954
|
zipBytes = await downloadPresignedZip(presignedUrl, options);
|
|
16647
16955
|
} catch (err) {
|
|
16648
|
-
throw new LayerMaterializationError(`Layer ${layer.arn}: failed to download layer ZIP from the presigned URL: ${errMsg(err)}.`);
|
|
16956
|
+
throw new LayerMaterializationError(`Layer ${layer.arn}: failed to download layer ZIP from the presigned URL: ${sanitizeServiceExceptionMessage(errMsg(err))}.`);
|
|
16649
16957
|
}
|
|
16650
16958
|
const dir = await mkdtemp(join(tmpdir(), `${getEmbedConfig().resourceNamePrefix}-arn-layer-${layer.name}-${layer.version}-`));
|
|
16651
16959
|
try {
|
|
@@ -16727,7 +17035,7 @@ async function buildAssumeRoleCommand(roleArn) {
|
|
|
16727
17035
|
}
|
|
16728
17036
|
async function downloadPresignedZip(presignedUrl, options) {
|
|
16729
17037
|
if (options.fetchZip) return options.fetchZip(presignedUrl);
|
|
16730
|
-
const response = await
|
|
17038
|
+
const response = await proxyAwareFetch(presignedUrl);
|
|
16731
17039
|
if (!response.ok) throw new Error(`HTTP ${response.status} ${flattenToOneLine(response.statusText)} from layer Content.Location URL`);
|
|
16732
17040
|
const buf = await response.arrayBuffer();
|
|
16733
17041
|
return new Uint8Array(buf);
|
|
@@ -16819,9 +17127,16 @@ async function inflateRaw(data) {
|
|
|
16819
17127
|
* The download `catch` DOES see wire-derived text — `downloadPresignedZip`
|
|
16820
17128
|
* raises `HTTP <status> <statusText> ...`, and the reason phrase is whatever
|
|
16821
17129
|
* the presigned host sent. Nothing there needs WITHHOLDING (no credential
|
|
16822
|
-
* chain, no secret), but it does need FLATTENING
|
|
16823
|
-
*
|
|
16824
|
-
*
|
|
17130
|
+
* chain, no secret), but it does need FLATTENING.
|
|
17131
|
+
*
|
|
17132
|
+
* CORRECTED AGAIN in issue #647: that flattening used to be applied at the
|
|
17133
|
+
* `HTTP <status>` throw alone, which was sufficient only while `fetch` was the
|
|
17134
|
+
* transport and its every failure was the fixed string `fetch failed`. The
|
|
17135
|
+
* download now goes through `proxyAwareFetch`, so the same `catch` also sees
|
|
17136
|
+
* `node:net` / OpenSSL / proxy-agent messages of arbitrary shape and length.
|
|
17137
|
+
* The download SITE therefore applies `sanitizeServiceExceptionMessage` to
|
|
17138
|
+
* whatever `errMsg` returns; `errMsg` itself stays bare because its other
|
|
17139
|
+
* caller is the unzip `catch`, whose input is a local `fflate` error.
|
|
16825
17140
|
*/
|
|
16826
17141
|
function errMsg(err) {
|
|
16827
17142
|
return err instanceof Error ? err.message : String(err);
|
|
@@ -37739,7 +38054,8 @@ function runChild(spawnFn, nodeBin, argv, cwd, invocationId, target, bus, clock)
|
|
|
37739
38054
|
cwd,
|
|
37740
38055
|
env: {
|
|
37741
38056
|
...process.env,
|
|
37742
|
-
CDKL_LOG_LEVEL: "warn"
|
|
38057
|
+
CDKL_LOG_LEVEL: "warn",
|
|
38058
|
+
CDKL_LOG_STREAM: "stderr"
|
|
37743
38059
|
}
|
|
37744
38060
|
});
|
|
37745
38061
|
} catch (err) {
|
|
@@ -39826,4 +40142,4 @@ function addStudioSpecificOptions(cmd) {
|
|
|
39826
40142
|
|
|
39827
40143
|
//#endregion
|
|
39828
40144
|
export { applyEdgeResponseResult as $, buildJwksUrlFromIssuer as $n, resolveCfnStackName as $r, buildCloudMapIndex as $t, startAgentCoreHttpServer as A, describeCredentialLoadFailure as Ai, classifySourceChange as An, ConnectionRegistry as Ar, addRunTaskSpecificOptions as At, idFromArn as B, buildStageMap as Bn, resolveRuntimeFileExtension as Br, resolveEcsAssumeRoleOption as Bt, addListSpecificOptions as C, resolveAgentCoreTarget as Ci, waitForAgentCorePing as Cn, tryParseStatus as Cr, parseLbPortOverrides as Ct, createLocalStartAgentCoreCommand as D, tryResolveImageFnJoin as Di, computeCodeImageTag as Dn, probeHostGatewaySupport as Dr, addStartServiceSpecificOptions as Dt, addStartAgentCoreSpecificOptions as E, substituteImagePlaceholders as Ei, buildAgentCoreCodeImage as En, HOST_GATEWAY_MIN_VERSION as Er, resolveAlbFrontDoor as Et, createLocalStartCloudFrontCommand as F, createWatchPredicates as Fn, buildDisconnectEvent as Fr, addImageOverrideOptions as Ft, classifyS3Error as G, filterRoutesByApiIdentifiers as Gn, substituteEnvVarsFromState as Gr, enforceImageOverrideOrphans as Gt, createDeployedKvsDataSource as H, resolveEnvVars$1 as Hn, EcsTaskResolutionError as Hr, runEcsServiceEmulator as Ht, normalizeKvsFileKeys as I, resolveApiTargetSubset as In, buildMessageEvent as Ir, buildEcsImageResolutionContext$1 as It, startCloudFrontServer as J, startApiServer as Jn, createLocalStateProvider as Jr, resolveImageOverrides as Jt, createS3OriginReader as K, groupRoutesByServer as Kn, substituteEnvVarsFromStateAsync as Kr, mergeForService as Kt, parseKvsFileOverrides as L, createAuthorizerCache as Ln, architectureToPlatform as Lr, ecsClusterOption as Lt, startAgentCoreWsBridge as M, resolveProfileCredentials as Mi, createLocalInvokeCommand as Mn, handleConnectionsRequest as Mr, MAX_TASKS_SUBNET_RANGE_CAP as Mt, LocalStartCloudFrontError as N, buildProxyClientConfig as Ni, addStartApiSpecificOptions as Nn, parseConnectionsPath as Nr, addCommonEcsServiceOptions as Nt, buildAgentCoreServeAuthCheck as O, LocalInvokeBuildError as Oi, renderCodeDockerfile as On, resolveHostGatewayExtraHosts as Or, createLocalStartServiceCommand as Ot, addStartCloudFrontSpecificOptions as P, isProxyEnvConfigured as Pi, createLocalStartApiCommand as Pn, buildConnectEvent as Pr, addEcsAssumeRoleOptions as Pt, applyEdgeRequestResult as Q, buildCognitoJwksUrl as Qn, resolveCfnRegion as Qr, listPinnedTargets as Qt, parseOriginOverrides as R, createFileWatcher as Rn, buildContainerImage as Rr, parseMaxTasks as Rt, StudioEventBus as S, pickAgentCoreCandidateStack as Si, waitForAgentCoreHttpReady as Sn, selectIntegrationResponse as Sr, createLocalStartAlbCommand as St, formatTargetListing as T, formatStateRemedy as Ti, SUPPORTED_CODE_RUNTIMES as Tn, HOST_DOCKER_INTERNAL_GATEWAY as Tr, isApplicationLoadBalancer as Tt, resolveDeployedKvsArnByName as U, availableApiIdentifiers as Un, substituteAgainstState as Ur, ImageOverrideError as Ut, resolveKvsModulesForDistribution as V, materializeLayerFromArn as Vn, resolveRuntimeImage as Vr, resolveSharedSidecarCredentials as Vt, resolveDeployedOriginBucket as W, filterRoutesByApiIdentifier as Wn, substituteAgainstStateAsync as Wr, buildImageOverrideTag as Wt, serveFromStaticOrigin as X, resolveServiceIntegrationParameters as Xn, rejectExplicitCfnStackWithMultipleStacks as Xr, describePinnedImageUri as Xt, resolveErrorResponseCandidates as Y, resolveSelectionExpression as Yn, isCfnFlagPresent as Yr, runImageOverrideBuilds as Yt, serveLambdaUrlOrigin as Z, defaultCredentialsLoader as Zn, resolveCfnFallbackRegion as Zr, isLocalCdkAssetImage as Zt, filterStudioTargetGroups as _, AGENTCORE_AGUI_PROTOCOL as _i, parseSseForJsonRpc as _n, applyAuthorizerOverlay as _r, createCloudFrontModule as _t, createLocalStudioCommand as a, countTargets as ai, attachContainerLogStreamer as an, computeRequestIdentityHash as ar, describeS3OriginDomain as at, renderStudioHtml as b, AGENTCORE_RUNTIME_TYPE as bi, AGENTCORE_SESSION_ID_HEADER as bn, evaluateResponseParameters as br, addAlbSpecificOptions as bt, startStudioProxy as c, discoverWebSocketApis as ci, bridgeAgentCoreWs as cn, invokeTokenAuthorizer as cr, pickFunctionUrlLogicalIdFromOrigin as ct, createStudioDispatcher as d, parseSelectionExpressionPath as di, A2A_PATH as dn, buildCorsConfigByApiId as dr, pickTargetFunctionLogicalId as dt, CfnLocalStateProvider as ei, CloudMapRegistry as en, createJwksCache as er, buildEdgeRequestEvent as et, filterStudioCustomResources as f, webSocketApiMatchesIdentifier as fi, a2aInvokeOnce as fn, buildCorsConfigFromCloudFrontChain as fr, resolveCloudFrontDistribution as ft, annotatePinnedEcsTargets as g, AGENTCORE_A2A_PROTOCOL as gi, mcpInvokeOnce as gn, translateLambdaResponse as gr, stripCloudFrontImport as gt, annotateEcsTaskPinnedTargets as h, resolveLambdaArnIntrinsic as hi, MCP_PROTOCOL_VERSION as hn, matchRoute as hr, runViewerResponse as ht, coerceStopRequest as i, resolveSingleTarget as ii, getContainerNetworkIp as in, buildMethodArn as ir, CLOUDFRONT_DISTRIBUTION_TYPE as it, attachAgentCoreWsBridge as j, buildStsClientConfig as ji, addInvokeSpecificOptions as jn, buildMgmtEndpointEnvUrl as jr, createLocalRunTaskCommand as jt, selectServeInboundAuth as k, describeAwsFailureForWarn as ki, toCmdArgv as kn, bufferToBody as kr, serviceStrategy as kt, relayServeRequest as l, discoverWebSocketApisOrThrow as li, invokeAgentCoreWs as ln, attachAuthorizers as lr, pickKvsLogicalIdFromArn as lt, annotateAlbPinnedBackingServices as m, pickRefLogicalId as mi, MCP_PATH as mn, matchPreflight as mr, runViewerRequest as mt, coerceRunRequest as n, resolveSsmParameters as ni, SOFT_RELOAD_COMPLETION_LOG_SUFFIX as nn, verifyJwtAuthorizer as nr, edgeHeadersToHttp as nt, resolveServeBaseUrl as o, listTargets as oi, addInvokeAgentCoreSpecificOptions as on, evaluateCachedLambdaPolicy as or, extractKvsAssociations as ot, isCustomResourceLambdaTarget as p, discoverRoutes as pi, MCP_CONTAINER_PORT as pn, isFunctionUrlOacFronted as pr, compileCloudFrontFunction as pt, matchBehavior as q, readMtlsMaterialsFromDisk as qn, LocalStateSourceError as qr, parseImageOverrideFlags as qt, coerceServeRequest as r, resolveWatchConfig as ri, setShadowReadyTimeoutMs as rn, verifyJwtViaDiscovery as rr, httpHeadersToEdge as rt, createStudioServeManager as s, availableWebSocketApiIdentifiers as si, createLocalInvokeAgentCoreCommand as sn, invokeRequestAuthorizer as sr, isCloudFrontDistribution as st, addStudioSpecificOptions as t, collectSsmParameterRefs as ti, DEFAULT_SHADOW_READY_TIMEOUT_MS as tn, verifyCognitoJwt as tr, buildEdgeResponseEvent as tt, reinvoke as u, filterWebSocketApisByIdentifiers as ui, A2A_CONTAINER_PORT as un, applyCorsResponseHeaders as ur, pickLambdaEdgeFunctionLogicalId as ut, startStudioServer as v, AGENTCORE_HTTP_PROTOCOL as vi, AGENTCORE_SIGV4_SERVICE as vn, buildHttpApiV2Event as vr, createLocalFileKvsDataSource as vt, createLocalListCommand as w, derivePseudoParametersFromRegion as wi, downloadAndExtractS3Bundle as wn, VtlEvaluationError as wr, resolveAlbTarget as wt, createStudioStore as x, AgentCoreResolutionError as xi, invokeAgentCore as xn, pickResponseTemplate as xr, albStrategy as xt, toStudioTargetGroups as y, AGENTCORE_MCP_PROTOCOL as yi, signAgentCoreInvocation as yn, buildRestV1Event as yr, createUnboundCloudFrontModule as yt, resolveCloudFrontTarget as z, attachStageContext as zn, resolveRuntimeCodeMountPath as zr, parseRestartPolicy as zt };
|
|
39829
|
-
//# sourceMappingURL=local-studio-
|
|
40145
|
+
//# sourceMappingURL=local-studio-BVxRUfQV.js.map
|