@go-to-k/cdkd 0.290.22 → 0.290.23
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-DTzndMHB.js → asg-provider-BOYln2Tw.js} +10 -10
- package/dist/asg-provider-BOYln2Tw.js.map +1 -0
- package/dist/cli.js +2 -2
- package/dist/{deploy-engine-Dbmoo4FQ.js → deploy-engine-CBzq85r6.js} +314 -72
- package/dist/deploy-engine-CBzq85r6.js.map +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -2
- package/dist/{logger-C17H06QA.js → logger-CkHVgzLx.js} +7 -1
- package/dist/logger-CkHVgzLx.js.map +1 -0
- package/dist/{program-BKuJRiz3.js → program-BgbPkrcx.js} +191 -189
- package/dist/{program-BKuJRiz3.js.map → program-BgbPkrcx.js.map} +1 -1
- package/dist/{version-CpOEkAtB.js → version-DxUVmvM5.js} +2 -2
- package/dist/{version-CpOEkAtB.js.map → version-DxUVmvM5.js.map} +1 -1
- package/package.json +1 -1
- package/dist/asg-provider-DTzndMHB.js.map +0 -1
- package/dist/deploy-engine-Dbmoo4FQ.js.map +0 -1
- package/dist/logger-C17H06QA.js.map +0 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { C as displaySafe, S as displayIdent, b as STACK_REF_MAX_CODE_POINTS, d as applyDefaultNameForFallback, f as explicitNamePropertyFor, g as looksLikeCdkdGeneratedName, h as getCurrentStackName, m as generateResourceNameWithFallback, n as getLogger, p as generateResourceName, r as isStdoutReservedForPayload, s as getLiveRenderer, v as withStackName, w as truncateCodePoints, x as UNRENDERABLE, y as withoutGeneratedFallbackName } from "./logger-
|
|
1
|
+
import { C as displaySafe, S as displayIdent, b as STACK_REF_MAX_CODE_POINTS, d as applyDefaultNameForFallback, f as explicitNamePropertyFor, g as looksLikeCdkdGeneratedName, h as getCurrentStackName, m as generateResourceNameWithFallback, n as getLogger, p as generateResourceName, r as isStdoutReservedForPayload, s as getLiveRenderer, v as withStackName, w as truncateCodePoints, x as UNRENDERABLE, y as withoutGeneratedFallbackName } from "./logger-CkHVgzLx.js";
|
|
2
2
|
import { a as setAssumedRoleCredentials, i as getPreAssumeEnvCredentials, n as awsClientDefaults, o as setPreAssumeEnvCredentials, r as getAssumedRoleCredentials, t as SECOND_ROLE_PUBLISH_REFUSAL } from "./aws-client-defaults-BoIxyCir.js";
|
|
3
|
-
import { t as getCdkdVersion } from "./version-
|
|
3
|
+
import { t as getCdkdVersion } from "./version-DxUVmvM5.js";
|
|
4
4
|
import { AsyncLocalStorage } from "node:async_hooks";
|
|
5
5
|
import { createHash, randomUUID } from "node:crypto";
|
|
6
6
|
import { CreateBucketCommand, DeleteObjectCommand, DeleteObjectsCommand, GetBucketLocationCommand, GetBucketReplicationCommand, GetObjectCommand, HeadBucketCommand, HeadObjectCommand, ListObjectVersionsCommand, ListObjectsV2Command, NoSuchKey, PutBucketEncryptionCommand, PutBucketPolicyCommand, PutObjectCommand, PutPublicAccessBlockCommand, S3Client, S3ServiceException } from "@aws-sdk/client-s3";
|
|
@@ -7360,7 +7360,7 @@ function repairSpawnRefusal(text, args, maskedArgs) {
|
|
|
7360
7360
|
* error would only say "Command failed with exit code N".
|
|
7361
7361
|
*/
|
|
7362
7362
|
function describeDockerExecFailure(error, args) {
|
|
7363
|
-
const message = thrownMessageText(error) || safeStringify(error);
|
|
7363
|
+
const message = thrownMessageText(error) || safeStringify$1(error);
|
|
7364
7364
|
const stderrText = capturedStreamText(error, "stderr");
|
|
7365
7365
|
return redactDockerArgvInText(stderrText ? `${message}\n${stderrText}` : message, args);
|
|
7366
7366
|
}
|
|
@@ -7403,7 +7403,7 @@ function thrownMessageText(error) {
|
|
|
7403
7403
|
* two of these call sites are in `cleanupEcsRun`, where an exception aborts
|
|
7404
7404
|
* the remaining volume / network teardown and leaks real Docker resources.
|
|
7405
7405
|
*/
|
|
7406
|
-
function safeStringify(error) {
|
|
7406
|
+
function safeStringify$1(error) {
|
|
7407
7407
|
try {
|
|
7408
7408
|
return String(error);
|
|
7409
7409
|
} catch {
|
|
@@ -7429,7 +7429,7 @@ function safeStringify(error) {
|
|
|
7429
7429
|
* wrapper text needs the status as well.
|
|
7430
7430
|
*/
|
|
7431
7431
|
function describeDockerFailure(error, args) {
|
|
7432
|
-
return redactDockerArgvInText(capturedStreamText(error, "stderr") || thrownMessageText(error) || safeStringify(error), args);
|
|
7432
|
+
return redactDockerArgvInText(capturedStreamText(error, "stderr") || thrownMessageText(error) || safeStringify$1(error), args);
|
|
7433
7433
|
}
|
|
7434
7434
|
/**
|
|
7435
7435
|
* A `cause` that is safe to CHAIN onto a wrapper error, for a caller that
|
|
@@ -8019,6 +8019,40 @@ function isAwsAuthoredFailure(error) {
|
|
|
8019
8019
|
return candidate.$fault !== void 0 || typeof candidate.$metadata?.httpStatusCode === "number" || error.name === "CredentialsProviderError";
|
|
8020
8020
|
}
|
|
8021
8021
|
/**
|
|
8022
|
+
* Exactly what `String(value)` produces, without the throw.
|
|
8023
|
+
*
|
|
8024
|
+
* `String(value)` is the only spelling that carries an `Error`'s NAME as well
|
|
8025
|
+
* as its message (`"AccessDenied: User ... is not authorized"`), and several
|
|
8026
|
+
* call sites depend on that: four build a persisted `outcome: 'partial'`
|
|
8027
|
+
* reason where the wire code is the discriminator an operator reads first.
|
|
8028
|
+
* {@link describeAwsFailure}'s `detail` is the MESSAGE only, so it is NOT a
|
|
8029
|
+
* drop-in for the bare form -- substituting it silently deletes the code.
|
|
8030
|
+
* Measured, after a sweep did exactly that at nine sites.
|
|
8031
|
+
*
|
|
8032
|
+
* So this is the 1:1 replacement: same output for every value `String` can
|
|
8033
|
+
* convert, and a stable sentence for the ones it cannot. A null-prototype
|
|
8034
|
+
* object throws `TypeError: Cannot convert object to primitive value`, and an
|
|
8035
|
+
* object with a hostile or `null` `toString` throws whatever it likes -- inside
|
|
8036
|
+
* a catch, that replaces the failure being reported.
|
|
8037
|
+
*
|
|
8038
|
+
* Use `describeAwsFailure(x).detail` where the site previously read
|
|
8039
|
+
* `x instanceof Error ? x.message : String(x)`; use THIS where it read a bare
|
|
8040
|
+
* `String(x)`.
|
|
8041
|
+
*
|
|
8042
|
+
* NOT a substitute for `displaySafe` in `display-safe.ts`, which guards the
|
|
8043
|
+
* same coercion and answers differently on purpose -- it falls back to
|
|
8044
|
+
* `Object.prototype.toString` and, more importantly, SANITISES the result for a
|
|
8045
|
+
* terminal. Anything about to be rendered or logged goes through that one; this
|
|
8046
|
+
* one is for the text a catch is about to record.
|
|
8047
|
+
*/
|
|
8048
|
+
function safeStringify(value) {
|
|
8049
|
+
try {
|
|
8050
|
+
return String(value);
|
|
8051
|
+
} catch {
|
|
8052
|
+
return "a value that could not be converted to text";
|
|
8053
|
+
}
|
|
8054
|
+
}
|
|
8055
|
+
/**
|
|
8022
8056
|
* Describe a caught failure for a thrown message. See {@link AwsFailureText}.
|
|
8023
8057
|
*/
|
|
8024
8058
|
function describeAwsFailure(error) {
|
|
@@ -11935,6 +11969,84 @@ function resolvedPlaintextOf(secrets, expression) {
|
|
|
11935
11969
|
function resolvedExpressionsOf(secrets) {
|
|
11936
11970
|
return [...resolvedPairsOf.get(secrets)?.keys() ?? []];
|
|
11937
11971
|
}
|
|
11972
|
+
/** Poison for an intrinsic object one pass resolved two different ways. */
|
|
11973
|
+
const CONFLICTING_LEAF_RESOLUTION = Symbol("conflicting leaf resolution");
|
|
11974
|
+
/**
|
|
11975
|
+
* {@link IntrinsicLeafResolution}s per pass bag, keyed by the template OBJECT
|
|
11976
|
+
* that was resolved (issue [#3156](https://github.com/go-to-k/cdkd/issues/3156)).
|
|
11977
|
+
* The carry in {@link recordNestedStackParameterExpressions} reads it for the
|
|
11978
|
+
* very object the deploy engine handed the resolver, so its evidence is THIS
|
|
11979
|
+
* leaf's own resolution: no other leaf's substitution, however equal its value,
|
|
11980
|
+
* can answer for it, and each substitution carries its own verdict, which the
|
|
11981
|
+
* secret-only pair table cannot (an unclassifiable `ssm` answer recorded as a
|
|
11982
|
+
* pair looks the same as a later public answer with the same plaintext).
|
|
11983
|
+
* Both keys are weak, so a record lives as long as its bag and its template.
|
|
11984
|
+
*/
|
|
11985
|
+
const intrinsicLeafResolutionsOf = /* @__PURE__ */ new WeakMap();
|
|
11986
|
+
/**
|
|
11987
|
+
* Record how the pass that owns `secrets` resolved the intrinsic object
|
|
11988
|
+
* `source`. A second resolution of the same object that differs in any field
|
|
11989
|
+
* poisons it for the pass, and the poison is never lifted; an identical one
|
|
11990
|
+
* changes nothing.
|
|
11991
|
+
*/
|
|
11992
|
+
function recordIntrinsicLeafResolution(secrets, source, resolution) {
|
|
11993
|
+
let leaves = intrinsicLeafResolutionsOf.get(secrets);
|
|
11994
|
+
if (leaves === void 0) {
|
|
11995
|
+
leaves = /* @__PURE__ */ new WeakMap();
|
|
11996
|
+
intrinsicLeafResolutionsOf.set(secrets, leaves);
|
|
11997
|
+
}
|
|
11998
|
+
const copy = {
|
|
11999
|
+
input: resolution.input,
|
|
12000
|
+
output: resolution.output,
|
|
12001
|
+
substitutions: resolution.substitutions.map(({ token, value, secret }) => ({
|
|
12002
|
+
token,
|
|
12003
|
+
value,
|
|
12004
|
+
secret
|
|
12005
|
+
})),
|
|
12006
|
+
complete: resolution.complete
|
|
12007
|
+
};
|
|
12008
|
+
const previous = leaves.get(source);
|
|
12009
|
+
if (previous === void 0) leaves.set(source, copy);
|
|
12010
|
+
else if (previous === CONFLICTING_LEAF_RESOLUTION || !sameLeafResolution(previous, copy)) leaves.set(source, CONFLICTING_LEAF_RESOLUTION);
|
|
12011
|
+
}
|
|
12012
|
+
function sameLeafResolution(a, b) {
|
|
12013
|
+
return a.input === b.input && a.output === b.output && a.complete === b.complete && a.substitutions.length === b.substitutions.length && a.substitutions.every((s, i) => s.token === b.substitutions[i].token && s.value === b.substitutions[i].value && s.secret === b.substitutions[i].secret);
|
|
12014
|
+
}
|
|
12015
|
+
/**
|
|
12016
|
+
* The spelling `source`'s own resolution in this pass proves for
|
|
12017
|
+
* `resolvedValue`, or `undefined` (issue
|
|
12018
|
+
* [#3156](https://github.com/go-to-k/cdkd/issues/3156)). Certified only when
|
|
12019
|
+
* the resolution replaced every token it met, replaced exactly ONE, took a
|
|
12020
|
+
* SECRET verdict for it, and produced `resolvedValue` from `input` by that one
|
|
12021
|
+
* replacement ({@link singleSpanFrame} over `input` with the token and value
|
|
12022
|
+
* equal). That is the observed equation `resolvedValue = input[token := value]`;
|
|
12023
|
+
* it says nothing about what a later lookup of the token returns.
|
|
12024
|
+
*
|
|
12025
|
+
* The `secret` test and the COUNT are independent. The count refuses a
|
|
12026
|
+
* replacement listed ahead of the one the frame names that left its plaintext,
|
|
12027
|
+
* not its token, in `input` -- a used Sub variable holding the SAME token as
|
|
12028
|
+
* the template (`port:T${V}` with `V` = `T`), whose first replacement passes
|
|
12029
|
+
* the token and value tests while `input` keeps the variable's plaintext.
|
|
12030
|
+
* `complete`, `output` and the token and value tests are implied, for every
|
|
12031
|
+
* shape the resolver records, by the count and `singleSpanFrame` over `input`:
|
|
12032
|
+
* a token left unreplaced in `input` is a second span, and a frame that fits
|
|
12033
|
+
* `input` around the one replacement fixes the output it produces. They are
|
|
12034
|
+
* kept so a recorder that is not faithful refuses rather than certifies, and
|
|
12035
|
+
* are pinned by hand-built records only.
|
|
12036
|
+
*/
|
|
12037
|
+
function substitutedSpellingOf(secrets, source, resolvedValue) {
|
|
12038
|
+
const resolution = intrinsicLeafResolutionsOf.get(secrets)?.get(source);
|
|
12039
|
+
if (resolution === void 0 || resolution === CONFLICTING_LEAF_RESOLUTION) return void 0;
|
|
12040
|
+
if (!resolution.complete || resolution.output !== resolvedValue) return void 0;
|
|
12041
|
+
if (resolution.substitutions.length !== 1) return void 0;
|
|
12042
|
+
const [substitution] = resolution.substitutions;
|
|
12043
|
+
if (!substitution.secret) return void 0;
|
|
12044
|
+
const frame = singleSpanFrame(resolvedValue, resolution.input);
|
|
12045
|
+
if (frame === void 0) return void 0;
|
|
12046
|
+
if (frame.token !== substitution.token || frame.middle !== substitution.value) return void 0;
|
|
12047
|
+
for (const plaintext of secrets.keys()) if (plaintext !== "" && (frame.prefix.includes(plaintext) || frame.suffix.includes(plaintext))) return;
|
|
12048
|
+
return resolution.input;
|
|
12049
|
+
}
|
|
11938
12050
|
/**
|
|
11939
12051
|
* The bag OBJECTS a deploy pass produced ITSELF and installed on a success
|
|
11940
12052
|
* path — the fact the resolved-pair evidence above cannot state (issue
|
|
@@ -12886,8 +12998,9 @@ const UNFRAMED_SPELLING = Symbol("cdkd.nested-parameter.unframed-spelling");
|
|
|
12886
12998
|
* literal source; pinned by the "map NO RESOLVER populated" case,
|
|
12887
12999
|
* where (ii) and (iii) both pass and only the missing pair refuses.
|
|
12888
13000
|
* On an OBJECT source (`Fn::Join` / `Fn::Sub`, issue #3062) there is
|
|
12889
|
-
* no source text to compare, so the spelling
|
|
12890
|
-
* admitted only when `positioned[name] !==
|
|
13001
|
+
* no source text to compare, so the spelling-based arm takes what
|
|
13002
|
+
* the pass WROTE, admitted only when `positioned[name] !==
|
|
13003
|
+
* resolvedValue`. Sound
|
|
12891
13004
|
* together with (ii), not alone: on a value the scan is silent on,
|
|
12892
13005
|
* the cross-stack and skeleton arms both refuse (each requires the
|
|
12893
13006
|
* WHOLE leaf to be a key of the map, which would make the scan's
|
|
@@ -12895,16 +13008,23 @@ const UNFRAMED_SPELLING = Symbol("cdkd.nested-parameter.unframed-spelling");
|
|
|
12895
13008
|
* scan leaves the leaf alone -- so the frame arm is the only writer
|
|
12896
13009
|
* that can have rewritten it, on its pair and the engine's mark. A
|
|
12897
13010
|
* frame that is not wholly literal makes that arm refuse, the leaf
|
|
12898
|
-
* comes back unrewritten, and
|
|
12899
|
-
*
|
|
13011
|
+
* comes back unrewritten, and this arm refuses too. It certifies
|
|
13012
|
+
* only a source whose OWN rendered token starts with a
|
|
12900
13013
|
* spelled-secret prefix (`secretsmanager:` / `ssm-secure:`), read from
|
|
12901
13014
|
* the source and never from what the pass wrote: the frame arm
|
|
12902
13015
|
* matches among RECORDED references and a public `ssm` parameter
|
|
12903
13016
|
* records none, so a public leaf whose source spells `ssm:`, or leaves
|
|
12904
13017
|
* the service to an intrinsic part, can match a recorded secret
|
|
12905
|
-
* sibling and be written as the sibling's reference.
|
|
12906
|
-
*
|
|
12907
|
-
*
|
|
13018
|
+
* sibling and be written as the sibling's reference. Where it refuses,
|
|
13019
|
+
* the PROVENANCE arm (issue #3156) certifies on the leaf's own
|
|
13020
|
+
* resolution instead: the resolver records, per `Fn::Join` /
|
|
13021
|
+
* `Fn::Sub` object and pass bag, every token it replaced with the
|
|
13022
|
+
* verdict that replacement took, and one SECRET replacement that turns
|
|
13023
|
+
* the record's input into the value certifies that input as the
|
|
13024
|
+
* spelling -- an `ssm:` or intrinsic-service token, and a frame whose
|
|
13025
|
+
* non-literal part sits OUTSIDE the token, which the frame arm never
|
|
13026
|
+
* writes. `frameSpellingOf` states what it proves and what it does
|
|
13027
|
+
* not. The STATE-derived
|
|
12908
13028
|
* call sites reach this arm as well: `cdkd import` can leave raw
|
|
12909
13029
|
* intrinsics in a record's `properties`, which a rollback replay
|
|
12910
13030
|
* passes as its source, and the frame arm does not read `rules`.
|
|
@@ -12940,10 +13060,9 @@ const UNFRAMED_SPELLING = Symbol("cdkd.nested-parameter.unframed-spelling");
|
|
|
12940
13060
|
* (i)-(iii) on its own), a leaf (iii) refused under a different
|
|
12941
13061
|
* frame, an object spelling the frame arm refused and a plain
|
|
12942
13062
|
* literal equal to the value all fail it and would take the entry's
|
|
12943
|
-
* frame (an object spelling
|
|
12944
|
-
*
|
|
12945
|
-
*
|
|
12946
|
-
* would a
|
|
13063
|
+
* frame (an object spelling (i) certified is a frame like a literal
|
|
13064
|
+
* one, issues #3062 and #3156; one it refused counts as unframed) --
|
|
13065
|
+
* and so would a
|
|
12947
13066
|
* same-frame sibling whose token this pass never resolved to the
|
|
12948
13067
|
* middle: a PUBLIC `ssm` reference in the same `port:` frame holding
|
|
12949
13068
|
* the same two characters is kept RESOLVED on the record, and the
|
|
@@ -12952,7 +13071,13 @@ const UNFRAMED_SPELLING = Symbol("cdkd.nested-parameter.unframed-spelling");
|
|
|
12952
13071
|
* the row are gathered BEFORE the conditions run, a spelling that is
|
|
12953
13072
|
* not a single-span literal frame with this pass's pair for its token
|
|
12954
13073
|
* (`resolvedPlaintextOf`) counting as its own, and a value is
|
|
12955
|
-
* recorded only when its certified frame is the row's only one.
|
|
13074
|
+
* recorded only when its certified frame is the row's only one. A
|
|
13075
|
+
* value one of whose leaves the position pass did NOT write (the
|
|
13076
|
+
* provenance arm's outside-the-token frame) also counts as unframed
|
|
13077
|
+
* unless every framed spelling of it carries ONE token: the frame arm
|
|
13078
|
+
* refuses that leaf on the parent's record, so the entry is written
|
|
13079
|
+
* onto it by the value scan whatever its token, and (iii)'s rescue
|
|
13080
|
+
* for a same-frame sibling does not reach it.
|
|
12956
13081
|
* (v) No OTHER string leaf of the ROW would be rewritten by the entry,
|
|
12957
13082
|
* read over every leaf of the resolved row since the bag is per
|
|
12958
13083
|
* resource, not per `Parameters`. Two arms of the persist walk read
|
|
@@ -13038,16 +13163,29 @@ const UNFRAMED_SPELLING = Symbol("cdkd.nested-parameter.unframed-spelling");
|
|
|
13038
13163
|
* persists the plaintext -- the same class as the nonliteral-frame deferral.
|
|
13039
13164
|
* (e) CLOSED for a wholly literal frame by (i)'s object arm (issue #3062;
|
|
13040
13165
|
* was: an `Fn::Join` / `Fn::Sub` source in the parent's own `Parameters`
|
|
13041
|
-
* block was never carried)
|
|
13042
|
-
*
|
|
13043
|
-
*
|
|
13044
|
-
* the
|
|
13045
|
-
*
|
|
13046
|
-
*
|
|
13047
|
-
*
|
|
13048
|
-
*
|
|
13049
|
-
*
|
|
13050
|
-
*
|
|
13166
|
+
* block was never carried), and for the two spellings that arm refused -- a
|
|
13167
|
+
* token spelling `ssm:` or leaving its service to an intrinsic part, and a
|
|
13168
|
+
* frame whose non-literal part sits outside the token -- by its provenance
|
|
13169
|
+
* arm (issue #3156), which on the second also rewrites the PARENT's record of
|
|
13170
|
+
* the leaf through the entry. What remains of it: a leaf whose own resolution
|
|
13171
|
+
* does not certify -- the token spelled inside a NESTED intrinsic part (the
|
|
13172
|
+
* outer object's own text spells none), the token held by a used `Fn::Sub`
|
|
13173
|
+
* variable (the template spells a placeholder there), a leaf resolved two
|
|
13174
|
+
* different ways in one pass, one whose replacement took a public verdict, one
|
|
13175
|
+
* that replaced more than one token, one whose affix holds a plaintext the bag
|
|
13176
|
+
* holds (another secret a non-literal part resolved), an `Fn::If` around the
|
|
13177
|
+
* object (which the skeleton cannot render, and whose record is under the
|
|
13178
|
+
* selected branch) -- keeps the plaintext in the child, and for the
|
|
13179
|
+
* outside-the-token frame in the parent's record; so does an outside-the-token
|
|
13180
|
+
* frame sharing its value with a leaf of another token, which (iv) refuses. A
|
|
13181
|
+
* rollback replay records nothing here (`resolveReplayProps` resolves strings,
|
|
13182
|
+
* not intrinsic objects): a journal a deploy wrote holds a carried frame's
|
|
13183
|
+
* persisted spelling as a STRING, which the literal arm reads, while a record
|
|
13184
|
+
* `cdkd import` left holding the raw intrinsic stays refused on this arm
|
|
13185
|
+
* (go-to-k/cdkd#3306 tracks the refused shapes). Any other resolved
|
|
13186
|
+
* text a non-literal part contributes is carried verbatim in the spelling, as
|
|
13187
|
+
* the value already carries it.
|
|
13188
|
+
* (f) A child record persisted BEFORE this carry
|
|
13051
13189
|
* keeps `port:q7` until the child is next redeployed: the parent's own row
|
|
13052
13190
|
* already held the frame (the literal or frame arm), so a parent deploy whose child
|
|
13053
13191
|
* row is unchanged never re-runs the child, and `cdkd scrub` cannot repair
|
|
@@ -13083,12 +13221,19 @@ function recordNestedStackParameterExpressions(secrets, resourceType, resolvedPr
|
|
|
13083
13221
|
}
|
|
13084
13222
|
const framesByValue = /* @__PURE__ */ new Map();
|
|
13085
13223
|
const tokensOf = /* @__PURE__ */ new Map();
|
|
13086
|
-
const
|
|
13224
|
+
const frameSpellings = /* @__PURE__ */ new Map();
|
|
13225
|
+
const frameSpellingOf = (name) => {
|
|
13226
|
+
if (!frameSpellings.has(name)) frameSpellings.set(name, computeFrameSpelling(name));
|
|
13227
|
+
return frameSpellings.get(name);
|
|
13228
|
+
};
|
|
13229
|
+
const computeFrameSpelling = (name) => {
|
|
13230
|
+
const resolvedValue = resolvedParameters[name];
|
|
13231
|
+
if (typeof resolvedValue !== "string") return void 0;
|
|
13087
13232
|
const sourceLeaf = sourceParameters[name];
|
|
13088
13233
|
if (typeof sourceLeaf === "string") return sourceLeaf;
|
|
13089
13234
|
if (!isPlainObject$2(sourceLeaf)) return void 0;
|
|
13090
13235
|
const written = positioned[name];
|
|
13091
|
-
if (typeof written !== "string"
|
|
13236
|
+
if (typeof written !== "string") return void 0;
|
|
13092
13237
|
const segments = intrinsicSkeletonSegments(sourceLeaf);
|
|
13093
13238
|
if (segments === void 0) return void 0;
|
|
13094
13239
|
const rendered = segments.map((s) => s === UNKNOWN_PART ? UNKNOWN_PART_PLACEHOLDER : s).join("");
|
|
@@ -13096,16 +13241,20 @@ function recordNestedStackParameterExpressions(secrets, resourceType, resolvedPr
|
|
|
13096
13241
|
if (spans.length !== 1) return void 0;
|
|
13097
13242
|
const [span] = spans;
|
|
13098
13243
|
const ownToken = rendered.slice(span.start, span.end);
|
|
13099
|
-
|
|
13244
|
+
if (written !== resolvedValue && SPELLED_SECRET_REFERENCE_PREFIXES.some((prefix) => ownToken.startsWith(prefix))) return written;
|
|
13245
|
+
const substituted = substitutedSpellingOf(secrets, sourceLeaf, resolvedValue);
|
|
13246
|
+
if (substituted === void 0) return void 0;
|
|
13247
|
+
return written === resolvedValue || written === substituted ? substituted : void 0;
|
|
13100
13248
|
};
|
|
13101
|
-
const certifiedSpellingOf = (name
|
|
13249
|
+
const certifiedSpellingOf = (name) => {
|
|
13102
13250
|
const sourceLeaf = sourceParameters[name];
|
|
13103
13251
|
if (typeof sourceLeaf === "string") return positioned[name] === sourceLeaf ? sourceLeaf : void 0;
|
|
13104
|
-
return frameSpellingOf(name
|
|
13252
|
+
return frameSpellingOf(name);
|
|
13105
13253
|
};
|
|
13254
|
+
const unwrittenValues = /* @__PURE__ */ new Set();
|
|
13106
13255
|
for (const [name, resolvedValue] of Object.entries(resolvedParameters)) {
|
|
13107
13256
|
if (typeof resolvedValue !== "string") continue;
|
|
13108
|
-
const spelling = frameSpellingOf(name
|
|
13257
|
+
const spelling = frameSpellingOf(name);
|
|
13109
13258
|
const frame = spelling === void 0 ? void 0 : singleSpanFrame(resolvedValue, spelling);
|
|
13110
13259
|
const frames = framesByValue.get(resolvedValue) ?? /* @__PURE__ */ new Set();
|
|
13111
13260
|
const unframed = frame === void 0 || resolvedPlaintextOf(secrets, frame.token) !== frame.middle;
|
|
@@ -13115,8 +13264,10 @@ function recordNestedStackParameterExpressions(secrets, resourceType, resolvedPr
|
|
|
13115
13264
|
const tokens = tokensOf.get(resolvedValue) ?? /* @__PURE__ */ new Set();
|
|
13116
13265
|
tokens.add(frame.token);
|
|
13117
13266
|
tokensOf.set(resolvedValue, tokens);
|
|
13267
|
+
if (typeof sourceParameters[name] !== "string" && positioned[name] !== spelling) unwrittenValues.add(resolvedValue);
|
|
13118
13268
|
}
|
|
13119
13269
|
}
|
|
13270
|
+
for (const value of unwrittenValues) if (tokensOf.get(value)?.size !== 1) framesByValue.get(value)?.add(UNFRAMED_SPELLING);
|
|
13120
13271
|
const rowWithoutParameters = {};
|
|
13121
13272
|
for (const [key, value] of Object.entries(resolvedProperties)) if (key !== "Parameters") rowWithoutParameters[key] = value;
|
|
13122
13273
|
const outsideLeaves = wholeStringLeavesOf(rowWithoutParameters);
|
|
@@ -13124,7 +13275,7 @@ function recordNestedStackParameterExpressions(secrets, resourceType, resolvedPr
|
|
|
13124
13275
|
const framedByName = [];
|
|
13125
13276
|
for (const [name, resolvedValue] of Object.entries(resolvedParameters)) {
|
|
13126
13277
|
if (typeof resolvedValue !== "string") continue;
|
|
13127
|
-
const spelling = certifiedSpellingOf(name
|
|
13278
|
+
const spelling = certifiedSpellingOf(name);
|
|
13128
13279
|
if (spelling === void 0) continue;
|
|
13129
13280
|
if (redactSecretsForState(resolvedValue, secrets) !== resolvedValue) continue;
|
|
13130
13281
|
const frame = singleSpanFrame(resolvedValue, spelling);
|
|
@@ -17884,7 +18035,7 @@ function getCreateOnlyPropertyPaths(resourceType) {
|
|
|
17884
18035
|
if (cached) return cached;
|
|
17885
18036
|
const entry = fetchCreateOnlyPropertyPaths(resourceType).catch((error) => {
|
|
17886
18037
|
createOnlyPropertiesCache.delete(resourceType);
|
|
17887
|
-
const message =
|
|
18038
|
+
const message = describeAwsFailure(error).detail;
|
|
17888
18039
|
getLogger().child("CreateOnlyProperties").warn(`Failed to resolve create-only properties for ${resourceType} via cloudformation:DescribeType (${message}). Falling back to the registry-only replacement classification for this resource — an immutable-property change may be mis-classified as an in-place update. Grant cloudformation:DescribeType to enable schema-driven replacement detection.`);
|
|
17889
18040
|
return [];
|
|
17890
18041
|
});
|
|
@@ -24743,7 +24894,7 @@ var WAFv2WebACLProvider = class {
|
|
|
24743
24894
|
const tagsResp = await this.getClient().send(new ListTagsForResourceCommand$11({ ResourceARN: physicalId }));
|
|
24744
24895
|
result["Tags"] = normalizeAwsTagsToCfn(tagsResp.TagInfoForResource?.TagList);
|
|
24745
24896
|
} catch (err) {
|
|
24746
|
-
this.logger.debug(`WAFv2 ListTagsForResource(${physicalId}) failed: ${
|
|
24897
|
+
this.logger.debug(`WAFv2 ListTagsForResource(${physicalId}) failed: ${describeAwsFailure(err).detail}`);
|
|
24747
24898
|
}
|
|
24748
24899
|
return result;
|
|
24749
24900
|
}
|
|
@@ -26967,8 +27118,8 @@ var IntrinsicFunctionResolver = class IntrinsicFunctionResolver {
|
|
|
26967
27118
|
const obj = value;
|
|
26968
27119
|
if ("Ref" in obj) return await this.resolveRef(obj["Ref"], context);
|
|
26969
27120
|
if ("Fn::GetAtt" in obj) return await this.resolveGetAtt(obj["Fn::GetAtt"], context);
|
|
26970
|
-
if ("Fn::Join" in obj) return await this.resolveJoin(obj["Fn::Join"], context);
|
|
26971
|
-
if ("Fn::Sub" in obj) return await this.resolveSub(obj["Fn::Sub"], context);
|
|
27121
|
+
if ("Fn::Join" in obj) return await this.resolveJoin(obj["Fn::Join"], context, obj);
|
|
27122
|
+
if ("Fn::Sub" in obj) return await this.resolveSub(obj["Fn::Sub"], context, obj);
|
|
26972
27123
|
if ("Fn::Select" in obj) return await this.resolveSelect(obj["Fn::Select"], context);
|
|
26973
27124
|
if ("Fn::Split" in obj) return await this.resolveSplit(obj["Fn::Split"], context);
|
|
26974
27125
|
if ("Fn::If" in obj) return await this.resolveIf(obj["Fn::If"], context);
|
|
@@ -28064,32 +28215,45 @@ var IntrinsicFunctionResolver = class IntrinsicFunctionResolver {
|
|
|
28064
28215
|
*
|
|
28065
28216
|
* Fn::Join: [delimiter, [value1, value2, ...]]
|
|
28066
28217
|
*/
|
|
28067
|
-
async resolveJoin(joinArgs, context) {
|
|
28218
|
+
async resolveJoin(joinArgs, context, source) {
|
|
28068
28219
|
const [delimiter, rawValues] = joinArgs;
|
|
28069
28220
|
let values = rawValues;
|
|
28070
28221
|
if (!Array.isArray(values)) values = await this.resolveValue(values, context);
|
|
28071
28222
|
if (!Array.isArray(values)) throw new Error(`Fn::Join's second argument must be a list (an array literal or a list-returning intrinsic such as Fn::Cidr / Fn::GetAZs / Fn::Split / a Ref to a list-typed parameter — any List<...> type or CommaDelimitedList), but resolved to ${typeof values}`);
|
|
28072
28223
|
const literalList = Array.isArray(rawValues);
|
|
28073
|
-
const
|
|
28074
|
-
if (typeof v === "string")
|
|
28075
|
-
|
|
28224
|
+
const resolvedParts = await allSettledKeepingFirstRejection(values.map(async (v) => {
|
|
28225
|
+
if (typeof v === "string") {
|
|
28226
|
+
const part = v.includes("{{resolve:") ? await this.resolveDynamicReferencesWithLogTwin(v, this.logTwinOfProduct({
|
|
28076
28227
|
result: v,
|
|
28077
28228
|
twin: v
|
|
28078
28229
|
}, context).twin, context) : {
|
|
28079
28230
|
result: v,
|
|
28080
|
-
twin: v
|
|
28081
|
-
|
|
28082
|
-
|
|
28083
|
-
|
|
28231
|
+
twin: v,
|
|
28232
|
+
substitutions: [],
|
|
28233
|
+
complete: true
|
|
28234
|
+
};
|
|
28235
|
+
return {
|
|
28236
|
+
result: part.result,
|
|
28237
|
+
twin: part.twin,
|
|
28238
|
+
product: !literalList,
|
|
28239
|
+
input: v,
|
|
28240
|
+
substitutions: part.substitutions,
|
|
28241
|
+
complete: part.complete
|
|
28242
|
+
};
|
|
28243
|
+
}
|
|
28084
28244
|
const raw = await this.resolveValue(v, context);
|
|
28085
28245
|
const resolved = String(raw);
|
|
28086
28246
|
return {
|
|
28087
28247
|
result: resolved,
|
|
28088
28248
|
twin: resolved,
|
|
28089
28249
|
product: true,
|
|
28090
|
-
raw: { value: raw }
|
|
28250
|
+
raw: { value: raw },
|
|
28251
|
+
input: resolved,
|
|
28252
|
+
substitutions: [],
|
|
28253
|
+
complete: true
|
|
28091
28254
|
};
|
|
28092
|
-
}), (pending) => this.warnAbandonedParts(pending))
|
|
28255
|
+
}), (pending) => this.warnAbandonedParts(pending));
|
|
28256
|
+
const parts = resolvedParts.map((part) => {
|
|
28093
28257
|
if (!part.product) return part;
|
|
28094
28258
|
if (part.raw) return {
|
|
28095
28259
|
result: part.result,
|
|
@@ -28099,7 +28263,20 @@ var IntrinsicFunctionResolver = class IntrinsicFunctionResolver {
|
|
|
28099
28263
|
});
|
|
28100
28264
|
let result = parts.map((part) => part.result).join(delimiter);
|
|
28101
28265
|
let twin = parts.map((part) => part.twin).join(delimiter);
|
|
28102
|
-
|
|
28266
|
+
const substitutions = resolvedParts.flatMap((part) => part.substitutions);
|
|
28267
|
+
let complete = resolvedParts.every((part) => part.complete);
|
|
28268
|
+
if (result.includes("{{resolve:")) {
|
|
28269
|
+
const joined = await this.resolveDynamicReferencesWithLogTwin(result, twin, context);
|
|
28270
|
+
({result, twin} = joined);
|
|
28271
|
+
substitutions.push(...joined.substitutions);
|
|
28272
|
+
complete &&= joined.complete;
|
|
28273
|
+
}
|
|
28274
|
+
this.recordLeafResolution(context, source, {
|
|
28275
|
+
input: resolvedParts.map((part) => part.input).join(delimiter),
|
|
28276
|
+
output: result,
|
|
28277
|
+
substitutions,
|
|
28278
|
+
complete
|
|
28279
|
+
});
|
|
28103
28280
|
this.rememberLogTwin(context, result, twin);
|
|
28104
28281
|
this.logger.debug(`Resolved Fn::Join: ${this.maskSecretsForLog(this.logTwinText(result, twin, context), context)}`);
|
|
28105
28282
|
return result;
|
|
@@ -28241,10 +28418,11 @@ var IntrinsicFunctionResolver = class IntrinsicFunctionResolver {
|
|
|
28241
28418
|
* inside replace(). For full async support, we'd need to collect all replacements
|
|
28242
28419
|
* first, then do them synchronously.
|
|
28243
28420
|
*/
|
|
28244
|
-
async resolveSub(subArgs, context) {
|
|
28421
|
+
async resolveSub(subArgs, context, source) {
|
|
28245
28422
|
let template;
|
|
28246
28423
|
const variables = Object.create(null);
|
|
28247
28424
|
const variableTwins = Object.create(null);
|
|
28425
|
+
const variablePasses = Object.create(null);
|
|
28248
28426
|
if (Array.isArray(subArgs)) {
|
|
28249
28427
|
const [templateString, variableMap] = subArgs;
|
|
28250
28428
|
template = templateString;
|
|
@@ -28252,10 +28430,13 @@ var IntrinsicFunctionResolver = class IntrinsicFunctionResolver {
|
|
|
28252
28430
|
for (const [key, val] of Object.entries(variableMap)) if (typeof val === "string") {
|
|
28253
28431
|
const resolved = val.includes("{{resolve:") ? await this.resolveDynamicReferencesWithLogTwin(val, val, context) : {
|
|
28254
28432
|
result: val,
|
|
28255
|
-
twin: val
|
|
28433
|
+
twin: val,
|
|
28434
|
+
substitutions: [],
|
|
28435
|
+
complete: true
|
|
28256
28436
|
};
|
|
28257
28437
|
variables[key] = resolved.result;
|
|
28258
28438
|
variableTwins[key] = resolved.twin;
|
|
28439
|
+
variablePasses[key] = resolved;
|
|
28259
28440
|
} else variables[key] = context.abandonedResolutions === void 0 ? await this.resolveValue(val, context) : await this.resolveKeyUnit(key, val, context, context.abandonedResolutions);
|
|
28260
28441
|
} else template = subArgs;
|
|
28261
28442
|
const replacements = [];
|
|
@@ -28282,9 +28463,11 @@ var IntrinsicFunctionResolver = class IntrinsicFunctionResolver {
|
|
|
28282
28463
|
}
|
|
28283
28464
|
let replacement;
|
|
28284
28465
|
let twinReplacement;
|
|
28466
|
+
let pass;
|
|
28285
28467
|
if (varNameStr in variables) {
|
|
28286
28468
|
replacement = String(variables[varNameStr]);
|
|
28287
28469
|
twinReplacement = varNameStr in variableTwins ? variableTwins[varNameStr] : this.productLogTwin(variables[varNameStr], context);
|
|
28470
|
+
if (varNameStr in variablePasses) pass = variablePasses[varNameStr];
|
|
28288
28471
|
} else {
|
|
28289
28472
|
const pseudoValue = await this.resolvePseudoParameter(varNameStr, context);
|
|
28290
28473
|
if (pseudoValue !== void 0) replacement = String(pseudoValue);
|
|
@@ -28314,7 +28497,8 @@ var IntrinsicFunctionResolver = class IntrinsicFunctionResolver {
|
|
|
28314
28497
|
replacements.push({
|
|
28315
28498
|
match: match[0],
|
|
28316
28499
|
replacement,
|
|
28317
|
-
twin: twinReplacement ?? replacement
|
|
28500
|
+
twin: twinReplacement ?? replacement,
|
|
28501
|
+
...pass ? { pass } : {}
|
|
28318
28502
|
});
|
|
28319
28503
|
}
|
|
28320
28504
|
let cursor = 0;
|
|
@@ -28327,7 +28511,21 @@ var IntrinsicFunctionResolver = class IntrinsicFunctionResolver {
|
|
|
28327
28511
|
const entry = replacements[twinCursor++];
|
|
28328
28512
|
return entry ? entry.twin : whole;
|
|
28329
28513
|
});
|
|
28330
|
-
|
|
28514
|
+
const input = result;
|
|
28515
|
+
const substitutions = replacements.flatMap((entry) => entry.pass?.substitutions ?? []);
|
|
28516
|
+
let complete = replacements.every((entry) => entry.pass?.complete ?? true);
|
|
28517
|
+
if (result.includes("{{resolve:")) {
|
|
28518
|
+
const substituted = await this.resolveDynamicReferencesWithLogTwin(result, twin, context);
|
|
28519
|
+
({result, twin} = substituted);
|
|
28520
|
+
substitutions.push(...substituted.substitutions);
|
|
28521
|
+
complete &&= substituted.complete;
|
|
28522
|
+
}
|
|
28523
|
+
this.recordLeafResolution(context, source, {
|
|
28524
|
+
input,
|
|
28525
|
+
output: result,
|
|
28526
|
+
substitutions,
|
|
28527
|
+
complete
|
|
28528
|
+
});
|
|
28331
28529
|
this.rememberLogTwin(context, result, twin);
|
|
28332
28530
|
this.logger.debug(`Resolved Fn::Sub: ${this.maskSecretsForLog(this.logTwinText(result, twin, context), context)}`);
|
|
28333
28531
|
return result;
|
|
@@ -29717,7 +29915,11 @@ var IntrinsicFunctionResolver = class IntrinsicFunctionResolver {
|
|
|
29717
29915
|
* not the bag holds pairs. Where the middle RE-WRAPS it (an `Fn::Join` around
|
|
29718
29916
|
* the `Ref`) the middle registers its own twin, and the hand-off still drops
|
|
29719
29917
|
* a bag holding no pairs (it passes `inheritedSecrets` only when `size` is
|
|
29720
|
-
* nonzero).
|
|
29918
|
+
* nonzero). What reaches a grandchild instead is the parent's WHOLE-VALUE
|
|
29919
|
+
* entry: the middle's `{ Ref }` copies it into the middle's bag, which is then
|
|
29920
|
+
* non-empty and handed down. Issue #3156 made the carry record that entry for
|
|
29921
|
+
* the intrinsic frames it used to refuse; a frame it still refuses (listed on
|
|
29922
|
+
* `recordNestedStackParameterExpressions`) keeps both gaps.
|
|
29721
29923
|
*
|
|
29722
29924
|
* The registry is keyed by VALUE, and `splitLogTwins`' unaligned arm
|
|
29723
29925
|
* registers every piece, public ones included. So a child `Fn::Base64` over a
|
|
@@ -29767,6 +29969,17 @@ var IntrinsicFunctionResolver = class IntrinsicFunctionResolver {
|
|
|
29767
29969
|
};
|
|
29768
29970
|
}
|
|
29769
29971
|
/**
|
|
29972
|
+
* Record the `Fn::Join` / `Fn::Sub` object `source`'s own resolution under
|
|
29973
|
+
* the pass bag the nested-stack carry reads (issue
|
|
29974
|
+
* [#3156](https://github.com/go-to-k/cdkd/issues/3156)). The key is the
|
|
29975
|
+
* object `resolveValue` dispatched on, and a context with no bag has no pass
|
|
29976
|
+
* to scope it to.
|
|
29977
|
+
*/
|
|
29978
|
+
recordLeafResolution(context, source, resolution) {
|
|
29979
|
+
if (context.recordedSecretValues === void 0) return;
|
|
29980
|
+
recordIntrinsicLeafResolution(context.recordedSecretValues, source, resolution);
|
|
29981
|
+
}
|
|
29982
|
+
/**
|
|
29770
29983
|
* Register a MASKED `twin` as the log twin of `result` for this pass (issue
|
|
29771
29984
|
* #3100). An unmasked twin is not registered, so a later literal that
|
|
29772
29985
|
* resolves to the same string cannot replace an earlier write's mask, and
|
|
@@ -29904,6 +30117,8 @@ var IntrinsicFunctionResolver = class IntrinsicFunctionResolver {
|
|
|
29904
30117
|
const pattern = /\{\{resolve:([^}]+)\}\}/g;
|
|
29905
30118
|
let result = value;
|
|
29906
30119
|
let twin = logTwin;
|
|
30120
|
+
const substitutions = [];
|
|
30121
|
+
let complete = true;
|
|
29907
30122
|
let match;
|
|
29908
30123
|
const matches = [];
|
|
29909
30124
|
while ((match = pattern.exec(value)) !== null) matches.push({
|
|
@@ -29919,7 +30134,10 @@ var IntrinsicFunctionResolver = class IntrinsicFunctionResolver {
|
|
|
29919
30134
|
const nameLogText = inherited?.nameLogText ?? (pairedTwin === void 0 ? () => "***" : this.dynamicReferenceNameLogText(inner, pairedTwin, context));
|
|
29920
30135
|
try {
|
|
29921
30136
|
const isKnownSecret = service === "secretsmanager" || service === "ssm-secure" || recordedSecretExpressions.has(fullMatch);
|
|
29922
|
-
if (isKnownSecret && context?.skipDynamicReferences)
|
|
30137
|
+
if (isKnownSecret && context?.skipDynamicReferences) {
|
|
30138
|
+
complete = false;
|
|
30139
|
+
continue;
|
|
30140
|
+
}
|
|
29923
30141
|
const regionVerdict = classifyReplaySecretRegion(fullMatch, this.explicitRegion ?? this.resolverRegion, context?.producerRegions);
|
|
29924
30142
|
if (regionVerdict.kind === "ambiguous") throw markNonRetryable(new DynamicReferenceRegionAmbiguousError(`Refusing to resolve the secret reference ${this.maskSecretsForLog(tokenLogText, context)}: it names '${this.maskSecretsForLog(nameLogText(regionVerdict.secretName), context)}' without a region, and this stack reads from ${this.maskSecretsForLog(regionVerdict.foreignProducerRegions.map((r) => this.maskSecretsForLog(r, context)).join(", "), context)} 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.`));
|
|
29925
30143
|
if (regionVerdict.kind === "named-region") {
|
|
@@ -29929,6 +30147,13 @@ var IntrinsicFunctionResolver = class IntrinsicFunctionResolver {
|
|
|
29929
30147
|
});
|
|
29930
30148
|
result = result.replace(fullMatch, () => foreign.result);
|
|
29931
30149
|
twin = twin.replace(fullMatch, () => foreign.twin);
|
|
30150
|
+
const [delegated] = foreign.substitutions;
|
|
30151
|
+
substitutions.push({
|
|
30152
|
+
token: fullMatch,
|
|
30153
|
+
value: foreign.result,
|
|
30154
|
+
secret: foreign.substitutions.length === 1 && delegated.secret
|
|
30155
|
+
});
|
|
30156
|
+
if (!foreign.complete || foreign.substitutions.length !== 1) complete = false;
|
|
29932
30157
|
continue;
|
|
29933
30158
|
}
|
|
29934
30159
|
const cached = this.cachedDynamicReferences.get(fullMatch);
|
|
@@ -29939,6 +30164,11 @@ var IntrinsicFunctionResolver = class IntrinsicFunctionResolver {
|
|
|
29939
30164
|
}
|
|
29940
30165
|
result = result.replace(fullMatch, () => cached.value);
|
|
29941
30166
|
twin = twin.replace(fullMatch, () => cached.secret && cached.value ? "***" : cached.value);
|
|
30167
|
+
substitutions.push({
|
|
30168
|
+
token: fullMatch,
|
|
30169
|
+
value: cached.value,
|
|
30170
|
+
secret: cached.secret
|
|
30171
|
+
});
|
|
29942
30172
|
continue;
|
|
29943
30173
|
}
|
|
29944
30174
|
const parts = inner.split(":");
|
|
@@ -29966,7 +30196,10 @@ var IntrinsicFunctionResolver = class IntrinsicFunctionResolver {
|
|
|
29966
30196
|
else cacheable = false;
|
|
29967
30197
|
isSecret = param.secure;
|
|
29968
30198
|
if (param.secure) {
|
|
29969
|
-
if (!decrypt)
|
|
30199
|
+
if (!decrypt) {
|
|
30200
|
+
complete = false;
|
|
30201
|
+
continue;
|
|
30202
|
+
}
|
|
29970
30203
|
}
|
|
29971
30204
|
resolved = param.value;
|
|
29972
30205
|
} else if (service === "ssm-secure") {
|
|
@@ -29976,6 +30209,7 @@ var IntrinsicFunctionResolver = class IntrinsicFunctionResolver {
|
|
|
29976
30209
|
resolved = param.value;
|
|
29977
30210
|
} else {
|
|
29978
30211
|
this.logger.warn(this.maskSecretsForLog(`Unsupported dynamic reference service: ${this.maskSecretsForLog(nameLogText(String(service)), context)}`, context));
|
|
30212
|
+
complete = false;
|
|
29979
30213
|
continue;
|
|
29980
30214
|
}
|
|
29981
30215
|
if (cacheable) this.cachedDynamicReferences.set(fullMatch, {
|
|
@@ -29989,6 +30223,11 @@ var IntrinsicFunctionResolver = class IntrinsicFunctionResolver {
|
|
|
29989
30223
|
}
|
|
29990
30224
|
result = result.replace(fullMatch, () => resolved);
|
|
29991
30225
|
twin = twin.replace(fullMatch, () => isSecret && resolved ? "***" : resolved);
|
|
30226
|
+
substitutions.push({
|
|
30227
|
+
token: fullMatch,
|
|
30228
|
+
value: resolved,
|
|
30229
|
+
secret: isSecret
|
|
30230
|
+
});
|
|
29992
30231
|
} catch (err) {
|
|
29993
30232
|
if (context?.abandonedResolutions === void 0) throw err;
|
|
29994
30233
|
if (isDeliberateResolutionRefusal(err)) throw err;
|
|
@@ -30001,13 +30240,16 @@ var IntrinsicFunctionResolver = class IntrinsicFunctionResolver {
|
|
|
30001
30240
|
}
|
|
30002
30241
|
return out;
|
|
30003
30242
|
}));
|
|
30243
|
+
complete = false;
|
|
30004
30244
|
continue;
|
|
30005
30245
|
}
|
|
30006
30246
|
}
|
|
30007
30247
|
if (context) this.rememberLogTwin(context, result, twin);
|
|
30008
30248
|
return {
|
|
30009
30249
|
result,
|
|
30010
|
-
twin
|
|
30250
|
+
twin,
|
|
30251
|
+
substitutions,
|
|
30252
|
+
complete
|
|
30011
30253
|
};
|
|
30012
30254
|
}
|
|
30013
30255
|
/**
|
|
@@ -30262,7 +30504,7 @@ async function disableInstanceApiTermination(client, instanceId, logger) {
|
|
|
30262
30504
|
}));
|
|
30263
30505
|
logger.debug(`Disabled DisableApiTermination on EC2 Instance ${instanceId} before deletion`);
|
|
30264
30506
|
} catch (flipError) {
|
|
30265
|
-
logger.debug(`Could not disable DisableApiTermination on ${instanceId}: ${
|
|
30507
|
+
logger.debug(`Could not disable DisableApiTermination on ${instanceId}: ${describeAwsFailure(flipError).detail}`);
|
|
30266
30508
|
}
|
|
30267
30509
|
}
|
|
30268
30510
|
/**
|
|
@@ -30574,7 +30816,7 @@ function getTopLevelWriteOnlyProperties(resourceType) {
|
|
|
30574
30816
|
if (cached) return cached;
|
|
30575
30817
|
const entry = fetchTopLevelWriteOnlyProperties(resourceType).catch((error) => {
|
|
30576
30818
|
writeOnlyPropertiesCache.delete(resourceType);
|
|
30577
|
-
const message =
|
|
30819
|
+
const message = describeAwsFailure(error).detail;
|
|
30578
30820
|
getLogger().child("WriteOnlyProperties").warn(`Failed to resolve write-only properties for ${resourceType} via cloudformation:DescribeType (${message}). Falling back to a minimal update patch — write-only properties (if any) may be dropped by the Cloud Control read-modify-write update. Grant cloudformation:DescribeType to enable write-only property re-inclusion.`);
|
|
30579
30821
|
return /* @__PURE__ */ new Set();
|
|
30580
30822
|
});
|
|
@@ -30700,7 +30942,7 @@ function getTopLevelReadOnlyProperties(resourceType) {
|
|
|
30700
30942
|
if (cached) return cached;
|
|
30701
30943
|
const entry = fetchTopLevelReadOnlyProperties(resourceType).catch((error) => {
|
|
30702
30944
|
readOnlyPropertiesCache.delete(resourceType);
|
|
30703
|
-
const message =
|
|
30945
|
+
const message = describeAwsFailure(error).detail;
|
|
30704
30946
|
getLogger().child("ReadOnlyProperties").debug(`Failed to resolve read-only properties for ${displaySafe(resourceType, { asciiOnly: true })} via cloudformation:DescribeType (${message}).`);
|
|
30705
30947
|
});
|
|
30706
30948
|
readOnlyPropertiesCache.set(resourceType, entry);
|
|
@@ -31918,7 +32160,7 @@ var CloudControlProvider = class {
|
|
|
31918
32160
|
const indeterminateGuard = await this.confirmDeleteTargetIdentity(logicalId, resourceType, physicalId, context);
|
|
31919
32161
|
if (context?.removeProtection === true && resourceType === "AWS::AutoScaling::AutoScalingGroup") {
|
|
31920
32162
|
this.logger.debug(`Delegating protected AutoScalingGroup ${logicalId} delete to the SDK ASGProvider (Cloud Control cannot force-delete a protected ASG)`);
|
|
31921
|
-
const { ASGProvider } = await import("./asg-provider-
|
|
32163
|
+
const { ASGProvider } = await import("./asg-provider-BOYln2Tw.js").then((n) => n.n);
|
|
31922
32164
|
const asgProvider = new ASGProvider();
|
|
31923
32165
|
return withIndeterminateGuard(await asgProvider.delete(logicalId, physicalId, resourceType, _properties, context), indeterminateGuard);
|
|
31924
32166
|
}
|
|
@@ -34585,7 +34827,7 @@ var CustomResourceProvider = class CustomResourceProvider {
|
|
|
34585
34827
|
}
|
|
34586
34828
|
this.logger.debug(`Successfully deleted custom resource ${logicalId}`);
|
|
34587
34829
|
} catch (error) {
|
|
34588
|
-
this.logger.warn(`Failed to delete custom resource ${logicalId}, but continuing: ${
|
|
34830
|
+
this.logger.warn(`Failed to delete custom resource ${logicalId}, but continuing: ${describeAwsFailure(error).detail}. The Delete handler did not complete, so anything this custom resource manages may still be LIVE — cdkd is KEEPING the state record and the run exits non-zero. ${CR_SKIP_NOT_A_RETRY_CAVEAT} ${DEPLOY_SKIP_CAVEAT}`);
|
|
34589
34831
|
return {
|
|
34590
34832
|
outcome: "skipped",
|
|
34591
34833
|
reason: CR_DELETE_INVOKE_FAILED_SKIP_REASON
|
|
@@ -34622,7 +34864,7 @@ var CustomResourceProvider = class CustomResourceProvider {
|
|
|
34622
34864
|
return false;
|
|
34623
34865
|
} catch (error) {
|
|
34624
34866
|
if (error.name === "ResourceNotFoundException") return true;
|
|
34625
|
-
this.logger.debug(`GetFunction pre-check for ${serviceToken} failed inconclusively (${
|
|
34867
|
+
this.logger.debug(`GetFunction pre-check for ${serviceToken} failed inconclusively (${describeAwsFailure(error).detail}); proceeding with the normal delete invoke`);
|
|
34626
34868
|
return false;
|
|
34627
34869
|
}
|
|
34628
34870
|
}
|
|
@@ -34699,7 +34941,7 @@ var CustomResourceProvider = class CustomResourceProvider {
|
|
|
34699
34941
|
} catch (error) {
|
|
34700
34942
|
if (delivered || preDeliveryRetries >= this.preDeliveryAuthzMaxRetries || !this.isTransientAuthzThrow(error)) throw error;
|
|
34701
34943
|
const delayMs = Math.min(250 * Math.pow(2, preDeliveryRetries), IAM_PROPAGATION_MAX_DELAY_MS);
|
|
34702
|
-
this.logger.warn(`Custom resource ${operation} for ${logicalId} hit a transient IAM-authorization error before the request was delivered (attempt ${attempt + 1}/${this.preDeliveryAuthzMaxRetries + 1}): ${this.truncateReason(
|
|
34944
|
+
this.logger.warn(`Custom resource ${operation} for ${logicalId} hit a transient IAM-authorization error before the request was delivered (attempt ${attempt + 1}/${this.preDeliveryAuthzMaxRetries + 1}): ${this.truncateReason(describeAwsFailure(error).detail)}. Retrying in ${delayMs / 1e3}s with a fresh response URL and RequestId.`);
|
|
34703
34945
|
if (invocation !== void 0) await this.cleanupResponseObject(invocation.responseKey);
|
|
34704
34946
|
preDeliveryRetries += 1;
|
|
34705
34947
|
await this.sleepInterruptibly(delayMs, watch);
|
|
@@ -34901,7 +35143,7 @@ var CustomResourceProvider = class CustomResourceProvider {
|
|
|
34901
35143
|
maxDelay: 5
|
|
34902
35144
|
}, { FunctionName: serviceToken });
|
|
34903
35145
|
} catch (error) {
|
|
34904
|
-
this.logger.debug(`Could not recycle backing function for ${logicalId} (${
|
|
35146
|
+
this.logger.debug(`Could not recycle backing function for ${logicalId} (${describeAwsFailure(error).detail}); retrying invoke without a forced cold start`);
|
|
34905
35147
|
}
|
|
34906
35148
|
}
|
|
34907
35149
|
/**
|
|
@@ -35250,7 +35492,7 @@ var CustomResourceProvider = class CustomResourceProvider {
|
|
|
35250
35492
|
Key: responseKey
|
|
35251
35493
|
}));
|
|
35252
35494
|
} catch (error) {
|
|
35253
|
-
this.logger.debug(`Failed to delete custom-resource response object s3://${displaySafe(bucket, { asciiOnly: true }) || "<unrenderable>"}/${displaySafe(responseKey)}; it remains as a current object. Underlying error: ${displaySafe(
|
|
35495
|
+
this.logger.debug(`Failed to delete custom-resource response object s3://${displaySafe(bucket, { asciiOnly: true }) || "<unrenderable>"}/${displaySafe(responseKey)}; it remains as a current object. Underlying error: ${displaySafe(describeAwsFailure(error).detail) || "<unrenderable>"}`);
|
|
35254
35496
|
}
|
|
35255
35497
|
await purgeNoncurrentKeyVersions(this.s3Client, bucket, [responseKey], {
|
|
35256
35498
|
logger: this.logger,
|
|
@@ -36029,7 +36271,7 @@ var IAMRoleProvider = class {
|
|
|
36029
36271
|
await this.iamClient.send(new DeleteRoleCommand({ RoleName: roleName }));
|
|
36030
36272
|
this.logger.debug(`Cleaned up partially-created IAM role ${logicalId} (${roleName}) after wiring failure`);
|
|
36031
36273
|
} catch (cleanupError) {
|
|
36032
|
-
this.logger.warn(`Failed to clean up partially-created IAM role ${logicalId} (${roleName}): ${
|
|
36274
|
+
this.logger.warn(`Failed to clean up partially-created IAM role ${logicalId} (${roleName}): ${describeAwsFailure(cleanupError).detail}. Manual deletion may be required before the next deploy: detach managed policies (aws iam list-attached-role-policies --role-name ${roleName} then aws iam detach-role-policy --role-name ${roleName} --policy-arn <arn>), delete inline policies (aws iam list-role-policies --role-name ${roleName} then aws iam delete-role-policy --role-name ${roleName} --policy-name <name>), then aws iam delete-role --role-name ${roleName}`);
|
|
36033
36275
|
}
|
|
36034
36276
|
throw innerError;
|
|
36035
36277
|
}
|
|
@@ -36066,8 +36308,8 @@ var IAMRoleProvider = class {
|
|
|
36066
36308
|
this.logger.warn(`Skipped deleting old role ${physicalId} during replacement: ${deleteResult.reason}. The old role may be orphaned and require manual cleanup.`);
|
|
36067
36309
|
}
|
|
36068
36310
|
} catch (error) {
|
|
36069
|
-
orphanReason = `old role ${physicalId} could not be deleted: ${
|
|
36070
|
-
this.logger.warn(`Failed to delete old role ${physicalId} during replacement: ${
|
|
36311
|
+
orphanReason = `old role ${physicalId} could not be deleted: ${safeStringify(error)}`;
|
|
36312
|
+
this.logger.warn(`Failed to delete old role ${physicalId} during replacement: ${safeStringify(error)}. The old role may be orphaned and require manual cleanup.`);
|
|
36071
36313
|
}
|
|
36072
36314
|
const base = {
|
|
36073
36315
|
physicalId: createResult.physicalId,
|
|
@@ -38336,7 +38578,7 @@ function makeCanonicalizePropertiesFn(registry) {
|
|
|
38336
38578
|
if (!registry.hasProvider(resourceType)) return properties;
|
|
38337
38579
|
return registry.getProvider(resourceType).canonicalizeDesiredProperties?.(resourceType, properties) ?? properties;
|
|
38338
38580
|
} catch (error) {
|
|
38339
|
-
logger.debug(`canonicalizeDesiredProperties failed for ${resourceType}: ${
|
|
38581
|
+
logger.debug(`canonicalizeDesiredProperties failed for ${resourceType}: ${describeAwsFailure(error).detail}`);
|
|
38340
38582
|
return properties;
|
|
38341
38583
|
}
|
|
38342
38584
|
};
|
|
@@ -44912,5 +45154,5 @@ var DeployEngine = class DeployEngine {
|
|
|
44912
45154
|
};
|
|
44913
45155
|
|
|
44914
45156
|
//#endregion
|
|
44915
|
-
export { secretBearing as $,
|
|
44916
|
-
//# sourceMappingURL=deploy-engine-
|
|
45157
|
+
export { secretBearing as $, isCdkdError as $i, scrubResourceRecord as $n, Synthesizer as $r, s3BucketArn as $t, extractDeploymentEventError as A, setAwsClients as Ai, repairMalformedResourcesForReadOnly as An, isCrossRegionRedirect as Ar, isImpossibleEmptyStoredAttribute as At, toCfnInteger as B, LocalStartServiceError as Bi, TEMPLATE_SOURCED_RULES as Bn, describeDockerExecFailure as Br, coerceCfnBoolean as Bt, buildFinalSnapshotIdentifier as C, AssemblyReader as Ci, refuseMalformedOutputs as Cn, loadPublishableAssetManifest as Cr, isTerminationProtectionPropagationError as Ct, refusesFinalSnapshot as D, AwsClients as Di, refuseMalformedState as Dn, assertAssetBucketRegion as Dr, cfnRefValueFromPhysicalId as Dt, isFinalSnapshotError as E, resolveBucketRegion as Ei, refuseMalformedResourcesForDestroy as En, BOOTSTRAP_MARKER_PREFIX as Er, carriesFetchableDynamicReference as Et, isStatefulRecreateTargetSync as F, DependencyError as Fi, DagBuilder as Fn, buildDenyExternalAccessPolicy as Fr, isSettledInstanceState as Ft, gray as G, ProvisioningError as Gi, identityKeyFor as Gn, partitionSensitiveEnv as Gr, readConfigString as Gt, formatResourceLine as H, MalformedProducerRecordRefusalError as Hi, createSecretMasker as Hn, dockerSpawnEnvWithSensitive as Hr, configBooleanRefusal as Ht, renderStatefulReason as I, DeployCancelledError as Ii, TemplateParser as In, describeAwsFailure as Ir, WAFv2WebACLProvider as It, yellow as J, StackHasActiveImportsError as Ji, maskSecretsInError as Jn, runDockerStreaming as Jr, requireConfigObject as Jt, green as K, ResourceTimeoutError as Ki, isSingleDynamicReferenceToken as Kn, redactDockerArgvValues as Kr, replayWarn as Kt, WARM_THROUGHPUT_MEMBERS as L, DynamicReferenceRegionAmbiguousError as Li, STATE_SOURCED_BASELINE_RULES as Ln, safeStringify as Lr, normalizeAwsTagsToCfn as Lt, planOrphanAdoption as M, CdkdError as Mi, findSilentDropProperties as Mn, readBootstrapMarkerBody as Mr, isUnboundTemplateParameter as Mt, MULTI_REGION_RECREATE_BLOCKED_TYPES as N, ConfigError as Ni, describeTypeWithThrottleRetry as Nn, validateAssetBucketName as Nr, parameterTypeMayLoseSecretIdentity as Nt, unsupportedFinalSnapshotError as O, getAwsClients as Oi, repairMalformedOutputsForReadOnly as On, ensureAssetStorage as Or, coerceParameterTypedValue as Ot, isStatefulRecreateTargetForReplace as P, CrossAccountSecretRefusalError as Pi, withRetry as Pn, validateContainerRepoName as Pr, refStateLookupFromResource as Pt, isExportAliasCollision as Q, formatError as Qi, redactSecretsForState as Qn, getDockerImageBySourceHash as Qr, withSharedDrainBudget as Qt, coerceWarmThroughput as R, IntrinsicResolutionRefusalError as Ri, STATE_SOURCED_CROSS_GENERATION_RULES as Rn, buildDockerImage as Rr, resolveExplicitPhysicalId as Rt, PRE_DELETE_SNAPSHOT_TYPES as S, derivePartitionAndUrlSuffix as Si, refuseMalformedNestedChildOutputs as Sn, createAssetRedirectResolver as Sr, disableInstanceApiTermination as St, createPreDeleteFinalSnapshot as T, clearBucketRegionCache as Ti, refuseMalformedResourcePropertiesForOrphan as Tn, AssetModeResolver as Tr, carriesDynamicReference as Tt, bold as U, NestedStackChildDirectDestroyError as Ui, dynamicReferenceTokens as Un, formatDockerLoginError as Ur, configIntegerRefusal as Ut, toFiniteNumber as V, LockError as Vi, carriesSecretMask as Vn, describeDockerFailure as Vr, coerceCfnInteger as Vt, cyan as W, PartialFailureError as Wi, errorCauseChain as Wn, getDockerCmd as Wr, configStringRefusal as Wt, collectPublishedOutputNames as X, StateError as Xi, recordMaskOnlyValue as Xn, stripControlChars as Xr, classifyReplaySecretRegion as Xt, collectDeclaredOutputNames as Y, StackTerminationProtectionError as Yi, maskSecretsInText as Yn, escapeRegExp$1 as Yr, requireConfigString as Yt, exportAliasCollisionScrubWarning as Z, SynthesisError as Zi, recoverMaskedOutput as Zn, AssetManifestLoader as Zr, producerRegionsFromState as Zt, isSecretBearingReferenceString as _, CUSTOM_RESOURCE_RESPONSE_OBJECT_DESCRIPTION as _i, malformedRenderedContainersWarning as _n, shouldRetainResource as _r, isWaitAbandonedError as _t, DeploymentEventsStore as a, isTransientServerError as aa, resolveCaptureObservedState as ai, applyCallerIdentityCredentials as an, forceQuitRecoveryClause as ar, clearOnUpdateRemoval as at, bindingSkippedOutputs as b, PARTITION_TABLE as bi, malformedStateRefusalMessage as bn, WorkGraph as br, deleteIndeterminateGuards as bt, replayFailedOperations as c, retryClassificationText as ca, resolveStateBucketWithDefaultAndSource as ci, INTRINSIC_KEYS as cn, CUSTOM_RESOURCE_RESPONSE_PREFIX as cr, createMaskedRetryLogger as ct, updatePartialReason as d, warnDeprecatedNoPrefixCliFlag as di, hasReadableResources as dn, hasReadableExportSet as dr, beginCommandInterruptScope as dt, normalizeAwsError as ea, synthesisStatusMessage as ei, s3BucketDomainName as en, LockManager as er, secretBearingStateKeyWarning as et, withResourceDeadline as f, CFN_TEMPLATE_BODY_LIMIT as fi, malformedExportNamesWarning as fn, importableOutputKeys as fr, endCommandInterruptScope as ft, bagHoldsSecretExpression as g, uploadCfnTemplate as gi, malformedOutputsWarning as gn, orphansCarriedFrom as gr, CloudControlProvider as gt, computeImplicitDeleteEdges as h, findLargeInlineResources as hi, malformedOutputsRefusalMessage as hn, orphansAfterRollback as hr, startInterruptWatch as ht, DeploymentEventsReader as i, isThrottlingError as ia, resolveAutoAssetStorage as ii, applyRoleArnIfSet as in, buildLockContentionMessage as ir, collectInlinePolicyNamesManagedBySiblings as it, makeSiblingClaimReader as j, AssetError as ji, findActionableSilentDrops as jn, parseBootstrapMarker as jr, isNamelessDynamicReferenceError as jt, makeCanonicalizePropertiesFn as k, resetAwsClients as ki, repairMalformedResourcePropertiesForReadOnly as kn, getBootstrapMarkerKey as kr, getAccountInfo as kt, replayRollback as l, __exportAll as la, resolveUseCdkBootstrapAssets as li, STATE_RESOURCES_MALFORMED as ln, DEFAULT_STATE_PREFIX as lr, maskDeep as lt, IMPLICIT_DELETE_DEPENDENCIES as m, MIGRATE_TMP_PREFIX as mi, malformedLocalOutputsWarning as mn, isReadableBag as mr, isInterruptedWaitError as mt, DEFAULT_RESOURCE_WARN_AFTER_MS as n, isMarkedNonRetryable as na, getLegacyStateBucketName as ni, s3BucketRegionalDomainName as nn, rebuildClientForBucketRegion as nr, getCurrentResourceSecrets as nt, planFailedOps as o, markNonRetryable as oa, resolveSkipPrefix as oi, callerEnvCredentials as on, formatLockExpiry as or, ProviderRegistry as ot, maskingRetryLogger as p, CFN_TEMPLATE_URL_LIMIT as pi, malformedExportSourceWarning as pn, importableOutputs as pr, interruptWatchListenerCount as pt, red as q, ResourceUpdateNotSupportedError as qi, markSameGenerationBag as qn, runDockerForeground as qr, requireConfigArray as qt, DeployEngine as r, isRetryableTransientError as ra, resolveApp as ri, s3BucketWebsiteUrl as rn, buildForceUnlockCommand as rr, IAMRoleProvider as rt, planRollback as s, markRedactedCause as sa, resolveStateBucketWithDefault as si, DiffCalculator as sn, shellQuote as sr, wouldReturnToSdkProvider as st, DEFAULT_RESOURCE_TIMEOUT_MS as t, withErrorHandling as ta, getDefaultStateBucketName as ti, s3BucketDualStackDomainName as tn, S3StateBackend as tr, secretSafeKeyDisplay as tt, updatePartialMessage as u, stateBucketExistenceConfirmed as ui, hasReadableOutputs as un, exportNamesCarriedFrom as ur, maskerOrIdentity as ut, keptWholeReasonText as v, decodeListingKey as vi, malformedResourcePropertiesWarning as vn, AssetPublisher as vr, slowCcOperationTimeoutMs as vt, ccRoutedFinalSnapshotError as w, processStackMessages as wi, refuseMalformedOutputsForDestroy as wn, rewriteTemplateAssetReferences as wr, IntrinsicFunctionResolver as wt, ATOMIC_FINAL_SNAPSHOT_TYPES as x, canonicalizeRegion as xi, producerRecordKey as xn, buildAssetRedirectMap as xr, deleteSkipReason as xt, mergeNoChangeOutputs as y, expectedOwnerParam as yi, malformedResourcesWarning as yn, stringifyValue as yr, UNSPECIFIED_SKIP_REASON as yt, isWarmThroughputDecrease as z, LocalInvokeBuildError as zi, STATE_SOURCED_READBACK_RULES as zn, describeDockerCapturedOutput as zr, assertRegionMatch as zt };
|
|
45158
|
+
//# sourceMappingURL=deploy-engine-CBzq85r6.js.map
|