@go-to-k/cdkd 0.284.7 → 0.284.9
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-DOdJgPLS.js → asg-provider-B09ceB1r.js} +2 -2
- package/dist/{asg-provider-DOdJgPLS.js.map → asg-provider-B09ceB1r.js.map} +1 -1
- package/dist/cli.js +170 -50
- package/dist/cli.js.map +1 -1
- package/dist/{deploy-engine-CJncZQEi.js → deploy-engine-CY2fx4K1.js} +413 -11
- package/dist/deploy-engine-CY2fx4K1.js.map +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/package.json +1 -1
- package/dist/deploy-engine-CJncZQEi.js.map +0 -1
package/dist/cli.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { $ as IntrinsicFunctionResolver, $n as StackHasActiveImportsError, $t as validateContainerRepoName, A as formatResourceLine, An as AssemblyReader, At as describeTypeWithThrottleRetry, B as isExportAliasCollision, Bt as WorkGraph, C as refusesFinalSnapshot, Cn as MIGRATE_TMP_PREFIX, Ct as s3BucketDomainName, D as MULTI_REGION_RECREATE_BLOCKED_TYPES, Dn as PARTITION_TABLE, Dt as applyRoleArnIfSet, E as extractDeploymentEventError, En as expectedOwnerParam, Et as s3BucketWebsiteUrl, F as red, Fn as getAwsClients, Ft as S3StateBackend, G as clearOnUpdateRemoval, Gn as LocalStartServiceError, Gt as escapeRegExp, H as stateKeySecretExposure, Hn as DeployCancelledError, Ht as createAssetRedirectResolver, I as yellow, In as resetAwsClients, It as rebuildClientForBucketRegion, J as findSilentDropProperties, Jn as NestedStackChildDirectDestroyError, Jt as BOOTSTRAP_MARKER_PREFIX, K as ProviderRegistry, Kt as stripControlChars, L as collectDeclaredOutputNames, Ln as setAwsClients, Lt as shouldRetainResource, M as cyan, Mt as DagBuilder, N as gray, Nn as resolveBucketRegion, Nt as TemplateParser, O as isStatefulRecreateTargetSync, On as canonicalizeRegion, Ot as DiffCalculator, P as green, Pn as AwsClients, Pt as LockManager, Q as isTerminationProtectionPropagationError, Qn as ResourceUpdateNotSupportedError, Qt as validateAssetBucketName, R as collectPublishedOutputNames, Rt as AssetPublisher, S as isFinalSnapshotError, Sn as CFN_TEMPLATE_URL_LIMIT, St as s3BucketArn, T as makeCanonicalizePropertiesFn, Tn as uploadCfnTemplate, Tt as s3BucketRegionalDomainName, U as IAMRoleProvider, Un as LocalInvokeBuildError$1, Ut as loadPublishableAssetManifest, V as secretBearingStateKeyWarning, Vt as buildAssetRedirectMap, W as collectInlinePolicyNamesManagedBySiblings, Wn as LocalMigrateError, Wt as rewriteTemplateAssetReferences, X as slowCcOperationTimeoutMs, Xn as ProvisioningError, Xt as getBootstrapMarkerKey, Y as CloudControlProvider, Yn as PartialFailureError, Yt as ensureAssetStorage, Z as disableInstanceApiTermination, Zn as ResourceTimeoutError, Zt as parseBootstrapMarker, _ as ATOMIC_FINAL_SNAPSHOT_TYPES, _n as resolveStateBucketWithDefaultAndSource, _t as TEMPLATE_SOURCED_RULES, a as DeploymentEventsStore, an as runDockerStreaming, ar as normalizeAwsError, at as resolveExplicitPhysicalId, b as ccRoutedFinalSnapshotError, bn as warnDeprecatedNoPrefixCliFlag, bt as redactSecretsForState, c as replayFailedOperations, cn as Synthesizer, cr as isRetryableTransientError, ct as configBooleanRefusal, d as updatePartialReason, dn as getLegacyStateBucketName, dt as replayWarn, en as buildDenyExternalAccessPolicy, er as StackTerminationProtectionError, et as cfnRefValueFromPhysicalId, f as UNSPECIFIED_SKIP_REASON, fn as resolveApp, ft as requireConfigArray, g as computeImplicitDeleteEdges, gn as resolveStateBucketWithDefault, gt as STATE_SOURCED_READBACK_RULES, h as IMPLICIT_DELETE_DEPENDENCIES, hn as resolveSkipPrefix, ht as STATE_SOURCED_CROSS_GENERATION_RULES, i as DeploymentEventsReader, in as runDockerForeground, it as normalizeAwsTagsToCfn, j as bold, jn as processStackMessages, jt as withRetry, k as renderStatefulReason, kn as derivePartitionAndUrlSuffix, kt as INTRINSIC_KEYS, l as replayRollback, ln as synthesisStatusMessage, lr as isThrottlingError, lt as configStringRefusal, m as withResourceDeadline, mn as resolveCaptureObservedState, mt as requireConfigString, n as DEFAULT_RESOURCE_WARN_AFTER_MS, nn as formatDockerLoginError, nt as refStateLookupFromResource, o as planFailedOps, on as AssetManifestLoader, or as withErrorHandling, ot as assertRegionMatch, p as deleteSkipReason, pn as resolveAutoAssetStorage, pt as requireConfigObject, q as findActionableSilentDrops, qn as MissingCdkCliError, qt as AssetModeResolver, r as DeployEngine, rn as getDockerCmd, rt as WAFv2WebACLProvider, s as planRollback, sn as getDockerImageBySourceHash, sr as isMarkedNonRetryable, st as coerceCfnBoolean, t as DEFAULT_RESOURCE_TIMEOUT_MS, tn as buildDockerImage, tt as getAccountInfo, u as updatePartialMessage, un as getDefaultStateBucketName, ur as markNonRetryable, ut as readConfigString, v as PRE_DELETE_SNAPSHOT_TYPES, vn as resolveUseCdkBootstrapAssets, vt as createSecretMasker, w as unsupportedFinalSnapshotError, wn as findLargeInlineResources, wt as s3BucketDualStackDomainName, x as createPreDeleteFinalSnapshot, xn as CFN_TEMPLATE_BODY_LIMIT, xt as scrubResourceRecord, y as buildFinalSnapshotIdentifier, yn as stateBucketExistenceConfirmed, yt as maskSecretsInText, z as exportAliasCollisionScrubWarning, zn as CdkdError, zt as stringifyValue } from "./deploy-engine-
|
|
2
|
+
import { $ as IntrinsicFunctionResolver, $n as StackHasActiveImportsError, $t as validateContainerRepoName, A as formatResourceLine, An as AssemblyReader, At as describeTypeWithThrottleRetry, B as isExportAliasCollision, Bt as WorkGraph, C as refusesFinalSnapshot, Cn as MIGRATE_TMP_PREFIX, Ct as s3BucketDomainName, D as MULTI_REGION_RECREATE_BLOCKED_TYPES, Dn as PARTITION_TABLE, Dt as applyRoleArnIfSet, E as extractDeploymentEventError, En as expectedOwnerParam, Et as s3BucketWebsiteUrl, F as red, Fn as getAwsClients, Ft as S3StateBackend, G as clearOnUpdateRemoval, Gn as LocalStartServiceError, Gt as escapeRegExp, H as stateKeySecretExposure, Hn as DeployCancelledError, Ht as createAssetRedirectResolver, I as yellow, In as resetAwsClients, It as rebuildClientForBucketRegion, J as findSilentDropProperties, Jn as NestedStackChildDirectDestroyError, Jt as BOOTSTRAP_MARKER_PREFIX, K as ProviderRegistry, Kt as stripControlChars, L as collectDeclaredOutputNames, Ln as setAwsClients, Lt as shouldRetainResource, M as cyan, Mt as DagBuilder, N as gray, Nn as resolveBucketRegion, Nt as TemplateParser, O as isStatefulRecreateTargetSync, On as canonicalizeRegion, Ot as DiffCalculator, P as green, Pn as AwsClients, Pt as LockManager, Q as isTerminationProtectionPropagationError, Qn as ResourceUpdateNotSupportedError, Qt as validateAssetBucketName, R as collectPublishedOutputNames, Rt as AssetPublisher, S as isFinalSnapshotError, Sn as CFN_TEMPLATE_URL_LIMIT, St as s3BucketArn, T as makeCanonicalizePropertiesFn, Tn as uploadCfnTemplate, Tt as s3BucketRegionalDomainName, U as IAMRoleProvider, Un as LocalInvokeBuildError$1, Ut as loadPublishableAssetManifest, V as secretBearingStateKeyWarning, Vt as buildAssetRedirectMap, W as collectInlinePolicyNamesManagedBySiblings, Wn as LocalMigrateError, Wt as rewriteTemplateAssetReferences, X as slowCcOperationTimeoutMs, Xn as ProvisioningError, Xt as getBootstrapMarkerKey, Y as CloudControlProvider, Yn as PartialFailureError, Yt as ensureAssetStorage, Z as disableInstanceApiTermination, Zn as ResourceTimeoutError, Zt as parseBootstrapMarker, _ as ATOMIC_FINAL_SNAPSHOT_TYPES, _n as resolveStateBucketWithDefaultAndSource, _t as TEMPLATE_SOURCED_RULES, a as DeploymentEventsStore, an as runDockerStreaming, ar as normalizeAwsError, at as resolveExplicitPhysicalId, b as ccRoutedFinalSnapshotError, bn as warnDeprecatedNoPrefixCliFlag, bt as redactSecretsForState, c as replayFailedOperations, cn as Synthesizer, cr as isRetryableTransientError, ct as configBooleanRefusal, d as updatePartialReason, dn as getLegacyStateBucketName, dt as replayWarn, en as buildDenyExternalAccessPolicy, er as StackTerminationProtectionError, et as cfnRefValueFromPhysicalId, f as UNSPECIFIED_SKIP_REASON, fn as resolveApp, ft as requireConfigArray, g as computeImplicitDeleteEdges, gn as resolveStateBucketWithDefault, gt as STATE_SOURCED_READBACK_RULES, h as IMPLICIT_DELETE_DEPENDENCIES, hn as resolveSkipPrefix, ht as STATE_SOURCED_CROSS_GENERATION_RULES, i as DeploymentEventsReader, in as runDockerForeground, it as normalizeAwsTagsToCfn, j as bold, jn as processStackMessages, jt as withRetry, k as renderStatefulReason, kn as derivePartitionAndUrlSuffix, kt as INTRINSIC_KEYS, l as replayRollback, ln as synthesisStatusMessage, lr as isThrottlingError, lt as configStringRefusal, m as withResourceDeadline, mn as resolveCaptureObservedState, mt as requireConfigString, n as DEFAULT_RESOURCE_WARN_AFTER_MS, nn as formatDockerLoginError, nt as refStateLookupFromResource, o as planFailedOps, on as AssetManifestLoader, or as withErrorHandling, ot as assertRegionMatch, p as deleteSkipReason, pn as resolveAutoAssetStorage, pt as requireConfigObject, q as findActionableSilentDrops, qn as MissingCdkCliError, qt as AssetModeResolver, r as DeployEngine, rn as getDockerCmd, rt as WAFv2WebACLProvider, s as planRollback, sn as getDockerImageBySourceHash, sr as isMarkedNonRetryable, st as coerceCfnBoolean, t as DEFAULT_RESOURCE_TIMEOUT_MS, tn as buildDockerImage, tt as getAccountInfo, u as updatePartialMessage, un as getDefaultStateBucketName, ur as markNonRetryable, ut as readConfigString, v as PRE_DELETE_SNAPSHOT_TYPES, vn as resolveUseCdkBootstrapAssets, vt as createSecretMasker, w as unsupportedFinalSnapshotError, wn as findLargeInlineResources, wt as s3BucketDualStackDomainName, x as createPreDeleteFinalSnapshot, xn as CFN_TEMPLATE_BODY_LIMIT, xt as scrubResourceRecord, y as buildFinalSnapshotIdentifier, yn as stateBucketExistenceConfirmed, yt as maskSecretsInText, z as exportAliasCollisionScrubWarning, zn as CdkdError, zt as stringifyValue } from "./deploy-engine-CY2fx4K1.js";
|
|
3
3
|
import { a as getLiveRenderer, c as PATTERN_B_RESOURCE_TYPES, d as generateResourceNameWithFallback, h as withStackName, i as runStackBuffered, m as withSkipPrefix, n as getLogger, o as PATTERN_B_NAME_OPTIONS, s as PATTERN_B_NAME_PROPERTIES, u as generateResourceName } from "./logger-zRrlbaQt.js";
|
|
4
|
-
import { t as ASGProvider } from "./asg-provider-
|
|
4
|
+
import { t as ASGProvider } from "./asg-provider-B09ceB1r.js";
|
|
5
5
|
import { AsyncLocalStorage } from "node:async_hooks";
|
|
6
6
|
import { createHash, randomBytes, randomUUID } from "node:crypto";
|
|
7
7
|
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, 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";
|
|
@@ -58723,6 +58723,18 @@ function containsSecretDynamicReference(value) {
|
|
|
58723
58723
|
if (value !== null && typeof value === "object") return Object.values(value).some(containsSecretDynamicReference);
|
|
58724
58724
|
return false;
|
|
58725
58725
|
}
|
|
58726
|
+
/**
|
|
58727
|
+
* Does this template carry a secret-bearing dynamic reference ANYWHERE?
|
|
58728
|
+
*
|
|
58729
|
+
* Exported for the DELETED nested-child path (issue #1948 review): that node
|
|
58730
|
+
* diffs its state against an EMPTY template, so it can compute nothing about
|
|
58731
|
+
* secrets from its own input and would render a pre-GHSA child's whole stored
|
|
58732
|
+
* bag in full. The caller passes the PARENT's answer instead — see
|
|
58733
|
+
* `diff-recursive.ts`'s `buildDeletedSubtree`.
|
|
58734
|
+
*/
|
|
58735
|
+
function templateHasSecretDynamicReference(template) {
|
|
58736
|
+
return containsSecretDynamicReference(template);
|
|
58737
|
+
}
|
|
58726
58738
|
/** Structural equality, mirroring the deploy engine's `outputMapsEqual` leaf rule. */
|
|
58727
58739
|
function valuesEqual(a, b) {
|
|
58728
58740
|
if (a === b) return true;
|
|
@@ -58772,13 +58784,21 @@ function valuesEqual(a, b) {
|
|
|
58772
58784
|
* resolver runs with `skipDynamicReferences`, so a `{{resolve:...}}` reference
|
|
58773
58785
|
* is never resolved to plaintext in the first place and the bag already holds
|
|
58774
58786
|
* the expression that state stores post-redaction.
|
|
58787
|
+
*
|
|
58788
|
+
* `storedOutputs` is the bag currently in state. It is consulted for exactly
|
|
58789
|
+
* one decision — the LITERAL `Export.Name` of a secret-bearing stack, see issue
|
|
58790
|
+
* #1942 at that branch — and never merged into the result: everything else here
|
|
58791
|
+
* previews what the template says, and reading state anywhere else would make
|
|
58792
|
+
* the preview agree with the past instead of with the next deploy.
|
|
58775
58793
|
*/
|
|
58776
|
-
async function resolveTemplateOutputs(template, resolveFn, conditions) {
|
|
58794
|
+
async function resolveTemplateOutputs(template, resolveFn, conditions, storedOutputs) {
|
|
58777
58795
|
const logger = getLogger().child("OutputsDiff");
|
|
58778
|
-
const outputs =
|
|
58796
|
+
const outputs = Object.create(null);
|
|
58779
58797
|
const exportNames = /* @__PURE__ */ new Set();
|
|
58780
58798
|
const failedKeys = /* @__PURE__ */ new Set();
|
|
58781
58799
|
const secretSourceKeys = /* @__PURE__ */ new Set();
|
|
58800
|
+
const declaredKeys = /* @__PURE__ */ new Set();
|
|
58801
|
+
const templateHasSecretReference = containsSecretDynamicReference(template);
|
|
58782
58802
|
let resolutionFailed = false;
|
|
58783
58803
|
const publishedOutputNames = collectPublishedOutputNames(template.Outputs ?? {}, conditions);
|
|
58784
58804
|
if (!template.Outputs) return {
|
|
@@ -58786,6 +58806,8 @@ async function resolveTemplateOutputs(template, resolveFn, conditions) {
|
|
|
58786
58806
|
exportNames,
|
|
58787
58807
|
failedKeys,
|
|
58788
58808
|
secretSourceKeys,
|
|
58809
|
+
declaredKeys,
|
|
58810
|
+
templateHasSecretReference,
|
|
58789
58811
|
resolutionFailed
|
|
58790
58812
|
};
|
|
58791
58813
|
/**
|
|
@@ -58799,6 +58821,8 @@ async function resolveTemplateOutputs(template, resolveFn, conditions) {
|
|
|
58799
58821
|
if (typeof output.Export?.Name === "string") failedKeys.add(output.Export.Name);
|
|
58800
58822
|
};
|
|
58801
58823
|
for (const [outputKey, output] of Object.entries(template.Outputs)) {
|
|
58824
|
+
declaredKeys.add(outputKey);
|
|
58825
|
+
if (typeof output.Export?.Name === "string") declaredKeys.add(output.Export.Name);
|
|
58802
58826
|
if (!containsSecretDynamicReference(output.Value)) continue;
|
|
58803
58827
|
secretSourceKeys.add(outputKey);
|
|
58804
58828
|
if (typeof output.Export?.Name === "string") secretSourceKeys.add(output.Export.Name);
|
|
@@ -58838,11 +58862,15 @@ async function resolveTemplateOutputs(template, resolveFn, conditions) {
|
|
|
58838
58862
|
}
|
|
58839
58863
|
if (typeof exportName === "string" && !isUnresolvedValue(exportName, exportSourceUsedSub)) if (declaredExportIsIntrinsic && isSecretDynamicReference(exportName)) logger.debug(`Diff skipping export alias of ${stripControlChars(outputKey)} — the name carries a secret reference`);
|
|
58840
58864
|
else if (isExportAliasCollision(exportName, outputKey, publishedOutputNames)) logger.debug(`Diff skipping export alias ${stripControlChars(exportName)} of ${stripControlChars(outputKey)} — collides with an output name`);
|
|
58841
|
-
else if (!declaredExportIsIntrinsic && secretSourceKeys.size > 0) {
|
|
58842
|
-
|
|
58865
|
+
else if (!declaredExportIsIntrinsic && secretSourceKeys.size > 0) if (storedOutputs !== void 0 && Object.prototype.hasOwnProperty.call(storedOutputs, exportName)) {
|
|
58866
|
+
outputs[exportName] = value;
|
|
58867
|
+
exportNames.add(exportName);
|
|
58868
|
+
} else {
|
|
58869
|
+
logger.debug(`Diff cannot decide the export alias of ${stripControlChars(outputKey)} — a literal name may contain a resolved secret and state does not hold that key`);
|
|
58843
58870
|
failedKeys.add(exportName);
|
|
58844
58871
|
resolutionFailed = true;
|
|
58845
|
-
}
|
|
58872
|
+
}
|
|
58873
|
+
else {
|
|
58846
58874
|
outputs[exportName] = value;
|
|
58847
58875
|
exportNames.add(exportName);
|
|
58848
58876
|
}
|
|
@@ -58854,6 +58882,8 @@ async function resolveTemplateOutputs(template, resolveFn, conditions) {
|
|
|
58854
58882
|
exportNames,
|
|
58855
58883
|
failedKeys,
|
|
58856
58884
|
secretSourceKeys,
|
|
58885
|
+
declaredKeys,
|
|
58886
|
+
templateHasSecretReference,
|
|
58857
58887
|
resolutionFailed
|
|
58858
58888
|
};
|
|
58859
58889
|
}
|
|
@@ -58883,24 +58913,73 @@ async function resolveTemplateOutputs(template, resolveFn, conditions) {
|
|
|
58883
58913
|
* {@link isSecretDynamicReference} (this resolver runs with
|
|
58884
58914
|
* `skipDynamicReferences`) while the stored side is not; and
|
|
58885
58915
|
* - `secretSourceKeys` — the template itself declares the key's value as such a
|
|
58886
|
-
* reference. This one reaches
|
|
58887
|
-
*
|
|
58888
|
-
*
|
|
58916
|
+
* reference. This one reaches a case the first cannot: a condition-skipped
|
|
58917
|
+
* secret output has NO desired side at all and would otherwise print in full
|
|
58918
|
+
* as a REMOVE row.
|
|
58889
58919
|
*
|
|
58890
58920
|
* A hit on either makes the WHOLE record suspect, not just that key: the
|
|
58891
58921
|
* record was written by a pre-GHSA binary, so every value in it is unredacted.
|
|
58892
58922
|
* Withholding is therefore record-level. The change is still REPORTED — only
|
|
58893
58923
|
* the value is withheld — so `--fail` and the exports story are unaffected.
|
|
58894
|
-
|
|
58895
|
-
|
|
58924
|
+
*
|
|
58925
|
+
* ## The key today's template cannot account for (issue #1948)
|
|
58926
|
+
*
|
|
58927
|
+
* Neither signal above covers an output DELETED from the template, and an
|
|
58928
|
+
* earlier revision of this note claimed `secretSourceKeys` did — a false
|
|
58929
|
+
* coverage claim, which is exactly what lets a reader conclude the case is
|
|
58930
|
+
* handled. It structurally cannot: that set is built from DECLARATIONS, and a
|
|
58931
|
+
* deleted output declares nothing, so a record whose ONLY secret-bearing output
|
|
58932
|
+
* has since been removed is judged not-legacy and its stored pre-GHSA plaintext
|
|
58933
|
+
* renders as the `old:` side of a REMOVE row.
|
|
58934
|
+
*
|
|
58935
|
+
* The signal has to come from the STORED bag, and the honest statement about
|
|
58936
|
+
* the stored bag is that the case is UNDECIDABLE there: post-GHSA a secret
|
|
58937
|
+
* output stores its `{{resolve:...}}` EXPRESSION, but pre-GHSA it stores a
|
|
58938
|
+
* plaintext, and a plaintext is indistinguishable from an ordinary string. So
|
|
58939
|
+
* this is a REFUSAL rather than a detection — a stored key the template cannot
|
|
58940
|
+
* account for has its value withheld — bounded by two gates that keep it off
|
|
58941
|
+
* the common benign case (deleting an output is a normal refactor):
|
|
58942
|
+
*
|
|
58943
|
+
* - `templateHasSecretReference` — the template must still prove this stack
|
|
58944
|
+
* handles secrets AT ALL (anywhere, `Resources` included). An ordinary stack
|
|
58945
|
+
* with no secret reference keeps printing its REMOVE values.
|
|
58946
|
+
* - no stored value is itself a secret-bearing expression. One that is proves
|
|
58947
|
+
* the LAST write was post-GHSA, and the bag is rewritten wholesale by
|
|
58948
|
+
* `resolveOutputs` on every deploy, so every other value in it is redacted
|
|
58949
|
+
* too. This exonerates the record.
|
|
58950
|
+
*
|
|
58951
|
+
* That reasoning holds for a DEPLOY write and is weaker for a `cdkd scrub`
|
|
58952
|
+
* one, which rewrites `state.outputs` IN PLACE: scrub redacts what it has a
|
|
58953
|
+
* needle or a template position for, and its own docs admit it can leave a
|
|
58954
|
+
* plaintext it has neither for — so a scrubbed bag holding one redacted key
|
|
58955
|
+
* can exonerate a deleted key's surviving plaintext. Recorded rather than
|
|
58956
|
+
* closed: removing the exoneration would withhold values on every clean
|
|
58957
|
+
* post-GHSA record in a secret-handling stack, which is the larger harm.
|
|
58958
|
+
*
|
|
58959
|
+
* Withholding here is PER-KEY, unlike the record-level arms above, and the
|
|
58960
|
+
* asymmetry follows from what each concludes: those conclude the record was
|
|
58961
|
+
* written by a pre-GHSA binary (a claim about the whole bag), while this one
|
|
58962
|
+
* concludes only that THIS key is undecidable. So a secret-handling stack that
|
|
58963
|
+
* deletes an ordinary output withholds that one row's value and prints the
|
|
58964
|
+
* rest.
|
|
58965
|
+
*
|
|
58966
|
+
* Residual, stated because the gate is what buys the low false-positive rate:
|
|
58967
|
+
* a stack whose ONLY secret reference WAS the deleted output has no secret left
|
|
58968
|
+
* in its template, so nothing here fires. Closing it would mean withholding
|
|
58969
|
+
* every REMOVE value on every stack, which is a worse trade.
|
|
58970
|
+
*/
|
|
58971
|
+
function computeOutputsDiff(current, desired, exportNames, secretSourceKeys = /* @__PURE__ */ new Set(), unaccountableScan = {}) {
|
|
58896
58972
|
const changes = [];
|
|
58897
58973
|
const currentBag = current ?? {};
|
|
58898
58974
|
const legacyRecord = Object.entries(currentBag).some(([name, oldValue]) => {
|
|
58899
58975
|
if (typeof oldValue === "string" && isSecretDynamicReference(oldValue)) return false;
|
|
58900
58976
|
return containsSecretDynamicReference(desired[name]) || secretSourceKeys.has(name);
|
|
58901
58977
|
});
|
|
58978
|
+
const recordProvesPostGhsa = Object.values(currentBag).some((v) => typeof v === "string" && isSecretDynamicReference(v));
|
|
58979
|
+
const declaredKeys = unaccountableScan.declaredKeys ?? /* @__PURE__ */ new Set();
|
|
58980
|
+
const unaccountable = (name) => unaccountableScan.templateHasSecretReference === true && !recordProvesPostGhsa && !declaredKeys.has(name) && !Object.prototype.hasOwnProperty.call(desired, name);
|
|
58902
58981
|
const push = (change) => {
|
|
58903
|
-
if (
|
|
58982
|
+
if (change.changeType !== "ADD" && (legacyRecord || unaccountable(change.name))) {
|
|
58904
58983
|
const { oldValue: _dropped, ...rest } = change;
|
|
58905
58984
|
changes.push({
|
|
58906
58985
|
...rest,
|
|
@@ -59911,7 +59990,8 @@ async function loadStateOrEmpty(stackName, region, stateBackend) {
|
|
|
59911
59990
|
* Pure with respect to AWS state mutation — only reads state (the resolver
|
|
59912
59991
|
* may read producer state for `Fn::ImportValue` / `Fn::GetStackOutput`).
|
|
59913
59992
|
*/
|
|
59914
|
-
async function computeStackDiff(currentState, template, region, stackName, stateBackend, diffCalculator,
|
|
59993
|
+
async function computeStackDiff(currentState, template, region, stackName, stateBackend, diffCalculator, options = {}) {
|
|
59994
|
+
const { parameters, canonicalizeProperties, cfnFallback, inheritSecretBearingTemplate } = options;
|
|
59915
59995
|
const intrinsicResolver = new IntrinsicFunctionResolver(region, { cfnFallback: cfnFallback ?? true });
|
|
59916
59996
|
let mergedParameters = parameters;
|
|
59917
59997
|
let parametersBound = false;
|
|
@@ -59953,11 +60033,17 @@ async function computeStackDiff(currentState, template, region, stackName, state
|
|
|
59953
60033
|
skipDynamicReferences: true
|
|
59954
60034
|
});
|
|
59955
60035
|
const changes = await diffCalculator.calculateDiff(currentState, effectiveTemplate, resolveFn, canonicalizeProperties);
|
|
59956
|
-
const resolved = await resolveTemplateOutputs(effectiveTemplate, resolveFn, conditions);
|
|
60036
|
+
const resolved = await resolveTemplateOutputs(effectiveTemplate, resolveFn, conditions, currentState.outputs);
|
|
59957
60037
|
let outputChanges = [];
|
|
59958
60038
|
if (resolved.resolutionFailed) {
|
|
59959
|
-
if (computeOutputsDiff(currentState.outputs, resolved.outputs, resolved.exportNames, resolved.secretSourceKeys
|
|
59960
|
-
|
|
60039
|
+
if (computeOutputsDiff(currentState.outputs, resolved.outputs, resolved.exportNames, resolved.secretSourceKeys, {
|
|
60040
|
+
declaredKeys: resolved.declaredKeys,
|
|
60041
|
+
templateHasSecretReference: resolved.templateHasSecretReference || inheritSecretBearingTemplate === true
|
|
60042
|
+
}).filter((change) => !resolved.failedKeys.has(change.name)).length > 0) logger.warn(`Outputs of stack ${stackName} may have changed, but one or more could not be resolved against current state — omitting the Outputs section from this diff. It is usually an output referencing a resource this deploy has yet to create.`);
|
|
60043
|
+
} else outputChanges = computeOutputsDiff(currentState.outputs, resolved.outputs, resolved.exportNames, resolved.secretSourceKeys, {
|
|
60044
|
+
declaredKeys: resolved.declaredKeys,
|
|
60045
|
+
templateHasSecretReference: resolved.templateHasSecretReference || inheritSecretBearingTemplate === true
|
|
60046
|
+
});
|
|
59961
60047
|
return {
|
|
59962
60048
|
changes,
|
|
59963
60049
|
outputChanges
|
|
@@ -60022,9 +60108,15 @@ async function resolveChildStackParameters(parentStackRow, parentTemplate, paren
|
|
|
60022
60108
|
* fail at deploy time.
|
|
60023
60109
|
*/
|
|
60024
60110
|
async function buildDiffTree(args) {
|
|
60025
|
-
const { stackName, displayName, region, template, nestedTemplates, recursive, stateBackend, diffCalculator, parameters, canonicalizeProperties, assetRedirect, cfnFallback } = args;
|
|
60111
|
+
const { stackName, displayName, region, template, nestedTemplates, recursive, stateBackend, diffCalculator, parentHasSecretReference, parameters, canonicalizeProperties, assetRedirect, cfnFallback } = args;
|
|
60026
60112
|
const state = await loadStateOrEmpty(stackName, region, stateBackend);
|
|
60027
|
-
const
|
|
60113
|
+
const secretBearingAbove = parentHasSecretReference === true || templateHasSecretDynamicReference(template);
|
|
60114
|
+
const { changes, outputChanges } = await computeStackDiff(state, template, region, stackName, stateBackend, diffCalculator, {
|
|
60115
|
+
...parameters && { parameters },
|
|
60116
|
+
...canonicalizeProperties && { canonicalizeProperties },
|
|
60117
|
+
...cfnFallback !== void 0 && { cfnFallback },
|
|
60118
|
+
inheritSecretBearingTemplate: false
|
|
60119
|
+
});
|
|
60028
60120
|
const node = {
|
|
60029
60121
|
stackName,
|
|
60030
60122
|
displayName,
|
|
@@ -60058,13 +60150,14 @@ async function buildDiffTree(args) {
|
|
|
60058
60150
|
parameters: childParameters,
|
|
60059
60151
|
...canonicalizeProperties && { canonicalizeProperties },
|
|
60060
60152
|
...assetRedirect && { assetRedirect },
|
|
60061
|
-
...cfnFallback !== void 0 && { cfnFallback }
|
|
60153
|
+
...cfnFallback !== void 0 && { cfnFallback },
|
|
60154
|
+
parentHasSecretReference: secretBearingAbove
|
|
60062
60155
|
}));
|
|
60063
60156
|
}
|
|
60064
60157
|
for (const [logicalId, resource] of Object.entries(state.resources)) {
|
|
60065
60158
|
if (resource.resourceType !== "AWS::CloudFormation::Stack") continue;
|
|
60066
60159
|
if (templateChildIds.has(logicalId)) continue;
|
|
60067
|
-
node.children.push(await buildDeletedSubtree(`${stackName}~${logicalId}`, region, stateBackend, diffCalculator));
|
|
60160
|
+
node.children.push(await buildDeletedSubtree(`${stackName}~${logicalId}`, region, stateBackend, diffCalculator, secretBearingAbove));
|
|
60068
60161
|
}
|
|
60069
60162
|
return node;
|
|
60070
60163
|
}
|
|
@@ -60074,9 +60167,9 @@ async function buildDiffTree(args) {
|
|
|
60074
60167
|
* (state vs empty template), recursing into state-listed grandchildren
|
|
60075
60168
|
* (also all DELETE).
|
|
60076
60169
|
*/
|
|
60077
|
-
async function buildDeletedSubtree(stackName, region, stateBackend, diffCalculator) {
|
|
60170
|
+
async function buildDeletedSubtree(stackName, region, stateBackend, diffCalculator, parentHasSecretReference) {
|
|
60078
60171
|
const state = await loadStateOrEmpty(stackName, region, stateBackend);
|
|
60079
|
-
const { changes, outputChanges } = await computeStackDiff(state, EMPTY_TEMPLATE, region, stackName, stateBackend, diffCalculator);
|
|
60172
|
+
const { changes, outputChanges } = await computeStackDiff(state, EMPTY_TEMPLATE, region, stackName, stateBackend, diffCalculator, { inheritSecretBearingTemplate: parentHasSecretReference });
|
|
60080
60173
|
const node = {
|
|
60081
60174
|
stackName,
|
|
60082
60175
|
displayName: stackName,
|
|
@@ -60088,7 +60181,7 @@ async function buildDeletedSubtree(stackName, region, stateBackend, diffCalculat
|
|
|
60088
60181
|
};
|
|
60089
60182
|
for (const [logicalId, resource] of Object.entries(state.resources)) {
|
|
60090
60183
|
if (resource.resourceType !== "AWS::CloudFormation::Stack") continue;
|
|
60091
|
-
node.children.push(await buildDeletedSubtree(`${stackName}~${logicalId}`, region, stateBackend, diffCalculator));
|
|
60184
|
+
node.children.push(await buildDeletedSubtree(`${stackName}~${logicalId}`, region, stateBackend, diffCalculator, parentHasSecretReference));
|
|
60092
60185
|
}
|
|
60093
60186
|
return node;
|
|
60094
60187
|
}
|
|
@@ -60318,25 +60411,19 @@ function renderChangeLines(changes, logFn, ccApiRoutes) {
|
|
|
60318
60411
|
delete: deleteCount
|
|
60319
60412
|
};
|
|
60320
60413
|
}
|
|
60321
|
-
/** Stand-in printed instead of a withheld legacy-plaintext output value. */
|
|
60322
|
-
const REDACTED_LEGACY_PLAINTEXT = "<redacted: legacy plaintext in state — run `cdkd scrub`>";
|
|
60323
60414
|
/**
|
|
60324
|
-
*
|
|
60325
|
-
* TERMINAL rather than merely appear in it: C0 (incl. ESC, so no ANSI sequence
|
|
60326
|
-
* survives), DEL, C1 (the 8-bit CSI forms some terminals still honor), and the
|
|
60327
|
-
* bidi / format overrides that visually reorder a rendered line.
|
|
60328
|
-
*
|
|
60329
|
-
* Applied only on the human-render path. The `--json` payload is deliberately
|
|
60330
|
-
* left byte-faithful: it is a machine interface, an export NAME is data a
|
|
60331
|
-
* consumer may match on, and silently mutating it there would trade a real
|
|
60332
|
-
* correctness regression for a display concern belonging to whatever renders
|
|
60333
|
-
* the JSON. `JSON.stringify` already escapes everything below 0x20.
|
|
60415
|
+
* Stand-in printed instead of a withheld stored output value.
|
|
60334
60416
|
*
|
|
60335
|
-
*
|
|
60336
|
-
*
|
|
60417
|
+
* Worded as a POSSIBILITY because both reasons the value is withheld are
|
|
60418
|
+
* suspicions rather than detections — a record that LOOKS pre-GHSA, and a
|
|
60419
|
+
* stored key today's template cannot account for (issue #1948), which is
|
|
60420
|
+
* undecidable by construction. Stating it as a fact would be wrong on the
|
|
60421
|
+
* benign half of each, and `cdkd scrub` finding nothing is the expected
|
|
60422
|
+
* outcome there.
|
|
60337
60423
|
*/
|
|
60424
|
+
const REDACTED_LEGACY_PLAINTEXT = "<redacted: may be legacy plaintext in state — run `cdkd scrub`>";
|
|
60338
60425
|
/**
|
|
60339
|
-
* The
|
|
60426
|
+
* The guard for an already-JSON-SERIALIZED value: C1 and the bidi marks
|
|
60340
60427
|
* only, deliberately NOT C0.
|
|
60341
60428
|
*
|
|
60342
60429
|
* `JSON.stringify` escapes every character below 0x20 that occurs INSIDE a
|
|
@@ -67888,13 +67975,13 @@ async function stateResourcesCommand(stackName, options) {
|
|
|
67888
67975
|
for (const detail of details) {
|
|
67889
67976
|
lines.push(detail.logicalId);
|
|
67890
67977
|
lines.push(` Type: ${detail.resourceType}`);
|
|
67891
|
-
lines.push(` PhysicalID: ${detail.physicalId}`);
|
|
67978
|
+
lines.push(` PhysicalID: ${stripControlChars(detail.physicalId)}`);
|
|
67892
67979
|
lines.push(` Dependencies: ${detail.dependencies.length > 0 ? detail.dependencies.join(", ") : "(none)"}`);
|
|
67893
67980
|
const attrEntries = Object.entries(detail.attributes);
|
|
67894
67981
|
if (attrEntries.length === 0) lines.push(" Attributes: (none)");
|
|
67895
67982
|
else {
|
|
67896
67983
|
lines.push(" Attributes:");
|
|
67897
|
-
for (const [k, v] of attrEntries) lines.push(` ${k}: ${formatAttributeValue(v)}`);
|
|
67984
|
+
for (const [k, v] of attrEntries) lines.push(` ${stripControlChars(k)}: ${formatAttributeValue(v)}`);
|
|
67898
67985
|
}
|
|
67899
67986
|
lines.push("");
|
|
67900
67987
|
}
|
|
@@ -67914,11 +68001,31 @@ async function stateResourcesCommand(stackName, options) {
|
|
|
67914
68001
|
*
|
|
67915
68002
|
* Scalar values render as-is; objects/arrays are JSON-encoded inline so a
|
|
67916
68003
|
* resource block stays compact even when an attribute is structured.
|
|
68004
|
+
*
|
|
68005
|
+
* Control characters are stripped HERE rather than at each call site (issue
|
|
68006
|
+
* #1948 review), because every caller has the same provenance problem and the
|
|
68007
|
+
* same answer: an Outputs value, a resource PROPERTY and a provider-returned
|
|
68008
|
+
* ATTRIBUTE are all values cdkd resolved or read back, none of them passed a
|
|
68009
|
+
* CloudFormation validator, and all three land in the same terminal. Doing it
|
|
68010
|
+
* once means a future caller cannot forget — the half-applied version of this
|
|
68011
|
+
* guard is what the review caught.
|
|
68012
|
+
*
|
|
68013
|
+
* The FULL class (C0 included), unlike `diff-recursive`'s
|
|
68014
|
+
* `stripDisplayOnlyChars`: that narrower guard exists to protect a
|
|
68015
|
+
* PRETTY-PRINTED payload's structural newlines, and this function never
|
|
68016
|
+
* pretty-prints — `JSON.stringify` is called without an indent, so a newline
|
|
68017
|
+
* here is content injected by the value, not layout.
|
|
68018
|
+
*
|
|
68019
|
+
* Only the human path routes through this; `--json` serializes the state
|
|
68020
|
+
* record directly and stays byte-faithful, which is the same split
|
|
68021
|
+
* `renderOutputChangeLines` makes.
|
|
67917
68022
|
*/
|
|
67918
68023
|
function formatAttributeValue(value) {
|
|
67919
68024
|
if (value === null) return "null";
|
|
67920
|
-
if (
|
|
67921
|
-
return
|
|
68025
|
+
if (value === void 0) return "undefined";
|
|
68026
|
+
if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") return stripControlChars(String(value));
|
|
68027
|
+
const json = JSON.stringify(value);
|
|
68028
|
+
return json === void 0 ? "(unserializable)" : stripControlChars(json);
|
|
67922
68029
|
}
|
|
67923
68030
|
/**
|
|
67924
68031
|
* Render a duration in milliseconds as `1m23s` / `45s`.
|
|
@@ -68020,7 +68127,7 @@ function renderStateBlock(state, lockInfo) {
|
|
|
68020
68127
|
if (outputEntries.length > 0) {
|
|
68021
68128
|
lines.push("");
|
|
68022
68129
|
lines.push("Outputs:");
|
|
68023
|
-
for (const [k, v] of outputEntries) lines.push(` ${k}: ${formatAttributeValue(v)}`);
|
|
68130
|
+
for (const [k, v] of outputEntries) lines.push(` ${stripControlChars(k)}: ${formatAttributeValue(v)}`);
|
|
68024
68131
|
}
|
|
68025
68132
|
const resourceEntries = Object.entries(state.resources ?? {}).sort(([a], [b]) => a.localeCompare(b));
|
|
68026
68133
|
lines.push("");
|
|
@@ -68029,7 +68136,7 @@ function renderStateBlock(state, lockInfo) {
|
|
|
68029
68136
|
lines.push("");
|
|
68030
68137
|
lines.push(logicalId);
|
|
68031
68138
|
lines.push(` Type: ${resource.resourceType}`);
|
|
68032
|
-
lines.push(` PhysicalID: ${resource.physicalId}`);
|
|
68139
|
+
lines.push(` PhysicalID: ${stripControlChars(resource.physicalId)}`);
|
|
68033
68140
|
const provisionedBy = resource.provisionedBy ?? "(sdk, legacy default)";
|
|
68034
68141
|
lines.push(` ProvisionedBy: ${provisionedBy}`);
|
|
68035
68142
|
const deps = resource.dependencies ?? [];
|
|
@@ -68038,13 +68145,13 @@ function renderStateBlock(state, lockInfo) {
|
|
|
68038
68145
|
if (attrEntries.length === 0) lines.push(" Attributes: (none)");
|
|
68039
68146
|
else {
|
|
68040
68147
|
lines.push(" Attributes:");
|
|
68041
|
-
for (const [k, v] of attrEntries) lines.push(` ${k}: ${formatAttributeValue(v)}`);
|
|
68148
|
+
for (const [k, v] of attrEntries) lines.push(` ${stripControlChars(k)}: ${formatAttributeValue(v)}`);
|
|
68042
68149
|
}
|
|
68043
68150
|
const propEntries = Object.entries(resource.properties ?? {});
|
|
68044
68151
|
if (propEntries.length === 0) lines.push(" Properties: (none)");
|
|
68045
68152
|
else {
|
|
68046
68153
|
lines.push(" Properties:");
|
|
68047
|
-
for (const [k, v] of propEntries) lines.push(` ${k}: ${formatAttributeValue(v)}`);
|
|
68154
|
+
for (const [k, v] of propEntries) lines.push(` ${stripControlChars(k)}: ${formatAttributeValue(v)}`);
|
|
68048
68155
|
}
|
|
68049
68156
|
}
|
|
68050
68157
|
return lines;
|
|
@@ -68715,6 +68822,19 @@ async function stateRefreshObservedCommand(stackArgs, options) {
|
|
|
68715
68822
|
}
|
|
68716
68823
|
}
|
|
68717
68824
|
/**
|
|
68825
|
+
* The secrets map every redaction on this command's paths gets, and it is
|
|
68826
|
+
* EMPTY by construction (issue #1926).
|
|
68827
|
+
*
|
|
68828
|
+
* `cdkd state refresh-observed` neither synthesizes a template nor resolves a
|
|
68829
|
+
* dynamic reference, so no plaintext is ever recorded here and a VALUE scan
|
|
68830
|
+
* would have no needles at all. That is the issue #1900 shape, and it is why
|
|
68831
|
+
* the PATH pass has to carry the redaction on its own — see the call site.
|
|
68832
|
+
*
|
|
68833
|
+
* Shared rather than constructed per resource because nothing writes to it:
|
|
68834
|
+
* `redactSecretsForState` only reads its argument.
|
|
68835
|
+
*/
|
|
68836
|
+
const NO_RECORDED_SECRETS = /* @__PURE__ */ new Map();
|
|
68837
|
+
/**
|
|
68718
68838
|
* Refresh the `observedProperties` of every resource in one stack
|
|
68719
68839
|
* record. Returns counts so the caller can aggregate across `--all`.
|
|
68720
68840
|
*
|
|
@@ -68793,7 +68913,7 @@ async function refreshObservedForStack(stackName, region, stateBackend, lockMana
|
|
|
68793
68913
|
unsupported++;
|
|
68794
68914
|
return;
|
|
68795
68915
|
}
|
|
68796
|
-
resource.observedProperties = observed;
|
|
68916
|
+
resource.observedProperties = redactSecretsForState(observed, NO_RECORDED_SECRETS, resource.properties ?? {}, STATE_SOURCED_READBACK_RULES);
|
|
68797
68917
|
refreshed++;
|
|
68798
68918
|
} catch (err) {
|
|
68799
68919
|
failed++;
|
|
@@ -68834,7 +68954,7 @@ async function confirmRefresh(prompt) {
|
|
|
68834
68954
|
* Create the `state refresh-observed` subcommand.
|
|
68835
68955
|
*/
|
|
68836
68956
|
function createStateRefreshObservedCommand() {
|
|
68837
|
-
const cmd = new Command("refresh-observed").description("Refresh observedProperties for every resource in a stack by calling provider.readCurrentState — populates the drift baseline for stacks deployed before state schema v3, without redeploying.").argument("[stacks...]", "Stack name(s) to refresh (physical CloudFormation names)").option("--all", "Refresh every stack in the state bucket", false).option("--dry-run", "Print the per-stack refresh count without writing state", false).addOption(stackRegionOption$1()).action(withErrorHandling(stateRefreshObservedCommand));
|
|
68957
|
+
const cmd = new Command("refresh-observed").description("Refresh observedProperties for every resource in a stack by calling provider.readCurrentState — populates the drift baseline for stacks deployed before state schema v3, without redeploying. Run cdkd scrub first on state written by a pre-GHSA binary: the readback is redacted by POSITION against the record, so a record whose own properties still hold plaintext has nothing to redact from.").argument("[stacks...]", "Stack name(s) to refresh (physical CloudFormation names)").option("--all", "Refresh every stack in the state bucket", false).option("--dry-run", "Print the per-stack refresh count without writing state", false).addOption(stackRegionOption$1()).action(withErrorHandling(stateRefreshObservedCommand));
|
|
68838
68958
|
[...commonOptions, ...stateOptions].forEach((opt) => cmd.addOption(opt));
|
|
68839
68959
|
cmd.addOption(deprecatedRegionOption);
|
|
68840
68960
|
return cmd;
|
|
@@ -82361,7 +82481,7 @@ function createMigrateCommand() {
|
|
|
82361
82481
|
*/
|
|
82362
82482
|
function buildProgram() {
|
|
82363
82483
|
const program = new Command();
|
|
82364
|
-
program.name("cdkd").description("CDK Direct - Deploy AWS CDK apps directly via SDK/Cloud Control API").version("0.284.
|
|
82484
|
+
program.name("cdkd").description("CDK Direct - Deploy AWS CDK apps directly via SDK/Cloud Control API").version("0.284.9");
|
|
82365
82485
|
program.hook("preAction", (_thisCommand, actionCommand) => {
|
|
82366
82486
|
const { profile } = actionCommand.optsWithGlobals();
|
|
82367
82487
|
if (profile !== void 0) process.env["AWS_PROFILE"] = profile;
|