@go-to-k/cdkd 0.284.35 → 0.284.37
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{asg-provider-bJ8nim2C.js → asg-provider-BbWubpjP.js} +2 -2
- package/dist/{asg-provider-bJ8nim2C.js.map → asg-provider-BbWubpjP.js.map} +1 -1
- package/dist/cli.js +182 -106
- package/dist/cli.js.map +1 -1
- package/dist/{deploy-engine-Wei5Yw-_.js → deploy-engine-C62UGXid.js} +296 -222
- package/dist/deploy-engine-C62UGXid.js.map +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/package.json +1 -1
- package/dist/deploy-engine-Wei5Yw-_.js.map +0 -1
|
@@ -875,6 +875,42 @@ var CrossAccountSecretRefusalError = class CrossAccountSecretRefusalError extend
|
|
|
875
875
|
}
|
|
876
876
|
};
|
|
877
877
|
/**
|
|
878
|
+
* A `{{resolve:...}}` reference whose REGION cannot be established (issue
|
|
879
|
+
* [#2134](https://github.com/go-to-k/cdkd/issues/2134)): it names no region,
|
|
880
|
+
* and the stack it sits in is on record as reading across a region boundary.
|
|
881
|
+
*
|
|
882
|
+
* A SUBCLASS rather than a bare code, because the consumers that must not
|
|
883
|
+
* swallow it identify it by CLASS. `cdkd scrub` wraps its resolution passes in
|
|
884
|
+
* best-effort `catch { logger.debug }` blocks so that one unresolvable resource
|
|
885
|
+
* does not abandon the rest of the scrub -- and a refusal swallowed there is
|
|
886
|
+
* the exact outcome the refusal exists to prevent: no needle is recorded for
|
|
887
|
+
* the reference, the plaintext survives in `state.json`, and the command
|
|
888
|
+
* reports `No plaintext secrets found` and exits 0. The pre-pass refusals in
|
|
889
|
+
* `scrub.ts` are placed OUTSIDE those catches for the same reason; this one
|
|
890
|
+
* fires from inside `resolveDynamicReferences`, so it cannot be placed --
|
|
891
|
+
* it has to be re-raised.
|
|
892
|
+
*
|
|
893
|
+
* USER-FIXABLE, so it deliberately does NOT extend
|
|
894
|
+
* {@link CrossAccountSecretRefusalError}, whose subclass identity marks the one
|
|
895
|
+
* PERMANENT refusal `scrub.ts`'s `isByDesignRefusal` reports as unclearable.
|
|
896
|
+
* Spelling the reference as a full ARN names its region and clears this.
|
|
897
|
+
*
|
|
898
|
+
* The CODE names the domain (`DYNAMIC_REFERENCE_REGION_AMBIGUOUS`) rather than
|
|
899
|
+
* carrying the base class's `INTRINSIC_RESOLUTION_REFUSAL_` prefix its one
|
|
900
|
+
* sibling uses. Deliberate: no consumer keys on that prefix, so it is not a
|
|
901
|
+
* contract, and the prefixed spelling would read
|
|
902
|
+
* `INTRINSIC_RESOLUTION_REFUSAL_DYNAMIC_REFERENCE_REGION_AMBIGUOUS`. Consumers
|
|
903
|
+
* that must act on this identify it by CLASS, which is what the subclass is
|
|
904
|
+
* for.
|
|
905
|
+
*/
|
|
906
|
+
var DynamicReferenceRegionAmbiguousError = class DynamicReferenceRegionAmbiguousError extends IntrinsicResolutionRefusalError {
|
|
907
|
+
constructor(message, cause) {
|
|
908
|
+
super(message, cause, "DYNAMIC_REFERENCE_REGION_AMBIGUOUS");
|
|
909
|
+
this.name = "DynamicReferenceRegionAmbiguousError";
|
|
910
|
+
Object.setPrototypeOf(this, DynamicReferenceRegionAmbiguousError.prototype);
|
|
911
|
+
}
|
|
912
|
+
};
|
|
913
|
+
/**
|
|
878
914
|
* Dependency resolution errors
|
|
879
915
|
*/
|
|
880
916
|
var DependencyError = class DependencyError extends CdkdError {
|
|
@@ -10325,6 +10361,226 @@ function s3BucketWebsiteUrl(bucketName, region) {
|
|
|
10325
10361
|
return `http://${bucketName}.s3-website${S3_WEBSITE_ENDPOINT_LEGACY_DASH_REGIONS.has(folded) ? "-" : "."}${folded}.${urlSuffix}`;
|
|
10326
10362
|
}
|
|
10327
10363
|
|
|
10364
|
+
//#endregion
|
|
10365
|
+
//#region src/deployment/secret-region-classification.ts
|
|
10366
|
+
/**
|
|
10367
|
+
* The `{{resolve:<service>:...}}` families whose value can be a SECRET, and
|
|
10368
|
+
* therefore the only ones the region question below is asked about: every
|
|
10369
|
+
* `secretsmanager` reference by spelling, and every `ssm` one, which is secret
|
|
10370
|
+
* exactly when its parameter is a `SecureString` (issue #1901).
|
|
10371
|
+
*
|
|
10372
|
+
* Every OTHER service is `local` because cdkd cannot resolve it at all, NOT
|
|
10373
|
+
* because it is public. `ssm-secure` is the live example and is emphatically
|
|
10374
|
+
* not public: `resolveDynamicReferences` has no arm for it, so the literal
|
|
10375
|
+
* token is passed through to AWS and CloudFormation resolves it SERVER-side.
|
|
10376
|
+
* cdkd never holds its value, so there is no region for cdkd to get wrong —
|
|
10377
|
+
* which is the only reason it can be waved through here.
|
|
10378
|
+
*/
|
|
10379
|
+
const REPLAY_SECRET_SERVICES = /* @__PURE__ */ new Set(["secretsmanager", "ssm"]);
|
|
10380
|
+
/**
|
|
10381
|
+
* Split a `{{resolve:secretsmanager:...}}` inner body into its SECRET_ID.
|
|
10382
|
+
*
|
|
10383
|
+
* Mirrors `IntrinsicFunctionResolver.resolveSecretsManagerReference`'s own
|
|
10384
|
+
* split — including the END-ANCHORED whole-secret form — because a secret ID
|
|
10385
|
+
* may legitimately contain colons (an ARN always does), so `split(':')[1]` is
|
|
10386
|
+
* wrong for exactly the shape this file cares about most.
|
|
10387
|
+
*/
|
|
10388
|
+
function secretsManagerSecretId(inner) {
|
|
10389
|
+
const afterService = inner.substring(15);
|
|
10390
|
+
let stringIdx = afterService.indexOf(":SecretString:");
|
|
10391
|
+
let binaryIdx = afterService.indexOf(":SecretBinary:");
|
|
10392
|
+
if (stringIdx < 0 && afterService.endsWith(":SecretString")) stringIdx = afterService.length - 13;
|
|
10393
|
+
if (binaryIdx < 0 && afterService.endsWith(":SecretBinary")) binaryIdx = afterService.length - 13;
|
|
10394
|
+
const delimiterIdx = stringIdx >= 0 && binaryIdx >= 0 ? Math.min(stringIdx, binaryIdx) : stringIdx >= 0 ? stringIdx : binaryIdx;
|
|
10395
|
+
return delimiterIdx >= 0 ? afterService.substring(0, delimiterIdx) : afterService;
|
|
10396
|
+
}
|
|
10397
|
+
/**
|
|
10398
|
+
* The parameter name an `{{resolve:ssm:...}}` reference asks for — byte-for-byte
|
|
10399
|
+
* what `IntrinsicFunctionResolver.resolveSSMReference` passes as `GetParameter`'s
|
|
10400
|
+
* `Name`, which is `parts.slice(1).join(':')` on the colon-split inner body.
|
|
10401
|
+
*
|
|
10402
|
+
* The whole remainder, deliberately, with NOTHING stripped:
|
|
10403
|
+
*
|
|
10404
|
+
* - An SSM dynamic reference CAN name a full ARN. The resolver joins the tail
|
|
10405
|
+
* back together, so `{{resolve:ssm:arn:aws:ssm:us-west-2:111122223333:parameter/db/pw}}`
|
|
10406
|
+
* reaches AWS as that ARN. A `split(':')[1]` here would yield the literal
|
|
10407
|
+
* `'arn'` — a parameter that does not exist — and then report the reference
|
|
10408
|
+
* as region-LESS and refuse it, which is the guess-in-the-other-direction the
|
|
10409
|
+
* `named-region` arm exists to prevent.
|
|
10410
|
+
* - A trailing `:<version>` / `:<label>` is part of the name AS SSM PARSES IT
|
|
10411
|
+
* (`GetParameter` accepts `name:3` / `name:prod`), so stripping it would name
|
|
10412
|
+
* a different thing in the refusal message than the one that would be read.
|
|
10413
|
+
*/
|
|
10414
|
+
function ssmParameterName(inner) {
|
|
10415
|
+
return inner.substring(4);
|
|
10416
|
+
}
|
|
10417
|
+
/**
|
|
10418
|
+
* The region an ARN names, or `undefined` for anything that is not an ARN with
|
|
10419
|
+
* a populated region field (`arn:<partition>:<service>:<region>:...`).
|
|
10420
|
+
*/
|
|
10421
|
+
function arnRegion(secretId) {
|
|
10422
|
+
if (!secretId.startsWith("arn:")) return void 0;
|
|
10423
|
+
const region = secretId.split(":")[3];
|
|
10424
|
+
return region ? region : void 0;
|
|
10425
|
+
}
|
|
10426
|
+
/**
|
|
10427
|
+
* The producer regions a stack's persisted cross-stack reads name, for
|
|
10428
|
+
* the replay's `RollbackExecutorContext.importedProducerRegions` (issue #2057).
|
|
10429
|
+
*
|
|
10430
|
+
* Both record kinds count, and for the same reason: each one is a value this
|
|
10431
|
+
* stack read out of ANOTHER region's state, so each one is a way a
|
|
10432
|
+
* foreign-region `{{resolve:...}}` expression can have reached this stack's own
|
|
10433
|
+
* record. `imports` is the strong `Fn::ImportValue` edge; `outputReads` is the
|
|
10434
|
+
* weak `Fn::GetStackOutput` one (schema v8), which is the EASIER of the two to
|
|
10435
|
+
* point across a region boundary because the reference carries its own
|
|
10436
|
+
* `Region` argument.
|
|
10437
|
+
*
|
|
10438
|
+
* Deduplicated case-insensitively, keeping each region's first-recorded
|
|
10439
|
+
* spelling so the refusal message echoes what the user will see in
|
|
10440
|
+
* `state.json`. The consumer's own region is deliberately NOT filtered here —
|
|
10441
|
+
* {@link classifyReplaySecretRegion} does that, because it is the one that
|
|
10442
|
+
* knows which region is asking.
|
|
10443
|
+
*
|
|
10444
|
+
* Exported so the two `RollbackExecutorContext` construction sites derive the
|
|
10445
|
+
* list identically — `cdkd rollback` from the state it loaded, and
|
|
10446
|
+
* `DeployEngine.rollbackExecutorContext` from `crossStackReadsForPartialSave`,
|
|
10447
|
+
* which unions that snapshot with the reads the failing deploy itself made.
|
|
10448
|
+
*/
|
|
10449
|
+
function producerRegionsFromState(state) {
|
|
10450
|
+
const seen = /* @__PURE__ */ new Set();
|
|
10451
|
+
const regions = [];
|
|
10452
|
+
for (const entry of [...state.imports ?? [], ...state.outputReads ?? []]) {
|
|
10453
|
+
const canonical = canonicalizeRegion(entry.sourceRegion);
|
|
10454
|
+
if (!canonical || seen.has(canonical)) continue;
|
|
10455
|
+
seen.add(canonical);
|
|
10456
|
+
regions.push(entry.sourceRegion);
|
|
10457
|
+
}
|
|
10458
|
+
return regions;
|
|
10459
|
+
}
|
|
10460
|
+
/**
|
|
10461
|
+
* Decide which region must answer for a single `{{resolve:...}}` expression a
|
|
10462
|
+
* rollback replay is about to re-resolve — issue
|
|
10463
|
+
* [#2057](https://github.com/go-to-k/cdkd/issues/2057).
|
|
10464
|
+
*
|
|
10465
|
+
* WHY A REPLAY CAN BE HOLDING A FOREIGN REGION'S EXPRESSION AT ALL. Since
|
|
10466
|
+
* issue #1934 a cross-stack consumer re-resolves a redacted producer value in
|
|
10467
|
+
* the PRODUCER's region (`reresolveCrossStackValue` /
|
|
10468
|
+
* `resolverForProducerRegion`) — correct, because a Secrets Manager secret or
|
|
10469
|
+
* an SSM `SecureString` of the same NAME in two regions is two independent
|
|
10470
|
+
* values. The plaintext is then recorded into the CONSUMER's
|
|
10471
|
+
* `recordedSecretValues`, so the consumer's `state.json` (and from there the
|
|
10472
|
+
* rollback journal) persists the PRODUCER's spelling of the expression. That is
|
|
10473
|
+
* the right thing to persist, and it is region-less: the reader cannot tell
|
|
10474
|
+
* from the string which region produced it.
|
|
10475
|
+
*
|
|
10476
|
+
* The replay rebuilds its resolver from the CONSUMER's region alone, so
|
|
10477
|
+
* re-resolving that expression locally answers from a same-named secret in the
|
|
10478
|
+
* wrong region and writes it to a LIVE resource. Silent, and on the recovery
|
|
10479
|
+
* path. The rule applied here is the family's, from issue #1957: A NAMED REGION
|
|
10480
|
+
* BINDS; NEVER SUBSTITUTE A GUESS. The three verdicts are that one sentence:
|
|
10481
|
+
*
|
|
10482
|
+
* - **`named-region`** — the expression's SECRET_ID is an ARN, which names its
|
|
10483
|
+
* own region. The region is ESTABLISHED, so it binds: the caller resolves
|
|
10484
|
+
* through a resolver pinned to it (each command's own `*Resolvers.forRegion`) rather
|
|
10485
|
+
* than refusing. Refusing here would be the guess in the other direction.
|
|
10486
|
+
*
|
|
10487
|
+
* cdkd would otherwise get this wrong, which is why the arm exists at all:
|
|
10488
|
+
* `resolveSecretsManagerReference` builds its client from
|
|
10489
|
+
* `this.explicitRegion` and passes the ARN through as an opaque `SecretId`,
|
|
10490
|
+
* and `@aws-sdk/client-secrets-manager`'s endpoint ruleset has NO
|
|
10491
|
+
* ARN-derived endpoint rule (unlike, say, S3 access points), so a
|
|
10492
|
+
* foreign-region ARN is sent to the stack's own regional endpoint. What the
|
|
10493
|
+
* SERVICE then does with it is not something this repo can settle offline —
|
|
10494
|
+
* see the fixture note in
|
|
10495
|
+
* `tests/integration/rollback-cross-region-secret/README.md`. Pinning the
|
|
10496
|
+
* client to the ARN's region is correct either way: if Secrets Manager would
|
|
10497
|
+
* have refused the foreign ARN, this turns a hard failure into a correct
|
|
10498
|
+
* resolution; if it would have honoured it, this reaches the same value by
|
|
10499
|
+
* the documented route. Neither outcome is a regression.
|
|
10500
|
+
*
|
|
10501
|
+
* - **`ambiguous`** — the expression names no region (the plain name form) AND
|
|
10502
|
+
* this stack has a foreign producer region on record
|
|
10503
|
+
* (the replay's `RollbackExecutorContext.importedProducerRegions`). Nothing on hand
|
|
10504
|
+
* can establish the origin, so the replay refuses instead of guessing.
|
|
10505
|
+
*
|
|
10506
|
+
* KNOWN OVER-REFUSAL, accepted deliberately, and WIDER THAN THE SSM CASE
|
|
10507
|
+
* ALONE — state both, because the second one is the common shape:
|
|
10508
|
+
*
|
|
10509
|
+
* (a) Any NAME-FORM `secretsmanager` reference in a stack that has ANY
|
|
10510
|
+
* foreign producer region on record is refused, even when that secret is
|
|
10511
|
+
* the stack's own purely-local one and has nothing to do with the
|
|
10512
|
+
* cross-region read. The evidence is per-STACK, not per-reference, so one
|
|
10513
|
+
* cross-region export plus one ordinary
|
|
10514
|
+
* `{{resolve:secretsmanager:mysecret:SecretString:pw}}` is enough — and CDK's
|
|
10515
|
+
* `secretValueFromJson` emits exactly that name form, so this is the shape
|
|
10516
|
+
* most people will meet. It also persists: with the union the producer
|
|
10517
|
+
* region stays on record until the next SUCCESSFUL deploy. Per-reference
|
|
10518
|
+
* evidence is what would narrow it, and that needs the region recorded
|
|
10519
|
+
* ALONGSIDE the expression — the persisted-shape change issue #2057
|
|
10520
|
+
* deliberately deferred (its options 1 and 2). Until then the refusal is
|
|
10521
|
+
* loud, names the ARN spelling as the remedy, and is the fail-closed side
|
|
10522
|
+
* of a trade whose other side is a silent wrong-secret write.
|
|
10523
|
+
*
|
|
10524
|
+
* (b) An `ssm` reference is secret only when its parameter is a
|
|
10525
|
+
* `SecureString`, and this arm cannot tell. So a `{{resolve:ssm:/app/env}}`
|
|
10526
|
+
* naming a PUBLIC `String` that reached a persisted bag (issue #2036's
|
|
10527
|
+
* acknowledged over-redaction) is refused too. Narrowing it by
|
|
10528
|
+
* `isRecordedSecretExpression` was considered and REJECTED, and not because
|
|
10529
|
+
* the store is unreachable — it is imported by this very file. It is
|
|
10530
|
+
* unusable: `recordedSecretExpressions` is populated BY resolution, and in
|
|
10531
|
+
* the standalone `cdkd rollback` process nothing has resolved anything when
|
|
10532
|
+
* the first op is classified, so the store is empty and every `ssm` verdict
|
|
10533
|
+
* would come back "not secret" — turning the protection off for exactly the
|
|
10534
|
+
* SecureString case it exists for. Worse, once one op DID resolve a
|
|
10535
|
+
* reference the store would be warm for the next, so the verdict would
|
|
10536
|
+
* depend on OP ORDER. A resolve-the-type-first probe is unsound for the
|
|
10537
|
+
* same reason the whole issue exists: the TYPE is region-dependent (#1957),
|
|
10538
|
+
* so probing locally can report `String` for a name that is `SecureString`
|
|
10539
|
+
* in the producer's region and wave through the very write this refuses.
|
|
10540
|
+
* The residual is therefore a loud, actionable error on a narrow
|
|
10541
|
+
* intersection (an over-redacted public ssm reference AND a cross-region
|
|
10542
|
+
* read on record), which is the fail-closed side of the trade.
|
|
10543
|
+
*
|
|
10544
|
+
* - **`local`** — everything else, which is the overwhelmingly common case:
|
|
10545
|
+
* every non-secret service, every same-region ARN (the ordinary CDK
|
|
10546
|
+
* `secretValueFromJson` shape), and every name-form expression in a stack
|
|
10547
|
+
* with no foreign producer region recorded. Resolved exactly as before this
|
|
10548
|
+
* change.
|
|
10549
|
+
*
|
|
10550
|
+
* A same-region ARN answers `local` even when a foreign producer region IS on
|
|
10551
|
+
* record: the expression settles the question itself, so the weaker evidence
|
|
10552
|
+
* never gets consulted.
|
|
10553
|
+
*/
|
|
10554
|
+
function classifyReplaySecretRegion(expression, consumerRegion, importedProducerRegions) {
|
|
10555
|
+
const inner = expression.startsWith("{{resolve:") ? expression.slice(10, -2) : void 0;
|
|
10556
|
+
if (inner === void 0) return { kind: "local" };
|
|
10557
|
+
const service = inner.split(":")[0];
|
|
10558
|
+
if (service === void 0 || !REPLAY_SECRET_SERVICES.has(service)) return { kind: "local" };
|
|
10559
|
+
const secretName = service === "secretsmanager" ? secretsManagerSecretId(inner) : ssmParameterName(inner);
|
|
10560
|
+
if (!secretName) return { kind: "local" };
|
|
10561
|
+
const named = arnRegion(secretName);
|
|
10562
|
+
if (named !== void 0) return canonicalizeRegion(named) === canonicalizeRegion(consumerRegion) ? { kind: "local" } : {
|
|
10563
|
+
kind: "named-region",
|
|
10564
|
+
secretName,
|
|
10565
|
+
region: named
|
|
10566
|
+
};
|
|
10567
|
+
const seen = /* @__PURE__ */ new Set();
|
|
10568
|
+
const foreignProducerRegions = [];
|
|
10569
|
+
for (const candidate of importedProducerRegions ?? []) {
|
|
10570
|
+
const canonical = canonicalizeRegion(candidate);
|
|
10571
|
+
if (!canonical || canonical === canonicalizeRegion(consumerRegion)) continue;
|
|
10572
|
+
if (seen.has(canonical)) continue;
|
|
10573
|
+
seen.add(canonical);
|
|
10574
|
+
foreignProducerRegions.push(candidate);
|
|
10575
|
+
}
|
|
10576
|
+
if (foreignProducerRegions.length === 0) return { kind: "local" };
|
|
10577
|
+
return {
|
|
10578
|
+
kind: "ambiguous",
|
|
10579
|
+
secretName,
|
|
10580
|
+
foreignProducerRegions
|
|
10581
|
+
};
|
|
10582
|
+
}
|
|
10583
|
+
|
|
10328
10584
|
//#endregion
|
|
10329
10585
|
//#region src/deployment/secret-redaction.ts
|
|
10330
10586
|
/** Fixed marker substituted for a secret value in log / error output. */
|
|
@@ -13566,6 +13822,33 @@ function buildUnknownIntrinsicError(key) {
|
|
|
13566
13822
|
return /* @__PURE__ */ new Error(`Unsupported CloudFormation intrinsic function "${key}": cdkd does not support resolving it yet. Deploying this template would produce a broken value. Please request support by opening an issue: ${issueUrl}`);
|
|
13567
13823
|
}
|
|
13568
13824
|
/**
|
|
13825
|
+
* The same context with the `producerRegions` EVIDENCE removed (issue #2134
|
|
13826
|
+
* review rounds 1 and 2).
|
|
13827
|
+
*
|
|
13828
|
+
* That field means "the CONSUMER stack reads from these regions", and it is
|
|
13829
|
+
* only meaningful where the origin of a reference is genuinely UNKNOWN. Hand it
|
|
13830
|
+
* to a resolution whose origin is already established and it re-judges a
|
|
13831
|
+
* reference cdkd has just proven, verdicting `ambiguous`.
|
|
13832
|
+
*
|
|
13833
|
+
* ROUND 1 stripped it by RESOLVER IDENTITY -- "is this a different instance?"
|
|
13834
|
+
* -- and round 2 measured that that is the wrong question. When the producer
|
|
13835
|
+
* lives in the CONSUMER's own region `resolverForProducerRegion` returns `this`,
|
|
13836
|
+
* so the identity test passed the evidence straight through and a name-form
|
|
13837
|
+
* reference read out of that producer was refused. The LOCAL producer failed
|
|
13838
|
+
* while the CROSS-REGION one succeeded, which is backwards, and after the
|
|
13839
|
+
* round-1 re-raise it aborted the whole stack's scrub rather than logging a
|
|
13840
|
+
* debug line.
|
|
13841
|
+
*
|
|
13842
|
+
* The right question is whether the ORIGIN IS KNOWN, so each caller answers it
|
|
13843
|
+
* for itself and this helper only performs the strip. Returned BY IDENTITY when
|
|
13844
|
+
* there is no evidence to remove, so the ordinary path allocates nothing.
|
|
13845
|
+
*/
|
|
13846
|
+
function withoutProducerRegions(context) {
|
|
13847
|
+
if (context?.producerRegions === void 0) return context;
|
|
13848
|
+
const { producerRegions: _stripped, ...rest } = context;
|
|
13849
|
+
return rest;
|
|
13850
|
+
}
|
|
13851
|
+
/**
|
|
13569
13852
|
* Does `value` carry a CloudFormation dynamic reference anywhere inside it?
|
|
13570
13853
|
*
|
|
13571
13854
|
* Used as the identity fast path of {@link
|
|
@@ -15467,8 +15750,9 @@ var IntrinsicFunctionResolver = class IntrinsicFunctionResolver {
|
|
|
15467
15750
|
async reresolveCrossStackValue(value, producerRegion, context, origin, sourceKey) {
|
|
15468
15751
|
if (!carriesDynamicReference(value)) return value;
|
|
15469
15752
|
const resolver = this.resolverForProducerRegion(producerRegion);
|
|
15753
|
+
const pinnedContext = producerRegion ? withoutProducerRegions(context) : context;
|
|
15470
15754
|
const walk = async (v) => {
|
|
15471
|
-
if (typeof v === "string") return v.includes("{{resolve:") ? await resolver.resolveDynamicReferences(v,
|
|
15755
|
+
if (typeof v === "string") return v.includes("{{resolve:") ? await resolver.resolveDynamicReferences(v, pinnedContext) : v;
|
|
15472
15756
|
if (Array.isArray(v)) {
|
|
15473
15757
|
const out = new Array(v.length);
|
|
15474
15758
|
for (let i = 0; i < v.length; i++) out[i] = await walk(v[i]);
|
|
@@ -16132,6 +16416,13 @@ var IntrinsicFunctionResolver = class IntrinsicFunctionResolver {
|
|
|
16132
16416
|
const service = inner.split(":")[0];
|
|
16133
16417
|
const isKnownSecret = service === "secretsmanager" || recordedSecretExpressions.has(fullMatch);
|
|
16134
16418
|
if (isKnownSecret && context?.skipDynamicReferences) continue;
|
|
16419
|
+
const regionVerdict = classifyReplaySecretRegion(fullMatch, this.explicitRegion ?? this.resolverRegion, context?.producerRegions);
|
|
16420
|
+
if (regionVerdict.kind === "ambiguous") throw markNonRetryable(new DynamicReferenceRegionAmbiguousError(`Refusing to resolve the secret reference ${fullMatch}: it names '${regionVerdict.secretName}' without a region, and this stack reads from ${regionVerdict.foreignProducerRegions.join(", ")} as well as its own region. cdkd cannot tell which one must answer, and resolving against the wrong one yields a different secret. Spell the reference as a full ARN to say which region owns it.`));
|
|
16421
|
+
if (regionVerdict.kind === "named-region") {
|
|
16422
|
+
const foreign = await this.resolverForProducerRegion(regionVerdict.region).resolveDynamicReferences(fullMatch, withoutProducerRegions(context));
|
|
16423
|
+
result = result.replace(fullMatch, () => foreign);
|
|
16424
|
+
continue;
|
|
16425
|
+
}
|
|
16135
16426
|
const cached = this.cachedDynamicReferences.get(fullMatch);
|
|
16136
16427
|
if (cached) {
|
|
16137
16428
|
if (cached.secret && cached.value) context?.recordedSecretValues?.set(cached.value, fullMatch);
|
|
@@ -17273,7 +17564,7 @@ var CloudControlProvider = class {
|
|
|
17273
17564
|
if (context?.finalSnapshotIdentifier !== void 0) throw new ProvisioningError(`${logicalId} (${resourceType}) requires a final snapshot (DeletionPolicy: Snapshot), but the Cloud Control API delete route has no final-snapshot parameter. Re-run with --skip-final-snapshot after snapshotting manually, or retain the resource.`, resourceType, logicalId, physicalId);
|
|
17274
17565
|
if (context?.removeProtection === true && resourceType === "AWS::AutoScaling::AutoScalingGroup") {
|
|
17275
17566
|
this.logger.debug(`Delegating protected AutoScalingGroup ${logicalId} delete to the SDK ASGProvider (Cloud Control cannot force-delete a protected ASG)`);
|
|
17276
|
-
const { ASGProvider } = await import("./asg-provider-
|
|
17567
|
+
const { ASGProvider } = await import("./asg-provider-BbWubpjP.js").then((n) => n.n);
|
|
17277
17568
|
return await new ASGProvider().delete(logicalId, physicalId, resourceType, _properties, context);
|
|
17278
17569
|
}
|
|
17279
17570
|
const isProtectedEc2Instance = context?.removeProtection === true && resourceType === "AWS::EC2::Instance";
|
|
@@ -25148,223 +25439,6 @@ async function resolveReplayProps(props, resolvers, secrets, execCtx, logicalId)
|
|
|
25148
25439
|
return await walk(props, "");
|
|
25149
25440
|
}
|
|
25150
25441
|
/**
|
|
25151
|
-
* The `{{resolve:<service>:...}}` families whose value can be a SECRET, and
|
|
25152
|
-
* therefore the only ones the region question below is asked about: every
|
|
25153
|
-
* `secretsmanager` reference by spelling, and every `ssm` one, which is secret
|
|
25154
|
-
* exactly when its parameter is a `SecureString` (issue #1901).
|
|
25155
|
-
*
|
|
25156
|
-
* Every OTHER service is `local` because cdkd cannot resolve it at all, NOT
|
|
25157
|
-
* because it is public. `ssm-secure` is the live example and is emphatically
|
|
25158
|
-
* not public: `resolveDynamicReferences` has no arm for it, so the literal
|
|
25159
|
-
* token is passed through to AWS and CloudFormation resolves it SERVER-side.
|
|
25160
|
-
* cdkd never holds its value, so there is no region for cdkd to get wrong —
|
|
25161
|
-
* which is the only reason it can be waved through here.
|
|
25162
|
-
*/
|
|
25163
|
-
const REPLAY_SECRET_SERVICES = /* @__PURE__ */ new Set(["secretsmanager", "ssm"]);
|
|
25164
|
-
/**
|
|
25165
|
-
* Split a `{{resolve:secretsmanager:...}}` inner body into its SECRET_ID.
|
|
25166
|
-
*
|
|
25167
|
-
* Mirrors `IntrinsicFunctionResolver.resolveSecretsManagerReference`'s own
|
|
25168
|
-
* split — including the END-ANCHORED whole-secret form — because a secret ID
|
|
25169
|
-
* may legitimately contain colons (an ARN always does), so `split(':')[1]` is
|
|
25170
|
-
* wrong for exactly the shape this file cares about most.
|
|
25171
|
-
*/
|
|
25172
|
-
function secretsManagerSecretId(inner) {
|
|
25173
|
-
const afterService = inner.substring(15);
|
|
25174
|
-
let stringIdx = afterService.indexOf(":SecretString:");
|
|
25175
|
-
let binaryIdx = afterService.indexOf(":SecretBinary:");
|
|
25176
|
-
if (stringIdx < 0 && afterService.endsWith(":SecretString")) stringIdx = afterService.length - 13;
|
|
25177
|
-
if (binaryIdx < 0 && afterService.endsWith(":SecretBinary")) binaryIdx = afterService.length - 13;
|
|
25178
|
-
const delimiterIdx = stringIdx >= 0 && binaryIdx >= 0 ? Math.min(stringIdx, binaryIdx) : stringIdx >= 0 ? stringIdx : binaryIdx;
|
|
25179
|
-
return delimiterIdx >= 0 ? afterService.substring(0, delimiterIdx) : afterService;
|
|
25180
|
-
}
|
|
25181
|
-
/**
|
|
25182
|
-
* The parameter name an `{{resolve:ssm:...}}` reference asks for — byte-for-byte
|
|
25183
|
-
* what `IntrinsicFunctionResolver.resolveSSMReference` passes as `GetParameter`'s
|
|
25184
|
-
* `Name`, which is `parts.slice(1).join(':')` on the colon-split inner body.
|
|
25185
|
-
*
|
|
25186
|
-
* The whole remainder, deliberately, with NOTHING stripped:
|
|
25187
|
-
*
|
|
25188
|
-
* - An SSM dynamic reference CAN name a full ARN. The resolver joins the tail
|
|
25189
|
-
* back together, so `{{resolve:ssm:arn:aws:ssm:us-west-2:111122223333:parameter/db/pw}}`
|
|
25190
|
-
* reaches AWS as that ARN. A `split(':')[1]` here would yield the literal
|
|
25191
|
-
* `'arn'` — a parameter that does not exist — and then report the reference
|
|
25192
|
-
* as region-LESS and refuse it, which is the guess-in-the-other-direction the
|
|
25193
|
-
* `named-region` arm exists to prevent.
|
|
25194
|
-
* - A trailing `:<version>` / `:<label>` is part of the name AS SSM PARSES IT
|
|
25195
|
-
* (`GetParameter` accepts `name:3` / `name:prod`), so stripping it would name
|
|
25196
|
-
* a different thing in the refusal message than the one that would be read.
|
|
25197
|
-
*/
|
|
25198
|
-
function ssmParameterName(inner) {
|
|
25199
|
-
return inner.substring(4);
|
|
25200
|
-
}
|
|
25201
|
-
/**
|
|
25202
|
-
* The region an ARN names, or `undefined` for anything that is not an ARN with
|
|
25203
|
-
* a populated region field (`arn:<partition>:<service>:<region>:...`).
|
|
25204
|
-
*/
|
|
25205
|
-
function arnRegion(secretId) {
|
|
25206
|
-
if (!secretId.startsWith("arn:")) return void 0;
|
|
25207
|
-
const region = secretId.split(":")[3];
|
|
25208
|
-
return region ? region : void 0;
|
|
25209
|
-
}
|
|
25210
|
-
/**
|
|
25211
|
-
* The producer regions a stack's persisted cross-stack reads name, for
|
|
25212
|
-
* {@link RollbackExecutorContext.importedProducerRegions} (issue #2057).
|
|
25213
|
-
*
|
|
25214
|
-
* Both record kinds count, and for the same reason: each one is a value this
|
|
25215
|
-
* stack read out of ANOTHER region's state, so each one is a way a
|
|
25216
|
-
* foreign-region `{{resolve:...}}` expression can have reached this stack's own
|
|
25217
|
-
* record. `imports` is the strong `Fn::ImportValue` edge; `outputReads` is the
|
|
25218
|
-
* weak `Fn::GetStackOutput` one (schema v8), which is the EASIER of the two to
|
|
25219
|
-
* point across a region boundary because the reference carries its own
|
|
25220
|
-
* `Region` argument.
|
|
25221
|
-
*
|
|
25222
|
-
* Deduplicated case-insensitively, keeping each region's first-recorded
|
|
25223
|
-
* spelling so the refusal message echoes what the user will see in
|
|
25224
|
-
* `state.json`. The consumer's own region is deliberately NOT filtered here —
|
|
25225
|
-
* {@link classifyReplaySecretRegion} does that, because it is the one that
|
|
25226
|
-
* knows which region is asking.
|
|
25227
|
-
*
|
|
25228
|
-
* Exported so the two `RollbackExecutorContext` construction sites derive the
|
|
25229
|
-
* list identically — `cdkd rollback` from the state it loaded, and
|
|
25230
|
-
* `DeployEngine.rollbackExecutorContext` from `crossStackReadsForPartialSave`,
|
|
25231
|
-
* which unions that snapshot with the reads the failing deploy itself made.
|
|
25232
|
-
*/
|
|
25233
|
-
function producerRegionsFromState(state) {
|
|
25234
|
-
const seen = /* @__PURE__ */ new Set();
|
|
25235
|
-
const regions = [];
|
|
25236
|
-
for (const entry of [...state.imports ?? [], ...state.outputReads ?? []]) {
|
|
25237
|
-
const canonical = canonicalizeRegion(entry.sourceRegion);
|
|
25238
|
-
if (!canonical || seen.has(canonical)) continue;
|
|
25239
|
-
seen.add(canonical);
|
|
25240
|
-
regions.push(entry.sourceRegion);
|
|
25241
|
-
}
|
|
25242
|
-
return regions;
|
|
25243
|
-
}
|
|
25244
|
-
/**
|
|
25245
|
-
* Decide which region must answer for a single `{{resolve:...}}` expression a
|
|
25246
|
-
* rollback replay is about to re-resolve — issue
|
|
25247
|
-
* [#2057](https://github.com/go-to-k/cdkd/issues/2057).
|
|
25248
|
-
*
|
|
25249
|
-
* WHY A REPLAY CAN BE HOLDING A FOREIGN REGION'S EXPRESSION AT ALL. Since
|
|
25250
|
-
* issue #1934 a cross-stack consumer re-resolves a redacted producer value in
|
|
25251
|
-
* the PRODUCER's region (`reresolveCrossStackValue` /
|
|
25252
|
-
* `resolverForProducerRegion`) — correct, because a Secrets Manager secret or
|
|
25253
|
-
* an SSM `SecureString` of the same NAME in two regions is two independent
|
|
25254
|
-
* values. The plaintext is then recorded into the CONSUMER's
|
|
25255
|
-
* `recordedSecretValues`, so the consumer's `state.json` (and from there the
|
|
25256
|
-
* rollback journal) persists the PRODUCER's spelling of the expression. That is
|
|
25257
|
-
* the right thing to persist, and it is region-less: the reader cannot tell
|
|
25258
|
-
* from the string which region produced it.
|
|
25259
|
-
*
|
|
25260
|
-
* The replay rebuilds its resolver from the CONSUMER's region alone, so
|
|
25261
|
-
* re-resolving that expression locally answers from a same-named secret in the
|
|
25262
|
-
* wrong region and writes it to a LIVE resource. Silent, and on the recovery
|
|
25263
|
-
* path. The rule applied here is the family's, from issue #1957: A NAMED REGION
|
|
25264
|
-
* BINDS; NEVER SUBSTITUTE A GUESS. The three verdicts are that one sentence:
|
|
25265
|
-
*
|
|
25266
|
-
* - **`named-region`** — the expression's SECRET_ID is an ARN, which names its
|
|
25267
|
-
* own region. The region is ESTABLISHED, so it binds: the caller resolves
|
|
25268
|
-
* through a resolver pinned to it ({@link ReplayResolvers.forRegion}) rather
|
|
25269
|
-
* than refusing. Refusing here would be the guess in the other direction.
|
|
25270
|
-
*
|
|
25271
|
-
* cdkd would otherwise get this wrong, which is why the arm exists at all:
|
|
25272
|
-
* `resolveSecretsManagerReference` builds its client from
|
|
25273
|
-
* `this.explicitRegion` and passes the ARN through as an opaque `SecretId`,
|
|
25274
|
-
* and `@aws-sdk/client-secrets-manager`'s endpoint ruleset has NO
|
|
25275
|
-
* ARN-derived endpoint rule (unlike, say, S3 access points), so a
|
|
25276
|
-
* foreign-region ARN is sent to the stack's own regional endpoint. What the
|
|
25277
|
-
* SERVICE then does with it is not something this repo can settle offline —
|
|
25278
|
-
* see the fixture note in
|
|
25279
|
-
* `tests/integration/rollback-cross-region-secret/README.md`. Pinning the
|
|
25280
|
-
* client to the ARN's region is correct either way: if Secrets Manager would
|
|
25281
|
-
* have refused the foreign ARN, this turns a hard failure into a correct
|
|
25282
|
-
* resolution; if it would have honoured it, this reaches the same value by
|
|
25283
|
-
* the documented route. Neither outcome is a regression.
|
|
25284
|
-
*
|
|
25285
|
-
* - **`ambiguous`** — the expression names no region (the plain name form) AND
|
|
25286
|
-
* this stack has a foreign producer region on record
|
|
25287
|
-
* ({@link RollbackExecutorContext.importedProducerRegions}). Nothing on hand
|
|
25288
|
-
* can establish the origin, so the replay refuses instead of guessing.
|
|
25289
|
-
*
|
|
25290
|
-
* KNOWN OVER-REFUSAL, accepted deliberately, and WIDER THAN THE SSM CASE
|
|
25291
|
-
* ALONE — state both, because the second one is the common shape:
|
|
25292
|
-
*
|
|
25293
|
-
* (a) Any NAME-FORM `secretsmanager` reference in a stack that has ANY
|
|
25294
|
-
* foreign producer region on record is refused, even when that secret is
|
|
25295
|
-
* the stack's own purely-local one and has nothing to do with the
|
|
25296
|
-
* cross-region read. The evidence is per-STACK, not per-reference, so one
|
|
25297
|
-
* cross-region export plus one ordinary
|
|
25298
|
-
* `{{resolve:secretsmanager:mysecret:SecretString:pw}}` is enough — and CDK's
|
|
25299
|
-
* `secretValueFromJson` emits exactly that name form, so this is the shape
|
|
25300
|
-
* most people will meet. It also persists: with the union the producer
|
|
25301
|
-
* region stays on record until the next SUCCESSFUL deploy. Per-reference
|
|
25302
|
-
* evidence is what would narrow it, and that needs the region recorded
|
|
25303
|
-
* ALONGSIDE the expression — the persisted-shape change issue #2057
|
|
25304
|
-
* deliberately deferred (its options 1 and 2). Until then the refusal is
|
|
25305
|
-
* loud, names the ARN spelling as the remedy, and is the fail-closed side
|
|
25306
|
-
* of a trade whose other side is a silent wrong-secret write.
|
|
25307
|
-
*
|
|
25308
|
-
* (b) An `ssm` reference is secret only when its parameter is a
|
|
25309
|
-
* `SecureString`, and this arm cannot tell. So a `{{resolve:ssm:/app/env}}`
|
|
25310
|
-
* naming a PUBLIC `String` that reached a persisted bag (issue #2036's
|
|
25311
|
-
* acknowledged over-redaction) is refused too. Narrowing it by
|
|
25312
|
-
* `isRecordedSecretExpression` was considered and REJECTED, and not because
|
|
25313
|
-
* the store is unreachable — it is imported by this very file. It is
|
|
25314
|
-
* unusable: `recordedSecretExpressions` is populated BY resolution, and in
|
|
25315
|
-
* the standalone `cdkd rollback` process nothing has resolved anything when
|
|
25316
|
-
* the first op is classified, so the store is empty and every `ssm` verdict
|
|
25317
|
-
* would come back "not secret" — turning the protection off for exactly the
|
|
25318
|
-
* SecureString case it exists for. Worse, once one op DID resolve a
|
|
25319
|
-
* reference the store would be warm for the next, so the verdict would
|
|
25320
|
-
* depend on OP ORDER. A resolve-the-type-first probe is unsound for the
|
|
25321
|
-
* same reason the whole issue exists: the TYPE is region-dependent (#1957),
|
|
25322
|
-
* so probing locally can report `String` for a name that is `SecureString`
|
|
25323
|
-
* in the producer's region and wave through the very write this refuses.
|
|
25324
|
-
* The residual is therefore a loud, actionable error on a narrow
|
|
25325
|
-
* intersection (an over-redacted public ssm reference AND a cross-region
|
|
25326
|
-
* read on record), which is the fail-closed side of the trade.
|
|
25327
|
-
*
|
|
25328
|
-
* - **`local`** — everything else, which is the overwhelmingly common case:
|
|
25329
|
-
* every non-secret service, every same-region ARN (the ordinary CDK
|
|
25330
|
-
* `secretValueFromJson` shape), and every name-form expression in a stack
|
|
25331
|
-
* with no foreign producer region recorded. Resolved exactly as before this
|
|
25332
|
-
* change.
|
|
25333
|
-
*
|
|
25334
|
-
* A same-region ARN answers `local` even when a foreign producer region IS on
|
|
25335
|
-
* record: the expression settles the question itself, so the weaker evidence
|
|
25336
|
-
* never gets consulted.
|
|
25337
|
-
*/
|
|
25338
|
-
function classifyReplaySecretRegion(expression, consumerRegion, importedProducerRegions) {
|
|
25339
|
-
const inner = expression.startsWith("{{resolve:") ? expression.slice(10, -2) : void 0;
|
|
25340
|
-
if (inner === void 0) return { kind: "local" };
|
|
25341
|
-
const service = inner.split(":")[0];
|
|
25342
|
-
if (service === void 0 || !REPLAY_SECRET_SERVICES.has(service)) return { kind: "local" };
|
|
25343
|
-
const secretName = service === "secretsmanager" ? secretsManagerSecretId(inner) : ssmParameterName(inner);
|
|
25344
|
-
if (!secretName) return { kind: "local" };
|
|
25345
|
-
const named = arnRegion(secretName);
|
|
25346
|
-
if (named !== void 0) return canonicalizeRegion(named) === canonicalizeRegion(consumerRegion) ? { kind: "local" } : {
|
|
25347
|
-
kind: "named-region",
|
|
25348
|
-
secretName,
|
|
25349
|
-
region: named
|
|
25350
|
-
};
|
|
25351
|
-
const seen = /* @__PURE__ */ new Set();
|
|
25352
|
-
const foreignProducerRegions = [];
|
|
25353
|
-
for (const candidate of importedProducerRegions ?? []) {
|
|
25354
|
-
const canonical = canonicalizeRegion(candidate);
|
|
25355
|
-
if (!canonical || canonical === canonicalizeRegion(consumerRegion)) continue;
|
|
25356
|
-
if (seen.has(canonical)) continue;
|
|
25357
|
-
seen.add(canonical);
|
|
25358
|
-
foreignProducerRegions.push(candidate);
|
|
25359
|
-
}
|
|
25360
|
-
if (foreignProducerRegions.length === 0) return { kind: "local" };
|
|
25361
|
-
return {
|
|
25362
|
-
kind: "ambiguous",
|
|
25363
|
-
secretName,
|
|
25364
|
-
foreignProducerRegions
|
|
25365
|
-
};
|
|
25366
|
-
}
|
|
25367
|
-
/**
|
|
25368
25442
|
* The replay's resolvers: the stack's own, plus one pinned sibling per FOREIGN
|
|
25369
25443
|
* region an ARN-named reference asks for (issue #2057).
|
|
25370
25444
|
*
|
|
@@ -26186,7 +26260,7 @@ const FLUSH_INTERVAL_MS = 2e3;
|
|
|
26186
26260
|
const FLUSH_EVENT_THRESHOLD = 50;
|
|
26187
26261
|
/** Build-time cdkd version, with a dev fallback for non-built contexts. */
|
|
26188
26262
|
function getCdkdVersion() {
|
|
26189
|
-
return "0.284.
|
|
26263
|
+
return "0.284.37";
|
|
26190
26264
|
}
|
|
26191
26265
|
/**
|
|
26192
26266
|
* Generate a time-sortable unique run id, e.g.
|
|
@@ -28806,5 +28880,5 @@ var DeployEngine = class {
|
|
|
28806
28880
|
};
|
|
28807
28881
|
|
|
28808
28882
|
//#endregion
|
|
28809
|
-
export {
|
|
28810
|
-
//# sourceMappingURL=deploy-engine-
|
|
28883
|
+
export { startInterruptWatch as $, ConfigError as $n, buildAssetRedirectMap as $t, renderStatefulReason as A, resolveStateBucketWithDefaultAndSource as An, redactSecretsForState as At, exportAliasCollisionScrubWarning as B, PARTITION_TABLE as Bn, DiffCalculator as Bt, isFinalSnapshotError as C, getDefaultStateBucketName as Cn, isRetryableTransientError as Cr, TEMPLATE_SOURCED_RULES as Ct, extractDeploymentEventError as D, resolveCaptureObservedState as Dn, isSingleDynamicReferenceToken as Dt, makeCanonicalizePropertiesFn as E, resolveAutoAssetStorage as En, __exportAll as Er, errorCauseChain as Et, green as F, CFN_TEMPLATE_URL_LIMIT as Fn, s3BucketDomainName as Ft, collectInlinePolicyNamesManagedBySiblings as G, clearBucketRegionCache as Gn, TemplateParser as Gt, secretBearingStateKeyWarning as H, derivePartitionAndUrlSuffix as Hn, describeTypeWithThrottleRetry as Ht, red as I, MIGRATE_TMP_PREFIX as In, s3BucketDualStackDomainName as It, findActionableSilentDrops as J, getAwsClients as Jn, rebuildClientForBucketRegion as Jt, clearOnUpdateRemoval as K, resolveBucketRegion as Kn, LockManager as Kt, yellow as L, findLargeInlineResources as Ln, s3BucketRegionalDomainName as Lt, bold as M, stateBucketExistenceConfirmed as Mn, classifyReplaySecretRegion as Mt, cyan as N, warnDeprecatedNoPrefixCliFlag as Nn, producerRegionsFromState as Nt, MULTI_REGION_RECREATE_BLOCKED_TYPES as O, resolveSkipPrefix as On, maskSecretsInError as Ot, gray as P, CFN_TEMPLATE_BODY_LIMIT as Pn, s3BucketArn as Pt, isInterruptedWaitError as Q, CdkdError as Qn, WorkGraph as Qt, collectDeclaredOutputNames as R, uploadCfnTemplate as Rn, s3BucketWebsiteUrl as Rt, createPreDeleteFinalSnapshot as S, synthesisStatusMessage as Sn, isMarkedNonRetryable as Sr, STATE_SOURCED_READBACK_RULES as St, unsupportedFinalSnapshotError as T, resolveApp as Tn, markNonRetryable as Tr, dynamicReferenceTokens as Tt, stateKeySecretExposure as U, AssemblyReader as Un, withRetry as Ut, isExportAliasCollision as V, canonicalizeRegion as Vn, INTRINSIC_KEYS as Vt, IAMRoleProvider as W, processStackMessages as Wn, DagBuilder as Wt, beginCommandInterruptScope as X, setAwsClients as Xn, AssetPublisher as Xt, findSilentDropProperties as Y, resetAwsClients as Yn, shouldRetainResource as Yt, endCommandInterruptScope as Z, AssetError as Zn, stringifyValue as Zt, computeImplicitDeleteEdges as _, runDockerForeground as _n, SynthesisError as _r, replayWarn as _t, DeploymentEventsStore as a, AssetModeResolver as an, LocalMigrateError as ar, carriesDynamicReference as at, buildFinalSnapshotIdentifier as b, getDockerImageBySourceHash as bn, normalizeAwsError as br, requireConfigString as bt, replayFailedOperations as c, getBootstrapMarkerKey as cn, MissingCdkCliError as cr, refStateLookupFromResource as ct, updatePartialReason as d, validateAssetBucketName as dn, ProvisioningError as dr, resolveExplicitPhysicalId as dt, createAssetRedirectResolver as en, CrossAccountSecretRefusalError as er, CloudControlProvider as et, UNSPECIFIED_SKIP_REASON as f, validateContainerRepoName as fn, ResourceTimeoutError as fr, assertRegionMatch as ft, IMPLICIT_DELETE_DEPENDENCIES as g, getDockerCmd as gn, StateError as gr, readConfigString as gt, maskingRetryLogger as h, formatDockerLoginError as hn, StackTerminationProtectionError as hr, configStringRefusal as ht, DeploymentEventsReader as i, stripControlChars as in, LocalInvokeBuildError as ir, IntrinsicFunctionResolver as it, formatResourceLine as j, resolveUseCdkBootstrapAssets as jn, scrubResourceRecord as jt, isStatefulRecreateTargetSync as k, resolveStateBucketWithDefault as kn, maskSecretsInText as kt, replayRollback as l, parseBootstrapMarker as ln, NestedStackChildDirectDestroyError as lr, WAFv2WebACLProvider as lt, withResourceDeadline as m, buildDockerImage as mn, StackHasActiveImportsError as mr, configBooleanRefusal as mt, DEFAULT_RESOURCE_WARN_AFTER_MS as n, rewriteTemplateAssetReferences as nn, DeployCancelledError as nr, disableInstanceApiTermination as nt, planFailedOps as o, BOOTSTRAP_MARKER_PREFIX as on, LocalStartServiceError as or, cfnRefValueFromPhysicalId as ot, deleteSkipReason as p, buildDenyExternalAccessPolicy as pn, ResourceUpdateNotSupportedError as pr, coerceCfnBoolean as pt, ProviderRegistry as q, AwsClients as qn, S3StateBackend as qt, DeployEngine as r, escapeRegExp$1 as rn, DynamicReferenceRegionAmbiguousError as rr, isTerminationProtectionPropagationError as rt, planRollback as s, ensureAssetStorage as sn, LockError as sr, getAccountInfo as st, DEFAULT_RESOURCE_TIMEOUT_MS as t, loadPublishableAssetManifest as tn, DependencyError as tr, slowCcOperationTimeoutMs as tt, updatePartialMessage as u, readBootstrapMarkerBody as un, PartialFailureError as ur, normalizeAwsTagsToCfn as ut, ATOMIC_FINAL_SNAPSHOT_TYPES as v, runDockerStreaming as vn, formatError as vr, requireConfigArray as vt, refusesFinalSnapshot as w, getLegacyStateBucketName as wn, isThrottlingError as wr, createSecretMasker as wt, ccRoutedFinalSnapshotError as x, Synthesizer as xn, withErrorHandling as xr, STATE_SOURCED_CROSS_GENERATION_RULES as xt, PRE_DELETE_SNAPSHOT_TYPES as y, AssetManifestLoader as yn, isCdkdError as yr, requireConfigObject as yt, collectPublishedOutputNames as z, expectedOwnerParam as zn, applyRoleArnIfSet as zt };
|
|
28884
|
+
//# sourceMappingURL=deploy-engine-C62UGXid.js.map
|