@go-to-k/cdkd 0.291.24 → 0.291.26
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-CXNAEgyw.js → asg-provider-Dbqbr89e.js} +2 -2
- package/dist/{asg-provider-CXNAEgyw.js.map → asg-provider-Dbqbr89e.js.map} +1 -1
- package/dist/cli.js +2 -2
- package/dist/{deploy-engine-Czuf7jgT.js → deploy-engine-BZps_IKn.js} +1500 -702
- package/dist/deploy-engine-BZps_IKn.js.map +1 -0
- package/dist/index.d.ts +7 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/{program-CQ_Y14q1.js → program-BALgPCWL.js} +253 -149
- package/dist/{program-CQ_Y14q1.js.map → program-BALgPCWL.js.map} +1 -1
- package/dist/{version-BI33Emlj.js → version-BkoR4hMq.js} +2 -2
- package/dist/{version-BI33Emlj.js.map → version-BkoR4hMq.js.map} +1 -1
- package/package.json +2 -2
- package/dist/deploy-engine-Czuf7jgT.js.map +0 -1
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { $ as yellow, $i as synthesisStatusMessage, $n as refuseMalformedOrphanRecordsForDestroy, $r as forceQuitRecoveryClause, $t as configIntegerRefusal, A as createPreDeleteFinalSnapshot, Aa as credentialFingerprint, Ai as validateContainerRepoName, An as hasReadableOutputs, Ao as retryClassificationText, Ar as TEMPLATE_SOURCED_RULES, At as deleteSkipReason, B as isStatefulRecreateTargetSync, Ba as absoluteAssemblyPathEscape, Bi as getDockerCmd, Bn as malformedOrphansRefusalMessage, Br as maskSecretsInText, Bt as isImpossibleEmptyStoredAttribute, C as namesAnyDeclaredParameter, Ca as expectedOwnerParam, Ci as assertAssetBucketRegion, Cn as STATE_REGION_DIVERGED, Co as shellQuote, Cr as describeTypeWithThrottleRetry, Ct as compositeIdSkipResult, D as PRE_DELETE_SNAPSHOT_TYPES, Da as ambientClientDefaults, Di as parseBootstrapMarker, Dn as deployRefusesOrphanRowsReason, Do as isTransientServerError, Dr as STATE_SOURCED_BASELINE_RULES, Dt as maskerOrIdentity, E as ATOMIC_FINAL_SNAPSHOT_TYPES, Ea as derivePartitionAndUrlSuffix, Ei as isCrossRegionRedirect, En as UNREADABLE_RESOURCES_MAP_ROW, Eo as isThrottlingError, Er as TemplateParser, Et as maskDeep, F as extractDeploymentEventError, Fa as defineOwnKey, Fi as describeDockerExecFailure, Fn as malformedExportSourceWarning, Fr as identityKeyFor, Ft as carriesDynamicReference, G as toCfnInteger, Ga as resolveBucketRegion, Gi as runDockerForeground, Gn as malformedResourceEntriesWarning, Gr as redactSecretsForState, Gt as isSettledInstanceState, H as WARM_THROUGHPUT_MEMBERS, Ha as renderAssemblyPathEscape, Hi as isMalformedEnvKey, Hn as malformedOutputsRefusalMessage, Hr as recordMaskOnlyValue, Ht as isUnboundTemplateParameter, I as makeSiblingClaimReader, Ia as hasOwnKey, Ii as describeDockerFailure, In as malformedLocalOutputsWarning, Ir as isSingleDynamicReferenceToken, It as carriesFetchableDynamicReference, J as bold, Ja as resetAwsClients, Ji as escapeRegExp, Jn as malformedStateRefusalMessage, Jr as S3StateBackend, Jt as resolveExplicitPhysicalId, K as toFiniteNumber, Ka as AwsClients, Ki as runDockerStreaming, Kn as malformedResourcePropertiesWarning, Kr as scrubResourceRecord, Kt as WAFv2WebACLProvider, L as planOrphanAdoption, La as hasPlainPrototype, Li as dockerSpawnEnvWithSensitive, Ln as malformedOrphanRecordsRefusalMessage, Lr as isUncertifiedBaselineMaskPosition, Lt as cfnRefValueFromPhysicalId, M as refusesFinalSnapshot, Ma as failedStageNote, Mi as buildDockerImage, Mn as isReadableOrphanRecord, Mo as safeStringify, Mr as createSecretMasker, Mt as disableInstanceApiTermination, N as unsupportedFinalSnapshotError, Na as globMatches, Ni as resolveDockerContextDirectory, Nn as isReadableResourceEntry, Nr as dynamicReferenceTokens, Nt as isTerminationProtectionPropagationError, O as buildFinalSnapshotIdentifier, Oa as ambientCredentialConfig, Oi as readBootstrapMarkerBody, On as displayLogicalId, Oo as markNonRetryable, Or as STATE_SOURCED_CROSS_GENERATION_RULES, Ot as UNSPECIFIED_SKIP_REASON, P as makeCanonicalizePropertiesFn, Pa as processStackMessages, Pi as describeDockerCapturedOutput, Pn as malformedExportNamesWarning, Pr as errorCauseChain, Pt as IntrinsicFunctionResolver, Q as red, Qa as CdkdError, Qi as Synthesizer, Qn as refuseMalformedOrphanRecords, Qr as buildLockContentionMessage, Qt as configBooleanRefusal, R as MULTI_REGION_RECREATE_BLOCKED_TYPES, Ra as nullPrototypeRecord, Ri as finchSecretArgvRefusal, Rn as malformedOrphanRecordsWarning, Rr as markSameGenerationBag, Rt as coerceParameterTypedValue, S as computeParameterTaint, Sa as decodeListingKey, Si as BOOTSTRAP_MARKER_PREFIX, Sn as INTRINSIC_KEYS, So as pasteableCommand, Sr as findSilentDropProperties, St as compositeIdSeparatorRefusal, T as resourcesNamingDeclaredParameter, Ta as canonicalizeRegion, Ti as getBootstrapMarkerKey, Tn as UNREADABLE_ORPHANS_CONTAINER_ROW, To as isRetryableTransientError, Tr as DagBuilder, Tt as createMaskedRetryLogger, U as coerceWarmThroughput$1, Ua as resolveAssemblyPath, Ui as partitionSensitiveEnv, Un as malformedOutputsWarning, Ur as recordMaskOnlyValuesIn, Ut as parameterTypeMayLoseSecretIdentity, V as renderStatefulReason, Va as displayAssemblyPath, Vi as isDockerClientEnvKey, Vn as malformedOrphansWarning, Vr as pathCrossesDottedKey, Vt as isNamelessDynamicReferenceError, W as isWarmThroughputDecrease, Wi as redactDockerArgvValues, Wn as malformedRenderedContainersWarning, Wr as recoverMaskedOutput, Wt as refStateLookupFromResource, X as gray, Xa as setAwsClients, Xi as AssetManifestLoader, Xn as refuseDivergentRecordRegionForDestroy, Xr as UNREPRODUCIBLE_LOCK_CLAUSE, Xt as coerceCfnBoolean, Y as cyan, Ya as runWithStackAwsClients, Yi as stripControlChars, Yn as previewableOrphanRecords, Yr as rebuildClientForBucketRegion, Yt as assertRegionMatch, Z as green, Zi as getDockerImageBySourceHash, Zn as refuseMalformedNestedChildOutputs, Zr as buildForceUnlockCommand, Zt as coerceCfnInteger, _ as bagHoldsSecretExpression, _a as CUSTOM_RESOURCE_RESPONSE_OBJECT_DESCRIPTION, _i as buildAssetRedirectMap, _n as AWS_CREDENTIAL_ENV_KEYS, _o as SynthesisError, _r as safeRegion, _t as startInterruptWatch, a as DeploymentEventsStore, aa as resolveSkipPrefix, ai as hasReadableExportSet, an as requireConfigString, ao as LocalInvokeBuildError$1, ar as refuseMalformedResourceAttributesForOrphan, at as secretBearingStateKeyWarning, b as mergeNoChangeOutputs, ba as producerCoordinateKey, bi as rewriteTemplateAssetReferences, bn as envCredentialsAreAssumedRole, bo as normalizeAwsError, br as unreadableOrphanRecords, bt as ccProtectionRegistryTypes, c as replayFailedOperations, ca as resolveUseCdkBootstrapAssets, ci as importableOutputKeys, cn as classifyReplaySecretRegion, co as MalformedProducerRecordRefusalError, cr as refuseMalformedResourcePropertiesForOrphan, ct as IAMRoleProvider, d as updatePartialMessage, da as ssmResolvedValueType, di as orphansAfterRollback, dn as s3BucketArn, do as ProvisioningError, dr as repairMalformedOrphanRecordsForReadOnly, dt as ProviderRegistry, ea as getDefaultStateBucketName, ei as formatLockExpiry, en as configStringRefusal, eo as CrossAccountSecretRefusalError, er as refuseMalformedOrphans, et as collectDeclaredOutputNames, f as updatePartialReason, fa as CFN_TEMPLATE_BODY_LIMIT, fi as orphansCarriedFrom, fn as s3BucketDomainName, fo as ResourceTimeoutError, fr as repairMalformedOrphansForReadOnly, ft as wouldReturnToSdkProvider, g as computeImplicitDeleteEdges, ga as uploadCfnTemplate, gi as WorkGraph, gn as applyRoleArnIfSet, gr as repairMalformedResourcesForReadOnly, gt as isInterruptedWaitError, h as IMPLICIT_DELETE_DEPENDENCIES, ha as findLargeInlineResources, hi as stringifyValue, hn as s3BucketWebsiteUrl, ho as StackTerminationProtectionError, hr as repairMalformedResourcePropertiesForReadOnly, ht as interruptWatchListenerCount, i as DeploymentEventsReader, ia as resolveCaptureObservedState, ii as exportNamesCarriedFrom, in as requireConfigObject, io as IntrinsicResolutionRefusalError, ir as refuseMalformedOutputsForDestroy, it as secretBearing, j as isFinalSnapshotError, ja as AssemblyReader, ji as buildDenyExternalAccessPolicy, jn as hasReadableResources, jo as describeAwsFailure, jr as carriesSecretMask, jt as isWaitAbandonedError, k as ccRoutedFinalSnapshotError, ka as clientDefaultsFor, ki as validateAssetBucketName, kn as hasReadableOrphans, ko as markRedactedCause, kr as STATE_SOURCED_READBACK_RULES, kt as deleteIndeterminateGuards, l as replayRollback, la as stateBucketExistenceConfirmed, li as importableOutputs, ln as producerRegionsFromState, lo as NestedStackChildDirectDestroyError, lr as refuseMalformedResourcesForDestroy, lt as collectInlinePolicyNamesManagedBySiblings, m as maskingRetryLogger, ma as MIGRATE_TMP_PREFIX, mi as AssetPublisher, mn as s3BucketRegionalDomainName, mo as StackHasActiveImportsError, mr as repairMalformedResourceEntriesForReadOnly, mt as endCommandInterruptScope, n as DEFAULT_RESOURCE_WARN_AFTER_MS, na as resolveApp, ni as DEFAULT_STATE_PREFIX, nn as replayWarn, no as DeployCancelledError, nr as refuseMalformedOrphansForOrphan, nt as exportAliasCollisionScrubWarning, o as planFailedOps, oa as resolveStateBucketWithDefault, oi as hasReasonlessBaselineRefusal, on as definedAttributes, oo as LocalStartServiceError, or as refuseMalformedResourceEntries, ot as secretSafeKeyDisplay, p as withResourceDeadline, pa as CFN_TEMPLATE_URL_LIMIT, pi as shouldRetainResource, pn as s3BucketDualStackDomainName, po as ResourceUpdateNotSupportedError, pr as repairMalformedOutputsForReadOnly, pt as beginCommandInterruptScope, q as formatResourceLine, qa as getAwsClients, qi as warnFinchArgvExposure, qn as malformedResourcesWarning, qr as LockManager, qt as normalizeAwsTagsToCfn, r as DeployEngine, ra as resolveAutoAssetStorage, ri as describeRegionValueKind, rn as requireConfigArray, ro as DynamicReferenceRegionAmbiguousError, rr as refuseMalformedOutputs, rt as isExportAliasCollision, s as planRollback, sa as resolveStateBucketWithDefaultAndSource, si as hasUnverifiableParameterRefusal, sn as stringifyIfAssigned, sr as refuseMalformedResourceEntriesForOrphan, st as getCurrentResourceSecrets, t as DEFAULT_RESOURCE_TIMEOUT_MS, ta as getLegacyStateBucketName, ti as CUSTOM_RESOURCE_RESPONSE_PREFIX, tn as readConfigString, tr as refuseMalformedOrphansForDestroy, tt as collectPublishedOutputNames, u as resolveReplacementOldType, ua as warnDeprecatedNoPrefixCliFlag, ui as isReadableBag, un as withSharedDrainBudget, uo as PartialFailureError, ur as refuseMalformedState, ut as clearOnUpdateRemoval, v as isSecretBearingReferenceString, va as injectiveKey, vi as createAssetRedirectResolver, vn as applyCallerIdentityCredentials, vr as safeStackName, vt as CloudControlProvider, w as reachableDivergentParameters, wa as PARTITION_TABLE, wi as ensureAssetStorage, wn as STATE_RESOURCES_MALFORMED, wo as isMarkedNonRetryable, wr as withRetry, wt as packCompositeId, x as bindingSkippedOutputs, xa as producerRecordKey, xi as AssetModeResolver, xn as DiffCalculator, xo as withErrorHandling, xr as findActionableSilentDrops, xt as compositeIdFormatMessage, y as keptWholeReasonText, ya as injectiveKeyPrefix, yi as loadPublishableAssetManifest, yn as callerEnvCredentials, yr as unpreviewableOrphanRecords, yt as slowCcOperationTimeoutMs, z as isStatefulRecreateTargetForReplace, za as ownValue, zi as formatDockerLoginError, zn as malformedOrphanRowsKeptWarning, zr as maskSecretsInError, zt as getAccountInfo } from "./deploy-engine-Czuf7jgT.js";
|
|
1
|
+
import { $ as yellow, $a as CdkdError, $i as synthesisStatusMessage, $n as refuseMalformedOrphanRecordsForDestroy, $r as forceQuitRecoveryClause, $t as configIntegerRefusal, A as createPreDeleteFinalSnapshot, Aa as credentialFingerprint, Ai as validateContainerRepoName, An as hasReadableOutputs, Ao as markRedactedCause, Ar as TEMPLATE_SOURCED_RULES, At as deleteSkipReason, B as isStatefulRecreateTargetSync, Ba as absoluteAssemblyPathEscape, Bi as getDockerCmd, Bn as malformedOrphansRefusalMessage, Br as maskSecretsInText, Bt as isImpossibleEmptyStoredAttribute, C as namesAnyDeclaredParameter, Ca as expectedOwnerParam, Ci as assertAssetBucketRegion, Cn as STATE_REGION_DIVERGED, Co as pasteableCommand, Cr as describeTypeWithThrottleRetry, Ct as compositeIdSkipResult, D as PRE_DELETE_SNAPSHOT_TYPES, Da as ambientClientDefaults, Di as parseBootstrapMarker, Dn as deployRefusesOrphanRowsReason, Do as isThrottlingError, Dr as STATE_SOURCED_BASELINE_RULES, Dt as maskerOrIdentity, E as ATOMIC_FINAL_SNAPSHOT_TYPES, Ea as derivePartitionAndUrlSuffix, Ei as isCrossRegionRedirect, En as UNREADABLE_RESOURCES_MAP_ROW, Eo as isRetryableTransientError, Er as TemplateParser, Et as maskDeep, F as extractDeploymentEventError, Fa as defineOwnKey, Fi as describeDockerExecFailure, Fn as malformedExportSourceWarning, Fr as identityKeyFor, Ft as carriesDynamicReference, G as toCfnInteger, Gi as runDockerForeground, Gn as malformedResourceEntriesWarning, Gr as redactSecretsForState, Gt as isSettledInstanceState, H as WARM_THROUGHPUT_MEMBERS, Ha as displayAssemblyPath, Hi as isMalformedEnvKey, Hn as malformedOutputsRefusalMessage, Hr as recordMaskOnlyValue, Ht as isUnboundTemplateParameter, I as makeSiblingClaimReader, Ia as hasOwnKey, Ii as describeDockerFailure, In as malformedLocalOutputsWarning, Ir as isSingleDynamicReferenceToken, It as carriesFetchableDynamicReference, J as bold, Ja as getAwsClients, Ji as escapeRegExp, Jn as malformedStateRefusalMessage, Jr as S3StateBackend, Jt as resolveExplicitPhysicalId, K as toFiniteNumber, Ka as resolveBucketRegion, Ki as runDockerStreaming, Kn as malformedResourcePropertiesWarning, Kr as scrubResourceRecord, Kt as WAFv2WebACLProvider, L as planOrphanAdoption, La as hasPlainPrototype, Li as dockerSpawnEnvWithSensitive, Ln as malformedOrphanRecordsRefusalMessage, Lr as isUncertifiedBaselineMaskPosition, Lt as cfnRefValueFromPhysicalId, M as refusesFinalSnapshot, Ma as failedStageNote, Mi as buildDockerImage, Mn as isReadableOrphanRecord, Mo as describeAwsFailure, Mr as createSecretMasker, Mt as disableInstanceApiTermination, N as unsupportedFinalSnapshotError, Na as globMatches, Ni as resolveDockerContextDirectory, Nn as isReadableResourceEntry, No as safeStringify, Nr as dynamicReferenceTokens, Nt as isTerminationProtectionPropagationError, O as buildFinalSnapshotIdentifier, Oa as ambientCredentialConfig, Oi as readBootstrapMarkerBody, On as displayLogicalId, Oo as isTransientServerError, Or as STATE_SOURCED_CROSS_GENERATION_RULES, Ot as UNSPECIFIED_SKIP_REASON, P as makeCanonicalizePropertiesFn, Pa as processStackMessages, Pi as describeDockerCapturedOutput, Pn as malformedExportNamesWarning, Pr as errorCauseChain, Pt as IntrinsicFunctionResolver, Q as red, Qi as Synthesizer, Qn as refuseMalformedOrphanRecords, Qr as buildLockContentionMessage, Qt as configBooleanRefusal, R as MULTI_REGION_RECREATE_BLOCKED_TYPES, Ra as nullPrototypeRecord, Ri as finchSecretArgvRefusal, Rn as malformedOrphanRecordsWarning, Rr as markSameGenerationBag, Rt as coerceParameterTypedValue, S as computeParameterTaint, Sa as decodeListingKey, Si as BOOTSTRAP_MARKER_PREFIX, Sn as INTRINSIC_KEYS, So as withErrorHandling, Sr as findSilentDropProperties, St as compositeIdSeparatorRefusal, T as resourcesNamingDeclaredParameter, Ta as canonicalizeRegion, Ti as getBootstrapMarkerKey, Tn as UNREADABLE_ORPHANS_CONTAINER_ROW, To as isMarkedNonRetryable, Tr as DagBuilder, Tt as createMaskedRetryLogger, U as coerceWarmThroughput$1, Ua as renderAssemblyPathEscape, Ui as partitionSensitiveEnv, Un as malformedOutputsWarning, Ur as recordMaskOnlyValuesIn, Ut as parameterTypeMayLoseSecretIdentity, V as renderStatefulReason, Va as describeFileReadFailure, Vi as isDockerClientEnvKey, Vn as malformedOrphansWarning, Vr as pathCrossesDottedKey, Vt as isNamelessDynamicReferenceError, W as isWarmThroughputDecrease, Wa as resolveAssemblyPath, Wi as redactDockerArgvValues, Wn as malformedRenderedContainersWarning, Wr as recoverMaskedOutput, Wt as refStateLookupFromResource, X as gray, Xa as runWithStackAwsClients, Xi as AssetManifestLoader, Xn as refuseDivergentRecordRegionForDestroy, Xr as UNREPRODUCIBLE_LOCK_CLAUSE, Xt as coerceCfnBoolean, Y as cyan, Ya as resetAwsClients, Yi as stripControlChars, Yn as previewableOrphanRecords, Yr as rebuildClientForBucketRegion, Yt as assertRegionMatch, Z as green, Za as setAwsClients, Zi as getDockerImageBySourceHash, Zn as refuseMalformedNestedChildOutputs, Zr as buildForceUnlockCommand, Zt as coerceCfnInteger, _ as bagHoldsSecretExpression, _a as CUSTOM_RESOURCE_RESPONSE_OBJECT_DESCRIPTION, _i as buildAssetRedirectMap, _n as AWS_CREDENTIAL_ENV_KEYS, _r as safeRegion, _t as startInterruptWatch, a as DeploymentEventsStore, aa as resolveSkipPrefix, ai as hasReadableExportSet, an as requireConfigString, ao as IntrinsicResolutionRefusalError, ar as refuseMalformedResourceAttributesForOrphan, at as secretBearingStateKeyWarning, b as mergeNoChangeOutputs, ba as producerCoordinateKey, bi as rewriteTemplateAssetReferences, bn as envCredentialsAreAssumedRole, br as unreadableOrphanRecords, bt as ccProtectionRegistryTypes, c as replayFailedOperations, ca as resolveUseCdkBootstrapAssets, ci as importableOutputKeys, cn as classifyReplaySecretRegion, cr as refuseMalformedResourcePropertiesForOrphan, ct as IAMRoleProvider, d as updatePartialMessage, da as ssmResolvedValueType, di as orphansAfterRollback, dn as s3BucketArn, do as PartialFailureError, dr as repairMalformedOrphanRecordsForReadOnly, dt as ProviderRegistry, ea as getDefaultStateBucketName, ei as formatLockExpiry, en as configStringRefusal, er as refuseMalformedOrphans, et as collectDeclaredOutputNames, f as updatePartialReason, fa as CFN_TEMPLATE_BODY_LIMIT, fi as orphansCarriedFrom, fn as s3BucketDomainName, fo as ProvisioningError, fr as repairMalformedOrphansForReadOnly, ft as wouldReturnToSdkProvider, g as computeImplicitDeleteEdges, ga as uploadCfnTemplate, gi as WorkGraph, gn as applyRoleArnIfSet, go as StackTerminationProtectionError, gr as repairMalformedResourcesForReadOnly, gt as isInterruptedWaitError, h as IMPLICIT_DELETE_DEPENDENCIES, ha as findLargeInlineResources, hi as stringifyValue, hn as s3BucketWebsiteUrl, ho as StackHasActiveImportsError, hr as repairMalformedResourcePropertiesForReadOnly, ht as interruptWatchListenerCount, i as DeploymentEventsReader, ia as resolveCaptureObservedState, ii as exportNamesCarriedFrom, in as requireConfigObject, io as DynamicReferenceRegionAmbiguousError, ir as refuseMalformedOutputsForDestroy, it as secretBearing, j as isFinalSnapshotError, ja as AssemblyReader, ji as buildDenyExternalAccessPolicy, jn as hasReadableResources, jo as retryClassificationText, jr as carriesSecretMask, jt as isWaitAbandonedError, k as ccRoutedFinalSnapshotError, ka as clientDefaultsFor, ki as validateAssetBucketName, kn as hasReadableOrphans, ko as markNonRetryable, kr as STATE_SOURCED_READBACK_RULES, kt as deleteIndeterminateGuards, l as replayRollback, la as stateBucketExistenceConfirmed, li as importableOutputs, ln as producerRegionsFromState, lo as MalformedProducerRecordRefusalError, lr as refuseMalformedResourcesForDestroy, lt as collectInlinePolicyNamesManagedBySiblings, m as maskingRetryLogger, ma as MIGRATE_TMP_PREFIX, mi as AssetPublisher, mn as s3BucketRegionalDomainName, mo as ResourceUpdateNotSupportedError, mr as repairMalformedResourceEntriesForReadOnly, mt as endCommandInterruptScope, n as DEFAULT_RESOURCE_WARN_AFTER_MS, na as resolveApp, ni as DEFAULT_STATE_PREFIX, nn as replayWarn, nr as refuseMalformedOrphansForOrphan, nt as exportAliasCollisionScrubWarning, o as planFailedOps, oa as resolveStateBucketWithDefault, oi as hasReasonlessBaselineRefusal, on as definedAttributes, oo as LocalInvokeBuildError$1, or as refuseMalformedResourceEntries, ot as secretSafeKeyDisplay, p as withResourceDeadline, pa as CFN_TEMPLATE_URL_LIMIT, pi as shouldRetainResource, pn as s3BucketDualStackDomainName, po as ResourceTimeoutError, pr as repairMalformedOutputsForReadOnly, pt as beginCommandInterruptScope, q as formatResourceLine, qa as AwsClients, qi as warnFinchArgvExposure, qn as malformedResourcesWarning, qr as LockManager, qt as normalizeAwsTagsToCfn, r as DeployEngine, ra as resolveAutoAssetStorage, ri as describeRegionValueKind, rn as requireConfigArray, ro as DeployCancelledError, rr as refuseMalformedOutputs, rt as isExportAliasCollision, s as planRollback, sa as resolveStateBucketWithDefaultAndSource, si as hasUnverifiableParameterRefusal, sn as stringifyIfAssigned, so as LocalStartServiceError, sr as refuseMalformedResourceEntriesForOrphan, st as getCurrentResourceSecrets, t as DEFAULT_RESOURCE_TIMEOUT_MS, ta as getLegacyStateBucketName, ti as CUSTOM_RESOURCE_RESPONSE_PREFIX, tn as readConfigString, to as CrossAccountSecretRefusalError, tr as refuseMalformedOrphansForDestroy, tt as collectPublishedOutputNames, u as resolveReplacementOldType, ua as warnDeprecatedNoPrefixCliFlag, ui as isReadableBag, un as withSharedDrainBudget, uo as NestedStackChildDirectDestroyError, ur as refuseMalformedState, ut as clearOnUpdateRemoval, v as isSecretBearingReferenceString, va as injectiveKey, vi as createAssetRedirectResolver, vn as applyCallerIdentityCredentials, vo as SynthesisError, vr as safeStackName, vt as CloudControlProvider, w as reachableDivergentParameters, wa as PARTITION_TABLE, wi as ensureAssetStorage, wn as STATE_RESOURCES_MALFORMED, wo as shellQuote, wr as withRetry, wt as packCompositeId, x as bindingSkippedOutputs, xa as producerRecordKey, xi as AssetModeResolver, xn as DiffCalculator, xo as normalizeAwsError, xr as findActionableSilentDrops, xt as compositeIdFormatMessage, y as keptWholeReasonText, ya as injectiveKeyPrefix, yi as loadPublishableAssetManifest, yn as callerEnvCredentials, yr as unpreviewableOrphanRecords, yt as slowCcOperationTimeoutMs, z as isStatefulRecreateTargetForReplace, za as ownValue, zi as formatDockerLoginError, zn as malformedOrphanRowsKeptWarning, zr as maskSecretsInError, zt as getAccountInfo } from "./deploy-engine-BZps_IKn.js";
|
|
2
2
|
import { C as displayAwsMessage, D as isPasteableIdent, E as displayStackName, O as truncateCodePoints, S as UNRENDERABLE, T as displaySafe, _ as withSkipPrefix, b as SECRET_REF_MAX_CODE_POINTS, c as PATTERN_B_NAME_OPTIONS, f as explicitNamePropertyFor, h as getCurrentStackName, i as reserveStdoutForPayload, l as PATTERN_B_NAME_PROPERTIES, m as generateResourceNameWithFallback, n as getLogger, o as runStackBuffered, p as generateResourceName, s as getLiveRenderer, u as PATTERN_B_RESOURCE_TYPES, v as withStackName, w as displayIdent, x as STACK_REF_MAX_CODE_POINTS } from "./logger-Bt0RGDfb.js";
|
|
3
3
|
import { n as awsClientDefaults, s as ambientRegion } from "./aws-client-defaults-jISU4PHo.js";
|
|
4
|
-
import { t as getCdkdVersion } from "./version-
|
|
5
|
-
import { a as renderDisableCommand, i as protectedReplacementAdvice, r as UNNAMEABLE_ID_CLAUSE, t as ASGProvider } from "./asg-provider-
|
|
4
|
+
import { t as getCdkdVersion } from "./version-BkoR4hMq.js";
|
|
5
|
+
import { a as renderDisableCommand, i as protectedReplacementAdvice, r as UNNAMEABLE_ID_CLAUSE, t as ASGProvider } from "./asg-provider-Dbqbr89e.js";
|
|
6
6
|
import { AsyncLocalStorage } from "node:async_hooks";
|
|
7
7
|
import { createHash, randomBytes, randomUUID } from "node:crypto";
|
|
8
8
|
import { CopyObjectCommand, CreateBucketCommand, DeleteBucketAnalyticsConfigurationCommand, DeleteBucketCommand, DeleteBucketCorsCommand, DeleteBucketEncryptionCommand, DeleteBucketIntelligentTieringConfigurationCommand, DeleteBucketInventoryConfigurationCommand, DeleteBucketLifecycleCommand, DeleteBucketMetricsConfigurationCommand, DeleteBucketOwnershipControlsCommand, DeleteBucketPolicyCommand, DeleteBucketReplicationCommand, DeleteBucketTaggingCommand, DeleteBucketWebsiteCommand, DeleteObjectsCommand, GetBucketAccelerateConfigurationCommand, GetBucketCorsCommand, GetBucketEncryptionCommand, GetBucketLifecycleConfigurationCommand, GetBucketLocationCommand, GetBucketLoggingCommand, GetBucketNotificationConfigurationCommand, GetBucketOwnershipControlsCommand, GetBucketPolicyCommand, GetBucketReplicationCommand, GetBucketTaggingCommand, GetBucketVersioningCommand, GetBucketWebsiteCommand, GetObjectCommand, GetObjectLockConfigurationCommand, GetPublicAccessBlockCommand, HeadBucketCommand, ListBucketAnalyticsConfigurationsCommand, ListBucketIntelligentTieringConfigurationsCommand, ListBucketInventoryConfigurationsCommand, ListBucketMetricsConfigurationsCommand, ListObjectVersionsCommand, ListObjectsV2Command, NoSuchBucket, NotFound, PutBucketAccelerateConfigurationCommand, PutBucketAnalyticsConfigurationCommand, PutBucketCorsCommand, PutBucketEncryptionCommand, PutBucketIntelligentTieringConfigurationCommand, PutBucketInventoryConfigurationCommand, PutBucketLifecycleConfigurationCommand, PutBucketLoggingCommand, PutBucketMetricsConfigurationCommand, PutBucketNotificationConfigurationCommand, PutBucketOwnershipControlsCommand, PutBucketPolicyCommand, PutBucketReplicationCommand, PutBucketTaggingCommand, PutBucketVersioningCommand, PutBucketWebsiteCommand, PutObjectCommand, PutObjectLockConfigurationCommand, PutPublicAccessBlockCommand, S3Client, S3ServiceException } from "@aws-sdk/client-s3";
|
|
@@ -3073,7 +3073,7 @@ function validateRecreateTargets(input) {
|
|
|
3073
3073
|
if (MULTI_REGION_RECREATE_BLOCKED_TYPES.has(resourceType)) blockedMultiRegionTargets.push(target);
|
|
3074
3074
|
if (resourceType === NESTED_STACK_RESOURCE_TYPE$1 || templateResource.Type === NESTED_STACK_RESOURCE_TYPE$1) blockedNestedStackTargets.push(target);
|
|
3075
3075
|
if (direction === "to-cc-api") {
|
|
3076
|
-
const actionableDrops = findActionableSilentDrops(resourceType, templateResource.Properties, EMPTY_ALLOW_SET$1);
|
|
3076
|
+
const actionableDrops = findActionableSilentDrops(resourceType, templateResource.Properties, EMPTY_ALLOW_SET$1, recordedResource.properties, { unresolvedAs: "changed" });
|
|
3077
3077
|
for (const { property } of actionableDrops) {
|
|
3078
3078
|
const allowKey = `${resourceType}:${property}`;
|
|
3079
3079
|
if (input.allowUnsupportedProperties.has(allowKey)) ambiguousIntent.push({
|
|
@@ -3084,7 +3084,7 @@ function validateRecreateTargets(input) {
|
|
|
3084
3084
|
}
|
|
3085
3085
|
if (recordedResource.provisionedBy === "cc-api") blockedAlreadyCcApi.push(target);
|
|
3086
3086
|
} else {
|
|
3087
|
-
const actionableDrops = findActionableSilentDrops(resourceType, templateResource.Properties, input.allowUnsupportedProperties);
|
|
3087
|
+
const actionableDrops = findActionableSilentDrops(resourceType, templateResource.Properties, input.allowUnsupportedProperties, recordedResource.properties, { unresolvedAs: "changed" });
|
|
3088
3088
|
for (const { property } of actionableDrops) ambiguousIntentSdk.push({
|
|
3089
3089
|
logicalId,
|
|
3090
3090
|
resourceType,
|
|
@@ -8600,6 +8600,16 @@ function noRecordedRegionCause() {
|
|
|
8600
8600
|
remedy: "This record predates cdkd's region-keyed state layout. Re-deploy the stack to write a record that carries its region, or confirm the bucket's location yourself, to have the guard run on the next destroy."
|
|
8601
8601
|
};
|
|
8602
8602
|
}
|
|
8603
|
+
/**
|
|
8604
|
+
* A lifecycle rule's `Id` as the warnings print it (go-to-k/cdkd#3617). The id
|
|
8605
|
+
* is template-chosen and free-form, so it renders through `displayIdent` --
|
|
8606
|
+
* bare when plain, otherwise one JSON string -- rather than inside cdkd's own
|
|
8607
|
+
* quotes, which a `'` in it would close. An absent or empty id is named in
|
|
8608
|
+
* words.
|
|
8609
|
+
*/
|
|
8610
|
+
function shownLifecycleRuleId(id) {
|
|
8611
|
+
return id === void 0 || id === null || id === "" ? "(no Id)" : displayIdent(id);
|
|
8612
|
+
}
|
|
8603
8613
|
var S3BucketProvider = class S3BucketProvider {
|
|
8604
8614
|
s3Client;
|
|
8605
8615
|
logger = getLogger().child("S3BucketProvider");
|
|
@@ -8901,7 +8911,7 @@ var S3BucketProvider = class S3BucketProvider {
|
|
|
8901
8911
|
if (coerceCfnBoolean(rule["ExpiredObjectDeleteMarker"]) === true) {
|
|
8902
8912
|
const exp = sdkRule.Expiration;
|
|
8903
8913
|
if (!(exp?.["Days"] !== void 0 || exp?.["Date"] !== void 0)) sdkRule.Expiration = { ExpiredObjectDeleteMarker: true };
|
|
8904
|
-
else this.logger.warn(`Lifecycle rule
|
|
8914
|
+
else this.logger.warn(`Lifecycle rule ${shownLifecycleRuleId(rule["Id"])} on ${displaySafe(bucketName)} sets ExpiredObjectDeleteMarker alongside an expiration Days/Date; S3 forbids combining them, so the delete-marker cleanup was not applied.`);
|
|
8905
8915
|
}
|
|
8906
8916
|
const nve = isPlainObject$2(rule["NoncurrentVersionExpiration"]) ? rule["NoncurrentVersionExpiration"] : void 0;
|
|
8907
8917
|
const legacyNveDays = rule["NoncurrentVersionExpirationInDays"];
|
|
@@ -8917,7 +8927,7 @@ var S3BucketProvider = class S3BucketProvider {
|
|
|
8917
8927
|
});
|
|
8918
8928
|
const nvts = rule["NoncurrentVersionTransitions"];
|
|
8919
8929
|
const singularNvt = rule["NoncurrentVersionTransition"];
|
|
8920
|
-
const allNvts = mergeLegacySingular(nvts, singularNvt, (sc) => this.logger.warn(`Lifecycle rule
|
|
8930
|
+
const allNvts = mergeLegacySingular(nvts, singularNvt, (sc) => this.logger.warn(`Lifecycle rule ${shownLifecycleRuleId(rule["Id"])} on ${displaySafe(bucketName)} declares both NoncurrentVersionTransitions and the legacy NoncurrentVersionTransition for storage class ${displaySafe(sc)}; S3 rejects duplicates, so the legacy singular was ignored.`));
|
|
8921
8931
|
if (allNvts.length > 0) sdkRule.NoncurrentVersionTransitions = allNvts.map(toSdkNvt);
|
|
8922
8932
|
const toSdkTransition = (t) => ({
|
|
8923
8933
|
Days: t["TransitionInDays"] ?? t["Days"],
|
|
@@ -8926,7 +8936,7 @@ var S3BucketProvider = class S3BucketProvider {
|
|
|
8926
8936
|
});
|
|
8927
8937
|
const transitions = rule["Transitions"];
|
|
8928
8938
|
const singularTransition = rule["Transition"];
|
|
8929
|
-
const allTransitions = mergeLegacySingular(transitions, singularTransition, (sc) => this.logger.warn(`Lifecycle rule
|
|
8939
|
+
const allTransitions = mergeLegacySingular(transitions, singularTransition, (sc) => this.logger.warn(`Lifecycle rule ${shownLifecycleRuleId(rule["Id"])} on ${displaySafe(bucketName)} declares both Transitions and the legacy Transition for storage class ${displaySafe(sc)}; S3 rejects duplicates, so the legacy singular was ignored.`));
|
|
8930
8940
|
if (allTransitions.length > 0) sdkRule.Transitions = allTransitions.map(toSdkTransition);
|
|
8931
8941
|
const abort = isPlainObject$2(rule["AbortIncompleteMultipartUpload"]) ? rule["AbortIncompleteMultipartUpload"] : void 0;
|
|
8932
8942
|
if (abort) sdkRule.AbortIncompleteMultipartUpload = { DaysAfterInitiation: abort["DaysAfterInitiation"] };
|
|
@@ -21135,23 +21145,29 @@ var DynamoDBTableProvider = class {
|
|
|
21135
21145
|
* CALLER-BLIND, decided rather than overlooked (PR review). A TEMPLATE-borne
|
|
21136
21146
|
* `{0, 0}` warn-skips here while `create()` fails loudly on the same value,
|
|
21137
21147
|
* which reads like the "loud failure for a quiet lie" trade the adopted-index
|
|
21138
|
-
* arm below forbids. It
|
|
21139
|
-
*
|
|
21140
|
-
*
|
|
21141
|
-
*
|
|
21142
|
-
*
|
|
21143
|
-
*
|
|
21144
|
-
*
|
|
21145
|
-
*
|
|
21146
|
-
*
|
|
21147
|
-
*
|
|
21148
|
-
*
|
|
21149
|
-
*
|
|
21150
|
-
*
|
|
21151
|
-
*
|
|
21152
|
-
*
|
|
21153
|
-
*
|
|
21154
|
-
*
|
|
21148
|
+
* arm below forbids. It was decided for three reasons; the first no longer
|
|
21149
|
+
* holds as written (see its own bullet), the other two still do:
|
|
21150
|
+
*
|
|
21151
|
+
* - When this was decided, no discriminator separated the callers that
|
|
21152
|
+
* matter. `ResourceProvider.update` takes an optional `UpdateContext`, and
|
|
21153
|
+
* `desiredFromAwsReadback` on it is set ONLY by `cdkd drift --revert`
|
|
21154
|
+
* (`src/cli/commands/drift.ts`). The rollback executor's revert arms DO
|
|
21155
|
+
* pass a context (a `maskSecrets` capability, issue #1932) but never set
|
|
21156
|
+
* that flag: their desired bag is `previousState.properties`, a TEMPLATE
|
|
21157
|
+
* recorded earlier. At the time they were therefore indistinguishable
|
|
21158
|
+
* from an ordinary template deploy — and THAT is the pair this decision
|
|
21159
|
+
* turns on. (An earlier revision said the revert arms "pass NO context",
|
|
21160
|
+
* which stopped being true with #1932 — issue #1999.) Since issue #3141
|
|
21161
|
+
* they ALSO set `UpdateContext.replayingState`, so the caller is now
|
|
21162
|
+
* knowable: the per-index `OnDemandThroughput` refusal in `update()` gates
|
|
21163
|
+
* on exactly that pair of flags (the go-to-k/cdkd#3401 review). This arm
|
|
21164
|
+
* was not re-decided when that became possible; splitting it the same way
|
|
21165
|
+
* would turn a template-path warn-skip into a refusal, a behaviour change
|
|
21166
|
+
* that needs its own review rather than a comment edit (issue #3728).
|
|
21167
|
+
* - The repo's general rule for the UPDATE path is WARN-never-throw (issues
|
|
21168
|
+
* #1545 / #1552): the desired bag here can BE a historical cdkd state
|
|
21169
|
+
* record, and a refusal would make the table un-updatable and
|
|
21170
|
+
* un-rollbackable with no template-side remedy.
|
|
21155
21171
|
* - The lie is bounded and self-surfacing. AWS never accepted `{0, 0}` at
|
|
21156
21172
|
* create either, so no live table can be holding it; and where the value
|
|
21157
21173
|
* would actually matter — a PROVISIONED table, whose indexes hold a real
|
|
@@ -31657,9 +31673,10 @@ var EC2Provider = class {
|
|
|
31657
31673
|
* narrowing here the template's extra keys read as an ADDED property on the
|
|
31658
31674
|
* next deploy — and every destination key is create-only in the registry
|
|
31659
31675
|
* schema, so the diff would classify a REPLACEMENT and the engine's
|
|
31660
|
-
* replacement create (
|
|
31661
|
-
* `
|
|
31662
|
-
* previously-green no-op deploy
|
|
31676
|
+
* replacement create (whose context carries a `maskSecrets` capability but
|
|
31677
|
+
* never `replayingState`, and so gets no `onMultipleDestinations`
|
|
31678
|
+
* downgrade) would hit the #1566 refusal. A previously-green no-op deploy
|
|
31679
|
+
* would start failing.
|
|
31663
31680
|
*
|
|
31664
31681
|
* Shares `narrowRouteDestinations` with the provisioning path so the two
|
|
31665
31682
|
* cannot disagree about which key survives.
|
|
@@ -31668,8 +31685,8 @@ var EC2Provider = class {
|
|
|
31668
31685
|
* half for the same reason: `IpProtocol` is create-only on that type in the
|
|
31669
31686
|
* registry schema, so normalizing state alone would make the template's
|
|
31670
31687
|
* original value read as a changed immutable property — a REPLACEMENT, whose
|
|
31671
|
-
* create
|
|
31672
|
-
* previously-green no-op deploy into a hard failure. Normalizing BOTH sides
|
|
31688
|
+
* create never sets `replayingState` and so gets no `onUnusable` downgrade,
|
|
31689
|
+
* turning a previously-green no-op deploy into a hard failure. Normalizing BOTH sides
|
|
31673
31690
|
* is also what keeps the fix correct for records written BEFORE it existed,
|
|
31674
31691
|
* which still carry the un-narrowed value.
|
|
31675
31692
|
*/
|
|
@@ -51256,6 +51273,40 @@ const GLUE_TABLE_ID_FORMAT = {
|
|
|
51256
51273
|
segments: ["databaseName", "tableName"]
|
|
51257
51274
|
};
|
|
51258
51275
|
/**
|
|
51276
|
+
* Decode an `AWS::Glue::Table` physicalId `<databaseName>|<tableName>`.
|
|
51277
|
+
*
|
|
51278
|
+
* The separator is unescaped (issue #1672), so a bare split of an id whose
|
|
51279
|
+
* table name carries a `|` returns a DIFFERENT table — `mydb|a|b` splits to
|
|
51280
|
+
* `mydb.a`, both halves non-empty, and a delete of it would hit the wrong
|
|
51281
|
+
* table. Such ids exist: a state-replay create warns and packs one anyway, and
|
|
51282
|
+
* binaries before the #1719 refusal recorded them. The recorded `DatabaseName`
|
|
51283
|
+
* disambiguates the id without re-deriving the identity from the bag: it is
|
|
51284
|
+
* used only when the id starts with it, and the table name is the remainder.
|
|
51285
|
+
*
|
|
51286
|
+
* `bags` are tried in order, so pass the one describing what was DEPLOYED
|
|
51287
|
+
* first. With no usable anchor only an id with exactly one separator decodes;
|
|
51288
|
+
* anything longer is ambiguous and returns `undefined`, the malformed-id arm
|
|
51289
|
+
* every caller already has.
|
|
51290
|
+
*/
|
|
51291
|
+
function decodeTableId(physicalId, ...bags) {
|
|
51292
|
+
for (const bag of bags) {
|
|
51293
|
+
const databaseName = bag?.["DatabaseName"];
|
|
51294
|
+
if (typeof databaseName !== "string" || databaseName === "") continue;
|
|
51295
|
+
if (!physicalId.startsWith(`${databaseName}|`)) continue;
|
|
51296
|
+
const tableName = physicalId.slice(databaseName.length + 1);
|
|
51297
|
+
if (tableName !== "") return {
|
|
51298
|
+
databaseName,
|
|
51299
|
+
tableName
|
|
51300
|
+
};
|
|
51301
|
+
}
|
|
51302
|
+
const parts = physicalId.split("|");
|
|
51303
|
+
if (parts.length !== 2 || !parts[0] || !parts[1]) return void 0;
|
|
51304
|
+
return {
|
|
51305
|
+
databaseName: parts[0],
|
|
51306
|
+
tableName: parts[1]
|
|
51307
|
+
};
|
|
51308
|
+
}
|
|
51309
|
+
/**
|
|
51259
51310
|
* Read a template-borne value that is about to be forwarded to a Glue read
|
|
51260
51311
|
* API as a string.
|
|
51261
51312
|
*
|
|
@@ -51585,8 +51636,9 @@ var GlueProvider = class {
|
|
|
51585
51636
|
}
|
|
51586
51637
|
async updateTable(logicalId, physicalId, resourceType, properties, previousProperties) {
|
|
51587
51638
|
this.logger.debug(`Updating Glue Table ${logicalId}: ${physicalId}`);
|
|
51588
|
-
const
|
|
51589
|
-
if (!
|
|
51639
|
+
const decoded = decodeTableId(physicalId, previousProperties, properties);
|
|
51640
|
+
if (!decoded) throw new ProvisioningError(compositeIdFormatMessage(GLUE_TABLE_ID_FORMAT, logicalId, physicalId), resourceType, logicalId, physicalId);
|
|
51641
|
+
const { databaseName, tableName } = decoded;
|
|
51590
51642
|
const tableInput = properties["TableInput"];
|
|
51591
51643
|
if (!tableInput) throw new ProvisioningError(`TableInput is required for Glue Table update ${logicalId}`, resourceType, logicalId, physicalId);
|
|
51592
51644
|
const catalogId = properties["CatalogId"];
|
|
@@ -51621,11 +51673,12 @@ var GlueProvider = class {
|
|
|
51621
51673
|
}
|
|
51622
51674
|
async deleteTable(logicalId, physicalId, resourceType, properties, context) {
|
|
51623
51675
|
this.logger.debug(`Deleting Glue Table ${logicalId}: ${physicalId}`);
|
|
51624
|
-
const
|
|
51625
|
-
if (!
|
|
51676
|
+
const decoded = decodeTableId(physicalId, properties);
|
|
51677
|
+
if (!decoded) {
|
|
51626
51678
|
this.logger.warn(compositeIdFormatMessage(GLUE_TABLE_ID_FORMAT, logicalId, physicalId, { skipping: true }));
|
|
51627
51679
|
return compositeIdSkipResult();
|
|
51628
51680
|
}
|
|
51681
|
+
const { databaseName, tableName } = decoded;
|
|
51629
51682
|
const target = deleteCatalogId(properties);
|
|
51630
51683
|
if (target.declaredButUnusable) this.logger.debug(`Glue Table ${logicalId}: CatalogId is not a usable value (likely an unresolved intrinsic), so DeleteTable targets ${describeCatalog(target.catalogId)}.`);
|
|
51631
51684
|
try {
|
|
@@ -51897,9 +51950,12 @@ var GlueProvider = class {
|
|
|
51897
51950
|
* downgrades through the shared `replayWarn`, since a reverse-replacement
|
|
51898
51951
|
* re-create reads a STATE record the user cannot edit from the template.
|
|
51899
51952
|
* - UPDATE passes a warn callback UNCONDITIONALLY (the `updateRoute`
|
|
51900
|
-
* precedent
|
|
51901
|
-
*
|
|
51902
|
-
*
|
|
51953
|
+
* precedent, decided when `update()` could not tell a template push
|
|
51954
|
+
* from the state-borne bag `drift --revert` and the rollback revert arm
|
|
51955
|
+
* hand it — since issue #3141 `UpdateContext.replayingState` plus
|
|
51956
|
+
* `desiredFromAwsReadback` can, and this arm was not re-decided — issue
|
|
51957
|
+
* #3728), and
|
|
51958
|
+
* then RETAINS the PREVIOUS side's block, which is why
|
|
51903
51959
|
* `previousDatabaseInput` is threaded in. Omitting instead would ERASE a
|
|
51904
51960
|
* live resource link, because `UpdateDatabase` replaces `DatabaseInput`
|
|
51905
51961
|
* wholesale — the #1612 "UPDATE retains the previous value" row, reached
|
|
@@ -52112,7 +52168,7 @@ var GlueProvider = class {
|
|
|
52112
52168
|
const catalogId = catalogIdForApi(properties?.["CatalogId"]);
|
|
52113
52169
|
switch (resourceType) {
|
|
52114
52170
|
case "AWS::Glue::Database": return this.readDatabase(physicalId, catalogId);
|
|
52115
|
-
case "AWS::Glue::Table": return this.readTable(physicalId, catalogId);
|
|
52171
|
+
case "AWS::Glue::Table": return this.readTable(physicalId, catalogId, properties);
|
|
52116
52172
|
default: return;
|
|
52117
52173
|
}
|
|
52118
52174
|
}
|
|
@@ -52175,9 +52231,10 @@ var GlueProvider = class {
|
|
|
52175
52231
|
if (db.Name !== void 0) result["DatabaseName"] = db.Name;
|
|
52176
52232
|
return result;
|
|
52177
52233
|
}
|
|
52178
|
-
async readTable(physicalId, catalogId) {
|
|
52179
|
-
const
|
|
52180
|
-
if (!
|
|
52234
|
+
async readTable(physicalId, catalogId, properties) {
|
|
52235
|
+
const decoded = decodeTableId(physicalId, properties);
|
|
52236
|
+
if (!decoded) return void 0;
|
|
52237
|
+
const { databaseName, tableName } = decoded;
|
|
52181
52238
|
let table;
|
|
52182
52239
|
try {
|
|
52183
52240
|
table = (await this.getClient().send(new GetTableCommand({
|
|
@@ -52421,8 +52478,19 @@ var GlueWorkflowProvider = class {
|
|
|
52421
52478
|
}
|
|
52422
52479
|
return null;
|
|
52423
52480
|
}
|
|
52481
|
+
/**
|
|
52482
|
+
* The workflow ARN `GetTags` needs. The partition is derived from the
|
|
52483
|
+
* client's region (issue #1815): the literal `arn:aws:` is structurally valid
|
|
52484
|
+
* everywhere, so in `aws-cn` / `aws-us-gov` nothing rejected it — `GetTags`
|
|
52485
|
+
* was simply aimed at an ARN naming no workflow, and the best-effort catch
|
|
52486
|
+
* below reads a failure there as EMPTY tags. A commercial region still derives to `aws`,
|
|
52487
|
+
* so commercial output is unchanged byte for byte.
|
|
52488
|
+
*/
|
|
52424
52489
|
async buildWorkflowArn(workflowName) {
|
|
52425
|
-
|
|
52490
|
+
const region = await this.getRegion();
|
|
52491
|
+
const account = await this.getAccountId();
|
|
52492
|
+
const { partition } = derivePartitionAndUrlSuffix(region);
|
|
52493
|
+
return `arn:${partition}:glue:${region}:${account}:workflow/${workflowName}`;
|
|
52426
52494
|
}
|
|
52427
52495
|
async getRegion() {
|
|
52428
52496
|
return await this.getClient().config.region() || this.providerRegion || "us-east-1";
|
|
@@ -52640,8 +52708,18 @@ function findIcebergTableInputKey(properties) {
|
|
|
52640
52708
|
* must never call `this.create()` from inside its own `update()` the way ACM /
|
|
52641
52709
|
* IAM / Lambda-permission / SNS-subscription do: those internal re-creates
|
|
52642
52710
|
* forward `update()`'s `properties` — a STATE record during a rollback replay —
|
|
52643
|
-
* and `
|
|
52644
|
-
*
|
|
52711
|
+
* and pass no `CreateContext`, so this refusal would fire on a replay with no
|
|
52712
|
+
* way to detect it. (`update()` DOES take a context — an `UpdateContext` since
|
|
52713
|
+
* issue #1732 — and since issue #3141 that context carries its own
|
|
52714
|
+
* `replayingState`, set by the rollback executor's two revert arms. So the
|
|
52715
|
+
* information now reaches `update()`; what is missing is a re-create that
|
|
52716
|
+
* builds a `CreateContext` from it, and none of those providers does. An
|
|
52717
|
+
* earlier revision said `update()` had "no context parameter to carry the
|
|
52718
|
+
* flag" — issue #1999.) Were GlueProvider ever to re-create inside `update()`,
|
|
52719
|
+
* it would have to forward a replay signal into that `create()` —
|
|
52720
|
+
* `context.replayingState` on the rollback path — and decide separately what
|
|
52721
|
+
* this refusal means for the `desiredFromAwsReadback` bag `cdkd drift --revert`
|
|
52722
|
+
* hands it, since that path sets no `replayingState`.
|
|
52645
52723
|
*
|
|
52646
52724
|
* **Known bypass: the sticky Cloud Control route.** This is a GlueProvider
|
|
52647
52725
|
* pre-flight, so it only runs on the SDK route. When a table's state record
|
|
@@ -52747,11 +52825,22 @@ function cleanCfnObject(obj) {
|
|
|
52747
52825
|
}
|
|
52748
52826
|
/**
|
|
52749
52827
|
* Build the ARN for a Glue resource. Used by tag-fetch via
|
|
52750
|
-
* `GetTagsCommand` which only accepts an ARN
|
|
52751
|
-
*
|
|
52828
|
+
* `GetTagsCommand` which only accepts an ARN, and by the Job / Crawler /
|
|
52829
|
+
* Trigger `applyTagDiff` as the `TagResource` / `UntagResource` target.
|
|
52830
|
+
* Account id falls back to STS when not provided.
|
|
52831
|
+
*
|
|
52832
|
+
* The partition is derived from the region (issue #1815). A hardcoded
|
|
52833
|
+
* `arn:aws:` is structurally valid everywhere, so in `aws-cn` / `aws-us-gov`
|
|
52834
|
+
* nothing rejected it: the tag MUTATION was aimed at an ARN naming no
|
|
52835
|
+
* resource, and the drift read's best-effort `GetTags` read the failure as
|
|
52836
|
+
* empty tags. A commercial region still derives to `aws`, so commercial output
|
|
52837
|
+
* is unchanged byte for byte.
|
|
52752
52838
|
*/
|
|
52753
52839
|
async function buildGlueResourceArn(client, stsClient, resource, name, accountId) {
|
|
52754
|
-
|
|
52840
|
+
const region = await client.config.region() || ambientRegion() || "us-east-1";
|
|
52841
|
+
const account = accountId ?? await resolveAccountId(stsClient);
|
|
52842
|
+
const { partition } = derivePartitionAndUrlSuffix(region);
|
|
52843
|
+
return `arn:${partition}:glue:${region}:${account}:${resource}/${name}`;
|
|
52755
52844
|
}
|
|
52756
52845
|
async function resolveAccountId(stsClient) {
|
|
52757
52846
|
const identity = await stsClient.send(new GetCallerIdentityCommand({}));
|
|
@@ -65583,13 +65672,13 @@ var NestedStackProvider = class {
|
|
|
65583
65672
|
try {
|
|
65584
65673
|
raw = fs.readFileSync(templatePath, "utf-8");
|
|
65585
65674
|
} catch (err) {
|
|
65586
|
-
throw new Error(`Failed to read nested template at ${displayAssemblyPath(templatePath)}: ${
|
|
65675
|
+
throw new Error(`Failed to read nested template at ${displayAssemblyPath(templatePath)}: ${describeFileReadFailure(err, templatePath)}`);
|
|
65587
65676
|
}
|
|
65588
65677
|
let template;
|
|
65589
65678
|
try {
|
|
65590
65679
|
template = JSON.parse(raw);
|
|
65591
65680
|
} catch (err) {
|
|
65592
|
-
throw new Error(`Failed to parse nested template at ${displayAssemblyPath(templatePath)}: ${
|
|
65681
|
+
throw new Error(`Failed to parse nested template at ${displayAssemblyPath(templatePath)}: ${describeFileReadFailure(err, templatePath)}`);
|
|
65593
65682
|
}
|
|
65594
65683
|
const grandchildTemplates = this.indexGrandchildTemplates(template, templatePath);
|
|
65595
65684
|
if (assetRedirect) {
|
|
@@ -68503,12 +68592,12 @@ function readNestedTemplate(templatePath) {
|
|
|
68503
68592
|
try {
|
|
68504
68593
|
raw = fs.readFileSync(templatePath, "utf-8");
|
|
68505
68594
|
} catch (err) {
|
|
68506
|
-
throw new Error(`Failed to read nested template at ${templatePath}: ${err
|
|
68595
|
+
throw new Error(`Failed to read nested template at ${displayAssemblyPath(templatePath)}: ${describeFileReadFailure(err, templatePath)}`);
|
|
68507
68596
|
}
|
|
68508
68597
|
try {
|
|
68509
68598
|
return JSON.parse(raw);
|
|
68510
68599
|
} catch (err) {
|
|
68511
|
-
throw new Error(`Failed to parse nested template at ${templatePath}: ${err
|
|
68600
|
+
throw new Error(`Failed to parse nested template at ${displayAssemblyPath(templatePath)}: ${describeFileReadFailure(err, templatePath)}`);
|
|
68512
68601
|
}
|
|
68513
68602
|
}
|
|
68514
68603
|
/**
|
|
@@ -68527,9 +68616,9 @@ function indexNestedChildTemplates(template, templatePath) {
|
|
|
68527
68616
|
if (resource?.Type !== "AWS::CloudFormation::Stack") continue;
|
|
68528
68617
|
const assetPath = resource.Metadata?.["aws:asset:path"];
|
|
68529
68618
|
if (typeof assetPath !== "string" || assetPath.length === 0) continue;
|
|
68530
|
-
if (isAbsoluteCrossPlatform(assetPath)) throw new Error(`Nested stack
|
|
68619
|
+
if (isAbsoluteCrossPlatform(assetPath)) throw new Error(`Nested stack ${displayIdent(logicalId)} has Metadata['aws:asset:path']=${displayAssemblyPath(assetPath)} which is absolute. CDK emits relative asset paths for nested templates; an absolute path indicates the synth output was hand-modified or generated by a non-CDK toolchain. Refusing to load.`);
|
|
68531
68620
|
const resolved = resolveAssemblyPath(dir, assetPath);
|
|
68532
|
-
if (!resolved.contained) throw new Error(`Nested stack
|
|
68621
|
+
if (!resolved.contained) throw new Error(`Nested stack ${displayIdent(logicalId)} has Metadata['aws:asset:path']=${displayAssemblyPath(assetPath)} which ${renderAssemblyPathEscape(resolved, dir)}`);
|
|
68533
68622
|
result[logicalId] = resolved.path;
|
|
68534
68623
|
}
|
|
68535
68624
|
return result;
|
|
@@ -68685,7 +68774,7 @@ async function computeStackDiff(currentState, template, region, stackName, state
|
|
|
68685
68774
|
const tokenParameterNames = new Set(Object.entries(parameters ?? {}).filter(([, value]) => carriesDynamicReference(value)).map(([name]) => name));
|
|
68686
68775
|
for (const name of tokenParameterNames) {
|
|
68687
68776
|
const declaredType = (template.Parameters?.[name])?.Type;
|
|
68688
|
-
if (typeof declaredType === "string" && parameterTypeMayLoseSecretIdentity(declaredType)) logger.warn(`Stack ${
|
|
68777
|
+
if (typeof declaredType === "string" && parameterTypeMayLoseSecretIdentity(declaredType)) logger.warn(`Stack ${displayStackName(stackName)}: parameter ${displayIdent(name)} is declared Type: ${displayIdent(declaredType)} and is fed a secret dynamic reference. 'cdkd deploy' refuses this when the coercion actually destroys the plaintext (a comma-bearing secret in a list-typed parameter) — declare it 'Type: String' — and this diff compares the unresolved reference, shaped by the declared type only where that keeps every part of it a string.`);
|
|
68689
68778
|
}
|
|
68690
68779
|
try {
|
|
68691
68780
|
const userParameters = {};
|
|
@@ -68701,7 +68790,7 @@ async function computeStackDiff(currentState, template, region, stackName, state
|
|
|
68701
68790
|
}
|
|
68702
68791
|
parametersBound = true;
|
|
68703
68792
|
} catch (error) {
|
|
68704
|
-
logger.debug(`Diff parameter binding for stack ${stackName} is partial: ${error instanceof Error ? error.message : String(error)}`);
|
|
68793
|
+
logger.debug(`Diff parameter binding for stack ${displayStackName(stackName)} is partial: ${error instanceof Error ? error.message : String(error)}`);
|
|
68705
68794
|
}
|
|
68706
68795
|
let effectiveTemplate = template;
|
|
68707
68796
|
let conditions;
|
|
@@ -68716,7 +68805,7 @@ async function computeStackDiff(currentState, template, region, stackName, state
|
|
|
68716
68805
|
});
|
|
68717
68806
|
effectiveTemplate = new TemplateParser().filterResourcesByCondition(template, conditions);
|
|
68718
68807
|
} catch (error) {
|
|
68719
|
-
logger.debug(`Diff condition evaluation for stack ${stackName} skipped: ${error instanceof Error ? error.message : String(error)}`);
|
|
68808
|
+
logger.debug(`Diff condition evaluation for stack ${displayStackName(stackName)} skipped: ${error instanceof Error ? error.message : String(error)}`);
|
|
68720
68809
|
}
|
|
68721
68810
|
const resolveFn = (value) => intrinsicResolver.resolve(value, {
|
|
68722
68811
|
template: effectiveTemplate,
|
|
@@ -68929,10 +69018,10 @@ async function buildDiffTree(args) {
|
|
|
68929
69018
|
if (resource?.Type !== "AWS::CloudFormation::Stack") continue;
|
|
68930
69019
|
templateChildIds.add(logicalId);
|
|
68931
69020
|
const childTemplatePath = nestedTemplates[logicalId];
|
|
68932
|
-
if (!childTemplatePath) throw new Error(`Nested template file not found for ${NESTED_STACK_RESOURCE_TYPE}
|
|
69021
|
+
if (!childTemplatePath) throw new Error(`Nested template file not found for ${NESTED_STACK_RESOURCE_TYPE} ${displayIdent(logicalId)} under stack ${displayStackName(stackName)}. Verify the synth output emits Metadata['aws:asset:path'] on this resource (CDK 2.x cdk.NestedStack does so by default), then re-run synth.`);
|
|
68933
69022
|
const childStackName = `${stackName}~${logicalId}`;
|
|
68934
69023
|
const resolvedChildPath = path.resolve(childTemplatePath);
|
|
68935
|
-
if (ancestorTemplatePaths?.has(resolvedChildPath) === true) throw new Error(`Nested stack
|
|
69024
|
+
if (ancestorTemplatePaths?.has(resolvedChildPath) === true) throw new Error(`Nested stack ${displayIdent(logicalId)} under stack ${displayStackName(stackName)} resolves to nested template ${displayAssemblyPath(resolvedChildPath)}, which is already being diffed higher up the same nesting chain. Its Metadata['aws:asset:path'] closes a cycle; CDK emits an acyclic nested template tree, so this indicates the synth output was hand-modified or generated by a non-CDK toolchain. Refusing to diff.`);
|
|
68936
69025
|
const childAncestorTemplatePaths = new Set(ancestorTemplatePaths ?? []).add(resolvedChildPath);
|
|
68937
69026
|
const childTemplate = readNestedTemplate(childTemplatePath);
|
|
68938
69027
|
if (assetRedirect) rewriteTemplateAssetReferences(childTemplate, assetRedirect);
|
|
@@ -69028,7 +69117,7 @@ function collectCcApiRoutes(template, state) {
|
|
|
69028
69117
|
if (!resource) continue;
|
|
69029
69118
|
if (resource.Type === "AWS::CDK::Metadata") continue;
|
|
69030
69119
|
if (resource.Type === "AWS::CloudFormation::Stack") continue;
|
|
69031
|
-
const drops = findActionableSilentDrops(resource.Type, resource.Properties, EMPTY_ALLOW_SET);
|
|
69120
|
+
const drops = findActionableSilentDrops(resource.Type, resource.Properties, EMPTY_ALLOW_SET, state.resources[logicalId]?.properties);
|
|
69032
69121
|
if (drops.length > 0) {
|
|
69033
69122
|
hits.set(logicalId, drops.map((d) => d.property));
|
|
69034
69123
|
continue;
|
|
@@ -69246,7 +69335,7 @@ function renderChangeLines(changes, logFn, ccApiRoutes, adoptedOrphans) {
|
|
|
69246
69335
|
logFn(` [~] ${logicalId} (${change.resourceType})${annotateAdoption(logicalId)}${annotateRouting(logicalId)}`);
|
|
69247
69336
|
if (change.propertyChanges && change.propertyChanges.length > 0) for (const propChange of change.propertyChanges) {
|
|
69248
69337
|
const requiresReplace = propChange.requiresReplacement ? " [requires replacement]" : "";
|
|
69249
|
-
const propagated = propChange.replacementPropagated ? " [replacement propagated]" : "";
|
|
69338
|
+
const propagated = propChange.replacementPropagated ? " [replacement propagated]" : propChange.inPlacePropagated ? " [attribute propagated]" : "";
|
|
69250
69339
|
const indent = " ";
|
|
69251
69340
|
const [oldFiltered, newFiltered] = stripUnchangedValuePair(propChange.oldValue, propChange.newValue);
|
|
69252
69341
|
const oldStr = renderDiffValue(propChange.oldValue, oldFiltered, indent, false);
|
|
@@ -69672,7 +69761,7 @@ function describeFailure(err) {
|
|
|
69672
69761
|
* thing the paragraph above rejects.
|
|
69673
69762
|
*/
|
|
69674
69763
|
function scrubStacksFailedError(failures) {
|
|
69675
|
-
return new ScrubRefusalError(`${failures.length} stack(s) could not be scrubbed: ${failures.map((f) => f.stackName).join(", ")}. Each one's reason was logged as it happened — see the 'Scrub of <stack> failed:' line above for it.`, "SCRUB_STACKS_FAILED");
|
|
69764
|
+
return new ScrubRefusalError(`${failures.length} stack(s) could not be scrubbed: ${failures.map((f) => displayStackName(f.stackName)).join(", ")}. Each one's reason was logged as it happened — see the 'Scrub of <stack> failed:' line above for it.`, "SCRUB_STACKS_FAILED");
|
|
69676
69765
|
}
|
|
69677
69766
|
/**
|
|
69678
69767
|
* Which of `entries` this stack's post-scrub `outputs` bag disagrees with.
|
|
@@ -69751,8 +69840,8 @@ function planExportIndexRepair(entries, stackName, producerRegion, outputs) {
|
|
|
69751
69840
|
*/
|
|
69752
69841
|
function exportIndexIncompleteError(unwritten, unreadable, dryRun) {
|
|
69753
69842
|
const parts = [dryRun ? "no state written (--dry-run)" : "state.json complete"];
|
|
69754
|
-
if (unwritten.length > 0) parts.push(`${unwritten.length} exports index entr${unwritten.length === 1 ? "y" : "ies"} unwritten (${unwritten.map((u) => `${u.shown} in ${u.region}`).join(", ")})`);
|
|
69755
|
-
if (unreadable.length > 0) parts.push(`${unreadable.length} region(s) whose exports index could not be read (${unreadable.map((u) => `${u.region}: ${u.reason}`).join("; ")})`);
|
|
69843
|
+
if (unwritten.length > 0) parts.push(`${unwritten.length} exports index entr${unwritten.length === 1 ? "y" : "ies"} unwritten (${unwritten.map((u) => `${u.shown} in ${displayIdent(u.region)}`).join(", ")})`);
|
|
69844
|
+
if (unreadable.length > 0) parts.push(`${unreadable.length} region(s) whose exports index could not be read (${unreadable.map((u) => `${displayIdent(u.region)}: ${u.reason}`).join("; ")})`);
|
|
69756
69845
|
return new ScrubRefusalError(`${parts.join("; ")}. Re-run the same command once the cause is cleared: each entry is written only while its value differs from the producer's state.outputs, so a re-run writes the remainder and leaves the rest alone.`, "SCRUB_EXPORT_INDEX_INCOMPLETE");
|
|
69757
69846
|
}
|
|
69758
69847
|
/**
|
|
@@ -69983,6 +70072,7 @@ async function scrubCommand(stacks, options) {
|
|
|
69983
70072
|
const indexUnwritten = [];
|
|
69984
70073
|
const indexUnreadable = [];
|
|
69985
70074
|
for (const stack of targetStacks) {
|
|
70075
|
+
const shownStack = displayStackName(stack.stackName);
|
|
69986
70076
|
const stackRegion = stack.region || region;
|
|
69987
70077
|
let scrubbed;
|
|
69988
70078
|
try {
|
|
@@ -69994,7 +70084,7 @@ async function scrubCommand(stacks, options) {
|
|
|
69994
70084
|
});
|
|
69995
70085
|
} catch (err) {
|
|
69996
70086
|
failures.push({ stackName: stack.stackName });
|
|
69997
|
-
logger.error(`Scrub of ${
|
|
70087
|
+
logger.error(`Scrub of ${shownStack} failed: ${describeFailure(err)}`);
|
|
69998
70088
|
if (err instanceof Error && err.stack) logger.debug("Stack trace:", err.stack);
|
|
69999
70089
|
continue;
|
|
70000
70090
|
}
|
|
@@ -70007,8 +70097,8 @@ async function scrubCommand(stacks, options) {
|
|
|
70007
70097
|
const named = (exportName) => {
|
|
70008
70098
|
const shown = scrubbed.exportNameDisplay(exportName);
|
|
70009
70099
|
switch (shown.kind) {
|
|
70010
|
-
case "safe": return
|
|
70011
|
-
case "masked": return `(masked:
|
|
70100
|
+
case "safe": return displayIdent(shown.text);
|
|
70101
|
+
case "masked": return `(masked: ${displayIdent(shown.text)})`;
|
|
70012
70102
|
case "withheld": return "(name withheld: it holds a secret this run recorded)";
|
|
70013
70103
|
}
|
|
70014
70104
|
};
|
|
@@ -70019,14 +70109,14 @@ async function scrubCommand(stacks, options) {
|
|
|
70019
70109
|
});
|
|
70020
70110
|
for (const finding of repair.findings) if (finding.kind === "converge") {
|
|
70021
70111
|
indexConverged++;
|
|
70022
|
-
if (!options.dryRun && unwrittenNames.has(finding.exportName)) logger.warn(`Exports index entry ${named(finding.exportName)} (${stackRegion}) differs from ${
|
|
70112
|
+
if (!options.dryRun && unwrittenNames.has(finding.exportName)) logger.warn(`Exports index entry ${named(finding.exportName)} (${displayIdent(stackRegion)}) differs from ${shownStack}'s state.outputs and could NOT be written — it keeps the value it holds.`);
|
|
70023
70113
|
else {
|
|
70024
70114
|
totalIndexEntriesConverged++;
|
|
70025
|
-
logger.info(`${options.dryRun ? "Would converge" : "Converged"} exports index entry ${named(finding.exportName)} (${stackRegion}) to ${
|
|
70115
|
+
logger.info(`${options.dryRun ? "Would converge" : "Converged"} exports index entry ${named(finding.exportName)} (${displayIdent(stackRegion)}) to ${shownStack}'s state.outputs value.`);
|
|
70026
70116
|
}
|
|
70027
70117
|
} else {
|
|
70028
70118
|
totalIndexEntriesAbsent++;
|
|
70029
|
-
logger.warn(`Exports index entry ${named(finding.exportName)} (${stackRegion}) is published by ${
|
|
70119
|
+
logger.warn(`Exports index entry ${named(finding.exportName)} (${displayIdent(stackRegion)}) is published by ${shownStack}, whose state.outputs has no key of that name — nothing was written for it and it keeps the value it holds. Redeploy ${shownStack} to rewrite the index from its own outputs.`);
|
|
70030
70120
|
}
|
|
70031
70121
|
} catch (err) {
|
|
70032
70122
|
if (err instanceof ScrubIndexInvariantError) throw err;
|
|
@@ -70036,28 +70126,28 @@ async function scrubCommand(stacks, options) {
|
|
|
70036
70126
|
region: stackRegion,
|
|
70037
70127
|
reason
|
|
70038
70128
|
});
|
|
70039
|
-
logger.error(`Exports index for ${stackRegion} could not be read (first seen while scrubbing ${
|
|
70129
|
+
logger.error(`Exports index for ${displayIdent(stackRegion)} could not be read (first seen while scrubbing ${shownStack}): ${reason}`);
|
|
70040
70130
|
}
|
|
70041
70131
|
}
|
|
70042
70132
|
if (scrubbed.recordsChanged > 0) {
|
|
70043
70133
|
totalStacksScrubbed++;
|
|
70044
|
-
logger.info(`${options.dryRun ? "Would scrub" : "Scrubbed"} ${scrubbed.recordsChanged} resource record(s) in ${
|
|
70045
|
-
} else if (scrubbed.secretBearingKeys === 0 && scrubbed.unverifiableReads === 0 && scrubbed.unverifiableLeaves === 0 && indexConverged === 0) logger.info(`No plaintext secrets found in ${
|
|
70134
|
+
logger.info(`${options.dryRun ? "Would scrub" : "Scrubbed"} ${scrubbed.recordsChanged} resource record(s) in ${shownStack}`);
|
|
70135
|
+
} else if (scrubbed.secretBearingKeys === 0 && scrubbed.unverifiableReads === 0 && scrubbed.unverifiableLeaves === 0 && indexConverged === 0) logger.info(`No plaintext secrets found in ${shownStack}`);
|
|
70046
70136
|
if (scrubbed.malformedResources) malformedRecords.push(stack.stackName);
|
|
70047
70137
|
if (scrubbed.malformedOutputs) malformedOutputRecords.push(stack.stackName);
|
|
70048
70138
|
if (scrubbed.malformedOrphans || scrubbed.malformedOrphanRows) malformedOrphanRecords.push(stack.stackName);
|
|
70049
70139
|
if (scrubbed.unverifiableLeaves > 0) {
|
|
70050
70140
|
totalStacksWithUnverifiableLeaves++;
|
|
70051
|
-
logger.warn(`${scrubbed.unverifiableLeaves} scan(s) in ${
|
|
70141
|
+
logger.warn(`${scrubbed.unverifiableLeaves} scan(s) in ${shownStack} were ABANDONED mid-value because a {{resolve:...}} reference could not be resolved (see the warnings above). The resolver stops at the first failing token, so a real secret after it in the same value recorded no needle — this stack is not reported clean. The count is per abandoned SCAN, not per secret: one record can contribute more than once (an output whose Export.Name and Value both abandon), and one abandoned scan can hide several unexamined leaves.`);
|
|
70052
70142
|
}
|
|
70053
70143
|
if (scrubbed.unverifiableProducerRecords > 0) damagedProducerStacks.push(stack.stackName);
|
|
70054
70144
|
if (scrubbed.unverifiableReads > 0) {
|
|
70055
70145
|
totalStacksWithUnverifiableReads++;
|
|
70056
|
-
logger.warn(`${scrubbed.unverifiableReads} cross-stack read(s) in ${
|
|
70146
|
+
logger.warn(`${scrubbed.unverifiableReads} cross-stack read(s) in ${shownStack} could NOT be verified (see the warnings above for which, and why) — so this stack is not reported clean.`);
|
|
70057
70147
|
}
|
|
70058
70148
|
if (scrubbed.secretBearingKeys > 0) {
|
|
70059
70149
|
totalStacksWithUnscrubbableKeys++;
|
|
70060
|
-
logger.warn(`${scrubbed.secretBearingKeys} output KEY(s) in ${
|
|
70150
|
+
logger.warn(`${scrubbed.secretBearingKeys} output KEY(s) in ${shownStack} hold plaintext and CANNOT be scrubbed — rename the Export.Name and redeploy (see the warning above).`);
|
|
70061
70151
|
}
|
|
70062
70152
|
}
|
|
70063
70153
|
for (const [indexRegion, store] of exportIndexStores) {
|
|
@@ -70071,7 +70161,7 @@ async function scrubCommand(stacks, options) {
|
|
|
70071
70161
|
region: indexRegion,
|
|
70072
70162
|
reason
|
|
70073
70163
|
});
|
|
70074
|
-
logger.error(`Exports index for ${indexRegion} could not be read for the coverage report: ${reason}`);
|
|
70164
|
+
logger.error(`Exports index for ${displayIdent(indexRegion)} could not be read for the coverage report: ${reason}`);
|
|
70075
70165
|
continue;
|
|
70076
70166
|
}
|
|
70077
70167
|
if (!entries) continue;
|
|
@@ -70079,7 +70169,7 @@ async function scrubCommand(stacks, options) {
|
|
|
70079
70169
|
const unexamined = [...entries.keys()].filter((name) => !examined.has(name));
|
|
70080
70170
|
if (unexamined.length === 0) continue;
|
|
70081
70171
|
totalIndexEntriesUnexamined += unexamined.length;
|
|
70082
|
-
logger.info(`Exports index (${indexRegion}): ${unexamined.length} entr${unexamined.length === 1 ? "y is" : "ies are"} published by a producer this run did not scrub, so nothing here read ${unexamined.length === 1 ? "its" : "their"} value. Coverage composes across the apps sharing this bucket and region — run each app's own cdkd scrub to reach its entries.`);
|
|
70172
|
+
logger.info(`Exports index (${displayIdent(indexRegion)}): ${unexamined.length} entr${unexamined.length === 1 ? "y is" : "ies are"} published by a producer this run did not scrub, so nothing here read ${unexamined.length === 1 ? "its" : "their"} value. Coverage composes across the apps sharing this bucket and region — run each app's own cdkd scrub to reach its entries.`);
|
|
70083
70173
|
}
|
|
70084
70174
|
if (totalStacksScrubbed === 0 && totalStacksWithUnscrubbableKeys === 0 && totalStacksWithUnverifiableReads === 0 && totalStacksWithUnverifiableLeaves === 0 && totalIndexEntriesConverged === 0 && indexUnwritten.length === 0 && indexUnreadable.length === 0 && malformedRecords.length === 0 && malformedOutputRecords.length === 0 && malformedOrphanRecords.length === 0) {
|
|
70085
70175
|
if (failures.length === 0) {
|
|
@@ -70370,8 +70460,8 @@ var ScrubResolvers = class {
|
|
|
70370
70460
|
* Never the resolved value: nothing has been resolved for this reference, and
|
|
70371
70461
|
* the expression is the same string `state.json` already stores in the clear.
|
|
70372
70462
|
*/
|
|
70373
|
-
function regionAmbiguousScrubSecretError(origin, stackName, secretName, foreignProducerRegions, stackRegion) {
|
|
70374
|
-
return new ScrubRefusalError(`Scrub of ${stackName} cannot re-resolve the secret reference
|
|
70463
|
+
function regionAmbiguousScrubSecretError(origin, stackName, secretName, foreignProducerRegions, stackRegion, secrets) {
|
|
70464
|
+
return new ScrubRefusalError(`Scrub of ${displayStackName(stackName)} cannot re-resolve the secret reference ${maskedIdent(secretName, secrets)} in ${origin}: the reference carries no region of its own, and this stack read across a region boundary (producer region(s) on record: ${foreignProducerRegions.map((r) => displayIdent(r)).join(", ")}), so it may have been resolved in one of those rather than in ${displayIdent(stackRegion)}. A secret of the same name in two regions is two independent values, so scrub would look for the WRONG plaintext — leaving the real one in state while reporting the stack clean, and using the foreign value as a needle that can rewrite an unrelated literal. Refusing instead. Spell the reference as a full ARN, which names its region and is resolved there, then re-run 'cdkd scrub'.`, "SCRUB_SECRET_REGION_AMBIGUOUS");
|
|
70375
70465
|
}
|
|
70376
70466
|
/**
|
|
70377
70467
|
* The refusal a `named-region` reference raises when its OWN region cannot
|
|
@@ -70389,7 +70479,7 @@ function regionAmbiguousScrubSecretError(origin, stackName, secretName, foreignP
|
|
|
70389
70479
|
* into, so a value recorded a moment earlier in this very leaf is covered.
|
|
70390
70480
|
*/
|
|
70391
70481
|
function unresolvableForeignScrubSecretError(origin, stackName, secretName, region, cause, secrets) {
|
|
70392
|
-
return new ScrubRefusalError(`Scrub of ${stackName} could not resolve the secret reference
|
|
70482
|
+
return new ScrubRefusalError(`Scrub of ${displayStackName(stackName)} could not resolve the secret reference ${maskedIdent(secretName, secrets)} in ${origin} in the region its ARN names (${displayIdent(region)}): ${maskSecretsInText(cause instanceof Error ? cause.message : String(cause), secrets)}. Refusing rather than resolving it in the stack's own region, which would look for a different secret's value and report the stack clean over state that still holds the plaintext.`, "SCRUB_CROSS_REGION_SECRET_UNRESOLVED");
|
|
70393
70483
|
}
|
|
70394
70484
|
/**
|
|
70395
70485
|
* The literal that OPENS a dynamic reference. Used as the CHEAP pre-filter that
|
|
@@ -70537,17 +70627,18 @@ function isAssembledSecretReference(leaf, secretTokens) {
|
|
|
70537
70627
|
* together out of a plaintext is not.
|
|
70538
70628
|
*/
|
|
70539
70629
|
async function resolveForeignRegionTokens(leaf, stackName, ctx) {
|
|
70630
|
+
const shownStackName = displayStackName(stackName);
|
|
70540
70631
|
const tokens = dynamicReferenceTokens(leaf);
|
|
70541
70632
|
if (isAssembledSecretReference(leaf, tokens.filter(isSecretReferenceToken))) return leaf;
|
|
70542
70633
|
const verdicts = tokens.map((token) => [token, classifyReplaySecretRegion(token, ctx.stackRegion, ctx.producerRegions)]);
|
|
70543
|
-
for (const [, verdict] of verdicts) if (verdict.kind === "ambiguous") throw regionAmbiguousScrubSecretError(ctx.origin, stackName, verdict.secretName, verdict.foreignProducerRegions, ctx.stackRegion);
|
|
70634
|
+
for (const [, verdict] of verdicts) if (verdict.kind === "ambiguous") throw regionAmbiguousScrubSecretError(ctx.origin, stackName, verdict.secretName, verdict.foreignProducerRegions, ctx.stackRegion, ctx.recordedSecretValues);
|
|
70544
70635
|
if (!verdicts.some(([, verdict]) => verdict.kind === "named-region")) return leaf;
|
|
70545
70636
|
const localTokens = [];
|
|
70546
70637
|
let out = "";
|
|
70547
70638
|
let cursor = 0;
|
|
70548
70639
|
for (const [token, verdict] of verdicts) {
|
|
70549
70640
|
const at = leaf.indexOf(token, cursor);
|
|
70550
|
-
if (at < 0) throw new ScrubRefusalError(`Scrub of ${
|
|
70641
|
+
if (at < 0) throw new ScrubRefusalError(`Scrub of ${shownStackName} could not locate a scanned dynamic reference in ${ctx.origin}, in the value it was scanned from. Refusing rather than resolving it in ${displayIdent(ctx.stackRegion)}, which would be the wrong region for a reference that names another one. This is an internal invariant failure — please report it with the resource type and property path.`, "SCRUB_SECRET_TOKEN_SCAN_MISMATCH");
|
|
70551
70642
|
out += leaf.slice(cursor, at);
|
|
70552
70643
|
if (verdict.kind === "named-region") {
|
|
70553
70644
|
const resolver = ctx.resolvers.forRegion(verdict.region);
|
|
@@ -70568,7 +70659,7 @@ async function resolveForeignRegionTokens(leaf, stackName, ctx) {
|
|
|
70568
70659
|
}
|
|
70569
70660
|
out += leaf.slice(cursor);
|
|
70570
70661
|
const surviving = dynamicReferenceTokens(out);
|
|
70571
|
-
if (surviving.length !== localTokens.length || surviving.some((token, i) => token !== localTokens[i])) throw new ScrubRefusalError(`Scrub of ${
|
|
70662
|
+
if (surviving.length !== localTokens.length || surviving.some((token, i) => token !== localTokens[i])) throw new ScrubRefusalError(`Scrub of ${shownStackName} refused ${ctx.origin}: resolving a cross-region secret reference produced a value that is itself dynamic-reference shaped, which the stack's own resolver would then resolve as if it were a reference of this stack's. Refusing rather than passing it on.`, "SCRUB_SECRET_RESOLUTION_REINTRODUCED_TOKEN");
|
|
70572
70663
|
return out;
|
|
70573
70664
|
}
|
|
70574
70665
|
/**
|
|
@@ -70875,7 +70966,7 @@ function effectiveIntrinsicKey(node) {
|
|
|
70875
70966
|
* can carry one, and the map is the same one this pass records into.
|
|
70876
70967
|
*/
|
|
70877
70968
|
function unresolvableCrossStackReadError(origin, stackName, intrinsic, path, cause, secrets) {
|
|
70878
|
-
return new ScrubRefusalError(`Scrub of ${stackName} could not resolve the ${intrinsic} in ${origin}${path ? ` at ${path}` : ""}: ${maskSecretsInText(cause instanceof Error ? cause.message : String(cause), secrets)}. Refusing rather than continuing: the value that reference carries may be a secret, and scrub would then have no plaintext to look for — reporting the stack clean over state that still holds it. Deploy the producer stack (or correct the reference) and re-run 'cdkd scrub'.`, "SCRUB_CROSS_STACK_READ_UNRESOLVED");
|
|
70969
|
+
return new ScrubRefusalError(`Scrub of ${displayStackName(stackName)} could not resolve the ${intrinsic} in ${origin}${path ? ` at ${maskedIdent(path, secrets)}` : ""}: ${maskSecretsInText(cause instanceof Error ? cause.message : String(cause), secrets)}. Refusing rather than continuing: the value that reference carries may be a secret, and scrub would then have no plaintext to look for — reporting the stack clean over state that still holds it. Deploy the producer stack (or correct the reference) and re-run 'cdkd scrub'.`, "SCRUB_CROSS_STACK_READ_UNRESOLVED");
|
|
70879
70970
|
}
|
|
70880
70971
|
/**
|
|
70881
70972
|
* The two sentences the plaintext-producer refusal is built from: what the
|
|
@@ -70919,8 +71010,10 @@ function unresolvableCrossStackReadError(origin, stackName, intrinsic, path, cau
|
|
|
70919
71010
|
function scrubRefusalWording(verdict, loggedExportKey, loggedProducerStack, loggedVia) {
|
|
70920
71011
|
const chain = dedupePreservingOrder(loggedVia, "first");
|
|
70921
71012
|
const chainRoot = chain[chain.length - 1];
|
|
70922
|
-
const
|
|
70923
|
-
const
|
|
71013
|
+
const shownKey = displayIdent(loggedExportKey);
|
|
71014
|
+
const shownRoot = chainRoot === void 0 ? void 0 : displayStackName(chainRoot);
|
|
71015
|
+
const through = chain.length > 1 ? ` (through ${chain.slice(0, -1).map((s) => displayStackName(s)).join(", ")})` : "";
|
|
71016
|
+
const templateClaim = verdict.kind === "declared" ? `declares ${shownKey} from a {{resolve:...}} expression` : verdict.kind === "chained" ? chainRoot !== void 0 ? `publishes ${shownKey} by RE-EXPORTING a value that ${shownRoot} declares from a {{resolve:...}} expression${through}` : `publishes ${shownKey} by RE-EXPORTING a value another stack of this app declares from a {{resolve:...}} expression` : chainRoot !== void 0 ? `publishes at least one output that RE-EXPORTS a value ${shownRoot} declares from a {{resolve:...}} expression${through} (this run could not match ${shownKey} to a declared output, so it cannot say which)` : `publishes at least one output from a {{resolve:...}} expression (this run could not match ${shownKey} to a declared output, so it cannot say which)`;
|
|
70924
71017
|
const scrubOrder = dedupePreservingOrder([...chain].reverse().concat(loggedProducerStack), "last");
|
|
70925
71018
|
const remedyCommands = scrubOrder.map((name) => `Scrub with: ${pasteableCommand("cdkd scrub", [{
|
|
70926
71019
|
value: name,
|
|
@@ -70993,7 +71086,7 @@ function plaintextProducerCrossStackReadError(origin, stackName, intrinsic, path
|
|
|
70993
71086
|
const loggedExportKey = maskSecretsInText(exportKey, secrets);
|
|
70994
71087
|
const loggedProducerStack = maskSecretsInText(producerStack, secrets);
|
|
70995
71088
|
const { templateClaim, remedy, remedyCommands } = scrubRefusalWording(verdict, loggedExportKey, loggedProducerStack, verdict.via.map((s) => maskSecretsInText(s, secrets)));
|
|
70996
|
-
return new ScrubRefusalError(`Scrub of ${stackName} resolved the ${intrinsic} in ${origin}${path ? ` at ${path}` : ""} to a PLAINTEXT value: the producer stack
|
|
71089
|
+
return new ScrubRefusalError(`Scrub of ${displayStackName(stackName)} resolved the ${intrinsic} in ${origin}${path ? ` at ${maskedIdent(path, secrets)}` : ""} to a PLAINTEXT value: the producer stack ${displayStackName(loggedProducerStack)} ${templateClaim}, but its own state still stores the resolved plaintext rather than that expression. scrub has no expression to write in this stack's place, so it cannot redact the imported secret and must not report this stack clean. ${remedy}, then re-run scrub for this stack — the read will then return the expression and this stack is scrubbed normally.\n${remedyCommands.join("\n")}\nThen re-run: ${pasteableCommand("cdkd scrub", [{
|
|
70997
71090
|
value: stackName,
|
|
70998
71091
|
hole: "stack",
|
|
70999
71092
|
opts: { patternMatched: true }
|
|
@@ -71445,6 +71538,16 @@ function isNamelessDynamicReferenceFailure(err) {
|
|
|
71445
71538
|
return isNamelessDynamicReferenceError(err);
|
|
71446
71539
|
}
|
|
71447
71540
|
/**
|
|
71541
|
+
* An assembly-chosen NAME (a logical id, a property or output name, a property
|
|
71542
|
+
* path, a secret reference's name) rendered into scrub's prose: MASKED FIRST,
|
|
71543
|
+
* then bounded (go-to-k/cdkd#3638). `displayIdent` JSON-escapes, blanks
|
|
71544
|
+
* non-ASCII and cuts at 255, any of which would stop a recorded plaintext
|
|
71545
|
+
* embedded in the name from matching a mask that ran over the rendered text.
|
|
71546
|
+
*/
|
|
71547
|
+
function maskedIdent(value, secrets) {
|
|
71548
|
+
return displayIdent(maskSecretsInText(value, secrets));
|
|
71549
|
+
}
|
|
71550
|
+
/**
|
|
71448
71551
|
* The per-record line each counting site prints. Deliberately ONE SHORT
|
|
71449
71552
|
* SENTENCE, and that is a fix rather than a style choice: the first cut emitted
|
|
71450
71553
|
* a ~440-character paragraph PER RECORD at default verbosity, and the arm it
|
|
@@ -71459,11 +71562,9 @@ function isNamelessDynamicReferenceFailure(err) {
|
|
|
71459
71562
|
* it through `maskSecretsInText`, and a resolver error echoes what it was
|
|
71460
71563
|
* handed — which, after `pinCrossRegionSecrets`, can be a foreign plaintext.
|
|
71461
71564
|
*
|
|
71462
|
-
*
|
|
71463
|
-
*
|
|
71464
|
-
*
|
|
71465
|
-
* it, so it cannot JOIN a split needle (the go-to-k/cdkd#2874 direction) but it
|
|
71466
|
-
* can BREAK one, and it leaves `U+200B`-`U+200D` / `U+FEFF` untouched. A secret
|
|
71565
|
+
* The `subject` the call sites pass renders each name through
|
|
71566
|
+
* {@link maskedIdent} — masked, then bounded — so bounding cannot break a needle.
|
|
71567
|
+
* RESIDUAL: the mask sees only what this run has recorded SO FAR, and a secret
|
|
71467
71568
|
* would have to sit inside a template logical id or Outputs key to be reachable,
|
|
71468
71569
|
* which is why `secretSafeKeyDisplay` is not used here — that one is for RESOLVED
|
|
71469
71570
|
* state-bag keys. Recorded rather than closed: go-to-k/cdkd#3178 security review.
|
|
@@ -71850,6 +71951,7 @@ var SharedEntriesSecrets = class extends Map {
|
|
|
71850
71951
|
*/
|
|
71851
71952
|
function makeCrossStackPrePass(deps) {
|
|
71852
71953
|
const { stackName, resolver, producerTemplates, findings, logger } = deps;
|
|
71954
|
+
const shownStackName = displayStackName(stackName);
|
|
71853
71955
|
const exportOwners = buildExportOwnerIndex(producerTemplates);
|
|
71854
71956
|
const verdicts = /* @__PURE__ */ new Map();
|
|
71855
71957
|
/**
|
|
@@ -72004,26 +72106,27 @@ function makeCrossStackPrePass(deps) {
|
|
|
72004
72106
|
*/
|
|
72005
72107
|
const storedProducerValue = async (producer, backend, nodeCanRefuse) => {
|
|
72006
72108
|
if (!backend) return void 0;
|
|
72109
|
+
const shownProducer = displayStackName(maskSecretsInText(producer.stack, secrets));
|
|
72007
72110
|
let loaded;
|
|
72008
72111
|
try {
|
|
72009
72112
|
loaded = await backend.getState(producer.stack, producer.region);
|
|
72010
72113
|
} catch (err) {
|
|
72011
|
-
logger.debug(`Scrub of ${
|
|
72114
|
+
logger.debug(`Scrub of ${shownStackName}: could not re-read producer ${shownProducer} (${displayIdent(producer.region)}) to classify its stored value: ${maskSecretsInText(err instanceof Error ? err.message : String(err), secrets)}`);
|
|
72012
72115
|
return;
|
|
72013
72116
|
}
|
|
72014
72117
|
const outputs = loaded?.state?.outputs;
|
|
72015
72118
|
if (outputs !== void 0 && !isReadableBag(outputs)) {
|
|
72016
72119
|
if (!nodeCanRefuse) {
|
|
72017
|
-
logger.debug(`Scrub of ${
|
|
72120
|
+
logger.debug(`Scrub of ${shownStackName}: producer ${shownProducer} (${displayIdent(producer.region)}) has no readable 'outputs' map, and this position cannot refuse.`);
|
|
72018
72121
|
return;
|
|
72019
72122
|
}
|
|
72020
72123
|
const seenKey = producerRecordKey(producer.stack, producer.region);
|
|
72021
72124
|
if (!warnedDamagedProducers.has(seenKey)) {
|
|
72022
72125
|
warnedDamagedProducers.add(seenKey);
|
|
72023
|
-
const detail = `the stored value of producer
|
|
72126
|
+
const detail = `the stored value of producer ${shownProducer} (${displayIdent(producer.region)}), whose 'outputs' map cannot be read`;
|
|
72024
72127
|
findings.unverifiable.push(detail);
|
|
72025
72128
|
findings.damagedProducerRecords.push(detail);
|
|
72026
|
-
logger.warn(`Scrub of ${
|
|
72129
|
+
logger.warn(`Scrub of ${shownStackName}: producer ${shownProducer} (${displayIdent(producer.region)}) has no readable 'outputs' map, so its stored value could NOT be classified — this run cannot tell whether it still holds plaintext for the value ${shownStackName} imports from it. ${shownStackName} is scrubbed for everything else. Repair that record and scrub it first.`);
|
|
72027
72130
|
}
|
|
72028
72131
|
return;
|
|
72029
72132
|
}
|
|
@@ -72037,60 +72140,60 @@ function makeCrossStackPrePass(deps) {
|
|
|
72037
72140
|
recordedImports: [],
|
|
72038
72141
|
recordedOutputReads: []
|
|
72039
72142
|
};
|
|
72040
|
-
const where = `${key} in ${origin}${path ? ` at ${path}` : ""}`;
|
|
72143
|
+
const where = `${key} in ${origin}${path ? ` at ${maskedIdent(path, secrets)}` : ""}`;
|
|
72041
72144
|
try {
|
|
72042
72145
|
await resolver.resolve({ [key]: node[key] }, probe);
|
|
72043
72146
|
} catch (err) {
|
|
72044
72147
|
if (!nodeCanRefuse) {
|
|
72045
|
-
logger.debug(`Scrub of ${
|
|
72148
|
+
logger.debug(`Scrub of ${shownStackName}: ${where} could not be resolved, and this position cannot refuse: ${maskSecretsInText(err instanceof Error ? err.message : String(err), secrets)}`);
|
|
72046
72149
|
return;
|
|
72047
72150
|
}
|
|
72048
72151
|
if (isByDesignRefusal(err)) {
|
|
72049
72152
|
const detail = `${where}: ${maskSecretsInText(err instanceof Error ? err.message : String(err), secrets)}`;
|
|
72050
72153
|
findings.unverifiable.push(detail);
|
|
72051
|
-
logger.warn(`Scrub of ${
|
|
72154
|
+
logger.warn(`Scrub of ${shownStackName} cannot verify ${detail} — cdkd declines this read by design, so no re-run can change it. The rest of the stack is still scrubbed; this stack is NOT reported clean.`);
|
|
72052
72155
|
return;
|
|
72053
72156
|
}
|
|
72054
72157
|
if (isMalformedProducerRefusal(err)) {
|
|
72055
72158
|
const detail = `${where}: ${maskSecretsInText(err instanceof Error ? err.message : String(err), secrets)}`;
|
|
72056
72159
|
findings.unverifiable.push(detail);
|
|
72057
72160
|
findings.damagedProducerRecords.push(detail);
|
|
72058
|
-
logger.warn(`Scrub of ${
|
|
72161
|
+
logger.warn(`Scrub of ${shownStackName} cannot verify ${detail} — the PRODUCER's state record is malformed or truncated, so this run cannot tell whether that producer still holds the plaintext. The rest of the stack is still scrubbed; this stack is NOT reported clean. Repair the producer's record and scrub it first, then re-run.`);
|
|
72059
72162
|
return;
|
|
72060
72163
|
}
|
|
72061
72164
|
throw unresolvableCrossStackReadError(origin, stackName, key, path, err, secrets);
|
|
72062
72165
|
}
|
|
72063
72166
|
const producer = recordedProducer(key, probe);
|
|
72064
72167
|
if (!producer) {
|
|
72065
|
-
logger.debug(`Scrub of ${
|
|
72168
|
+
logger.debug(`Scrub of ${shownStackName}: ${where} resolved, but the resolver recorded no cdkd cross-stack read for it — the value came from a CloudFormation fallback or a cross-account arm that records nothing, so scrub cannot name a producer to classify. Not classified as a plaintext producer.`);
|
|
72066
72169
|
return;
|
|
72067
72170
|
}
|
|
72068
|
-
const loggedKey = maskSecretsInText(producer.key, secrets);
|
|
72069
|
-
const loggedStack = maskSecretsInText(producer.stack, secrets);
|
|
72171
|
+
const loggedKey = displayIdent(maskSecretsInText(producer.key, secrets));
|
|
72172
|
+
const loggedStack = displayStackName(maskSecretsInText(producer.stack, secrets));
|
|
72070
72173
|
if (!producerTemplates.has(producer.stack)) {
|
|
72071
|
-
logger.debug(`Scrub of ${
|
|
72174
|
+
logger.debug(`Scrub of ${shownStackName}: ${where} resolved through producer ${loggedStack} (${displayIdent(producer.region)}), which is not a stack of this app — scrub has no template to classify export ${loggedKey} with. Not classified as a plaintext producer.`);
|
|
72072
72175
|
return;
|
|
72073
72176
|
}
|
|
72074
72177
|
const verdict = secretExpressionVerdict(producer.stack, producer.key);
|
|
72075
72178
|
if (verdict.kind === "no") {
|
|
72076
|
-
logger.debug(`Scrub of ${
|
|
72179
|
+
logger.debug(`Scrub of ${shownStackName}: ${where} resolved through producer ${loggedStack}, whose template declares no {{resolve:...}} expression for ${loggedKey} and no re-export chain reaching one. Not classified as a plaintext producer.`);
|
|
72077
72180
|
return;
|
|
72078
72181
|
}
|
|
72079
72182
|
const stored = await storedProducerValue(producer, context.stateBackend, nodeCanRefuse);
|
|
72080
72183
|
if (!stored) {
|
|
72081
|
-
logger.debug(`Scrub of ${
|
|
72184
|
+
logger.debug(`Scrub of ${shownStackName}: ${where} resolved through producer ${loggedStack} (${displayIdent(producer.region)}), whose state record could not be read or does not carry the key ${loggedKey} — cannot classify, so this is not classified as a plaintext producer.`);
|
|
72082
72185
|
return;
|
|
72083
72186
|
}
|
|
72084
72187
|
if (carriesDynamicReference(stored.stored)) {
|
|
72085
|
-
logger.debug(`Scrub of ${
|
|
72188
|
+
logger.debug(`Scrub of ${shownStackName}: ${where} resolved through producer ${loggedStack}, whose stored value for ${loggedKey} already carries a {{resolve:...}} expression — the producer is scrubbed and there is nothing wrong with this read.`);
|
|
72086
72189
|
return;
|
|
72087
72190
|
}
|
|
72088
72191
|
if (storedValueCarriesNoPlaintext(stored.stored)) {
|
|
72089
|
-
logger.debug(`Scrub of ${
|
|
72192
|
+
logger.debug(`Scrub of ${shownStackName}: ${where} resolved through producer ${loggedStack}, whose stored value for that key carries no text — nothing to redact, so this is not classified as a plaintext producer.`);
|
|
72090
72193
|
return;
|
|
72091
72194
|
}
|
|
72092
72195
|
if (!nodeCanRefuse) {
|
|
72093
|
-
logger.debug(`Scrub of ${
|
|
72196
|
+
logger.debug(`Scrub of ${shownStackName}: ${where} resolved to a plaintext from unscrubbed producer ${loggedStack}, and this position cannot refuse.`);
|
|
72094
72197
|
return;
|
|
72095
72198
|
}
|
|
72096
72199
|
throw plaintextProducerCrossStackReadError(origin, stackName, key, path, producer.stack, producer.key, verdict, secrets);
|
|
@@ -72147,6 +72250,7 @@ function makeCrossStackPrePass(deps) {
|
|
|
72147
72250
|
*/
|
|
72148
72251
|
async function scrubStack(stack, region, stateBackend, lockManager, opts) {
|
|
72149
72252
|
const { logger } = opts;
|
|
72253
|
+
const shownStack = displayStackName(stack.stackName);
|
|
72150
72254
|
const acquired = !opts.dryRun;
|
|
72151
72255
|
if (acquired) await lockManager.acquireLockWithRetry(stack.stackName, region, void 0, "scrub");
|
|
72152
72256
|
const perResourceSecrets = /* @__PURE__ */ new Map();
|
|
@@ -72232,7 +72336,7 @@ async function scrubStack(stack, region, stateBackend, lockManager, opts) {
|
|
|
72232
72336
|
try {
|
|
72233
72337
|
const loaded = await stateBackend.getState(stack.stackName, region);
|
|
72234
72338
|
if (!loaded) {
|
|
72235
|
-
logger.debug(`No state for ${
|
|
72339
|
+
logger.debug(`No state for ${shownStack} (${displayIdent(region)}) — skipping`);
|
|
72236
72340
|
return {
|
|
72237
72341
|
recordsChanged: 0,
|
|
72238
72342
|
secretsFound: 0,
|
|
@@ -72285,7 +72389,7 @@ async function scrubStack(stack, region, stateBackend, lockManager, opts) {
|
|
|
72285
72389
|
try {
|
|
72286
72390
|
parameters = await resolver.resolveParameters(stack.template);
|
|
72287
72391
|
} catch (err) {
|
|
72288
|
-
logger.debug(`Parameter resolution skipped for ${
|
|
72392
|
+
logger.debug(`Parameter resolution skipped for ${shownStack}: ${maskSecretsInText(err instanceof Error ? err.message : String(err), outputSecrets)}`);
|
|
72289
72393
|
}
|
|
72290
72394
|
const resolverStateBackend = memoizeCrossStackStateReads(stateBackend);
|
|
72291
72395
|
const resolverContext = (recordedSecretValues) => ({
|
|
@@ -72309,7 +72413,7 @@ async function scrubStack(stack, region, stateBackend, lockManager, opts) {
|
|
|
72309
72413
|
try {
|
|
72310
72414
|
conditions = await resolver.evaluateConditions(resolverContext(outputSecrets));
|
|
72311
72415
|
} catch (err) {
|
|
72312
|
-
logger.debug(`Condition evaluation skipped for ${
|
|
72416
|
+
logger.debug(`Condition evaluation skipped for ${shownStack}: ${maskSecretsInText(err instanceof Error ? err.message : String(err), outputSecrets)}`);
|
|
72313
72417
|
}
|
|
72314
72418
|
const templateResources = stack.template.Resources ?? {};
|
|
72315
72419
|
const templateOutputs = stack.template.Outputs ?? {};
|
|
@@ -72329,10 +72433,10 @@ async function scrubStack(stack, region, stateBackend, lockManager, opts) {
|
|
|
72329
72433
|
producerRegions,
|
|
72330
72434
|
resolvers,
|
|
72331
72435
|
recordedSecretValues,
|
|
72332
|
-
origin: `resource
|
|
72436
|
+
origin: `resource ${maskedIdent(logicalId, recordedSecretValues)}`
|
|
72333
72437
|
});
|
|
72334
72438
|
const resourceContext = resolverContext(recordedSecretValues);
|
|
72335
|
-
await resolveCrossStackReads(resolveInput, resourceContext, `resource
|
|
72439
|
+
await resolveCrossStackReads(resolveInput, resourceContext, `resource ${maskedIdent(logicalId, recordedSecretValues)}`);
|
|
72336
72440
|
const bagKeys = resolveInput !== null && typeof resolveInput === "object" && !Array.isArray(resolveInput) ? Object.keys(resolveInput) : void 0;
|
|
72337
72441
|
const intrinsicShapedBag = bagKeys?.some((k) => RESOLVER_DISPATCH_KEYS.has(k)) ?? false;
|
|
72338
72442
|
const resolveUnits = bagKeys && !intrinsicShapedBag ? Object.entries(resolveInput) : [["", resolveInput]];
|
|
@@ -72343,16 +72447,16 @@ async function scrubStack(stack, region, stateBackend, lockManager, opts) {
|
|
|
72343
72447
|
...resourceContext,
|
|
72344
72448
|
abandonedResolutions: abandoned
|
|
72345
72449
|
});
|
|
72346
|
-
reportAbandonedBag(abandoned, propertyName ? `resource
|
|
72450
|
+
reportAbandonedBag(abandoned, propertyName ? `resource ${maskedIdent(logicalId, recordedSecretValues)} property ${maskedIdent(propertyName, recordedSecretValues)}` : `resource ${maskedIdent(logicalId, recordedSecretValues)}`, recordedSecretValues, `${maskedIdent(logicalId, recordedSecretValues)}${propertyName ? `.${maskedIdent(propertyName, recordedSecretValues)}` : ""}`);
|
|
72347
72451
|
} catch (err) {
|
|
72348
72452
|
if (isRegionAmbiguousRefusal(err) || isNamelessDynamicReferenceFailure(err)) throw err;
|
|
72349
72453
|
const leafVerdict = abandonedScanVerdict(propertyValue, err);
|
|
72350
72454
|
if (leafVerdict !== "silent") {
|
|
72351
72455
|
if (leafVerdict === "count") unverifiableLeaves++;
|
|
72352
72456
|
else ungateableAbandonedScans++;
|
|
72353
|
-
logger.warn(maskSecretsInText(abandonedScanWarning(propertyName ? `resource
|
|
72457
|
+
logger.warn(maskSecretsInText(abandonedScanWarning(propertyName ? `resource ${maskedIdent(logicalId, recordedSecretValues)} property ${maskedIdent(propertyName, recordedSecretValues)}` : `resource ${maskedIdent(logicalId, recordedSecretValues)}`, leafVerdict), recordedSecretValues));
|
|
72354
72458
|
}
|
|
72355
|
-
logger.debug(maskSecretsInText(`Resolution of ${
|
|
72459
|
+
logger.debug(maskSecretsInText(`Resolution of ${maskedIdent(logicalId, recordedSecretValues)}${propertyName ? `.${maskedIdent(propertyName, recordedSecretValues)}` : ""} during scrub was partial: ${err instanceof Error ? err.message : String(err)}`, recordedSecretValues));
|
|
72356
72460
|
}
|
|
72357
72461
|
}
|
|
72358
72462
|
perResourceTemplateProps.set(logicalId, templateResource.Properties);
|
|
@@ -72369,7 +72473,7 @@ async function scrubStack(stack, region, stateBackend, lockManager, opts) {
|
|
|
72369
72473
|
producerRegions,
|
|
72370
72474
|
resolvers,
|
|
72371
72475
|
recordedSecretValues,
|
|
72372
|
-
origin: `orphan record
|
|
72476
|
+
origin: `orphan record ${maskedIdent(record.logicalId, recordedSecretValues)}`
|
|
72373
72477
|
});
|
|
72374
72478
|
const orphanContext = resolverContext(recordedSecretValues);
|
|
72375
72479
|
for (const [bagName, bagValue] of Object.entries(resolveInput)) {
|
|
@@ -72379,16 +72483,16 @@ async function scrubStack(stack, region, stateBackend, lockManager, opts) {
|
|
|
72379
72483
|
...orphanContext,
|
|
72380
72484
|
abandonedResolutions: abandoned
|
|
72381
72485
|
});
|
|
72382
|
-
reportAbandonedBag(abandoned, `orphan record
|
|
72486
|
+
reportAbandonedBag(abandoned, `orphan record ${maskedIdent(record.logicalId, recordedSecretValues)} ${bagName}`, recordedSecretValues, `orphan record ${maskedIdent(record.logicalId, recordedSecretValues)} ${bagName}`);
|
|
72383
72487
|
} catch (err) {
|
|
72384
72488
|
if (isRegionAmbiguousRefusal(err) || isNamelessDynamicReferenceFailure(err)) throw err;
|
|
72385
72489
|
const leafVerdict = abandonedScanVerdict(bagValue, err);
|
|
72386
72490
|
if (leafVerdict !== "silent") {
|
|
72387
72491
|
if (leafVerdict === "count") unverifiableLeaves++;
|
|
72388
72492
|
else ungateableAbandonedScans++;
|
|
72389
|
-
logger.warn(maskSecretsInText(abandonedScanWarning(`orphan record
|
|
72493
|
+
logger.warn(maskSecretsInText(abandonedScanWarning(`orphan record ${maskedIdent(record.logicalId, recordedSecretValues)} ${bagName}`, leafVerdict), recordedSecretValues));
|
|
72390
72494
|
}
|
|
72391
|
-
logger.debug(maskSecretsInText(`Resolution of orphan record ${
|
|
72495
|
+
logger.debug(maskSecretsInText(`Resolution of orphan record ${maskedIdent(record.logicalId, recordedSecretValues)} ${bagName} during scrub was partial: ${err instanceof Error ? err.message : String(err)}`, recordedSecretValues));
|
|
72392
72496
|
}
|
|
72393
72497
|
}
|
|
72394
72498
|
}
|
|
@@ -72404,10 +72508,10 @@ async function scrubStack(stack, region, stateBackend, lockManager, opts) {
|
|
|
72404
72508
|
producerRegions,
|
|
72405
72509
|
resolvers,
|
|
72406
72510
|
recordedSecretValues: nameSecrets,
|
|
72407
|
-
origin: `Export.Name of output
|
|
72511
|
+
origin: `Export.Name of output ${maskedIdent(name, nameSecrets)}`
|
|
72408
72512
|
});
|
|
72409
72513
|
const nameContext = resolverContext(nameSecrets);
|
|
72410
|
-
await resolveCrossStackReads(nameSource, nameContext, `Export.Name of output
|
|
72514
|
+
await resolveCrossStackReads(nameSource, nameContext, `Export.Name of output ${maskedIdent(name, nameSecrets)}`, { canRefuse: !isOutputSuppressed(name, output, conditions, state.outputs ?? {}) });
|
|
72411
72515
|
try {
|
|
72412
72516
|
exportName = await resolver.resolve(nameSource, nameContext);
|
|
72413
72517
|
} catch (err) {
|
|
@@ -72416,14 +72520,14 @@ async function scrubStack(stack, region, stateBackend, lockManager, opts) {
|
|
|
72416
72520
|
if (leafVerdict !== "silent") {
|
|
72417
72521
|
if (leafVerdict === "count") unverifiableLeaves++;
|
|
72418
72522
|
else ungateableAbandonedScans++;
|
|
72419
|
-
logger.warn(maskSecretsInText(abandonedScanWarning(`the Export.Name of output
|
|
72523
|
+
logger.warn(maskSecretsInText(abandonedScanWarning(`the Export.Name of output ${maskedIdent(name, outputSecrets)}`, leafVerdict), outputSecrets));
|
|
72420
72524
|
}
|
|
72421
72525
|
nameFailed = true;
|
|
72422
72526
|
nameError = err;
|
|
72423
72527
|
}
|
|
72424
72528
|
if (nameFailed) {
|
|
72425
72529
|
outputsSourceUntrusted = true;
|
|
72426
|
-
logger.warn(`Export.Name of output ${name} could not be resolved during scrub (${maskSecretsInText(nameError instanceof Error ? nameError.message : String(nameError), outputSecrets)}) — redacting this stack's outputs by value match instead of by template position, since state may be keyed under a name this run cannot reproduce.`);
|
|
72530
|
+
logger.warn(`Export.Name of output ${maskedIdent(name, outputSecrets)} could not be resolved during scrub (${maskSecretsInText(nameError instanceof Error ? nameError.message : String(nameError), outputSecrets)}) — redacting this stack's outputs by value match instead of by template position, since state may be keyed under a name this run cannot reproduce.`);
|
|
72427
72531
|
}
|
|
72428
72532
|
}
|
|
72429
72533
|
if (declaredExportName !== void 0 && typeof exportName !== "string") outputsSourceUntrusted = true;
|
|
@@ -72431,7 +72535,7 @@ async function scrubStack(stack, region, stateBackend, lockManager, opts) {
|
|
|
72431
72535
|
if (typeof exportName === "string" && !exportNameUnresolved) accountedOutputKeys.add(exportName);
|
|
72432
72536
|
if (exportNameUnresolved) {
|
|
72433
72537
|
outputsSourceUntrusted = true;
|
|
72434
|
-
logger.warn(`Export.Name of output ${name} did not fully resolve during scrub — redacting this stack's outputs by value match instead of by template position, since state may be keyed under a name this run cannot reproduce.`);
|
|
72538
|
+
logger.warn(`Export.Name of output ${maskedIdent(name, outputSecrets)} did not fully resolve during scrub — redacting this stack's outputs by value match instead of by template position, since state may be keyed under a name this run cannot reproduce.`);
|
|
72435
72539
|
} else if (typeof exportName === "string" && isExportAliasCollision(exportName, name, declaredOutputNames)) {
|
|
72436
72540
|
ambiguousKeys.add(exportName);
|
|
72437
72541
|
collisions.push([name, exportName]);
|
|
@@ -72448,26 +72552,26 @@ async function scrubStack(stack, region, stateBackend, lockManager, opts) {
|
|
|
72448
72552
|
producerRegions,
|
|
72449
72553
|
resolvers,
|
|
72450
72554
|
recordedSecretValues: outputSecrets,
|
|
72451
|
-
origin: `output
|
|
72555
|
+
origin: `output ${maskedIdent(name, outputSecrets)}`
|
|
72452
72556
|
});
|
|
72453
72557
|
const valueContext = resolverContext(outputSecrets);
|
|
72454
|
-
await resolveCrossStackReads(valueSource, valueContext, `output
|
|
72558
|
+
await resolveCrossStackReads(valueSource, valueContext, `output ${maskedIdent(name, outputSecrets)}`, { canRefuse: !isOutputSuppressed(name, output, conditions, state.outputs ?? {}) });
|
|
72455
72559
|
const abandonedOutput = [];
|
|
72456
72560
|
try {
|
|
72457
72561
|
await resolver.resolve(valueSource, {
|
|
72458
72562
|
...valueContext,
|
|
72459
72563
|
abandonedResolutions: abandonedOutput
|
|
72460
72564
|
});
|
|
72461
|
-
reportAbandonedBag(abandonedOutput, `output
|
|
72565
|
+
reportAbandonedBag(abandonedOutput, `output ${maskedIdent(name, outputSecrets)}`, outputSecrets, `output ${maskedIdent(name, outputSecrets)}`);
|
|
72462
72566
|
} catch (err) {
|
|
72463
72567
|
if (isRegionAmbiguousRefusal(err) || isNamelessDynamicReferenceFailure(err)) throw err;
|
|
72464
72568
|
const leafVerdict = abandonedScanVerdict(valueSource, err);
|
|
72465
72569
|
if (leafVerdict !== "silent") {
|
|
72466
72570
|
if (leafVerdict === "count") unverifiableLeaves++;
|
|
72467
72571
|
else ungateableAbandonedScans++;
|
|
72468
|
-
logger.warn(maskSecretsInText(abandonedScanWarning(`output
|
|
72572
|
+
logger.warn(maskSecretsInText(abandonedScanWarning(`output ${maskedIdent(name, outputSecrets)}`, leafVerdict), outputSecrets));
|
|
72469
72573
|
}
|
|
72470
|
-
logger.debug(`Resolution of output ${name} during scrub was partial: ${maskSecretsInText(err instanceof Error ? err.message : String(err), outputSecrets)}`);
|
|
72574
|
+
logger.debug(`Resolution of output ${maskedIdent(name, outputSecrets)} during scrub was partial: ${maskSecretsInText(err instanceof Error ? err.message : String(err), outputSecrets)}`);
|
|
72471
72575
|
}
|
|
72472
72576
|
}
|
|
72473
72577
|
});
|
|
@@ -72580,7 +72684,7 @@ async function scrubStack(stack, region, stateBackend, lockManager, opts) {
|
|
|
72580
72684
|
throw maskSecretsInError(err, allRecordedSecrets(outputSecrets, perResourceSecrets, orphanSecrets));
|
|
72581
72685
|
} finally {
|
|
72582
72686
|
if (acquired) await lockManager.releaseLock(stack.stackName, region).catch((err) => {
|
|
72583
|
-
logger.warn(`Failed to release lock for ${
|
|
72687
|
+
logger.warn(`Failed to release lock for ${shownStack}: ${err instanceof Error ? err.message : String(err)}`);
|
|
72584
72688
|
});
|
|
72585
72689
|
}
|
|
72586
72690
|
}
|
|
@@ -86366,7 +86470,7 @@ var AttributeFetcher = class {
|
|
|
86366
86470
|
const orphan = this.orphans[orphanLogicalId];
|
|
86367
86471
|
const bag = orphan.attributes;
|
|
86368
86472
|
if (bag !== void 0 && !isReadableBag(bag)) {
|
|
86369
|
-
this.logger.warn(`--force: state.attributes of
|
|
86473
|
+
this.logger.warn(`--force: state.attributes of ${displayIdent(orphanLogicalId)} is not a readable map, so it is not consulted for ${displayIdent(attribute)}; leaving the original intrinsic in place.`);
|
|
86370
86474
|
return {
|
|
86371
86475
|
ok: false,
|
|
86372
86476
|
reason: `${reason}; the state.attributes cache is not a readable map`
|
|
@@ -88372,7 +88476,7 @@ async function resolveImportedProperties(stackState, template, region, stateBack
|
|
|
88372
88476
|
if (divergentParameters !== void 0 && divergentParameters.size > 0) try {
|
|
88373
88477
|
parameterTaint = computeParameterTaint(template, new Map(entries.map(([logicalId, resource]) => [logicalId, resource.properties])), divergentParameters);
|
|
88374
88478
|
} catch (err) {
|
|
88375
|
-
logger.debug(`observed-baseline parameter-dependence walk failed for
|
|
88479
|
+
logger.debug(`observed-baseline parameter-dependence walk failed for ${displayStackName(stackState.stackName)}: ${err instanceof Error ? err.name : typeof err} — refusing every baseline in the stack fail-closed.`);
|
|
88376
88480
|
const all = new Set(entries.map(([logicalId]) => logicalId));
|
|
88377
88481
|
parameterTaint = {
|
|
88378
88482
|
refused: all,
|
|
@@ -88425,8 +88529,8 @@ async function resolveImportedProperties(stackState, template, region, stateBack
|
|
|
88425
88529
|
const refusedHere = [...parameterTaint.refused].filter((id) => inState.has(id));
|
|
88426
88530
|
const unreadable = refusedHere.filter((id) => parameterTaint.unclassifiable.has(id));
|
|
88427
88531
|
if (refusedHere.length > 0) {
|
|
88428
|
-
const named = [...parameterTaint.parametersHit].sort().map((name) =>
|
|
88429
|
-
logger.warn(`${refusedHere.length} resource(s) in
|
|
88532
|
+
const named = [...parameterTaint.parametersHit].sort().map((name) => displayIdent(name));
|
|
88533
|
+
logger.warn(`${refusedHere.length} resource(s) in ${displayStackName(stackState.stackName)} depend, directly or through another resource's attributes, on template parameter(s) whose deployed CloudFormation value could not be proven equal to the template 'Default' 'cdkd import' binds` + (named.length > 0 ? ` (${named.join(", ")})` : "") + (unreadable.length > 0 ? ` — ${unreadable.length} of them because their properties could not be checked for such a dependence` : "") + ". Their recorded properties hold the 'Default', NOT the deployed value, and no observed drift baseline was captured for them by this import (the live value may be a secret this import cannot position a redaction for). Review 'cdkd diff' before the next 'cdkd deploy'.");
|
|
88430
88534
|
}
|
|
88431
88535
|
}
|
|
88432
88536
|
return unsafeObservedBaselineLogicalIds;
|
|
@@ -89048,9 +89152,9 @@ function indexGrandchildTemplatePaths(childTemplate, childTemplatePath) {
|
|
|
89048
89152
|
if (resource.Type !== "AWS::CloudFormation::Stack") continue;
|
|
89049
89153
|
const assetPath = resource.Metadata?.["aws:asset:path"];
|
|
89050
89154
|
if (typeof assetPath !== "string" || assetPath.length === 0) continue;
|
|
89051
|
-
if (path.isAbsolute(assetPath)) throw new Error(`cdkd import --migrate-from-cloudformation: grandchild nested-stack
|
|
89155
|
+
if (path.isAbsolute(assetPath)) throw new Error(`cdkd import --migrate-from-cloudformation: grandchild nested-stack ${displayIdent(grandLogicalId)} has Metadata['aws:asset:path']=${displayAssemblyPath(assetPath)} which is absolute. CDK emits relative asset paths for nested templates.`);
|
|
89052
89156
|
const resolved = resolveAssemblyPath(dir, assetPath);
|
|
89053
|
-
if (!resolved.contained) throw new Error(`cdkd import --migrate-from-cloudformation: grandchild nested-stack
|
|
89157
|
+
if (!resolved.contained) throw new Error(`cdkd import --migrate-from-cloudformation: grandchild nested-stack ${displayIdent(grandLogicalId)} has Metadata['aws:asset:path']=${displayAssemblyPath(assetPath)} which ${renderAssemblyPathEscape(resolved, dir)}`);
|
|
89054
89158
|
result[grandLogicalId] = resolved.path;
|
|
89055
89159
|
}
|
|
89056
89160
|
return result;
|
|
@@ -95028,7 +95132,7 @@ async function resolveOne(entry, secretsClient, ssmClient) {
|
|
|
95028
95132
|
switch (shape.kind) {
|
|
95029
95133
|
case "secrets-manager": return resolveSecretsManager(entry, shape, secretsClient);
|
|
95030
95134
|
case "ssm": return resolveSsm(entry, shape, ssmClient);
|
|
95031
|
-
case "unknown": throw new EcsSecretsResolutionError(`Container
|
|
95135
|
+
case "unknown": throw new EcsSecretsResolutionError(`Container ${displayIdent(entry.containerName)} secret ${displayIdent(entry.name)} references an unsupported ValueFrom shape ${displayIdent(arn, { maxCodePoints: SECRET_REF_MAX_CODE_POINTS })}. Expected Secrets Manager ARN (optionally with :<json-key>::) or SSM Parameter ARN.`);
|
|
95032
95136
|
}
|
|
95033
95137
|
}
|
|
95034
95138
|
/**
|
|
@@ -95061,20 +95165,20 @@ async function resolveSecretsManager(entry, shape, client) {
|
|
|
95061
95165
|
try {
|
|
95062
95166
|
secretString = (await client.send(new GetSecretValueCommand({ SecretId: shape.baseArn }))).SecretString;
|
|
95063
95167
|
} catch (err) {
|
|
95064
|
-
throw new EcsSecretsResolutionError(`Failed to resolve Secrets Manager secret for container
|
|
95168
|
+
throw new EcsSecretsResolutionError(`Failed to resolve Secrets Manager secret for container ${displayIdent(entry.containerName)} / env ${displayIdent(entry.name)} (${displayIdent(shape.baseArn, { maxCodePoints: SECRET_REF_MAX_CODE_POINTS })}): ${displaySafe(err instanceof Error ? err.message : String(err))}`);
|
|
95065
95169
|
}
|
|
95066
|
-
if (secretString === void 0) throw new EcsSecretsResolutionError(`Secrets Manager returned no SecretString for container
|
|
95170
|
+
if (secretString === void 0) throw new EcsSecretsResolutionError(`Secrets Manager returned no SecretString for container ${displayIdent(entry.containerName)} / env ${displayIdent(entry.name)} (${displayIdent(shape.baseArn, { maxCodePoints: SECRET_REF_MAX_CODE_POINTS })}). Binary secrets are not supported.`);
|
|
95067
95171
|
if (shape.jsonKey === void 0) return secretString;
|
|
95068
95172
|
let parsed;
|
|
95069
95173
|
try {
|
|
95070
95174
|
parsed = JSON.parse(secretString);
|
|
95071
95175
|
} catch (err) {
|
|
95072
95176
|
const kind = err instanceof Error ? err.name : "unknown";
|
|
95073
|
-
throw new EcsSecretsResolutionError(`Container
|
|
95177
|
+
throw new EcsSecretsResolutionError(`Container ${displayIdent(entry.containerName)} secret ${displayIdent(entry.name)} specified json-key ${displayIdent(shape.jsonKey)} but the secret value is not valid JSON (${displayIdent(kind)}). The parser detail is withheld because it would echo the secret plaintext.`);
|
|
95074
95178
|
}
|
|
95075
|
-
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) throw new EcsSecretsResolutionError(`Container
|
|
95179
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) throw new EcsSecretsResolutionError(`Container ${displayIdent(entry.containerName)} secret ${displayIdent(entry.name)} specified json-key ${displayIdent(shape.jsonKey)} but the secret root is not a JSON object.`);
|
|
95076
95180
|
const value = parsed[shape.jsonKey];
|
|
95077
|
-
if (value === void 0) throw new EcsSecretsResolutionError(`Container
|
|
95181
|
+
if (value === void 0) throw new EcsSecretsResolutionError(`Container ${displayIdent(entry.containerName)} secret ${displayIdent(entry.name)} specified json-key ${displayIdent(shape.jsonKey)} but no such key exists in the secret JSON.`);
|
|
95078
95182
|
return typeof value === "string" ? value : JSON.stringify(value);
|
|
95079
95183
|
}
|
|
95080
95184
|
async function resolveSsm(entry, shape, client) {
|
|
@@ -95083,11 +95187,11 @@ async function resolveSsm(entry, shape, client) {
|
|
|
95083
95187
|
Name: shape.name,
|
|
95084
95188
|
WithDecryption: true
|
|
95085
95189
|
}))).Parameter?.Value;
|
|
95086
|
-
if (value === void 0) throw new EcsSecretsResolutionError(`SSM parameter
|
|
95190
|
+
if (value === void 0) throw new EcsSecretsResolutionError(`SSM parameter ${displayIdent(shape.name, { maxCodePoints: SECRET_REF_MAX_CODE_POINTS })} returned no Value for container ${displayIdent(entry.containerName)} / env ${displayIdent(entry.name)}.`);
|
|
95087
95191
|
return value;
|
|
95088
95192
|
} catch (err) {
|
|
95089
95193
|
if (err instanceof EcsSecretsResolutionError) throw err;
|
|
95090
|
-
throw new EcsSecretsResolutionError(`Failed to resolve SSM parameter for container
|
|
95194
|
+
throw new EcsSecretsResolutionError(`Failed to resolve SSM parameter for container ${displayIdent(entry.containerName)} / env ${displayIdent(entry.name)} (${displayIdent(shape.name, { maxCodePoints: SECRET_REF_MAX_CODE_POINTS })}): ${displaySafe(err instanceof Error ? err.message : String(err))}`);
|
|
95091
95195
|
}
|
|
95092
95196
|
}
|
|
95093
95197
|
|
|
@@ -95500,7 +95604,7 @@ async function prepareOneImage(task, container, options) {
|
|
|
95500
95604
|
tag,
|
|
95501
95605
|
...task.stack.assetOutdir !== void 0 && { assetOutdir: task.stack.assetOutdir },
|
|
95502
95606
|
...options.platformOverride !== void 0 && { platform: options.platformOverride },
|
|
95503
|
-
wrapError: (stderr) => new LocalInvokeBuildError$1(`docker build failed for ECS container
|
|
95607
|
+
wrapError: (stderr) => new LocalInvokeBuildError$1(`docker build failed for ECS container ${displayIdent(container.name)} (${asset.source.directory !== void 0 ? displayAssemblyPath(asset.source.directory) : asset.source.executable ? redactDockerArgvValues(asset.source.executable).join(" ") : void 0}): ${displaySafe(stderr)}`)
|
|
95504
95608
|
});
|
|
95505
95609
|
if (actualTag !== tag) {
|
|
95506
95610
|
const tagArgs = [
|
|
@@ -95511,7 +95615,7 @@ async function prepareOneImage(task, container, options) {
|
|
|
95511
95615
|
try {
|
|
95512
95616
|
await runDockerStreaming(tagArgs);
|
|
95513
95617
|
} catch (err) {
|
|
95514
|
-
throw new LocalInvokeBuildError$1(`docker tag failed re-tagging
|
|
95618
|
+
throw new LocalInvokeBuildError$1(`docker tag failed re-tagging ${displayIdent(actualTag)} → ${displayIdent(tag)} for ECS container ${displayIdent(container.name)}: ${displaySafe(describeDockerFailure(err, tagArgs))}`);
|
|
95515
95619
|
}
|
|
95516
95620
|
}
|
|
95517
95621
|
return tag;
|
|
@@ -99040,4 +99144,4 @@ function buildProgram() {
|
|
|
99040
99144
|
|
|
99041
99145
|
//#endregion
|
|
99042
99146
|
export { buildProgram };
|
|
99043
|
-
//# sourceMappingURL=program-
|
|
99147
|
+
//# sourceMappingURL=program-BALgPCWL.js.map
|