@go-to-k/cdkd 0.282.4 → 0.282.6
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-D9VJTwn3.js → asg-provider-Dm_dVhvQ.js} +2 -2
- package/dist/{asg-provider-D9VJTwn3.js.map → asg-provider-Dm_dVhvQ.js.map} +1 -1
- package/dist/cli.js +99 -41
- package/dist/cli.js.map +1 -1
- package/dist/{deploy-engine-CnxJLy3Y.js → deploy-engine-4K_iJ2rV.js} +107 -16
- package/dist/deploy-engine-4K_iJ2rV.js.map +1 -0
- package/dist/index.js +1 -1
- package/package.json +1 -1
- package/dist/deploy-engine-CnxJLy3Y.js.map +0 -1
|
@@ -2573,6 +2573,39 @@ const PARTITION_TABLE = [
|
|
|
2573
2573
|
}
|
|
2574
2574
|
];
|
|
2575
2575
|
/**
|
|
2576
|
+
* Fold an AWS region name to its canonical lower-case spelling.
|
|
2577
|
+
*
|
|
2578
|
+
* AWS region ids ARE lower case — `${AWS::Region}` always returns that form —
|
|
2579
|
+
* but nothing between a `--region` flag and an SDK client enforces it, and
|
|
2580
|
+
* essentially everything downstream is case-SENSITIVE (issue
|
|
2581
|
+
* [#1795](https://github.com/go-to-k/cdkd/issues/1795)):
|
|
2582
|
+
*
|
|
2583
|
+
* - This module's own `PARTITION_TABLE` walk is a `startsWith` prefix test, so
|
|
2584
|
+
* `--region CN-NORTH-1` fell through to the commercial partition and the
|
|
2585
|
+
* `cdkd local *` commands synthesized
|
|
2586
|
+
* `<acct>.dkr.ecr.CN-NORTH-1.amazonaws.com/...` — a `cn-` region carrying the
|
|
2587
|
+
* commercial suffix, a host that does not exist.
|
|
2588
|
+
* - The AWS SDK's endpoint resolution is case-sensitive in the SAME direction.
|
|
2589
|
+
* Measured against this repo's vendored `@aws-sdk/util-endpoints` partition
|
|
2590
|
+
* data: `cn-north-1` resolves `aws-cn` / `amazonaws.com.cn` while
|
|
2591
|
+
* `CN-NORTH-1` resolves `aws` / `amazonaws.com` (both the exact-match table
|
|
2592
|
+
* and the `regionRegex` fallback are case-sensitive). So EVERY SDK client
|
|
2593
|
+
* built from a raw region — `STSClient` for `${AWS::AccountId}`, the ECR /
|
|
2594
|
+
* SecretsManager / SSM clients further down the `cdkd local` path — talks to
|
|
2595
|
+
* the wrong partition's endpoint and fails.
|
|
2596
|
+
* - `${AWS::Region}` substituted from a raw value spells the region wrongly
|
|
2597
|
+
* inside every ARN the resolver builds from it.
|
|
2598
|
+
*
|
|
2599
|
+
* Applied BOTH in `derivePartitionAndUrlSuffix` (so any caller of the mapping
|
|
2600
|
+
* inherits it) AND at the `cdkd local *` region-resolution points (so the
|
|
2601
|
+
* region VALUE those commands hand to SDK clients and to `${AWS::Region}` is
|
|
2602
|
+
* canonical too). Double-folding is a no-op, which is what makes having it in
|
|
2603
|
+
* both places safe rather than redundant.
|
|
2604
|
+
*/
|
|
2605
|
+
function canonicalizeRegion(region) {
|
|
2606
|
+
return typeof region === "string" ? region.toLowerCase() : region;
|
|
2607
|
+
}
|
|
2608
|
+
/**
|
|
2576
2609
|
* Derive the AWS partition / URL suffix for an AWS region. Same mapping
|
|
2577
2610
|
* CloudFormation applies to `${AWS::Partition}` / `${AWS::URLSuffix}`.
|
|
2578
2611
|
*
|
|
@@ -2583,9 +2616,24 @@ const PARTITION_TABLE = [
|
|
|
2583
2616
|
* the COMMERCIAL suffix, so `parseEcrRegistryHost` (`src/utils/ecr-uri.ts`)
|
|
2584
2617
|
* rejected it under the strict host check issue #1758 added and the image was
|
|
2585
2618
|
* classified `public` — anonymous pull, no `docker login`, opaque failure.
|
|
2619
|
+
*
|
|
2620
|
+
* The region is CANONICALIZED through {@link canonicalizeRegion} before the
|
|
2621
|
+
* prefix tests (issue [#1795](https://github.com/go-to-k/cdkd/issues/1795)),
|
|
2622
|
+
* so every present and future caller inherits ONE normalization point and the
|
|
2623
|
+
* three `cdkd local *` call sites cannot drift apart again.
|
|
2624
|
+
*
|
|
2625
|
+
* This is only HALF the answer at those call sites, and the half it is NOT is
|
|
2626
|
+
* worth stating: canonicalizing here fixes the derived SUFFIX, but each caller
|
|
2627
|
+
* also passes the raw region VALUE to its SDK clients and stores it as
|
|
2628
|
+
* `${AWS::Region}`. The AWS SDK's own endpoint resolution is case-sensitive in
|
|
2629
|
+
* exactly the same way (measured against this repo's vendored
|
|
2630
|
+
* `@aws-sdk/util-endpoints` partition data: `CN-NORTH-1` resolves to the
|
|
2631
|
+
* COMMERCIAL `amazonaws.com`), so the callers canonicalize the value too — see
|
|
2632
|
+
* `canonicalizeRegion`'s own note.
|
|
2586
2633
|
*/
|
|
2587
2634
|
function derivePartitionAndUrlSuffix(region) {
|
|
2588
|
-
|
|
2635
|
+
const canonical = canonicalizeRegion(region);
|
|
2636
|
+
for (const { prefix, partition, urlSuffix } of PARTITION_TABLE) if (canonical.startsWith(prefix)) return {
|
|
2589
2637
|
partition,
|
|
2590
2638
|
urlSuffix
|
|
2591
2639
|
};
|
|
@@ -4613,6 +4661,59 @@ var DockerAssetPublisher = class {
|
|
|
4613
4661
|
}
|
|
4614
4662
|
};
|
|
4615
4663
|
|
|
4664
|
+
//#endregion
|
|
4665
|
+
//#region src/utils/deny-external-access-policy.ts
|
|
4666
|
+
/**
|
|
4667
|
+
* Build the `DenyExternalAccess` bucket policy cdkd applies to every bucket it
|
|
4668
|
+
* owns — the state bucket (`cdkd bootstrap`), the migration destination bucket
|
|
4669
|
+
* (`cdkd state-migrate`) and the asset bucket (`ensureAssetStorage`).
|
|
4670
|
+
*
|
|
4671
|
+
* The statement denies `s3:*` to every principal whose `aws:PrincipalAccount`
|
|
4672
|
+
* is not the bucket owner, so the resource ARNs it names are the whole
|
|
4673
|
+
* mechanism: a `Resource` that does not match the bucket makes the statement
|
|
4674
|
+
* apply to nothing, and the deny silently stops protecting anything.
|
|
4675
|
+
*
|
|
4676
|
+
* That is exactly what the hardcoded `arn:aws:` partition did outside the
|
|
4677
|
+
* commercial partition (issue
|
|
4678
|
+
* [#1794](https://github.com/go-to-k/cdkd/issues/1794), the residual of
|
|
4679
|
+
* [#1745](https://github.com/go-to-k/cdkd/issues/1745)). A bucket in `aws-cn`
|
|
4680
|
+
* is `arn:aws-cn:s3:::<bucket>`, so a statement naming `arn:aws:s3:::<bucket>`
|
|
4681
|
+
* matched no resource there. The policy was still structurally valid and
|
|
4682
|
+
* `PutBucketPolicy` still succeeded, which is what made the defect quiet —
|
|
4683
|
+
* cdkd reported "✓ Set bucket policy (deny external access)" over a bucket
|
|
4684
|
+
* that had no effective deny at all.
|
|
4685
|
+
*
|
|
4686
|
+
* The three call sites were byte-identical copies of this document before this
|
|
4687
|
+
* helper existed, and the partition literal drifted in all three at once. They
|
|
4688
|
+
* are centralized here so a fourth copy cannot re-introduce the same class:
|
|
4689
|
+
* the partition is derived from `region` in ONE place.
|
|
4690
|
+
*
|
|
4691
|
+
* @param bucketName - The bucket the policy is attached to.
|
|
4692
|
+
* @param accountId - The bucket owner; the only account the policy admits.
|
|
4693
|
+
* @param region - Any region in the BUCKET's partition; only the partition
|
|
4694
|
+
* prefix is read, the region itself never appears in the output. Pass the
|
|
4695
|
+
* region of the CLIENT that writes the bucket (`await
|
|
4696
|
+
* client.config.region()`), NOT a CLI `--region` variable: those fall back to
|
|
4697
|
+
* a hardcoded `us-east-1` when the flag is absent, while the client resolves
|
|
4698
|
+
* the profile region through the SDK chain — so the two disagree exactly for
|
|
4699
|
+
* the non-commercial user this helper exists to serve.
|
|
4700
|
+
* @returns The policy document, ready for `JSON.stringify`.
|
|
4701
|
+
*/
|
|
4702
|
+
function buildDenyExternalAccessPolicy(bucketName, accountId, region) {
|
|
4703
|
+
const { partition } = derivePartitionAndUrlSuffix(region);
|
|
4704
|
+
return {
|
|
4705
|
+
Version: "2012-10-17",
|
|
4706
|
+
Statement: [{
|
|
4707
|
+
Sid: "DenyExternalAccess",
|
|
4708
|
+
Effect: "Deny",
|
|
4709
|
+
Principal: "*",
|
|
4710
|
+
Action: "s3:*",
|
|
4711
|
+
Resource: [`arn:${partition}:s3:::${bucketName}`, `arn:${partition}:s3:::${bucketName}/*`],
|
|
4712
|
+
Condition: { StringNotEquals: { "aws:PrincipalAccount": accountId } }
|
|
4713
|
+
}]
|
|
4714
|
+
};
|
|
4715
|
+
}
|
|
4716
|
+
|
|
4616
4717
|
//#endregion
|
|
4617
4718
|
//#region src/assets/asset-storage.ts
|
|
4618
4719
|
/**
|
|
@@ -4861,17 +4962,7 @@ async function ensureAssetStorage(options) {
|
|
|
4861
4962
|
await s3Client.send(new PutBucketPolicyCommand({
|
|
4862
4963
|
Bucket: assetBucket,
|
|
4863
4964
|
ExpectedBucketOwner: accountId,
|
|
4864
|
-
Policy: JSON.stringify(
|
|
4865
|
-
Version: "2012-10-17",
|
|
4866
|
-
Statement: [{
|
|
4867
|
-
Sid: "DenyExternalAccess",
|
|
4868
|
-
Effect: "Deny",
|
|
4869
|
-
Principal: "*",
|
|
4870
|
-
Action: "s3:*",
|
|
4871
|
-
Resource: [`arn:aws:s3:::${assetBucket}`, `arn:aws:s3:::${assetBucket}/*`],
|
|
4872
|
-
Condition: { StringNotEquals: { "aws:PrincipalAccount": accountId } }
|
|
4873
|
-
}]
|
|
4874
|
-
})
|
|
4965
|
+
Policy: JSON.stringify(buildDenyExternalAccessPolicy(assetBucket, accountId, await s3Client.config.region()))
|
|
4875
4966
|
}));
|
|
4876
4967
|
logger.info("✓ Configured asset bucket (AES-256 encryption, public access block, deny external access)");
|
|
4877
4968
|
}
|
|
@@ -13754,7 +13845,7 @@ var CloudControlProvider = class {
|
|
|
13754
13845
|
if (context?.finalSnapshotIdentifier !== void 0) throw new ProvisioningError(`${logicalId} (${resourceType}) requires a final snapshot (DeletionPolicy: Snapshot), but the Cloud Control API delete route has no final-snapshot parameter. Re-run with --skip-final-snapshot after snapshotting manually, or retain the resource.`, resourceType, logicalId, physicalId);
|
|
13755
13846
|
if (context?.removeProtection === true && resourceType === "AWS::AutoScaling::AutoScalingGroup") {
|
|
13756
13847
|
this.logger.debug(`Delegating protected AutoScalingGroup ${logicalId} delete to the SDK ASGProvider (Cloud Control cannot force-delete a protected ASG)`);
|
|
13757
|
-
const { ASGProvider } = await import("./asg-provider-
|
|
13848
|
+
const { ASGProvider } = await import("./asg-provider-Dm_dVhvQ.js").then((n) => n.n);
|
|
13758
13849
|
await new ASGProvider().delete(logicalId, physicalId, resourceType, _properties, context);
|
|
13759
13850
|
return;
|
|
13760
13851
|
}
|
|
@@ -20671,7 +20762,7 @@ const FLUSH_INTERVAL_MS = 2e3;
|
|
|
20671
20762
|
const FLUSH_EVENT_THRESHOLD = 50;
|
|
20672
20763
|
/** Build-time cdkd version, with a dev fallback for non-built contexts. */
|
|
20673
20764
|
function getCdkdVersion() {
|
|
20674
|
-
return "0.282.
|
|
20765
|
+
return "0.282.6";
|
|
20675
20766
|
}
|
|
20676
20767
|
/**
|
|
20677
20768
|
* Generate a time-sortable unique run id, e.g.
|
|
@@ -22839,5 +22930,5 @@ var DeployEngine = class {
|
|
|
22839
22930
|
};
|
|
22840
22931
|
|
|
22841
22932
|
//#endregion
|
|
22842
|
-
export { configStringRefusal as $,
|
|
22843
|
-
//# sourceMappingURL=deploy-engine-
|
|
22933
|
+
export { configStringRefusal as $, resolveStateBucketWithDefaultAndSource as $t, green as A, NestedStackChildDirectDestroyError as An, BOOTSTRAP_MARKER_PREFIX as At, slowCcOperationTimeoutMs as B, isCdkdError as Bn, runDockerForeground as Bt, MULTI_REGION_RECREATE_BLOCKED_TYPES as C, DependencyError as Cn, stringifyValue as Ct, bold as D, LocalStartServiceError as Dn, loadPublishableAssetManifest as Dt, formatResourceLine as E, LocalMigrateError as En, createAssetRedirectResolver as Et, clearOnUpdateRemoval as F, StackHasActiveImportsError as Fn, validateContainerRepoName as Ft, getAccountInfo as G, synthesisStatusMessage as Gt, isTerminationProtectionPropagationError as H, withErrorHandling as Hn, AssetManifestLoader as Ht, ProviderRegistry as I, StackTerminationProtectionError as In, buildDenyExternalAccessPolicy as It, normalizeAwsTagsToCfn as J, resolveApp as Jt, refStateLookupFromResource as K, getDefaultStateBucketName as Kt, findActionableSilentDrops as L, StateError as Ln, buildDockerImage as Lt, yellow as M, ProvisioningError as Mn, getBootstrapMarkerKey as Mt, IAMRoleProvider as N, ResourceTimeoutError as Nn, parseBootstrapMarker as Nt, cyan as O, LockError as On, rewriteTemplateAssetReferences as Ot, collectInlinePolicyNamesManagedBySiblings as P, ResourceUpdateNotSupportedError as Pn, validateAssetBucketName as Pt, configBooleanRefusal as Q, resolveStateBucketWithDefault as Qt, findSilentDropProperties as R, SynthesisError as Rn, formatDockerLoginError as Rt, extractDeploymentEventError as S, ConfigError as Sn, AssetPublisher as St, renderStatefulReason as T, LocalInvokeBuildError as Tn, buildAssetRedirectMap as Tt, IntrinsicFunctionResolver as U, __exportAll as Un, getDockerImageBySourceHash as Ut, disableInstanceApiTermination as V, normalizeAwsError as Vn, runDockerStreaming as Vt, cfnRefValueFromPhysicalId as W, Synthesizer as Wt, assertRegionMatch as X, resolveCaptureObservedState as Xt, resolveExplicitPhysicalId as Y, resolveAutoAssetStorage as Yt, coerceCfnBoolean as Z, resolveSkipPrefix as Zt, createPreDeleteFinalSnapshot as _, getAwsClients as _n, TemplateParser as _t, DeploymentEventsStore as a, MIGRATE_TMP_PREFIX as an, s3BucketArn as at, unsupportedFinalSnapshotError as b, AssetError as bn, rebuildClientForBucketRegion as bt, replayFailedOperations as c, expectedOwnerParam as cn, s3BucketRegionalDomainName as ct, IMPLICIT_DELETE_DEPENDENCIES as d, derivePartitionAndUrlSuffix as dn, DiffCalculator as dt, resolveUseCdkBootstrapAssets as en, readConfigString as et, computeImplicitDeleteEdges as f, AssemblyReader as fn, describeTypeWithThrottleRetry as ft, ccRoutedFinalSnapshotError as g, AwsClients as gn, DagBuilder as gt, buildFinalSnapshotIdentifier as h, resolveBucketRegion as hn, isThrottlingError as ht, DeploymentEventsReader as i, CFN_TEMPLATE_URL_LIMIT as in, requireConfigString as it, red as j, PartialFailureError as jn, ensureAssetStorage as jt, gray as k, MissingCdkCliError as kn, AssetModeResolver as kt, replayRollback as l, PARTITION_TABLE as ln, s3BucketWebsiteUrl as lt, PRE_DELETE_SNAPSHOT_TYPES as m, clearBucketRegionCache as mn, isRetryableTransientError as mt, DEFAULT_RESOURCE_WARN_AFTER_MS as n, warnDeprecatedNoPrefixCliFlag as nn, requireConfigArray as nt, planFailedOps as o, findLargeInlineResources as on, s3BucketDomainName as ot, ATOMIC_FINAL_SNAPSHOT_TYPES as p, processStackMessages as pn, withRetry as pt, WAFv2WebACLProvider as q, getLegacyStateBucketName as qt, DeployEngine as r, CFN_TEMPLATE_BODY_LIMIT as rn, requireConfigObject as rt, planRollback as s, uploadCfnTemplate as sn, s3BucketDualStackDomainName as st, DEFAULT_RESOURCE_TIMEOUT_MS as t, stateBucketExistenceConfirmed as tn, replayWarn as tt, withResourceDeadline as u, canonicalizeRegion as un, applyRoleArnIfSet as ut, isFinalSnapshotError as v, resetAwsClients as vn, LockManager as vt, isStatefulRecreateTargetSync as w, DeployCancelledError as wn, WorkGraph as wt, makeCanonicalizePropertiesFn as x, CdkdError as xn, shouldRetainResource as xt, refusesFinalSnapshot as y, setAwsClients as yn, S3StateBackend as yt, CloudControlProvider as z, formatError as zn, getDockerCmd as zt };
|
|
22934
|
+
//# sourceMappingURL=deploy-engine-4K_iJ2rV.js.map
|