@go-to-k/cdkd 0.99.0 → 0.99.1
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/cli.js +143 -20
- package/dist/cli.js.map +1 -1
- package/dist/go-to-k-cdkd-0.99.1.tgz +0 -0
- package/package.json +1 -1
- package/dist/go-to-k-cdkd-0.99.0.tgz +0 -0
package/dist/cli.js
CHANGED
|
@@ -4217,23 +4217,83 @@ var S3BucketPolicyProvider = class {
|
|
|
4217
4217
|
/**
|
|
4218
4218
|
* Adopt an existing S3 bucket policy into cdkd state.
|
|
4219
4219
|
*
|
|
4220
|
-
*
|
|
4221
|
-
*
|
|
4222
|
-
*
|
|
4223
|
-
*
|
|
4220
|
+
* The operational identifier for an `S3::BucketPolicy` is the **bucket
|
|
4221
|
+
* name** — every AWS SDK call (`PutBucketPolicy` / `GetBucketPolicy` /
|
|
4222
|
+
* `DeleteBucketPolicy`) takes the bucket name via the `Bucket`
|
|
4223
|
+
* parameter, and cdkd's `create()` records `properties.Bucket` as the
|
|
4224
|
+
* resource's `physicalId` so subsequent `update()` / `delete()` /
|
|
4225
|
+
* `readCurrentState()` calls hit the right bucket. A `BucketPolicy`
|
|
4226
|
+
* has no standalone identity, no taggable ARN, and no `aws:cdk:path`
|
|
4227
|
+
* lookup — only the bucket itself is taggable.
|
|
4228
|
+
*
|
|
4229
|
+
* Resolution order (closes [#356](https://github.com/go-to-k/cdkd/issues/356)):
|
|
4230
|
+
*
|
|
4231
|
+
* 1. **`knownPhysicalId` if it matches an S3 bucket name shape.**
|
|
4232
|
+
* Preserves the `cdkd import --resource <logicalId>=<bucketName>`
|
|
4233
|
+
* path that has always worked.
|
|
4234
|
+
* 2. **`properties.Bucket` if it is a literal bucket name.** Closes
|
|
4235
|
+
* the `--migrate-from-cloudformation` case: AWS CloudFormation's
|
|
4236
|
+
* `DescribeStackResources` returns the CFn-generated policy NAME
|
|
4237
|
+
* for `AWS::S3::BucketPolicy` (e.g.
|
|
4238
|
+
* `MyStack-MyBucketPolicy-XXXXXXXXXX`), which is NOT a valid S3
|
|
4239
|
+
* bucket name. The first time cdkd touches the imported state with
|
|
4240
|
+
* that name, `readCurrentState` → `GetBucketPolicy` rejects it.
|
|
4241
|
+
* 3. **Hard error** when neither path resolves a bucket name. This
|
|
4242
|
+
* covers (a) `--migrate-from-cloudformation` against a CFn stack
|
|
4243
|
+
* whose template carries `Bucket: {Ref: <MyBucket>}` (the typical
|
|
4244
|
+
* CDK shape) when the referenced bucket is NOT in the importable
|
|
4245
|
+
* set (or hasn't been imported yet in the current run), and (b)
|
|
4246
|
+
* explicit `--resource <logicalId>=<non-bucket-name>` typos.
|
|
4247
|
+
* Pointing the user at `--resource <logicalId>=<bucketName>` is
|
|
4248
|
+
* the recovery path that always works.
|
|
4224
4249
|
*
|
|
4225
|
-
*
|
|
4226
|
-
*
|
|
4227
|
-
*
|
|
4250
|
+
* Intrinsic-valued `Bucket` (e.g. `{Ref: <MyBucket>}`) falls into
|
|
4251
|
+
* branch 3 here even when the referenced sibling has been imported in
|
|
4252
|
+
* the same run — `import()` is called BEFORE
|
|
4253
|
+
* `resolveImportedProperties` runs the synth template's Properties
|
|
4254
|
+
* through the intrinsic resolver, so the raw intrinsic object is what
|
|
4255
|
+
* we see. The recovery message names `--resource` as the explicit
|
|
4256
|
+
* escape hatch.
|
|
4228
4257
|
*/
|
|
4229
4258
|
async import(input) {
|
|
4230
|
-
if (input.knownPhysicalId) return {
|
|
4259
|
+
if (input.knownPhysicalId && isS3BucketName(input.knownPhysicalId)) return {
|
|
4231
4260
|
physicalId: input.knownPhysicalId,
|
|
4232
4261
|
attributes: {}
|
|
4233
4262
|
};
|
|
4234
|
-
|
|
4263
|
+
const bucket = input.properties["Bucket"];
|
|
4264
|
+
if (typeof bucket === "string" && isS3BucketName(bucket)) return {
|
|
4265
|
+
physicalId: bucket,
|
|
4266
|
+
attributes: {}
|
|
4267
|
+
};
|
|
4268
|
+
const knownNote = input.knownPhysicalId ? ` Got knownPhysicalId='${input.knownPhysicalId}' (not a valid S3 bucket name; CloudFormation returns the policy resource NAME for AWS::S3::BucketPolicy, which is not the operational identifier).` : "";
|
|
4269
|
+
const bucketNote = bucket !== void 0 ? ` Properties.Bucket=${JSON.stringify(bucket)} did not resolve to a literal bucket name (intrinsic-valued entries like {Ref: <Bucket>} are not resolved at import time).` : " Properties.Bucket is missing.";
|
|
4270
|
+
throw new Error(`Cannot determine bucket name for ${input.resourceType} '${input.logicalId}'.${knownNote}${bucketNote} Re-run with --resource ${input.logicalId}=<bucketName> (e.g. my-bucket-12345) to point cdkd at the bucket this policy is attached to.`);
|
|
4235
4271
|
}
|
|
4236
4272
|
};
|
|
4273
|
+
/**
|
|
4274
|
+
* Recognize an S3 bucket name. AWS rules
|
|
4275
|
+
* (https://docs.aws.amazon.com/AmazonS3/latest/userguide/bucketnamingrules.html):
|
|
4276
|
+
* - 3-63 characters
|
|
4277
|
+
* - lowercase letters, digits, hyphens, and dots
|
|
4278
|
+
* - must start and end with a letter or digit
|
|
4279
|
+
* - no consecutive dots
|
|
4280
|
+
* - no `xn--` prefix (reserved for IDN bucket names)
|
|
4281
|
+
* - no `-s3alias` suffix (reserved for S3 Access Point aliases)
|
|
4282
|
+
* - no `--ol-s3` suffix (reserved for S3 on Outposts)
|
|
4283
|
+
*
|
|
4284
|
+
* A practical pattern that excludes the obvious CFn-generated names like
|
|
4285
|
+
* `MyStack-MyBucketPolicy-XXXXXXXXXX` (which contain uppercase letters
|
|
4286
|
+
* and exceed 63 chars in common cases) while accepting every normal CDK
|
|
4287
|
+
* auto-generated and user-declared bucket name.
|
|
4288
|
+
*/
|
|
4289
|
+
function isS3BucketName(value) {
|
|
4290
|
+
if (value.length < 3 || value.length > 63) return false;
|
|
4291
|
+
if (!/^[a-z0-9][a-z0-9.-]*[a-z0-9]$/.test(value)) return false;
|
|
4292
|
+
if (value.includes("..")) return false;
|
|
4293
|
+
if (value.startsWith("xn--")) return false;
|
|
4294
|
+
if (value.endsWith("-s3alias") || value.endsWith("--ol-s3")) return false;
|
|
4295
|
+
return true;
|
|
4296
|
+
}
|
|
4237
4297
|
|
|
4238
4298
|
//#endregion
|
|
4239
4299
|
//#region src/provisioning/providers/sqs-queue-provider.ts
|
|
@@ -5593,22 +5653,60 @@ var SNSTopicPolicyProvider = class {
|
|
|
5593
5653
|
/**
|
|
5594
5654
|
* Adopt an existing SNS topic policy into cdkd state.
|
|
5595
5655
|
*
|
|
5596
|
-
*
|
|
5597
|
-
*
|
|
5598
|
-
*
|
|
5599
|
-
*
|
|
5600
|
-
*
|
|
5656
|
+
* The operational identifier for a `TopicPolicy` is the **comma-joined
|
|
5657
|
+
* list of SNS topic ARNs** the policy is attached to — every AWS SDK
|
|
5658
|
+
* call (`SetTopicAttributes` / `GetTopicAttributes`) takes a topic ARN
|
|
5659
|
+
* via the `TopicArn` parameter, and cdkd's `create()` records
|
|
5660
|
+
* `topics.join(',')` as the resource's `physicalId` so subsequent
|
|
5661
|
+
* `update()` / `delete()` / `readCurrentState()` calls hit the right
|
|
5662
|
+
* topic(s). A `TopicPolicy` has no standalone identity, no taggable
|
|
5663
|
+
* ARN, and no `aws:cdk:path` lookup — only the parent topics are
|
|
5664
|
+
* taggable.
|
|
5665
|
+
*
|
|
5666
|
+
* Resolution order (closes [#356](https://github.com/go-to-k/cdkd/issues/356)):
|
|
5667
|
+
*
|
|
5668
|
+
* 1. **`knownPhysicalId` if it is a comma-joined list of SNS topic ARNs.**
|
|
5669
|
+
* Preserves the `cdkd import --resource <logicalId>=<topic-arns>`
|
|
5670
|
+
* path that has always worked.
|
|
5671
|
+
* 2. **`properties.Topics.join(',')` if every entry is a literal topic
|
|
5672
|
+
* ARN.** Closes the `--migrate-from-cloudformation` case: AWS
|
|
5673
|
+
* CloudFormation's `DescribeStackResources` returns the CFn-generated
|
|
5674
|
+
* policy NAME for `AWS::SNS::TopicPolicy` (e.g.
|
|
5675
|
+
* `MyStack-MyTopicPolicy-XXXXXXXXXX`), which is NOT a valid topic
|
|
5676
|
+
* ARN. The first time cdkd touches the imported state with that
|
|
5677
|
+
* name, `readCurrentState` → `GetTopicAttributes` rejects it.
|
|
5678
|
+
* 3. **Hard error** when neither path resolves a topic-ARN list. This
|
|
5679
|
+
* covers (a) `--migrate-from-cloudformation` against a CFn stack
|
|
5680
|
+
* whose template carries `Topics: [{Ref: <MyTopic>}]` (the typical
|
|
5681
|
+
* CDK shape) when the referenced topic is NOT in the importable
|
|
5682
|
+
* set (or hasn't been imported yet in the current run), and (b)
|
|
5683
|
+
* explicit `--resource <logicalId>=<non-arn>` typos. Pointing the
|
|
5684
|
+
* user at `--resource <logicalId>=<topic-arns>` is the recovery
|
|
5685
|
+
* path that always works.
|
|
5601
5686
|
*
|
|
5602
|
-
*
|
|
5603
|
-
*
|
|
5604
|
-
*
|
|
5687
|
+
* Intrinsic-valued `Topics` entries (e.g. `{Ref: <MyTopic>}`) fall into
|
|
5688
|
+
* branch 3 here even when the referenced sibling has been imported in
|
|
5689
|
+
* the same run — `import()` is called BEFORE
|
|
5690
|
+
* `resolveImportedProperties` runs the synth template's Properties
|
|
5691
|
+
* through the intrinsic resolver, so the raw intrinsic object is what
|
|
5692
|
+
* we see. The recovery message names `--resource` as the explicit
|
|
5693
|
+
* escape hatch.
|
|
5605
5694
|
*/
|
|
5606
5695
|
async import(input) {
|
|
5607
|
-
if (input.knownPhysicalId) return {
|
|
5696
|
+
if (input.knownPhysicalId && isSnsTopicArnList(input.knownPhysicalId)) return {
|
|
5608
5697
|
physicalId: input.knownPhysicalId,
|
|
5609
5698
|
attributes: {}
|
|
5610
5699
|
};
|
|
5611
|
-
|
|
5700
|
+
const topics = input.properties["Topics"];
|
|
5701
|
+
if (Array.isArray(topics) && topics.length > 0) {
|
|
5702
|
+
if (topics.every((t) => typeof t === "string" && isSnsTopicArn(t))) return {
|
|
5703
|
+
physicalId: topics.join(","),
|
|
5704
|
+
attributes: {}
|
|
5705
|
+
};
|
|
5706
|
+
}
|
|
5707
|
+
const knownNote = input.knownPhysicalId ? ` Got knownPhysicalId='${input.knownPhysicalId}' (not a comma-joined list of SNS topic ARNs; CloudFormation returns the policy resource NAME for AWS::SNS::TopicPolicy, which is not the operational identifier).` : "";
|
|
5708
|
+
const topicsNote = Array.isArray(topics) && topics.length > 0 ? ` Properties.Topics=${JSON.stringify(topics)} did not resolve to a list of literal topic ARNs (intrinsic-valued entries like {Ref: <Topic>} are not resolved at import time).` : " Properties.Topics is missing or empty.";
|
|
5709
|
+
throw new Error(`Cannot determine topic ARNs for ${input.resourceType} '${input.logicalId}'.${knownNote}${topicsNote} Re-run with --resource ${input.logicalId}=<comma-joined-topic-ARNs> (e.g. arn:aws:sns:${input.region}:<account>:<topic-name>) to point cdkd at the topic(s) this policy is attached to.`);
|
|
5612
5710
|
}
|
|
5613
5711
|
/**
|
|
5614
5712
|
* Set the policy on a single SNS topic
|
|
@@ -5621,6 +5719,31 @@ var SNSTopicPolicyProvider = class {
|
|
|
5621
5719
|
}));
|
|
5622
5720
|
}
|
|
5623
5721
|
};
|
|
5722
|
+
/**
|
|
5723
|
+
* Recognize a single SNS topic ARN. AWS standard form is
|
|
5724
|
+
* `arn:<partition>:sns:<region>:<account>:<name>`; FIFO topics end in
|
|
5725
|
+
* `.fifo`. Accepts every partition (`aws` / `aws-cn` / `aws-us-gov` /
|
|
5726
|
+
* `aws-iso` / etc.) via the broader `arn:<partition>:sns:` prefix shape.
|
|
5727
|
+
*/
|
|
5728
|
+
function isSnsTopicArn(value) {
|
|
5729
|
+
return /^arn:[a-z0-9-]+:sns:[a-z0-9-]+:\d{12}:[\w.-]+$/.test(value);
|
|
5730
|
+
}
|
|
5731
|
+
/**
|
|
5732
|
+
* Recognize a comma-joined list of SNS topic ARNs. cdkd's `create()`
|
|
5733
|
+
* records `topics.join(',')` as the `physicalId`, so a single ARN
|
|
5734
|
+
* (`arn:aws:sns:us-east-1:123456789012:my-topic`) is also accepted.
|
|
5735
|
+
* Every comma-separated segment must be a valid SNS topic ARN — a CFn
|
|
5736
|
+
* generated name like `MyStack-MyTopicPolicy-XXX` is correctly rejected
|
|
5737
|
+
* because it does not match the ARN prefix, and a partially-valid
|
|
5738
|
+
* mixture (one literal ARN + one CFn name) is also rejected so we fall
|
|
5739
|
+
* back to the properties-based resolution rather than baking a half-bad
|
|
5740
|
+
* list into state.
|
|
5741
|
+
*/
|
|
5742
|
+
function isSnsTopicArnList(value) {
|
|
5743
|
+
const segments = value.split(",");
|
|
5744
|
+
if (segments.length === 0) return false;
|
|
5745
|
+
return segments.every((s) => isSnsTopicArn(s));
|
|
5746
|
+
}
|
|
5624
5747
|
|
|
5625
5748
|
//#endregion
|
|
5626
5749
|
//#region src/provisioning/providers/lambda-function-provider.ts
|
|
@@ -42424,7 +42547,7 @@ function reorderArgs(argv) {
|
|
|
42424
42547
|
*/
|
|
42425
42548
|
async function main() {
|
|
42426
42549
|
const program = new Command();
|
|
42427
|
-
program.name("cdkd").description("CDK Direct - Deploy AWS CDK apps directly via SDK/Cloud Control API").version("0.
|
|
42550
|
+
program.name("cdkd").description("CDK Direct - Deploy AWS CDK apps directly via SDK/Cloud Control API").version("0.99.0");
|
|
42428
42551
|
program.addCommand(createBootstrapCommand());
|
|
42429
42552
|
program.addCommand(createSynthCommand());
|
|
42430
42553
|
program.addCommand(createListCommand());
|