@go-to-k/cdkd 0.302.1 → 0.302.3
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-BpRcm_UB.js → asg-provider-DCrwgSCZ.js} +27 -9
- package/dist/asg-provider-DCrwgSCZ.js.map +1 -0
- package/dist/cli.js +2 -2
- package/dist/{deploy-engine-CYVt2NQR.js → deploy-engine-D9SDE-Pj.js} +359 -4269
- package/dist/deploy-engine-D9SDE-Pj.js.map +1 -0
- package/dist/{iam-policy-targets-CmHNH1DY.js → iam-policy-targets-OtGPguLH.js} +3 -2
- package/dist/{iam-policy-targets-CmHNH1DY.js.map → iam-policy-targets-OtGPguLH.js.map} +1 -1
- package/dist/{iam-role-provider-R1GC6KcT.js → iam-role-provider-Q1sv3tF1.js} +9 -5
- package/dist/iam-role-provider-Q1sv3tF1.js.map +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -3
- package/dist/{neptune-provider-DzTl6-74.js → neptune-provider-DjVgEWGf.js} +121 -11
- package/dist/neptune-provider-DjVgEWGf.js.map +1 -0
- package/dist/{program-CvRs5pV_.js → program-DSbJoNKe.js} +559 -305
- package/dist/program-DSbJoNKe.js.map +1 -0
- package/dist/{provider-classes-B2_u4Fg0.js → provider-classes-CDtquwkU.js} +673 -131
- package/dist/provider-classes-CDtquwkU.js.map +1 -0
- package/dist/{rds-provider-CmKbYAvr.js → rds-provider-ByCpdpUq.js} +208 -42
- package/dist/rds-provider-ByCpdpUq.js.map +1 -0
- package/dist/secret-redaction-BHWS-PZK.js +3937 -0
- package/dist/secret-redaction-BHWS-PZK.js.map +1 -0
- package/dist/{version-CaejipV3.js → version-DDpKuzTw.js} +2 -2
- package/dist/{version-CaejipV3.js.map → version-DDpKuzTw.js.map} +1 -1
- package/package.json +2 -2
- package/dist/asg-provider-BpRcm_UB.js.map +0 -1
- package/dist/deploy-engine-CYVt2NQR.js.map +0 -1
- package/dist/iam-role-provider-R1GC6KcT.js.map +0 -1
- package/dist/neptune-provider-DzTl6-74.js.map +0 -1
- package/dist/program-CvRs5pV_.js.map +0 -1
- package/dist/provider-classes-B2_u4Fg0.js.map +0 -1
- package/dist/rds-provider-CmKbYAvr.js.map +0 -1
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { r as getAwsClients, s as __exportAll } from "./aws-clients-B_CEQGE1.js";
|
|
2
|
-
import { A as isNameGeneration, B as SECRET_REF_MAX_CODE_POINTS, D as getCurrentStackInstanceId, E as getCurrentSkipPrefix, F as withSkipPrefix, G as displayAwsMessage, H as UNRENDERABLE, I as withStackScope, J as displayStackName, K as displayIdent, L as withStackScopeBeforeStateRead, N as stackInstanceNameSuffix, O as getCurrentStackName, P as withNameGeneration, Q as safeMsg, R as withoutGeneratedFallbackName, S as fallbackNamePropertyFor, T as generatedNameFor, U as asIsMessage, V as STACK_REF_MAX_CODE_POINTS, Y as isPasteableIdent, Z as plainIdentOr, a as safeStringify$1, c as isStdoutReservedForPayload, et as terminalSafe, f as currentLogLineMasker, j as looksLikeCdkdGeneratedName, m as getLiveRenderer, n as describeAwsFailure, p as installLogLineMaskerSource, q as displaySafe, s as getLogger, t as VERBOSE_POINTER, tt as truncateCodePoints, v as applyDefaultNameForFallback, w as generateResourceNameWithFallback, x as explicitNamePropertyFor, y as currentNameGeneration
|
|
3
|
-
import { $ as protectedReplacementAdvice, $n as isReplayedNameCollisionFrom, $t as ambientCredentialConfig, A as isQuotableImportValue, At as isAuxiliaryMarkOf, B as isTerminalDeleteFailure, Bn as plainOrDescribed, Bt as formatLockOperation, Ct as RETRY_AUXILIARY_OWNER, Dt as createdResourceIdentityBeforeFailure, E as assertRegionMatch, Et as createdBeforeFailure, F as resolveExplicitPhysicalId, Fn as commandHole, Ft as UNREPRODUCIBLE_LOCK_CLAUSE, G as runDeleteAttempt, Gt as DEFAULT_STATE_PREFIX, H as observeThenDisableProtection, Hn as shellBoundedDisplay, Ht as recoveryCommandFlags, It as buildForceUnlockCommand, J as DELETION_PROTECTION_DOC_POINTER, Jn as hasReplayMayCollide, Kt as injectiveKey, L as ProtectionFlipRegistry, Ln as isInertUnquoted, M as quotedRemedyLogicalId, Mn as SHELL_ACTIVE, Mt as markCreatedBeforeFailure, N as refusalTypeShown, Nn as SHELL_ACTIVE_WHY, On as isSoftAbort, Ot as hasCreatedBeforeFailure, Pn as UNSHOWABLE_VALUE, Pt as replayMadeAnotherResource, Q as pasteableAwsCommand, Qn as isRecreateRetryableError, Qt as ambientClientDefaults, R as compensateProtectionFlip, Rn as pasteableCommand, St as withDerivedNameMasks, T as RESOURCE_NOT_FOUND, Tn as SynthesisError, U as protectionFlipKey, Un as shellQuote, Ut as sanitizeRecoveryValue, Vn as quotedOrDescribed, Vt as formatLockOwner, Wn as withheldTargetClause, Wt as CUSTOM_RESOURCE_RESPONSE_PREFIX, Xn as isNameCollisionErrorFrom, Yt as producerRecordKey, Zn as isNameCooldownError, Zt as withPasteableAwsProfile, _r as isThrottlingError, _t as createMaskedLogSinks, at as startInterruptWatch, bn as ResourceTimeoutError, br as wrapMaskedAwsError, bt as maskDeep, cr as isAmbiguousCcHandlerErrorCode, ct as canonicalizeRoute53QueryName, d as prepareRemovalForUpdate, dn as IntrinsicResolutionRefusalError, dr as isIamPropagationError, en as clientDefaultsFor, f as removalWarning, fr as isRetryableTransientError, ft as logicalIdShown, gn as MalformedProducerRecordRefusalError, gr as isMarkedNonRetryable, gt as stateOrphanRecordRemedy, hn as MacroExpansionError, ht as segmentAfterAnchor, i as holdsSecretDerivedEntry, in as CdkdError, ir as stripControlChars, it as isInterruptedWaitError, j as normalizeAwsTagsToCfn, jt as markAuxiliaryFailure, kn as normalizeAwsError, kt as isAuxiliaryFailure, l as withUnchangedSecretPrincipalLists, ln as DeploymentNotApprovedError, lr as isAmbiguousOutcomeError, m as withoutInjectedRemovals, mn as LockError, mr as retryClassificationText, mt as resourceTypeShown, nn as AccountIdUnavailableError, nr as relayedNameCollision, on as CrossAccountSecretRefusalError, ot as ElapsedBudgetRegistry, pr as isTransientServerError, qn as isUpdateUnsupportedError, rn as AssetError, rr as escapeRegExp$
|
|
2
|
+
import { A as isNameGeneration, B as SECRET_REF_MAX_CODE_POINTS, D as getCurrentStackInstanceId, E as getCurrentSkipPrefix, F as withSkipPrefix, G as displayAwsMessage, H as UNRENDERABLE, I as withStackScope, J as displayStackName, K as displayIdent, L as withStackScopeBeforeStateRead, N as stackInstanceNameSuffix, O as getCurrentStackName, P as withNameGeneration, Q as safeMsg, R as withoutGeneratedFallbackName, S as fallbackNamePropertyFor, T as generatedNameFor, U as asIsMessage, V as STACK_REF_MAX_CODE_POINTS, Y as isPasteableIdent, Z as plainIdentOr, a as safeStringify$1, c as isStdoutReservedForPayload, et as terminalSafe, f as currentLogLineMasker, j as looksLikeCdkdGeneratedName, m as getLiveRenderer, n as describeAwsFailure, p as installLogLineMaskerSource, q as displaySafe, s as getLogger, t as VERBOSE_POINTER, tt as truncateCodePoints, v as applyDefaultNameForFallback, w as generateResourceNameWithFallback, x as explicitNamePropertyFor, y as currentNameGeneration } from "./aws-failure-text-e_ddrDDo.js";
|
|
3
|
+
import { $ as protectedReplacementAdvice, $n as isReplayedNameCollisionFrom, $t as ambientCredentialConfig, A as isQuotableImportValue, At as isAuxiliaryMarkOf, B as isTerminalDeleteFailure, Bn as plainOrDescribed, Bt as formatLockOperation, Ct as RETRY_AUXILIARY_OWNER, Dt as createdResourceIdentityBeforeFailure, E as assertRegionMatch, Et as createdBeforeFailure, F as resolveExplicitPhysicalId, Fn as commandHole, Ft as UNREPRODUCIBLE_LOCK_CLAUSE, G as runDeleteAttempt, Gt as DEFAULT_STATE_PREFIX, H as observeThenDisableProtection, Hn as shellBoundedDisplay, Ht as recoveryCommandFlags, It as buildForceUnlockCommand, J as DELETION_PROTECTION_DOC_POINTER, Jn as hasReplayMayCollide, Kt as injectiveKey, L as ProtectionFlipRegistry, Ln as isInertUnquoted, M as quotedRemedyLogicalId, Mn as SHELL_ACTIVE, Mt as markCreatedBeforeFailure, N as refusalTypeShown, Nn as SHELL_ACTIVE_WHY, On as isSoftAbort, Ot as hasCreatedBeforeFailure, Pn as UNSHOWABLE_VALUE, Pt as replayMadeAnotherResource, Q as pasteableAwsCommand, Qn as isRecreateRetryableError, Qt as ambientClientDefaults, R as compensateProtectionFlip, Rn as pasteableCommand, St as withDerivedNameMasks, T as RESOURCE_NOT_FOUND, Tn as SynthesisError, U as protectionFlipKey, Un as shellQuote, Ut as sanitizeRecoveryValue, Vn as quotedOrDescribed, Vt as formatLockOwner, Wn as withheldTargetClause, Wt as CUSTOM_RESOURCE_RESPONSE_PREFIX, Xn as isNameCollisionErrorFrom, Yt as producerRecordKey, Zn as isNameCooldownError, Zt as withPasteableAwsProfile, _r as isThrottlingError, _t as createMaskedLogSinks, at as startInterruptWatch, bn as ResourceTimeoutError, br as wrapMaskedAwsError, bt as maskDeep, cr as isAmbiguousCcHandlerErrorCode, ct as canonicalizeRoute53QueryName, d as prepareRemovalForUpdate, dn as IntrinsicResolutionRefusalError, dr as isIamPropagationError, en as clientDefaultsFor, f as removalWarning, fr as isRetryableTransientError, ft as logicalIdShown, gn as MalformedProducerRecordRefusalError, gr as isMarkedNonRetryable, gt as stateOrphanRecordRemedy, hn as MacroExpansionError, ht as segmentAfterAnchor, i as holdsSecretDerivedEntry, in as CdkdError, ir as stripControlChars, it as isInterruptedWaitError, j as normalizeAwsTagsToCfn, jt as markAuxiliaryFailure, kn as normalizeAwsError, kt as isAuxiliaryFailure, l as withUnchangedSecretPrincipalLists, ln as DeploymentNotApprovedError, lr as isAmbiguousOutcomeError, m as withoutInjectedRemovals, mn as LockError, mr as retryClassificationText, mt as resourceTypeShown, nn as AccountIdUnavailableError, nr as relayedNameCollision, on as CrossAccountSecretRefusalError, ot as ElapsedBudgetRegistry, pr as isTransientServerError, qn as isUpdateUnsupportedError, rn as AssetError, rr as escapeRegExp$2, sn as DependencyError, sr as formatRetryClassificationSignals, st as monotonicNowMs, tn as credentialFingerprint, tr as markReplayMayCollide, un as DynamicReferenceRegionAmbiguousError, ut as compositeIdSeparatorRefusal, vr as markNonRetryable, vt as createMaskedRetryLogger, w as withoutServerErrorRetries, wn as StateError, wt as carryCreatedBeforeFailure, xn as ResourceUpdateNotSupportedError, xt as maskerOrIdentity, yn as ProvisioningError, yr as markRedactedCause, yt as isSecretDerivedValue, z as deleteWithProtectionCompensation, zn as physicalIdShownBesideCommand, zt as formatLockExpiry } from "./iam-policy-targets-OtGPguLH.js";
|
|
4
4
|
import { a as setAssumedRoleCredentials, i as getPreAssumeEnvCredentials, n as awsClientDefaults, o as setPreAssumeEnvCredentials, r as getAssumedRoleCredentials, s as ambientRegion, t as SECOND_ROLE_PUBLISH_REFUSAL } from "./aws-client-defaults-DBXBcg0J.js";
|
|
5
|
-
import { t as
|
|
5
|
+
import { $ as recordLogOnlyParameterValue, $t as crossStackSourceKey, A as recordIntrinsicLeafResolutionAs, At as inheritedParameterExpression, B as passProvenanceFor, Bt as standsForInheritedSecret, C as carryRedactionMarks, Ct as DYNAMIC_REFERENCE_TOKEN_SCAN, D as markSameGenerationBag, E as markLeafCertifiedBag, En as maskMatchSpans, F as redactForState, Ft as recordInheritedPseudoParameters, G as carryLogOnlyValues, Gt as freshNoEchoLeafPositions, H as recordReferenceProvenanceEntry, Ht as withdrawRenderedParameterSpelling, I as foldRecording, It as recordNestedStackParameterExpressions, J as hasLogOnlyValues, Jt as physicalNameCopiesOf, K as carryLogOnlyValuesCarriedBy, Kt as recordRecoverableMaskedOutput, L as openRecordingScope, Lt as redactInheritedParameterValue, M as resolvedPlaintextOf, Mt as inheritedRenderedToken, N as mixedLiteralAnswered, Nt as recordInheritedParameterRead, O as mergeResolvedPairs, P as withLegacyMixedScan, Pt as recordInheritedParameterValue, Q as printingCorpusOf, Qt as recordTakenIfBranch, R as recordSecretResolution, Rt as rereadParameterExpression, Sn as withoutNoEchoParameterEntries, St as spanNamesResolvableService, T as isSameGenerationBag, Tn as isSingleDynamicReferenceToken, Tt as dynamicReferenceTokens, U as recordReferenceResolution, Ut as carriesFreshNoEchoValue, V as passReadVersionsFor, Vt as templateRereadsAccountId, Wt as embedsFreshNoEchoValue, X as literalSplitDelimitersOf, Xt as recordPhysicalNameCopy, Y as hasMaskableValues, Zt as recordDroppedArrayElements, _ as recordPassedNoEchoParameters, _t as replaceWholeLeaves, a as maskReadbackAtCoordinates, an as freshNoEchoValuesOf, at as errorCauseChain, b as valueAtCoordinate, bn as recordProvenPublicExpression, bt as withPhysicalNameCopies, c as noEchoComparison, cn as isScopedSecretVerdict, ct as maskSecretsInText, dn as noEchoParameterPlaintextsOf, dt as legacyLeavesWithoutMask, en as recordCrossStackExpression, et as recordLogOnlySplitFragments, f as noEchoParameterNodesAt, fn as pinScopedSecretVerdict, ft as legacyReferenceLeavesOnly, gt as replaceEmbeddedPhysicalNameRewrites, h as readbackPathFor, hn as recordFreshNoEchoValuesIn, ht as repairPhysicalNameCopyLeaves, i as maskAtCoordinates, in as contradictProvenPublicExpression, it as createSecretMasker, j as redactionClaimOf, jt as inheritedPseudoValue, k as recordIntrinsicLeafResolution, kt as inheritNestedStackParameterAssociations, l as noEchoCoordinatesOf, ln as isSecretExpressionByVerdictOrSpelling, lt as differingStringLeaves, mn as recordDerivedMaskOnlyValue, mt as repairEmbeddedPhysicalNamesTowards, n as canonicalJson$3, nn as carriesSecretMask, nt as shareLogOnlyValues, o as maskWholeValue, on as isMaskOnlyPlaintext, ot as maskRecordedSecretsInText, p as noEchoParametersReadBy, pt as overlapRuleAnswered, q as createUnionSecretMasker, qt as recoverMaskedOutput, r as isMarkedCoordinate, rn as carryFreshNoEchoMark, rt as unionOfSecretBags, s as maskedLeafCoordinatesOf, sn as isNoEchoParameterPlaintext, st as maskSecretsInError, t as canonicalCoordinates, tn as splitGetAttStringForm, tt as recordLogOnlyValue, u as noEchoLeavesOf, un as markNoEchoParameterClass, ut as embeddedPhysicalNameRewrites, v as recordedNoEchoValuesOf, vn as recordNoEchoAttributeValues, vt as scrubResourceRecord, w as intrinsicLeafResolutionOf, wn as isDynamicReferenceString, wt as arrayPairsWhateverDrops, x as witnessNormalize, xn as wholeStringLeavesOf, xt as withoutPhysicalNameCopies, y as replaceAtCoordinates, yn as recordNoEchoParameterFreshValue, yt as withLegacyOverlapScan, z as hasPassProvenance, zt as splitOutsideDynamicReferences } from "./secret-redaction-BHWS-PZK.js";
|
|
6
|
+
import { t as getCdkdVersion } from "./version-DDpKuzTw.js";
|
|
6
7
|
import { createHash, randomUUID } from "node:crypto";
|
|
7
8
|
import { AsyncLocalStorage } from "node:async_hooks";
|
|
8
9
|
import { CreateBucketCommand, DeleteObjectCommand, DeleteObjectsCommand, GetBucketLifecycleConfigurationCommand, GetBucketLocationCommand, GetBucketReplicationCommand, GetObjectCommand, HeadBucketCommand, HeadObjectCommand, ListObjectVersionsCommand, ListObjectsV2Command, NoSuchKey, PutBucketEncryptionCommand, PutBucketLifecycleConfigurationCommand, PutBucketPolicyCommand, PutObjectCommand, PutPublicAccessBlockCommand, S3Client, S3ServiceException } from "@aws-sdk/client-s3";
|
|
@@ -424,7 +425,7 @@ function defineOwnKey(target, key, value) {
|
|
|
424
425
|
configurable: true
|
|
425
426
|
});
|
|
426
427
|
}
|
|
427
|
-
function hasPlainPrototype
|
|
428
|
+
function hasPlainPrototype(value) {
|
|
428
429
|
const proto = Object.getPrototypeOf(value);
|
|
429
430
|
return proto === Object.prototype || proto === null;
|
|
430
431
|
}
|
|
@@ -3247,7 +3248,7 @@ function trailingShortFlagOfCluster(arg) {
|
|
|
3247
3248
|
for (const flag of ARGV_VALUE_BEARING_FLAGS) if (flag.length === 2 && flag.startsWith("-") && flag[1] !== "-" && flag[1] === last) return flag;
|
|
3248
3249
|
}
|
|
3249
3250
|
const ARGV_VALUE_TOKEN_RE = (() => {
|
|
3250
|
-
const alternation = [...ARGV_VALUE_BEARING_FLAGS].sort((a, b) => b.length - a.length || a.localeCompare(b)).map(escapeRegExp$
|
|
3251
|
+
const alternation = [...ARGV_VALUE_BEARING_FLAGS].sort((a, b) => b.length - a.length || a.localeCompare(b)).map(escapeRegExp$2).join("|");
|
|
3251
3252
|
if (alternation.length === 0 || [...ARGV_VALUE_BEARING_FLAGS].some((f) => f.trim() === "")) throw new Error("ARGV_VALUE_BEARING_FLAGS is empty or holds an empty flag: the token scan would match every k=v");
|
|
3252
3253
|
return new RegExp(`(^|\\s)(${alternation})(\\s+|=)([^\\s=]*)=\\S*`, "g");
|
|
3253
3254
|
})();
|
|
@@ -4265,10 +4266,10 @@ function flattenAssetPlaceholders(value, accountId, region, partition = "aws") {
|
|
|
4265
4266
|
return value.replace(/\$\{AWS::AccountId\}/g, accountId).replace(/\$\{AWS::Region\}/g, region).replace(/\$\{AWS::Partition\}/g, partition);
|
|
4266
4267
|
}
|
|
4267
4268
|
function isDefaultBootstrapBucketName(name, accountId, region) {
|
|
4268
|
-
return new RegExp(`^cdk-[a-z0-9]+-assets-${accountId}-${escapeRegExp$
|
|
4269
|
+
return new RegExp(`^cdk-[a-z0-9]+-assets-${accountId}-${escapeRegExp$2(region)}$`).test(name);
|
|
4269
4270
|
}
|
|
4270
4271
|
function isDefaultBootstrapRepoName(name, accountId, region) {
|
|
4271
|
-
return new RegExp(`^cdk-[a-z0-9]+-container-assets-${accountId}-${escapeRegExp$
|
|
4272
|
+
return new RegExp(`^cdk-[a-z0-9]+-container-assets-${accountId}-${escapeRegExp$2(region)}$`).test(name);
|
|
4272
4273
|
}
|
|
4273
4274
|
function buildAssetRedirectMap(manifest, marker, accountId, region, partition = "aws") {
|
|
4274
4275
|
const buckets = /* @__PURE__ */ new Map();
|
|
@@ -4277,7 +4278,7 @@ function buildAssetRedirectMap(manifest, marker, accountId, region, partition =
|
|
|
4277
4278
|
const addForms = (rawName, flattened, target) => {
|
|
4278
4279
|
sources.set(flattened, target);
|
|
4279
4280
|
if (rawName !== flattened) sources.set(rawName, target);
|
|
4280
|
-
const suffixRe = new RegExp(`-${accountId}-${escapeRegExp$
|
|
4281
|
+
const suffixRe = new RegExp(`-${accountId}-${escapeRegExp$2(region)}$`);
|
|
4281
4282
|
for (const suffix of [
|
|
4282
4283
|
"-${AWS::AccountId}-${AWS::Region}",
|
|
4283
4284
|
`-\${AWS::AccountId}-${region}`,
|
|
@@ -4318,7 +4319,7 @@ function buildAssetRedirectMap(manifest, marker, accountId, region, partition =
|
|
|
4318
4319
|
};
|
|
4319
4320
|
}
|
|
4320
4321
|
function buildBoundaryRegex(source) {
|
|
4321
|
-
return new RegExp(`(?<![A-Za-z0-9_.-])${escapeRegExp$
|
|
4322
|
+
return new RegExp(`(?<![A-Za-z0-9_.-])${escapeRegExp$2(source)}(?![A-Za-z0-9_-])`, "g");
|
|
4322
4323
|
}
|
|
4323
4324
|
function rewriteString(value, map, counter) {
|
|
4324
4325
|
let result = value;
|
|
@@ -7104,4294 +7105,361 @@ var LockManager = class {
|
|
|
7104
7105
|
const why = Number.isFinite(existing.info.expiresAt) ? "A live cdkd process renews its lock well inside the TTL, so this normally means the previous owner crashed or was suspended" : `Its expiresAt is not a finite number, which cdkd treats as already expired`;
|
|
7105
7106
|
this.logger.warn(`Took over an EXPIRED lock for stack: ${safeSegment(stackName)} (${safeSegment(region)}, owner: ${formatLockOwner(existing.info.owner)}, ${formatLockExpiry(existing.info.expiresAt)}). ${why} -- if it is in fact still running, both processes are now writing to the same stack.`);
|
|
7106
7107
|
const abandonedAt = abandonedRunHorizon(existing);
|
|
7107
|
-
if (abandonedAt !== void 0) this.abandonedLocks.set(key, abandonedAt);
|
|
7108
|
-
try {
|
|
7109
|
-
const retryEtag = await this.putLockObject(key, lockInfo);
|
|
7110
|
-
this.logger.debug(`Lock acquired for stack: ${stackRef(stackName, region)} after expired lock cleanup, owner: ${displaySafe(lockOwner)}`);
|
|
7111
|
-
this.trackHeldLock({
|
|
7112
|
-
stackName,
|
|
7113
|
-
region,
|
|
7114
|
-
key,
|
|
7115
|
-
info: lockInfo,
|
|
7116
|
-
etag: retryEtag
|
|
7117
|
-
});
|
|
7118
|
-
return true;
|
|
7119
|
-
} catch (retryError) {
|
|
7120
|
-
if (this.isForeignLockError(retryError)) {
|
|
7121
|
-
this.logger.debug(`Lock was acquired by another process during expired lock cleanup for stack: ${stackRef(stackName, region)}`);
|
|
7122
|
-
return false;
|
|
7123
|
-
}
|
|
7124
|
-
throw retryError;
|
|
7125
|
-
} finally {
|
|
7126
|
-
await this.purgeLockVersions(key, "reap");
|
|
7127
|
-
}
|
|
7128
|
-
}
|
|
7129
|
-
return false;
|
|
7130
|
-
}
|
|
7131
|
-
throw new LockError(`Failed to acquire lock for stack ${safeSegment(stackName)} (${safeSegment(region)}): ` + errorDetail$1(error), error instanceof Error ? error : void 0);
|
|
7132
|
-
}
|
|
7133
|
-
}
|
|
7134
|
-
async putLockObject(key, lockInfo, condition = { IfNoneMatch: "*" }) {
|
|
7135
|
-
const body = JSON.stringify(lockInfo, null, 2);
|
|
7136
|
-
return (await this.s3Client.send(new PutObjectCommand({
|
|
7137
|
-
Bucket: this.config.bucket,
|
|
7138
|
-
...await this.ownerParam(),
|
|
7139
|
-
Key: key,
|
|
7140
|
-
Body: body,
|
|
7141
|
-
ContentLength: Buffer.byteLength(body),
|
|
7142
|
-
ContentType: "application/json",
|
|
7143
|
-
...condition
|
|
7144
|
-
}))).ETag;
|
|
7145
|
-
}
|
|
7146
|
-
async getLockInfo(stackName, region) {
|
|
7147
|
-
const record = await this.getLockRecord(stackName, region);
|
|
7148
|
-
return record ? record.info : null;
|
|
7149
|
-
}
|
|
7150
|
-
async getLockRecord(stackName, region) {
|
|
7151
|
-
await this.ensureClientForBucket();
|
|
7152
|
-
const key = this.getLockKey(stackName, region);
|
|
7153
|
-
const shownStack = safeSegment(stackName);
|
|
7154
|
-
try {
|
|
7155
|
-
this.logger.debug(`Getting lock info for stack: ${shownStack}`);
|
|
7156
|
-
const response = await this.s3Client.send(new GetObjectCommand({
|
|
7157
|
-
Bucket: this.config.bucket,
|
|
7158
|
-
...await this.ownerParam(),
|
|
7159
|
-
Key: key
|
|
7160
|
-
}));
|
|
7161
|
-
if (!response.Body) throw new LockError(`Lock file for stack ${shownStack} has no body`);
|
|
7162
|
-
const bodyString = await response.Body.transformToString();
|
|
7163
|
-
const raw = JSON.parse(bodyString);
|
|
7164
|
-
if (raw === null || typeof raw !== "object" || Array.isArray(raw)) {
|
|
7165
|
-
this.logger.debug(`Lock file for stack ${shownStack} is not an object; treating as absent`);
|
|
7166
|
-
return null;
|
|
7167
|
-
}
|
|
7168
|
-
const parsed = raw;
|
|
7169
|
-
const lockInfo = {
|
|
7170
|
-
...parsed,
|
|
7171
|
-
owner: displaySafe(parsed.owner),
|
|
7172
|
-
...parsed.operation !== void 0 && { operation: displaySafe(parsed.operation) },
|
|
7173
|
-
expiresAt: nanIfUncoercible(parsed.expiresAt)
|
|
7174
|
-
};
|
|
7175
|
-
this.logger.debug(`Lock info for stack: ${shownStack}:`, lockInfo);
|
|
7176
|
-
return {
|
|
7177
|
-
info: lockInfo,
|
|
7178
|
-
etag: response.ETag,
|
|
7179
|
-
...response.LastModified instanceof Date && { lastModified: response.LastModified.getTime() }
|
|
7180
|
-
};
|
|
7181
|
-
} catch (error) {
|
|
7182
|
-
if (error instanceof NoSuchKey) {
|
|
7183
|
-
this.logger.debug(`No lock exists for stack: ${shownStack}`);
|
|
7184
|
-
return null;
|
|
7185
|
-
}
|
|
7186
|
-
if (error instanceof LockError) throw error;
|
|
7187
|
-
throw new LockError(`Failed to get lock info for stack ${shownStack}: ${errorDetail$1(error)}`, error instanceof Error ? error : void 0);
|
|
7188
|
-
}
|
|
7189
|
-
}
|
|
7190
|
-
async isLocked(stackName, region) {
|
|
7191
|
-
return await this.getLockInfo(stackName, region) !== null;
|
|
7192
|
-
}
|
|
7193
|
-
async releaseLock(stackName, region) {
|
|
7194
|
-
const key = this.getLockKey(stackName, region);
|
|
7195
|
-
const held = this.heldLocks.get(key);
|
|
7196
|
-
if (held?.releasing) {
|
|
7197
|
-
this.logger.debug(`Release already in flight (or done) for stack ${stackRef(stackName, region)}`);
|
|
7198
|
-
return held.releasing;
|
|
7199
|
-
}
|
|
7200
|
-
if (!held) return this.doReleaseLock(stackName, region, void 0);
|
|
7201
|
-
this.stopRenewal(held);
|
|
7202
|
-
const releasing = this.doReleaseLock(stackName, region, held);
|
|
7203
|
-
held.releasing = releasing;
|
|
7204
|
-
return releasing;
|
|
7205
|
-
}
|
|
7206
|
-
async doReleaseLock(stackName, region, held) {
|
|
7207
|
-
await this.ensureClientForBucket();
|
|
7208
|
-
if (held) await held.renewing?.catch(() => void 0);
|
|
7209
|
-
if (held?.lost) {
|
|
7210
|
-
this.logger.warn(`Not releasing the lock for stack ${stackRef(stackName, region)}: this process lost it while the operation was still running, so the lock present now belongs to someone else.`);
|
|
7211
|
-
return;
|
|
7212
|
-
}
|
|
7213
|
-
if (held && held.etag === void 0 && !await this.stillOursByBody(held)) {
|
|
7214
|
-
this.logger.warn(`Not releasing the lock for stack ${stackRef(stackName, region)}: this process never learned which version of the lock it wrote, and could not confirm the one present is its own. It expires on its own, or clear it with cdkd force-unlock.`);
|
|
7215
|
-
return;
|
|
7216
|
-
}
|
|
7217
|
-
try {
|
|
7218
|
-
this.logger.debug(`Releasing lock for stack: ${stackRef(stackName, region)}`);
|
|
7219
|
-
await this.deleteLock(stackName, region, held?.etag);
|
|
7220
|
-
this.logger.debug(`Lock released for stack: ${stackRef(stackName, region)}`);
|
|
7221
|
-
} catch (error) {
|
|
7222
|
-
if (this.isForeignLockError(error)) {
|
|
7223
|
-
this.logger.warn(held?.etagUncertain ? `Not releasing the lock for stack ${stackRef(stackName, region)}: this process could not confirm which version of the lock it last wrote, so it will not delete one it may not own. The lock clears on its own at ${new Date(held.info.expiresAt).toISOString()}, or immediately with cdkd force-unlock.` : `Not releasing the lock for stack ${stackRef(stackName, region)}: it has been replaced since this process acquired it, so another cdkd process now holds it. Leaving it in place.`);
|
|
7224
|
-
return;
|
|
7225
|
-
}
|
|
7226
|
-
if (this.isGoneError(error)) {
|
|
7227
|
-
this.logger.debug(`Lock for stack ${stackRef(stackName, region)} was already gone`);
|
|
7228
|
-
return;
|
|
7229
|
-
}
|
|
7230
|
-
if (held?.etag !== void 0 && this.isConditionUnsupportedError(error)) {
|
|
7231
|
-
if (!await this.stillOursByBody(held)) {
|
|
7232
|
-
this.logger.warn(`Not releasing the lock for stack ${stackRef(stackName, region)}: the conditional delete could not be evaluated here, and this process could not confirm the lock is still its own. Leaving it in place rather than risk deleting another process's lock. It expires on its own, or clear it with cdkd force-unlock. If this repeats, grant s3:GetObject on the lock key -- a delete conditioned on an ETag requires it.`);
|
|
7233
|
-
return;
|
|
7234
|
-
}
|
|
7235
|
-
this.logger.debug(`Conditional lock release for stack ${stackRef(stackName, region)} is not supported here (${errorDetail$1(error)}); retrying unconditionally`);
|
|
7236
|
-
try {
|
|
7237
|
-
await this.deleteLock(stackName, region);
|
|
7238
|
-
this.logger.debug(`Lock released for stack: ${stackRef(stackName, region)}`);
|
|
7239
|
-
return;
|
|
7240
|
-
} catch (fallbackError) {
|
|
7241
|
-
throw new LockError(`Failed to release lock for stack ${stackRef(stackName, region)}: ${errorDetail$1(fallbackError)}`, fallbackError instanceof Error ? fallbackError : void 0);
|
|
7242
|
-
}
|
|
7243
|
-
}
|
|
7244
|
-
throw new LockError(`Failed to release lock for stack ${stackRef(stackName, region)}: ${errorDetail$1(error)}`, error instanceof Error ? error : void 0);
|
|
7245
|
-
} finally {
|
|
7246
|
-
const purge = this.purgeLockVersions(this.getLockKey(stackName, region), "release");
|
|
7247
|
-
if (this.deferReleasePurge) {
|
|
7248
|
-
this.deferredPurges.add(purge);
|
|
7249
|
-
purge.finally(() => this.deferredPurges.delete(purge));
|
|
7250
|
-
} else await purge;
|
|
7251
|
-
}
|
|
7252
|
-
}
|
|
7253
|
-
async stillOursByBody(held) {
|
|
7254
|
-
let record;
|
|
7255
|
-
try {
|
|
7256
|
-
record = await this.getLockRecord(held.stackName, held.region);
|
|
7257
|
-
} catch {
|
|
7258
|
-
return false;
|
|
7259
|
-
}
|
|
7260
|
-
if (!record) return false;
|
|
7261
|
-
return this.sameLockIdentity(record.info, held.info);
|
|
7262
|
-
}
|
|
7263
|
-
sameLockIdentity(a, b) {
|
|
7264
|
-
return displaySafe(a.owner) === displaySafe(b.owner) && a.timestamp === b.timestamp;
|
|
7265
|
-
}
|
|
7266
|
-
abandonedRunEndedBy(stackName, region) {
|
|
7267
|
-
return this.abandonedLocks.get(this.getLockKey(stackName, region));
|
|
7268
|
-
}
|
|
7269
|
-
async forceReleaseLock(stackName, region, beforeDelete) {
|
|
7270
|
-
const where = stackRef(stackName, region);
|
|
7271
|
-
const record = await this.getLockRecord(stackName, region).catch(() => null);
|
|
7272
|
-
const lockInfo = record?.info ?? null;
|
|
7273
|
-
this.logger.warn(lockInfo ? `Force releasing lock for stack: ${where}, owner: ${formatLockOwner(lockInfo.owner)}${lockInfo.operation ? `, operation: ${formatLockOperation(lockInfo.operation)}` : ""}, expired: ${this.isLockExpired(lockInfo)}` : `Force releasing lock for stack: ${where} (no lock body read — absent or unparseable; deleting the object either way, since a lock cdkd cannot read is a lock nothing else can clear)`);
|
|
7274
|
-
const key = this.getLockKey(stackName, region);
|
|
7275
|
-
const held = this.heldLocks.get(key);
|
|
7276
|
-
if (held) {
|
|
7277
|
-
this.stopRenewal(held);
|
|
7278
|
-
held.releasing = Promise.resolve();
|
|
7279
|
-
}
|
|
7280
|
-
const horizon = record ? abandonedRunHorizon(record) : void 0;
|
|
7281
|
-
if (horizon !== void 0 && beforeDelete !== void 0) await beforeDelete(horizon).catch(() => void 0);
|
|
7282
|
-
try {
|
|
7283
|
-
await this.deleteLock(stackName, region);
|
|
7284
|
-
} finally {
|
|
7285
|
-
await this.purgeLockVersions(key, "reap");
|
|
7286
|
-
}
|
|
7287
|
-
return horizon;
|
|
7288
|
-
}
|
|
7289
|
-
async deleteLock(stackName, region, etag) {
|
|
7290
|
-
await this.ensureClientForBucket();
|
|
7291
|
-
const key = this.getLockKey(stackName, region);
|
|
7292
|
-
await this.s3Client.send(new DeleteObjectCommand({
|
|
7293
|
-
Bucket: this.config.bucket,
|
|
7294
|
-
...await this.ownerParam(),
|
|
7295
|
-
Key: key,
|
|
7296
|
-
...etag !== void 0 && { IfMatch: etag }
|
|
7297
|
-
}));
|
|
7298
|
-
}
|
|
7299
|
-
async purgeLockVersions(key, path) {
|
|
7300
|
-
const report = (message) => {
|
|
7301
|
-
try {
|
|
7302
|
-
if (path === "reap") this.logger.warn(message);
|
|
7303
|
-
else this.logger.debug(message);
|
|
7304
|
-
} catch {}
|
|
7305
|
-
};
|
|
7306
|
-
try {
|
|
7307
|
-
await this.ensureClientForBucket();
|
|
7308
|
-
await purgeNoncurrentKeyVersions(this.s3Client, this.config.bucket, [key], {
|
|
7309
|
-
requestFields: await this.ownerParam(),
|
|
7310
|
-
logger: { warn: report },
|
|
7311
|
-
objectDescription: LOCK_OBJECT_DESCRIPTION
|
|
7312
|
-
});
|
|
7313
|
-
} catch (error) {
|
|
7314
|
-
report(`Could not purge noncurrent versions of the lock key ${displayIdent(key, { maxCodePoints: STACK_REF_MAX_CODE_POINTS })} in bucket '${this.config.bucket}': the purge could not be started. Their previous versions survive and remain readable via GetObject with a VersionId (${LOCK_OBJECT_DESCRIPTION}). Grant s3:ListBucketVersions and s3:DeleteObjectVersion on the state bucket, or purge the key by hand. Underlying error: ${errorDetail$1(error)}`);
|
|
7315
|
-
}
|
|
7316
|
-
}
|
|
7317
|
-
trackHeldLock(args) {
|
|
7318
|
-
const previous = this.heldLocks.get(args.key);
|
|
7319
|
-
if (previous) this.stopRenewal(previous);
|
|
7320
|
-
const held = {
|
|
7321
|
-
stackName: args.stackName,
|
|
7322
|
-
region: args.region,
|
|
7323
|
-
key: args.key,
|
|
7324
|
-
info: args.info,
|
|
7325
|
-
etag: args.etag,
|
|
7326
|
-
timer: void 0,
|
|
7327
|
-
renewing: void 0,
|
|
7328
|
-
lost: false,
|
|
7329
|
-
releasing: void 0,
|
|
7330
|
-
etagUncertain: false,
|
|
7331
|
-
warnedPastExpiry: false
|
|
7332
|
-
};
|
|
7333
|
-
this.heldLocks.set(args.key, held);
|
|
7334
|
-
if (this.renewalDisabled) {
|
|
7335
|
-
this.logger.debug(`Lock renewal is disabled; the lock for ${stackRef(args.stackName, args.region)} will lapse at its TTL`);
|
|
7336
|
-
return;
|
|
7337
|
-
}
|
|
7338
|
-
if (args.etag === void 0) {
|
|
7339
|
-
this.logger.debug(`No ETag returned when acquiring the lock for ${stackRef(args.stackName, args.region)}; renewal disabled for this lock`);
|
|
7340
|
-
return;
|
|
7341
|
-
}
|
|
7342
|
-
this.startRenewal(held);
|
|
7343
|
-
}
|
|
7344
|
-
startRenewal(held) {
|
|
7345
|
-
const timer = setInterval(() => {
|
|
7346
|
-
this.renewLock(held);
|
|
7347
|
-
}, this.renewalIntervalMs);
|
|
7348
|
-
timer.unref?.();
|
|
7349
|
-
held.timer = timer;
|
|
7350
|
-
}
|
|
7351
|
-
stopRenewal(held) {
|
|
7352
|
-
if (held.timer !== void 0) {
|
|
7353
|
-
clearInterval(held.timer);
|
|
7354
|
-
held.timer = void 0;
|
|
7355
|
-
}
|
|
7356
|
-
}
|
|
7357
|
-
renewLock(held) {
|
|
7358
|
-
if (held.lost || held.renewing !== void 0 || held.etag === void 0) return Promise.resolve();
|
|
7359
|
-
const inFlight = this.doRenewLock(held).finally(() => {
|
|
7360
|
-
held.renewing = void 0;
|
|
7361
|
-
});
|
|
7362
|
-
held.renewing = inFlight;
|
|
7363
|
-
return inFlight;
|
|
7364
|
-
}
|
|
7365
|
-
async doRenewLock(held) {
|
|
7366
|
-
const currentEtag = held.etag;
|
|
7367
|
-
if (currentEtag === void 0) return;
|
|
7368
|
-
const renewed = {
|
|
7369
|
-
...held.info,
|
|
7370
|
-
expiresAt: Date.now() + this.ttlMs
|
|
7371
|
-
};
|
|
7372
|
-
try {
|
|
7373
|
-
const etag = await this.putLockObject(held.key, renewed, { IfMatch: currentEtag });
|
|
7374
|
-
if (etag === void 0) {
|
|
7375
|
-
if (await this.adoptOwnWrite(held, renewed)) return;
|
|
7376
|
-
held.info = renewed;
|
|
7377
|
-
held.etagUncertain = true;
|
|
7378
|
-
this.stopRenewal(held);
|
|
7379
|
-
this.logger.debug(`Lock renewal for ${stackRef(held.stackName, held.region)} returned no ETag and the object could not be re-read; stopping renewal and keeping the previous ETag`);
|
|
7380
|
-
return;
|
|
7381
|
-
}
|
|
7382
|
-
held.info = renewed;
|
|
7383
|
-
held.etag = etag;
|
|
7384
|
-
held.warnedPastExpiry = false;
|
|
7385
|
-
this.logger.debug(`Renewed lock for stack: ${stackRef(held.stackName, held.region)} until ${new Date(renewed.expiresAt).toISOString()}`);
|
|
7386
|
-
} catch (error) {
|
|
7387
|
-
if (this.isForeignLockError(error) && await this.adoptOwnWrite(held, renewed)) return;
|
|
7388
|
-
if (this.isNotOursError(error)) {
|
|
7389
|
-
held.lost = true;
|
|
7390
|
-
this.stopRenewal(held);
|
|
7391
|
-
this.logger.warn(`Lost the lock for stack ${stackRef(held.stackName, held.region)} while the operation was still running: the lock object has been replaced or removed. Another cdkd process may now be writing to this stack concurrently. This process will not delete the current lock when it finishes.`);
|
|
7392
|
-
return;
|
|
7393
|
-
}
|
|
7394
|
-
this.logger.debug(`Lock renewal for stack ${stackRef(held.stackName, held.region)} failed, will retry: ${errorDetail$1(error)}`);
|
|
7395
|
-
if (!held.warnedPastExpiry && Date.now() >= held.info.expiresAt) {
|
|
7396
|
-
held.warnedPastExpiry = true;
|
|
7397
|
-
this.logger.warn(`Lock renewal for stack ${stackRef(held.stackName, held.region)} has been failing long enough that the lock expired at ${new Date(held.info.expiresAt).toISOString()}. Another cdkd process can now take it while this operation is still running. Renewal keeps retrying.`);
|
|
7398
|
-
}
|
|
7399
|
-
}
|
|
7400
|
-
}
|
|
7401
|
-
async adoptOwnWrite(held, renewed) {
|
|
7402
|
-
const record = await this.getLockRecord(held.stackName, held.region).catch(() => null);
|
|
7403
|
-
if (!record || record.etag === void 0 || record.info.expiresAt !== renewed.expiresAt || !this.sameLockIdentity(record.info, renewed)) return false;
|
|
7404
|
-
held.info = renewed;
|
|
7405
|
-
held.etag = record.etag;
|
|
7406
|
-
held.warnedPastExpiry = false;
|
|
7407
|
-
this.logger.debug(`Lock renewal for stack ${stackRef(held.stackName, held.region)} reported a conflict, but the object holds this process's own renewal -- adopting it and continuing`);
|
|
7408
|
-
return true;
|
|
7409
|
-
}
|
|
7410
|
-
isForeignLockError(error) {
|
|
7411
|
-
return error instanceof S3ServiceException && (error.name === "PreconditionFailed" || error.$metadata.httpStatusCode === 412);
|
|
7412
|
-
}
|
|
7413
|
-
isGoneError(error) {
|
|
7414
|
-
if (error instanceof NoSuchKey) return true;
|
|
7415
|
-
if (!(error instanceof S3ServiceException)) return false;
|
|
7416
|
-
if (error.name === "NoSuchBucket") return false;
|
|
7417
|
-
return error.name === "NoSuchKey" || error.$metadata.httpStatusCode === 404;
|
|
7418
|
-
}
|
|
7419
|
-
isConditionUnsupportedError(error) {
|
|
7420
|
-
if (!(error instanceof S3ServiceException)) return false;
|
|
7421
|
-
const status = error.$metadata.httpStatusCode;
|
|
7422
|
-
return status === 403 || status === 501 || error.name === "AccessDenied" || error.name === "Forbidden" || error.name === "NotImplemented";
|
|
7423
|
-
}
|
|
7424
|
-
isNotOursError(error) {
|
|
7425
|
-
return this.isForeignLockError(error) || this.isGoneError(error);
|
|
7426
|
-
}
|
|
7427
|
-
async acquireLockWithRetry(stackName, region, owner, operation, maxRetries = 3, retryDelay = 2e3) {
|
|
7428
|
-
let attempts = 0;
|
|
7429
|
-
let releasedReacquires = 0;
|
|
7430
|
-
let lockInfo = null;
|
|
7431
|
-
for (let attempt = 0; attempt <= maxRetries; attempt++) {
|
|
7432
|
-
attempts++;
|
|
7433
|
-
if (await this.acquireLock(stackName, region, owner, operation)) return;
|
|
7434
|
-
lockInfo = await this.getLockInfo(stackName, region);
|
|
7435
|
-
if (!lockInfo && releasedReacquires < 3) {
|
|
7436
|
-
releasedReacquires++;
|
|
7437
|
-
this.logger.debug(safeMsg`Lock for stack ${stackRef(stackName, region)} could not be acquired, yet no readable lock was found -- most likely released in between; re-attempting (${releasedReacquires}/${3})`);
|
|
7438
|
-
attempt--;
|
|
7439
|
-
continue;
|
|
7440
|
-
}
|
|
7441
|
-
if (attempt < maxRetries) {
|
|
7442
|
-
const holder = lockInfo ? `is locked by ${formatLockOwner(lockInfo.owner)}${lockInfo.operation ? ` (operation: ${formatLockOperation(lockInfo.operation)})` : ""}. Lock ${formatLockExpiry(lockInfo.expiresAt)}.` : `could not be locked, and no readable lock was found.`;
|
|
7443
|
-
this.logger.info(`Stack ${safeSegment(stackName)} (${safeSegment(region)}) ${holder} Retrying in ${this.formatDuration(retryDelay)}... (attempt ${attempt + 1}/${maxRetries})`);
|
|
7444
|
-
await new Promise((resolve) => setTimeout(resolve, retryDelay));
|
|
7445
|
-
}
|
|
7446
|
-
}
|
|
7447
|
-
const expiry = lockInfo ? formatLockExpiry(lockInfo.expiresAt) : void 0;
|
|
7448
|
-
const forceUnlockCommand = buildForceUnlockCommand(stackName, region);
|
|
7449
|
-
const recovery = forceUnlockCommand ? `If you are certain no other process is active, run: ${forceUnlockCommand}` : `If you are certain no other process is active, ${UNREPRODUCIBLE_LOCK_CLAUSE.charAt(0).toLowerCase()}${UNREPRODUCIBLE_LOCK_CLAUSE.slice(1)}`;
|
|
7450
|
-
const safeStack = safeSegment(stackName);
|
|
7451
|
-
const safeRegion = safeSegment(region);
|
|
7452
|
-
throw new LockError(`Failed to acquire lock for stack ${safeStack} (${safeRegion}) after ${attempts} attempt${attempts === 1 ? "" : "s"}. ` + (lockInfo ? `Locked by: ${formatLockOwner(lockInfo.owner)}${lockInfo.operation ? `, operation: ${formatLockOperation(lockInfo.operation)}` : ""}, ${expiry}. ` + recovery : `No lock could be read after the last failed attempt, so it was most likely released just now: re-run the command. If this repeats, lock.json may hold a body that is not a readable lock. ${recovery}`));
|
|
7453
|
-
}
|
|
7454
|
-
};
|
|
7455
|
-
function nanIfUncoercible(value) {
|
|
7456
|
-
try {
|
|
7457
|
-
Number(value);
|
|
7458
|
-
return value;
|
|
7459
|
-
} catch {
|
|
7460
|
-
return NaN;
|
|
7461
|
-
}
|
|
7462
|
-
}
|
|
7463
|
-
|
|
7464
|
-
//#endregion
|
|
7465
|
-
//#region src/deployment/secret-redaction/rules.ts
|
|
7466
|
-
const MIN_NEEDLE_LENGTH = 4;
|
|
7467
|
-
function printingNeedles(values) {
|
|
7468
|
-
const out = /* @__PURE__ */ new Set();
|
|
7469
|
-
for (const value of values) {
|
|
7470
|
-
if (value.length < 4) continue;
|
|
7471
|
-
out.add(value);
|
|
7472
|
-
const flat = flattenedSpelling(value);
|
|
7473
|
-
if (flat !== void 0 && flat.trim().length >= 4) out.add(flat);
|
|
7474
|
-
}
|
|
7475
|
-
return [...out];
|
|
7476
|
-
}
|
|
7477
|
-
const FLATTENED_MEMO_CAP = 4096;
|
|
7478
|
-
const flattenedMemo = /* @__PURE__ */ new Map();
|
|
7479
|
-
function flattenedSpelling(value) {
|
|
7480
|
-
if (!SAFE_MSG_ALTERED_CHAR.test(value)) return void 0;
|
|
7481
|
-
let flat = flattenedMemo.get(value);
|
|
7482
|
-
if (flat === void 0) {
|
|
7483
|
-
flat = safeMsg`${value}`;
|
|
7484
|
-
if (flattenedMemo.size >= FLATTENED_MEMO_CAP) flattenedMemo.clear();
|
|
7485
|
-
flattenedMemo.set(value, flat);
|
|
7486
|
-
}
|
|
7487
|
-
return flat === value ? void 0 : flat;
|
|
7488
|
-
}
|
|
7489
|
-
function escapeRegExp$2(value) {
|
|
7490
|
-
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
7491
|
-
}
|
|
7492
|
-
function maskMatchSpans(text, needles, mask) {
|
|
7493
|
-
const spans = [];
|
|
7494
|
-
for (const needle of needles) for (let at = text.indexOf(needle); at !== -1; at = text.indexOf(needle, at + 1)) spans.push([at, at + needle.length]);
|
|
7495
|
-
if (spans.length === 0) return text;
|
|
7496
|
-
spans.sort((a, b) => a[0] - b[0] || b[1] - a[1]);
|
|
7497
|
-
let out = "";
|
|
7498
|
-
let cursor = 0;
|
|
7499
|
-
let [start, end] = spans[0];
|
|
7500
|
-
for (const [nextStart, nextEnd] of spans.slice(1)) {
|
|
7501
|
-
if (nextStart < end) {
|
|
7502
|
-
end = Math.max(end, nextEnd);
|
|
7503
|
-
continue;
|
|
7504
|
-
}
|
|
7505
|
-
out += text.slice(cursor, start) + mask;
|
|
7506
|
-
cursor = end;
|
|
7507
|
-
[start, end] = [nextStart, nextEnd];
|
|
7508
|
-
}
|
|
7509
|
-
return out + text.slice(cursor, start) + mask + text.slice(end);
|
|
7510
|
-
}
|
|
7511
|
-
function buildNeedleRegex(values) {
|
|
7512
|
-
const needles = Array.from(new Set(values)).filter((v) => v.length >= 4).sort((a, b) => b.length - a.length);
|
|
7513
|
-
if (needles.length === 0) return void 0;
|
|
7514
|
-
return new RegExp(needles.map(escapeRegExp$2).join("|"), "g");
|
|
7515
|
-
}
|
|
7516
|
-
const TEMPLATE_DERIVED_RULES = {
|
|
7517
|
-
descendArrays: true,
|
|
7518
|
-
trustAnyExpression: false,
|
|
7519
|
-
sourceIsSameGeneration: false
|
|
7520
|
-
};
|
|
7521
|
-
const TEMPLATE_SOURCED_RULES = {
|
|
7522
|
-
descendArrays: false,
|
|
7523
|
-
trustAnyExpression: false,
|
|
7524
|
-
sourceIsSameGeneration: false
|
|
7525
|
-
};
|
|
7526
|
-
const STATE_SOURCED_READBACK_RULES = {
|
|
7527
|
-
descendArrays: false,
|
|
7528
|
-
trustAnyExpression: true,
|
|
7529
|
-
sourceIsSameGeneration: true
|
|
7530
|
-
};
|
|
7531
|
-
const STATE_SOURCED_BASELINE_RULES = {
|
|
7532
|
-
descendArrays: false,
|
|
7533
|
-
trustAnyExpression: true,
|
|
7534
|
-
sourceIsSameGeneration: true,
|
|
7535
|
-
failClosedOnUncertifiedPositions: true
|
|
7536
|
-
};
|
|
7537
|
-
const STATE_SOURCED_CROSS_GENERATION_RULES = {
|
|
7538
|
-
descendArrays: false,
|
|
7539
|
-
trustAnyExpression: true,
|
|
7540
|
-
sourceIsSameGeneration: false
|
|
7541
|
-
};
|
|
7542
|
-
const STATE_DERIVED_RULES = {
|
|
7543
|
-
descendArrays: true,
|
|
7544
|
-
trustAnyExpression: true,
|
|
7545
|
-
sourceIsSameGeneration: true
|
|
7546
|
-
};
|
|
7547
|
-
function isDynamicReferenceString(value) {
|
|
7548
|
-
return typeof value === "string" && value.includes("{{resolve:");
|
|
7549
|
-
}
|
|
7550
|
-
const DYNAMIC_REFERENCE_INNER_CHAR = "[^}]";
|
|
7551
|
-
const DYNAMIC_REFERENCE_INNER = `${DYNAMIC_REFERENCE_INNER_CHAR}+`;
|
|
7552
|
-
const WHOLE_DYNAMIC_REFERENCE_PATTERN = new RegExp(`^\\{\\{resolve:${DYNAMIC_REFERENCE_INNER}\\}\\}$`);
|
|
7553
|
-
function isSingleDynamicReferenceToken(value) {
|
|
7554
|
-
return WHOLE_DYNAMIC_REFERENCE_PATTERN.test(value);
|
|
7555
|
-
}
|
|
7556
|
-
function isPlainObject$7(value) {
|
|
7557
|
-
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
7558
|
-
}
|
|
7559
|
-
|
|
7560
|
-
//#endregion
|
|
7561
|
-
//#region src/deployment/secret-redaction/mask-only.ts
|
|
7562
|
-
const recordedSecretExpressions = /* @__PURE__ */ new Set();
|
|
7563
|
-
const secretVerdictScopes = /* @__PURE__ */ new Map();
|
|
7564
|
-
function pinScopedSecretVerdict(scope, expression, secret) {
|
|
7565
|
-
const scopes = secretVerdictScopes.get(expression);
|
|
7566
|
-
if (secret) {
|
|
7567
|
-
if (scopes) scopes.add(scope);
|
|
7568
|
-
else secretVerdictScopes.set(expression, /* @__PURE__ */ new Set([scope]));
|
|
7569
|
-
recordedSecretExpressions.add(expression);
|
|
7570
|
-
return;
|
|
7571
|
-
}
|
|
7572
|
-
if (scopes?.delete(scope) && scopes.size === 0) secretVerdictScopes.delete(expression);
|
|
7573
|
-
recordedSecretExpressions.delete(expression);
|
|
7574
|
-
}
|
|
7575
|
-
function isScopedSecretVerdict(scope, expression) {
|
|
7576
|
-
return secretVerdictScopes.get(expression)?.has(scope) === true;
|
|
7577
|
-
}
|
|
7578
|
-
function isRecordedSecretExpression(expression) {
|
|
7579
|
-
return recordedSecretExpressions.has(expression);
|
|
7580
|
-
}
|
|
7581
|
-
const provenPublicExpressions = /* @__PURE__ */ new WeakMap();
|
|
7582
|
-
function proofsOf(bag) {
|
|
7583
|
-
let proofs = provenPublicExpressions.get(bag);
|
|
7584
|
-
if (!proofs) {
|
|
7585
|
-
proofs = /* @__PURE__ */ new Map();
|
|
7586
|
-
provenPublicExpressions.set(bag, proofs);
|
|
7587
|
-
}
|
|
7588
|
-
return proofs;
|
|
7589
|
-
}
|
|
7590
|
-
function recordProvenPublicExpression(bag, expression, value) {
|
|
7591
|
-
const proofs = proofsOf(bag);
|
|
7592
|
-
const prior = proofs.get(expression);
|
|
7593
|
-
if (prior === false) return;
|
|
7594
|
-
proofs.set(expression, prior === void 0 || prior === value ? value : false);
|
|
7595
|
-
}
|
|
7596
|
-
function sharePublicProofs(view, pass) {
|
|
7597
|
-
provenPublicExpressions.set(view, proofsOf(pass));
|
|
7598
|
-
}
|
|
7599
|
-
function carryPublicProofs(from, to) {
|
|
7600
|
-
for (const [expression, value] of provenPublicExpressions.get(from) ?? []) if (value === false) contradictProvenPublicExpression(to, expression);
|
|
7601
|
-
else recordProvenPublicExpression(to, expression, value);
|
|
7602
|
-
}
|
|
7603
|
-
function contradictProvenPublicExpression(bag, expression) {
|
|
7604
|
-
proofsOf(bag).set(expression, false);
|
|
7605
|
-
}
|
|
7606
|
-
function provenPublicValue(bag, expression) {
|
|
7607
|
-
const value = provenPublicExpressions.get(bag)?.get(expression);
|
|
7608
|
-
if (value === void 0 || value === false) return void 0;
|
|
7609
|
-
if (recordedSecretExpressions.has(expression)) return void 0;
|
|
7610
|
-
for (const recorded of bag.values()) if (recorded === expression) return void 0;
|
|
7611
|
-
return value;
|
|
7612
|
-
}
|
|
7613
|
-
function recordMaskOnlyValue(secrets, plaintext) {
|
|
7614
|
-
if (plaintext.length < 4) return;
|
|
7615
|
-
const existing = secrets.get(plaintext);
|
|
7616
|
-
if (existing !== void 0 && existing !== "***") return;
|
|
7617
|
-
secrets.set(plaintext, "***");
|
|
7618
|
-
}
|
|
7619
|
-
function isMaskOnlyPlaintext(secrets, plaintext) {
|
|
7620
|
-
return secrets.get(plaintext) === "***";
|
|
7621
|
-
}
|
|
7622
|
-
function recordMaskOnlyValuesIn(value, secrets, excluded) {
|
|
7623
|
-
const seen = /* @__PURE__ */ new Set();
|
|
7624
|
-
const walk = (node) => {
|
|
7625
|
-
if (typeof node === "string") {
|
|
7626
|
-
if (excluded?.has(node) === true) return;
|
|
7627
|
-
recordMaskOnlyValue(secrets, node);
|
|
7628
|
-
return;
|
|
7629
|
-
}
|
|
7630
|
-
if (node === null || typeof node !== "object") return;
|
|
7631
|
-
if (seen.has(node)) return;
|
|
7632
|
-
seen.add(node);
|
|
7633
|
-
if (Array.isArray(node)) {
|
|
7634
|
-
for (const item of node) walk(item);
|
|
7635
|
-
return;
|
|
7636
|
-
}
|
|
7637
|
-
for (const child of Object.values(node)) walk(child);
|
|
7638
|
-
};
|
|
7639
|
-
walk(value);
|
|
7640
|
-
}
|
|
7641
|
-
function wholeStringLeavesOf(value) {
|
|
7642
|
-
const leaves = /* @__PURE__ */ new Set();
|
|
7643
|
-
const seen = /* @__PURE__ */ new Set();
|
|
7644
|
-
const walk = (node) => {
|
|
7645
|
-
if (typeof node === "string") {
|
|
7646
|
-
leaves.add(node);
|
|
7647
|
-
return;
|
|
7648
|
-
}
|
|
7649
|
-
if (node === null || typeof node !== "object") return;
|
|
7650
|
-
if (seen.has(node)) return;
|
|
7651
|
-
seen.add(node);
|
|
7652
|
-
if (Array.isArray(node)) {
|
|
7653
|
-
for (const item of node) walk(item);
|
|
7654
|
-
return;
|
|
7655
|
-
}
|
|
7656
|
-
for (const child of Object.values(node)) walk(child);
|
|
7657
|
-
};
|
|
7658
|
-
walk(value);
|
|
7659
|
-
return leaves;
|
|
7660
|
-
}
|
|
7661
|
-
function recordNoEchoAttributeValues(result, secrets, ownProperties) {
|
|
7662
|
-
const attributes = result.attributes;
|
|
7663
|
-
if (attributes === void 0) return void 0;
|
|
7664
|
-
const excluded = ownProperties === void 0 ? void 0 : wholeStringLeavesOf(ownProperties);
|
|
7665
|
-
if (result.noEchoAttributes === true) {
|
|
7666
|
-
recordMaskOnlyValuesIn(attributes, secrets, excluded);
|
|
7667
|
-
return true;
|
|
7668
|
-
}
|
|
7669
|
-
const names = (result.noEchoAttributeNames ?? []).filter((name) => Object.hasOwn(attributes, name));
|
|
7670
|
-
if (names.length === 0) return void 0;
|
|
7671
|
-
for (const name of names) recordMaskOnlyValuesIn(attributes[name], secrets, excluded);
|
|
7672
|
-
return new Set(names);
|
|
7673
|
-
}
|
|
7674
|
-
function carriesSecretMask(value) {
|
|
7675
|
-
const seen = /* @__PURE__ */ new Set();
|
|
7676
|
-
const walk = (node) => {
|
|
7677
|
-
if (typeof node === "string") return node === "***";
|
|
7678
|
-
if (node === null || typeof node !== "object") return false;
|
|
7679
|
-
if (seen.has(node)) return false;
|
|
7680
|
-
seen.add(node);
|
|
7681
|
-
if (Array.isArray(node)) return node.some((item) => walk(item));
|
|
7682
|
-
return Object.values(node).some((child) => walk(child));
|
|
7683
|
-
};
|
|
7684
|
-
return walk(value);
|
|
7685
|
-
}
|
|
7686
|
-
const freshNoEchoValuesOf = /* @__PURE__ */ new WeakMap();
|
|
7687
|
-
function freshNoEchoSet(secrets) {
|
|
7688
|
-
return sideSetOf(freshNoEchoValuesOf, secrets);
|
|
7689
|
-
}
|
|
7690
|
-
const containmentValuesOf = /* @__PURE__ */ new WeakMap();
|
|
7691
|
-
function sideSetOf(table, secrets) {
|
|
7692
|
-
let set = table.get(secrets);
|
|
7693
|
-
if (set === void 0) {
|
|
7694
|
-
set = /* @__PURE__ */ new Set();
|
|
7695
|
-
table.set(secrets, set);
|
|
7696
|
-
}
|
|
7697
|
-
return set;
|
|
7698
|
-
}
|
|
7699
|
-
function recordDerivedMaskOnlyValue(secrets, plaintext) {
|
|
7700
|
-
recordMaskOnlyValue(secrets, plaintext);
|
|
7701
|
-
if (isMaskOnlyPlaintext(secrets, plaintext)) sideSetOf(containmentValuesOf, secrets).add(plaintext);
|
|
7702
|
-
}
|
|
7703
|
-
function recordFreshNoEchoValuesIn(value, secrets, excluded, publicTokens) {
|
|
7704
|
-
recordMaskOnlyValuesIn(value, secrets, excluded);
|
|
7705
|
-
const fresh = freshNoEchoSet(secrets);
|
|
7706
|
-
const containment = sideSetOf(containmentValuesOf, secrets);
|
|
7707
|
-
const seen = /* @__PURE__ */ new Set();
|
|
7708
|
-
const walk = (node) => {
|
|
7709
|
-
if (typeof node === "string") {
|
|
7710
|
-
if (excluded?.has(node) !== true && isMaskOnlyPlaintext(secrets, node)) {
|
|
7711
|
-
fresh.add(node);
|
|
7712
|
-
if (publicTokens?.has(node) !== true) containment.add(node);
|
|
7713
|
-
}
|
|
7714
|
-
return;
|
|
7715
|
-
}
|
|
7716
|
-
if (node === null || typeof node !== "object") return;
|
|
7717
|
-
if (seen.has(node)) return;
|
|
7718
|
-
seen.add(node);
|
|
7719
|
-
if (Array.isArray(node)) {
|
|
7720
|
-
for (const item of node) walk(item);
|
|
7721
|
-
return;
|
|
7722
|
-
}
|
|
7723
|
-
for (const child of Object.values(node)) walk(child);
|
|
7724
|
-
};
|
|
7725
|
-
walk(value);
|
|
7726
|
-
}
|
|
7727
|
-
const noEchoParameterValuesOf = /* @__PURE__ */ new WeakMap();
|
|
7728
|
-
function recordNoEchoParameterFreshValue(value, secrets, publicTokens) {
|
|
7729
|
-
recordFreshNoEchoValuesIn(value, secrets, void 0, publicTokens);
|
|
7730
|
-
const parameterClass = sideSetOf(noEchoParameterValuesOf, secrets);
|
|
7731
|
-
const walk = (node) => {
|
|
7732
|
-
if (typeof node === "string") {
|
|
7733
|
-
if (isMaskOnlyPlaintext(secrets, node)) parameterClass.add(node);
|
|
7734
|
-
return;
|
|
7735
|
-
}
|
|
7736
|
-
if (Array.isArray(node)) for (const item of node) walk(item);
|
|
7737
|
-
};
|
|
7738
|
-
walk(value);
|
|
7739
|
-
}
|
|
7740
|
-
function withoutNoEchoParameterEntries(secrets) {
|
|
7741
|
-
const fresh = freshNoEchoValuesOf.get(secrets);
|
|
7742
|
-
if (fresh === void 0 || fresh.size === 0) return secrets;
|
|
7743
|
-
const copy = /* @__PURE__ */ new Map();
|
|
7744
|
-
for (const [plaintext, expression] of secrets) {
|
|
7745
|
-
if (expression === "***" && fresh.has(plaintext)) continue;
|
|
7746
|
-
copy.set(plaintext, expression);
|
|
7747
|
-
}
|
|
7748
|
-
mergeResolvedPairs(secrets, copy);
|
|
7749
|
-
carryMaskOnlyMarks(secrets, copy);
|
|
7750
|
-
return copy;
|
|
7751
|
-
}
|
|
7752
|
-
function markNoEchoParameterClass(secrets, plaintext) {
|
|
7753
|
-
if (isMaskOnlyPlaintext(secrets, plaintext)) sideSetOf(noEchoParameterValuesOf, secrets).add(plaintext);
|
|
7754
|
-
}
|
|
7755
|
-
function isNoEchoParameterPlaintext(secrets, plaintext) {
|
|
7756
|
-
return noEchoParameterValuesOf.get(secrets)?.has(plaintext) === true && isMaskOnlyPlaintext(secrets, plaintext);
|
|
7757
|
-
}
|
|
7758
|
-
function noEchoParameterPlaintextsOf(secrets) {
|
|
7759
|
-
return [...noEchoParameterValuesOf.get(secrets) ?? []].filter((plaintext) => isMaskOnlyPlaintext(secrets, plaintext));
|
|
7760
|
-
}
|
|
7761
|
-
function carryFreshNoEchoMark(from, to, plaintext) {
|
|
7762
|
-
if (!isMaskOnlyPlaintext(to, plaintext)) return;
|
|
7763
|
-
if (containmentValuesOf.get(from)?.has(plaintext) === true) sideSetOf(containmentValuesOf, to).add(plaintext);
|
|
7764
|
-
if (freshNoEchoValuesOf.get(from)?.has(plaintext) === true) freshNoEchoSet(to).add(plaintext);
|
|
7765
|
-
if (noEchoParameterValuesOf.get(from)?.has(plaintext) === true) sideSetOf(noEchoParameterValuesOf, to).add(plaintext);
|
|
7766
|
-
}
|
|
7767
|
-
function carryMaskOnlyMarks(from, to) {
|
|
7768
|
-
for (const table of [
|
|
7769
|
-
freshNoEchoValuesOf,
|
|
7770
|
-
containmentValuesOf,
|
|
7771
|
-
noEchoParameterValuesOf
|
|
7772
|
-
]) {
|
|
7773
|
-
const marks = table.get(from);
|
|
7774
|
-
if (marks === void 0) continue;
|
|
7775
|
-
for (const plaintext of marks) if (isMaskOnlyPlaintext(to, plaintext)) sideSetOf(table, to).add(plaintext);
|
|
7776
|
-
}
|
|
7777
|
-
}
|
|
7778
|
-
function isKnownSecretExpression(expression, secretExpressions) {
|
|
7779
|
-
return isSecretExpressionByVerdictOrSpelling(expression) || secretExpressions.has(expression);
|
|
7780
|
-
}
|
|
7781
|
-
function isSecretExpressionByVerdictOrSpelling(expression) {
|
|
7782
|
-
return expression.startsWith("{{resolve:secretsmanager:") || expression.startsWith("{{resolve:ssm-secure:") || isRecordedSecretExpression(expression);
|
|
7783
|
-
}
|
|
7784
|
-
|
|
7785
|
-
//#endregion
|
|
7786
|
-
//#region src/deployment/secret-redaction/cross-stack.ts
|
|
7787
|
-
const crossStackAssociations = /* @__PURE__ */ new WeakMap();
|
|
7788
|
-
const CONFLICTING_CROSS_STACK = Symbol("conflicting cross-stack association");
|
|
7789
|
-
const CROSS_STACK_KEY_SEPARATOR = "\0";
|
|
7790
|
-
function literalStringOrUndefined(value) {
|
|
7791
|
-
return typeof value === "string" && value !== "" ? value : void 0;
|
|
7792
|
-
}
|
|
7793
|
-
function splitGetAttStringForm(getAtt) {
|
|
7794
|
-
const firstDot = getAtt.indexOf(".");
|
|
7795
|
-
if (firstDot <= 0 || firstDot === getAtt.length - 1) return void 0;
|
|
7796
|
-
return {
|
|
7797
|
-
logicalId: getAtt.slice(0, firstDot),
|
|
7798
|
-
attributeName: getAtt.slice(firstDot + 1)
|
|
7799
|
-
};
|
|
7800
|
-
}
|
|
7801
|
-
function crossStackSourceKey(source) {
|
|
7802
|
-
const keys = Object.keys(source);
|
|
7803
|
-
if (keys.length !== 1) return void 0;
|
|
7804
|
-
const key = keys[0];
|
|
7805
|
-
if (key === "Fn::ImportValue") {
|
|
7806
|
-
const exportName = literalStringOrUndefined(source[key]);
|
|
7807
|
-
if (exportName === void 0) return void 0;
|
|
7808
|
-
return ["Fn::ImportValue", exportName].join(CROSS_STACK_KEY_SEPARATOR);
|
|
7809
|
-
}
|
|
7810
|
-
if (key === "Fn::GetStackOutput") {
|
|
7811
|
-
const args = source[key];
|
|
7812
|
-
if (!isPlainObject$7(args)) return void 0;
|
|
7813
|
-
const stackName = Object.hasOwn(args, "StackName") ? literalStringOrUndefined(args["StackName"]) : void 0;
|
|
7814
|
-
const outputName = Object.hasOwn(args, "OutputName") ? literalStringOrUndefined(args["OutputName"]) : void 0;
|
|
7815
|
-
if (stackName === void 0 || outputName === void 0) return void 0;
|
|
7816
|
-
const slots = [
|
|
7817
|
-
"Fn::GetStackOutput",
|
|
7818
|
-
stackName,
|
|
7819
|
-
outputName
|
|
7820
|
-
];
|
|
7821
|
-
for (const optional of ["Region", "RoleArn"]) {
|
|
7822
|
-
const raw = Object.hasOwn(args, optional) ? args[optional] : void 0;
|
|
7823
|
-
if (raw === void 0 || raw === null) {
|
|
7824
|
-
slots.push("");
|
|
7825
|
-
continue;
|
|
7826
|
-
}
|
|
7827
|
-
const literal = literalStringOrUndefined(raw);
|
|
7828
|
-
if (literal === void 0) return void 0;
|
|
7829
|
-
slots.push(literal);
|
|
7830
|
-
}
|
|
7831
|
-
return slots.join(CROSS_STACK_KEY_SEPARATOR);
|
|
7832
|
-
}
|
|
7833
|
-
if (key === "Fn::GetAtt") {
|
|
7834
|
-
const raw = source[key];
|
|
7835
|
-
let logicalId;
|
|
7836
|
-
let attributeName;
|
|
7837
|
-
if (typeof raw === "string") {
|
|
7838
|
-
const split = splitGetAttStringForm(raw);
|
|
7839
|
-
if (split === void 0) return void 0;
|
|
7840
|
-
logicalId = split.logicalId;
|
|
7841
|
-
attributeName = split.attributeName;
|
|
7842
|
-
} else if (Array.isArray(raw) && raw.length === 2) {
|
|
7843
|
-
logicalId = literalStringOrUndefined(raw[0]);
|
|
7844
|
-
attributeName = literalStringOrUndefined(raw[1]);
|
|
7845
|
-
}
|
|
7846
|
-
if (logicalId === void 0 || attributeName === void 0) return void 0;
|
|
7847
|
-
return [
|
|
7848
|
-
"Fn::GetAtt",
|
|
7849
|
-
logicalId,
|
|
7850
|
-
attributeName
|
|
7851
|
-
].join(CROSS_STACK_KEY_SEPARATOR);
|
|
7852
|
-
}
|
|
7853
|
-
if (key === "Fn::Sub") {
|
|
7854
|
-
const raw = source[key];
|
|
7855
|
-
let template;
|
|
7856
|
-
let variables;
|
|
7857
|
-
if (typeof raw === "string") template = raw;
|
|
7858
|
-
else if (Array.isArray(raw) && raw.length === 2 && isPlainObject$7(raw[1])) {
|
|
7859
|
-
if (typeof raw[0] !== "string") return void 0;
|
|
7860
|
-
template = raw[0];
|
|
7861
|
-
variables = raw[1];
|
|
7862
|
-
}
|
|
7863
|
-
if (template === void 0) return void 0;
|
|
7864
|
-
const only = /^\$\{(!)?([^}]*)\}$/.exec(template);
|
|
7865
|
-
if (only === null || only[1] === "!") return void 0;
|
|
7866
|
-
const varName = only[2] ?? "";
|
|
7867
|
-
if (varName in (variables ?? {})) return void 0;
|
|
7868
|
-
const split = splitGetAttStringForm(varName);
|
|
7869
|
-
if (split === void 0) return void 0;
|
|
7870
|
-
return [
|
|
7871
|
-
"Fn::GetAtt",
|
|
7872
|
-
split.logicalId,
|
|
7873
|
-
split.attributeName
|
|
7874
|
-
].join(CROSS_STACK_KEY_SEPARATOR);
|
|
7875
|
-
}
|
|
7876
|
-
if (key === "Ref") {
|
|
7877
|
-
const parameterName = literalStringOrUndefined(source[key]);
|
|
7878
|
-
if (parameterName === void 0) return void 0;
|
|
7879
|
-
return ["Ref", parameterName].join(CROSS_STACK_KEY_SEPARATOR);
|
|
7880
|
-
}
|
|
7881
|
-
}
|
|
7882
|
-
function recordCrossStackExpression(secrets, key, expression, plaintext) {
|
|
7883
|
-
if (!isSingleDynamicReferenceToken(expression)) return;
|
|
7884
|
-
let associations = crossStackAssociations.get(secrets);
|
|
7885
|
-
if (associations === void 0) {
|
|
7886
|
-
associations = /* @__PURE__ */ new Map();
|
|
7887
|
-
crossStackAssociations.set(secrets, associations);
|
|
7888
|
-
}
|
|
7889
|
-
storeAssociation(associations, key, expression, plaintext);
|
|
7890
|
-
}
|
|
7891
|
-
function storeAssociation(associations, key, expression, plaintext) {
|
|
7892
|
-
const seen = associations.get(key);
|
|
7893
|
-
if (seen === void 0) {
|
|
7894
|
-
associations.set(key, {
|
|
7895
|
-
expression,
|
|
7896
|
-
plaintext
|
|
7897
|
-
});
|
|
7898
|
-
return;
|
|
7899
|
-
}
|
|
7900
|
-
if (typeof seen === "symbol") return;
|
|
7901
|
-
if (seen.expression !== expression || seen.plaintext !== plaintext) associations.set(key, CONFLICTING_CROSS_STACK);
|
|
7902
|
-
}
|
|
7903
|
-
|
|
7904
|
-
//#endregion
|
|
7905
|
-
//#region src/deployment/secret-redaction/certified-positions.ts
|
|
7906
|
-
function plaintextIndexOf(secrets) {
|
|
7907
|
-
const plaintextOf = /* @__PURE__ */ new Map();
|
|
7908
|
-
for (const [plaintext, expression] of secrets) plaintextOf.set(expression, plaintextOf.has(expression) ? CONFLICTING_PLAINTEXT : plaintext);
|
|
7909
|
-
return plaintextOf;
|
|
7910
|
-
}
|
|
7911
|
-
function certifiedExpressionForLeaf(secrets, association, leaf) {
|
|
7912
|
-
if (typeof leaf !== "string" || leaf === "") return void 0;
|
|
7913
|
-
if (!secrets.has(leaf)) return void 0;
|
|
7914
|
-
if (association.plaintext !== leaf) return void 0;
|
|
7915
|
-
const recordedPlaintext = plaintextIndexOf(secrets).get(association.expression);
|
|
7916
|
-
if (recordedPlaintext !== void 0 && recordedPlaintext !== leaf) return void 0;
|
|
7917
|
-
return association.expression;
|
|
7918
|
-
}
|
|
7919
|
-
function certifiedListForLeaf(secrets, association, bag) {
|
|
7920
|
-
const certified = bag.map((element) => certifiedExpressionForLeaf(secrets, association, element));
|
|
7921
|
-
if (certified.every((expression) => expression === void 0)) return void 0;
|
|
7922
|
-
return bag.map((element, i) => certified[i] ?? redactForState(element, {
|
|
7923
|
-
provenance: "value-scan",
|
|
7924
|
-
secrets
|
|
7925
|
-
}));
|
|
7926
|
-
}
|
|
7927
|
-
function associationForSource(source, secrets) {
|
|
7928
|
-
const key = crossStackSourceKey(source);
|
|
7929
|
-
if (key === void 0) return void 0;
|
|
7930
|
-
const associations = crossStackAssociations.get(secrets);
|
|
7931
|
-
if (associations === void 0) return void 0;
|
|
7932
|
-
const association = associations.get(key);
|
|
7933
|
-
if (association === void 0 || typeof association === "symbol") return void 0;
|
|
7934
|
-
return association;
|
|
7935
|
-
}
|
|
7936
|
-
function positionByCrossStackSource(bag, source, secrets) {
|
|
7937
|
-
const association = associationForSource(source, secrets);
|
|
7938
|
-
if (association === void 0) return void 0;
|
|
7939
|
-
return certifiedExpressionForLeaf(secrets, association, bag);
|
|
7940
|
-
}
|
|
7941
|
-
|
|
7942
|
-
//#endregion
|
|
7943
|
-
//#region src/deployment/secret-redaction/resolver-outcomes.ts
|
|
7944
|
-
const CONFLICTING = Symbol("cdkd.resolver-outcome.conflicting");
|
|
7945
|
-
const takenBranches = /* @__PURE__ */ new WeakMap();
|
|
7946
|
-
function recordTakenIfBranch(secrets, source, tookTrueBranch) {
|
|
7947
|
-
let taken = takenBranches.get(secrets);
|
|
7948
|
-
if (taken === void 0) {
|
|
7949
|
-
taken = /* @__PURE__ */ new WeakMap();
|
|
7950
|
-
takenBranches.set(secrets, taken);
|
|
7951
|
-
}
|
|
7952
|
-
const previous = taken.get(source);
|
|
7953
|
-
if (previous === void 0) taken.set(source, tookTrueBranch);
|
|
7954
|
-
else if (previous !== tookTrueBranch) taken.set(source, CONFLICTING);
|
|
7955
|
-
}
|
|
7956
|
-
function takenIfBranchOf(secrets, source) {
|
|
7957
|
-
const taken = takenBranches.get(secrets)?.get(source);
|
|
7958
|
-
return taken === CONFLICTING ? void 0 : taken;
|
|
7959
|
-
}
|
|
7960
|
-
const droppedElements = /* @__PURE__ */ new WeakMap();
|
|
7961
|
-
function recordDroppedArrayElements(secrets, source, dropped) {
|
|
7962
|
-
let arrays = droppedElements.get(secrets);
|
|
7963
|
-
if (arrays === void 0) {
|
|
7964
|
-
arrays = /* @__PURE__ */ new WeakMap();
|
|
7965
|
-
droppedElements.set(secrets, arrays);
|
|
7966
|
-
}
|
|
7967
|
-
const previous = arrays.get(source);
|
|
7968
|
-
if (previous === void 0) arrays.set(source, [...dropped]);
|
|
7969
|
-
else if (previous !== CONFLICTING && (previous.length !== dropped.length || previous.some((index, i) => index !== dropped[i]))) arrays.set(source, CONFLICTING);
|
|
7970
|
-
}
|
|
7971
|
-
function droppedArrayElementsOf(secrets, source) {
|
|
7972
|
-
const dropped = droppedElements.get(secrets)?.get(source);
|
|
7973
|
-
return dropped === CONFLICTING ? void 0 : dropped;
|
|
7974
|
-
}
|
|
7975
|
-
|
|
7976
|
-
//#endregion
|
|
7977
|
-
//#region src/deployment/secret-redaction/physical-name-copies.ts
|
|
7978
|
-
const physicalNameCopiesOf = /* @__PURE__ */ new WeakMap();
|
|
7979
|
-
function recordPhysicalNameCopy(secrets, physicalId) {
|
|
7980
|
-
if (physicalId === "") return;
|
|
7981
|
-
sideSetOf(physicalNameCopiesOf, secrets).add(physicalId);
|
|
7982
|
-
}
|
|
7983
|
-
const attributeIdCopiesOf = /* @__PURE__ */ new WeakMap();
|
|
7984
|
-
function recordAttributeIdCopy(secrets, physicalId) {
|
|
7985
|
-
if (physicalId === "") return;
|
|
7986
|
-
sideSetOf(attributeIdCopiesOf, secrets).add(physicalId);
|
|
7987
|
-
}
|
|
7988
|
-
function physicalNameSpans(names, value) {
|
|
7989
|
-
const spans = [];
|
|
7990
|
-
if (names === void 0) return spans;
|
|
7991
|
-
for (const name of names) for (let at = value.indexOf(name); at !== -1; at = value.indexOf(name, at + 1)) spans.push({
|
|
7992
|
-
start: at,
|
|
7993
|
-
end: at + name.length
|
|
7994
|
-
});
|
|
7995
|
-
return spans;
|
|
7996
|
-
}
|
|
7997
|
-
|
|
7998
|
-
//#endregion
|
|
7999
|
-
//#region src/deployment/secret-redaction/fresh-noecho.ts
|
|
8000
|
-
function embedsFreshNoEchoValue(text, secrets, freshClass) {
|
|
8001
|
-
const fresh = freshNoEchoValuesOf.get(secrets);
|
|
8002
|
-
if (fresh === void 0) return false;
|
|
8003
|
-
for (const value of fresh) {
|
|
8004
|
-
if (freshClass !== void 0 && isNoEchoParameterPlaintext(secrets, value) !== (freshClass === "parameter")) continue;
|
|
8005
|
-
if (isMaskOnlyPlaintext(secrets, value) && text.includes(value)) return true;
|
|
8006
|
-
}
|
|
8007
|
-
return false;
|
|
8008
|
-
}
|
|
8009
|
-
function carriesFreshNoEchoValue(value, secrets, freshClass) {
|
|
8010
|
-
const isFresh = freshNoEchoLeafTest(secrets, freshClass);
|
|
8011
|
-
if (isFresh === void 0) return false;
|
|
8012
|
-
const seen = /* @__PURE__ */ new Set();
|
|
8013
|
-
const walk = (node) => {
|
|
8014
|
-
if (typeof node === "string") return isFresh(node);
|
|
8015
|
-
if (node === null || typeof node !== "object") return false;
|
|
8016
|
-
if (seen.has(node)) return false;
|
|
8017
|
-
seen.add(node);
|
|
8018
|
-
if (Array.isArray(node)) return node.some((item) => walk(item));
|
|
8019
|
-
return Object.values(node).some((child) => walk(child));
|
|
8020
|
-
};
|
|
8021
|
-
return walk(value);
|
|
8022
|
-
}
|
|
8023
|
-
function freshNoEchoLeafPositions(value, secrets, freshClass) {
|
|
8024
|
-
const isFresh = freshNoEchoLeafTest(secrets, freshClass);
|
|
8025
|
-
if (isFresh === void 0) return [];
|
|
8026
|
-
const leaves = [];
|
|
8027
|
-
const ancestors = /* @__PURE__ */ new Set();
|
|
8028
|
-
const walk = (node, path) => {
|
|
8029
|
-
if (typeof node === "string") {
|
|
8030
|
-
if (isFresh(node)) leaves.push({
|
|
8031
|
-
path,
|
|
8032
|
-
plaintext: node
|
|
8033
|
-
});
|
|
8034
|
-
return;
|
|
8035
|
-
}
|
|
8036
|
-
if (node === null || typeof node !== "object") return;
|
|
8037
|
-
if (ancestors.has(node)) return;
|
|
8038
|
-
ancestors.add(node);
|
|
8039
|
-
if (Array.isArray(node)) node.forEach((item, index) => walk(item, [...path, index]));
|
|
8040
|
-
else for (const [key, child] of Object.entries(node)) walk(child, [...path, key]);
|
|
8041
|
-
ancestors.delete(node);
|
|
8042
|
-
};
|
|
8043
|
-
walk(value, []);
|
|
8044
|
-
return leaves;
|
|
8045
|
-
}
|
|
8046
|
-
function freshNoEchoLeafTest(secrets, freshClass) {
|
|
8047
|
-
const all = freshNoEchoValuesOf.get(secrets);
|
|
8048
|
-
if (all === void 0 || all.size === 0) return void 0;
|
|
8049
|
-
const fresh = freshClass === void 0 ? all : new Set([...all].filter((value) => isNoEchoParameterPlaintext(secrets, value) === (freshClass === "parameter")));
|
|
8050
|
-
if (fresh.size === 0) return void 0;
|
|
8051
|
-
const needles = containmentNeedlesOf(secrets).filter((needle) => fresh.has(needle));
|
|
8052
|
-
return (leaf) => fresh.has(leaf) && isMaskOnlyPlaintext(secrets, leaf) || leaf !== "***" && embedsNeedleOutsideReferences(leaf, needles, secrets);
|
|
8053
|
-
}
|
|
8054
|
-
function containmentNeedlesOf(secrets) {
|
|
8055
|
-
const values = containmentValuesOf.get(secrets);
|
|
8056
|
-
if (values === void 0 || values.size === 0) return [];
|
|
8057
|
-
const needles = [];
|
|
8058
|
-
for (const value of values) if (value.length >= 4 && isMaskOnlyPlaintext(secrets, value)) needles.push(value);
|
|
8059
|
-
return needles;
|
|
8060
|
-
}
|
|
8061
|
-
function isStrictlyInsideASpan(spans, start, end) {
|
|
8062
|
-
return spans.some((span) => span.start <= start && end <= span.end && (span.start !== start || span.end !== end));
|
|
8063
|
-
}
|
|
8064
|
-
function embedsNeedleOutsideReferences(leaf, needles, secrets) {
|
|
8065
|
-
return needleOccurrencesOutsideReferences(leaf, needles, secrets, true).length > 0;
|
|
8066
|
-
}
|
|
8067
|
-
function needleOccurrencesOutsideReferences(leaf, needles, secrets, first) {
|
|
8068
|
-
const found = [];
|
|
8069
|
-
let spans;
|
|
8070
|
-
let names;
|
|
8071
|
-
for (const needle of needles) for (let at = leaf.indexOf(needle); at >= 0; at = leaf.indexOf(needle, at + 1)) {
|
|
8072
|
-
spans ??= isDynamicReferenceString(leaf) ? resolvableReferenceSpans(leaf, new Set(secrets.values())) : [];
|
|
8073
|
-
if (isStrictlyInsideASpan(spans, at, at + needle.length)) continue;
|
|
8074
|
-
names ??= physicalNameSpans(physicalNameCopiesOf.get(secrets), leaf);
|
|
8075
|
-
const end = at + needle.length;
|
|
8076
|
-
if (names.some((n) => n.start <= at && end <= n.end)) continue;
|
|
8077
|
-
found.push({
|
|
8078
|
-
start: at,
|
|
8079
|
-
end
|
|
8080
|
-
});
|
|
8081
|
-
if (first) return found;
|
|
8082
|
-
}
|
|
8083
|
-
return found;
|
|
8084
|
-
}
|
|
8085
|
-
function cutsContainmentNeedle(leaf, secrets, redacted) {
|
|
8086
|
-
if (redacted.length === 0) return false;
|
|
8087
|
-
const needles = containmentNeedlesOf(secrets);
|
|
8088
|
-
if (needles.length === 0) return false;
|
|
8089
|
-
return needleOccurrencesOutsideReferences(leaf, needles, secrets, false).some((c) => redacted.some((m) => m.start < c.end && c.start < m.end && !(m.start <= c.start && c.end <= m.end)));
|
|
8090
|
-
}
|
|
8091
|
-
function flattenEmbeddedNoEchoLeaves(value, secrets) {
|
|
8092
|
-
const needles = containmentNeedlesOf(secrets);
|
|
8093
|
-
if (needles.length === 0) return value;
|
|
8094
|
-
const flattens = (leaf) => leaf !== "***" && embedsNeedleOutsideReferences(leaf, needles, secrets);
|
|
8095
|
-
const walk = (node) => {
|
|
8096
|
-
if (typeof node === "string") return flattens(node) ? "***" : node;
|
|
8097
|
-
if (node === null || typeof node !== "object") return node;
|
|
8098
|
-
if (Array.isArray(node)) {
|
|
8099
|
-
let changed = false;
|
|
8100
|
-
const out = node.map((item) => {
|
|
8101
|
-
const next = walk(item);
|
|
8102
|
-
if (next !== item) changed = true;
|
|
8103
|
-
return next;
|
|
8104
|
-
});
|
|
8105
|
-
return changed ? out : node;
|
|
8106
|
-
}
|
|
8107
|
-
if (isOrdinaryDate(node)) {
|
|
8108
|
-
const persisted = node.toJSON();
|
|
8109
|
-
return typeof persisted === "string" && flattens(persisted) ? "***" : node;
|
|
8110
|
-
}
|
|
8111
|
-
let out;
|
|
8112
|
-
for (const [key, child] of Object.entries(node)) {
|
|
8113
|
-
const next = walk(child);
|
|
8114
|
-
if (next === child) continue;
|
|
8115
|
-
out ??= Object.assign(Object.create(null), node);
|
|
8116
|
-
out[key] = next;
|
|
8117
|
-
}
|
|
8118
|
-
return out ?? node;
|
|
8119
|
-
};
|
|
8120
|
-
return walk(value);
|
|
8121
|
-
}
|
|
8122
|
-
function substringNeedlesOf(secrets) {
|
|
8123
|
-
const needles = [];
|
|
8124
|
-
for (const plaintext of secrets.keys()) if (!isMaskOnlyPlaintext(secrets, plaintext)) needles.push(plaintext);
|
|
8125
|
-
return needles;
|
|
8126
|
-
}
|
|
8127
|
-
function recordedExpressionsOf(secrets) {
|
|
8128
|
-
const expressions = /* @__PURE__ */ new Set();
|
|
8129
|
-
for (const [plaintext, expression] of secrets) if (!isMaskOnlyPlaintext(secrets, plaintext)) expressions.add(expression);
|
|
8130
|
-
return expressions;
|
|
8131
|
-
}
|
|
8132
|
-
const recoverableMaskedOutputs = /* @__PURE__ */ new Map();
|
|
8133
|
-
function maskedOutputKey(identity, stackName, region, outputKey) {
|
|
8134
|
-
return `${identity}\u0000${stackName}\u0000${region}\u0000${outputKey}`;
|
|
8135
|
-
}
|
|
8136
|
-
function recordRecoverableMaskedOutput(identity, stackName, region, outputKey, plaintext) {
|
|
8137
|
-
recoverableMaskedOutputs.set(maskedOutputKey(identity, stackName, region, outputKey), plaintext);
|
|
8138
|
-
}
|
|
8139
|
-
function recoverMaskedOutput(identity, stackName, region, outputKey) {
|
|
8140
|
-
return recoverableMaskedOutputs.get(maskedOutputKey(identity, stackName, region, outputKey));
|
|
8141
|
-
}
|
|
8142
|
-
|
|
8143
|
-
//#endregion
|
|
8144
|
-
//#region src/deployment/secret-redaction/nested-stack.ts
|
|
8145
|
-
const NESTED_STACK_RESOURCE_TYPE$4 = "AWS::CloudFormation::Stack";
|
|
8146
|
-
const nestedStackParameterExpressions = /* @__PURE__ */ new WeakMap();
|
|
8147
|
-
const renderedParameterSpellings = /* @__PURE__ */ new WeakMap();
|
|
8148
|
-
const UNFRAMED_SPELLING = Symbol("cdkd.nested-parameter.unframed-spelling");
|
|
8149
|
-
function recordNestedStackParameterExpressions(secrets, resourceType, resolvedProperties, sourceProperties, provenance = "template-derived") {
|
|
8150
|
-
if (resourceType !== NESTED_STACK_RESOURCE_TYPE$4) return;
|
|
8151
|
-
if (secrets.size === 0) return;
|
|
8152
|
-
if (!isPlainObject$7(resolvedProperties) || !isPlainObject$7(sourceProperties)) return;
|
|
8153
|
-
if (!Object.hasOwn(resolvedProperties, "Parameters")) return;
|
|
8154
|
-
if (!Object.hasOwn(sourceProperties, "Parameters")) return;
|
|
8155
|
-
const resolvedParameters = resolvedProperties["Parameters"];
|
|
8156
|
-
const sourceParameters = sourceProperties["Parameters"];
|
|
8157
|
-
if (!isPlainObject$7(resolvedParameters) || !isPlainObject$7(sourceParameters)) return;
|
|
8158
|
-
const positioned = redactAtProvenance({ ...resolvedParameters }, secrets, sourceParameters, provenance, true);
|
|
8159
|
-
let table = nestedStackParameterExpressions.get(secrets);
|
|
8160
|
-
for (const [name, resolvedValue] of Object.entries(resolvedParameters)) {
|
|
8161
|
-
const sourceLeaf = sourceParameters[name];
|
|
8162
|
-
if (typeof resolvedValue !== "string" || typeof sourceLeaf !== "string") continue;
|
|
8163
|
-
if (isSingleDynamicReferenceToken(sourceLeaf) || positioned[name] !== sourceLeaf) continue;
|
|
8164
|
-
if (!rendersLiteralTo(sourceLeaf, secrets, resolvedValue)) continue;
|
|
8165
|
-
let rendered = renderedParameterSpellings.get(secrets);
|
|
8166
|
-
if (rendered === void 0) {
|
|
8167
|
-
rendered = /* @__PURE__ */ new Map();
|
|
8168
|
-
renderedParameterSpellings.set(secrets, rendered);
|
|
8169
|
-
}
|
|
8170
|
-
const previous = rendered.get(name);
|
|
8171
|
-
if (previous === void 0) rendered.set(name, {
|
|
8172
|
-
spelling: sourceLeaf,
|
|
8173
|
-
value: resolvedValue
|
|
8174
|
-
});
|
|
8175
|
-
else if (previous?.spelling !== sourceLeaf || previous.value !== resolvedValue) rendered.set(name, null);
|
|
8176
|
-
}
|
|
8177
|
-
for (const [name, resolvedValue] of Object.entries(resolvedParameters)) {
|
|
8178
|
-
if (typeof resolvedValue !== "string" || !secrets.has(resolvedValue)) continue;
|
|
8179
|
-
const expression = positioned[name];
|
|
8180
|
-
if (typeof expression !== "string") continue;
|
|
8181
|
-
if (!isSingleDynamicReferenceToken(expression)) continue;
|
|
8182
|
-
const sourceLeaf = sourceParameters[name];
|
|
8183
|
-
if (typeof sourceLeaf === "string" && expression !== sourceLeaf) continue;
|
|
8184
|
-
if (expression === resolvedValue) continue;
|
|
8185
|
-
const seenResolvingTo = plaintextIndexOf(secrets).get(expression);
|
|
8186
|
-
if (seenResolvingTo !== void 0 && seenResolvingTo !== resolvedValue) continue;
|
|
8187
|
-
if (typeof sourceLeaf === "string" && resolvedPlaintextOf(secrets, expression) !== resolvedValue) continue;
|
|
8188
|
-
if (table === void 0) {
|
|
8189
|
-
table = /* @__PURE__ */ new Map();
|
|
8190
|
-
nestedStackParameterExpressions.set(secrets, table);
|
|
8191
|
-
}
|
|
8192
|
-
storeAssociation(table, name, expression, resolvedValue);
|
|
8193
|
-
}
|
|
8194
|
-
const framesByValue = /* @__PURE__ */ new Map();
|
|
8195
|
-
const tokensOf = /* @__PURE__ */ new Map();
|
|
8196
|
-
const frameSpellings = /* @__PURE__ */ new Map();
|
|
8197
|
-
const frameSpellingOf = (name) => {
|
|
8198
|
-
if (!frameSpellings.has(name)) frameSpellings.set(name, computeFrameSpelling(name));
|
|
8199
|
-
return frameSpellings.get(name);
|
|
8200
|
-
};
|
|
8201
|
-
const computeFrameSpelling = (name) => {
|
|
8202
|
-
const resolvedValue = resolvedParameters[name];
|
|
8203
|
-
if (typeof resolvedValue !== "string") return void 0;
|
|
8204
|
-
const sourceLeaf = sourceParameters[name];
|
|
8205
|
-
if (typeof sourceLeaf === "string") return sourceLeaf;
|
|
8206
|
-
if (!isPlainObject$7(sourceLeaf)) return void 0;
|
|
8207
|
-
const written = positioned[name];
|
|
8208
|
-
if (typeof written !== "string") return void 0;
|
|
8209
|
-
const rendered = intrinsicSkeletonSegments(sourceLeaf)?.map((s) => s === UNKNOWN_PART ? "\0" : s).join("");
|
|
8210
|
-
const spans = rendered === void 0 ? [] : dynamicReferenceSpans(rendered);
|
|
8211
|
-
if (rendered !== void 0 && spans.length === 1) {
|
|
8212
|
-
const [span] = spans;
|
|
8213
|
-
const ownToken = rendered.slice(span.start, span.end);
|
|
8214
|
-
if (written !== resolvedValue && SPELLED_SECRET_REFERENCE_PREFIXES.some((prefix) => ownToken.startsWith(prefix))) return written;
|
|
8215
|
-
}
|
|
8216
|
-
const substituted = substitutedSpellingOf(secrets, sourceLeaf, resolvedValue);
|
|
8217
|
-
if (substituted === void 0) return void 0;
|
|
8218
|
-
return written === resolvedValue || written === substituted ? substituted : void 0;
|
|
8219
|
-
};
|
|
8220
|
-
const certifiedSpellingOf = (name) => {
|
|
8221
|
-
const sourceLeaf = sourceParameters[name];
|
|
8222
|
-
if (typeof sourceLeaf === "string") return positioned[name] === sourceLeaf ? sourceLeaf : void 0;
|
|
8223
|
-
return frameSpellingOf(name);
|
|
8224
|
-
};
|
|
8225
|
-
const unwrittenValues = /* @__PURE__ */ new Set();
|
|
8226
|
-
for (const [name, resolvedValue] of Object.entries(resolvedParameters)) {
|
|
8227
|
-
if (typeof resolvedValue !== "string") continue;
|
|
8228
|
-
const spelling = frameSpellingOf(name);
|
|
8229
|
-
const frame = spelling === void 0 ? void 0 : singleSpanFrame(resolvedValue, spelling);
|
|
8230
|
-
const frames = framesByValue.get(resolvedValue) ?? /* @__PURE__ */ new Set();
|
|
8231
|
-
const unframed = frame === void 0 || resolvedPlaintextOf(secrets, frame.token) !== frame.middle;
|
|
8232
|
-
frames.add(unframed ? UNFRAMED_SPELLING : `${frame.prefix.length}:${frame.prefix}${frame.suffix}`);
|
|
8233
|
-
framesByValue.set(resolvedValue, frames);
|
|
8234
|
-
if (!unframed) {
|
|
8235
|
-
const tokens = tokensOf.get(resolvedValue) ?? /* @__PURE__ */ new Set();
|
|
8236
|
-
tokens.add(frame.token);
|
|
8237
|
-
tokensOf.set(resolvedValue, tokens);
|
|
8238
|
-
if (typeof sourceParameters[name] !== "string" && positioned[name] !== spelling) unwrittenValues.add(resolvedValue);
|
|
8239
|
-
}
|
|
8240
|
-
}
|
|
8241
|
-
for (const value of unwrittenValues) if (tokensOf.get(value)?.size !== 1) framesByValue.get(value)?.add(UNFRAMED_SPELLING);
|
|
8242
|
-
const rowWithoutParameters = {};
|
|
8243
|
-
for (const [key, value] of Object.entries(resolvedProperties)) if (key !== "Parameters") rowWithoutParameters[key] = value;
|
|
8244
|
-
const outsideLeaves = wholeStringLeavesOf(rowWithoutParameters);
|
|
8245
|
-
const framed = /* @__PURE__ */ new Map();
|
|
8246
|
-
const framedByName = [];
|
|
8247
|
-
for (const [name, resolvedValue] of Object.entries(resolvedParameters)) {
|
|
8248
|
-
if (typeof resolvedValue !== "string") continue;
|
|
8249
|
-
const spelling = certifiedSpellingOf(name);
|
|
8250
|
-
if (spelling === void 0) continue;
|
|
8251
|
-
if (redactForState(resolvedValue, {
|
|
8252
|
-
provenance: "value-scan",
|
|
8253
|
-
secrets
|
|
8254
|
-
}) !== resolvedValue) continue;
|
|
8255
|
-
const frame = singleSpanFrame(resolvedValue, spelling);
|
|
8256
|
-
if (frame === void 0 || resolvedPlaintextOf(secrets, frame.token) !== frame.middle) continue;
|
|
8257
|
-
if (framesByValue.get(resolvedValue)?.size !== 1) continue;
|
|
8258
|
-
const isNeedle = resolvedValue.length >= 4;
|
|
8259
|
-
const rewrites = (leaf) => leaf === resolvedValue || isNeedle && leaf.includes(resolvedValue);
|
|
8260
|
-
let embedded = false;
|
|
8261
|
-
for (const leaf of outsideLeaves) if (rewrites(leaf)) {
|
|
8262
|
-
embedded = true;
|
|
8263
|
-
break;
|
|
8264
|
-
}
|
|
8265
|
-
for (const other of Object.values(resolvedParameters)) {
|
|
8266
|
-
if (embedded) break;
|
|
8267
|
-
if (typeof other === "string") {
|
|
8268
|
-
if (other !== resolvedValue && rewrites(other)) embedded = true;
|
|
8269
|
-
continue;
|
|
8270
|
-
}
|
|
8271
|
-
for (const leaf of wholeStringLeavesOf(other)) if (rewrites(leaf)) {
|
|
8272
|
-
embedded = true;
|
|
8273
|
-
break;
|
|
8274
|
-
}
|
|
8275
|
-
}
|
|
8276
|
-
if (embedded) continue;
|
|
8277
|
-
framedByName.push([
|
|
8278
|
-
name,
|
|
8279
|
-
spelling,
|
|
8280
|
-
resolvedValue
|
|
8281
|
-
]);
|
|
8282
|
-
if (secrets.get(frame.middle) !== frame.token && tokensOf.get(resolvedValue)?.size !== 1) continue;
|
|
8283
|
-
framed.set(resolvedValue, spelling);
|
|
8284
|
-
}
|
|
8285
|
-
for (const [plaintext, expression] of framed) secrets.set(plaintext, expression);
|
|
8286
|
-
for (const [name, expression, plaintext] of framedByName) {
|
|
8287
|
-
if (table === void 0) {
|
|
8288
|
-
table = /* @__PURE__ */ new Map();
|
|
8289
|
-
nestedStackParameterExpressions.set(secrets, table);
|
|
8290
|
-
}
|
|
8291
|
-
storeAssociation(table, name, expression, plaintext);
|
|
8292
|
-
}
|
|
8293
|
-
}
|
|
8294
|
-
function inheritNestedStackParameterAssociations(childSecrets, parentSecrets) {
|
|
8295
|
-
const table = nestedStackParameterExpressions.get(parentSecrets);
|
|
8296
|
-
if (table === void 0 || table.size === 0) return;
|
|
8297
|
-
let associations = crossStackAssociations.get(childSecrets);
|
|
8298
|
-
for (const [name, association] of table) {
|
|
8299
|
-
const key = crossStackSourceKey({ Ref: name });
|
|
8300
|
-
if (key === void 0) continue;
|
|
8301
|
-
if (associations === void 0) {
|
|
8302
|
-
associations = /* @__PURE__ */ new Map();
|
|
8303
|
-
crossStackAssociations.set(childSecrets, associations);
|
|
8304
|
-
}
|
|
8305
|
-
if (typeof association === "symbol") {
|
|
8306
|
-
associations.set(key, association);
|
|
8307
|
-
continue;
|
|
8308
|
-
}
|
|
8309
|
-
storeAssociation(associations, key, association.expression, association.plaintext);
|
|
8310
|
-
}
|
|
8311
|
-
}
|
|
8312
|
-
function inheritedParameterExpression(parentSecrets, parameterName, resolvedValue) {
|
|
8313
|
-
const association = nestedStackParameterExpressions.get(parentSecrets)?.get(parameterName);
|
|
8314
|
-
if (association === void 0) return renderedParameterSpelling(parentSecrets, parameterName, resolvedValue);
|
|
8315
|
-
if (typeof association === "symbol") return void 0;
|
|
8316
|
-
if (Array.isArray(resolvedValue)) return certifiedListForLeaf(parentSecrets, association, resolvedValue);
|
|
8317
|
-
return certifiedExpressionForLeaf(parentSecrets, association, resolvedValue);
|
|
8318
|
-
}
|
|
8319
|
-
function renderedParameterSpelling(parentSecrets, parameterName, resolvedValue) {
|
|
8320
|
-
if (typeof resolvedValue !== "string" || parentSecrets.has(resolvedValue)) return void 0;
|
|
8321
|
-
const rendered = renderedParameterSpellings.get(parentSecrets)?.get(parameterName);
|
|
8322
|
-
if (rendered == null || rendered.value !== resolvedValue) return void 0;
|
|
8323
|
-
if (!rendersLiteralTo(rendered.spelling, parentSecrets, resolvedValue)) return void 0;
|
|
8324
|
-
return rendered.spelling;
|
|
8325
|
-
}
|
|
8326
|
-
function inheritedRenderedToken(parentSecrets, parameterName, value, plaintext) {
|
|
8327
|
-
const spelling = inheritedParameterExpression(parentSecrets, parameterName, value);
|
|
8328
|
-
if (typeof spelling !== "string" || isSingleDynamicReferenceToken(spelling)) return void 0;
|
|
8329
|
-
return renderedTokenOf(spelling, parentSecrets, plaintext);
|
|
8330
|
-
}
|
|
8331
|
-
function withdrawRenderedParameterSpelling(parentSecrets, parameterName) {
|
|
8332
|
-
const rendered = renderedParameterSpellings.get(parentSecrets);
|
|
8333
|
-
if (rendered?.has(parameterName)) rendered.set(parameterName, null);
|
|
8334
|
-
}
|
|
8335
|
-
function inheritedRenderedSpan(childSecrets, key, text) {
|
|
8336
|
-
const reads = inheritedParameterReads.get(childSecrets);
|
|
8337
|
-
if (reads === void 0 || typeof reads === "symbol") return void 0;
|
|
8338
|
-
for (const name of reads.names) {
|
|
8339
|
-
if (crossStackSourceKey({ Ref: name }) !== key) continue;
|
|
8340
|
-
const value = renderedParameterSpellings.get(reads.parent)?.get(name)?.value;
|
|
8341
|
-
if (value === void 0 || text !== void 0 && text !== value) return void 0;
|
|
8342
|
-
if (carriesChildOnlyPlaintext(value, childSecrets, reads.parent)) return void 0;
|
|
8343
|
-
const spelling = inheritedParameterExpression(reads.parent, name, value);
|
|
8344
|
-
if (typeof spelling !== "string") return void 0;
|
|
8345
|
-
if (redactForState(spelling, {
|
|
8346
|
-
provenance: "value-scan",
|
|
8347
|
-
secrets: childSecrets
|
|
8348
|
-
}) !== spelling) return void 0;
|
|
8349
|
-
return {
|
|
8350
|
-
value,
|
|
8351
|
-
spelling
|
|
8352
|
-
};
|
|
8353
|
-
}
|
|
8354
|
-
}
|
|
8355
|
-
const inheritedParameterReads = /* @__PURE__ */ new WeakMap();
|
|
8356
|
-
const POISONED_PARAMETER_READS = Symbol("cdkd.inherited-parameter-reads.poisoned");
|
|
8357
|
-
function parameterReadsFor(childSecrets, parentSecrets) {
|
|
8358
|
-
const reads = inheritedParameterReads.get(childSecrets);
|
|
8359
|
-
if (reads === void 0) {
|
|
8360
|
-
const created = {
|
|
8361
|
-
parent: parentSecrets,
|
|
8362
|
-
names: /* @__PURE__ */ new Set(),
|
|
8363
|
-
values: /* @__PURE__ */ new Map()
|
|
8364
|
-
};
|
|
8365
|
-
inheritedParameterReads.set(childSecrets, created);
|
|
8366
|
-
return created;
|
|
8367
|
-
}
|
|
8368
|
-
if (typeof reads === "symbol") return void 0;
|
|
8369
|
-
if (reads.parent !== parentSecrets) {
|
|
8370
|
-
inheritedParameterReads.set(childSecrets, POISONED_PARAMETER_READS);
|
|
8371
|
-
return;
|
|
8372
|
-
}
|
|
8373
|
-
return reads;
|
|
8374
|
-
}
|
|
8375
|
-
function recordInheritedParameterValue(childSecrets, parentSecrets, parameterName, value, declared) {
|
|
8376
|
-
const reads = parameterReadsFor(childSecrets, parentSecrets);
|
|
8377
|
-
if (reads === void 0) return;
|
|
8378
|
-
if (declared !== void 0) {
|
|
8379
|
-
if (reads.declared === void 0) reads.declared = declared;
|
|
8380
|
-
else if (reads.declared.size !== declared.size || [...declared].some((name) => !reads.declared.has(name))) {
|
|
8381
|
-
inheritedParameterReads.set(childSecrets, POISONED_PARAMETER_READS);
|
|
8382
|
-
return;
|
|
8383
|
-
}
|
|
8384
|
-
}
|
|
8385
|
-
if (reads.values.has(parameterName)) {
|
|
8386
|
-
if (!deepEqualJsonValue(reads.values.get(parameterName), value)) inheritedParameterReads.set(childSecrets, POISONED_PARAMETER_READS);
|
|
8387
|
-
return;
|
|
8388
|
-
}
|
|
8389
|
-
reads.values.set(parameterName, value);
|
|
8390
|
-
}
|
|
8391
|
-
function recordInheritedParameterRead(childSecrets, parentSecrets, parameterName) {
|
|
8392
|
-
parameterReadsFor(childSecrets, parentSecrets)?.names.add(parameterName);
|
|
8393
|
-
}
|
|
8394
|
-
function redactInheritedParameterValue(parentSecrets, parameterName, value) {
|
|
8395
|
-
return inheritedParameterExpression(parentSecrets, parameterName, value) ?? redactForState(value, {
|
|
8396
|
-
provenance: "value-scan",
|
|
8397
|
-
secrets: parentSecrets
|
|
8398
|
-
});
|
|
8399
|
-
}
|
|
8400
|
-
function positionByInheritedParameter(bag, source, secrets) {
|
|
8401
|
-
const keys = Object.keys(source);
|
|
8402
|
-
if (keys.length !== 1 || keys[0] !== "Ref") return void 0;
|
|
8403
|
-
const name = source["Ref"];
|
|
8404
|
-
if (typeof name !== "string") return void 0;
|
|
8405
|
-
const reads = inheritedParameterReads.get(secrets);
|
|
8406
|
-
if (reads === void 0 || typeof reads === "symbol" || !reads.names.has(name)) return;
|
|
8407
|
-
if (typeof bag !== "string" && !Array.isArray(bag)) return void 0;
|
|
8408
|
-
if (carriesChildOnlyPlaintext(bag, secrets, reads.parent)) return void 0;
|
|
8409
|
-
const answer = redactInheritedParameterValue(reads.parent, name, bag);
|
|
8410
|
-
if (!deepEqualJsonValue(redactForState(answer, {
|
|
8411
|
-
provenance: "value-scan",
|
|
8412
|
-
secrets
|
|
8413
|
-
}), answer)) return void 0;
|
|
8414
|
-
return answer;
|
|
8415
|
-
}
|
|
8416
|
-
const REREAD_PSEUDO_PARAMETERS = /* @__PURE__ */ new Set([
|
|
8417
|
-
"AWS::Region",
|
|
8418
|
-
"AWS::Partition",
|
|
8419
|
-
"AWS::URLSuffix",
|
|
8420
|
-
"AWS::AccountId"
|
|
8421
|
-
]);
|
|
8422
|
-
function templateRereadsAccountId(template) {
|
|
8423
|
-
if (template === void 0) return false;
|
|
8424
|
-
const resources = template.Resources !== null && typeof template.Resources === "object" ? template.Resources : void 0;
|
|
8425
|
-
const cached = resources && accountRereadVerdicts.get(resources);
|
|
8426
|
-
if (cached !== void 0 && cached.outputs === template.Outputs) return cached.verdict;
|
|
8427
|
-
const parts = resources ? Object.values(resources) : [];
|
|
8428
|
-
if (template.Outputs !== void 0) parts.push(template.Outputs);
|
|
8429
|
-
const verdict = parts.some(partRereadsAccountId);
|
|
8430
|
-
if (resources) accountRereadVerdicts.set(resources, {
|
|
8431
|
-
outputs: template.Outputs,
|
|
8432
|
-
verdict
|
|
8433
|
-
});
|
|
8434
|
-
return verdict;
|
|
8435
|
-
}
|
|
8436
|
-
const accountRereadVerdicts = /* @__PURE__ */ new WeakMap();
|
|
8437
|
-
function partRereadsAccountId(part) {
|
|
8438
|
-
let trigger = false;
|
|
8439
|
-
let account = false;
|
|
8440
|
-
const pending = [part];
|
|
8441
|
-
while (pending.length > 0 && !(trigger && account)) {
|
|
8442
|
-
const node = pending.pop();
|
|
8443
|
-
if (Array.isArray(node)) {
|
|
8444
|
-
pending.push(...node);
|
|
8445
|
-
continue;
|
|
8446
|
-
}
|
|
8447
|
-
if (node === null || typeof node !== "object") continue;
|
|
8448
|
-
for (const [key, value] of Object.entries(node)) {
|
|
8449
|
-
if (REREAD_TRIGGERS.has(key)) trigger = true;
|
|
8450
|
-
if (key === "Ref" && value === "AWS::AccountId") account = true;
|
|
8451
|
-
if (key === "Fn::Sub") {
|
|
8452
|
-
const text = Array.isArray(value) ? value[0] : value;
|
|
8453
|
-
if (typeof text === "string" && text.includes("${AWS::AccountId}")) account = true;
|
|
8454
|
-
}
|
|
8455
|
-
pending.push(value);
|
|
8456
|
-
}
|
|
8457
|
-
}
|
|
8458
|
-
return trigger && account;
|
|
8459
|
-
}
|
|
8460
|
-
const inheritedPseudoParameters = /* @__PURE__ */ new WeakMap();
|
|
8461
|
-
const POISONED_PSEUDO_PARAMETERS = Symbol("cdkd.inherited-pseudo-parameters.poisoned");
|
|
8462
|
-
function recordInheritedPseudoParameters(inheritedSecrets, values) {
|
|
8463
|
-
let table = inheritedPseudoParameters.get(inheritedSecrets);
|
|
8464
|
-
if (table === POISONED_PSEUDO_PARAMETERS) return;
|
|
8465
|
-
if (table === void 0) {
|
|
8466
|
-
table = /* @__PURE__ */ new Map();
|
|
8467
|
-
inheritedPseudoParameters.set(inheritedSecrets, table);
|
|
8468
|
-
}
|
|
8469
|
-
for (const [name, value] of values) {
|
|
8470
|
-
if (!REREAD_PSEUDO_PARAMETERS.has(name) || typeof value !== "string") continue;
|
|
8471
|
-
const known = table.get(name);
|
|
8472
|
-
if (known !== void 0 && known !== value) {
|
|
8473
|
-
inheritedPseudoParameters.set(inheritedSecrets, POISONED_PSEUDO_PARAMETERS);
|
|
8474
|
-
return;
|
|
8475
|
-
}
|
|
8476
|
-
table.set(name, value);
|
|
8477
|
-
}
|
|
8478
|
-
}
|
|
8479
|
-
function pseudoBindingOf(parentSecrets) {
|
|
8480
|
-
const table = inheritedPseudoParameters.get(parentSecrets);
|
|
8481
|
-
return (name) => table instanceof Map && table.has(name) ? { value: table.get(name) } : void 0;
|
|
8482
|
-
}
|
|
8483
|
-
function inheritedPseudoValue(parentSecrets, name) {
|
|
8484
|
-
const bound = pseudoBindingOf(parentSecrets)(name)?.value;
|
|
8485
|
-
return typeof bound === "string" ? bound : void 0;
|
|
8486
|
-
}
|
|
8487
|
-
function inheritedPseudoSpan(childSecrets, key) {
|
|
8488
|
-
const reads = inheritedParameterReads.get(childSecrets);
|
|
8489
|
-
if (reads === void 0 || typeof reads === "symbol") return void 0;
|
|
8490
|
-
for (const name of REREAD_PSEUDO_PARAMETERS) if (crossStackSourceKey({ Ref: name }) === key) return inheritedPseudoValue(reads.parent, name);
|
|
8491
|
-
}
|
|
8492
|
-
const REREAD_TRIGGERS = /* @__PURE__ */ new Set([
|
|
8493
|
-
"Fn::Select",
|
|
8494
|
-
"Fn::Split",
|
|
8495
|
-
"Fn::If"
|
|
8496
|
-
]);
|
|
8497
|
-
const MAX_REREAD_DEPTH = 16;
|
|
8498
|
-
const MAX_REREAD_CONDITIONS = 4;
|
|
8499
|
-
const REREAD_NO_VALUE = Symbol("cdkd.reread.no-value");
|
|
8500
|
-
function splitOutsideDynamicReferences(text, delimiter, standsForSecret) {
|
|
8501
|
-
if (delimiter === "") return text.split(delimiter);
|
|
8502
|
-
const spans = dynamicReferenceSpans(text).filter((span) => {
|
|
8503
|
-
const token = text.slice(span.start, span.end);
|
|
8504
|
-
return spanNamesResolvableService(token) && standsForSecret(token);
|
|
8505
|
-
});
|
|
8506
|
-
if (spans.length === 0) return text.split(delimiter);
|
|
8507
|
-
const pieces = [];
|
|
8508
|
-
let cursor = 0;
|
|
8509
|
-
let from = 0;
|
|
8510
|
-
for (;;) {
|
|
8511
|
-
const at = text.indexOf(delimiter, from);
|
|
8512
|
-
if (at === -1) break;
|
|
8513
|
-
const end = at + delimiter.length;
|
|
8514
|
-
const token = spans.find((span) => span.start < end && at < span.end);
|
|
8515
|
-
if (token !== void 0) {
|
|
8516
|
-
from = token.end;
|
|
8517
|
-
continue;
|
|
8518
|
-
}
|
|
8519
|
-
pieces.push(text.slice(cursor, at));
|
|
8520
|
-
cursor = end;
|
|
8521
|
-
from = end;
|
|
8522
|
-
}
|
|
8523
|
-
pieces.push(text.slice(cursor));
|
|
8524
|
-
return pieces;
|
|
8525
|
-
}
|
|
8526
|
-
function standsForInheritedSecret(parentSecrets, token) {
|
|
8527
|
-
return parentSecrets !== void 0 && resolvedPlaintextOf(parentSecrets, token) !== void 0;
|
|
8528
|
-
}
|
|
8529
|
-
const plainSplit = (text, delimiter) => text.split(delimiter);
|
|
8530
|
-
function evaluatePureRead(node, bind, pseudo, split, choose, depth = 0) {
|
|
8531
|
-
if (depth > MAX_REREAD_DEPTH) return void 0;
|
|
8532
|
-
const evaluate = (child) => evaluatePureRead(child, bind, pseudo, split, choose, depth + 1);
|
|
8533
|
-
if (typeof node === "string") return node.includes("{{resolve:") ? void 0 : { value: node };
|
|
8534
|
-
if (Array.isArray(node)) {
|
|
8535
|
-
const out = [];
|
|
8536
|
-
for (const element of node) {
|
|
8537
|
-
const evaluated = evaluate(element);
|
|
8538
|
-
if (evaluated === void 0 || evaluated.value === REREAD_NO_VALUE) return void 0;
|
|
8539
|
-
out.push(evaluated.value);
|
|
8540
|
-
}
|
|
8541
|
-
return { value: out };
|
|
8542
|
-
}
|
|
8543
|
-
if (!isPlainObject$7(node)) return void 0;
|
|
8544
|
-
const keys = Object.keys(node);
|
|
8545
|
-
if (keys.length !== 1) return void 0;
|
|
8546
|
-
const key = keys[0];
|
|
8547
|
-
const args = node[key];
|
|
8548
|
-
if (key === "Ref") {
|
|
8549
|
-
if (args === "AWS::NoValue") return { value: REREAD_NO_VALUE };
|
|
8550
|
-
return typeof args === "string" ? bindReadName(args, bind, pseudo) : void 0;
|
|
8551
|
-
}
|
|
8552
|
-
if (key === "Fn::If") {
|
|
8553
|
-
if (!Array.isArray(args) || args.length !== 3 || typeof args[0] !== "string") return void 0;
|
|
8554
|
-
const tookTrue = choose(args[0], node);
|
|
8555
|
-
if (tookTrue === void 0) return void 0;
|
|
8556
|
-
return evaluate(tookTrue ? args[1] : args[2]);
|
|
8557
|
-
}
|
|
8558
|
-
if (key === "Fn::Sub") return evaluatePureSub(args, bind, pseudo, evaluate);
|
|
8559
|
-
if (!Array.isArray(args) || args.length !== 2) return void 0;
|
|
8560
|
-
if (key === "Fn::Select") {
|
|
8561
|
-
const index = args[0];
|
|
8562
|
-
const position = typeof index === "number" ? index : typeof index === "string" && /^(0|[1-9][0-9]*)$/.test(index) ? Number(index) : void 0;
|
|
8563
|
-
if (position === void 0 || !Number.isSafeInteger(position) || position < 0) return void 0;
|
|
8564
|
-
const list = evaluate(args[1]);
|
|
8565
|
-
if (list === void 0 || !Array.isArray(list.value) || position >= list.value.length) return;
|
|
8566
|
-
return { value: list.value[position] };
|
|
8567
|
-
}
|
|
8568
|
-
const delimiter = args[0];
|
|
8569
|
-
if (typeof delimiter !== "string") return void 0;
|
|
8570
|
-
if (key === "Fn::Split") {
|
|
8571
|
-
const value = evaluate(args[1]);
|
|
8572
|
-
if (value === void 0 || typeof value.value !== "string") return void 0;
|
|
8573
|
-
return { value: split(value.value, delimiter) };
|
|
8574
|
-
}
|
|
8575
|
-
if (key === "Fn::Join") {
|
|
8576
|
-
const parts = evaluate(args[1]);
|
|
8577
|
-
if (parts === void 0 || !Array.isArray(parts.value)) return void 0;
|
|
8578
|
-
if (!parts.value.every((part) => typeof part === "string")) return void 0;
|
|
8579
|
-
return { value: parts.value.join(delimiter) };
|
|
8580
|
-
}
|
|
8581
|
-
}
|
|
8582
|
-
function evaluatePureSub(args, bind, pseudo, evaluate) {
|
|
8583
|
-
const [text, variables] = typeof args === "string" ? [args, {}] : Array.isArray(args) && args.length === 2 ? [args[0], args[1]] : [void 0, void 0];
|
|
8584
|
-
if (typeof text !== "string" || text.includes("{{resolve:") || !isPlainObject$7(variables)) return;
|
|
8585
|
-
const bound = /* @__PURE__ */ new Map();
|
|
8586
|
-
for (const [name, variable] of Object.entries(variables)) {
|
|
8587
|
-
const evaluated = evaluate(variable);
|
|
8588
|
-
if (evaluated === void 0 || typeof evaluated.value !== "string") return void 0;
|
|
8589
|
-
bound.set(name, evaluated.value);
|
|
8590
|
-
}
|
|
8591
|
-
let out = "";
|
|
8592
|
-
let cursor = 0;
|
|
8593
|
-
for (const match of text.matchAll(/\$\{(!)?([^}]*)\}/g)) {
|
|
8594
|
-
const name = match[2] ?? "";
|
|
8595
|
-
let replacement;
|
|
8596
|
-
if (match[1] === "!") replacement = `\${${name}}`;
|
|
8597
|
-
else if (name === "") replacement = match[0];
|
|
8598
|
-
else if (bound.has(name)) replacement = bound.get(name);
|
|
8599
|
-
else {
|
|
8600
|
-
if (name.includes(".")) return void 0;
|
|
8601
|
-
const value = bindReadName(name, bind, pseudo);
|
|
8602
|
-
if (value === void 0 || typeof value.value !== "string") return void 0;
|
|
8603
|
-
replacement = value.value;
|
|
8604
|
-
}
|
|
8605
|
-
out += text.slice(cursor, match.index) + replacement;
|
|
8606
|
-
cursor = match.index + match[0].length;
|
|
8607
|
-
}
|
|
8608
|
-
return { value: out + text.slice(cursor) };
|
|
8609
|
-
}
|
|
8610
|
-
function bindReadName(name, bind, pseudo) {
|
|
8611
|
-
if (!name.startsWith("AWS::")) return bind(name);
|
|
8612
|
-
return bind(name) === void 0 ? pseudo(name) : void 0;
|
|
8613
|
-
}
|
|
8614
|
-
function collectRereadConditions(node, names, depth = 0) {
|
|
8615
|
-
if (depth > MAX_REREAD_DEPTH) return false;
|
|
8616
|
-
if (Array.isArray(node)) return node.every((element) => collectRereadConditions(element, names, depth + 1));
|
|
8617
|
-
if (!isPlainObject$7(node)) return true;
|
|
8618
|
-
if (Object.hasOwn(node, "Fn::If")) {
|
|
8619
|
-
const args = node["Fn::If"];
|
|
8620
|
-
if (!Array.isArray(args) || typeof args[0] !== "string") return false;
|
|
8621
|
-
names.add(args[0]);
|
|
8622
|
-
}
|
|
8623
|
-
return Object.values(node).every((child) => collectRereadConditions(child, names, depth + 1));
|
|
8624
|
-
}
|
|
8625
|
-
function holdsRereadTrigger(node, depth = 0) {
|
|
8626
|
-
if (depth > MAX_REREAD_DEPTH) return false;
|
|
8627
|
-
if (Array.isArray(node)) return node.some((element) => holdsRereadTrigger(element, depth + 1));
|
|
8628
|
-
if (!isPlainObject$7(node)) return false;
|
|
8629
|
-
return Object.entries(node).some(([key, child]) => REREAD_TRIGGERS.has(key) || holdsRereadTrigger(child, depth + 1));
|
|
8630
|
-
}
|
|
8631
|
-
function rendersReadTo(spelling, parentSecrets, value) {
|
|
8632
|
-
if (typeof spelling === "string" && typeof value === "string") {
|
|
8633
|
-
if (spelling === value) return redactForState(spelling, {
|
|
8634
|
-
provenance: "value-scan",
|
|
8635
|
-
secrets: parentSecrets
|
|
8636
|
-
}) === spelling;
|
|
8637
|
-
return rendersLiteralTo(spelling, parentSecrets, value);
|
|
8638
|
-
}
|
|
8639
|
-
if (Array.isArray(spelling) && Array.isArray(value) && spelling.length === value.length) return spelling.every((element, i) => rendersReadTo(element, parentSecrets, value[i]));
|
|
8640
|
-
return false;
|
|
8641
|
-
}
|
|
8642
|
-
const REREAD_UNBOUND = Symbol("cdkd.reread.unbound");
|
|
8643
|
-
const REREAD_PARAMETER_FREE = Symbol("cdkd.reread.parameter-free");
|
|
8644
|
-
function diffSideReading(bind, parentSecrets) {
|
|
8645
|
-
return {
|
|
8646
|
-
bind: (name) => {
|
|
8647
|
-
const bound = bind(name);
|
|
8648
|
-
return bound && { value: redactInheritedParameterValue(parentSecrets, name, bound.value) };
|
|
8649
|
-
},
|
|
8650
|
-
split: (text, delimiter) => splitOutsideDynamicReferences(text, delimiter, (token) => standsForInheritedSecret(parentSecrets, token))
|
|
8651
|
-
};
|
|
8652
|
-
}
|
|
8653
|
-
function rereadUnder(source, bind, parentSecrets, choose) {
|
|
8654
|
-
const pseudo = pseudoBindingOf(parentSecrets);
|
|
8655
|
-
const resolved = evaluatePureRead(source, bind, pseudo, plainSplit, choose);
|
|
8656
|
-
if (resolved === void 0) return void 0;
|
|
8657
|
-
const diffSide = diffSideReading(bind, parentSecrets);
|
|
8658
|
-
const redacted = evaluatePureRead(source, diffSide.bind, pseudo, diffSide.split, choose);
|
|
8659
|
-
if (redacted === void 0) return void 0;
|
|
8660
|
-
if (resolved.value === REREAD_NO_VALUE || redacted.value === REREAD_NO_VALUE) return resolved.value === redacted.value ? REREAD_NO_VALUE : void 0;
|
|
8661
|
-
if (!rendersReadTo(redacted.value, parentSecrets, resolved.value)) return void 0;
|
|
8662
|
-
return {
|
|
8663
|
-
resolved: resolved.value,
|
|
8664
|
-
redacted: redacted.value
|
|
8665
|
-
};
|
|
8666
|
-
}
|
|
8667
|
-
function namesParameterOnBranches(node, choose, isParameter, depth = 0) {
|
|
8668
|
-
if (depth > MAX_REREAD_DEPTH) return true;
|
|
8669
|
-
if (typeof node === "string") return node.includes("{{resolve:");
|
|
8670
|
-
if (Array.isArray(node)) return node.some((element) => namesParameterOnBranches(element, choose, isParameter, depth + 1));
|
|
8671
|
-
if (!isPlainObject$7(node)) return false;
|
|
8672
|
-
if (Object.hasOwn(node, "Fn::If")) {
|
|
8673
|
-
const args = node["Fn::If"];
|
|
8674
|
-
if (Object.keys(node).length !== 1) return true;
|
|
8675
|
-
if (!Array.isArray(args) || args.length !== 3 || typeof args[0] !== "string") return true;
|
|
8676
|
-
const tookTrue = choose(args[0], node);
|
|
8677
|
-
if (tookTrue === void 0) return true;
|
|
8678
|
-
return namesParameterOnBranches(tookTrue ? args[1] : args[2], choose, isParameter, depth + 1);
|
|
8679
|
-
}
|
|
8680
|
-
if (typeof node["Ref"] === "string" && isParameter(node["Ref"])) return true;
|
|
8681
|
-
const sub = node["Fn::Sub"];
|
|
8682
|
-
const text = typeof sub === "string" ? sub : Array.isArray(sub) ? sub[0] : void 0;
|
|
8683
|
-
if (typeof text === "string") {
|
|
8684
|
-
for (const match of text.matchAll(/\$\{([^}!][^}]*)\}/g)) if (isParameter(match[1].trim()) || isParameter(match[1])) return true;
|
|
8685
|
-
}
|
|
8686
|
-
return Object.values(node).some((child) => namesParameterOnBranches(child, choose, isParameter, depth + 1));
|
|
8687
|
-
}
|
|
8688
|
-
function rereadAssignments(source, bind, parentSecrets, untakenWhenUnbound = () => false, parameterFree) {
|
|
8689
|
-
if (!holdsRereadTrigger(source)) return void 0;
|
|
8690
|
-
const conditions = /* @__PURE__ */ new Set();
|
|
8691
|
-
if (!collectRereadConditions(source, conditions)) return void 0;
|
|
8692
|
-
if (conditions.size > MAX_REREAD_CONDITIONS) return void 0;
|
|
8693
|
-
const names = [...conditions];
|
|
8694
|
-
const out = [];
|
|
8695
|
-
for (let assignment = 0; assignment < 2 ** names.length; assignment++) {
|
|
8696
|
-
const choose = (condition) => Math.floor(assignment / 2 ** names.indexOf(condition)) % 2 === 1;
|
|
8697
|
-
let unbound = false;
|
|
8698
|
-
const tracked = (name) => {
|
|
8699
|
-
const bound = bind(name);
|
|
8700
|
-
if (bound === void 0 && untakenWhenUnbound(name)) unbound = true;
|
|
8701
|
-
return bound;
|
|
8702
|
-
};
|
|
8703
|
-
const reread = rereadUnder(source, tracked, parentSecrets, choose);
|
|
8704
|
-
if (unbound) out.push(REREAD_UNBOUND);
|
|
8705
|
-
else if (reread !== void 0) out.push(reread);
|
|
8706
|
-
else if (parameterFree !== void 0 && !namesParameterOnBranches(source, choose, parameterFree)) out.push(REREAD_PARAMETER_FREE);
|
|
8707
|
-
else out.push(void 0);
|
|
8708
|
-
}
|
|
8709
|
-
return out;
|
|
8710
|
-
}
|
|
8711
|
-
function rereadParameterExpression(source, bind, parentSecrets) {
|
|
8712
|
-
const assignments = rereadAssignments(source, bind, parentSecrets, void 0, (name) => bind(name) !== void 0);
|
|
8713
|
-
if (assignments === void 0 || assignments.includes(void 0) || assignments.includes(REREAD_UNBOUND)) return;
|
|
8714
|
-
return assignments.find((entry) => entry !== void 0 && entry !== REREAD_NO_VALUE && entry !== REREAD_UNBOUND && entry !== REREAD_PARAMETER_FREE);
|
|
8715
|
-
}
|
|
8716
|
-
function ambiguousRereads(rereads) {
|
|
8717
|
-
return rereads.some((a, i) => rereads.slice(i + 1).some((b) => deepEqualJsonValue(a.resolved, b.resolved) && !deepEqualJsonValue(a.redacted, b.redacted)));
|
|
8718
|
-
}
|
|
8719
|
-
function positionByParameterReread(bag, source, secrets) {
|
|
8720
|
-
const reads = inheritedParameterReads.get(secrets);
|
|
8721
|
-
if (reads === void 0 || typeof reads === "symbol") return void 0;
|
|
8722
|
-
if (typeof bag !== "string" && !Array.isArray(bag)) return void 0;
|
|
8723
|
-
if (!holdsRereadTrigger(source)) return void 0;
|
|
8724
|
-
const bind = (name) => reads.values.has(name) ? { value: reads.values.get(name) } : void 0;
|
|
8725
|
-
let unrecorded = false;
|
|
8726
|
-
const recorded = rereadUnder(source, bind, reads.parent, (_, node) => {
|
|
8727
|
-
const taken = takenIfBranchOf(secrets, node);
|
|
8728
|
-
if (taken === void 0) unrecorded = true;
|
|
8729
|
-
return taken;
|
|
8730
|
-
});
|
|
8731
|
-
let answer;
|
|
8732
|
-
if (!unrecorded) {
|
|
8733
|
-
if (recorded === void 0 || recorded === REREAD_NO_VALUE || !deepEqualJsonValue(recorded.resolved, bag)) return;
|
|
8734
|
-
answer = recorded.redacted;
|
|
8735
|
-
} else {
|
|
8736
|
-
const declared = reads.declared;
|
|
8737
|
-
const assignments = rereadAssignments(source, bind, reads.parent, (name) => declared?.has(name) === true);
|
|
8738
|
-
if (assignments === void 0 || assignments.includes(void 0)) return void 0;
|
|
8739
|
-
const matching = assignments.filter((entry) => entry !== void 0 && entry !== REREAD_NO_VALUE && entry !== REREAD_UNBOUND && entry !== REREAD_PARAMETER_FREE && deepEqualJsonValue(entry.resolved, bag));
|
|
8740
|
-
if (matching.length === 0 || ambiguousRereads(matching)) return void 0;
|
|
8741
|
-
answer = matching[0].redacted;
|
|
8742
|
-
}
|
|
8743
|
-
if (carriesChildOnlyPlaintext(bag, secrets, reads.parent)) return void 0;
|
|
8744
|
-
if (!deepEqualJsonValue(redactForState(answer, {
|
|
8745
|
-
provenance: "value-scan",
|
|
8746
|
-
secrets
|
|
8747
|
-
}), answer)) return void 0;
|
|
8748
|
-
return answer;
|
|
8749
|
-
}
|
|
8750
|
-
function carriesChildOnlyPlaintext(value, childSecrets, parentSecrets) {
|
|
8751
|
-
const parentNeedles = new Set(substringNeedlesOf(parentSecrets));
|
|
8752
|
-
const childNeedles = new Set(substringNeedlesOf(childSecrets));
|
|
8753
|
-
const childOnly = [...childSecrets.keys()].filter((plaintext) => plaintext !== "" && (!parentSecrets.has(plaintext) || childNeedles.has(plaintext) && !parentNeedles.has(plaintext)));
|
|
8754
|
-
for (const needle of parentNeedles) if (needle.length >= 4 && !childSecrets.has(needle)) childOnly.push(needle);
|
|
8755
|
-
if (childOnly.length === 0) return false;
|
|
8756
|
-
const visit = (node) => {
|
|
8757
|
-
if (typeof node === "string") return childOnly.some((plaintext) => node.includes(plaintext));
|
|
8758
|
-
if (Array.isArray(node)) return node.some(visit);
|
|
8759
|
-
if (node !== null && typeof node === "object") return Object.values(node).some(visit);
|
|
8760
|
-
return false;
|
|
8761
|
-
};
|
|
8762
|
-
return visit(value);
|
|
8763
|
-
}
|
|
8764
|
-
|
|
8765
|
-
//#endregion
|
|
8766
|
-
//#region src/deployment/secret-redaction/placeholder-positions.ts
|
|
8767
|
-
function keyedPart(source) {
|
|
8768
|
-
const key = crossStackSourceKey(source);
|
|
8769
|
-
return key === void 0 ? UNKNOWN_PART : { key };
|
|
8770
|
-
}
|
|
8771
|
-
const MAX_PLACEHOLDER_DEPTH = 8;
|
|
8772
|
-
function pushPlaceholderPart(out, part, budget) {
|
|
8773
|
-
if (budget.remaining <= 0) {
|
|
8774
|
-
budget.exhausted = true;
|
|
8775
|
-
return;
|
|
8776
|
-
}
|
|
8777
|
-
budget.remaining -= 1;
|
|
8778
|
-
out.push(part);
|
|
8779
|
-
}
|
|
8780
|
-
function appendValuePlaceholderParts(value, out, budget, depth) {
|
|
8781
|
-
if (budget.exhausted) return;
|
|
8782
|
-
const literal = joinPartLiteralText(value);
|
|
8783
|
-
if (literal !== void 0) return pushPlaceholderPart(out, literal, budget);
|
|
8784
|
-
if (isPlainObject$7(value) && Object.keys(value).length === 1) {
|
|
8785
|
-
const ref = value["Ref"];
|
|
8786
|
-
if (typeof ref === "string" && ref !== "") return pushPlaceholderPart(out, keyedPart({ Ref: ref }), budget);
|
|
8787
|
-
if (depth >= MAX_PLACEHOLDER_DEPTH) {
|
|
8788
|
-
budget.exhausted = true;
|
|
8789
|
-
return;
|
|
8790
|
-
}
|
|
8791
|
-
if (appendParameterPlaceholderParts(value, out, budget, depth + 1)) return;
|
|
8792
|
-
return pushPlaceholderPart(out, keyedPart(value), budget);
|
|
8793
|
-
}
|
|
8794
|
-
pushPlaceholderPart(out, UNKNOWN_PART, budget);
|
|
8795
|
-
}
|
|
8796
|
-
function appendParameterPlaceholderParts(source, out, budget, depth) {
|
|
8797
|
-
const keys = Object.keys(source);
|
|
8798
|
-
if (keys.length !== 1) return false;
|
|
8799
|
-
const key = keys[0];
|
|
8800
|
-
if (key === "Fn::Join") {
|
|
8801
|
-
const args = source[key];
|
|
8802
|
-
if (!Array.isArray(args) || args.length !== 2) return false;
|
|
8803
|
-
const [delimiter, parts] = args;
|
|
8804
|
-
if (typeof delimiter !== "string" || !Array.isArray(parts)) return false;
|
|
8805
|
-
for (let index = 0; index < parts.length && !budget.exhausted; index++) {
|
|
8806
|
-
if (index > 0) pushPlaceholderPart(out, delimiter, budget);
|
|
8807
|
-
appendValuePlaceholderParts(parts[index], out, budget, depth);
|
|
8808
|
-
}
|
|
8809
|
-
return true;
|
|
8810
|
-
}
|
|
8811
|
-
if (key === "Fn::Sub") {
|
|
8812
|
-
const args = source[key];
|
|
8813
|
-
let template;
|
|
8814
|
-
let variables = {};
|
|
8815
|
-
if (typeof args === "string") template = args;
|
|
8816
|
-
else if (Array.isArray(args) && args.length === 2 && isPlainObject$7(args[1])) {
|
|
8817
|
-
template = args[0];
|
|
8818
|
-
variables = args[1];
|
|
8819
|
-
} else return false;
|
|
8820
|
-
if (typeof template !== "string") return false;
|
|
8821
|
-
let cursor = 0;
|
|
8822
|
-
for (const hit of template.matchAll(/\$\{(!)?([^}]*)\}/g)) {
|
|
8823
|
-
if (budget.exhausted) return true;
|
|
8824
|
-
pushPlaceholderPart(out, template.slice(cursor, hit.index), budget);
|
|
8825
|
-
cursor = hit.index + hit[0].length;
|
|
8826
|
-
const name = hit[2] ?? "";
|
|
8827
|
-
if (hit[1] === "!") pushPlaceholderPart(out, `\${${name}}`, budget);
|
|
8828
|
-
else if (name === "") pushPlaceholderPart(out, hit[0], budget);
|
|
8829
|
-
else if (Object.hasOwn(variables, name)) appendValuePlaceholderParts(variables[name], out, budget, depth);
|
|
8830
|
-
else if (name.includes(".")) pushPlaceholderPart(out, keyedPart({ "Fn::GetAtt": name }), budget);
|
|
8831
|
-
else pushPlaceholderPart(out, keyedPart({ Ref: name }), budget);
|
|
8832
|
-
}
|
|
8833
|
-
pushPlaceholderPart(out, template.slice(cursor), budget);
|
|
8834
|
-
return true;
|
|
8835
|
-
}
|
|
8836
|
-
return false;
|
|
8837
|
-
}
|
|
8838
|
-
function parameterPlaceholderParts(source, bag) {
|
|
8839
|
-
const budget = {
|
|
8840
|
-
remaining: bag.length * 2 + 16,
|
|
8841
|
-
exhausted: false
|
|
8842
|
-
};
|
|
8843
|
-
const out = [];
|
|
8844
|
-
if (!appendParameterPlaceholderParts(source, out, budget, 0)) return void 0;
|
|
8845
|
-
return budget.exhausted ? void 0 : out;
|
|
8846
|
-
}
|
|
8847
|
-
function positionByParameterPlaceholders(bag, source, secrets) {
|
|
8848
|
-
const associations = crossStackAssociations.get(secrets);
|
|
8849
|
-
const spanned = positionByRecordedParameterSpans(bag, source, secrets, associations);
|
|
8850
|
-
if (spanned !== void 0) return spanned;
|
|
8851
|
-
const parts = parameterPlaceholderParts(source, bag);
|
|
8852
|
-
if (parts === void 0) return void 0;
|
|
8853
|
-
const before = ["", ""];
|
|
8854
|
-
const after = ["", ""];
|
|
8855
|
-
let side = before;
|
|
8856
|
-
let unknown = false;
|
|
8857
|
-
let certified = 0;
|
|
8858
|
-
const spans = [];
|
|
8859
|
-
for (const part of parts) {
|
|
8860
|
-
let rendered;
|
|
8861
|
-
let persisted;
|
|
8862
|
-
if (typeof part === "string") {
|
|
8863
|
-
rendered = part;
|
|
8864
|
-
persisted = part;
|
|
8865
|
-
} else {
|
|
8866
|
-
let expression;
|
|
8867
|
-
let plaintext = "";
|
|
8868
|
-
if (part !== UNKNOWN_PART) {
|
|
8869
|
-
const association = associations?.get(part.key);
|
|
8870
|
-
if (association !== void 0 && typeof association !== "symbol") {
|
|
8871
|
-
plaintext = association.plaintext;
|
|
8872
|
-
expression = certifiedExpressionForLeaf(secrets, association, plaintext);
|
|
8873
|
-
}
|
|
8874
|
-
if (expression === void 0) {
|
|
8875
|
-
const inherited = inheritedRenderedSpan(secrets, part.key);
|
|
8876
|
-
if (inherited !== void 0) {
|
|
8877
|
-
plaintext = inherited.value;
|
|
8878
|
-
expression = inherited.spelling;
|
|
8879
|
-
}
|
|
8880
|
-
}
|
|
8881
|
-
}
|
|
8882
|
-
const pseudo = expression === void 0 && part !== UNKNOWN_PART ? inheritedPseudoSpan(secrets, part.key) : void 0;
|
|
8883
|
-
if (pseudo !== void 0) {
|
|
8884
|
-
side[0] += pseudo;
|
|
8885
|
-
side[1] += pseudo;
|
|
8886
|
-
continue;
|
|
8887
|
-
}
|
|
8888
|
-
if (expression === void 0) {
|
|
8889
|
-
if (unknown) return void 0;
|
|
8890
|
-
unknown = true;
|
|
8891
|
-
side = after;
|
|
8892
|
-
continue;
|
|
8893
|
-
}
|
|
8894
|
-
rendered = plaintext;
|
|
8895
|
-
persisted = expression;
|
|
8896
|
-
certified += 1;
|
|
8897
|
-
spans.push([
|
|
8898
|
-
side,
|
|
8899
|
-
side[0].length,
|
|
8900
|
-
plaintext.length
|
|
8901
|
-
]);
|
|
8902
|
-
}
|
|
8903
|
-
side[0] += rendered;
|
|
8904
|
-
side[1] += persisted;
|
|
8905
|
-
}
|
|
8906
|
-
if (certified === 0) return void 0;
|
|
8907
|
-
let persisted;
|
|
8908
|
-
if (!unknown) {
|
|
8909
|
-
if (before[0] !== bag) return void 0;
|
|
8910
|
-
persisted = before[1];
|
|
8911
|
-
} else {
|
|
8912
|
-
if (bag.length < before[0].length + after[0].length) return void 0;
|
|
8913
|
-
if (!bag.startsWith(before[0]) || !bag.endsWith(after[0])) return void 0;
|
|
8914
|
-
const middle = bag.slice(before[0].length, bag.length - after[0].length);
|
|
8915
|
-
if (redactForState(middle, {
|
|
8916
|
-
provenance: "value-scan",
|
|
8917
|
-
secrets
|
|
8918
|
-
}) !== middle) return void 0;
|
|
8919
|
-
persisted = before[1] + middle + after[1];
|
|
8920
|
-
}
|
|
8921
|
-
const afterStart = bag.length - after[0].length;
|
|
8922
|
-
return acceptedPlaceholderRendering(bag, persisted, spans.map(([side, offset, length]) => [(side === before ? 0 : afterStart) + offset, length]), secrets);
|
|
8923
|
-
}
|
|
8924
|
-
function acceptedPlaceholderRendering(bag, persisted, spans, secrets) {
|
|
8925
|
-
for (const plaintext of secrets.keys()) {
|
|
8926
|
-
if (plaintext.length < 4) continue;
|
|
8927
|
-
for (let at = bag.indexOf(plaintext); at !== -1; at = bag.indexOf(plaintext, at + 1)) {
|
|
8928
|
-
const end = at + plaintext.length;
|
|
8929
|
-
for (const [start, length] of spans) if (at < start + length && end > start && (at < start || end > start + length)) return void 0;
|
|
8930
|
-
}
|
|
8931
|
-
}
|
|
8932
|
-
if (redactForState(persisted, {
|
|
8933
|
-
provenance: "value-scan",
|
|
8934
|
-
secrets
|
|
8935
|
-
}) !== persisted) return void 0;
|
|
8936
|
-
return persisted;
|
|
8937
|
-
}
|
|
8938
|
-
function positionByRecordedParameterSpans(bag, source, secrets, associations) {
|
|
8939
|
-
const resolution = intrinsicLeafResolutionOf(secrets, source);
|
|
8940
|
-
if (resolution === void 0 || resolution.output !== bag) return void 0;
|
|
8941
|
-
const recorded = resolution.parameterSpans;
|
|
8942
|
-
if (recorded === void 0) return void 0;
|
|
8943
|
-
let previousEnd = 0;
|
|
8944
|
-
let cursor = 0;
|
|
8945
|
-
let persisted = "";
|
|
8946
|
-
const gaps = [];
|
|
8947
|
-
const certified = [];
|
|
8948
|
-
for (const { start, length, key } of recorded) {
|
|
8949
|
-
if (!(start >= previousEnd && length > 0 && start + length <= bag.length)) return void 0;
|
|
8950
|
-
previousEnd = start + length;
|
|
8951
|
-
const text = bag.slice(start, start + length);
|
|
8952
|
-
const association = associations?.get(key);
|
|
8953
|
-
const expression = (association !== void 0 && typeof association !== "symbol" ? certifiedExpressionForLeaf(secrets, association, text) : void 0) ?? inheritedRenderedSpan(secrets, key, text)?.spelling;
|
|
8954
|
-
if (expression === void 0) continue;
|
|
8955
|
-
const gap = bag.slice(cursor, start);
|
|
8956
|
-
gaps.push(gap);
|
|
8957
|
-
persisted += gap + expression;
|
|
8958
|
-
certified.push([start, length]);
|
|
8959
|
-
cursor = start + length;
|
|
8960
|
-
}
|
|
8961
|
-
if (certified.length === 0) return void 0;
|
|
8962
|
-
const tail = bag.slice(cursor);
|
|
8963
|
-
gaps.push(tail);
|
|
8964
|
-
persisted += tail;
|
|
8965
|
-
for (const gap of gaps) if (redactForState(gap, {
|
|
8966
|
-
provenance: "value-scan",
|
|
8967
|
-
secrets
|
|
8968
|
-
}) !== gap) return void 0;
|
|
8969
|
-
return acceptedPlaceholderRendering(bag, persisted, certified, secrets);
|
|
8970
|
-
}
|
|
8971
|
-
|
|
8972
|
-
//#endregion
|
|
8973
|
-
//#region src/deployment/secret-redaction/identity-keys.ts
|
|
8974
|
-
const ARRAY_IDENTITY_KEYS = ["Name", "Key"];
|
|
8975
|
-
function isUniquelyKeyedBy(items, key) {
|
|
8976
|
-
if (items.length === 0) return false;
|
|
8977
|
-
const seen = /* @__PURE__ */ new Set();
|
|
8978
|
-
for (const item of items) {
|
|
8979
|
-
if (!isPlainObject$7(item) || !Object.hasOwn(item, key)) return false;
|
|
8980
|
-
const id = item[key];
|
|
8981
|
-
if (typeof id !== "string" || id === "") return false;
|
|
8982
|
-
if (seen.has(id)) return false;
|
|
8983
|
-
seen.add(id);
|
|
8984
|
-
}
|
|
8985
|
-
return true;
|
|
8986
|
-
}
|
|
8987
|
-
function identityKeyFor(bag, source) {
|
|
8988
|
-
for (const key of ARRAY_IDENTITY_KEYS) if (isUniquelyKeyedBy(bag, key) && isUniquelyKeyedBy(source, key)) return key;
|
|
8989
|
-
}
|
|
8990
|
-
function positionListByCrossStackSource(bag, source, secrets) {
|
|
8991
|
-
const association = associationForSource(source, secrets);
|
|
8992
|
-
if (association === void 0) return void 0;
|
|
8993
|
-
return certifiedListForLeaf(secrets, association, bag);
|
|
8994
|
-
}
|
|
8995
|
-
|
|
8996
|
-
//#endregion
|
|
8997
|
-
//#region src/deployment/secret-redaction/redact-path.ts
|
|
8998
|
-
const NEVER_DROPPING_INTRINSICS = /* @__PURE__ */ new Set([
|
|
8999
|
-
"Fn::Join",
|
|
9000
|
-
"Fn::Sub",
|
|
9001
|
-
"Fn::Select",
|
|
9002
|
-
"Fn::Split",
|
|
9003
|
-
"Fn::GetAtt"
|
|
9004
|
-
]);
|
|
9005
|
-
function arrayElementDrop(element, depth = 0) {
|
|
9006
|
-
if (depth > 16) return "unknown";
|
|
9007
|
-
if (!isPlainObject$7(element)) return "never";
|
|
9008
|
-
if (Object.hasOwn(element, "Ref")) return element["Ref"] === "AWS::NoValue" ? "always" : "never";
|
|
9009
|
-
const keys = Object.keys(element);
|
|
9010
|
-
if (keys.filter((key) => key.startsWith("Fn::") || key === "Condition").length === 0) return "never";
|
|
9011
|
-
if (keys.length !== 1) return "unknown";
|
|
9012
|
-
if (NEVER_DROPPING_INTRINSICS.has(keys[0])) return "never";
|
|
9013
|
-
if (keys[0] !== "Fn::If") return "unknown";
|
|
9014
|
-
const args = element["Fn::If"];
|
|
9015
|
-
if (!Array.isArray(args) || args.length !== 3) return "unknown";
|
|
9016
|
-
const branches = [arrayElementDrop(args[1], depth + 1), arrayElementDrop(args[2], depth + 1)];
|
|
9017
|
-
if (branches.includes("unknown")) return "unknown";
|
|
9018
|
-
if (branches.every((branch) => branch === "never")) return "never";
|
|
9019
|
-
if (branches.every((branch) => branch === "always")) return "always";
|
|
9020
|
-
return "maybe";
|
|
9021
|
-
}
|
|
9022
|
-
function sourceElementsKeptFor(source, bagLength, secrets) {
|
|
9023
|
-
const recorded = secrets && droppedArrayElementsOf(secrets, source);
|
|
9024
|
-
if (recorded !== void 0) {
|
|
9025
|
-
if (source.length - recorded.length !== bagLength) return void 0;
|
|
9026
|
-
return source.filter((_, i) => !recorded.includes(i));
|
|
9027
|
-
}
|
|
9028
|
-
const drops = source.map((element) => arrayElementDrop(element));
|
|
9029
|
-
if (drops.includes("unknown")) return void 0;
|
|
9030
|
-
const always = drops.filter((drop) => drop === "always").length;
|
|
9031
|
-
const maybe = drops.filter((drop) => drop === "maybe").length;
|
|
9032
|
-
const dropped = source.length - bagLength;
|
|
9033
|
-
let dropMaybe;
|
|
9034
|
-
if (dropped === always) dropMaybe = false;
|
|
9035
|
-
else if (dropped === always + maybe) dropMaybe = true;
|
|
9036
|
-
else return void 0;
|
|
9037
|
-
return source.filter((_, i) => drops[i] === "never" || drops[i] === "maybe" && !dropMaybe);
|
|
9038
|
-
}
|
|
9039
|
-
function keptLiteralsCorroborate(kept, bag, secrets) {
|
|
9040
|
-
return kept.every((element, i) => keptElementCorroborates(element, bag[i], secrets));
|
|
9041
|
-
}
|
|
9042
|
-
function isIntrinsicNode(value) {
|
|
9043
|
-
if (!isPlainObject$7(value)) return false;
|
|
9044
|
-
const keys = Object.keys(value);
|
|
9045
|
-
return keys.length === 1 && (keys[0] === "Ref" || keys[0].startsWith("Fn::"));
|
|
9046
|
-
}
|
|
9047
|
-
function keptElementCorroborates(source, bag, secrets, depth = 0) {
|
|
9048
|
-
if (depth > 16) return false;
|
|
9049
|
-
if (typeof source === "string") {
|
|
9050
|
-
if (!source.includes("{{resolve:")) return source === bag;
|
|
9051
|
-
return isSingleDynamicReferenceToken(source) && resolvedPlaintextOf(secrets, source) === bag;
|
|
9052
|
-
}
|
|
9053
|
-
if (source === null || typeof source !== "object") return source === bag;
|
|
9054
|
-
if (isIntrinsicNode(source)) return true;
|
|
9055
|
-
if (Array.isArray(source)) return Array.isArray(bag) && bag.length === source.length && source.every((element, i) => keptElementCorroborates(element, bag[i], secrets, depth + 1));
|
|
9056
|
-
if (!isPlainObject$7(source) || !isPlainObject$7(bag)) return false;
|
|
9057
|
-
if (Object.keys(bag).some((key) => !Object.hasOwn(source, key))) return false;
|
|
9058
|
-
return Object.entries(source).every(([key, value]) => Object.hasOwn(bag, key) ? keptElementCorroborates(value, bag[key], secrets, depth + 1) : arrayElementDrop(value) === "always" || arrayElementDrop(value) === "maybe");
|
|
9059
|
-
}
|
|
9060
|
-
function corroboratesWhateverResolves(source, depth = 0) {
|
|
9061
|
-
if (depth > 16) return false;
|
|
9062
|
-
if (typeof source === "string") return !source.includes("{{resolve:");
|
|
9063
|
-
if (source === null || typeof source !== "object") return true;
|
|
9064
|
-
if (isIntrinsicNode(source)) return true;
|
|
9065
|
-
if (Array.isArray(source)) return source.every((element) => arrayElementDrop(element) === "never" && corroboratesWhateverResolves(element, depth + 1));
|
|
9066
|
-
if (!isPlainObject$7(source)) return false;
|
|
9067
|
-
if (Object.keys(source).some((key) => key === "Ref" || key.startsWith("Fn::"))) return false;
|
|
9068
|
-
return Object.values(source).every((value) => arrayElementDrop(value) !== "unknown" && corroboratesWhateverResolves(value, depth + 1));
|
|
9069
|
-
}
|
|
9070
|
-
function arrayPairsWhateverDrops(source) {
|
|
9071
|
-
if (!source.some((element) => isPlainObject$7(element) && (Object.hasOwn(element, "Fn::If") || element["Ref"] === "AWS::NoValue" || Array.isArray(element["Fn::FindInMap"]) && element["Fn::FindInMap"].length > 3))) return true;
|
|
9072
|
-
return source.every((element) => corroboratesWhateverResolves(element));
|
|
9073
|
-
}
|
|
9074
|
-
function redactByPath(bag, source, secrets, rules, secretExpressions, bagIsSameGeneration) {
|
|
9075
|
-
if (isDynamicReferenceString(source) && typeof bag === "string") {
|
|
9076
|
-
if (isSingleDynamicReferenceToken(source) && (rules.trustAnyExpression || isKnownSecretExpression(source, secretExpressions))) {
|
|
9077
|
-
if (!rules.sourceIsSameGeneration && isSingleDynamicReferenceToken(bag)) {
|
|
9078
|
-
if (!spanNamesResolvableService(bag)) return redactForState(bag, {
|
|
9079
|
-
provenance: "value-scan",
|
|
9080
|
-
secrets
|
|
9081
|
-
});
|
|
9082
|
-
return secrets.get(bag) ?? bag;
|
|
9083
|
-
}
|
|
9084
|
-
return source;
|
|
9085
|
-
}
|
|
9086
|
-
return positionByEmbeddedSpan(bag, source, secrets, bagIsSameGeneration);
|
|
9087
|
-
}
|
|
9088
|
-
if ((typeof bag === "string" || Array.isArray(bag)) && isPlainObject$7(source)) {
|
|
9089
|
-
const inherited = positionByInheritedParameter(bag, source, secrets);
|
|
9090
|
-
if (inherited !== void 0) return inherited;
|
|
9091
|
-
const reread = positionByParameterReread(bag, source, secrets);
|
|
9092
|
-
if (reread !== void 0) return reread;
|
|
9093
|
-
}
|
|
9094
|
-
if (typeof bag === "string" && isPlainObject$7(source)) {
|
|
9095
|
-
const certified = positionByCrossStackSource(bag, source, secrets);
|
|
9096
|
-
if (certified !== void 0) return certified;
|
|
9097
|
-
const placeheld = positionByParameterPlaceholders(bag, source, secrets);
|
|
9098
|
-
if (placeheld !== void 0) return placeheld;
|
|
9099
|
-
const positioned = positionByIntrinsicSkeleton(bag, source, secrets, secretExpressions);
|
|
9100
|
-
if (positioned !== void 0) return positioned;
|
|
9101
|
-
const framed = positionByIntrinsicFrame(bag, source, secrets, secretExpressions, bagIsSameGeneration);
|
|
9102
|
-
if (framed !== void 0) return framed;
|
|
9103
|
-
}
|
|
9104
|
-
if (Array.isArray(bag) && isPlainObject$7(source)) {
|
|
9105
|
-
const positionedList = positionListByCrossStackSource(bag, source, secrets);
|
|
9106
|
-
if (positionedList !== void 0) return positionedList;
|
|
9107
|
-
}
|
|
9108
|
-
if (Array.isArray(bag) && Array.isArray(source)) {
|
|
9109
|
-
const key = identityKeyFor(bag, source);
|
|
9110
|
-
if (key !== void 0) {
|
|
9111
|
-
const sourceIndexById = /* @__PURE__ */ new Map();
|
|
9112
|
-
source.forEach((item, i) => {
|
|
9113
|
-
sourceIndexById.set(item[key], i);
|
|
9114
|
-
});
|
|
9115
|
-
let orderPreserved = true;
|
|
9116
|
-
const partnerIndex = bag.map((item, i) => {
|
|
9117
|
-
const j = sourceIndexById.get(item[key]);
|
|
9118
|
-
if (j === void 0) return -1;
|
|
9119
|
-
if (j !== i) orderPreserved = false;
|
|
9120
|
-
return j;
|
|
9121
|
-
});
|
|
9122
|
-
const positionalIsExact = rules.descendArrays && bag.length === source.length && orderPreserved;
|
|
9123
|
-
return bag.map((item, i) => {
|
|
9124
|
-
const j = partnerIndex[i];
|
|
9125
|
-
if (j >= 0) return redactByPath(item, source[j], secrets, rules, secretExpressions, bagIsSameGeneration);
|
|
9126
|
-
if (positionalIsExact) return redactByPath(item, source[i], secrets, rules, secretExpressions, bagIsSameGeneration);
|
|
9127
|
-
return redactForState(item, {
|
|
9128
|
-
provenance: "value-scan",
|
|
9129
|
-
secrets
|
|
9130
|
-
});
|
|
9131
|
-
});
|
|
9132
|
-
}
|
|
9133
|
-
if (rules.descendArrays && bag.length === source.length) return bag.map((item, i) => redactByPath(item, source[i], secrets, rules, secretExpressions, bagIsSameGeneration));
|
|
9134
|
-
if (rules.descendArrays && bag.length < source.length) {
|
|
9135
|
-
const kept = sourceElementsKeptFor(source, bag.length, secrets);
|
|
9136
|
-
if (kept !== void 0 && keptLiteralsCorroborate(kept, bag, secrets)) return bag.map((item, i) => redactByPath(item, kept[i], secrets, rules, secretExpressions, bagIsSameGeneration));
|
|
9137
|
-
}
|
|
9138
|
-
}
|
|
9139
|
-
if (isPlainObject$7(bag) && hasPlainPrototype(bag) && isPlainObject$7(source)) {
|
|
9140
|
-
const out = Object.create(null);
|
|
9141
|
-
for (const [k, v] of Object.entries(bag)) out[k] = Object.hasOwn(source, k) ? redactByPath(v, source[k], secrets, rules, secretExpressions, bagIsSameGeneration) : redactForState(v, {
|
|
9142
|
-
provenance: "value-scan",
|
|
9143
|
-
secrets
|
|
9144
|
-
});
|
|
9145
|
-
return out;
|
|
9146
|
-
}
|
|
9147
|
-
return redactForState(bag, {
|
|
9148
|
-
provenance: "value-scan",
|
|
9149
|
-
secrets
|
|
9150
|
-
});
|
|
9151
|
-
}
|
|
9152
|
-
function isReadbackProjectedFromState(rules) {
|
|
9153
|
-
return rules.trustAnyExpression && !rules.descendArrays && rules.sourceIsSameGeneration;
|
|
9154
|
-
}
|
|
9155
|
-
function subtreeHasDynamicReference(value) {
|
|
9156
|
-
if (isDynamicReferenceString(value)) return true;
|
|
9157
|
-
if (Array.isArray(value)) return value.some(subtreeHasDynamicReference);
|
|
9158
|
-
if (isPlainObject$7(value)) return Object.values(value).some(subtreeHasDynamicReference);
|
|
9159
|
-
return false;
|
|
9160
|
-
}
|
|
9161
|
-
function pathCrossesDottedKey(bag, path) {
|
|
9162
|
-
const segments = path.split(".");
|
|
9163
|
-
let cursor = bag;
|
|
9164
|
-
for (let i = 0; i < segments.length; i++) {
|
|
9165
|
-
if (cursor === null || typeof cursor !== "object" || Array.isArray(cursor)) return false;
|
|
9166
|
-
const rest = segments.slice(i).join(".");
|
|
9167
|
-
for (const key of Object.keys(cursor)) if (key.includes(".") && (rest === key || rest.startsWith(`${key}.`))) return true;
|
|
9168
|
-
if (!Object.hasOwn(cursor, segments[i])) return false;
|
|
9169
|
-
cursor = cursor[segments[i]];
|
|
9170
|
-
}
|
|
9171
|
-
return false;
|
|
9172
|
-
}
|
|
9173
|
-
function isUncertifiedBaselineMaskPosition(properties, path) {
|
|
9174
|
-
if (pathCrossesDottedKey(properties, path)) return false;
|
|
9175
|
-
let cursor = properties;
|
|
9176
|
-
for (const segment of path.split(".")) {
|
|
9177
|
-
if (typeof cursor === "string") break;
|
|
9178
|
-
if (cursor === null || typeof cursor !== "object" || Array.isArray(cursor) || !Object.hasOwn(cursor, segment)) return false;
|
|
9179
|
-
cursor = cursor[segment];
|
|
9180
|
-
}
|
|
9181
|
-
if (typeof cursor === "string") return isDynamicReferenceString(cursor) && cursor !== "***";
|
|
9182
|
-
return subtreeHasDynamicReference(cursor) && !carriesSecretMask(cursor);
|
|
9183
|
-
}
|
|
9184
|
-
const DYNAMIC_REFERENCE_TOKEN_SCAN = new RegExp(`\\{\\{resolve:${DYNAMIC_REFERENCE_INNER}\\}\\}`, "g");
|
|
9185
|
-
function dynamicReferenceTokens(value) {
|
|
9186
|
-
return value.match(DYNAMIC_REFERENCE_TOKEN_SCAN) ?? [];
|
|
9187
|
-
}
|
|
9188
|
-
function dynamicReferenceSpans(value) {
|
|
9189
|
-
DYNAMIC_REFERENCE_TOKEN_SCAN.lastIndex = 0;
|
|
9190
|
-
const spans = [];
|
|
9191
|
-
for (const match of value.matchAll(DYNAMIC_REFERENCE_TOKEN_SCAN)) spans.push({
|
|
9192
|
-
start: match.index,
|
|
9193
|
-
end: match.index + match[0].length
|
|
9194
|
-
});
|
|
9195
|
-
return spans;
|
|
9196
|
-
}
|
|
9197
|
-
function mixedLeafMayCarryPublicReference(source, secrets, readback) {
|
|
9198
|
-
if (secrets.size === 0) return mixedLeafProvenPublic(source, secrets, readback);
|
|
9199
|
-
return dynamicReferenceTokens(source).some((token) => token.startsWith("{{resolve:ssm:") && !isRecordedSecretExpression(token));
|
|
9200
|
-
}
|
|
9201
|
-
function mixedLeafProvenPublic(source, secrets, readback) {
|
|
9202
|
-
const tokens = dynamicReferenceTokens(source);
|
|
9203
|
-
if (tokens.length === 0) return false;
|
|
9204
|
-
const values = /* @__PURE__ */ new Map();
|
|
9205
|
-
for (const token of tokens) {
|
|
9206
|
-
if (!token.startsWith("{{resolve:ssm:")) return false;
|
|
9207
|
-
const value = provenPublicValue(secrets, token);
|
|
9208
|
-
if (value === void 0) return false;
|
|
9209
|
-
values.set(token, value);
|
|
9210
|
-
}
|
|
9211
|
-
DYNAMIC_REFERENCE_TOKEN_SCAN.lastIndex = 0;
|
|
9212
|
-
return source.replace(DYNAMIC_REFERENCE_TOKEN_SCAN, (token) => values.get(token)) === readback;
|
|
9213
|
-
}
|
|
9214
|
-
function hasPlainPrototype(value) {
|
|
9215
|
-
const proto = Object.getPrototypeOf(value);
|
|
9216
|
-
return proto === Object.prototype || proto === null;
|
|
9217
|
-
}
|
|
9218
|
-
function isOrdinaryDate(value) {
|
|
9219
|
-
if (Object.getPrototypeOf(value) !== Date.prototype) return false;
|
|
9220
|
-
try {
|
|
9221
|
-
Date.prototype.getTime.call(value);
|
|
9222
|
-
} catch {
|
|
9223
|
-
return false;
|
|
9224
|
-
}
|
|
9225
|
-
return Reflect.ownKeys(value).length === 0;
|
|
9226
|
-
}
|
|
9227
|
-
function deepEqualJsonValue(a, b) {
|
|
9228
|
-
if (a === b) return true;
|
|
9229
|
-
if (Array.isArray(a)) {
|
|
9230
|
-
if (!Array.isArray(b) || a.length !== b.length) return false;
|
|
9231
|
-
return a.every((item, i) => deepEqualJsonValue(item, b[i]));
|
|
9232
|
-
}
|
|
9233
|
-
if (isPlainObject$7(a)) {
|
|
9234
|
-
if (!isPlainObject$7(b)) return false;
|
|
9235
|
-
if (!hasPlainPrototype(a) || !hasPlainPrototype(b)) return false;
|
|
9236
|
-
const keys = Object.keys(a);
|
|
9237
|
-
if (keys.length !== Object.keys(b).length) return false;
|
|
9238
|
-
return keys.every((k) => Object.hasOwn(b, k) && deepEqualJsonValue(a[k], b[k]));
|
|
9239
|
-
}
|
|
9240
|
-
return false;
|
|
9241
|
-
}
|
|
9242
|
-
|
|
9243
|
-
//#endregion
|
|
9244
|
-
//#region src/deployment/secret-redaction/readback-certification.ts
|
|
9245
|
-
function refuseUncertifiedSubtree(value, sourceLiterals, mark, seen = /* @__PURE__ */ new Map()) {
|
|
9246
|
-
if (typeof value === "string") {
|
|
9247
|
-
if (isSingleDynamicReferenceToken(value) && spanNamesResolvableService(value) || sourceLiterals.has(value)) return value;
|
|
9248
|
-
if (value === "") return value;
|
|
9249
|
-
return mark ? POSITION_UNCERTIFIED : "***";
|
|
9250
|
-
}
|
|
9251
|
-
if (value === null || typeof value !== "object") return value;
|
|
9252
|
-
const memo = seen.get(value);
|
|
9253
|
-
if (memo !== void 0) return memo;
|
|
9254
|
-
if (Array.isArray(value)) {
|
|
9255
|
-
const out = [];
|
|
9256
|
-
seen.set(value, out);
|
|
9257
|
-
for (const item of value) out.push(refuseUncertifiedSubtree(item, sourceLiterals, mark, seen));
|
|
9258
|
-
return out;
|
|
9259
|
-
}
|
|
9260
|
-
if (isPlainObject$7(value) && hasPlainPrototype(value)) {
|
|
9261
|
-
const out = Object.create(null);
|
|
9262
|
-
seen.set(value, out);
|
|
9263
|
-
for (const [k, v] of Object.entries(value)) out[k] = refuseUncertifiedSubtree(v, sourceLiterals, mark, seen);
|
|
9264
|
-
return out;
|
|
9265
|
-
}
|
|
9266
|
-
if (ArrayBuffer.isView(value)) return mark ? POSITION_UNCERTIFIED : "***";
|
|
9267
|
-
seen.set(value, value);
|
|
9268
|
-
return value;
|
|
9269
|
-
}
|
|
9270
|
-
function refuseAgainstSource(bag, source, failClosed, mark) {
|
|
9271
|
-
if (failClosed !== true) return bag;
|
|
9272
|
-
return refuseUncertifiedSubtree(bag, wholeStringLeavesOf(source), mark);
|
|
9273
|
-
}
|
|
9274
|
-
function unpairedSourceCarriesReference(source, key, bagIdentities) {
|
|
9275
|
-
return source.some((item) => !bagIdentities.has(item[key]) && subtreeHasDynamicReference(item));
|
|
9276
|
-
}
|
|
9277
|
-
function refuseUncertifiedReadbackPositions(bag, source, secrets, failClosed, learn, mark) {
|
|
9278
|
-
if (isDynamicReferenceString(source) && typeof bag === "string") {
|
|
9279
|
-
if (isSingleDynamicReferenceToken(source)) {
|
|
9280
|
-
if (learn) learnWholeTokenNeedle(learn, bag, source);
|
|
9281
|
-
return mark ? POSITION_DECIDED : source;
|
|
9282
|
-
}
|
|
9283
|
-
if (mixedLeafMayCarryPublicReference(source, secrets, bag)) return mark ? POSITION_DECIDED : bag;
|
|
9284
|
-
if (learn) learnMixedLeafNeedle(learn, bag, source);
|
|
9285
|
-
return mark ? POSITION_DECIDED : source;
|
|
9286
|
-
}
|
|
9287
|
-
if (!subtreeHasDynamicReference(source)) return bag;
|
|
9288
|
-
if (isPlainObject$7(bag) && hasPlainPrototype(bag) && isPlainObject$7(source)) {
|
|
9289
|
-
const out = Object.create(null);
|
|
9290
|
-
for (const [k, v] of Object.entries(bag)) out[k] = Object.hasOwn(source, k) ? refuseUncertifiedReadbackPositions(v, source[k], secrets, failClosed, learn, mark) : v;
|
|
9291
|
-
return out;
|
|
9292
|
-
}
|
|
9293
|
-
if (Array.isArray(bag) && Array.isArray(source)) {
|
|
9294
|
-
const key = identityKeyFor(bag, source);
|
|
9295
|
-
if (key === void 0) {
|
|
9296
|
-
if (!unkeyedArrayPairsByAnchors(bag, source)) return refuseAgainstSource(bag, source, failClosed, mark);
|
|
9297
|
-
return bag.map((item, i) => refuseUncertifiedReadbackPositions(item, source[i], secrets, failClosed, learn, mark));
|
|
9298
|
-
}
|
|
9299
|
-
const sourceByIdentity = /* @__PURE__ */ new Map();
|
|
9300
|
-
for (const item of source) sourceByIdentity.set(item[key], item);
|
|
9301
|
-
const orphanLiterals = unpairedSourceCarriesReference(source, key, new Set(bag.map((item) => item[key]))) && failClosed === true ? wholeStringLeavesOf(source) : void 0;
|
|
9302
|
-
return bag.map((item) => {
|
|
9303
|
-
const partner = sourceByIdentity.get(item[key]);
|
|
9304
|
-
return partner === void 0 ? orphanLiterals !== void 0 ? refuseUncertifiedSubtree(item, orphanLiterals, mark) : item : refuseUncertifiedReadbackPositions(item, partner, secrets, failClosed, learn, mark);
|
|
9305
|
-
});
|
|
9306
|
-
}
|
|
9307
|
-
return refuseAgainstSource(bag, source, failClosed, mark);
|
|
9308
|
-
}
|
|
9309
|
-
|
|
9310
|
-
//#endregion
|
|
9311
|
-
//#region src/deployment/secret-redaction/anchors.ts
|
|
9312
|
-
function isDistinguishingAnchor(value) {
|
|
9313
|
-
if (typeof value === "string") return value !== "";
|
|
9314
|
-
if (Array.isArray(value)) return value.some(isDistinguishingAnchor);
|
|
9315
|
-
if (isPlainObject$7(value)) return Object.values(value).some(isDistinguishingAnchor);
|
|
9316
|
-
return false;
|
|
9317
|
-
}
|
|
9318
|
-
const ANCHOR_REFERENCE_MASK = "<ref>";
|
|
9319
|
-
function anchorSignature(source) {
|
|
9320
|
-
if (isDynamicReferenceString(source)) return ANCHOR_REFERENCE_MASK;
|
|
9321
|
-
if (Array.isArray(source)) return `[${source.map(anchorSignature).sort().join(",")}]`;
|
|
9322
|
-
if (isPlainObject$7(source)) return `{${Object.keys(source).sort().map((k) => `${JSON.stringify(k)}:${anchorSignature(source[k])}`).join(",")}}`;
|
|
9323
|
-
return JSON.stringify(source) ?? "undefined";
|
|
9324
|
-
}
|
|
9325
|
-
function anchorsCorroboratePairing(bag, source, anchors) {
|
|
9326
|
-
if (!subtreeHasDynamicReference(source)) {
|
|
9327
|
-
if (!deepEqualJsonValue(bag, source)) return false;
|
|
9328
|
-
if (isDistinguishingAnchor(source)) anchors.distinguishing += 1;
|
|
9329
|
-
return true;
|
|
9330
|
-
}
|
|
9331
|
-
if (isDynamicReferenceString(source)) return typeof bag === "string";
|
|
9332
|
-
if (isPlainObject$7(source)) {
|
|
9333
|
-
if (!isPlainObject$7(bag)) return false;
|
|
9334
|
-
return Object.keys(source).every((k) => Object.hasOwn(bag, k) && anchorsCorroboratePairing(bag[k], source[k], anchors));
|
|
9335
|
-
}
|
|
9336
|
-
if (Array.isArray(source)) {
|
|
9337
|
-
if (!Array.isArray(bag) || bag.length !== source.length) return false;
|
|
9338
|
-
return source.every((item, i) => anchorsCorroboratePairing(bag[i], item, anchors));
|
|
9339
|
-
}
|
|
9340
|
-
return false;
|
|
9341
|
-
}
|
|
9342
|
-
function unkeyedArrayPairsByAnchors(bag, source) {
|
|
9343
|
-
if (bag.length !== source.length) return false;
|
|
9344
|
-
const distinguishingPerElement = [];
|
|
9345
|
-
for (const [i, item] of source.entries()) {
|
|
9346
|
-
const anchors = { distinguishing: 0 };
|
|
9347
|
-
if (!anchorsCorroboratePairing(bag[i], item, anchors)) return false;
|
|
9348
|
-
distinguishingPerElement.push(anchors.distinguishing);
|
|
9349
|
-
}
|
|
9350
|
-
const frameDistinguishing = source.reduce((total, item, i) => subtreeHasDynamicReference(item) ? total : total + distinguishingPerElement[i], 0);
|
|
9351
|
-
const signatures = /* @__PURE__ */ new Set();
|
|
9352
|
-
for (const [i, item] of source.entries()) {
|
|
9353
|
-
if (!subtreeHasDynamicReference(item)) continue;
|
|
9354
|
-
const signature = anchorSignature(item);
|
|
9355
|
-
if (signatures.has(signature)) return false;
|
|
9356
|
-
signatures.add(signature);
|
|
9357
|
-
if (distinguishingPerElement[i] > 0) continue;
|
|
9358
|
-
if (!isDynamicReferenceString(item) || frameDistinguishing === 0) return false;
|
|
9359
|
-
}
|
|
9360
|
-
return true;
|
|
9361
|
-
}
|
|
9362
|
-
const POSITION_DECIDED = Symbol("position decided by a position pass");
|
|
9363
|
-
const POSITION_UNCERTIFIED = Symbol("position refused by a position pass");
|
|
9364
|
-
function learnNeedle(collector, plaintext, expression) {
|
|
9365
|
-
if (plaintext.length < 4) return;
|
|
9366
|
-
if (collector.poisoned.has(plaintext)) return;
|
|
9367
|
-
if (expressionSecretIsInferred(expression)) collector.inferred.add(plaintext);
|
|
9368
|
-
const already = collector.needles.get(plaintext);
|
|
9369
|
-
if (already === void 0) {
|
|
9370
|
-
collector.needles.set(plaintext, expression);
|
|
9371
|
-
return;
|
|
9372
|
-
}
|
|
9373
|
-
if (already === expression) return;
|
|
9374
|
-
collector.needles.delete(plaintext);
|
|
9375
|
-
collector.poisoned.add(plaintext);
|
|
9376
|
-
}
|
|
9377
|
-
const SECRET_BEARING_REFERENCE_PREFIXES = [
|
|
9378
|
-
"{{resolve:secretsmanager:",
|
|
9379
|
-
"{{resolve:ssm-secure:",
|
|
9380
|
-
"{{resolve:ssm:"
|
|
9381
|
-
];
|
|
9382
|
-
function spanNamesResolvableService(token) {
|
|
9383
|
-
return SECRET_BEARING_REFERENCE_PREFIXES.some((prefix) => token.startsWith(prefix));
|
|
9384
|
-
}
|
|
9385
|
-
function resolvableReferenceSpans(value, vouchedExpressions) {
|
|
9386
|
-
const spans = dynamicReferenceSpans(value).filter((span) => spanNamesResolvableService(value.slice(span.start, span.end)));
|
|
9387
|
-
const starts = new Set(spans.map((span) => span.start));
|
|
9388
|
-
for (const prefix of SECRET_BEARING_REFERENCE_PREFIXES) for (let at = value.indexOf(prefix); at >= 0; at = value.indexOf(prefix, at + 1)) {
|
|
9389
|
-
if (starts.has(at)) continue;
|
|
9390
|
-
DYNAMIC_REFERENCE_TOKEN_SCAN.lastIndex = at;
|
|
9391
|
-
const match = DYNAMIC_REFERENCE_TOKEN_SCAN.exec(value);
|
|
9392
|
-
DYNAMIC_REFERENCE_TOKEN_SCAN.lastIndex = 0;
|
|
9393
|
-
if (match?.index !== at) continue;
|
|
9394
|
-
const end = at + match[0].length;
|
|
9395
|
-
if (!vouchedExpressions.has(value.slice(at, end))) continue;
|
|
9396
|
-
spans.push({
|
|
9397
|
-
start: at,
|
|
9398
|
-
end
|
|
9399
|
-
});
|
|
9400
|
-
starts.add(at);
|
|
9401
|
-
}
|
|
9402
|
-
return spans;
|
|
9403
|
-
}
|
|
9404
|
-
const SPELLED_SECRET_REFERENCE_PREFIXES = ["{{resolve:secretsmanager:", "{{resolve:ssm-secure:"];
|
|
9405
|
-
function expressionSecretIsInferred(expression) {
|
|
9406
|
-
return !SPELLED_SECRET_REFERENCE_PREFIXES.some((prefix) => expression.startsWith(prefix));
|
|
9407
|
-
}
|
|
9408
|
-
function expressionMaySeedANeedle(expression) {
|
|
9409
|
-
return isRecordedSecretExpression(expression) || SECRET_BEARING_REFERENCE_PREFIXES.some((prefix) => expression.startsWith(prefix));
|
|
9410
|
-
}
|
|
9411
|
-
function learnWholeTokenNeedle(collector, bag, source) {
|
|
9412
|
-
if (isSingleDynamicReferenceToken(bag)) return;
|
|
9413
|
-
if (!expressionMaySeedANeedle(source)) return;
|
|
9414
|
-
learnNeedle(collector, bag, source);
|
|
9415
|
-
}
|
|
9416
|
-
function learnMixedLeafNeedle(collector, bag, source) {
|
|
9417
|
-
const frame = singleSpanFrame(bag, source);
|
|
9418
|
-
if (frame === void 0) return;
|
|
9419
|
-
const { token, middle: plaintext } = frame;
|
|
9420
|
-
if (!expressionMaySeedANeedle(token)) return;
|
|
9421
|
-
learnNeedle(collector, plaintext, token);
|
|
9422
|
-
}
|
|
9423
|
-
function asChild(marks, key) {
|
|
9424
|
-
return isPlainObject$7(marks) && hasPlainPrototype(marks) ? marks[key] : void 0;
|
|
9425
|
-
}
|
|
9426
|
-
function asIndex(marks, index) {
|
|
9427
|
-
return Array.isArray(marks) ? marks[index] : void 0;
|
|
9428
|
-
}
|
|
9429
|
-
function preferPositionDecisions(scanned, refused, bag, marks, inferred) {
|
|
9430
|
-
if (isPlainObject$7(bag) && hasPlainPrototype(bag) && isPlainObject$7(refused) && isPlainObject$7(scanned)) {
|
|
9431
|
-
const out = Object.create(null);
|
|
9432
|
-
for (const [k, v] of Object.entries(refused)) out[k] = preferPositionDecisions(scanned[k], v, bag[k], asChild(marks, k), inferred);
|
|
9433
|
-
return out;
|
|
9434
|
-
}
|
|
9435
|
-
if (Array.isArray(bag) && Array.isArray(refused) && Array.isArray(scanned) && refused.length === bag.length && scanned.length === bag.length) return refused.map((item, i) => preferPositionDecisions(scanned[i], item, bag[i], asIndex(marks, i), inferred));
|
|
9436
|
-
if (typeof bag !== "string" || marks === POSITION_DECIDED) return refused;
|
|
9437
|
-
const scanDecision = scanned === bag ? inferred.get(bag) ?? scanned : scanned;
|
|
9438
|
-
if (marks === POSITION_UNCERTIFIED && !(typeof scanDecision === "string" && isSingleDynamicReferenceToken(scanDecision))) return refused;
|
|
9439
|
-
return scanDecision;
|
|
9440
|
-
}
|
|
9441
|
-
function deriveReadbackNeedles(bag, source, secrets, rules) {
|
|
9442
|
-
if (!isReadbackProjectedFromState(rules)) return void 0;
|
|
9443
|
-
if (secrets.size > 0) return void 0;
|
|
9444
|
-
if (!subtreeHasDynamicReference(source)) return void 0;
|
|
9445
|
-
const collector = {
|
|
9446
|
-
needles: /* @__PURE__ */ new Map(),
|
|
9447
|
-
poisoned: /* @__PURE__ */ new Set(),
|
|
9448
|
-
inferred: /* @__PURE__ */ new Set()
|
|
9449
|
-
};
|
|
9450
|
-
refuseUncertifiedReadbackPositions(bag, source, secrets, false, collector);
|
|
9451
|
-
if (collector.needles.size === 0) return void 0;
|
|
9452
|
-
const certain = /* @__PURE__ */ new Map();
|
|
9453
|
-
const inferred = /* @__PURE__ */ new Map();
|
|
9454
|
-
for (const [plaintext, expression] of collector.needles) (collector.inferred.has(plaintext) ? inferred : certain).set(plaintext, expression);
|
|
9455
|
-
return {
|
|
9456
|
-
certain,
|
|
9457
|
-
inferred
|
|
9458
|
-
};
|
|
9459
|
-
}
|
|
9460
|
-
|
|
9461
|
-
//#endregion
|
|
9462
|
-
//#region src/deployment/secret-redaction/redact-state.ts
|
|
9463
|
-
function redactSecretsForState(bag, secrets, source, rules = TEMPLATE_DERIVED_RULES, bagIsSameGeneration = false) {
|
|
9464
|
-
return flattenEmbeddedNoEchoLeaves(redactSecretsForStatePasses(bag, secrets, source, rules, bagIsSameGeneration), secrets);
|
|
9465
|
-
}
|
|
9466
|
-
function redactSecretsForStatePasses(bag, secrets, source, rules, bagIsSameGeneration) {
|
|
9467
|
-
if (secrets.size === 0 && source === void 0) return bag;
|
|
9468
|
-
if (source !== void 0) {
|
|
9469
|
-
const positioned = redactByPath(bag, source, secrets, rules, recordedExpressionsOf(secrets), bagIsSameGeneration);
|
|
9470
|
-
if (!isReadbackProjectedFromState(rules)) return positioned;
|
|
9471
|
-
const failClosed = rules.failClosedOnUncertifiedPositions === true;
|
|
9472
|
-
const refused = refuseUncertifiedReadbackPositions(positioned, source, secrets, failClosed);
|
|
9473
|
-
const derived = deriveReadbackNeedles(bag, source, secrets, rules);
|
|
9474
|
-
if (derived === void 0) return refused;
|
|
9475
|
-
const marks = refuseUncertifiedReadbackPositions(positioned, source, secrets, failClosed, void 0, true);
|
|
9476
|
-
return preferPositionDecisions(redactForState(bag, {
|
|
9477
|
-
provenance: "value-scan",
|
|
9478
|
-
secrets: derived.certain
|
|
9479
|
-
}), refused, bag, marks, derived.inferred);
|
|
9480
|
-
}
|
|
9481
|
-
const regex = buildNeedleRegex(substringNeedlesOf(secrets));
|
|
9482
|
-
const wholeValueExpr = (s) => s === "" ? void 0 : secrets.get(s);
|
|
9483
|
-
const physicalNames = physicalNameCopiesOf.get(secrets);
|
|
9484
|
-
let vouched;
|
|
9485
|
-
const vouchedExpressions = () => vouched ??= new Set(secrets.values());
|
|
9486
|
-
const expressionFor = (match) => {
|
|
9487
|
-
return secrets.get(match) ?? "***";
|
|
9488
|
-
};
|
|
9489
|
-
const scanLeaf = (value, needles) => {
|
|
9490
|
-
const spans = isDynamicReferenceString(value) ? resolvableReferenceSpans(value, vouchedExpressions()) : [];
|
|
9491
|
-
const names = physicalNameSpans(physicalNames, value);
|
|
9492
|
-
const kept = (start, end) => isStrictlyInsideASpan(spans, start, end) || names.some((n) => n.start <= start && end <= n.end);
|
|
9493
|
-
if (!legacyOverlapScan.has(secrets)) {
|
|
9494
|
-
const matches = everyMatch(value, needles);
|
|
9495
|
-
const redacted = matches.filter((m) => !kept(m.start, m.end));
|
|
9496
|
-
if (cutsContainmentNeedle(value, secrets, redacted)) {
|
|
9497
|
-
overlapAnswered.add(secrets);
|
|
9498
|
-
return "***";
|
|
9499
|
-
}
|
|
9500
|
-
const overlapping = redactOverlappingMatches(value, matches, redacted, expressionFor);
|
|
9501
|
-
if (overlapping !== void 0) {
|
|
9502
|
-
overlapAnswered.add(secrets);
|
|
9503
|
-
return overlapping;
|
|
9504
|
-
}
|
|
9505
|
-
}
|
|
9506
|
-
return value.replace(needles, (match, offset) => {
|
|
9507
|
-
if (kept(offset, offset + match.length)) return match;
|
|
9508
|
-
return expressionFor(match);
|
|
9509
|
-
});
|
|
9510
|
-
};
|
|
9511
|
-
const walk = (value) => {
|
|
9512
|
-
if (typeof value === "string") {
|
|
9513
|
-
if (physicalNames?.has(value) === true) return value;
|
|
9514
|
-
const whole = wholeValueExpr(value);
|
|
9515
|
-
if (whole !== void 0) return whole;
|
|
9516
|
-
if (isSingleDynamicReferenceToken(value) && spanNamesResolvableService(value)) return value;
|
|
9517
|
-
if (!regex) return value;
|
|
9518
|
-
regex.lastIndex = 0;
|
|
9519
|
-
if (!regex.test(value)) return value;
|
|
9520
|
-
return scanLeaf(value, regex);
|
|
9521
|
-
}
|
|
9522
|
-
if (Array.isArray(value)) return value.map(walk);
|
|
9523
|
-
if (value !== null && typeof value === "object") {
|
|
9524
|
-
if (isOrdinaryDate(value)) {
|
|
9525
|
-
const persisted = value.toJSON();
|
|
9526
|
-
if (typeof persisted !== "string") return value;
|
|
9527
|
-
const scanned = walk(persisted);
|
|
9528
|
-
return scanned === persisted ? value : scanned;
|
|
9529
|
-
}
|
|
9530
|
-
const out = Object.create(null);
|
|
9531
|
-
for (const [k, v] of Object.entries(value)) out[k] = walk(v);
|
|
9532
|
-
return out;
|
|
9533
|
-
}
|
|
9534
|
-
return value;
|
|
9535
|
-
};
|
|
9536
|
-
return walk(bag);
|
|
9537
|
-
}
|
|
9538
|
-
const legacyOverlapScan = /* @__PURE__ */ new WeakSet();
|
|
9539
|
-
const overlapAnswered = /* @__PURE__ */ new WeakSet();
|
|
9540
|
-
function overlapRuleAnswered(secrets) {
|
|
9541
|
-
return overlapAnswered.has(secrets);
|
|
9542
|
-
}
|
|
9543
|
-
function withLegacyOverlapScan(secrets, run) {
|
|
9544
|
-
if (legacyOverlapScan.has(secrets)) return run();
|
|
9545
|
-
legacyOverlapScan.add(secrets);
|
|
9546
|
-
try {
|
|
9547
|
-
return run();
|
|
9548
|
-
} finally {
|
|
9549
|
-
legacyOverlapScan.delete(secrets);
|
|
9550
|
-
}
|
|
9551
|
-
}
|
|
9552
|
-
function differingStringLeaves(legacy, current, out = []) {
|
|
9553
|
-
if (typeof legacy === "string" && typeof current === "string") {
|
|
9554
|
-
if (legacy !== current) out.push([legacy, current]);
|
|
9555
|
-
return out;
|
|
9556
|
-
}
|
|
9557
|
-
if (Array.isArray(legacy) && Array.isArray(current) && legacy.length === current.length) {
|
|
9558
|
-
legacy.forEach((item, i) => differingStringLeaves(item, current[i], out));
|
|
9559
|
-
return out;
|
|
9560
|
-
}
|
|
9561
|
-
if (legacy !== null && current !== null && typeof legacy === "object" && typeof current === "object" && !Array.isArray(legacy) && !Array.isArray(current)) {
|
|
9562
|
-
const c = current;
|
|
9563
|
-
for (const [key, value] of Object.entries(legacy)) if (Object.hasOwn(c, key)) differingStringLeaves(value, c[key], out);
|
|
9564
|
-
}
|
|
9565
|
-
return out;
|
|
9566
|
-
}
|
|
9567
|
-
function legacyLeavesWithoutMask(legacy) {
|
|
9568
|
-
if (typeof legacy === "string") return legacy.includes("***") ? void 0 : legacy;
|
|
9569
|
-
if (Array.isArray(legacy)) return legacy.map(legacyLeavesWithoutMask);
|
|
9570
|
-
if (legacy !== null && typeof legacy === "object") {
|
|
9571
|
-
const out = Object.create(null);
|
|
9572
|
-
for (const [key, value] of Object.entries(legacy)) out[key] = legacyLeavesWithoutMask(value);
|
|
9573
|
-
return out;
|
|
9574
|
-
}
|
|
9575
|
-
return legacy;
|
|
9576
|
-
}
|
|
9577
|
-
function legacyReferenceLeavesOnly(legacy) {
|
|
9578
|
-
if (typeof legacy === "string") return legacy.includes("{{resolve:") ? legacy : void 0;
|
|
9579
|
-
if (Array.isArray(legacy)) return legacy.map(legacyReferenceLeavesOnly);
|
|
9580
|
-
if (legacy !== null && typeof legacy === "object") {
|
|
9581
|
-
const out = Object.create(null);
|
|
9582
|
-
for (const [key, value] of Object.entries(legacy)) out[key] = legacyReferenceLeavesOnly(value);
|
|
9583
|
-
return out;
|
|
9584
|
-
}
|
|
9585
|
-
return legacy;
|
|
9586
|
-
}
|
|
9587
|
-
function replaceWholeLeaves(value, pairs) {
|
|
9588
|
-
if (pairs.length === 0) return value;
|
|
9589
|
-
if (typeof value === "string") {
|
|
9590
|
-
const hit = pairs.find(([legacy]) => legacy === value);
|
|
9591
|
-
return hit === void 0 ? value : hit[1];
|
|
9592
|
-
}
|
|
9593
|
-
if (Array.isArray(value)) {
|
|
9594
|
-
let changed = false;
|
|
9595
|
-
const out = value.map((item) => {
|
|
9596
|
-
const next = replaceWholeLeaves(item, pairs);
|
|
9597
|
-
if (next !== item) changed = true;
|
|
9598
|
-
return next;
|
|
9599
|
-
});
|
|
9600
|
-
return changed ? out : value;
|
|
9601
|
-
}
|
|
9602
|
-
if (value !== null && typeof value === "object") {
|
|
9603
|
-
let out;
|
|
9604
|
-
for (const [key, item] of Object.entries(value)) {
|
|
9605
|
-
const next = replaceWholeLeaves(item, pairs);
|
|
9606
|
-
if (next !== item) {
|
|
9607
|
-
out ??= Object.assign(Object.create(null), value);
|
|
9608
|
-
out[key] = next;
|
|
9609
|
-
}
|
|
9610
|
-
}
|
|
9611
|
-
return out ?? value;
|
|
9612
|
-
}
|
|
9613
|
-
return value;
|
|
9614
|
-
}
|
|
9615
|
-
function everyMatch(value, needles) {
|
|
9616
|
-
const matches = [];
|
|
9617
|
-
needles.lastIndex = 0;
|
|
9618
|
-
for (let m = needles.exec(value); m !== null; m = needles.exec(value)) {
|
|
9619
|
-
matches.push({
|
|
9620
|
-
start: m.index,
|
|
9621
|
-
end: m.index + m[0].length
|
|
9622
|
-
});
|
|
9623
|
-
needles.lastIndex = m.index + 1;
|
|
9624
|
-
}
|
|
9625
|
-
needles.lastIndex = 0;
|
|
9626
|
-
return matches;
|
|
9627
|
-
}
|
|
9628
|
-
function redactOverlappingMatches(value, matches, redacted, expressionFor) {
|
|
9629
|
-
let reach = 0;
|
|
9630
|
-
let overlap = false;
|
|
9631
|
-
for (const m of matches) {
|
|
9632
|
-
if (m.start < reach) overlap = true;
|
|
9633
|
-
reach = Math.max(reach, m.end);
|
|
9634
|
-
}
|
|
9635
|
-
if (!overlap) return void 0;
|
|
9636
|
-
let out = "";
|
|
9637
|
-
let cursor = 0;
|
|
9638
|
-
for (let i = 0; i < redacted.length;) {
|
|
9639
|
-
let end = redacted[i].end;
|
|
9640
|
-
let j = i + 1;
|
|
9641
|
-
for (; j < redacted.length && redacted[j].start < end; j++) end = Math.max(end, redacted[j].end);
|
|
9642
|
-
const cluster = redacted.slice(i, j);
|
|
9643
|
-
out += value.slice(cursor, cluster[0].start);
|
|
9644
|
-
for (let at = cluster[0].start; at < end;) {
|
|
9645
|
-
const tile = cluster.find((m) => m.start === at);
|
|
9646
|
-
if (tile === void 0) return "***";
|
|
9647
|
-
out += expressionFor(value.slice(tile.start, tile.end));
|
|
9648
|
-
at = tile.end;
|
|
9649
|
-
}
|
|
9650
|
-
cursor = end;
|
|
9651
|
-
i = j;
|
|
9652
|
-
}
|
|
9653
|
-
return out + value.slice(cursor);
|
|
9654
|
-
}
|
|
9655
|
-
function scrubResourceRecord(record, secrets, sourceProperties, observedProvenance, claims = {}) {
|
|
9656
|
-
const propertiesClaimed = claims.properties === "same-generation";
|
|
9657
|
-
const observedClaimed = claims.observed === "same-generation";
|
|
9658
|
-
if (secrets.size === 0 && sourceProperties === void 0 && !record.observedProperties) return record;
|
|
9659
|
-
const next = { ...record };
|
|
9660
|
-
next.properties = sourceProperties === void 0 ? redactForState(record.properties, {
|
|
9661
|
-
provenance: "value-scan",
|
|
9662
|
-
secrets
|
|
9663
|
-
}) : redactAtProvenance(record.properties, secrets, sourceProperties, "template-derived", propertiesClaimed);
|
|
9664
|
-
if (record.attributes) {
|
|
9665
|
-
const ownId = record.physicalId;
|
|
9666
|
-
const ids = [...attributeIdCopiesOf.get(secrets) ?? []];
|
|
9667
|
-
if (typeof ownId === "string" && ownId !== "") ids.push(ownId);
|
|
9668
|
-
const attributes = record.attributes;
|
|
9669
|
-
next.attributes = ids.length > 0 ? withPhysicalNameCopies(secrets, ids, () => redactForState(attributes, {
|
|
9670
|
-
provenance: "value-scan",
|
|
9671
|
-
secrets
|
|
9672
|
-
})) : redactForState(attributes, {
|
|
9673
|
-
provenance: "value-scan",
|
|
9674
|
-
secrets
|
|
9675
|
-
});
|
|
9676
|
-
}
|
|
9677
|
-
if (record.observedProperties) next.observedProperties = redactAtProvenance(record.observedProperties, secrets, sourceProperties ?? next.properties, observedProvenance ?? (sourceProperties !== void 0 ? "template-sourced" : secrets.size === 0 && observedClaimed ? "state-baseline" : "state-readback"), observedClaimed);
|
|
9678
|
-
return next;
|
|
9679
|
-
}
|
|
9680
|
-
function withoutPhysicalNameCopies(secrets, run) {
|
|
9681
|
-
const names = physicalNameCopiesOf.get(secrets);
|
|
9682
|
-
if (names === void 0) return run();
|
|
9683
|
-
physicalNameCopiesOf.delete(secrets);
|
|
9684
|
-
try {
|
|
9685
|
-
return run();
|
|
9686
|
-
} finally {
|
|
9687
|
-
physicalNameCopiesOf.set(secrets, names);
|
|
9688
|
-
}
|
|
9689
|
-
}
|
|
9690
|
-
function withPhysicalNameCopies(secrets, ids, run) {
|
|
9691
|
-
const previous = physicalNameCopiesOf.get(secrets);
|
|
9692
|
-
const names = new Set(previous);
|
|
9693
|
-
for (const id of ids) if (id !== "") names.add(id);
|
|
9694
|
-
physicalNameCopiesOf.set(secrets, names);
|
|
9695
|
-
try {
|
|
9696
|
-
return run();
|
|
9697
|
-
} finally {
|
|
9698
|
-
if (previous === void 0) physicalNameCopiesOf.delete(secrets);
|
|
9699
|
-
else physicalNameCopiesOf.set(secrets, previous);
|
|
9700
|
-
}
|
|
9701
|
-
}
|
|
9702
|
-
function repairPhysicalNameCopyLeaves(stored, legacy, current) {
|
|
9703
|
-
if (typeof stored === "string") return typeof legacy === "string" && typeof current === "string" && stored === legacy && current !== legacy ? current : stored;
|
|
9704
|
-
if (Array.isArray(stored)) {
|
|
9705
|
-
if (!Array.isArray(legacy) || !Array.isArray(current)) return stored;
|
|
9706
|
-
if (legacy.length !== stored.length || current.length !== stored.length) return stored;
|
|
9707
|
-
let changed = false;
|
|
9708
|
-
const out = stored.map((item, i) => {
|
|
9709
|
-
const next = repairPhysicalNameCopyLeaves(item, legacy[i], current[i]);
|
|
9710
|
-
if (next !== item) changed = true;
|
|
9711
|
-
return next;
|
|
9712
|
-
});
|
|
9713
|
-
return changed ? out : stored;
|
|
9714
|
-
}
|
|
9715
|
-
if (stored !== null && typeof stored === "object") {
|
|
9716
|
-
if (legacy === null || typeof legacy !== "object" || Array.isArray(legacy)) return stored;
|
|
9717
|
-
if (current === null || typeof current !== "object" || Array.isArray(current)) return stored;
|
|
9718
|
-
const l = legacy;
|
|
9719
|
-
const c = current;
|
|
9720
|
-
let out;
|
|
9721
|
-
for (const [key, value] of Object.entries(stored)) {
|
|
9722
|
-
if (!Object.hasOwn(l, key) || !Object.hasOwn(c, key)) continue;
|
|
9723
|
-
const next = repairPhysicalNameCopyLeaves(value, l[key], c[key]);
|
|
9724
|
-
if (next !== value) {
|
|
9725
|
-
out ??= { ...stored };
|
|
9726
|
-
out[key] = next;
|
|
9727
|
-
}
|
|
9728
|
-
}
|
|
9729
|
-
return out ?? stored;
|
|
9730
|
-
}
|
|
9731
|
-
return stored;
|
|
9732
|
-
}
|
|
9733
|
-
function embeddedPhysicalNameRewrites(secrets, legacySecrets = secrets) {
|
|
9734
|
-
const names = physicalNameCopiesOf.get(secrets);
|
|
9735
|
-
if (names === void 0) return [];
|
|
9736
|
-
const pairs = [];
|
|
9737
|
-
withoutPhysicalNameCopies(legacySecrets, () => {
|
|
9738
|
-
for (const name of names) {
|
|
9739
|
-
const legacy = redactForState(name, {
|
|
9740
|
-
provenance: "value-scan",
|
|
9741
|
-
secrets: legacySecrets
|
|
9742
|
-
});
|
|
9743
|
-
if (typeof legacy === "string" && legacy !== name && legacy.includes("{{resolve:") && !isSingleDynamicReferenceToken(legacy) && !legacy.includes("***")) pairs.push([legacy, name]);
|
|
9744
|
-
}
|
|
9745
|
-
});
|
|
9746
|
-
return pairs;
|
|
9747
|
-
}
|
|
9748
|
-
function replaceEmbeddedPhysicalNameRewrites(value, pairs) {
|
|
9749
|
-
if (pairs.length === 0) return value;
|
|
9750
|
-
if (typeof value === "string") {
|
|
9751
|
-
let next = value;
|
|
9752
|
-
for (const [legacy, name] of pairs) next = next.split(legacy).join(name);
|
|
9753
|
-
return next;
|
|
9754
|
-
}
|
|
9755
|
-
if (Array.isArray(value)) {
|
|
9756
|
-
let changed = false;
|
|
9757
|
-
const out = value.map((item) => {
|
|
9758
|
-
const next = replaceEmbeddedPhysicalNameRewrites(item, pairs);
|
|
9759
|
-
if (next !== item) changed = true;
|
|
9760
|
-
return next;
|
|
9761
|
-
});
|
|
9762
|
-
return changed ? out : value;
|
|
9763
|
-
}
|
|
9764
|
-
if (value !== null && typeof value === "object") {
|
|
9765
|
-
let out;
|
|
9766
|
-
for (const [key, item] of Object.entries(value)) {
|
|
9767
|
-
const next = replaceEmbeddedPhysicalNameRewrites(item, pairs);
|
|
9768
|
-
if (next !== item) {
|
|
9769
|
-
out ??= { ...value };
|
|
9770
|
-
out[key] = next;
|
|
9771
|
-
}
|
|
9772
|
-
}
|
|
9773
|
-
return out ?? value;
|
|
9774
|
-
}
|
|
9775
|
-
return value;
|
|
9776
|
-
}
|
|
9777
|
-
function repairEmbeddedPhysicalNamesTowards(stored, target, pairs) {
|
|
9778
|
-
if (pairs.length === 0) return stored;
|
|
9779
|
-
if (typeof stored === "string") {
|
|
9780
|
-
if (typeof target !== "string" || stored === target) return stored;
|
|
9781
|
-
const repaired = replaceEmbeddedPhysicalNameRewrites(stored, pairs);
|
|
9782
|
-
return repaired === target ? repaired : stored;
|
|
9783
|
-
}
|
|
9784
|
-
if (Array.isArray(stored)) {
|
|
9785
|
-
if (!Array.isArray(target) || target.length !== stored.length) return stored;
|
|
9786
|
-
let changed = false;
|
|
9787
|
-
const out = stored.map((item, i) => {
|
|
9788
|
-
const next = repairEmbeddedPhysicalNamesTowards(item, target[i], pairs);
|
|
9789
|
-
if (next !== item) changed = true;
|
|
9790
|
-
return next;
|
|
9791
|
-
});
|
|
9792
|
-
return changed ? out : stored;
|
|
9793
|
-
}
|
|
9794
|
-
if (stored !== null && typeof stored === "object") {
|
|
9795
|
-
if (target === null || typeof target !== "object" || Array.isArray(target)) return stored;
|
|
9796
|
-
const t = target;
|
|
9797
|
-
let out;
|
|
9798
|
-
for (const [key, value] of Object.entries(stored)) {
|
|
9799
|
-
if (!Object.hasOwn(t, key)) continue;
|
|
9800
|
-
const next = repairEmbeddedPhysicalNamesTowards(value, t[key], pairs);
|
|
9801
|
-
if (next !== value) {
|
|
9802
|
-
out ??= { ...stored };
|
|
9803
|
-
out[key] = next;
|
|
9804
|
-
}
|
|
9805
|
-
}
|
|
9806
|
-
return out ?? stored;
|
|
9807
|
-
}
|
|
9808
|
-
return stored;
|
|
9809
|
-
}
|
|
9810
|
-
|
|
9811
|
-
//#endregion
|
|
9812
|
-
//#region src/deployment/secret-redaction/mask-errors.ts
|
|
9813
|
-
function maskSecretsInText(text, secrets) {
|
|
9814
|
-
const logOnly = logOnlyValuesOf.get(secrets);
|
|
9815
|
-
const noLogOnly = logOnly === void 0 || logOnly.size === 0;
|
|
9816
|
-
if (secrets.size === 0 && noLogOnly) return text;
|
|
9817
|
-
if (text !== "" && (secrets.has(text) || logOnly?.has(text) === true)) return "***";
|
|
9818
|
-
return maskMatchSpans(text, printingNeedles(noLogOnly ? secrets.keys() : [...secrets.keys(), ...logOnly]), "***");
|
|
9819
|
-
}
|
|
9820
|
-
function maskRecordedSecretsInText(text, secrets) {
|
|
9821
|
-
if (secrets.size === 0) return text;
|
|
9822
|
-
if (text !== "" && secrets.has(text)) return "***";
|
|
9823
|
-
return maskMatchSpans(text, substringNeedles(secrets.keys()), "***");
|
|
9824
|
-
}
|
|
9825
|
-
function substringNeedles(values) {
|
|
9826
|
-
return [...new Set(values)].filter((value) => value.length >= 4);
|
|
9827
|
-
}
|
|
9828
|
-
const ERROR_CAUSE_MASK_MAX_DEPTH = 20;
|
|
9829
|
-
function errorCauseChain(root) {
|
|
9830
|
-
const chain = [];
|
|
9831
|
-
const seen = /* @__PURE__ */ new Set();
|
|
9832
|
-
let current = root;
|
|
9833
|
-
while (current instanceof Error && !seen.has(current) && chain.length < 20) {
|
|
9834
|
-
seen.add(current);
|
|
9835
|
-
chain.push(current);
|
|
9836
|
-
current = current.cause;
|
|
9837
|
-
}
|
|
9838
|
-
return chain;
|
|
9839
|
-
}
|
|
9840
|
-
function readStack(error) {
|
|
9841
|
-
try {
|
|
9842
|
-
const stack = error.stack;
|
|
9843
|
-
return typeof stack === "string" ? stack : void 0;
|
|
9844
|
-
} catch {
|
|
9845
|
-
return;
|
|
9846
|
-
}
|
|
9847
|
-
}
|
|
9848
|
-
function maskDescriptorValue(descriptor, maskText) {
|
|
9849
|
-
if (!("value" in descriptor)) return descriptor;
|
|
9850
|
-
const value = maskErrorFieldValue(descriptor.value, maskText);
|
|
9851
|
-
return value === descriptor.value ? descriptor : {
|
|
9852
|
-
...descriptor,
|
|
9853
|
-
value
|
|
9854
|
-
};
|
|
9855
|
-
}
|
|
9856
|
-
const CLASSIFIER_IDENTIFIER_FIELDS = /* @__PURE__ */ new Set([
|
|
9857
|
-
"name",
|
|
9858
|
-
"code",
|
|
9859
|
-
"Code",
|
|
9860
|
-
"__type",
|
|
9861
|
-
"ccErrorCode",
|
|
9862
|
-
"ccOperation"
|
|
9863
|
-
]);
|
|
9864
|
-
function isAuxiliaryAnchor(key, descriptor) {
|
|
9865
|
-
return key === "logicalId" && descriptor.enumerable === false && descriptor.writable === false && typeof descriptor.value === "string" && descriptor.value.endsWith("/auxiliary");
|
|
9866
|
-
}
|
|
9867
|
-
const CREATED_BEFORE_FAILURE_MARK = Symbol.for("cdkd.createdBeforeFailure");
|
|
9868
|
-
function isCreatedBeforeFailureMark(key, descriptor) {
|
|
9869
|
-
return key === CREATED_BEFORE_FAILURE_MARK && descriptor.enumerable === false && descriptor.writable === false && typeof descriptor.value === "object" && descriptor.value !== null && Object.isFrozen(descriptor.value);
|
|
9870
|
-
}
|
|
9871
|
-
function isPlainContainer(value) {
|
|
9872
|
-
const proto = Object.getPrototypeOf(value);
|
|
9873
|
-
return Array.isArray(value) ? proto === Array.prototype : proto === Object.prototype || proto === null;
|
|
9874
|
-
}
|
|
9875
|
-
function readFieldNode(node) {
|
|
9876
|
-
try {
|
|
9877
|
-
if (!isPlainContainer(node)) return void 0;
|
|
9878
|
-
const entries = [];
|
|
9879
|
-
for (const key of Reflect.ownKeys(node)) {
|
|
9880
|
-
const descriptor = Object.getOwnPropertyDescriptor(node, key);
|
|
9881
|
-
if (descriptor) entries.push([key, descriptor]);
|
|
9882
|
-
}
|
|
9883
|
-
const isArray = Array.isArray(node);
|
|
9884
|
-
return {
|
|
9885
|
-
proto: Object.getPrototypeOf(node),
|
|
9886
|
-
isArray,
|
|
9887
|
-
length: isArray ? Object.getOwnPropertyDescriptor(node, "length") : void 0,
|
|
9888
|
-
extensible: Object.isExtensible(node),
|
|
9889
|
-
entries
|
|
9890
|
-
};
|
|
9891
|
-
} catch {
|
|
9892
|
-
return;
|
|
9893
|
-
}
|
|
9894
|
-
}
|
|
9895
|
-
function maskErrorFieldValue(value, maskText) {
|
|
9896
|
-
if (typeof value === "string") return maskText(value);
|
|
9897
|
-
if (typeof value !== "object" || value === null) return value;
|
|
9898
|
-
try {
|
|
9899
|
-
const nodes = /* @__PURE__ */ new Map();
|
|
9900
|
-
const seen = /* @__PURE__ */ new Set();
|
|
9901
|
-
let changed = false;
|
|
9902
|
-
let frontier = [value];
|
|
9903
|
-
for (let depth = 0; frontier.length > 0 && depth < 20; depth++) {
|
|
9904
|
-
const next = [];
|
|
9905
|
-
for (const node of frontier) {
|
|
9906
|
-
if (seen.has(node)) continue;
|
|
9907
|
-
seen.add(node);
|
|
9908
|
-
const read = readFieldNode(node);
|
|
9909
|
-
if (!read) continue;
|
|
9910
|
-
nodes.set(node, read);
|
|
9911
|
-
for (const [, descriptor] of read.entries) {
|
|
9912
|
-
if (!("value" in descriptor)) continue;
|
|
9913
|
-
const child = descriptor.value;
|
|
9914
|
-
if (typeof child === "string") {
|
|
9915
|
-
if (!changed && maskText(child) !== child) changed = true;
|
|
9916
|
-
} else if (typeof child === "object" && child !== null) next.push(child);
|
|
9917
|
-
}
|
|
9918
|
-
}
|
|
9919
|
-
frontier = next;
|
|
9920
|
-
}
|
|
9921
|
-
if (!changed) return value;
|
|
9922
|
-
const copies = /* @__PURE__ */ new Map();
|
|
9923
|
-
for (const [node, read] of nodes) copies.set(node, read.isArray ? new Array(read.length?.value ?? 0) : Object.create(read.proto));
|
|
9924
|
-
for (const [node, read] of nodes) {
|
|
9925
|
-
const copy = copies.get(node);
|
|
9926
|
-
for (const [key, original] of read.entries) {
|
|
9927
|
-
if (key === "length" && read.isArray) continue;
|
|
9928
|
-
const descriptor = { ...original };
|
|
9929
|
-
if ("value" in descriptor) {
|
|
9930
|
-
const child = descriptor.value;
|
|
9931
|
-
if (typeof child === "string") descriptor.value = maskText(child);
|
|
9932
|
-
else if (typeof child === "object" && child !== null && copies.has(child)) descriptor.value = copies.get(child);
|
|
9933
|
-
}
|
|
9934
|
-
Object.defineProperty(copy, key, descriptor);
|
|
9935
|
-
}
|
|
9936
|
-
if (read.length?.writable === false) Object.defineProperty(copy, "length", { writable: false });
|
|
9937
|
-
if (!read.extensible) Object.preventExtensions(copy);
|
|
9938
|
-
}
|
|
9939
|
-
return copies.get(value) ?? value;
|
|
9940
|
-
} catch {
|
|
9941
|
-
return value;
|
|
9942
|
-
}
|
|
9943
|
-
}
|
|
9944
|
-
function maskSecretsInError(error, secrets, extraMask) {
|
|
9945
|
-
if (!(error instanceof Error) || !hasMaskableValues(secrets) && !extraMask) return error;
|
|
9946
|
-
const maskText = (text) => maskSecretsInText(extraMask ? extraMask(text) : text, secrets);
|
|
9947
|
-
const chain = errorCauseChain(error);
|
|
9948
|
-
let changed = false;
|
|
9949
|
-
const links = chain.map((link) => {
|
|
9950
|
-
const message = maskText(link.message);
|
|
9951
|
-
const stack = readStack(link);
|
|
9952
|
-
const maskedStack = typeof stack === "string" ? maskText(stack) : void 0;
|
|
9953
|
-
const descriptors = {};
|
|
9954
|
-
for (const key of Reflect.ownKeys(link)) {
|
|
9955
|
-
if (key === "message" || key === "cause" || key === "stack") continue;
|
|
9956
|
-
const descriptor = Object.getOwnPropertyDescriptor(link, key);
|
|
9957
|
-
if (!descriptor) continue;
|
|
9958
|
-
descriptors[key] = typeof key === "string" && CLASSIFIER_IDENTIFIER_FIELDS.has(key) && typeof descriptor.value === "string" || isAuxiliaryAnchor(key, descriptor) || isCreatedBeforeFailureMark(key, descriptor) ? descriptor : maskDescriptorValue(descriptor, maskText);
|
|
9959
|
-
if (descriptors[key] !== descriptor) changed = true;
|
|
9960
|
-
}
|
|
9961
|
-
let cause = Object.getOwnPropertyDescriptor(link, "cause");
|
|
9962
|
-
if (cause && !("value" in cause && cause.value instanceof Error)) {
|
|
9963
|
-
const masked = maskDescriptorValue(cause, maskText);
|
|
9964
|
-
if (masked !== cause) changed = true;
|
|
9965
|
-
cause = masked;
|
|
9966
|
-
}
|
|
9967
|
-
if (message !== link.message || maskedStack !== stack) changed = true;
|
|
9968
|
-
return {
|
|
9969
|
-
message,
|
|
9970
|
-
stack: maskedStack,
|
|
9971
|
-
descriptors,
|
|
9972
|
-
cause
|
|
9973
|
-
};
|
|
9974
|
-
});
|
|
9975
|
-
if (!changed) return error;
|
|
9976
|
-
const clones = /* @__PURE__ */ new Map();
|
|
9977
|
-
for (const [i, original] of chain.entries()) {
|
|
9978
|
-
const { message, stack, descriptors } = links[i];
|
|
9979
|
-
const clone = Object.create(Object.getPrototypeOf(original), descriptors);
|
|
9980
|
-
Object.defineProperty(clone, "message", {
|
|
9981
|
-
value: message,
|
|
9982
|
-
writable: true,
|
|
9983
|
-
enumerable: false,
|
|
9984
|
-
configurable: true
|
|
9985
|
-
});
|
|
9986
|
-
if (stack !== void 0) Object.defineProperty(clone, "stack", {
|
|
9987
|
-
value: stack,
|
|
9988
|
-
writable: true,
|
|
9989
|
-
enumerable: false,
|
|
9990
|
-
configurable: true
|
|
9991
|
-
});
|
|
9992
|
-
clones.set(original, clone);
|
|
9993
|
-
}
|
|
9994
|
-
for (const [i, original] of chain.entries()) {
|
|
9995
|
-
const causeDescriptor = links[i].cause;
|
|
9996
|
-
if (!causeDescriptor) continue;
|
|
9997
|
-
const clone = clones.get(original);
|
|
9998
|
-
const causeValue = original.cause;
|
|
9999
|
-
const replacement = causeValue instanceof Error ? clones.get(causeValue) : void 0;
|
|
10000
|
-
Object.defineProperty(clone, "cause", replacement ? {
|
|
10001
|
-
value: replacement,
|
|
10002
|
-
writable: true,
|
|
10003
|
-
enumerable: causeDescriptor.enumerable === true,
|
|
10004
|
-
configurable: true
|
|
10005
|
-
} : causeDescriptor);
|
|
10006
|
-
}
|
|
10007
|
-
return clones.get(error);
|
|
10008
|
-
}
|
|
10009
|
-
function createSecretMasker(secrets) {
|
|
10010
|
-
return (text) => maskSecretsInText(text, secrets);
|
|
10011
|
-
}
|
|
10012
|
-
|
|
10013
|
-
//#endregion
|
|
10014
|
-
//#region src/deployment/secret-redaction/log-only.ts
|
|
10015
|
-
const logOnlyValuesOf = /* @__PURE__ */ new WeakMap();
|
|
10016
|
-
function recordLogOnlyValue(secrets, plaintext) {
|
|
10017
|
-
if (plaintext === "") return;
|
|
10018
|
-
sideSetOf(logOnlyValuesOf, secrets).add(plaintext);
|
|
10019
|
-
}
|
|
10020
|
-
function carryLogOnlyValues(from, to) {
|
|
10021
|
-
const values = logOnlyValuesOf.get(from);
|
|
10022
|
-
if (values === void 0 || values.size === 0) return;
|
|
10023
|
-
const into = sideSetOf(logOnlyValuesOf, to);
|
|
10024
|
-
for (const value of values) into.add(value);
|
|
10025
|
-
}
|
|
10026
|
-
function carryLogOnlyValuesCarriedBy(from, to, value) {
|
|
10027
|
-
const values = logOnlyValuesOf.get(from);
|
|
10028
|
-
if (values === void 0 || values.size === 0) return;
|
|
10029
|
-
const leaves = printedLeavesOf(value);
|
|
10030
|
-
if (leaves.size === 0) return;
|
|
10031
|
-
for (const needle of values) for (const leaf of leaves) if (leaf === needle || needle.length >= 4 && leaf.includes(needle)) {
|
|
10032
|
-
recordLogOnlyValue(to, needle);
|
|
10033
|
-
break;
|
|
10034
|
-
}
|
|
10035
|
-
carryListElementFragments(values, to, value);
|
|
10036
|
-
}
|
|
10037
|
-
function carryListElementFragments(needles, to, value) {
|
|
10038
|
-
if (!Array.isArray(value) || value.length === 0) return;
|
|
10039
|
-
if (!value.every((e) => typeof e === "string" || typeof e === "number" || typeof e === "boolean")) return;
|
|
10040
|
-
const numeric = value.every((element) => typeof element === "number");
|
|
10041
|
-
const joined = value.map((element) => String(element)).join(",");
|
|
10042
|
-
for (const needle of [...needles]) {
|
|
10043
|
-
const pieces = needle.split(",").map((piece) => piece.trim());
|
|
10044
|
-
if (numeric && pieces.every((piece) => piece === "" || Number.isNaN(Number(piece)))) continue;
|
|
10045
|
-
const fragments = fragmentsOfNeedleIn(joined, ",", pieces.map((piece) => numeric ? String(Number(piece)) : piece).join(","));
|
|
10046
|
-
if (fragments.size === 0) continue;
|
|
10047
|
-
recordLogOnlyValue(to, needle);
|
|
10048
|
-
for (const fragment of fragments) recordLogOnlyValue(to, fragment);
|
|
10049
|
-
}
|
|
10050
|
-
}
|
|
10051
|
-
function recordLogOnlySplitFragments(from, to, text, delimiter, printed) {
|
|
10052
|
-
if (delimiter === "") return;
|
|
10053
|
-
const splits = [text.split(delimiter)];
|
|
10054
|
-
if (printed !== void 0 && (printed.length !== splits[0].length || printed.some((piece, i) => piece !== splits[0][i]))) splits.push(printed);
|
|
10055
|
-
for (const bag of from) {
|
|
10056
|
-
if (bag === void 0) continue;
|
|
10057
|
-
for (const needle of [...logOnlyValuesOf.get(bag) ?? []]) for (const pieces of splits) for (const fragment of fragmentsOfNeedleIn(text, delimiter, needle, pieces)) if (fragment !== needle) recordLogOnlyValue(to, fragment);
|
|
10058
|
-
}
|
|
10059
|
-
}
|
|
10060
|
-
function fragmentsOfNeedleIn(text, delimiter, needle, pieces = text.split(delimiter)) {
|
|
10061
|
-
const fragments = /* @__PURE__ */ new Set();
|
|
10062
|
-
if (needle === "") return fragments;
|
|
10063
|
-
const starts = [];
|
|
10064
|
-
if (text === needle) starts.push(0);
|
|
10065
|
-
else if (needle.length >= 4) for (let at = text.indexOf(needle); at !== -1; at = text.indexOf(needle, at + 1)) starts.push(at);
|
|
10066
|
-
if (starts.length === 0) return fragments;
|
|
10067
|
-
const spans = [];
|
|
10068
|
-
let offset = 0;
|
|
10069
|
-
for (const piece of pieces) {
|
|
10070
|
-
spans.push([offset, offset + piece.length]);
|
|
10071
|
-
offset += piece.length + delimiter.length;
|
|
10072
|
-
}
|
|
10073
|
-
for (const start of starts) {
|
|
10074
|
-
const end = start + needle.length;
|
|
10075
|
-
for (const [pieceStart, pieceEnd] of spans) {
|
|
10076
|
-
const from = Math.max(pieceStart, start);
|
|
10077
|
-
const to = Math.min(pieceEnd, end);
|
|
10078
|
-
if (from < to) fragments.add(text.slice(from, to));
|
|
10079
|
-
}
|
|
10080
|
-
}
|
|
10081
|
-
return fragments;
|
|
10082
|
-
}
|
|
10083
|
-
function printedLeavesOf(value) {
|
|
10084
|
-
const leaves = wholeStringLeavesOf(value);
|
|
10085
|
-
const seen = /* @__PURE__ */ new Set();
|
|
10086
|
-
const walk = (node) => {
|
|
10087
|
-
if (typeof node === "number" || typeof node === "boolean") {
|
|
10088
|
-
leaves.add(String(node));
|
|
10089
|
-
return;
|
|
10090
|
-
}
|
|
10091
|
-
if (node === null || typeof node !== "object") return;
|
|
10092
|
-
if (seen.has(node)) return;
|
|
10093
|
-
seen.add(node);
|
|
10094
|
-
for (const child of Array.isArray(node) ? node : Object.values(node)) walk(child);
|
|
10095
|
-
};
|
|
10096
|
-
walk(value);
|
|
10097
|
-
return leaves;
|
|
10098
|
-
}
|
|
10099
|
-
function shareLogOnlyValues(view, target) {
|
|
10100
|
-
logOnlyValuesOf.set(view, sideSetOf(logOnlyValuesOf, target));
|
|
10101
|
-
}
|
|
10102
|
-
function recordLogOnlyParameterValue(secrets, value, splitDelimiters) {
|
|
10103
|
-
const record = (leaf) => {
|
|
10104
|
-
const spelled = typeof leaf === "string" ? leaf : typeof leaf === "number" || typeof leaf === "boolean" ? String(leaf) : void 0;
|
|
10105
|
-
if (spelled === void 0) return;
|
|
10106
|
-
recordLogOnlyValue(secrets, spelled);
|
|
10107
|
-
for (const delimiter of splitDelimiters ?? []) {
|
|
10108
|
-
if (delimiter === "" || !spelled.includes(delimiter)) continue;
|
|
10109
|
-
for (const piece of spelled.split(delimiter)) recordLogOnlyValue(secrets, piece);
|
|
10110
|
-
}
|
|
10111
|
-
};
|
|
10112
|
-
if (Array.isArray(value)) {
|
|
10113
|
-
for (const element of value) record(element);
|
|
10114
|
-
record(value.map((element) => String(element)).join(","));
|
|
10115
|
-
return;
|
|
10116
|
-
}
|
|
10117
|
-
record(value);
|
|
10118
|
-
}
|
|
10119
|
-
function literalSplitDelimitersOf(template, parameters) {
|
|
10120
|
-
const delimiters = /* @__PURE__ */ new Set();
|
|
10121
|
-
if (parameters.size === 0) return delimiters;
|
|
10122
|
-
const reads = (node, seen) => {
|
|
10123
|
-
if (typeof node === "string") {
|
|
10124
|
-
for (const name of parameters) if (node.includes(`\${${name}}`)) return true;
|
|
10125
|
-
return false;
|
|
10126
|
-
}
|
|
10127
|
-
if (node === null || typeof node !== "object" || seen.has(node)) return false;
|
|
10128
|
-
seen.add(node);
|
|
10129
|
-
if (!Array.isArray(node)) {
|
|
10130
|
-
const ref = node["Ref"];
|
|
10131
|
-
if (typeof ref === "string" && parameters.has(ref)) return true;
|
|
10132
|
-
}
|
|
10133
|
-
for (const child of Array.isArray(node) ? node : Object.values(node)) if (reads(child, seen)) return true;
|
|
10134
|
-
return false;
|
|
10135
|
-
};
|
|
10136
|
-
const seen = /* @__PURE__ */ new Set();
|
|
10137
|
-
const walk = (node) => {
|
|
10138
|
-
if (node === null || typeof node !== "object" || seen.has(node)) return;
|
|
10139
|
-
seen.add(node);
|
|
10140
|
-
if (Array.isArray(node)) {
|
|
10141
|
-
for (const child of node) walk(child);
|
|
10142
|
-
return;
|
|
10143
|
-
}
|
|
10144
|
-
for (const [key, child] of Object.entries(node)) {
|
|
10145
|
-
if (key === "Fn::Split" && Array.isArray(child) && typeof child[0] === "string" && reads(child[1], /* @__PURE__ */ new Set())) delimiters.add(child[0]);
|
|
10146
|
-
walk(child);
|
|
10147
|
-
}
|
|
10148
|
-
};
|
|
10149
|
-
walk(template);
|
|
10150
|
-
return delimiters;
|
|
10151
|
-
}
|
|
10152
|
-
function printingCorpusOf(secrets) {
|
|
10153
|
-
const logOnly = logOnlyValuesOf.get(secrets);
|
|
10154
|
-
if (logOnly === void 0 || logOnly.size === 0) return secrets;
|
|
10155
|
-
const corpus = new Map(secrets);
|
|
10156
|
-
for (const needle of logOnly) if (!corpus.has(needle)) corpus.set(needle, "***");
|
|
10157
|
-
return corpus;
|
|
10158
|
-
}
|
|
10159
|
-
function logOnlyValueCount(secrets) {
|
|
10160
|
-
return logOnlyValuesOf.get(secrets)?.size ?? 0;
|
|
10161
|
-
}
|
|
10162
|
-
function unionOfSecretBags(bags) {
|
|
10163
|
-
const union = /* @__PURE__ */ new Map();
|
|
10164
|
-
for (const bag of bags) {
|
|
10165
|
-
if (bag === void 0) continue;
|
|
10166
|
-
for (const [plaintext, expression] of bag) if (!union.has(plaintext)) union.set(plaintext, expression);
|
|
10167
|
-
carryLogOnlyValues(bag, union);
|
|
10168
|
-
}
|
|
10169
|
-
return union;
|
|
10170
|
-
}
|
|
10171
|
-
function createUnionSecretMasker(bags) {
|
|
10172
|
-
const present = bags.filter((bag) => bag !== void 0);
|
|
10173
|
-
let stamp;
|
|
10174
|
-
let needles = /* @__PURE__ */ new Set();
|
|
10175
|
-
let scanned = [];
|
|
10176
|
-
return (text) => {
|
|
10177
|
-
const now = present.map((bag) => `${bag.size}:${logOnlyValueCount(bag)}`).join(",");
|
|
10178
|
-
if (now !== stamp) {
|
|
10179
|
-
needles = /* @__PURE__ */ new Set();
|
|
10180
|
-
for (const bag of present) {
|
|
10181
|
-
for (const plaintext of bag.keys()) needles.add(plaintext);
|
|
10182
|
-
for (const plaintext of logOnlyValuesOf.get(bag) ?? []) needles.add(plaintext);
|
|
10183
|
-
}
|
|
10184
|
-
scanned = printingNeedles(needles);
|
|
10185
|
-
stamp = now;
|
|
10186
|
-
}
|
|
10187
|
-
if (text !== "" && needles.has(text)) return "***";
|
|
10188
|
-
return maskMatchSpans(text, scanned, "***");
|
|
10189
|
-
};
|
|
10190
|
-
}
|
|
10191
|
-
function hasLogOnlyValues(secrets) {
|
|
10192
|
-
if (secrets === void 0) return false;
|
|
10193
|
-
const logOnly = logOnlyValuesOf.get(secrets);
|
|
10194
|
-
return logOnly !== void 0 && logOnly.size > 0;
|
|
10195
|
-
}
|
|
10196
|
-
function hasMaskableValues(secrets) {
|
|
10197
|
-
if (secrets === void 0) return false;
|
|
10198
|
-
if (secrets.size > 0) return true;
|
|
10199
|
-
const logOnly = logOnlyValuesOf.get(secrets);
|
|
10200
|
-
return logOnly !== void 0 && logOnly.size > 0;
|
|
10201
|
-
}
|
|
10202
|
-
|
|
10203
|
-
//#endregion
|
|
10204
|
-
//#region src/deployment/secret-redaction/reference-provenance.ts
|
|
10205
|
-
const passProvenanceOf = /* @__PURE__ */ new WeakMap();
|
|
10206
|
-
const MAX_REFERENCE_VERSIONS = 8;
|
|
10207
|
-
function provenanceTableFor(secrets) {
|
|
10208
|
-
let table = passProvenanceOf.get(secrets);
|
|
10209
|
-
if (table === void 0) {
|
|
10210
|
-
table = /* @__PURE__ */ new Map();
|
|
10211
|
-
passProvenanceOf.set(secrets, table);
|
|
10212
|
-
}
|
|
10213
|
-
return table;
|
|
10214
|
-
}
|
|
10215
|
-
function shareReferenceProvenance(view, pass) {
|
|
10216
|
-
passProvenanceOf.set(view, provenanceTableFor(pass));
|
|
10217
|
-
}
|
|
10218
|
-
function entryFor(secrets, token) {
|
|
10219
|
-
const table = provenanceTableFor(secrets);
|
|
10220
|
-
let entry = table.get(token);
|
|
10221
|
-
if (entry === void 0) {
|
|
10222
|
-
entry = {
|
|
10223
|
-
regions: /* @__PURE__ */ new Set(),
|
|
10224
|
-
regionUnknown: false,
|
|
10225
|
-
versions: /* @__PURE__ */ new Set(),
|
|
10226
|
-
versionUnknown: false,
|
|
10227
|
-
readVersions: /* @__PURE__ */ new Set()
|
|
10228
|
-
};
|
|
10229
|
-
table.set(token, entry);
|
|
10230
|
-
}
|
|
10231
|
-
return entry;
|
|
10232
|
-
}
|
|
10233
|
-
function recordReferenceResolution(secrets, token, resolution) {
|
|
10234
|
-
const entry = entryFor(secrets, token);
|
|
10235
|
-
if (resolution.region === void 0) entry.regionUnknown = true;
|
|
10236
|
-
else entry.regions.add(resolution.region);
|
|
10237
|
-
if (resolution.version === void 0) {
|
|
10238
|
-
entry.versionUnknown = true;
|
|
10239
|
-
return;
|
|
10240
|
-
}
|
|
10241
|
-
entry.versions.add(resolution.version);
|
|
10242
|
-
if (resolution.route === "read") entry.readVersions.add(resolution.version);
|
|
10243
|
-
}
|
|
10244
|
-
function recordReferenceProvenanceEntry(secrets, token, provenance, route) {
|
|
10245
|
-
const entry = entryFor(secrets, token);
|
|
10246
|
-
if (provenance.region === void 0) entry.regionUnknown = true;
|
|
10247
|
-
else entry.regions.add(provenance.region);
|
|
10248
|
-
if (provenance.versions === void 0 || provenance.versions.length === 0) {
|
|
10249
|
-
entry.versionUnknown = true;
|
|
10250
|
-
return;
|
|
10251
|
-
}
|
|
10252
|
-
for (const version of provenance.versions) {
|
|
10253
|
-
entry.versions.add(version);
|
|
10254
|
-
if (route === "read") entry.readVersions.add(version);
|
|
10255
|
-
}
|
|
10256
|
-
if (route === "literal") for (const version of provenance.readVersions ?? []) entry.readVersions.add(version);
|
|
10257
|
-
}
|
|
10258
|
-
function mergeReferenceProvenance(from, to) {
|
|
10259
|
-
const source = passProvenanceOf.get(from);
|
|
10260
|
-
if (source === void 0 || from === to) return;
|
|
10261
|
-
for (const [token, entry] of source) {
|
|
10262
|
-
const target = entryFor(to, token);
|
|
10263
|
-
for (const region of entry.regions) target.regions.add(region);
|
|
10264
|
-
target.regionUnknown ||= entry.regionUnknown;
|
|
10265
|
-
for (const version of entry.versions) target.versions.add(version);
|
|
10266
|
-
target.versionUnknown ||= entry.versionUnknown;
|
|
10267
|
-
for (const version of entry.readVersions) target.readVersions.add(version);
|
|
10268
|
-
}
|
|
10269
|
-
}
|
|
10270
|
-
function hasPassProvenance(secrets) {
|
|
10271
|
-
if (secrets === void 0) return false;
|
|
10272
|
-
const table = passProvenanceOf.get(secrets);
|
|
10273
|
-
return table !== void 0 && table.size > 0;
|
|
10274
|
-
}
|
|
10275
|
-
function passProvenanceFor(secrets, token) {
|
|
10276
|
-
if (secrets === void 0) return void 0;
|
|
10277
|
-
const entry = passProvenanceOf.get(secrets)?.get(token);
|
|
10278
|
-
if (entry === void 0) return void 0;
|
|
10279
|
-
return finalize(entry);
|
|
10280
|
-
}
|
|
10281
|
-
function passReadVersionsFor(secrets, token) {
|
|
10282
|
-
if (secrets === void 0) return void 0;
|
|
10283
|
-
const read = passProvenanceOf.get(secrets)?.get(token)?.readVersions;
|
|
10284
|
-
return read === void 0 || read.size === 0 ? void 0 : read;
|
|
10285
|
-
}
|
|
10286
|
-
function finalize(entry) {
|
|
10287
|
-
const out = {};
|
|
10288
|
-
if (!entry.regionUnknown && entry.regions.size === 1) out.region = [...entry.regions][0];
|
|
10289
|
-
if (!entry.versionUnknown && entry.versions.size > 0 && entry.versions.size <= 8) {
|
|
10290
|
-
out.versions = [...entry.versions].sort();
|
|
10291
|
-
if (entry.readVersions.size > 0) out.readVersions = [...entry.readVersions].sort();
|
|
10292
|
-
}
|
|
10293
|
-
return out;
|
|
10294
|
-
}
|
|
10295
|
-
function snapshotPassProvenance(secrets) {
|
|
10296
|
-
if (secrets === void 0) return void 0;
|
|
10297
|
-
const table = passProvenanceOf.get(secrets);
|
|
10298
|
-
if (table === void 0 || table.size === 0) return void 0;
|
|
10299
|
-
const out = /* @__PURE__ */ new Map();
|
|
10300
|
-
for (const [token, entry] of table) out.set(token, finalize(entry));
|
|
10301
|
-
return out;
|
|
10302
|
-
}
|
|
10303
|
-
|
|
10304
|
-
//#endregion
|
|
10305
|
-
//#region src/deployment/secret-redaction/recording.ts
|
|
10306
|
-
const scopeMaps = /* @__PURE__ */ new WeakSet();
|
|
10307
|
-
var WriteThroughSecrets = class extends Map {
|
|
10308
|
-
pass;
|
|
10309
|
-
constructor(pass) {
|
|
10310
|
-
super();
|
|
10311
|
-
this.pass = pass;
|
|
10312
|
-
}
|
|
10313
|
-
set(plaintext, expression) {
|
|
10314
|
-
super.set(plaintext, expression);
|
|
10315
|
-
this.pass.set(plaintext, expression);
|
|
10316
|
-
return this;
|
|
10317
|
-
}
|
|
10318
|
-
};
|
|
10319
|
-
function openRecordingScope(pass, policy) {
|
|
10320
|
-
const secrets = new WriteThroughSecrets(pass);
|
|
10321
|
-
scopeMaps.add(secrets);
|
|
10322
|
-
shareLogOnlyValues(secrets, pass);
|
|
10323
|
-
for (const [kind, share] of Object.entries(SCOPE_SHARERS)) if (policy[kind] === "carry") share(secrets, pass);
|
|
10324
|
-
return {
|
|
10325
|
-
secrets,
|
|
10326
|
-
pass
|
|
10327
|
-
};
|
|
10328
|
-
}
|
|
10329
|
-
const SCOPE_SHARERS = {
|
|
10330
|
-
pairs: sharePairTable,
|
|
10331
|
-
"mask-only-marks": (scope, pass) => {
|
|
10332
|
-
for (const table of [
|
|
10333
|
-
freshNoEchoValuesOf,
|
|
10334
|
-
containmentValuesOf,
|
|
10335
|
-
noEchoParameterValuesOf
|
|
10336
|
-
]) table.set(scope, sideSetOf(table, pass));
|
|
10337
|
-
},
|
|
10338
|
-
"reference-provenance": shareReferenceProvenance,
|
|
10339
|
-
"physical-name-copies": (scope, pass) => {
|
|
10340
|
-
physicalNameCopiesOf.set(scope, sideSetOf(physicalNameCopiesOf, pass));
|
|
10341
|
-
},
|
|
10342
|
-
"public-proofs": sharePublicProofs
|
|
10343
|
-
};
|
|
10344
|
-
function isRecordingScope(secrets) {
|
|
10345
|
-
return scopeMaps.has(secrets);
|
|
10346
|
-
}
|
|
10347
|
-
function foldRecording(from, to, policy) {
|
|
10348
|
-
if (from === to) return;
|
|
10349
|
-
for (const [plaintext, expression] of from) to.set(plaintext, expression);
|
|
10350
|
-
for (const [kind, carry] of Object.entries(FOLD_CARRIERS)) if (policy[kind] === "carry") carry(from, to);
|
|
10351
|
-
}
|
|
10352
|
-
const FOLD_CARRIERS = {
|
|
10353
|
-
"mask-only-marks": carryMaskOnlyMarks,
|
|
10354
|
-
"reference-provenance": mergeReferenceProvenance,
|
|
10355
|
-
pairs: mergePairTables,
|
|
10356
|
-
"log-only": carryLogOnlyValues,
|
|
10357
|
-
"physical-name-copies": (from, to) => {
|
|
10358
|
-
for (const physicalId of physicalNameCopiesOf.get(from) ?? []) recordPhysicalNameCopy(to, physicalId);
|
|
10359
|
-
},
|
|
10360
|
-
"public-proofs": carryPublicProofs
|
|
10361
|
-
};
|
|
10362
|
-
function recordSecretResolution(secrets, expression, plaintext, options) {
|
|
10363
|
-
secrets.set(plaintext, expression);
|
|
10364
|
-
if (options.pairEvidence) recordResolvedPair(secrets, expression, plaintext);
|
|
10365
|
-
}
|
|
10366
|
-
|
|
10367
|
-
//#endregion
|
|
10368
|
-
//#region src/deployment/secret-redaction/context.ts
|
|
10369
|
-
const RULES_BY_PROVENANCE = {
|
|
10370
|
-
"template-derived": TEMPLATE_DERIVED_RULES,
|
|
10371
|
-
"template-sourced": TEMPLATE_SOURCED_RULES,
|
|
10372
|
-
"state-readback": STATE_SOURCED_READBACK_RULES,
|
|
10373
|
-
"state-baseline": STATE_SOURCED_BASELINE_RULES,
|
|
10374
|
-
"state-cross-generation": STATE_SOURCED_CROSS_GENERATION_RULES,
|
|
10375
|
-
"state-derived": STATE_DERIVED_RULES
|
|
10376
|
-
};
|
|
10377
|
-
function redactForState(bag, context) {
|
|
10378
|
-
refuseScopeAsPass(context.secrets);
|
|
10379
|
-
if (context.provenance === "value-scan") return redactSecretsForState(bag, context.secrets);
|
|
10380
|
-
const { secrets, source, provenance } = context;
|
|
10381
|
-
if (!((context.provenance === "template-derived" || context.provenance === "template-sourced" || context.provenance === "state-derived") && context.generation === "same-generation") || !isPlainBag(bag)) return redactAtProvenance(bag, secrets, source, provenance, false);
|
|
10382
|
-
const copy = shallowCopy(bag);
|
|
10383
|
-
const redacted = redactAtProvenance(copy, secrets, source, provenance, true);
|
|
10384
|
-
return redacted === copy ? shallowCopy(copy) : redacted;
|
|
10385
|
-
}
|
|
10386
|
-
function redactAtProvenance(bag, secrets, source, provenance, sameGeneration) {
|
|
10387
|
-
refuseScopeAsPass(secrets);
|
|
10388
|
-
return redactSecretsForState(bag, secrets, source, RULES_BY_PROVENANCE[provenance], sameGeneration);
|
|
10389
|
-
}
|
|
10390
|
-
function refuseScopeAsPass(secrets) {
|
|
10391
|
-
if (isRecordingScope(secrets)) throw new Error("Internal error: a bag was redacted for persistence with a recording scope; pass the scope's pass map instead.");
|
|
10392
|
-
}
|
|
10393
|
-
function isPlainBag(bag) {
|
|
10394
|
-
if (Array.isArray(bag)) return true;
|
|
10395
|
-
if (bag === null || typeof bag !== "object") return false;
|
|
10396
|
-
const proto = Object.getPrototypeOf(bag);
|
|
10397
|
-
return proto === Object.prototype || proto === null;
|
|
10398
|
-
}
|
|
10399
|
-
function shallowCopy(bag) {
|
|
10400
|
-
return Array.isArray(bag) ? [...bag] : { ...bag };
|
|
10401
|
-
}
|
|
10402
|
-
|
|
10403
|
-
//#endregion
|
|
10404
|
-
//#region src/deployment/secret-redaction/positions.ts
|
|
10405
|
-
const SKELETON_WILDCARD = `${DYNAMIC_REFERENCE_INNER_CHAR}*`;
|
|
10406
|
-
const MAX_SKELETON_WILDCARDS = 3;
|
|
10407
|
-
const MAX_SKELETON_CANDIDATE_LENGTH = 512;
|
|
10408
|
-
function joinSkeletonSegments(segments) {
|
|
10409
|
-
const out = [];
|
|
10410
|
-
let wildcards = 0;
|
|
10411
|
-
for (const segment of segments) {
|
|
10412
|
-
if (segment === "") continue;
|
|
10413
|
-
if (segment === SKELETON_WILDCARD) {
|
|
10414
|
-
if (out[out.length - 1] === SKELETON_WILDCARD) continue;
|
|
10415
|
-
wildcards += 1;
|
|
10416
|
-
if (wildcards > MAX_SKELETON_WILDCARDS) return void 0;
|
|
10417
|
-
}
|
|
10418
|
-
out.push(segment);
|
|
10419
|
-
}
|
|
10420
|
-
return out.join("");
|
|
10421
|
-
}
|
|
10422
|
-
function intrinsicSkeletonPattern(source) {
|
|
10423
|
-
const segments = intrinsicSkeletonSegments(source);
|
|
10424
|
-
if (segments === void 0) return void 0;
|
|
10425
|
-
return anchoredSkeletonPattern(segments);
|
|
10426
|
-
}
|
|
10427
|
-
function anchoredSkeletonPattern(segments) {
|
|
10428
|
-
const body = joinSkeletonSegments(segments.map((segment) => segment === UNKNOWN_PART ? SKELETON_WILDCARD : escapeRegExp$2(segment)));
|
|
10429
|
-
return body === void 0 ? void 0 : new RegExp(`^${body}$`);
|
|
10430
|
-
}
|
|
10431
|
-
const UNKNOWN_PART = Symbol("unknown intrinsic part");
|
|
10432
|
-
const UNKNOWN_PART_PLACEHOLDER = "\0";
|
|
10433
|
-
function joinPartLiteralText(part) {
|
|
10434
|
-
if (typeof part === "string") return part;
|
|
10435
|
-
if (typeof part === "number" || typeof part === "boolean") return String(part);
|
|
10436
|
-
}
|
|
10437
|
-
function intrinsicSkeletonSegments(source) {
|
|
10438
|
-
const keys = Object.keys(source);
|
|
10439
|
-
if (keys.length !== 1) return void 0;
|
|
10440
|
-
const key = keys[0];
|
|
10441
|
-
if (key === "Fn::Join") {
|
|
10442
|
-
const args = source[key];
|
|
10443
|
-
if (!Array.isArray(args) || args.length !== 2) return void 0;
|
|
10444
|
-
const [delimiter, parts] = args;
|
|
10445
|
-
if (typeof delimiter !== "string" || !Array.isArray(parts)) return void 0;
|
|
10446
|
-
const segments = [];
|
|
10447
|
-
parts.forEach((part, index) => {
|
|
10448
|
-
if (index > 0) segments.push(delimiter);
|
|
10449
|
-
segments.push(joinPartLiteralText(part) ?? UNKNOWN_PART);
|
|
10450
|
-
});
|
|
10451
|
-
return segments;
|
|
10452
|
-
}
|
|
10453
|
-
if (key === "Fn::Sub") {
|
|
10454
|
-
const args = source[key];
|
|
10455
|
-
const template = typeof args === "string" ? args : Array.isArray(args) ? args[0] : void 0;
|
|
10456
|
-
if (typeof template !== "string") return void 0;
|
|
10457
|
-
const segments = [];
|
|
10458
|
-
let cursor = 0;
|
|
10459
|
-
const variable = /\$\{([^}]*)\}/g;
|
|
10460
|
-
let hit;
|
|
10461
|
-
while ((hit = variable.exec(template)) !== null) {
|
|
10462
|
-
segments.push(template.slice(cursor, hit.index));
|
|
10463
|
-
const inner = hit[1];
|
|
10464
|
-
segments.push(inner.startsWith("!") ? `\${${inner.slice(1)}}` : UNKNOWN_PART);
|
|
10465
|
-
cursor = hit.index + hit[0].length;
|
|
10466
|
-
}
|
|
10467
|
-
segments.push(template.slice(cursor));
|
|
10468
|
-
return segments;
|
|
10469
|
-
}
|
|
10470
|
-
}
|
|
10471
|
-
function positionByIntrinsicSkeleton(bag, source, secrets, secretExpressions) {
|
|
10472
|
-
if (bag === "" || !secrets.has(bag)) return void 0;
|
|
10473
|
-
const pattern = intrinsicSkeletonPattern(source);
|
|
10474
|
-
if (!pattern) return void 0;
|
|
10475
|
-
const plaintextOf = plaintextIndexOf(secrets);
|
|
10476
|
-
let matched;
|
|
10477
|
-
for (const candidate of /* @__PURE__ */ new Set([...secretExpressions, ...recordedSecretExpressions])) {
|
|
10478
|
-
if (candidate.length > MAX_SKELETON_CANDIDATE_LENGTH) return void 0;
|
|
10479
|
-
if (!pattern.test(candidate)) continue;
|
|
10480
|
-
const recordedPlaintext = plaintextOf.get(candidate);
|
|
10481
|
-
if (recordedPlaintext !== void 0 && recordedPlaintext !== bag) continue;
|
|
10482
|
-
if (matched !== void 0) return void 0;
|
|
10483
|
-
matched = candidate;
|
|
10484
|
-
}
|
|
10485
|
-
return matched;
|
|
10486
|
-
}
|
|
10487
|
-
function singleSpanFrame(bag, source) {
|
|
10488
|
-
const spans = dynamicReferenceSpans(source);
|
|
10489
|
-
if (spans.length !== 1) return void 0;
|
|
10490
|
-
const [span] = spans;
|
|
10491
|
-
const token = source.slice(span.start, span.end);
|
|
10492
|
-
const prefix = source.slice(0, span.start);
|
|
10493
|
-
const suffix = source.slice(span.end);
|
|
10494
|
-
if (bag.length <= prefix.length + suffix.length) return void 0;
|
|
10495
|
-
if (!bag.startsWith(prefix) || !bag.endsWith(suffix)) return void 0;
|
|
10496
|
-
const middle = bag.slice(prefix.length, bag.length - suffix.length);
|
|
10497
|
-
if (isSingleDynamicReferenceToken(middle)) return void 0;
|
|
10498
|
-
return {
|
|
10499
|
-
token,
|
|
10500
|
-
prefix,
|
|
10501
|
-
suffix,
|
|
10502
|
-
middle
|
|
10503
|
-
};
|
|
10504
|
-
}
|
|
10505
|
-
function positionByEmbeddedSpan(bag, source, secrets, bagIsSameGeneration) {
|
|
10506
|
-
const frame = singleSpanFrame(bag, source);
|
|
10507
|
-
if (frame === void 0) {
|
|
10508
|
-
if (dynamicReferenceSpans(source).length >= 2) {
|
|
10509
|
-
if (certifiesRenderedLiteral(bag, source, secrets, bagIsSameGeneration)) return source;
|
|
10510
|
-
if (bagIsSameGeneration) {
|
|
10511
|
-
const mixed = certifiedMixedLiteral(bag, source, secrets);
|
|
10512
|
-
if (mixed !== void 0) return mixed;
|
|
10513
|
-
}
|
|
10514
|
-
}
|
|
10515
|
-
return redactForState(bag, {
|
|
10516
|
-
provenance: "value-scan",
|
|
10517
|
-
secrets
|
|
10518
|
-
});
|
|
10519
|
-
}
|
|
10520
|
-
const recorded = resolvedPlaintextOf(secrets, frame.token);
|
|
10521
|
-
if (recorded === void 0 || recorded !== frame.middle) return redactForState(bag, {
|
|
10522
|
-
provenance: "value-scan",
|
|
10523
|
-
secrets
|
|
10524
|
-
});
|
|
10525
|
-
return writeFramedTokenWithinScanBound(bag, secrets, frame, bagIsSameGeneration);
|
|
10526
|
-
}
|
|
10527
|
-
function pairedSpans(source, secrets) {
|
|
10528
|
-
const spans = dynamicReferenceSpans(source);
|
|
10529
|
-
if (spans.length === 0) return void 0;
|
|
10530
|
-
const out = [];
|
|
10531
|
-
for (const span of spans) {
|
|
10532
|
-
const plaintext = resolvedPlaintextOf(secrets, source.slice(span.start, span.end));
|
|
10533
|
-
if (plaintext === void 0 || plaintext === "") return void 0;
|
|
10534
|
-
if (isSingleDynamicReferenceToken(plaintext)) return void 0;
|
|
10535
|
-
out.push({
|
|
10536
|
-
...span,
|
|
10537
|
-
plaintext
|
|
10538
|
-
});
|
|
10539
|
-
}
|
|
10540
|
-
return out;
|
|
10541
|
-
}
|
|
10542
|
-
function renderedTokenOf(spelling, secrets, plaintext) {
|
|
10543
|
-
const spans = pairedSpans(spelling, secrets);
|
|
10544
|
-
if (spans === void 0) return void 0;
|
|
10545
|
-
const tokens = new Set(spans.filter((span) => span.plaintext === plaintext).map((span) => spelling.slice(span.start, span.end)));
|
|
10546
|
-
return tokens.size === 1 ? [...tokens][0] : void 0;
|
|
10547
|
-
}
|
|
10548
|
-
function renderSpans(source, spans, textOf) {
|
|
10549
|
-
let out = "";
|
|
10550
|
-
let cursor = 0;
|
|
10551
|
-
spans.forEach((span, index) => {
|
|
10552
|
-
out += source.slice(cursor, span.start) + textOf(index);
|
|
10553
|
-
cursor = span.end;
|
|
10554
|
-
});
|
|
10555
|
-
return out + source.slice(cursor);
|
|
10556
|
-
}
|
|
10557
|
-
function rendersLiteralTo(spelling, secrets, value) {
|
|
10558
|
-
return renderedLiteralSpans(spelling, secrets, value) !== void 0;
|
|
10559
|
-
}
|
|
10560
|
-
function renderedLiteralSpans(spelling, secrets, value) {
|
|
10561
|
-
const spans = pairedSpans(spelling, secrets);
|
|
10562
|
-
if (spans === void 0) return void 0;
|
|
10563
|
-
if (renderSpans(spelling, spans, (i) => spans[i].plaintext) !== value) return void 0;
|
|
10564
|
-
return redactForState(spelling, {
|
|
10565
|
-
provenance: "value-scan",
|
|
10566
|
-
secrets
|
|
10567
|
-
}) === spelling ? spans : void 0;
|
|
10568
|
-
}
|
|
10569
|
-
function certifiesRenderedLiteral(bag, source, secrets, bagIsSameGeneration) {
|
|
10570
|
-
const spans = renderedLiteralSpans(source, secrets, bag);
|
|
10571
|
-
if (spans === void 0) return false;
|
|
10572
|
-
const survivors = [];
|
|
10573
|
-
for (const span of spans) {
|
|
10574
|
-
const survivor = secrets.get(span.plaintext);
|
|
10575
|
-
if (survivor === void 0) return false;
|
|
10576
|
-
survivors.push(survivor);
|
|
10577
|
-
}
|
|
10578
|
-
const scanned = redactForState(bag, {
|
|
10579
|
-
provenance: "value-scan",
|
|
10580
|
-
secrets
|
|
10581
|
-
});
|
|
10582
|
-
if (scanned === renderSpans(source, spans, (i) => survivors[i])) return true;
|
|
10583
|
-
if (!bagIsSameGeneration) return false;
|
|
10584
|
-
return scanned === renderSpans(source, spans, (i) => spans[i].plaintext.length >= 4 ? survivors[i] : spans[i].plaintext);
|
|
10585
|
-
}
|
|
10586
|
-
function certifiedMixedLiteral(bag, source, secrets) {
|
|
10587
|
-
if (legacyMixedScan.has(secrets)) return void 0;
|
|
10588
|
-
const answer = certifyMixedLiteral(bag, source, secrets);
|
|
10589
|
-
if (answer !== void 0) mixedAnswered.add(secrets);
|
|
10590
|
-
return answer;
|
|
10591
|
-
}
|
|
10592
|
-
const mixedAnswered = /* @__PURE__ */ new WeakSet();
|
|
10593
|
-
const legacyMixedScan = /* @__PURE__ */ new WeakSet();
|
|
10594
|
-
function mixedLiteralAnswered(secrets) {
|
|
10595
|
-
return mixedAnswered.has(secrets);
|
|
10596
|
-
}
|
|
10597
|
-
function withLegacyMixedScan(secrets, run) {
|
|
10598
|
-
if (legacyMixedScan.has(secrets)) return run();
|
|
10599
|
-
legacyMixedScan.add(secrets);
|
|
10600
|
-
try {
|
|
10601
|
-
return run();
|
|
10602
|
-
} finally {
|
|
10603
|
-
legacyMixedScan.delete(secrets);
|
|
10604
|
-
}
|
|
10605
|
-
}
|
|
10606
|
-
function certifyMixedLiteral(bag, source, secrets) {
|
|
10607
|
-
const spans = dynamicReferenceSpans(source);
|
|
10608
|
-
const parts = [];
|
|
10609
|
-
for (const span of spans) {
|
|
10610
|
-
const token = source.slice(span.start, span.end);
|
|
10611
|
-
const plaintext = resolvedPlaintextOf(secrets, token);
|
|
10612
|
-
if (plaintext !== void 0) {
|
|
10613
|
-
if (plaintext === "" || isSingleDynamicReferenceToken(plaintext)) return void 0;
|
|
10614
|
-
const survivor = secrets.get(plaintext);
|
|
10615
|
-
if (survivor === void 0) return void 0;
|
|
10616
|
-
parts.push({
|
|
10617
|
-
kind: "secret",
|
|
10618
|
-
plaintext,
|
|
10619
|
-
survivor
|
|
10620
|
-
});
|
|
10621
|
-
continue;
|
|
7108
|
+
if (abandonedAt !== void 0) this.abandonedLocks.set(key, abandonedAt);
|
|
7109
|
+
try {
|
|
7110
|
+
const retryEtag = await this.putLockObject(key, lockInfo);
|
|
7111
|
+
this.logger.debug(`Lock acquired for stack: ${stackRef(stackName, region)} after expired lock cleanup, owner: ${displaySafe(lockOwner)}`);
|
|
7112
|
+
this.trackHeldLock({
|
|
7113
|
+
stackName,
|
|
7114
|
+
region,
|
|
7115
|
+
key,
|
|
7116
|
+
info: lockInfo,
|
|
7117
|
+
etag: retryEtag
|
|
7118
|
+
});
|
|
7119
|
+
return true;
|
|
7120
|
+
} catch (retryError) {
|
|
7121
|
+
if (this.isForeignLockError(retryError)) {
|
|
7122
|
+
this.logger.debug(`Lock was acquired by another process during expired lock cleanup for stack: ${stackRef(stackName, region)}`);
|
|
7123
|
+
return false;
|
|
7124
|
+
}
|
|
7125
|
+
throw retryError;
|
|
7126
|
+
} finally {
|
|
7127
|
+
await this.purgeLockVersions(key, "reap");
|
|
7128
|
+
}
|
|
7129
|
+
}
|
|
7130
|
+
return false;
|
|
7131
|
+
}
|
|
7132
|
+
throw new LockError(`Failed to acquire lock for stack ${safeSegment(stackName)} (${safeSegment(region)}): ` + errorDetail$1(error), error instanceof Error ? error : void 0);
|
|
10622
7133
|
}
|
|
10623
|
-
const value = provenPublicValue(secrets, token);
|
|
10624
|
-
if (value === void 0 || value === "" || value.includes("{{resolve:")) return void 0;
|
|
10625
|
-
parts.push({
|
|
10626
|
-
kind: "public",
|
|
10627
|
-
value
|
|
10628
|
-
});
|
|
10629
|
-
}
|
|
10630
|
-
const secretParts = parts.filter((p) => p.kind === "secret");
|
|
10631
|
-
const publicParts = parts.filter((p) => p.kind === "public");
|
|
10632
|
-
if (secretParts.length === 0 || publicParts.length === 0) return void 0;
|
|
10633
|
-
const textOf = (secret) => (i) => {
|
|
10634
|
-
const part = parts[i];
|
|
10635
|
-
return part.kind === "secret" ? secret(part) : part.value;
|
|
10636
|
-
};
|
|
10637
|
-
if (renderSpans(source, spans, textOf((p) => p.plaintext)) !== bag) return void 0;
|
|
10638
|
-
if (redactForState(source, {
|
|
10639
|
-
provenance: "value-scan",
|
|
10640
|
-
secrets
|
|
10641
|
-
}) !== source) return void 0;
|
|
10642
|
-
if (redactForState(bag, {
|
|
10643
|
-
provenance: "value-scan",
|
|
10644
|
-
secrets
|
|
10645
|
-
}) !== renderSpans(source, spans, textOf((p) => p.plaintext.length >= 4 ? p.survivor : p.plaintext))) return void 0;
|
|
10646
|
-
return renderSpans(source, spans, (i) => {
|
|
10647
|
-
const part = parts[i];
|
|
10648
|
-
return part.kind === "secret" ? source.slice(spans[i].start, spans[i].end) : part.value;
|
|
10649
|
-
});
|
|
10650
|
-
}
|
|
10651
|
-
function writeFramedTokenWithinScanBound(bag, secrets, frame, bagIsSameGeneration) {
|
|
10652
|
-
const scanned = redactForState(bag, {
|
|
10653
|
-
provenance: "value-scan",
|
|
10654
|
-
secrets
|
|
10655
|
-
});
|
|
10656
|
-
const { token, prefix, suffix, middle } = frame;
|
|
10657
|
-
const survivor = secrets.get(middle);
|
|
10658
|
-
if (survivor === void 0) return scanned;
|
|
10659
|
-
if (scanned === prefix + survivor + suffix) return prefix + token + suffix;
|
|
10660
|
-
if (bagIsSameGeneration && scanned === bag) return prefix + token + suffix;
|
|
10661
|
-
return scanned;
|
|
10662
|
-
}
|
|
10663
|
-
function positionByIntrinsicFrame(bag, source, secrets, secretExpressions, bagIsSameGeneration) {
|
|
10664
|
-
const segments = intrinsicSkeletonSegments(source);
|
|
10665
|
-
if (segments === void 0) return void 0;
|
|
10666
|
-
if (segments.some((s) => s !== UNKNOWN_PART && s.includes("\0"))) return;
|
|
10667
|
-
const frame = singleSpanFrame(bag, segments.map((s) => s === UNKNOWN_PART ? "\0" : s).join(""));
|
|
10668
|
-
if (frame === void 0) return void 0;
|
|
10669
|
-
const { token, prefix, suffix, middle } = frame;
|
|
10670
|
-
if (prefix.includes("\0") || suffix.includes("\0")) return;
|
|
10671
|
-
const pattern = anchoredSkeletonPattern(token.split("\0").flatMap((literal, i) => i === 0 ? [literal] : [UNKNOWN_PART, literal]));
|
|
10672
|
-
if (pattern === void 0) return void 0;
|
|
10673
|
-
const plaintextOf = plaintextIndexOf(secrets);
|
|
10674
|
-
let matched;
|
|
10675
|
-
for (const candidate of /* @__PURE__ */ new Set([
|
|
10676
|
-
...secretExpressions,
|
|
10677
|
-
...recordedSecretExpressions,
|
|
10678
|
-
...resolvedExpressionsOf(secrets)
|
|
10679
|
-
])) {
|
|
10680
|
-
if (candidate.length > MAX_SKELETON_CANDIDATE_LENGTH) return void 0;
|
|
10681
|
-
if (!pattern.test(candidate)) continue;
|
|
10682
|
-
const recordedPlaintext = plaintextOf.get(candidate);
|
|
10683
|
-
if (recordedPlaintext !== void 0 && recordedPlaintext !== middle) continue;
|
|
10684
|
-
if (matched !== void 0) return void 0;
|
|
10685
|
-
matched = candidate;
|
|
10686
|
-
}
|
|
10687
|
-
if (matched === void 0 || resolvedPlaintextOf(secrets, matched) !== middle) return;
|
|
10688
|
-
return writeFramedTokenWithinScanBound(bag, secrets, {
|
|
10689
|
-
token: matched,
|
|
10690
|
-
prefix,
|
|
10691
|
-
suffix,
|
|
10692
|
-
middle
|
|
10693
|
-
}, bagIsSameGeneration);
|
|
10694
|
-
}
|
|
10695
|
-
|
|
10696
|
-
//#endregion
|
|
10697
|
-
//#region src/deployment/secret-redaction/pairs.ts
|
|
10698
|
-
const resolvedPairsOf = /* @__PURE__ */ new WeakMap();
|
|
10699
|
-
const CONFLICTING_PLAINTEXT = Symbol("conflicting plaintext");
|
|
10700
|
-
function pairsFor(secrets) {
|
|
10701
|
-
let pairs = resolvedPairsOf.get(secrets);
|
|
10702
|
-
if (pairs === void 0) {
|
|
10703
|
-
pairs = /* @__PURE__ */ new Map();
|
|
10704
|
-
resolvedPairsOf.set(secrets, pairs);
|
|
10705
7134
|
}
|
|
10706
|
-
|
|
10707
|
-
|
|
10708
|
-
|
|
10709
|
-
|
|
10710
|
-
|
|
10711
|
-
|
|
10712
|
-
|
|
10713
|
-
|
|
10714
|
-
|
|
10715
|
-
|
|
10716
|
-
|
|
10717
|
-
mergePairTables(from, to);
|
|
10718
|
-
}
|
|
10719
|
-
function mergePairTables(from, to) {
|
|
10720
|
-
const pairs = resolvedPairsOf.get(from);
|
|
10721
|
-
if (pairs === void 0) return;
|
|
10722
|
-
for (const [expression, plaintext] of pairs) if (typeof plaintext === "string") recordResolvedPair(to, expression, plaintext);
|
|
10723
|
-
else pairsFor(to).set(expression, CONFLICTING_PLAINTEXT);
|
|
10724
|
-
}
|
|
10725
|
-
function sharePairTable(view, pass) {
|
|
10726
|
-
resolvedPairsOf.set(view, pairsFor(pass));
|
|
10727
|
-
}
|
|
10728
|
-
function resolvedPlaintextOf(secrets, expression) {
|
|
10729
|
-
const recorded = resolvedPairsOf.get(secrets)?.get(expression);
|
|
10730
|
-
return typeof recorded === "string" ? recorded : void 0;
|
|
10731
|
-
}
|
|
10732
|
-
function resolvedExpressionsOf(secrets) {
|
|
10733
|
-
return [...resolvedPairsOf.get(secrets)?.keys() ?? []];
|
|
10734
|
-
}
|
|
10735
|
-
const CONFLICTING_LEAF_RESOLUTION = Symbol("conflicting leaf resolution");
|
|
10736
|
-
const intrinsicLeafResolutionsOf = /* @__PURE__ */ new WeakMap();
|
|
10737
|
-
function recordIntrinsicLeafResolution(secrets, source, resolution) {
|
|
10738
|
-
let leaves = intrinsicLeafResolutionsOf.get(secrets);
|
|
10739
|
-
if (leaves === void 0) {
|
|
10740
|
-
leaves = /* @__PURE__ */ new WeakMap();
|
|
10741
|
-
intrinsicLeafResolutionsOf.set(secrets, leaves);
|
|
10742
|
-
}
|
|
10743
|
-
const copy = {
|
|
10744
|
-
input: resolution.input,
|
|
10745
|
-
output: resolution.output,
|
|
10746
|
-
substitutions: resolution.substitutions.map(({ token, value, secret }) => ({
|
|
10747
|
-
token,
|
|
10748
|
-
value,
|
|
10749
|
-
secret
|
|
10750
|
-
})),
|
|
10751
|
-
complete: resolution.complete,
|
|
10752
|
-
...resolution.parameterSpans === void 0 ? {} : { parameterSpans: resolution.parameterSpans.map(({ start, length, key }) => ({
|
|
10753
|
-
start,
|
|
10754
|
-
length,
|
|
10755
|
-
key
|
|
10756
|
-
})) }
|
|
10757
|
-
};
|
|
10758
|
-
const previous = leaves.get(source);
|
|
10759
|
-
if (previous === void 0) leaves.set(source, copy);
|
|
10760
|
-
else if (previous === CONFLICTING_LEAF_RESOLUTION || !sameLeafResolution(previous, copy)) leaves.set(source, CONFLICTING_LEAF_RESOLUTION);
|
|
10761
|
-
}
|
|
10762
|
-
function intrinsicLeafResolutionOf(secrets, source) {
|
|
10763
|
-
const resolution = intrinsicLeafResolutionsOf.get(secrets)?.get(source);
|
|
10764
|
-
return resolution === CONFLICTING_LEAF_RESOLUTION ? void 0 : resolution;
|
|
10765
|
-
}
|
|
10766
|
-
function recordIntrinsicLeafResolutionAs(secrets, source, branch) {
|
|
10767
|
-
let leaves = intrinsicLeafResolutionsOf.get(secrets);
|
|
10768
|
-
const resolution = typeof branch === "object" && branch !== null ? leaves?.get(branch) : void 0;
|
|
10769
|
-
if (resolution === void 0 || resolution === CONFLICTING_LEAF_RESOLUTION) {
|
|
10770
|
-
if (leaves === void 0) {
|
|
10771
|
-
leaves = /* @__PURE__ */ new WeakMap();
|
|
10772
|
-
intrinsicLeafResolutionsOf.set(secrets, leaves);
|
|
10773
|
-
}
|
|
10774
|
-
leaves.set(source, CONFLICTING_LEAF_RESOLUTION);
|
|
10775
|
-
return;
|
|
7135
|
+
async putLockObject(key, lockInfo, condition = { IfNoneMatch: "*" }) {
|
|
7136
|
+
const body = JSON.stringify(lockInfo, null, 2);
|
|
7137
|
+
return (await this.s3Client.send(new PutObjectCommand({
|
|
7138
|
+
Bucket: this.config.bucket,
|
|
7139
|
+
...await this.ownerParam(),
|
|
7140
|
+
Key: key,
|
|
7141
|
+
Body: body,
|
|
7142
|
+
ContentLength: Buffer.byteLength(body),
|
|
7143
|
+
ContentType: "application/json",
|
|
7144
|
+
...condition
|
|
7145
|
+
}))).ETag;
|
|
10776
7146
|
}
|
|
10777
|
-
|
|
10778
|
-
|
|
10779
|
-
|
|
10780
|
-
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) && sameParameterSpans(a.parameterSpans, b.parameterSpans);
|
|
10781
|
-
}
|
|
10782
|
-
function sameParameterSpans(a, b) {
|
|
10783
|
-
if (a === void 0 || b === void 0) return a === b;
|
|
10784
|
-
return a.length === b.length && a.every((s, i) => s.start === b[i].start && s.length === b[i].length && s.key === b[i].key);
|
|
10785
|
-
}
|
|
10786
|
-
function substitutedSpellingOf(secrets, source, resolvedValue) {
|
|
10787
|
-
const resolution = intrinsicLeafResolutionsOf.get(secrets)?.get(source);
|
|
10788
|
-
if (resolution === void 0 || resolution === CONFLICTING_LEAF_RESOLUTION) return void 0;
|
|
10789
|
-
if (!resolution.complete || resolution.output !== resolvedValue) return void 0;
|
|
10790
|
-
if (resolution.substitutions.length !== 1) return void 0;
|
|
10791
|
-
const [substitution] = resolution.substitutions;
|
|
10792
|
-
if (!substitution.secret) return void 0;
|
|
10793
|
-
const frame = singleSpanFrame(resolvedValue, resolution.input);
|
|
10794
|
-
if (frame === void 0) return void 0;
|
|
10795
|
-
if (frame.token !== substitution.token || frame.middle !== substitution.value) return void 0;
|
|
10796
|
-
for (const plaintext of secrets.keys()) {
|
|
10797
|
-
if (plaintext === "") continue;
|
|
10798
|
-
const outsideToken = frame.prefix.includes(plaintext) || frame.suffix.includes(plaintext);
|
|
10799
|
-
if (plaintext === substitution.value ? outsideToken : resolution.input.includes(plaintext)) return;
|
|
10800
|
-
}
|
|
10801
|
-
return resolution.input;
|
|
10802
|
-
}
|
|
10803
|
-
const sameGenerationBags = /* @__PURE__ */ new WeakSet();
|
|
10804
|
-
function markSameGenerationBag(bag) {
|
|
10805
|
-
sameGenerationBags.add(bag);
|
|
10806
|
-
return bag;
|
|
10807
|
-
}
|
|
10808
|
-
function isSameGenerationBag(bag) {
|
|
10809
|
-
return sameGenerationBags.has(bag);
|
|
10810
|
-
}
|
|
10811
|
-
const leafCertifiedBags = /* @__PURE__ */ new WeakSet();
|
|
10812
|
-
function markLeafCertifiedBag(bag) {
|
|
10813
|
-
leafCertifiedBags.add(bag);
|
|
10814
|
-
return bag;
|
|
10815
|
-
}
|
|
10816
|
-
function isLeafCertifiedBag(bag) {
|
|
10817
|
-
return leafCertifiedBags.has(bag);
|
|
10818
|
-
}
|
|
10819
|
-
function redactionClaimOf(bag) {
|
|
10820
|
-
return isSameGenerationBag(bag) || isLeafCertifiedBag(bag) ? "same-generation" : "unproven";
|
|
10821
|
-
}
|
|
10822
|
-
function carryRedactionMarks(from, to) {
|
|
10823
|
-
if (isSameGenerationBag(from)) markSameGenerationBag(to);
|
|
10824
|
-
if (isLeafCertifiedBag(from)) markLeafCertifiedBag(to);
|
|
10825
|
-
return to;
|
|
10826
|
-
}
|
|
10827
|
-
|
|
10828
|
-
//#endregion
|
|
10829
|
-
//#region src/deployment/secret-redaction/unresolved-token-frame.ts
|
|
10830
|
-
function liveMatchesUnresolvedTokenFrame(send, live, unresolvedTokens, secrets) {
|
|
10831
|
-
const wildcards = dynamicReferenceSpans(send).filter((span) => unresolvedTokens.has(send.slice(span.start, span.end)));
|
|
10832
|
-
if (wildcards.length === 0) return false;
|
|
10833
|
-
if (wildcardOverlapsResolvedPlaintext(send, wildcards, secrets)) return false;
|
|
10834
|
-
const literals = [];
|
|
10835
|
-
let at = 0;
|
|
10836
|
-
for (const span of wildcards) {
|
|
10837
|
-
literals.push(send.slice(at, span.start));
|
|
10838
|
-
at = span.end;
|
|
10839
|
-
}
|
|
10840
|
-
literals.push(send.slice(at));
|
|
10841
|
-
const first = literals[0];
|
|
10842
|
-
const last = literals[literals.length - 1];
|
|
10843
|
-
if (live.length < first.length + last.length) return false;
|
|
10844
|
-
if (!live.startsWith(first) || !live.endsWith(last)) return false;
|
|
10845
|
-
let pos = first.length;
|
|
10846
|
-
const end = live.length - last.length;
|
|
10847
|
-
for (let i = 1; i < literals.length - 1; i++) {
|
|
10848
|
-
const literal = literals[i];
|
|
10849
|
-
const found = live.indexOf(literal, pos);
|
|
10850
|
-
if (found < 0 || found + literal.length > end) return false;
|
|
10851
|
-
pos = found + literal.length;
|
|
7147
|
+
async getLockInfo(stackName, region) {
|
|
7148
|
+
const record = await this.getLockRecord(stackName, region);
|
|
7149
|
+
return record ? record.info : null;
|
|
10852
7150
|
}
|
|
10853
|
-
|
|
10854
|
-
|
|
10855
|
-
|
|
10856
|
-
|
|
10857
|
-
|
|
10858
|
-
|
|
10859
|
-
const
|
|
10860
|
-
|
|
7151
|
+
async getLockRecord(stackName, region) {
|
|
7152
|
+
await this.ensureClientForBucket();
|
|
7153
|
+
const key = this.getLockKey(stackName, region);
|
|
7154
|
+
const shownStack = safeSegment(stackName);
|
|
7155
|
+
try {
|
|
7156
|
+
this.logger.debug(`Getting lock info for stack: ${shownStack}`);
|
|
7157
|
+
const response = await this.s3Client.send(new GetObjectCommand({
|
|
7158
|
+
Bucket: this.config.bucket,
|
|
7159
|
+
...await this.ownerParam(),
|
|
7160
|
+
Key: key
|
|
7161
|
+
}));
|
|
7162
|
+
if (!response.Body) throw new LockError(`Lock file for stack ${shownStack} has no body`);
|
|
7163
|
+
const bodyString = await response.Body.transformToString();
|
|
7164
|
+
const raw = JSON.parse(bodyString);
|
|
7165
|
+
if (raw === null || typeof raw !== "object" || Array.isArray(raw)) {
|
|
7166
|
+
this.logger.debug(`Lock file for stack ${shownStack} is not an object; treating as absent`);
|
|
7167
|
+
return null;
|
|
7168
|
+
}
|
|
7169
|
+
const parsed = raw;
|
|
7170
|
+
const lockInfo = {
|
|
7171
|
+
...parsed,
|
|
7172
|
+
owner: displaySafe(parsed.owner),
|
|
7173
|
+
...parsed.operation !== void 0 && { operation: displaySafe(parsed.operation) },
|
|
7174
|
+
expiresAt: nanIfUncoercible(parsed.expiresAt)
|
|
7175
|
+
};
|
|
7176
|
+
this.logger.debug(`Lock info for stack: ${shownStack}:`, lockInfo);
|
|
7177
|
+
return {
|
|
7178
|
+
info: lockInfo,
|
|
7179
|
+
etag: response.ETag,
|
|
7180
|
+
...response.LastModified instanceof Date && { lastModified: response.LastModified.getTime() }
|
|
7181
|
+
};
|
|
7182
|
+
} catch (error) {
|
|
7183
|
+
if (error instanceof NoSuchKey) {
|
|
7184
|
+
this.logger.debug(`No lock exists for stack: ${shownStack}`);
|
|
7185
|
+
return null;
|
|
7186
|
+
}
|
|
7187
|
+
if (error instanceof LockError) throw error;
|
|
7188
|
+
throw new LockError(`Failed to get lock info for stack ${shownStack}: ${errorDetail$1(error)}`, error instanceof Error ? error : void 0);
|
|
10861
7189
|
}
|
|
10862
7190
|
}
|
|
10863
|
-
|
|
10864
|
-
|
|
10865
|
-
|
|
10866
|
-
//#endregion
|
|
10867
|
-
//#region src/deployment/secret-redaction/noecho-leaves.ts
|
|
10868
|
-
const SUB_VARIABLE$2 = /\$\{([^}!][^}]*)\}/g;
|
|
10869
|
-
function intrinsicKeyOf(node) {
|
|
10870
|
-
const keys = Object.keys(node);
|
|
10871
|
-
if (keys.length !== 1) return void 0;
|
|
10872
|
-
const key = keys[0];
|
|
10873
|
-
return key === "Ref" || key.startsWith("Fn::") ? key : void 0;
|
|
10874
|
-
}
|
|
10875
|
-
function conditionVerdict(sources, name) {
|
|
10876
|
-
if (typeof name !== "string" || sources.conditions === void 0) return void 0;
|
|
10877
|
-
return Object.hasOwn(sources.conditions, name) ? sources.conditions[name] : void 0;
|
|
10878
|
-
}
|
|
10879
|
-
function getAttReadsNoEcho(argument, sources) {
|
|
10880
|
-
if (sources.attributeIsNoEcho === void 0) return false;
|
|
10881
|
-
let target;
|
|
10882
|
-
let attribute;
|
|
10883
|
-
if (typeof argument === "string") {
|
|
10884
|
-
const dot = argument.indexOf(".");
|
|
10885
|
-
if (dot <= 0) return false;
|
|
10886
|
-
target = argument.slice(0, dot);
|
|
10887
|
-
attribute = argument.slice(dot + 1);
|
|
10888
|
-
} else if (Array.isArray(argument) && argument.length === 2) [target, attribute] = argument;
|
|
10889
|
-
else return false;
|
|
10890
|
-
if (typeof target !== "string") return false;
|
|
10891
|
-
if (typeof attribute !== "string") return readsNoEchoSource(attribute, sources);
|
|
10892
|
-
return sources.attributeIsNoEcho(target, attribute);
|
|
10893
|
-
}
|
|
10894
|
-
function subStringReadsNoEcho(text, variables, sources) {
|
|
10895
|
-
for (const match of text.matchAll(SUB_VARIABLE$2)) {
|
|
10896
|
-
const name = match[1].trim();
|
|
10897
|
-
if (variables !== void 0 && Object.hasOwn(variables, name)) continue;
|
|
10898
|
-
if (sources.parameters.has(name)) return true;
|
|
10899
|
-
const dot = name.indexOf(".");
|
|
10900
|
-
if (dot > 0 && sources.attributeIsNoEcho?.(name.slice(0, dot), name.slice(dot + 1)) === true) return true;
|
|
7191
|
+
async isLocked(stackName, region) {
|
|
7192
|
+
return await this.getLockInfo(stackName, region) !== null;
|
|
10901
7193
|
}
|
|
10902
|
-
|
|
10903
|
-
|
|
10904
|
-
|
|
10905
|
-
|
|
10906
|
-
|
|
10907
|
-
|
|
10908
|
-
if (seen.has(value)) return false;
|
|
10909
|
-
seen.add(value);
|
|
10910
|
-
if (Array.isArray(value)) return value.some(walk);
|
|
10911
|
-
const record = value;
|
|
10912
|
-
const intrinsic = intrinsicKeyOf(record);
|
|
10913
|
-
if (intrinsic === "Ref") return typeof record["Ref"] === "string" && sources.parameters.has(record["Ref"]);
|
|
10914
|
-
if (intrinsic === "Fn::GetAtt") return getAttReadsNoEcho(record["Fn::GetAtt"], sources);
|
|
10915
|
-
if (intrinsic === "Fn::Sub") {
|
|
10916
|
-
const argument = record["Fn::Sub"];
|
|
10917
|
-
if (typeof argument === "string") return subStringReadsNoEcho(argument, void 0, sources);
|
|
10918
|
-
if (Array.isArray(argument)) {
|
|
10919
|
-
const [text, variables] = argument;
|
|
10920
|
-
const vars = isPlainObject$7(variables) ? variables : void 0;
|
|
10921
|
-
if (typeof text === "string" && subStringReadsNoEcho(text, vars, sources)) return true;
|
|
10922
|
-
return vars !== void 0 && Object.values(vars).some(walk);
|
|
10923
|
-
}
|
|
10924
|
-
return walk(argument);
|
|
7194
|
+
async releaseLock(stackName, region) {
|
|
7195
|
+
const key = this.getLockKey(stackName, region);
|
|
7196
|
+
const held = this.heldLocks.get(key);
|
|
7197
|
+
if (held?.releasing) {
|
|
7198
|
+
this.logger.debug(`Release already in flight (or done) for stack ${stackRef(stackName, region)}`);
|
|
7199
|
+
return held.releasing;
|
|
10925
7200
|
}
|
|
10926
|
-
if (
|
|
10927
|
-
|
|
10928
|
-
|
|
10929
|
-
|
|
10930
|
-
|
|
10931
|
-
|
|
10932
|
-
|
|
10933
|
-
|
|
7201
|
+
if (!held) return this.doReleaseLock(stackName, region, void 0);
|
|
7202
|
+
this.stopRenewal(held);
|
|
7203
|
+
const releasing = this.doReleaseLock(stackName, region, held);
|
|
7204
|
+
held.releasing = releasing;
|
|
7205
|
+
return releasing;
|
|
7206
|
+
}
|
|
7207
|
+
async doReleaseLock(stackName, region, held) {
|
|
7208
|
+
await this.ensureClientForBucket();
|
|
7209
|
+
if (held) await held.renewing?.catch(() => void 0);
|
|
7210
|
+
if (held?.lost) {
|
|
7211
|
+
this.logger.warn(`Not releasing the lock for stack ${stackRef(stackName, region)}: this process lost it while the operation was still running, so the lock present now belongs to someone else.`);
|
|
7212
|
+
return;
|
|
7213
|
+
}
|
|
7214
|
+
if (held && held.etag === void 0 && !await this.stillOursByBody(held)) {
|
|
7215
|
+
this.logger.warn(`Not releasing the lock for stack ${stackRef(stackName, region)}: this process never learned which version of the lock it wrote, and could not confirm the one present is its own. It expires on its own, or clear it with cdkd force-unlock.`);
|
|
7216
|
+
return;
|
|
10934
7217
|
}
|
|
10935
|
-
return Object.values(record).some(walk);
|
|
10936
|
-
};
|
|
10937
|
-
return walk(node);
|
|
10938
|
-
}
|
|
10939
|
-
function literalIndex(index) {
|
|
10940
|
-
if (typeof index === "number" && Number.isInteger(index)) return index;
|
|
10941
|
-
if (typeof index === "string" && /^\d+$/.test(index)) return Number(index);
|
|
10942
|
-
}
|
|
10943
|
-
function noEchoCoordinatesOf(template, resolved, sources, onCoordinate) {
|
|
10944
|
-
const coordinates = [];
|
|
10945
|
-
const push = (path, node) => {
|
|
10946
|
-
coordinates.push(path);
|
|
10947
|
-
onCoordinate?.(path, node);
|
|
10948
|
-
};
|
|
10949
|
-
const ancestors = /* @__PURE__ */ new Set();
|
|
10950
|
-
const parametersOnly = {
|
|
10951
|
-
parameters: sources.parameters,
|
|
10952
|
-
...sources.conditions !== void 0 && { conditions: sources.conditions }
|
|
10953
|
-
};
|
|
10954
|
-
const isBareDeclaredGetAtt = (node) => isPlainObject$7(node) && intrinsicKeyOf(node) === "Fn::GetAtt" && getAttReadsNoEcho(node["Fn::GetAtt"], sources);
|
|
10955
|
-
const walk = (source, value, path) => {
|
|
10956
|
-
if (value === void 0) return;
|
|
10957
|
-
if (source === null || typeof source !== "object") return;
|
|
10958
|
-
if (ancestors.has(source)) return;
|
|
10959
|
-
ancestors.add(source);
|
|
10960
7218
|
try {
|
|
10961
|
-
|
|
10962
|
-
|
|
10963
|
-
|
|
10964
|
-
|
|
7219
|
+
this.logger.debug(`Releasing lock for stack: ${stackRef(stackName, region)}`);
|
|
7220
|
+
await this.deleteLock(stackName, region, held?.etag);
|
|
7221
|
+
this.logger.debug(`Lock released for stack: ${stackRef(stackName, region)}`);
|
|
7222
|
+
} catch (error) {
|
|
7223
|
+
if (this.isForeignLockError(error)) {
|
|
7224
|
+
this.logger.warn(held?.etagUncertain ? `Not releasing the lock for stack ${stackRef(stackName, region)}: this process could not confirm which version of the lock it last wrote, so it will not delete one it may not own. The lock clears on its own at ${new Date(held.info.expiresAt).toISOString()}, or immediately with cdkd force-unlock.` : `Not releasing the lock for stack ${stackRef(stackName, region)}: it has been replaced since this process acquired it, so another cdkd process now holds it. Leaving it in place.`);
|
|
10965
7225
|
return;
|
|
10966
7226
|
}
|
|
10967
|
-
|
|
10968
|
-
|
|
10969
|
-
if (intrinsic === void 0) {
|
|
10970
|
-
if (!isPlainObject$7(value)) {
|
|
10971
|
-
if (readsNoEchoSource(record, parametersOnly)) push(path, source);
|
|
10972
|
-
return;
|
|
10973
|
-
}
|
|
10974
|
-
for (const [key, child] of Object.entries(record)) if (Object.hasOwn(value, key)) walk(child, value[key], [...path, key]);
|
|
7227
|
+
if (this.isGoneError(error)) {
|
|
7228
|
+
this.logger.debug(`Lock for stack ${stackRef(stackName, region)} was already gone`);
|
|
10975
7229
|
return;
|
|
10976
7230
|
}
|
|
10977
|
-
if (
|
|
10978
|
-
|
|
10979
|
-
|
|
10980
|
-
|
|
10981
|
-
if (verdict !== void 0) {
|
|
10982
|
-
walk(verdict ? argument[1] : argument[2], value, path);
|
|
10983
|
-
return;
|
|
10984
|
-
}
|
|
10985
|
-
if (isBareDeclaredGetAtt(argument[1]) || isBareDeclaredGetAtt(argument[2])) {
|
|
10986
|
-
push(path, source);
|
|
10987
|
-
return;
|
|
10988
|
-
}
|
|
7231
|
+
if (held?.etag !== void 0 && this.isConditionUnsupportedError(error)) {
|
|
7232
|
+
if (!await this.stillOursByBody(held)) {
|
|
7233
|
+
this.logger.warn(`Not releasing the lock for stack ${stackRef(stackName, region)}: the conditional delete could not be evaluated here, and this process could not confirm the lock is still its own. Leaving it in place rather than risk deleting another process's lock. It expires on its own, or clear it with cdkd force-unlock. If this repeats, grant s3:GetObject on the lock key -- a delete conditioned on an ETag requires it.`);
|
|
7234
|
+
return;
|
|
10989
7235
|
}
|
|
10990
|
-
|
|
10991
|
-
|
|
10992
|
-
|
|
10993
|
-
|
|
10994
|
-
|
|
10995
|
-
|
|
10996
|
-
|
|
10997
|
-
walk(list[index], value, path);
|
|
10998
|
-
return;
|
|
10999
|
-
}
|
|
7236
|
+
this.logger.debug(`Conditional lock release for stack ${stackRef(stackName, region)} is not supported here (${errorDetail$1(error)}); retrying unconditionally`);
|
|
7237
|
+
try {
|
|
7238
|
+
await this.deleteLock(stackName, region);
|
|
7239
|
+
this.logger.debug(`Lock released for stack: ${stackRef(stackName, region)}`);
|
|
7240
|
+
return;
|
|
7241
|
+
} catch (fallbackError) {
|
|
7242
|
+
throw new LockError(`Failed to release lock for stack ${stackRef(stackName, region)}: ${errorDetail$1(fallbackError)}`, fallbackError instanceof Error ? fallbackError : void 0);
|
|
11000
7243
|
}
|
|
11001
7244
|
}
|
|
11002
|
-
|
|
11003
|
-
if (getAttReadsNoEcho(record["Fn::GetAtt"], sources)) push(path, source);
|
|
11004
|
-
return;
|
|
11005
|
-
}
|
|
11006
|
-
if (readsNoEchoSource(record, parametersOnly)) push(path, source);
|
|
7245
|
+
throw new LockError(`Failed to release lock for stack ${stackRef(stackName, region)}: ${errorDetail$1(error)}`, error instanceof Error ? error : void 0);
|
|
11007
7246
|
} finally {
|
|
11008
|
-
|
|
11009
|
-
|
|
11010
|
-
|
|
11011
|
-
|
|
11012
|
-
|
|
11013
|
-
}
|
|
11014
|
-
function noEchoParameterNodesAt(templateProperties, shape, noEchoParameters, conditions) {
|
|
11015
|
-
const nodes = /* @__PURE__ */ new Map();
|
|
11016
|
-
noEchoCoordinatesOf(templateProperties ?? {}, shape, {
|
|
11017
|
-
parameters: noEchoParameters,
|
|
11018
|
-
...conditions !== void 0 && { conditions }
|
|
11019
|
-
}, (coordinate, node) => nodes.set(canonicalJson$3(coordinate), {
|
|
11020
|
-
coordinate,
|
|
11021
|
-
node
|
|
11022
|
-
}));
|
|
11023
|
-
return nodes;
|
|
11024
|
-
}
|
|
11025
|
-
function recordedNoEchoValuesOf(templateProperties, record, noEchoParameterNames, conditions) {
|
|
11026
|
-
const bag = /* @__PURE__ */ new Map();
|
|
11027
|
-
const properties = record?.properties;
|
|
11028
|
-
if (properties === null || typeof properties !== "object") return bag;
|
|
11029
|
-
const coordinates = /* @__PURE__ */ new Map();
|
|
11030
|
-
if (noEchoParameterNames.size > 0 && templateProperties !== void 0) for (const [key, { coordinate }] of noEchoParameterNodesAt(templateProperties, properties, noEchoParameterNames, conditions)) coordinates.set(key, coordinate);
|
|
11031
|
-
for (const coordinate of noEchoLeavesOf(record ?? {}) ?? []) coordinates.set(canonicalJson$3(coordinate), coordinate);
|
|
11032
|
-
const recordLeaf = (leaf) => {
|
|
11033
|
-
if (typeof leaf === "string") {
|
|
11034
|
-
if (leaf === "***" || leaf.includes("{{resolve:")) return;
|
|
11035
|
-
recordLogOnlyValue(bag, leaf);
|
|
11036
|
-
} else if (typeof leaf === "number") recordLogOnlyValue(bag, String(leaf));
|
|
11037
|
-
};
|
|
11038
|
-
const seen = /* @__PURE__ */ new Set();
|
|
11039
|
-
const walk = (value) => {
|
|
11040
|
-
if (value === null || typeof value !== "object") {
|
|
11041
|
-
recordLeaf(value);
|
|
11042
|
-
return;
|
|
7247
|
+
const purge = this.purgeLockVersions(this.getLockKey(stackName, region), "release");
|
|
7248
|
+
if (this.deferReleasePurge) {
|
|
7249
|
+
this.deferredPurges.add(purge);
|
|
7250
|
+
purge.finally(() => this.deferredPurges.delete(purge));
|
|
7251
|
+
} else await purge;
|
|
11043
7252
|
}
|
|
11044
|
-
if (seen.has(value)) return;
|
|
11045
|
-
seen.add(value);
|
|
11046
|
-
for (const child of Object.values(value)) walk(child);
|
|
11047
|
-
};
|
|
11048
|
-
for (const coordinate of coordinates.values()) walk(valueAtCoordinate(properties, coordinate));
|
|
11049
|
-
return bag;
|
|
11050
|
-
}
|
|
11051
|
-
function maskWholeValue(value) {
|
|
11052
|
-
if (value === null || value === void 0) return value;
|
|
11053
|
-
if (typeof value === "string" && isSingleDynamicReferenceToken(value)) return value;
|
|
11054
|
-
if (Array.isArray(value)) return value.map(maskWholeValue);
|
|
11055
|
-
if (isPlainObject$7(value)) {
|
|
11056
|
-
const out = {};
|
|
11057
|
-
for (const [key, child] of Object.entries(value)) Object.defineProperty(out, key, {
|
|
11058
|
-
value: maskWholeValue(child),
|
|
11059
|
-
enumerable: true,
|
|
11060
|
-
writable: true,
|
|
11061
|
-
configurable: true
|
|
11062
|
-
});
|
|
11063
|
-
return out;
|
|
11064
7253
|
}
|
|
11065
|
-
|
|
11066
|
-
|
|
11067
|
-
|
|
11068
|
-
|
|
11069
|
-
|
|
11070
|
-
|
|
11071
|
-
if (!Array.isArray(node) || segment >= node.length) return {
|
|
11072
|
-
found: false,
|
|
11073
|
-
value: void 0
|
|
11074
|
-
};
|
|
11075
|
-
node = node[segment];
|
|
11076
|
-
continue;
|
|
7254
|
+
async stillOursByBody(held) {
|
|
7255
|
+
let record;
|
|
7256
|
+
try {
|
|
7257
|
+
record = await this.getLockRecord(held.stackName, held.region);
|
|
7258
|
+
} catch {
|
|
7259
|
+
return false;
|
|
11077
7260
|
}
|
|
11078
|
-
if (!
|
|
11079
|
-
|
|
11080
|
-
value: void 0
|
|
11081
|
-
};
|
|
11082
|
-
node = node[segment];
|
|
7261
|
+
if (!record) return false;
|
|
7262
|
+
return this.sameLockIdentity(record.info, held.info);
|
|
11083
7263
|
}
|
|
11084
|
-
|
|
11085
|
-
|
|
11086
|
-
value: node
|
|
11087
|
-
};
|
|
11088
|
-
}
|
|
11089
|
-
function valueAtCoordinate(bag, coordinate) {
|
|
11090
|
-
return readAt(bag, coordinate).value;
|
|
11091
|
-
}
|
|
11092
|
-
function cloneContainer(node) {
|
|
11093
|
-
if (Array.isArray(node)) return [...node];
|
|
11094
|
-
if (isPlainObject$7(node)) return { ...node };
|
|
11095
|
-
return node;
|
|
11096
|
-
}
|
|
11097
|
-
function maskAtCoordinates(bag, coordinates) {
|
|
11098
|
-
if (coordinates.length === 0) return bag;
|
|
11099
|
-
let root = bag;
|
|
11100
|
-
for (const coordinate of coordinates) {
|
|
11101
|
-
if (!readAt(root, coordinate).found) continue;
|
|
11102
|
-
if (coordinate.length === 0) {
|
|
11103
|
-
root = maskWholeValue(root);
|
|
11104
|
-
continue;
|
|
11105
|
-
}
|
|
11106
|
-
root = cloneContainer(root);
|
|
11107
|
-
let node = root;
|
|
11108
|
-
for (let i = 0; i < coordinate.length - 1; i++) {
|
|
11109
|
-
const segment = coordinate[i];
|
|
11110
|
-
const next = cloneContainer(node[segment]);
|
|
11111
|
-
node[segment] = next;
|
|
11112
|
-
node = next;
|
|
11113
|
-
}
|
|
11114
|
-
const last = coordinate[coordinate.length - 1];
|
|
11115
|
-
node[last] = maskWholeValue(node[last]);
|
|
7264
|
+
sameLockIdentity(a, b) {
|
|
7265
|
+
return displaySafe(a.owner) === displaySafe(b.owner) && a.timestamp === b.timestamp;
|
|
11116
7266
|
}
|
|
11117
|
-
|
|
11118
|
-
|
|
11119
|
-
|
|
11120
|
-
|
|
11121
|
-
|
|
11122
|
-
|
|
11123
|
-
|
|
11124
|
-
|
|
11125
|
-
|
|
7267
|
+
abandonedRunEndedBy(stackName, region) {
|
|
7268
|
+
return this.abandonedLocks.get(this.getLockKey(stackName, region));
|
|
7269
|
+
}
|
|
7270
|
+
async forceReleaseLock(stackName, region, beforeDelete) {
|
|
7271
|
+
const where = stackRef(stackName, region);
|
|
7272
|
+
const record = await this.getLockRecord(stackName, region).catch(() => null);
|
|
7273
|
+
const lockInfo = record?.info ?? null;
|
|
7274
|
+
this.logger.warn(lockInfo ? `Force releasing lock for stack: ${where}, owner: ${formatLockOwner(lockInfo.owner)}${lockInfo.operation ? `, operation: ${formatLockOperation(lockInfo.operation)}` : ""}, expired: ${this.isLockExpired(lockInfo)}` : `Force releasing lock for stack: ${where} (no lock body read — absent or unparseable; deleting the object either way, since a lock cdkd cannot read is a lock nothing else can clear)`);
|
|
7275
|
+
const key = this.getLockKey(stackName, region);
|
|
7276
|
+
const held = this.heldLocks.get(key);
|
|
7277
|
+
if (held) {
|
|
7278
|
+
this.stopRenewal(held);
|
|
7279
|
+
held.releasing = Promise.resolve();
|
|
11126
7280
|
}
|
|
11127
|
-
|
|
11128
|
-
|
|
11129
|
-
|
|
11130
|
-
|
|
11131
|
-
|
|
11132
|
-
|
|
11133
|
-
else Object.defineProperty(node, segment, {
|
|
11134
|
-
value: next,
|
|
11135
|
-
enumerable: true,
|
|
11136
|
-
writable: true,
|
|
11137
|
-
configurable: true
|
|
11138
|
-
});
|
|
11139
|
-
node = next;
|
|
7281
|
+
const horizon = record ? abandonedRunHorizon(record) : void 0;
|
|
7282
|
+
if (horizon !== void 0 && beforeDelete !== void 0) await beforeDelete(horizon).catch(() => void 0);
|
|
7283
|
+
try {
|
|
7284
|
+
await this.deleteLock(stackName, region);
|
|
7285
|
+
} finally {
|
|
7286
|
+
await this.purgeLockVersions(key, "reap");
|
|
11140
7287
|
}
|
|
7288
|
+
return horizon;
|
|
11141
7289
|
}
|
|
11142
|
-
|
|
11143
|
-
|
|
11144
|
-
|
|
11145
|
-
|
|
11146
|
-
|
|
11147
|
-
|
|
11148
|
-
|
|
7290
|
+
async deleteLock(stackName, region, etag) {
|
|
7291
|
+
await this.ensureClientForBucket();
|
|
7292
|
+
const key = this.getLockKey(stackName, region);
|
|
7293
|
+
await this.s3Client.send(new DeleteObjectCommand({
|
|
7294
|
+
Bucket: this.config.bucket,
|
|
7295
|
+
...await this.ownerParam(),
|
|
7296
|
+
Key: key,
|
|
7297
|
+
...etag !== void 0 && { IfMatch: etag }
|
|
7298
|
+
}));
|
|
11149
7299
|
}
|
|
11150
|
-
|
|
11151
|
-
|
|
11152
|
-
|
|
11153
|
-
|
|
11154
|
-
|
|
11155
|
-
|
|
11156
|
-
|
|
11157
|
-
|
|
11158
|
-
|
|
11159
|
-
|
|
11160
|
-
|
|
11161
|
-
|
|
11162
|
-
|
|
11163
|
-
|
|
11164
|
-
|
|
11165
|
-
|
|
11166
|
-
live = live[index];
|
|
11167
|
-
desired = element;
|
|
11168
|
-
continue;
|
|
7300
|
+
async purgeLockVersions(key, path) {
|
|
7301
|
+
const report = (message) => {
|
|
7302
|
+
try {
|
|
7303
|
+
if (path === "reap") this.logger.warn(message);
|
|
7304
|
+
else this.logger.debug(message);
|
|
7305
|
+
} catch {}
|
|
7306
|
+
};
|
|
7307
|
+
try {
|
|
7308
|
+
await this.ensureClientForBucket();
|
|
7309
|
+
await purgeNoncurrentKeyVersions(this.s3Client, this.config.bucket, [key], {
|
|
7310
|
+
requestFields: await this.ownerParam(),
|
|
7311
|
+
logger: { warn: report },
|
|
7312
|
+
objectDescription: LOCK_OBJECT_DESCRIPTION
|
|
7313
|
+
});
|
|
7314
|
+
} catch (error) {
|
|
7315
|
+
report(`Could not purge noncurrent versions of the lock key ${displayIdent(key, { maxCodePoints: STACK_REF_MAX_CODE_POINTS })} in bucket '${this.config.bucket}': the purge could not be started. Their previous versions survive and remain readable via GetObject with a VersionId (${LOCK_OBJECT_DESCRIPTION}). Grant s3:ListBucketVersions and s3:DeleteObjectVersion on the state bucket, or purge the key by hand. Underlying error: ${errorDetail$1(error)}`);
|
|
11169
7316
|
}
|
|
11170
|
-
if (!isPlainObject$7(live)) return path.length === 0 ? void 0 : path;
|
|
11171
|
-
if (!Object.hasOwn(live, segment)) return void 0;
|
|
11172
|
-
path.push(segment);
|
|
11173
|
-
live = live[segment];
|
|
11174
|
-
desired = isPlainObject$7(desired) ? desired[segment] : void 0;
|
|
11175
|
-
}
|
|
11176
|
-
return path;
|
|
11177
|
-
}
|
|
11178
|
-
function canonicalCoordinates(coordinates) {
|
|
11179
|
-
const keyed = /* @__PURE__ */ new Map();
|
|
11180
|
-
for (const coordinate of coordinates) keyed.set(JSON.stringify(coordinate), [...coordinate]);
|
|
11181
|
-
const all = [...keyed.values()];
|
|
11182
|
-
const covered = (inner) => all.some((outer) => outer.length < inner.length && outer.every((segment, i) => segment === inner[i]));
|
|
11183
|
-
return all.filter((coordinate) => !covered(coordinate)).sort((a, b) => JSON.stringify(a).localeCompare(JSON.stringify(b)));
|
|
11184
|
-
}
|
|
11185
|
-
function noEchoLeavesOf(record) {
|
|
11186
|
-
const field = record.noEchoLeaves;
|
|
11187
|
-
if (!Array.isArray(field)) return void 0;
|
|
11188
|
-
const out = [];
|
|
11189
|
-
for (const entry of field) {
|
|
11190
|
-
if (!Array.isArray(entry)) return void 0;
|
|
11191
|
-
if (!entry.every((s) => typeof s === "string" || typeof s === "number" && Number.isInteger(s))) return void 0;
|
|
11192
|
-
out.push(entry);
|
|
11193
7317
|
}
|
|
11194
|
-
|
|
11195
|
-
|
|
11196
|
-
|
|
11197
|
-
|
|
11198
|
-
|
|
11199
|
-
|
|
11200
|
-
|
|
11201
|
-
|
|
11202
|
-
|
|
11203
|
-
|
|
11204
|
-
|
|
11205
|
-
|
|
11206
|
-
|
|
11207
|
-
|
|
11208
|
-
|
|
11209
|
-
|
|
11210
|
-
|
|
11211
|
-
|
|
11212
|
-
|
|
11213
|
-
|
|
11214
|
-
if (jsonEqual(s, t)) {
|
|
11215
|
-
confirmed.push(path);
|
|
11216
|
-
return v;
|
|
11217
|
-
}
|
|
11218
|
-
differing.push(path);
|
|
11219
|
-
return s;
|
|
11220
|
-
}
|
|
11221
|
-
if (Array.isArray(v) && Array.isArray(s)) {
|
|
11222
|
-
if (s.length !== v.length) return s;
|
|
11223
|
-
const tt = Array.isArray(t) ? t : [];
|
|
11224
|
-
let changed = false;
|
|
11225
|
-
const out = s.map((item, i) => {
|
|
11226
|
-
const next = walk(item, tt[i], v[i], [...path, i]);
|
|
11227
|
-
if (next !== item) changed = true;
|
|
11228
|
-
return next;
|
|
11229
|
-
});
|
|
11230
|
-
return changed ? out : s;
|
|
11231
|
-
}
|
|
11232
|
-
if (isPlainObject$7(v) && isPlainObject$7(s)) {
|
|
11233
|
-
const tt = isPlainObject$7(t) ? t : {};
|
|
11234
|
-
let out;
|
|
11235
|
-
for (const key of Object.keys(v)) {
|
|
11236
|
-
if (!Object.hasOwn(s, key)) continue;
|
|
11237
|
-
const next = walk(s[key], tt[key], v[key], [...path, key]);
|
|
11238
|
-
if (next !== s[key]) {
|
|
11239
|
-
out ??= { ...s };
|
|
11240
|
-
out[key] = next;
|
|
11241
|
-
}
|
|
11242
|
-
}
|
|
11243
|
-
return out ?? s;
|
|
7318
|
+
trackHeldLock(args) {
|
|
7319
|
+
const previous = this.heldLocks.get(args.key);
|
|
7320
|
+
if (previous) this.stopRenewal(previous);
|
|
7321
|
+
const held = {
|
|
7322
|
+
stackName: args.stackName,
|
|
7323
|
+
region: args.region,
|
|
7324
|
+
key: args.key,
|
|
7325
|
+
info: args.info,
|
|
7326
|
+
etag: args.etag,
|
|
7327
|
+
timer: void 0,
|
|
7328
|
+
renewing: void 0,
|
|
7329
|
+
lost: false,
|
|
7330
|
+
releasing: void 0,
|
|
7331
|
+
etagUncertain: false,
|
|
7332
|
+
warnedPastExpiry: false
|
|
7333
|
+
};
|
|
7334
|
+
this.heldLocks.set(args.key, held);
|
|
7335
|
+
if (this.renewalDisabled) {
|
|
7336
|
+
this.logger.debug(`Lock renewal is disabled; the lock for ${stackRef(args.stackName, args.region)} will lapse at its TTL`);
|
|
7337
|
+
return;
|
|
11244
7338
|
}
|
|
11245
|
-
|
|
11246
|
-
|
|
11247
|
-
|
|
11248
|
-
current: walk(stored, today, v11, []),
|
|
11249
|
-
confirmed,
|
|
11250
|
-
differing
|
|
11251
|
-
};
|
|
11252
|
-
}
|
|
11253
|
-
function containsMask(value) {
|
|
11254
|
-
if (value === "***") return true;
|
|
11255
|
-
if (Array.isArray(value)) return value.some(containsMask);
|
|
11256
|
-
if (isPlainObject$7(value)) return Object.values(value).some(containsMask);
|
|
11257
|
-
return false;
|
|
11258
|
-
}
|
|
11259
|
-
function jsonEqual(a, b) {
|
|
11260
|
-
return canonicalJson$3(a) === canonicalJson$3(b);
|
|
11261
|
-
}
|
|
11262
|
-
function canonicalJson$3(value) {
|
|
11263
|
-
return JSON.stringify(value, (_key, node) => {
|
|
11264
|
-
if (node === null || typeof node !== "object" || Array.isArray(node)) return node;
|
|
11265
|
-
const sorted = Object.create(null);
|
|
11266
|
-
for (const key of Object.keys(node).sort()) sorted[key] = node[key];
|
|
11267
|
-
return sorted;
|
|
11268
|
-
});
|
|
11269
|
-
}
|
|
11270
|
-
const PREVIOUS_NOECHO_VALUE = "(previous NoEcho value)";
|
|
11271
|
-
function noEchoParametersReadBy(node, sources) {
|
|
11272
|
-
return [...sources.parameters].filter((name) => readsNoEchoSource(node, {
|
|
11273
|
-
parameters: /* @__PURE__ */ new Set([name]),
|
|
11274
|
-
...sources.conditions !== void 0 && { conditions: sources.conditions }
|
|
11275
|
-
}));
|
|
11276
|
-
}
|
|
11277
|
-
function noEchoComparison(options) {
|
|
11278
|
-
const { sources, values, minNeedleLength, publicTokens } = options;
|
|
11279
|
-
return ({ templateProperties, desired, current }) => {
|
|
11280
|
-
const coordinates = noEchoCoordinatesOf(templateProperties, desired, sources);
|
|
11281
|
-
const needles = [];
|
|
11282
|
-
for (const name of noEchoParametersReadBy(templateProperties, sources)) {
|
|
11283
|
-
const value = values[name];
|
|
11284
|
-
const leaves = Array.isArray(value) ? value : [value];
|
|
11285
|
-
for (const leaf of leaves) if (typeof leaf === "string" && leaf.length >= minNeedleLength && !isSingleDynamicReferenceToken(leaf)) needles.push(leaf);
|
|
11286
|
-
}
|
|
11287
|
-
if (coordinates.length === 0 && needles.length === 0) return void 0;
|
|
11288
|
-
let masked = maskAtCoordinates(desired, coordinates);
|
|
11289
|
-
if (needles.length > 0) {
|
|
11290
|
-
const walk = (node) => {
|
|
11291
|
-
if (typeof node === "string") {
|
|
11292
|
-
if (node === "***") return node;
|
|
11293
|
-
const outside = node.replace(DYNAMIC_REFERENCE_TOKEN_SCAN, "");
|
|
11294
|
-
return needles.some((needle) => node === needle || publicTokens?.has(needle) !== true && outside.includes(needle)) ? "***" : node;
|
|
11295
|
-
}
|
|
11296
|
-
if (Array.isArray(node)) {
|
|
11297
|
-
const out = node.map(walk);
|
|
11298
|
-
return out.some((item, i) => item !== node[i]) ? out : node;
|
|
11299
|
-
}
|
|
11300
|
-
if (isPlainObject$7(node)) {
|
|
11301
|
-
let out;
|
|
11302
|
-
for (const [key, child] of Object.entries(node)) {
|
|
11303
|
-
const next = walk(child);
|
|
11304
|
-
if (next !== child) {
|
|
11305
|
-
out ??= { ...node };
|
|
11306
|
-
out[key] = next;
|
|
11307
|
-
}
|
|
11308
|
-
}
|
|
11309
|
-
return out ?? node;
|
|
11310
|
-
}
|
|
11311
|
-
return node;
|
|
11312
|
-
};
|
|
11313
|
-
masked = walk(masked);
|
|
7339
|
+
if (args.etag === void 0) {
|
|
7340
|
+
this.logger.debug(`No ETag returned when acquiring the lock for ${stackRef(args.stackName, args.region)}; renewal disabled for this lock`);
|
|
7341
|
+
return;
|
|
11314
7342
|
}
|
|
11315
|
-
|
|
11316
|
-
|
|
11317
|
-
|
|
11318
|
-
|
|
11319
|
-
|
|
11320
|
-
};
|
|
11321
|
-
|
|
11322
|
-
|
|
11323
|
-
|
|
11324
|
-
|
|
11325
|
-
|
|
11326
|
-
|
|
11327
|
-
|
|
11328
|
-
let node = root;
|
|
11329
|
-
for (let i = 0; i < coordinate.length - 1; i++) {
|
|
11330
|
-
const segment = coordinate[i];
|
|
11331
|
-
const next = cloneContainer(node[segment]);
|
|
11332
|
-
node[segment] = next;
|
|
11333
|
-
node = next;
|
|
7343
|
+
this.startRenewal(held);
|
|
7344
|
+
}
|
|
7345
|
+
startRenewal(held) {
|
|
7346
|
+
const timer = setInterval(() => {
|
|
7347
|
+
this.renewLock(held);
|
|
7348
|
+
}, this.renewalIntervalMs);
|
|
7349
|
+
timer.unref?.();
|
|
7350
|
+
held.timer = timer;
|
|
7351
|
+
}
|
|
7352
|
+
stopRenewal(held) {
|
|
7353
|
+
if (held.timer !== void 0) {
|
|
7354
|
+
clearInterval(held.timer);
|
|
7355
|
+
held.timer = void 0;
|
|
11334
7356
|
}
|
|
11335
|
-
node[coordinate[coordinate.length - 1]] = replacement;
|
|
11336
7357
|
}
|
|
11337
|
-
|
|
11338
|
-
|
|
11339
|
-
|
|
11340
|
-
|
|
11341
|
-
|
|
11342
|
-
|
|
11343
|
-
|
|
11344
|
-
|
|
11345
|
-
|
|
11346
|
-
|
|
11347
|
-
|
|
11348
|
-
|
|
7358
|
+
renewLock(held) {
|
|
7359
|
+
if (held.lost || held.renewing !== void 0 || held.etag === void 0) return Promise.resolve();
|
|
7360
|
+
const inFlight = this.doRenewLock(held).finally(() => {
|
|
7361
|
+
held.renewing = void 0;
|
|
7362
|
+
});
|
|
7363
|
+
held.renewing = inFlight;
|
|
7364
|
+
return inFlight;
|
|
7365
|
+
}
|
|
7366
|
+
async doRenewLock(held) {
|
|
7367
|
+
const currentEtag = held.etag;
|
|
7368
|
+
if (currentEtag === void 0) return;
|
|
7369
|
+
const renewed = {
|
|
7370
|
+
...held.info,
|
|
7371
|
+
expiresAt: Date.now() + this.ttlMs
|
|
11349
7372
|
};
|
|
11350
|
-
|
|
11351
|
-
|
|
11352
|
-
|
|
11353
|
-
|
|
11354
|
-
|
|
11355
|
-
|
|
11356
|
-
|
|
11357
|
-
|
|
11358
|
-
|
|
7373
|
+
try {
|
|
7374
|
+
const etag = await this.putLockObject(held.key, renewed, { IfMatch: currentEtag });
|
|
7375
|
+
if (etag === void 0) {
|
|
7376
|
+
if (await this.adoptOwnWrite(held, renewed)) return;
|
|
7377
|
+
held.info = renewed;
|
|
7378
|
+
held.etagUncertain = true;
|
|
7379
|
+
this.stopRenewal(held);
|
|
7380
|
+
this.logger.debug(`Lock renewal for ${stackRef(held.stackName, held.region)} returned no ETag and the object could not be re-read; stopping renewal and keeping the previous ETag`);
|
|
7381
|
+
return;
|
|
7382
|
+
}
|
|
7383
|
+
held.info = renewed;
|
|
7384
|
+
held.etag = etag;
|
|
7385
|
+
held.warnedPastExpiry = false;
|
|
7386
|
+
this.logger.debug(`Renewed lock for stack: ${stackRef(held.stackName, held.region)} until ${new Date(renewed.expiresAt).toISOString()}`);
|
|
7387
|
+
} catch (error) {
|
|
7388
|
+
if (this.isForeignLockError(error) && await this.adoptOwnWrite(held, renewed)) return;
|
|
7389
|
+
if (this.isNotOursError(error)) {
|
|
7390
|
+
held.lost = true;
|
|
7391
|
+
this.stopRenewal(held);
|
|
7392
|
+
this.logger.warn(`Lost the lock for stack ${stackRef(held.stackName, held.region)} while the operation was still running: the lock object has been replaced or removed. Another cdkd process may now be writing to this stack concurrently. This process will not delete the current lock when it finishes.`);
|
|
7393
|
+
return;
|
|
7394
|
+
}
|
|
7395
|
+
this.logger.debug(`Lock renewal for stack ${stackRef(held.stackName, held.region)} failed, will retry: ${errorDetail$1(error)}`);
|
|
7396
|
+
if (!held.warnedPastExpiry && Date.now() >= held.info.expiresAt) {
|
|
7397
|
+
held.warnedPastExpiry = true;
|
|
7398
|
+
this.logger.warn(`Lock renewal for stack ${stackRef(held.stackName, held.region)} has been failing long enough that the lock expired at ${new Date(held.info.expiresAt).toISOString()}. Another cdkd process can now take it while this operation is still running. Renewal keeps retrying.`);
|
|
7399
|
+
}
|
|
11359
7400
|
}
|
|
11360
|
-
|
|
11361
|
-
|
|
11362
|
-
|
|
11363
|
-
|
|
11364
|
-
|
|
11365
|
-
|
|
11366
|
-
|
|
11367
|
-
|
|
11368
|
-
|
|
11369
|
-
|
|
11370
|
-
|
|
11371
|
-
|
|
11372
|
-
|
|
11373
|
-
|
|
7401
|
+
}
|
|
7402
|
+
async adoptOwnWrite(held, renewed) {
|
|
7403
|
+
const record = await this.getLockRecord(held.stackName, held.region).catch(() => null);
|
|
7404
|
+
if (!record || record.etag === void 0 || record.info.expiresAt !== renewed.expiresAt || !this.sameLockIdentity(record.info, renewed)) return false;
|
|
7405
|
+
held.info = renewed;
|
|
7406
|
+
held.etag = record.etag;
|
|
7407
|
+
held.warnedPastExpiry = false;
|
|
7408
|
+
this.logger.debug(`Lock renewal for stack ${stackRef(held.stackName, held.region)} reported a conflict, but the object holds this process's own renewal -- adopting it and continuing`);
|
|
7409
|
+
return true;
|
|
7410
|
+
}
|
|
7411
|
+
isForeignLockError(error) {
|
|
7412
|
+
return error instanceof S3ServiceException && (error.name === "PreconditionFailed" || error.$metadata.httpStatusCode === 412);
|
|
7413
|
+
}
|
|
7414
|
+
isGoneError(error) {
|
|
7415
|
+
if (error instanceof NoSuchKey) return true;
|
|
7416
|
+
if (!(error instanceof S3ServiceException)) return false;
|
|
7417
|
+
if (error.name === "NoSuchBucket") return false;
|
|
7418
|
+
return error.name === "NoSuchKey" || error.$metadata.httpStatusCode === 404;
|
|
7419
|
+
}
|
|
7420
|
+
isConditionUnsupportedError(error) {
|
|
7421
|
+
if (!(error instanceof S3ServiceException)) return false;
|
|
7422
|
+
const status = error.$metadata.httpStatusCode;
|
|
7423
|
+
return status === 403 || status === 501 || error.name === "AccessDenied" || error.name === "Forbidden" || error.name === "NotImplemented";
|
|
7424
|
+
}
|
|
7425
|
+
isNotOursError(error) {
|
|
7426
|
+
return this.isForeignLockError(error) || this.isGoneError(error);
|
|
7427
|
+
}
|
|
7428
|
+
async acquireLockWithRetry(stackName, region, owner, operation, maxRetries = 3, retryDelay = 2e3) {
|
|
7429
|
+
let attempts = 0;
|
|
7430
|
+
let releasedReacquires = 0;
|
|
7431
|
+
let lockInfo = null;
|
|
7432
|
+
for (let attempt = 0; attempt <= maxRetries; attempt++) {
|
|
7433
|
+
attempts++;
|
|
7434
|
+
if (await this.acquireLock(stackName, region, owner, operation)) return;
|
|
7435
|
+
lockInfo = await this.getLockInfo(stackName, region);
|
|
7436
|
+
if (!lockInfo && releasedReacquires < 3) {
|
|
7437
|
+
releasedReacquires++;
|
|
7438
|
+
this.logger.debug(safeMsg`Lock for stack ${stackRef(stackName, region)} could not be acquired, yet no readable lock was found -- most likely released in between; re-attempting (${releasedReacquires}/${3})`);
|
|
7439
|
+
attempt--;
|
|
7440
|
+
continue;
|
|
7441
|
+
}
|
|
7442
|
+
if (attempt < maxRetries) {
|
|
7443
|
+
const holder = lockInfo ? `is locked by ${formatLockOwner(lockInfo.owner)}${lockInfo.operation ? ` (operation: ${formatLockOperation(lockInfo.operation)})` : ""}. Lock ${formatLockExpiry(lockInfo.expiresAt)}.` : `could not be locked, and no readable lock was found.`;
|
|
7444
|
+
this.logger.info(`Stack ${safeSegment(stackName)} (${safeSegment(region)}) ${holder} Retrying in ${this.formatDuration(retryDelay)}... (attempt ${attempt + 1}/${maxRetries})`);
|
|
7445
|
+
await new Promise((resolve) => setTimeout(resolve, retryDelay));
|
|
7446
|
+
}
|
|
11374
7447
|
}
|
|
11375
|
-
|
|
11376
|
-
|
|
11377
|
-
|
|
11378
|
-
|
|
11379
|
-
|
|
11380
|
-
|
|
11381
|
-
|
|
11382
|
-
|
|
11383
|
-
|
|
11384
|
-
|
|
11385
|
-
|
|
11386
|
-
|
|
11387
|
-
|
|
11388
|
-
|
|
7448
|
+
const expiry = lockInfo ? formatLockExpiry(lockInfo.expiresAt) : void 0;
|
|
7449
|
+
const forceUnlockCommand = buildForceUnlockCommand(stackName, region);
|
|
7450
|
+
const recovery = forceUnlockCommand ? `If you are certain no other process is active, run: ${forceUnlockCommand}` : `If you are certain no other process is active, ${UNREPRODUCIBLE_LOCK_CLAUSE.charAt(0).toLowerCase()}${UNREPRODUCIBLE_LOCK_CLAUSE.slice(1)}`;
|
|
7451
|
+
const safeStack = safeSegment(stackName);
|
|
7452
|
+
const safeRegion = safeSegment(region);
|
|
7453
|
+
throw new LockError(`Failed to acquire lock for stack ${safeStack} (${safeRegion}) after ${attempts} attempt${attempts === 1 ? "" : "s"}. ` + (lockInfo ? `Locked by: ${formatLockOwner(lockInfo.owner)}${lockInfo.operation ? `, operation: ${formatLockOperation(lockInfo.operation)}` : ""}, ${expiry}. ` + recovery : `No lock could be read after the last failed attempt, so it was most likely released just now: re-run the command. If this repeats, lock.json may hold a body that is not a readable lock. ${recovery}`));
|
|
7454
|
+
}
|
|
7455
|
+
};
|
|
7456
|
+
function nanIfUncoercible(value) {
|
|
7457
|
+
try {
|
|
7458
|
+
Number(value);
|
|
7459
|
+
return value;
|
|
7460
|
+
} catch {
|
|
7461
|
+
return NaN;
|
|
11389
7462
|
}
|
|
11390
|
-
if (names.size > 0) passedNoEchoParameters.set(bag, names);
|
|
11391
|
-
else passedNoEchoParameters.delete(bag);
|
|
11392
|
-
}
|
|
11393
|
-
function passedNoEchoParametersOf(bag) {
|
|
11394
|
-
return bag === void 0 ? void 0 : passedNoEchoParameters.get(bag);
|
|
11395
7463
|
}
|
|
11396
7464
|
|
|
11397
7465
|
//#endregion
|
|
@@ -21838,6 +17906,20 @@ function pinSecretVerdict(resolver, expression, secret, scope) {
|
|
|
21838
17906
|
if (resolver.producerRegionGuest) return;
|
|
21839
17907
|
pinScopedSecretVerdict(scope, expression, secret);
|
|
21840
17908
|
}
|
|
17909
|
+
async function sameRegionExportEntry(resolver, context, exportName, entry) {
|
|
17910
|
+
try {
|
|
17911
|
+
const local = await context.stateBackend.getState(entry.producerStack, resolver.resolverRegion);
|
|
17912
|
+
if (!local || !importableOutputKeys(local.state).includes(exportName)) return void 0;
|
|
17913
|
+
return {
|
|
17914
|
+
value: local.state.outputs[exportName],
|
|
17915
|
+
producerStack: entry.producerStack,
|
|
17916
|
+
producerRegion: resolver.resolverRegion
|
|
17917
|
+
};
|
|
17918
|
+
} catch (err) {
|
|
17919
|
+
resolver.logger.debug(safeMsg`Same-region read for an exports index entry failed: ${displayMasked(resolver, describeAwsFailure(err).detail, context)}`);
|
|
17920
|
+
return;
|
|
17921
|
+
}
|
|
17922
|
+
}
|
|
21841
17923
|
async function resolveImportValue(resolver, importValueArg, context) {
|
|
21842
17924
|
const sourceKey = crossStackSourceKey({ "Fn::ImportValue": importValueArg });
|
|
21843
17925
|
const exportName = await resolver.resolveValue(importValueArg, context);
|
|
@@ -21853,6 +17935,7 @@ async function resolveImportValue(resolver, importValueArg, context) {
|
|
|
21853
17935
|
resolver.logger.warn(`Exports index lookup failed for ${quotedRender(loggedExportName, "'", "an export whose name is not a plain identifier")}: ${displayMasked(resolver, describeAwsFailure(err).detail, context)}; falling back to state.json scan`);
|
|
21854
17936
|
entry = void 0;
|
|
21855
17937
|
}
|
|
17938
|
+
if (entry && !sameRegion(entry.producerRegion, resolver.resolverRegion) && entry.producerStack !== context.stackName) entry = await sameRegionExportEntry(resolver, context, exportName, entry) ?? entry;
|
|
21856
17939
|
if (entry && (!context.stackName || entry.producerStack !== context.stackName)) {
|
|
21857
17940
|
recordImport(resolver, context, exportName, entry.producerStack, entry.producerRegion);
|
|
21858
17941
|
resolver.logger.info(`Resolved Fn::ImportValue: ${loggedExportName} (from index: ${displayMasked(resolver, entry.producerStack, context)} / ${displayMasked(resolver, entry.producerRegion, context)}; ${carriesDynamicReference(entry.value) ? "redacted dynamic reference" : "literal value"})`);
|
|
@@ -21866,7 +17949,9 @@ async function resolveImportValue(resolver, importValueArg, context) {
|
|
|
21866
17949
|
const allStacks = await context.stateBackend.listStacks();
|
|
21867
17950
|
resolver.logger.debug(`Found ${allStacks.length} state record(s) to search for export: ${loggedExportName}`);
|
|
21868
17951
|
let found;
|
|
21869
|
-
|
|
17952
|
+
const inThisRegion = (r) => r.region === void 0 || sameRegion(r.region, resolver.resolverRegion);
|
|
17953
|
+
const scanOrder = [...allStacks.filter(inThisRegion), ...allStacks.filter((r) => !inThisRegion(r))];
|
|
17954
|
+
for (const ref of scanOrder) {
|
|
21870
17955
|
const { stackName: refStack, region: refRegion } = ref;
|
|
21871
17956
|
if (context.stackName && refStack === context.stackName) {
|
|
21872
17957
|
resolver.logger.debug(`Skipping current stack: ${displayMasked(resolver, refStack, context)}`);
|
|
@@ -27428,7 +23513,7 @@ var CloudControlProvider = class {
|
|
|
27428
23513
|
const indeterminateGuard = await this.confirmDeleteTargetIdentity(logicalId, resourceType, physicalId, context);
|
|
27429
23514
|
if (context?.removeProtection === true && resourceType === "AWS::AutoScaling::AutoScalingGroup") {
|
|
27430
23515
|
this.logger.debug(`Delegating protected AutoScalingGroup ${logicalId} delete to the SDK ASGProvider (Cloud Control cannot force-delete a protected ASG)`);
|
|
27431
|
-
const { ASGProvider } = await import("./asg-provider-
|
|
23516
|
+
const { ASGProvider } = await import("./asg-provider-DCrwgSCZ.js");
|
|
27432
23517
|
const delegateRegion = ambientRegion();
|
|
27433
23518
|
let asgProvider = this.asgDeleteDelegates.get(delegateRegion);
|
|
27434
23519
|
if (asgProvider === void 0) {
|
|
@@ -27460,7 +23545,7 @@ var CloudControlProvider = class {
|
|
|
27460
23545
|
client: ec2Client,
|
|
27461
23546
|
observedOn: await observeThenDisableInstanceApiTermination(ec2Client, physicalId, flip, this.logger)
|
|
27462
23547
|
};
|
|
27463
|
-
else await this.observeThenDisableCcProtection(logicalId, physicalId, resourceType, protectionEntry, flip);
|
|
23548
|
+
else await this.observeThenDisableCcProtection(logicalId, physicalId, resourceType, protectionEntry, flip, context?.maskSecrets);
|
|
27464
23549
|
try {
|
|
27465
23550
|
result = await this.deleteThroughCloudControl(logicalId, physicalId, resourceType, context, indeterminateGuard, flip, protectedEc2);
|
|
27466
23551
|
} catch (error) {
|
|
@@ -27534,7 +23619,7 @@ var CloudControlProvider = class {
|
|
|
27534
23619
|
const family = SDK_DELETE_FAMILIES.get(resourceType);
|
|
27535
23620
|
const cached = this.sdkDeleteDelegates.get(family);
|
|
27536
23621
|
if (cached !== void 0 && cached.region === ccRegion) return cached.provider;
|
|
27537
|
-
const provider = family === "rds" ? new (await (import("./rds-provider-
|
|
23622
|
+
const provider = family === "rds" ? new (await (import("./rds-provider-ByCpdpUq.js"))).RDSProvider({ region: ccRegion }) : new (await (import("./neptune-provider-DjVgEWGf.js"))).NeptuneProvider({ region: ccRegion });
|
|
27538
23623
|
this.sdkDeleteDelegates.set(family, {
|
|
27539
23624
|
region: ccRegion,
|
|
27540
23625
|
provider
|
|
@@ -27647,12 +23732,13 @@ var CloudControlProvider = class {
|
|
|
27647
23732
|
return isWaitAbandonedError(error) || error instanceof CloudControlOperationFailedError && error.ccOperation === "UPDATE" && isAmbiguousCcHandlerErrorCode(error.ccErrorCode);
|
|
27648
23733
|
}
|
|
27649
23734
|
}
|
|
27650
|
-
async observeThenDisableCcProtection(logicalId, physicalId, resourceType, entry, flip) {
|
|
23735
|
+
async observeThenDisableCcProtection(logicalId, physicalId, resourceType, entry, flip, mask) {
|
|
27651
23736
|
try {
|
|
27652
23737
|
await observeThenDisableProtection({
|
|
27653
23738
|
flip,
|
|
27654
23739
|
logger: this.logger,
|
|
27655
23740
|
physicalId,
|
|
23741
|
+
mask,
|
|
27656
23742
|
guardName: entry.property,
|
|
27657
23743
|
observe: async () => {
|
|
27658
23744
|
const model = await this.getResourceState(resourceType, physicalId);
|
|
@@ -36807,7 +32893,7 @@ function keepPersistedPlainLeaves(redacted, raw, persisted) {
|
|
|
36807
32893
|
return out ?? redacted;
|
|
36808
32894
|
}
|
|
36809
32895
|
function isPlainRecord$1(value) {
|
|
36810
|
-
return typeof value === "object" && value !== null && !Array.isArray(value) && hasPlainPrototype
|
|
32896
|
+
return typeof value === "object" && value !== null && !Array.isArray(value) && hasPlainPrototype(value);
|
|
36811
32897
|
}
|
|
36812
32898
|
|
|
36813
32899
|
//#endregion
|
|
@@ -43073,7 +39159,8 @@ async function withResourceDeadline(operation, opts) {
|
|
|
43073
39159
|
}
|
|
43074
39160
|
outer?.resume();
|
|
43075
39161
|
},
|
|
43076
|
-
expired: () => timedOut || (outer?.expired() ?? false)
|
|
39162
|
+
expired: () => timedOut || (outer?.expired() ?? false),
|
|
39163
|
+
remainingMs: () => Math.min(timedOut ? 0 : Math.max(0, opts.timeoutMs - elapsed()), outer?.remainingMs() ?? Number.POSITIVE_INFINITY)
|
|
43077
39164
|
};
|
|
43078
39165
|
Promise.resolve().then(() => deadlineScope.run(control, operation)).then((value) => {
|
|
43079
39166
|
if (settled) return;
|
|
@@ -43102,6 +39189,9 @@ async function whileEnclosingDeadlinesPaused(fn) {
|
|
|
43102
39189
|
function enclosingDeadlineExpired() {
|
|
43103
39190
|
return deadlineScope.getStore()?.expired() ?? false;
|
|
43104
39191
|
}
|
|
39192
|
+
function enclosingDeadlineRemainingMs() {
|
|
39193
|
+
return deadlineScope.getStore()?.remainingMs() ?? Number.POSITIVE_INFINITY;
|
|
39194
|
+
}
|
|
43105
39195
|
|
|
43106
39196
|
//#endregion
|
|
43107
39197
|
//#region src/deployment/deployment-approval.ts
|
|
@@ -50452,5 +46542,5 @@ function sameGenerationClaimsOf(record) {
|
|
|
50452
46542
|
}
|
|
50453
46543
|
|
|
50454
46544
|
//#endregion
|
|
50455
|
-
export { resolvePendingCloudControlRequests as $, refuseMalformedOutputsForDestroy as $a, validateAssetBucketName as $c, carriesDynamicReference as $i, hasPlainPrototype$1 as $l, noEchoParameterNamesOf as $n, templateResourceTypes as $o, customResourceResponseExpirationWarning as $r, recordPhysicalNameCopy as $s, nameGenerationHighWaterOf as $t, inheritedProvenanceForChildDiff as A, malformedLocalResourcesWarning as Aa, importableOutputKeys as Ac, keepHeldTokenProvenance as Ai, resolveSkipPrefix as Al, destroyStackRecordsView as An, hasNoCloudControlHandlers as Ao, markDeleteStarted as Ar, logOnlyValueCount as As, removeProtectionTypeList as At, conditionFingerprint as B, malformedResourcePropertiesWarning as Ba, WorkGraph as Bc, AWS_CREDENTIAL_ENV_KEYS as Bi, findLargeInlineResources as Bl, addSuperseded as Bn, toCfnInteger as Bo, CC_BROKEN_REASON as Br, scrubResourceRecord as Bs, resolveReplacementOldType as Bt, hasCdkAutoDeleteTag as C, isReadableOrphanRecord as Ca, splitImportedOps as Cc, s3BucketDomainName as Ci, synthesisStatusMessage as Cl, DEFAULT_RESOURCE_TIMEOUT_MS as Cn, unreadableResourceEntries as Co, reserveStackCreateToken as Cr, redactForState as Cs, formatResourceLine as Ct, IMPLICIT_DELETE_DEPENDENCIES as D, malformedExportSourceWarning as Da, hasReadableExportSet as Dc, resolveDynamicReferences as Di, resolveApp as Dl, findDestructiveChanges as Dn, unwrittenCreateOnlyReplacement as Do, DeploymentEventsStore as Dr, createUnionSecretMasker as Ds, withApiLimit as Dt, markRefusedBeforeApplying as E, malformedExportNamesWarning as Ea, exportNamesCarriedFrom as Ec, s3BucketWebsiteUrl as Ei, loadCdkJson as El, constructPathOf as En, findSilentDropProperties as Eo, DeploymentEventsReader as Er, carryLogOnlyValues as Es, lookupEachName as Et, findNestedTemplateTreeDefect as F, malformedOrphansWarning as Fa, shouldRetainResource as Fc, assertFlagRoleArn as Fi, warnDeprecatedNoPrefixCliFlag as Fl, cyan as Fn, isStatefulRecreateTargetSync as Fo, refuseMalformedDesiredTags as Fr, unionOfSecretBags as Fs, planFailedOps as Ft, diffSecurity as G, refuseDivergentRecordRegionForDestroy as Ga, AssetModeResolver as Gc, classifyReplaySecretRegion as Gi, PARTITION_TABLE as Gl, supersededAfterRollback as Gn, configIntegerRefusal as Go, waitForLambdaFunctionActive as Gr, isUncertifiedBaselineMaskPosition as Gs, inheritProducerRegions as Gt, parentSuppliedValues as H, malformedScrubResourceEntriesRefusalMessage as Ha, createAssetRedirectResolver as Hc, callerEnvCredentials as Hi, CUSTOM_RESOURCE_RESPONSE_OBJECT_DESCRIPTION as Hl, holdsSupersededResources as Hn, coerceCfnBoolean as Ho, ccBrokenReason as Hr, withoutPhysicalNameCopies as Hs, orphanNeedsIdentity as Ht, isAbsoluteAssetPath as I, malformedOutputsRefusalMessage as Ia, stackInstanceIdCarriedFrom as Ic, assertSendableRoleArn as Ii, ssmResolvedValueType as Il, gray as In, renderStatefulReason as Io, tagMapAsList as Ir, createSecretMasker as Is, planRollback as It, mergeNoChangeOutputs as J, refuseMalformedOrphanRecordsForDestroy as Ja, ensureAssetStorage as Jc, coerceParameterTypedValue as Ji, AssemblyReader as Jl, supersededResourcesOf as Jn, replayWarn as Jo, isCustomResourceType as Jr, inheritNestedStackParameterAssociations as Js, redactedDeleteAddressFields as Jt, isSecretBearingReferenceString as K, refuseMalformedNestedChildOutputs as Ka, BOOTSTRAP_MARKER_PREFIX as Kc, producerRegionsFromState as Ki, canonicalizeRegion as Kl, supersededHeldByOtherTypeWarning as Kn, configStringRefusal as Ko, TemplateNoEchoReresolver as Kr, pathCrossesDottedKey as Ks, REDACTED_DELETE_ADDRESS_SKIP_REASON as Kt, listNestedTemplateRows as L, malformedOutputsWarning as La, AssetPublisher as Lc, explicitRoleArnOrThrow as Li, CFN_TEMPLATE_BODY_LIMIT as Ll, green as Ln, WARM_THROUGHPUT_MEMBERS as Lo, tagPlanWarning as Lr, errorCauseChain as Ls, recheckFailedPlan as Lt, findServiceTokenRefusals as M, malformedOrphanRecordsWarning as Ma, isReadableBag as Mc, recordedOutputReferenceRegions as Mi, resolveStateBucketWithDefaultAndSource as Ml, withStackRecords as Mn, shownType as Mo, DBPROXY_TAG_OPTIONS as Mr, recordLogOnlyParameterValue as Ms, demoteSupersededOrphans as Mt, serviceTokenBlockingReason as N, malformedOrphanRowsKeptWarning as Na, orphansAfterRollback as Nc, recordedReferenceRegions as Ni, resolveUseCdkBootstrapAssets as Nl, replacedDeleteFailureVerdict as Nn, MULTI_REGION_RECREATE_BLOCKED_TYPES as No, planTagDiff as Nr, recordLogOnlyValue as Ns, isJournaledOrphan as Nt, computeImplicitDeleteEdges as O, malformedLocalOutputsWarning as Oa, hasReasonlessBaselineRefusal as Oc, producerLookupOver as Oi, resolveAutoAssetStorage as Ol, formatDestructiveChange as On, withoutSilentDropProperties as Oo, extractDeploymentEventError as Or, hasMaskableValues as Os, replayFailedOperations as Ot, childTemplateLoader as P, malformedOrphansRefusalMessage as Pa, orphansCarriedFrom as Pc, applyRoleArnIfSet as Pi, stateBucketExistenceConfirmed as Pl, bold as Pn, isStatefulRecreateTargetForReplace as Po, readTagList as Pr, shareLogOnlyValues as Ps, isReplacementOrphan as Pt, pendingRequestCount as Q, refuseMalformedOutputs as Qa, readBootstrapMarkerBody as Qc, isImpossibleEmptyStoredAttribute as Qi, hasOwnKey as Ql, noEchoExactEchoLeavesOf as Qn, prefetchCreateOnlyPropertyPaths as Qo, applyCustomResourceResponseExpiration as Qr, recordAttributeIdCopy as Qs, nameGenerationCarriedFrom as Qt, renderNestedTemplateTreeDefect as R, malformedRenderedContainersWarning as Ra, isSensitiveAttributeName as Rc, isIamRoleArn as Ri, CFN_TEMPLATE_URL_LIMIT as Rl, red as Rn, coerceWarmThroughput as Ro, definedAttributes as Rr, maskSecretsInError as Rs, recordUnderIdIsNotOwn as Rt, S3_AUTO_DELETE_OBJECTS_TAG as S, hasReadableResources as Sa, withStackInstanceIdWithheld as Sc, s3BucketArn as Si, Synthesizer as Sl, bindingSkippedOutputs as Sn, unreadableOrphanRecords as So, ledgerForStack as Sr, markSameGenerationBag as Ss, sameJournaledOrphans as St, getPriorAttempts as T, malformedDriftResourcePropertiesWarning as Ta, describeRegionValueKind as Tc, s3BucketRegionalDomainName as Ti, getLegacyStateBucketName as Tl, maskingRetryLogger as Tn, findActionableSilentDrops as To, acquireIdempotencyToken as Tr, snapshotPassProvenance as Ts, isAccessDeniedError as Tt, readRecordedConditionVerdicts as U, malformedStateRefusalMessage as Ua, loadPublishableAssetManifest as Uc, envCredentialsAreAssumedRole as Ui, decodeListingKey as Ul, isSupersededResourceRecord as Un, coerceCfnInteger as Uo, isCustomResource as Ur, DYNAMIC_REFERENCE_TOKEN_SCAN as Us, findNestedStackTypeChanges as Ut, conditionInputsFrom as V, malformedResourcesWarning as Va, buildAssetRedirectMap as Vc, applyCallerIdentityCredentials as Vi, uploadCfnTemplate as Vl, deleteSupersededEntry as Vn, toFiniteNumber as Vo, ProviderRegistry as Vr, withPhysicalNameCopies as Vs, seedsDeleteFirstGuard as Vt, withResourceDeadline as W, previewableOrphanRecords as Wa, rewriteTemplateAssetReferences as Wc, classifyRecordedSecretRegion as Wi, expectedOwnerParam as Wl, removeSuperseded as Wn, configBooleanRefusal as Wo, wouldReturnToSdkProvider as Wr, dynamicReferenceTokens as Ws, getCurrentProducerRegions as Wt, makeSiblingClaimReader as X, refuseMalformedOrphansForDestroy as Xa, isCrossRegionRedirect as Xc, parameterTypeMayLoseSecretIdentity as Xi, processStackMessages as Xl, noEchoAttributeNamesOf as Xn, requireConfigObject as Xo, withPrintingSecrets as Xr, recoverMaskedOutput as Xs, updatePartialMessage as Xt, makeCanonicalizePropertiesFn as Y, refuseMalformedOrphans as Ya, getBootstrapMarkerKey as Yc, isUnboundTemplateParameter as Yi, StageLoadError as Yl, withoutSuperseded as Yn, requireConfigArray as Yo, getCurrentResourceSecrets as Yr, recordNestedStackParameterExpressions as Ys, redactedDeleteAddressSkip as Yt, planOrphanAdoption as Z, refuseMalformedOrphansForOrphan as Za, parseBootstrapMarker as Zc, getAccountInfo as Zi, defineOwnKey as Zl, noEchoComparisonForTemplate as Zn, requireConfigString as Zo, CUSTOM_RESOURCE_RESPONSE_LIFECYCLE_RULE_ID as Zr, physicalNameCopiesOf as Zs, updatePartialReason as Zt, deleteTableWithIndexBusyRetry as _, accountArgs as _a, applyCrossPrefixScan as _c, DiffCalculator as _i, runDockerForeground as _l, isWholeDynamicReferenceValue as _n, repairMalformedOutputsForReadOnly as _o, effectiveDeletionPolicy as _r, readbackPathFor as _s, dropFailedHint as _t, isProtectionValueActive as a, isStalePlaceholderArnAttribute as aa, recordNoEchoAttributeValues as ac, deleteIndeterminateGuards as ai, describeDockerExecFailure as al, namesAnyDeclaredParameter as an, refuseMalformedResourceEntriesForImportSave as ao, orphanRecordsPrintingBag as ar, DagBuilder as as, dropSettledNestedJournals as at, renderAssemblyPathEscape as au, waitForIndexesSettled as b, hasReadableOrphans as ba, isNotImplemented as bc, poisonRenderedSpellingsCollidingIn as bi, AssetManifestLoader as bl, collectPublishedOutputNames as bn, repairMalformedResourcesForReadOnly as bo, unsupportedFinalSnapshotError as br, valueAtCoordinate as bs, loadJournaledOrphans as bt, DynamoDBGlobalTableProvider as c, withSharedDrainBudget as ca, wholeStringLeavesOf as cc, withIndeterminateGuard as ci, finchSecretArgvRefusal as cl, WITHHELD_NAME_DISPLAY as cn, refuseMalformedResourcePropertiesForDrift as co, secretNamedAttributeNamesOf as cr, isMarkedCoordinate as cs, recordDisplacedSkips as ct, injectedAwsRegionValue as cu, compensateRemovedDeletionProtection as d, declaresNoEcho as da, LockManager as dc, disableInstanceApiTermination as di, isDockerClientEnvKey as dl, secretBearing as dn, refuseMalformedResourcesForDeploy as do, storedSecretNameNeedles as dr, maskWholeValue as ds, withNestedRevertRun as dt, carriesFetchableDynamicReference as ea, splitGetAttStringForm as ec, CloudControlProvider as ei, validateContainerRepoName as el, nameScopeOf as en, refuseMalformedResourceAttributesForOrphan as eo, createReadOnlyAttributeHealerFactory as er, describeTypeWithThrottleRetry as es, keptForRetainedRecord as et, nullPrototypeRecord as eu, deleteBudgetKey as f, JSON_LISTING_HOLE_VALUE as fa, isLockInfoExpired as fc, ec2InstanceProtectionSite as fi, isMalformedEnvKey as fl, secretBearingStateKeyWarning as fn, refuseMalformedResourcesForDestroy as fo, ATOMIC_FINAL_SNAPSHOT_TYPES as fr, maskedLeafCoordinatesOf as fs, collectNestedChildUnaddressed as ft, INDEX_SETTLE_POLL_INTERVAL_MS as g, UNREADABLE_RESOURCES_MAP_ROW as ga, CrossPrefixScanCache as gc, reEnableInstanceApiTermination as gi, redactedDockerCause as gl, exportNameSecretExposure as gn, repairMalformedOrphansForReadOnly as go, createPreDeleteFinalSnapshot as gr, passedNoEchoParametersOf as gs, dropFailedCommands as gt, DELETE_INDEX_WAIT_PROCEED_NOTE as h, UNREADABLE_ORPHANS_CONTAINER_ROW as ha, CrossPrefixReadError as hc, reDisableInstanceApiTermination as hi, redactedCause as hl, exportNameNoEchoParameters as hn, repairMalformedOrphanRecordsForReadOnly as ho, ccRoutedFinalSnapshotError as hr, noEchoOutputsComparison as hs, deleteJournaledOrphans as ht, PROTECTION_PROPERTY_BY_TYPE as i, cfnRefValueFromPhysicalId as ia, recordMaskOnlyValuesIn as ic, UNSPECIFIED_SKIP_REASON as ii, describeDockerCapturedOutput as il, computeParameterTaint as in, refuseMalformedResourceEntriesForImport as io, namingSecretsWithRecordedNoEcho as ir, sameLambdaFunctionAddress as is, displacedPhysicalIdShown as it, displayAssemblyPath as iu, deferredServiceTokenWarning as j, malformedOrphanRecordsRefusalMessage as ja, importableOutputs as jc, outputReferenceProvenanceOf as ji, resolveStateBucketWithDefault as jl, getStackRecords as jn, findReplacedReadersOfRecreateTargets as jo, DBPROXY_TAGS_WHAT as jr, printingCorpusOf as js, recordAfterRollbackUpdate as jt, crossStackOutputProvenanceSource as k, malformedLocalResourceEntriesWarning as ka, hasUnverifiableParameterRefusal as kc, refuseUnreadableCdkCrossAccountRefs as ki, resolveCaptureObservedState as kl, awaitInFlightSibling as kn, NO_CC_HANDLERS_REASON as ko, isRefusedByName as kr, literalSplitDelimitersOf as ks, replayRollback as kt, DYNAMODB_DELETE_MIN_RESOURCE_TIMEOUT_MS as l, parameterInputsFor as la, WHOLE_DYNAMIC_REFERENCE_PATTERN as lc, isWaitAbandonedError as li, formatDockerLoginError as ll, displayTextOrWithheld as ln, refuseMalformedResourcePropertiesForExport as lo, secretNamedRecordNeedles as lr, maskAtCoordinates as ls, revertNestedChildFromJournal as lt, clearBucketRegionCache as lu, resolveDynamoDbDeleteBudgetMs as m, STATE_RESOURCES_MALFORMED as ma, rebuildClientForBucketRegion as mc, observeThenDisableInstanceApiTermination as mi, redactDockerArgvValues as ml, carriedExportAliasExposure as mn, refuseMalformedState as mo, buildFinalSnapshotIdentifier as mr, noEchoLeavesOf as ms, withNestedStackContext as mt, recordedProtectionEvidence as n, keepsSecretReferenceToken as na, provenPublicValue as nc, unchangedBehindSecretReference as ni, buildDockerImage as nl, retiredNameGenerationsAfter as nn, refuseMalformedResourceEntriesForDeploy as no, journaledOrphanPrintingBag as nr, canonicalLambdaFunctionName as ns, NESTED_PENDING_PARENT_REASON as nt, absoluteAssemblyPathEscape as nu, perType as o, refStateLookupFromResource as oa, recordNoEchoParameterFreshValue as oc, deleteLeftInPlace as oi, describeDockerFailure as ol, reachableDivergentParameters as on, refuseMalformedResourceEntriesForOrphan as oo, secretNamePrintingBag as or, TemplateParser as os, getNestedRevertRun as ot, resolveAssemblyPath as ou, resolveDynamoDbDeleteBudgetClock as p, STATE_REGION_DIVERGED as pa, S3StateBackend as pc, isTerminationProtectionPropagationError as pi, partitionSensitiveEnv as pl, secretSafeKeyDisplay as pn, refuseMalformedResourcesForExport as po, PRE_DELETE_SNAPSHOT_TYPES as pr, noEchoCoordinatesOf as ps, getCurrentNestedStackContext as pt, keptWholeReasonText as q, refuseMalformedOrphanRecords as qa, assertAssetBucketRegion as qc, regionLessSecretName as qi, derivePartitionAndUrlSuffix as ql, supersededHolderOf as qn, readConfigString as qo, readsNoEchoDeleteValues as qr, identityKeyFor as qs, isRedactedRecordedValue as qt, recordedProtectionNote as r, AWS_NO_VALUE as ra, recordMaskOnlyValue as rc, RollbackInlinePolicyWriters as ri, resolveDockerContextDirectory as rl, retiredNameGenerationsLeaving as rn, refuseMalformedResourceEntriesForDestroy as ro, maskEventTextWithBoundBags as rr, lambdaFunctionNameForMask as rs, displacedOpClause as rt, describeFileReadFailure as ru, readProtection as s, parseWebACLArn as sa, recordProvenPublicExpression as sc, deleteSkipReason as si, dockerSpawnEnvWithSensitive as sl, resourcesNamingDeclaredParameter as sn, refuseMalformedResourcePropertiesForDestroy as so, secretNamePrintingBags as sr, canonicalCoordinates as ss, nestedChildStackName as st, injectAwsRegion as su, DeployEngine as t, isNamelessDynamicReferenceError as ta, carriesSecretMask as tc, slowCcOperationTimeoutMs as ti, buildDenyExternalAccessPolicy as tl, retiredAfterRollback as tn, refuseMalformedResourceEntries as to, completedReplayEntries as tr, withRetry as ts, recordRetainedForReadoption as tt, ownValue as tu, beginDeleteWait as u, passedParameterClassesOf as ua, isSingleDynamicReferenceToken as uc, markWaitAbandoned as ui, getDockerCmd as ul, exportAliasCollisionScrubWarning as un, refuseMalformedResourcePropertiesForOrphan as uo, stateSecretNameNeedles as ur, maskReadbackAtCoordinates as us, revertedNestedRowIds as ut, resolveBucketRegion as uu, maskedLogger as v, deployRefusesOrphanRowsReason as va, crossPrefixDeniedWarning as vc, INTRINSIC_KEYS as vi, runDockerStreaming as vl, noEchoParameterValueSeed as vn, repairMalformedResourceEntriesForReadOnly as vo, isFinalSnapshotError as vr, readsNoEchoSource as vs, isHandledOrphan as vt, isTruthyCfnBoolean as w, isReadableResourceEntry as wa, acceptedCreateOnlyDropsOf as wc, s3BucketDualStackDomainName as wi, getDefaultStateBucketName as wl, DEFAULT_RESOURCE_WARN_AFTER_MS as wn, withheldAccountClause as wo, withCreateTokenLedger as wr, recordReferenceProvenanceEntry as ws, chunks as wt, ECR_AUTO_DELETE_IMAGES_TAG as x, hasReadableOutputs as xa, stackInstanceIdOf as xc, isSettledInstanceState as xi, getDockerImageBySourceHash as xl, isExportAliasCollision as xn, unpreviewableOrphanRecords as xo, earliestDefined as xr, liveMatchesUnresolvedTokenFrame as xs, makeForeignHolderScan as xt, relayedIndexBusyDelete as y, displayLogicalId as ya, isAccessDenied$1 as yc, IntrinsicFunctionResolver as yi, warnFinchArgvExposure as yl, collectDeclaredOutputNames as yn, repairMalformedResourcePropertiesForReadOnly as yo, refusesFinalSnapshot as yr, recordedNoEchoValuesOf as ys, journaledOrphanLines as yt, templateIdentity as z, malformedResourceEntriesWarning as za, stringifyValue as zc, sendableAssumeRoleCommand as zi, MIGRATE_TMP_PREFIX as zl, yellow as zn, isWarmThroughputDecrease as zo, stringifyIfAssigned as zr, maskSecretsInText as zs, replacementNeverSwapped as zt };
|
|
50456
|
-
//# sourceMappingURL=deploy-engine-
|
|
46545
|
+
export { pendingRequestCount as $, refuseMalformedOutputs as $a, absoluteAssemblyPathEscape as $c, isImpossibleEmptyStoredAttribute as $i, noEchoExactEchoLeavesOf as $n, prefetchCreateOnlyPropertyPaths as $o, applyCustomResourceResponseExpiration as $r, buildDockerImage as $s, nameGenerationCarriedFrom as $t, inheritedProvenanceForChildDiff as A, malformedLocalResourceEntriesWarning as Aa, resolveUseCdkBootstrapAssets as Ac, refuseUnreadableCdkCrossAccountRefs as Ai, awaitInFlightSibling as An, NO_CC_HANDLERS_REASON as Ao, isRefusedByName as Ar, orphansAfterRollback as As, replayRollback as At, conditionFingerprint as B, malformedResourceEntriesWarning as Ba, decodeListingKey as Bc, sendableAssumeRoleCommand as Bi, yellow as Bn, isWarmThroughputDecrease as Bo, stringifyIfAssigned as Br, loadPublishableAssetManifest as Bs, replacementNeverSwapped as Bt, hasCdkAutoDeleteTag as C, hasReadableResources as Ca, loadCdkJson as Cc, s3BucketArn as Ci, bindingSkippedOutputs as Cn, unreadableOrphanRecords as Co, ledgerForStack as Cr, exportNamesCarriedFrom as Cs, sameJournaledOrphans as Ct, IMPLICIT_DELETE_DEPENDENCIES as D, malformedExportNamesWarning as Da, resolveSkipPrefix as Dc, s3BucketWebsiteUrl as Di, constructPathOf as Dn, findSilentDropProperties as Do, DeploymentEventsReader as Dr, importableOutputKeys as Ds, lookupEachName as Dt, markRefusedBeforeApplying as E, malformedDriftResourcePropertiesWarning as Ea, resolveCaptureObservedState as Ec, s3BucketRegionalDomainName as Ei, maskingRetryLogger as En, findActionableSilentDrops as Eo, acquireIdempotencyToken as Er, hasUnverifiableParameterRefusal as Es, isAccessDeniedError as Et, findNestedTemplateTreeDefect as F, malformedOrphansRefusalMessage as Fa, CFN_TEMPLATE_URL_LIMIT as Fc, applyRoleArnIfSet as Fi, bold as Fn, isStatefulRecreateTargetForReplace as Fo, readTagList as Fr, isSensitiveAttributeName as Fs, isReplacementOrphan as Ft, withResourceDeadline as G, previewableOrphanRecords as Ga, AssemblyReader as Gc, classifyRecordedSecretRegion as Gi, removeSuperseded as Gn, configBooleanRefusal as Go, wouldReturnToSdkProvider as Gr, ensureAssetStorage as Gs, getCurrentProducerRegions as Gt, parentSuppliedValues as H, malformedResourcesWarning as Ha, PARTITION_TABLE as Hc, applyCallerIdentityCredentials as Hi, deleteSupersededEntry as Hn, toFiniteNumber as Ho, ProviderRegistry as Hr, AssetModeResolver as Hs, seedsDeleteFirstGuard as Ht, isAbsoluteAssetPath as I, malformedOrphansWarning as Ia, MIGRATE_TMP_PREFIX as Ic, assertFlagRoleArn as Ii, cyan as In, isStatefulRecreateTargetSync as Io, refuseMalformedDesiredTags as Ir, stringifyValue as Is, planFailedOps as It, keptWholeReasonText as J, refuseMalformedOrphanRecords as Ja, defineOwnKey as Jc, regionLessSecretName as Ji, supersededHolderOf as Jn, readConfigString as Jo, readsNoEchoDeleteValues as Jr, parseBootstrapMarker as Js, isRedactedRecordedValue as Jt, diffSecurity as K, refuseDivergentRecordRegionForDestroy as Ka, StageLoadError as Kc, classifyReplaySecretRegion as Ki, supersededAfterRollback as Kn, configIntegerRefusal as Ko, waitForLambdaFunctionActive as Kr, getBootstrapMarkerKey as Ks, inheritProducerRegions as Kt, listNestedTemplateRows as L, malformedOutputsRefusalMessage as La, findLargeInlineResources as Lc, assertSendableRoleArn as Li, gray as Ln, renderStatefulReason as Lo, tagMapAsList as Lr, WorkGraph as Ls, planRollback as Lt, findServiceTokenRefusals as M, malformedOrphanRecordsRefusalMessage as Ma, warnDeprecatedNoPrefixCliFlag as Mc, outputReferenceProvenanceOf as Mi, getStackRecords as Mn, findReplacedReadersOfRecreateTargets as Mo, DBPROXY_TAGS_WHAT as Mr, shouldRetainResource as Ms, recordAfterRollbackUpdate as Mt, serviceTokenBlockingReason as N, malformedOrphanRecordsWarning as Na, ssmResolvedValueType as Nc, recordedOutputReferenceRegions as Ni, withStackRecords as Nn, shownType as No, DBPROXY_TAG_OPTIONS as Nr, stackInstanceIdCarriedFrom as Ns, demoteSupersededOrphans as Nt, computeImplicitDeleteEdges as O, malformedExportSourceWarning as Oa, resolveStateBucketWithDefault as Oc, resolveDynamicReferences as Oi, findDestructiveChanges as On, unwrittenCreateOnlyReplacement as Oo, DeploymentEventsStore as Or, importableOutputs as Os, withApiLimit as Ot, childTemplateLoader as P, malformedOrphanRowsKeptWarning as Pa, CFN_TEMPLATE_BODY_LIMIT as Pc, recordedReferenceRegions as Pi, replacedDeleteFailureVerdict as Pn, MULTI_REGION_RECREATE_BLOCKED_TYPES as Po, planTagDiff as Pr, AssetPublisher as Ps, isJournaledOrphan as Pt, planOrphanAdoption as Q, refuseMalformedOrphansForOrphan as Qa, ownValue as Qc, getAccountInfo as Qi, noEchoComparisonForTemplate as Qn, requireConfigString as Qo, CUSTOM_RESOURCE_RESPONSE_LIFECYCLE_RULE_ID as Qr, buildDenyExternalAccessPolicy as Qs, updatePartialReason as Qt, renderNestedTemplateTreeDefect as R, malformedOutputsWarning as Ra, uploadCfnTemplate as Rc, explicitRoleArnOrThrow as Ri, green as Rn, WARM_THROUGHPUT_MEMBERS as Ro, tagPlanWarning as Rr, buildAssetRedirectMap as Rs, recheckFailedPlan as Rt, S3_AUTO_DELETE_OBJECTS_TAG as S, hasReadableOutputs as Sa, getLegacyStateBucketName as Sc, isSettledInstanceState as Si, isExportAliasCollision as Sn, unpreviewableOrphanRecords as So, earliestDefined as Sr, describeRegionValueKind as Ss, makeForeignHolderScan as St, getPriorAttempts as T, isReadableResourceEntry as Ta, resolveAutoAssetStorage as Tc, s3BucketDualStackDomainName as Ti, DEFAULT_RESOURCE_WARN_AFTER_MS as Tn, withheldAccountClause as To, withCreateTokenLedger as Tr, hasReasonlessBaselineRefusal as Ts, chunks as Tt, readRecordedConditionVerdicts as U, malformedScrubResourceEntriesRefusalMessage as Ua, canonicalizeRegion as Uc, callerEnvCredentials as Ui, holdsSupersededResources as Un, coerceCfnBoolean as Uo, ccBrokenReason as Ur, BOOTSTRAP_MARKER_PREFIX as Us, orphanNeedsIdentity as Ut, conditionInputsFrom as V, malformedResourcePropertiesWarning as Va, expectedOwnerParam as Vc, AWS_CREDENTIAL_ENV_KEYS as Vi, addSuperseded as Vn, toCfnInteger as Vo, CC_BROKEN_REASON as Vr, rewriteTemplateAssetReferences as Vs, resolveReplacementOldType as Vt, enclosingDeadlineRemainingMs as W, malformedStateRefusalMessage as Wa, derivePartitionAndUrlSuffix as Wc, envCredentialsAreAssumedRole as Wi, isSupersededResourceRecord as Wn, coerceCfnInteger as Wo, isCustomResource as Wr, assertAssetBucketRegion as Ws, findNestedStackTypeChanges as Wt, makeCanonicalizePropertiesFn as X, refuseMalformedOrphans as Xa, hasPlainPrototype as Xc, isUnboundTemplateParameter as Xi, withoutSuperseded as Xn, requireConfigArray as Xo, getCurrentResourceSecrets as Xr, validateAssetBucketName as Xs, redactedDeleteAddressSkip as Xt, mergeNoChangeOutputs as Y, refuseMalformedOrphanRecordsForDestroy as Ya, hasOwnKey as Yc, coerceParameterTypedValue as Yi, supersededResourcesOf as Yn, replayWarn as Yo, isCustomResourceType as Yr, readBootstrapMarkerBody as Ys, redactedDeleteAddressFields as Yt, makeSiblingClaimReader as Z, refuseMalformedOrphansForDestroy as Za, nullPrototypeRecord as Zc, parameterTypeMayLoseSecretIdentity as Zi, noEchoAttributeNamesOf as Zn, requireConfigObject as Zo, withPrintingSecrets as Zr, validateContainerRepoName as Zs, updatePartialMessage as Zt, deleteTableWithIndexBusyRetry as _, UNREADABLE_RESOURCES_MAP_ROW as _a, AssetManifestLoader as _c, reEnableInstanceApiTermination as _i, exportNameSecretExposure as _n, repairMalformedOrphansForReadOnly as _o, createPreDeleteFinalSnapshot as _r, isNotImplemented as _s, dropFailedCommands as _t, isProtectionValueActive as a, cfnRefValueFromPhysicalId as aa, finchSecretArgvRefusal as ac, UNSPECIFIED_SKIP_REASON as ai, injectedAwsRegionValue as al, computeParameterTaint as an, refuseMalformedResourceEntriesForImport as ao, namingSecretsWithRecordedNoEcho as ar, sameLambdaFunctionAddress as as, displacedPhysicalIdShown as at, waitForIndexesSettled as b, displayLogicalId as ba, synthesisStatusMessage as bc, IntrinsicFunctionResolver as bi, collectDeclaredOutputNames as bn, repairMalformedResourcePropertiesForReadOnly as bo, refusesFinalSnapshot as br, splitImportedOps as bs, journaledOrphanLines as bt, DynamoDBGlobalTableProvider as c, parseWebACLArn as ca, isDockerClientEnvKey as cc, deleteSkipReason as ci, resourcesNamingDeclaredParameter as cn, refuseMalformedResourcePropertiesForDestroy as co, secretNamePrintingBags as cr, LockManager as cs, nestedChildStackName as ct, compensateRemovedDeletionProtection as d, passedParameterClassesOf as da, redactDockerArgvValues as dc, markWaitAbandoned as di, exportAliasCollisionScrubWarning as dn, refuseMalformedResourcePropertiesForOrphan as do, stateSecretNameNeedles as dr, rebuildClientForBucketRegion as ds, revertedNestedRowIds as dt, carriesDynamicReference as ea, resolveDockerContextDirectory as ec, customResourceResponseExpirationWarning as ei, describeFileReadFailure as el, nameGenerationHighWaterOf as en, refuseMalformedOutputsForDestroy as eo, noEchoParameterNamesOf as er, templateResourceTypes as es, resolvePendingCloudControlRequests as et, deleteBudgetKey as f, declaresNoEcho as fa, redactedCause as fc, disableInstanceApiTermination as fi, secretBearing as fn, refuseMalformedResourcesForDeploy as fo, storedSecretNameNeedles as fr, CrossPrefixReadError as fs, withNestedRevertRun as ft, INDEX_SETTLE_POLL_INTERVAL_MS as g, UNREADABLE_ORPHANS_CONTAINER_ROW as ga, warnFinchArgvExposure as gc, reDisableInstanceApiTermination as gi, exportNameNoEchoParameters as gn, repairMalformedOrphanRecordsForReadOnly as go, ccRoutedFinalSnapshotError as gr, isAccessDenied$1 as gs, deleteJournaledOrphans as gt, DELETE_INDEX_WAIT_PROCEED_NOTE as h, STATE_RESOURCES_MALFORMED as ha, runDockerStreaming as hc, observeThenDisableInstanceApiTermination as hi, carriedExportAliasExposure as hn, refuseMalformedState as ho, buildFinalSnapshotIdentifier as hr, crossPrefixDeniedWarning as hs, withNestedStackContext as ht, PROTECTION_PROPERTY_BY_TYPE as i, AWS_NO_VALUE as ia, dockerSpawnEnvWithSensitive as ic, RollbackInlinePolicyWriters as ii, injectAwsRegion as il, retiredNameGenerationsLeaving as in, refuseMalformedResourceEntriesForDestroy as io, maskEventTextWithBoundBags as ir, lambdaFunctionNameForMask as is, displacedOpClause as it, deferredServiceTokenWarning as j, malformedLocalResourcesWarning as ja, stateBucketExistenceConfirmed as jc, keepHeldTokenProvenance as ji, destroyStackRecordsView as jn, hasNoCloudControlHandlers as jo, markDeleteStarted as jr, orphansCarriedFrom as js, removeProtectionTypeList as jt, crossStackOutputProvenanceSource as k, malformedLocalOutputsWarning as ka, resolveStateBucketWithDefaultAndSource as kc, producerLookupOver as ki, formatDestructiveChange as kn, withoutSilentDropProperties as ko, extractDeploymentEventError as kr, isReadableBag as ks, replayFailedOperations as kt, DYNAMODB_DELETE_MIN_RESOURCE_TIMEOUT_MS as l, withSharedDrainBudget as la, isMalformedEnvKey as lc, withIndeterminateGuard as li, WITHHELD_NAME_DISPLAY as ln, refuseMalformedResourcePropertiesForDrift as lo, secretNamedAttributeNamesOf as lr, isLockInfoExpired as ls, recordDisplacedSkips as lt, resolveDynamoDbDeleteBudgetMs as m, STATE_REGION_DIVERGED as ma, runDockerForeground as mc, isTerminationProtectionPropagationError as mi, secretSafeKeyDisplay as mn, refuseMalformedResourcesForExport as mo, PRE_DELETE_SNAPSHOT_TYPES as mr, applyCrossPrefixScan as ms, getCurrentNestedStackContext as mt, recordedProtectionEvidence as n, isNamelessDynamicReferenceError as na, describeDockerExecFailure as nc, slowCcOperationTimeoutMs as ni, renderAssemblyPathEscape as nl, retiredAfterRollback as nn, refuseMalformedResourceEntries as no, completedReplayEntries as nr, withRetry as ns, recordRetainedForReadoption as nt, perType as o, isStalePlaceholderArnAttribute as oa, formatDockerLoginError as oc, deleteIndeterminateGuards as oi, clearBucketRegionCache as ol, namesAnyDeclaredParameter as on, refuseMalformedResourceEntriesForImportSave as oo, orphanRecordsPrintingBag as or, DagBuilder as os, dropSettledNestedJournals as ot, resolveDynamoDbDeleteBudgetClock as p, JSON_LISTING_HOLE_VALUE as pa, redactedDockerCause as pc, ec2InstanceProtectionSite as pi, secretBearingStateKeyWarning as pn, refuseMalformedResourcesForDestroy as po, ATOMIC_FINAL_SNAPSHOT_TYPES as pr, CrossPrefixScanCache as ps, collectNestedChildUnaddressed as pt, isSecretBearingReferenceString as q, refuseMalformedNestedChildOutputs as qa, processStackMessages as qc, producerRegionsFromState as qi, supersededHeldByOtherTypeWarning as qn, configStringRefusal as qo, TemplateNoEchoReresolver as qr, isCrossRegionRedirect as qs, REDACTED_DELETE_ADDRESS_SKIP_REASON as qt, recordedProtectionNote as r, keepsSecretReferenceToken as ra, describeDockerFailure as rc, unchangedBehindSecretReference as ri, resolveAssemblyPath as rl, retiredNameGenerationsAfter as rn, refuseMalformedResourceEntriesForDeploy as ro, journaledOrphanPrintingBag as rr, canonicalLambdaFunctionName as rs, NESTED_PENDING_PARENT_REASON as rt, readProtection as s, refStateLookupFromResource as sa, getDockerCmd as sc, deleteLeftInPlace as si, resolveBucketRegion as sl, reachableDivergentParameters as sn, refuseMalformedResourceEntriesForOrphan as so, secretNamePrintingBag as sr, TemplateParser as ss, getNestedRevertRun as st, DeployEngine as t, carriesFetchableDynamicReference as ta, describeDockerCapturedOutput as tc, CloudControlProvider as ti, displayAssemblyPath as tl, nameScopeOf as tn, refuseMalformedResourceAttributesForOrphan as to, createReadOnlyAttributeHealerFactory as tr, describeTypeWithThrottleRetry as ts, keptForRetainedRecord as tt, beginDeleteWait as u, parameterInputsFor as ua, partitionSensitiveEnv as uc, isWaitAbandonedError as ui, displayTextOrWithheld as un, refuseMalformedResourcePropertiesForExport as uo, secretNamedRecordNeedles as ur, S3StateBackend as us, revertNestedChildFromJournal as ut, maskedLogger as v, accountArgs as va, getDockerImageBySourceHash as vc, DiffCalculator as vi, isWholeDynamicReferenceValue as vn, repairMalformedOutputsForReadOnly as vo, effectiveDeletionPolicy as vr, stackInstanceIdOf as vs, dropFailedHint as vt, isTruthyCfnBoolean as w, isReadableOrphanRecord as wa, resolveApp as wc, s3BucketDomainName as wi, DEFAULT_RESOURCE_TIMEOUT_MS as wn, unreadableResourceEntries as wo, reserveStackCreateToken as wr, hasReadableExportSet as ws, formatResourceLine as wt, ECR_AUTO_DELETE_IMAGES_TAG as x, hasReadableOrphans as xa, getDefaultStateBucketName as xc, poisonRenderedSpellingsCollidingIn as xi, collectPublishedOutputNames as xn, repairMalformedResourcesForReadOnly as xo, unsupportedFinalSnapshotError as xr, acceptedCreateOnlyDropsOf as xs, loadJournaledOrphans as xt, relayedIndexBusyDelete as y, deployRefusesOrphanRowsReason as ya, Synthesizer as yc, INTRINSIC_KEYS as yi, noEchoParameterValueSeed as yn, repairMalformedResourceEntriesForReadOnly as yo, isFinalSnapshotError as yr, withStackInstanceIdWithheld as ys, isHandledOrphan as yt, templateIdentity as z, malformedRenderedContainersWarning as za, CUSTOM_RESOURCE_RESPONSE_OBJECT_DESCRIPTION as zc, isIamRoleArn as zi, red as zn, coerceWarmThroughput as zo, definedAttributes as zr, createAssetRedirectResolver as zs, recordUnderIdIsNotOwn as zt };
|
|
46546
|
+
//# sourceMappingURL=deploy-engine-D9SDE-Pj.js.map
|