@go-to-k/cdkd 0.155.0 → 0.157.0
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/{aws-clients-BF03Alpe.js → aws-clients-B15NAPbL.js} +24 -1
- package/dist/aws-clients-B15NAPbL.js.map +1 -0
- package/dist/cli.js +401 -26
- package/dist/cli.js.map +1 -1
- package/dist/{deploy-engine-DWLTHfXj.js → deploy-engine-UmoqjtWH.js} +2063 -6
- package/dist/deploy-engine-UmoqjtWH.js.map +1 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -2
- package/package.json +2 -1
- package/dist/aws-clients-BF03Alpe.js.map +0 -1
- package/dist/deploy-engine-DWLTHfXj.js.map +0 -1
package/dist/cli.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { _ as withSkipPrefix, a as runDockerStreaming, c as getLogger, d as getLiveRenderer, f as PATTERN_B_NAME_PROPERTIES, g as generateResourceNameWithFallback, h as generateResourceName, i as runDockerForeground, n as formatDockerLoginError, p as PATTERN_B_RESOURCE_TYPES, r as getDockerCmd, u as runStackBuffered, v as withStackName } from "./docker-cmd-iDMcWcre.js";
|
|
3
|
-
import { $ as CdkdError, A as shouldRetainResource, B as resolveSkipPrefix, C as IntrinsicFunctionResolver, D as TemplateParser, E as DagBuilder, F as Synthesizer, G as CFN_TEMPLATE_URL_LIMIT, H as resolveStateBucketWithDefaultAndSource, I as getDefaultStateBucketName, J as uploadCfnTemplate, K as MIGRATE_TMP_PREFIX, L as getLegacyStateBucketName, M as stringifyValue, N as WorkGraph, O as LockManager, P as buildDockerImage, R as resolveApp, S as assertRegionMatch, T as DiffCalculator, U as warnDeprecatedNoPrefixCliFlag, V as resolveStateBucketWithDefault, W as CFN_TEMPLATE_BODY_LIMIT, Y as AssemblyReader, Z as resolveBucketRegion, _ as matchesCdkPath, a as withRetry, b as ProviderRegistry, bt as withErrorHandling, c as bold, ct as PartialFailureError, d as green, dt as ResourceUpdateNotSupportedError, f as red, ft as RouteDiscoveryError, g as CDK_PATH_TAG, h as collectInlinePolicyNamesManagedBySiblings, i as withResourceDeadline, it as LocalStartServiceError, j as AssetPublisher, k as S3StateBackend, l as cyan, lt as ProvisioningError, m as IAMRoleProvider, mt as StackTerminationProtectionError, n as DEFAULT_RESOURCE_WARN_AFTER_MS, nt as LocalInvokeBuildError, o as IMPLICIT_DELETE_DEPENDENCIES, ot as MissingCdkCliError, p as yellow, pt as StackHasActiveImportsError, q as findLargeInlineResources, r as DeployEngine, rt as LocalMigrateError, s as formatResourceLine, st as NestedStackChildDirectDestroyError, t as DEFAULT_RESOURCE_TIMEOUT_MS, u as gray, ut as ResourceTimeoutError, v as normalizeAwsTagsToCfn, w as applyRoleArnIfSet, x as CloudControlProvider, y as resolveExplicitPhysicalId, yt as normalizeAwsError, z as resolveCaptureObservedState } from "./deploy-engine-
|
|
4
|
-
import { a as setAwsClients, i as resetAwsClients, r as getAwsClients, t as AwsClients } from "./aws-clients-
|
|
3
|
+
import { $ as CdkdError, A as shouldRetainResource, B as resolveSkipPrefix, C as IntrinsicFunctionResolver, D as TemplateParser, E as DagBuilder, F as Synthesizer, G as CFN_TEMPLATE_URL_LIMIT, H as resolveStateBucketWithDefaultAndSource, I as getDefaultStateBucketName, J as uploadCfnTemplate, K as MIGRATE_TMP_PREFIX, L as getLegacyStateBucketName, M as stringifyValue, N as WorkGraph, O as LockManager, P as buildDockerImage, R as resolveApp, S as assertRegionMatch, T as DiffCalculator, U as warnDeprecatedNoPrefixCliFlag, V as resolveStateBucketWithDefault, W as CFN_TEMPLATE_BODY_LIMIT, Y as AssemblyReader, Z as resolveBucketRegion, _ as matchesCdkPath, a as withRetry, b as ProviderRegistry, bt as withErrorHandling, c as bold, ct as PartialFailureError, d as green, dt as ResourceUpdateNotSupportedError, f as red, ft as RouteDiscoveryError, g as CDK_PATH_TAG, h as collectInlinePolicyNamesManagedBySiblings, i as withResourceDeadline, it as LocalStartServiceError, j as AssetPublisher, k as S3StateBackend, l as cyan, lt as ProvisioningError, m as IAMRoleProvider, mt as StackTerminationProtectionError, n as DEFAULT_RESOURCE_WARN_AFTER_MS, nt as LocalInvokeBuildError, o as IMPLICIT_DELETE_DEPENDENCIES, ot as MissingCdkCliError, p as yellow, pt as StackHasActiveImportsError, q as findLargeInlineResources, r as DeployEngine, rt as LocalMigrateError, s as formatResourceLine, st as NestedStackChildDirectDestroyError, t as DEFAULT_RESOURCE_TIMEOUT_MS, u as gray, ut as ResourceTimeoutError, v as normalizeAwsTagsToCfn, w as applyRoleArnIfSet, x as CloudControlProvider, y as resolveExplicitPhysicalId, yt as normalizeAwsError, z as resolveCaptureObservedState } from "./deploy-engine-UmoqjtWH.js";
|
|
4
|
+
import { a as setAwsClients, i as resetAwsClients, r as getAwsClients, t as AwsClients } from "./aws-clients-B15NAPbL.js";
|
|
5
5
|
import { AsyncLocalStorage } from "node:async_hooks";
|
|
6
6
|
import { createHash, createHmac, createPublicKey, createVerify, randomBytes, randomUUID, timingSafeEqual } from "node:crypto";
|
|
7
7
|
import { CopyObjectCommand, CreateBucketCommand, DeleteBucketAnalyticsConfigurationCommand, DeleteBucketCommand, DeleteBucketCorsCommand, DeleteBucketIntelligentTieringConfigurationCommand, DeleteBucketInventoryConfigurationCommand, DeleteBucketLifecycleCommand, DeleteBucketMetricsConfigurationCommand, DeleteBucketPolicyCommand, DeleteBucketReplicationCommand, DeleteBucketTaggingCommand, DeleteBucketWebsiteCommand, DeleteObjectsCommand, GetBucketAccelerateConfigurationCommand, GetBucketCorsCommand, GetBucketEncryptionCommand, GetBucketLifecycleConfigurationCommand, GetBucketLocationCommand, GetBucketLoggingCommand, GetBucketNotificationConfigurationCommand, GetBucketPolicyCommand, GetBucketReplicationCommand, GetBucketTaggingCommand, GetBucketVersioningCommand, GetBucketWebsiteCommand, GetObjectCommand, GetObjectLockConfigurationCommand, GetPublicAccessBlockCommand, HeadBucketCommand, ListBucketAnalyticsConfigurationsCommand, ListBucketIntelligentTieringConfigurationsCommand, ListBucketInventoryConfigurationsCommand, ListBucketMetricsConfigurationsCommand, ListBucketsCommand, ListDirectoryBucketsCommand, 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";
|
|
@@ -21,6 +21,7 @@ import { CloudFrontClient, CreateCloudFrontOriginAccessIdentityCommand, CreateDi
|
|
|
21
21
|
import { CloudWatchClient, DeleteAlarmsCommand, DescribeAlarmsCommand, ListTagsForResourceCommand as ListTagsForResourceCommand$4, PutMetricAlarmCommand, TagResourceCommand as TagResourceCommand$6, UntagResourceCommand as UntagResourceCommand$6 } from "@aws-sdk/client-cloudwatch";
|
|
22
22
|
import { CloudWatchLogsClient, CreateLogGroupCommand, DeleteDataProtectionPolicyCommand, DeleteIndexPolicyCommand, DeleteLogGroupCommand, DeleteRetentionPolicyCommand, DescribeIndexPoliciesCommand, DescribeLogGroupsCommand, GetDataProtectionPolicyCommand, ListTagsForResourceCommand as ListTagsForResourceCommand$5, PutBearerTokenAuthenticationCommand, PutDataProtectionPolicyCommand, PutIndexPolicyCommand, PutLogGroupDeletionProtectionCommand, PutRetentionPolicyCommand, ResourceAlreadyExistsException, ResourceNotFoundException as ResourceNotFoundException$4, TagResourceCommand as TagResourceCommand$7, UntagResourceCommand as UntagResourceCommand$7 } from "@aws-sdk/client-cloudwatch-logs";
|
|
23
23
|
import { BedrockAgentCoreControlClient, CreateAgentRuntimeCommand, DeleteAgentRuntimeCommand, GetAgentRuntimeCommand, ResourceNotFoundException as ResourceNotFoundException$5, UpdateAgentRuntimeCommand } from "@aws-sdk/client-bedrock-agentcore-control";
|
|
24
|
+
import { ACMClient, AddTagsToCertificateCommand, DeleteCertificateCommand, DescribeCertificateCommand, ListCertificatesCommand, ListTagsForCertificateCommand, RemoveTagsFromCertificateCommand, RequestCertificateCommand, ResourceNotFoundException as ResourceNotFoundException$6, UpdateCertificateOptionsCommand } from "@aws-sdk/client-acm";
|
|
24
25
|
import * as fs from "node:fs";
|
|
25
26
|
import { cpSync, createWriteStream, existsSync, mkdirSync, mkdtempSync, readFileSync, readdirSync, rmSync, statSync, writeFileSync } from "node:fs";
|
|
26
27
|
import * as path from "node:path";
|
|
@@ -44,17 +45,17 @@ import { CreateClusterCommand, CreateServiceCommand, DeleteClusterCommand, Delet
|
|
|
44
45
|
import { AddTagsToResourceCommand as AddTagsToResourceCommand$2, CreateDBClusterCommand as CreateDBClusterCommand$1, CreateDBInstanceCommand as CreateDBInstanceCommand$1, CreateDBSubnetGroupCommand as CreateDBSubnetGroupCommand$1, DeleteDBClusterCommand as DeleteDBClusterCommand$1, DeleteDBInstanceCommand as DeleteDBInstanceCommand$1, DeleteDBSubnetGroupCommand as DeleteDBSubnetGroupCommand$1, DescribeDBClustersCommand as DescribeDBClustersCommand$1, DescribeDBInstancesCommand as DescribeDBInstancesCommand$1, DescribeDBSubnetGroupsCommand as DescribeDBSubnetGroupsCommand$1, DocDBClient, ListTagsForResourceCommand as ListTagsForResourceCommand$11, ModifyDBClusterCommand as ModifyDBClusterCommand$1, ModifyDBInstanceCommand as ModifyDBInstanceCommand$1, ModifyDBSubnetGroupCommand as ModifyDBSubnetGroupCommand$1, RemoveTagsFromResourceCommand as RemoveTagsFromResourceCommand$2 } from "@aws-sdk/client-docdb";
|
|
45
46
|
import { AddTagsToResourceCommand as AddTagsToResourceCommand$3, CreateDBClusterCommand as CreateDBClusterCommand$2, CreateDBInstanceCommand as CreateDBInstanceCommand$2, CreateDBSubnetGroupCommand as CreateDBSubnetGroupCommand$2, DeleteDBClusterCommand as DeleteDBClusterCommand$2, DeleteDBInstanceCommand as DeleteDBInstanceCommand$2, DeleteDBSubnetGroupCommand as DeleteDBSubnetGroupCommand$2, DescribeDBClustersCommand as DescribeDBClustersCommand$2, DescribeDBInstancesCommand as DescribeDBInstancesCommand$2, DescribeDBSubnetGroupsCommand as DescribeDBSubnetGroupsCommand$2, ListTagsForResourceCommand as ListTagsForResourceCommand$12, ModifyDBClusterCommand as ModifyDBClusterCommand$2, ModifyDBInstanceCommand as ModifyDBInstanceCommand$2, ModifyDBSubnetGroupCommand as ModifyDBSubnetGroupCommand$2, NeptuneClient, RemoveTagsFromResourceCommand as RemoveTagsFromResourceCommand$3 } from "@aws-sdk/client-neptune";
|
|
46
47
|
import { CreateWebACLCommand, DeleteWebACLCommand, GetWebACLCommand, ListTagsForResourceCommand as ListTagsForResourceCommand$13, ListWebACLsCommand, TagResourceCommand as TagResourceCommand$12, UntagResourceCommand as UntagResourceCommand$11, UpdateWebACLCommand, WAFNonexistentItemException, WAFV2Client } from "@aws-sdk/client-wafv2";
|
|
47
|
-
import { CognitoIdentityProviderClient, CreateUserPoolCommand, DeleteUserPoolCommand, DescribeUserPoolCommand, ListTagsForResourceCommand as ListTagsForResourceCommand$14, ListUserPoolsCommand, ResourceNotFoundException as ResourceNotFoundException$
|
|
48
|
+
import { CognitoIdentityProviderClient, CreateUserPoolCommand, DeleteUserPoolCommand, DescribeUserPoolCommand, ListTagsForResourceCommand as ListTagsForResourceCommand$14, ListUserPoolsCommand, ResourceNotFoundException as ResourceNotFoundException$7, UpdateUserPoolCommand } from "@aws-sdk/client-cognito-identity-provider";
|
|
48
49
|
import { AddTagsToResourceCommand as AddTagsToResourceCommand$4, CreateCacheClusterCommand, CreateCacheSubnetGroupCommand, DeleteCacheClusterCommand, DeleteCacheSubnetGroupCommand, DescribeCacheClustersCommand, DescribeCacheSubnetGroupsCommand, ElastiCacheClient, ListTagsForResourceCommand as ListTagsForResourceCommand$15, ModifyCacheClusterCommand, ModifyCacheSubnetGroupCommand, RemoveTagsFromResourceCommand as RemoveTagsFromResourceCommand$4 } from "@aws-sdk/client-elasticache";
|
|
49
50
|
import { CreatePrivateDnsNamespaceCommand, CreateServiceCommand as CreateServiceCommand$1, DeleteNamespaceCommand, DeleteServiceCommand as DeleteServiceCommand$1, GetNamespaceCommand, GetOperationCommand, GetServiceCommand, ListNamespacesCommand, ListServicesCommand as ListServicesCommand$1, ListTagsForResourceCommand as ListTagsForResourceCommand$16, NamespaceNotFound, ServiceDiscoveryClient, ServiceNotFound, UpdatePrivateDnsNamespaceCommand, UpdateServiceCommand as UpdateServiceCommand$1 } from "@aws-sdk/client-servicediscovery";
|
|
50
51
|
import { AppSyncClient, CreateApiKeyCommand, CreateDataSourceCommand, CreateGraphqlApiCommand, CreateResolverCommand, DeleteApiKeyCommand, DeleteDataSourceCommand, DeleteGraphqlApiCommand, DeleteResolverCommand, GetDataSourceCommand, GetGraphqlApiCommand, GetIntrospectionSchemaCommand, GetResolverCommand, ListApiKeysCommand, ListGraphqlApisCommand, NotFoundException as NotFoundException$4, StartSchemaCreationCommand, TagResourceCommand as TagResourceCommand$13, UntagResourceCommand as UntagResourceCommand$12, UpdateApiKeyCommand, UpdateDataSourceCommand, UpdateGraphqlApiCommand, UpdateResolverCommand } from "@aws-sdk/client-appsync";
|
|
51
52
|
import { parse, print } from "graphql";
|
|
52
53
|
import { CreateConnectionCommand, CreateCrawlerCommand, CreateDatabaseCommand, CreateJobCommand, CreateSecurityConfigurationCommand, CreateTableCommand as CreateTableCommand$1, CreateTriggerCommand, CreateWorkflowCommand, DeleteConnectionCommand, DeleteCrawlerCommand, DeleteDatabaseCommand, DeleteJobCommand, DeleteSecurityConfigurationCommand, DeleteTableCommand as DeleteTableCommand$1, DeleteTriggerCommand, DeleteWorkflowCommand, EntityNotFoundException, GetConnectionCommand, GetCrawlerCommand, GetDatabaseCommand, GetDatabasesCommand, GetJobCommand, GetSecurityConfigurationCommand, GetSecurityConfigurationsCommand, GetTableCommand, GetTablesCommand, GetTagsCommand, GetTriggerCommand, GetWorkflowCommand, GlueClient, ListWorkflowsCommand, StartCrawlerScheduleCommand, StartTriggerCommand, StopCrawlerScheduleCommand, StopTriggerCommand, UpdateConnectionCommand, UpdateCrawlerCommand, UpdateDatabaseCommand, UpdateJobCommand, UpdateTableCommand as UpdateTableCommand$1, UpdateTriggerCommand, UpdateWorkflowCommand } from "@aws-sdk/client-glue";
|
|
53
|
-
import { AddTagsToStreamCommand, CreateStreamCommand, DecreaseStreamRetentionPeriodCommand, DeleteStreamCommand, DeregisterStreamConsumerCommand, DescribeStreamCommand, DescribeStreamConsumerCommand, IncreaseStreamRetentionPeriodCommand, KinesisClient, ListStreamsCommand, ListTagsForResourceCommand as ListTagsForResourceCommand$17, ListTagsForStreamCommand, RegisterStreamConsumerCommand, RemoveTagsFromStreamCommand, ResourceNotFoundException as ResourceNotFoundException$
|
|
54
|
+
import { AddTagsToStreamCommand, CreateStreamCommand, DecreaseStreamRetentionPeriodCommand, DeleteStreamCommand, DeregisterStreamConsumerCommand, DescribeStreamCommand, DescribeStreamConsumerCommand, IncreaseStreamRetentionPeriodCommand, KinesisClient, ListStreamsCommand, ListTagsForResourceCommand as ListTagsForResourceCommand$17, ListTagsForStreamCommand, RegisterStreamConsumerCommand, RemoveTagsFromStreamCommand, ResourceNotFoundException as ResourceNotFoundException$8, StartStreamEncryptionCommand, StopStreamEncryptionCommand, TagResourceCommand as TagResourceCommand$14, UntagResourceCommand as UntagResourceCommand$13, UpdateShardCountCommand } from "@aws-sdk/client-kinesis";
|
|
54
55
|
import { AccessPointNotFound, CreateAccessPointCommand, CreateFileSystemCommand, CreateMountTargetCommand, DeleteAccessPointCommand, DeleteFileSystemCommand, DeleteMountTargetCommand, DescribeAccessPointsCommand, DescribeBackupPolicyCommand, DescribeFileSystemsCommand, DescribeLifecycleConfigurationCommand, DescribeMountTargetSecurityGroupsCommand, DescribeMountTargetsCommand, EFSClient, FileSystemNotFound, ModifyMountTargetSecurityGroupsCommand, MountTargetNotFound, UpdateFileSystemCommand } from "@aws-sdk/client-efs";
|
|
55
|
-
import { CreateDeliveryStreamCommand, DeleteDeliveryStreamCommand, DescribeDeliveryStreamCommand, FirehoseClient, ListDeliveryStreamsCommand, ListTagsForDeliveryStreamCommand, ResourceNotFoundException as ResourceNotFoundException$
|
|
56
|
+
import { CreateDeliveryStreamCommand, DeleteDeliveryStreamCommand, DescribeDeliveryStreamCommand, FirehoseClient, ListDeliveryStreamsCommand, ListTagsForDeliveryStreamCommand, ResourceNotFoundException as ResourceNotFoundException$9, TagDeliveryStreamCommand, UntagDeliveryStreamCommand, UpdateDestinationCommand } from "@aws-sdk/client-firehose";
|
|
56
57
|
import { AddTagsCommand as AddTagsCommand$1, CloudTrailClient, CreateTrailCommand, DeleteTrailCommand, GetEventSelectorsCommand, GetInsightSelectorsCommand, GetTrailCommand, GetTrailStatusCommand, ListTagsCommand as ListTagsCommand$1, ListTrailsCommand, PutEventSelectorsCommand, PutInsightSelectorsCommand, RemoveTagsCommand as RemoveTagsCommand$1, StartLoggingCommand, StopLoggingCommand, TrailNotFoundException, UpdateTrailCommand } from "@aws-sdk/client-cloudtrail";
|
|
57
|
-
import { BatchGetProjectsCommand, CodeBuildClient, CreateProjectCommand, DeleteProjectCommand, ListProjectsCommand, ResourceNotFoundException as ResourceNotFoundException$
|
|
58
|
+
import { BatchGetProjectsCommand, CodeBuildClient, CreateProjectCommand, DeleteProjectCommand, ListProjectsCommand, ResourceNotFoundException as ResourceNotFoundException$10, UpdateProjectCommand } from "@aws-sdk/client-codebuild";
|
|
58
59
|
import { CreateVectorBucketCommand, DeleteIndexCommand, DeleteVectorBucketCommand, GetVectorBucketCommand, ListIndexesCommand, ListTagsForResourceCommand as ListTagsForResourceCommand$18, ListVectorBucketsCommand, S3VectorsClient } from "@aws-sdk/client-s3vectors";
|
|
59
60
|
import { CreateNamespaceCommand, CreateTableBucketCommand, CreateTableCommand as CreateTableCommand$2, DeleteNamespaceCommand as DeleteNamespaceCommand$1, DeleteTableBucketCommand, DeleteTableCommand as DeleteTableCommand$2, GetTableBucketCommand, GetTableCommand as GetTableCommand$1, ListNamespacesCommand as ListNamespacesCommand$1, ListTableBucketsCommand, ListTablesCommand as ListTablesCommand$1, ListTagsForResourceCommand as ListTagsForResourceCommand$19, NotFoundException as NotFoundException$5, S3TablesClient } from "@aws-sdk/client-s3tables";
|
|
60
61
|
import { AttachLoadBalancerTargetGroupsCommand, AttachLoadBalancersCommand, AttachTrafficSourcesCommand, AutoScalingClient, CreateAutoScalingGroupCommand, CreateOrUpdateTagsCommand, DeleteAutoScalingGroupCommand, DeleteLifecycleHookCommand, DeleteNotificationConfigurationCommand, DeleteTagsCommand as DeleteTagsCommand$1, DescribeAutoScalingGroupsCommand, DescribeLifecycleHooksCommand, DescribeNotificationConfigurationsCommand, DescribeTrafficSourcesCommand, DetachLoadBalancerTargetGroupsCommand, DetachLoadBalancersCommand, DetachTrafficSourcesCommand, DisableMetricsCollectionCommand, EnableMetricsCollectionCommand, PutLifecycleHookCommand, PutNotificationConfigurationCommand, UpdateAutoScalingGroupCommand } from "@aws-sdk/client-auto-scaling";
|
|
@@ -395,6 +396,33 @@ function parseAllowUnsupportedTypesToken(value, previous) {
|
|
|
395
396
|
return [...previous ?? [], ...parsed];
|
|
396
397
|
}
|
|
397
398
|
const allowUnsupportedTypesOption = new Option("--allow-unsupported-types <types>", "Comma-separated resource types to attempt via Cloud Control even though cdkd reports them unsupported (AWS NON_PROVISIONABLE). Escape hatch — Cloud Control will likely still fail. Example: --allow-unsupported-types AWS::Foo::Bar,AWS::Baz::Qux").argParser(parseAllowUnsupportedTypesToken);
|
|
399
|
+
/**
|
|
400
|
+
* Escape hatch for the property-level silent-drop pre-flight reject.
|
|
401
|
+
* Comma-separated (and repeatable) `<ResourceType>:<PropertyName>` tokens
|
|
402
|
+
* the user explicitly accepts as silently dropped at deploy time. Per
|
|
403
|
+
* type+property pair (not blanket) so each silent drop is acknowledged
|
|
404
|
+
* by name.
|
|
405
|
+
*
|
|
406
|
+
* Format-checks each token against `<Namespace>::<Service>::<Type>:<Prop>`
|
|
407
|
+
* with both halves PascalCase, so a typo aborts at parse time instead of
|
|
408
|
+
* being silently added to the allowlist with no effect.
|
|
409
|
+
*
|
|
410
|
+
* The check is Tier-1-only by design (Cloud Control forwards every property
|
|
411
|
+
* to AWS, so there is no write-side silent drop for Tier 2 / Custom). A
|
|
412
|
+
* `Custom::Foo:Bar` token is therefore always a user mistake — it would be
|
|
413
|
+
* added to the allowlist but never consulted at runtime. Reject it at parse
|
|
414
|
+
* time so the user sees the error immediately.
|
|
415
|
+
*/
|
|
416
|
+
const RESOURCE_PROPERTY_FORMAT = /^[A-Z][A-Za-z0-9]+(::[A-Z][A-Za-z0-9]+)+:[A-Z][A-Za-z0-9]*$/;
|
|
417
|
+
function parseAllowUnsupportedPropertiesToken(value, previous) {
|
|
418
|
+
const parsed = value.split(",").map((s) => s.trim()).filter(Boolean);
|
|
419
|
+
for (const token of parsed) {
|
|
420
|
+
if (!RESOURCE_PROPERTY_FORMAT.test(token)) throw new Error(`Invalid --allow-unsupported-properties value "${token}": expected <ResourceType>:<PropertyName> with PascalCase on both halves (e.g. AWS::Lambda::Function:LoggingConfig).`);
|
|
421
|
+
if (token.startsWith("Custom::")) throw new Error(`Invalid --allow-unsupported-properties value "${token}": Custom:: resources are routed through cfn-response and have no write-side silent drop at cdkd, so the flag would have no effect. Use --allow-unsupported-types for type-level escape hatches instead.`);
|
|
422
|
+
}
|
|
423
|
+
return [...previous ?? [], ...parsed];
|
|
424
|
+
}
|
|
425
|
+
const allowUnsupportedPropertiesOption = new Option("--allow-unsupported-properties <entries>", "Comma-separated <ResourceType>:<PropertyName> tokens to accept as silently dropped at deploy time. Escape hatch — the property will NOT be written to AWS, the deployed resource will be missing the field. Example: --allow-unsupported-properties AWS::Lambda::Function:LoggingConfig,AWS::RDS::DBInstance:CACertificateIdentifier").argParser(parseAllowUnsupportedPropertiesToken);
|
|
398
426
|
const deployOptions = [
|
|
399
427
|
new Option("--concurrency <number>", "Maximum concurrent resource operations").default(10).argParser((value) => parseInt(value, 10)),
|
|
400
428
|
new Option("--stack-concurrency <number>", "Maximum concurrent stack deployments").default(4).argParser((value) => parseInt(value, 10)),
|
|
@@ -409,6 +437,7 @@ const deployOptions = [
|
|
|
409
437
|
aggressiveVpcParallelOption,
|
|
410
438
|
new Option("-e, --exclusively", "Only deploy requested stacks, do not include dependencies").default(false),
|
|
411
439
|
allowUnsupportedTypesOption,
|
|
440
|
+
allowUnsupportedPropertiesOption,
|
|
412
441
|
...resourceTimeoutOptions
|
|
413
442
|
];
|
|
414
443
|
/**
|
|
@@ -22615,7 +22644,7 @@ var CognitoUserPoolProvider = class {
|
|
|
22615
22644
|
if (!templatedActive) try {
|
|
22616
22645
|
needsFlip = (await this.getClient().send(new DescribeUserPoolCommand({ UserPoolId: physicalId }))).UserPool?.DeletionProtection === "ACTIVE";
|
|
22617
22646
|
} catch (descError) {
|
|
22618
|
-
if (descError instanceof ResourceNotFoundException$
|
|
22647
|
+
if (descError instanceof ResourceNotFoundException$7) {
|
|
22619
22648
|
assertRegionMatch(await this.getClient().config.region(), context?.expectedRegion, resourceType, logicalId, physicalId);
|
|
22620
22649
|
this.logger.debug(`Cognito User Pool ${physicalId} does not exist, skipping deletion`);
|
|
22621
22650
|
return;
|
|
@@ -22638,7 +22667,7 @@ var CognitoUserPoolProvider = class {
|
|
|
22638
22667
|
await this.getClient().send(new DeleteUserPoolCommand({ UserPoolId: physicalId }));
|
|
22639
22668
|
this.logger.debug(`Successfully deleted Cognito User Pool ${logicalId}`);
|
|
22640
22669
|
} catch (error) {
|
|
22641
|
-
if (error instanceof ResourceNotFoundException$
|
|
22670
|
+
if (error instanceof ResourceNotFoundException$7) {
|
|
22642
22671
|
assertRegionMatch(await this.getClient().config.region(), context?.expectedRegion, resourceType, logicalId, physicalId);
|
|
22643
22672
|
this.logger.debug(`Cognito User Pool ${physicalId} does not exist, skipping deletion`);
|
|
22644
22673
|
return;
|
|
@@ -22671,7 +22700,7 @@ var CognitoUserPoolProvider = class {
|
|
|
22671
22700
|
try {
|
|
22672
22701
|
resp = await this.getClient().send(new DescribeUserPoolCommand({ UserPoolId: physicalId }));
|
|
22673
22702
|
} catch (err) {
|
|
22674
|
-
if (err instanceof ResourceNotFoundException$
|
|
22703
|
+
if (err instanceof ResourceNotFoundException$7) return void 0;
|
|
22675
22704
|
throw err;
|
|
22676
22705
|
}
|
|
22677
22706
|
const pool = resp.UserPool;
|
|
@@ -22726,7 +22755,7 @@ var CognitoUserPoolProvider = class {
|
|
|
22726
22755
|
attributes: {}
|
|
22727
22756
|
};
|
|
22728
22757
|
} catch (err) {
|
|
22729
|
-
if (err instanceof ResourceNotFoundException$
|
|
22758
|
+
if (err instanceof ResourceNotFoundException$7) return null;
|
|
22730
22759
|
throw err;
|
|
22731
22760
|
}
|
|
22732
22761
|
const desiredName = typeof input.properties?.["UserPoolName"] === "string" ? input.properties["UserPoolName"] : void 0;
|
|
@@ -22750,7 +22779,7 @@ var CognitoUserPoolProvider = class {
|
|
|
22750
22779
|
attributes: {}
|
|
22751
22780
|
};
|
|
22752
22781
|
} catch (err) {
|
|
22753
|
-
if (err instanceof ResourceNotFoundException$
|
|
22782
|
+
if (err instanceof ResourceNotFoundException$7) continue;
|
|
22754
22783
|
throw err;
|
|
22755
22784
|
}
|
|
22756
22785
|
}
|
|
@@ -26980,7 +27009,7 @@ var KinesisStreamProvider = class {
|
|
|
26980
27009
|
}));
|
|
26981
27010
|
this.logger.debug(`Successfully deleted Kinesis stream ${logicalId}`);
|
|
26982
27011
|
} catch (error) {
|
|
26983
|
-
if (error instanceof ResourceNotFoundException$
|
|
27012
|
+
if (error instanceof ResourceNotFoundException$8) {
|
|
26984
27013
|
assertRegionMatch(await this.getClient().config.region(), context?.expectedRegion, resourceType, logicalId, physicalId);
|
|
26985
27014
|
this.logger.debug(`Kinesis stream ${physicalId} does not exist, skipping deletion`);
|
|
26986
27015
|
return;
|
|
@@ -27060,7 +27089,7 @@ var KinesisStreamProvider = class {
|
|
|
27060
27089
|
try {
|
|
27061
27090
|
stream = (await this.getClient().send(new DescribeStreamCommand({ StreamName: physicalId }))).StreamDescription;
|
|
27062
27091
|
} catch (err) {
|
|
27063
|
-
if (err instanceof ResourceNotFoundException$
|
|
27092
|
+
if (err instanceof ResourceNotFoundException$8) return void 0;
|
|
27064
27093
|
throw err;
|
|
27065
27094
|
}
|
|
27066
27095
|
if (!stream) return void 0;
|
|
@@ -27078,7 +27107,7 @@ var KinesisStreamProvider = class {
|
|
|
27078
27107
|
try {
|
|
27079
27108
|
result["Tags"] = normalizeAwsTagsToCfn((await this.getClient().send(new ListTagsForStreamCommand({ StreamName: physicalId }))).Tags);
|
|
27080
27109
|
} catch (err) {
|
|
27081
|
-
if (err instanceof ResourceNotFoundException$
|
|
27110
|
+
if (err instanceof ResourceNotFoundException$8) return void 0;
|
|
27082
27111
|
this.logger.debug(`Kinesis ListTagsForStream(${physicalId}) failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
27083
27112
|
}
|
|
27084
27113
|
return result;
|
|
@@ -27092,7 +27121,7 @@ var KinesisStreamProvider = class {
|
|
|
27092
27121
|
attributes: {}
|
|
27093
27122
|
};
|
|
27094
27123
|
} catch (err) {
|
|
27095
|
-
if (err instanceof ResourceNotFoundException$
|
|
27124
|
+
if (err instanceof ResourceNotFoundException$8) return null;
|
|
27096
27125
|
throw err;
|
|
27097
27126
|
}
|
|
27098
27127
|
if (!input.cdkPath) return null;
|
|
@@ -27263,7 +27292,7 @@ var KinesisStreamConsumerProvider = class {
|
|
|
27263
27292
|
await this.getClient().send(new DeregisterStreamConsumerCommand({ ConsumerARN: physicalId }));
|
|
27264
27293
|
this.logger.debug(`Successfully deregistered Kinesis stream consumer ${logicalId}`);
|
|
27265
27294
|
} catch (error) {
|
|
27266
|
-
if (error instanceof ResourceNotFoundException$
|
|
27295
|
+
if (error instanceof ResourceNotFoundException$8) {
|
|
27267
27296
|
assertRegionMatch(await this.getClient().config.region(), context?.expectedRegion, resourceType, logicalId, physicalId);
|
|
27268
27297
|
this.logger.debug(`Kinesis stream consumer ${physicalId} not found, skipping`);
|
|
27269
27298
|
return;
|
|
@@ -27309,7 +27338,7 @@ var KinesisStreamConsumerProvider = class {
|
|
|
27309
27338
|
try {
|
|
27310
27339
|
desc = (await this.getClient().send(new DescribeStreamConsumerCommand({ ConsumerARN: physicalId }))).ConsumerDescription;
|
|
27311
27340
|
} catch (err) {
|
|
27312
|
-
if (err instanceof ResourceNotFoundException$
|
|
27341
|
+
if (err instanceof ResourceNotFoundException$8) return void 0;
|
|
27313
27342
|
throw err;
|
|
27314
27343
|
}
|
|
27315
27344
|
if (!desc) return void 0;
|
|
@@ -27319,7 +27348,7 @@ var KinesisStreamConsumerProvider = class {
|
|
|
27319
27348
|
try {
|
|
27320
27349
|
result["Tags"] = normalizeAwsTagsToCfn((await this.getClient().send(new ListTagsForResourceCommand$17({ ResourceARN: physicalId }))).Tags);
|
|
27321
27350
|
} catch (err) {
|
|
27322
|
-
if (err instanceof ResourceNotFoundException$
|
|
27351
|
+
if (err instanceof ResourceNotFoundException$8) return void 0;
|
|
27323
27352
|
this.logger.debug(`ListTagsForResource(${physicalId}) failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
27324
27353
|
result["Tags"] = [];
|
|
27325
27354
|
}
|
|
@@ -28386,7 +28415,7 @@ var FirehoseProvider = class {
|
|
|
28386
28415
|
await this.getClient().send(new DeleteDeliveryStreamCommand({ DeliveryStreamName: physicalId }));
|
|
28387
28416
|
this.logger.debug(`Successfully deleted Firehose delivery stream ${logicalId}`);
|
|
28388
28417
|
} catch (error) {
|
|
28389
|
-
if (error instanceof ResourceNotFoundException$
|
|
28418
|
+
if (error instanceof ResourceNotFoundException$9) {
|
|
28390
28419
|
assertRegionMatch(await this.getClient().config.region(), context?.expectedRegion, resourceType, logicalId, physicalId);
|
|
28391
28420
|
this.logger.debug(`Firehose delivery stream ${physicalId} does not exist, skipping deletion`);
|
|
28392
28421
|
return;
|
|
@@ -28923,7 +28952,7 @@ var FirehoseProvider = class {
|
|
|
28923
28952
|
try {
|
|
28924
28953
|
desc = (await this.getClient().send(new DescribeDeliveryStreamCommand({ DeliveryStreamName: physicalId }))).DeliveryStreamDescription;
|
|
28925
28954
|
} catch (err) {
|
|
28926
|
-
if (err instanceof ResourceNotFoundException$
|
|
28955
|
+
if (err instanceof ResourceNotFoundException$9) return void 0;
|
|
28927
28956
|
throw err;
|
|
28928
28957
|
}
|
|
28929
28958
|
if (!desc) return void 0;
|
|
@@ -28954,7 +28983,7 @@ var FirehoseProvider = class {
|
|
|
28954
28983
|
try {
|
|
28955
28984
|
result["Tags"] = normalizeAwsTagsToCfn((await this.getClient().send(new ListTagsForDeliveryStreamCommand({ DeliveryStreamName: physicalId }))).Tags);
|
|
28956
28985
|
} catch (err) {
|
|
28957
|
-
if (err instanceof ResourceNotFoundException$
|
|
28986
|
+
if (err instanceof ResourceNotFoundException$9) return void 0;
|
|
28958
28987
|
this.logger.debug(`Firehose ListTagsForDeliveryStream(${physicalId}) failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
28959
28988
|
result["Tags"] = [];
|
|
28960
28989
|
}
|
|
@@ -28991,7 +29020,7 @@ var FirehoseProvider = class {
|
|
|
28991
29020
|
attributes: {}
|
|
28992
29021
|
};
|
|
28993
29022
|
} catch (err) {
|
|
28994
|
-
if (err instanceof ResourceNotFoundException$
|
|
29023
|
+
if (err instanceof ResourceNotFoundException$9) return null;
|
|
28995
29024
|
throw err;
|
|
28996
29025
|
}
|
|
28997
29026
|
if (!input.cdkPath) return null;
|
|
@@ -29762,7 +29791,7 @@ var CodeBuildProvider = class {
|
|
|
29762
29791
|
await this.getClient().send(new DeleteProjectCommand({ name: physicalId }));
|
|
29763
29792
|
this.logger.debug(`Successfully deleted CodeBuild Project ${logicalId}`);
|
|
29764
29793
|
} catch (error) {
|
|
29765
|
-
if (error instanceof ResourceNotFoundException$
|
|
29794
|
+
if (error instanceof ResourceNotFoundException$10) {
|
|
29766
29795
|
assertRegionMatch(await this.getClient().config.region(), context?.expectedRegion, resourceType, logicalId, physicalId);
|
|
29767
29796
|
this.logger.debug(`CodeBuild Project ${physicalId} does not exist, skipping deletion`);
|
|
29768
29797
|
return;
|
|
@@ -29817,7 +29846,7 @@ var CodeBuildProvider = class {
|
|
|
29817
29846
|
try {
|
|
29818
29847
|
project = (await this.getClient().send(new BatchGetProjectsCommand({ names: [physicalId] }))).projects?.[0];
|
|
29819
29848
|
} catch (err) {
|
|
29820
|
-
if (err instanceof ResourceNotFoundException$
|
|
29849
|
+
if (err instanceof ResourceNotFoundException$10) return void 0;
|
|
29821
29850
|
throw err;
|
|
29822
29851
|
}
|
|
29823
29852
|
if (!project) return void 0;
|
|
@@ -29961,7 +29990,7 @@ var CodeBuildProvider = class {
|
|
|
29961
29990
|
attributes: {}
|
|
29962
29991
|
} : null;
|
|
29963
29992
|
} catch (err) {
|
|
29964
|
-
if (err instanceof ResourceNotFoundException$
|
|
29993
|
+
if (err instanceof ResourceNotFoundException$10) return null;
|
|
29965
29994
|
throw err;
|
|
29966
29995
|
}
|
|
29967
29996
|
if (!input.cdkPath) return null;
|
|
@@ -32497,6 +32526,350 @@ var NestedStackProvider = class {
|
|
|
32497
32526
|
}
|
|
32498
32527
|
};
|
|
32499
32528
|
|
|
32529
|
+
//#endregion
|
|
32530
|
+
//#region src/provisioning/providers/acm-certificate-provider.ts
|
|
32531
|
+
/**
|
|
32532
|
+
* AWS ACM Certificate Provider
|
|
32533
|
+
*
|
|
32534
|
+
* Implements `AWS::CertificateManager::Certificate` using the ACM SDK.
|
|
32535
|
+
*
|
|
32536
|
+
* **DNS / EMAIL validation is asynchronous.** `RequestCertificate` returns
|
|
32537
|
+
* immediately with status `PENDING_VALIDATION`; the certificate only reaches
|
|
32538
|
+
* `ISSUED` once AWS has confirmed the DNS records (or the email click).
|
|
32539
|
+
*
|
|
32540
|
+
* `create()` polls `DescribeCertificate` until status flips to `ISSUED`. On
|
|
32541
|
+
* the first poll that returns PENDING_VALIDATION, the provider logs the
|
|
32542
|
+
* `DomainValidationOptions` AWS posted so the user knows which CNAME records
|
|
32543
|
+
* to add to their DNS zone. `CDKD_NO_WAIT=true` (or `cdkd deploy --no-wait`)
|
|
32544
|
+
* short-circuits the loop and returns immediately with the ARN — downstream
|
|
32545
|
+
* consumers (CloudFront, ALB) will fail to start if they reach the cert
|
|
32546
|
+
* before it issues, but that's the documented trade-off.
|
|
32547
|
+
*
|
|
32548
|
+
* **CloudFront cross-region note**: ACM certificates referenced by a
|
|
32549
|
+
* CloudFront Distribution MUST live in `us-east-1`. cdkd does not enforce
|
|
32550
|
+
* this — it's the developer's responsibility to deploy the certificate
|
|
32551
|
+
* stack to `us-east-1`. The provider uses the single ACMClient configured
|
|
32552
|
+
* in `aws-clients.ts` (region = stack's region) and does NOT override.
|
|
32553
|
+
*
|
|
32554
|
+
* Physical id is the certificate ARN. CFn exposes only `Ref` (returns the
|
|
32555
|
+
* ARN); `getAttribute('Arn')` / `getAttribute('CertificateArn')` also
|
|
32556
|
+
* return the ARN for any defensive call site.
|
|
32557
|
+
*/
|
|
32558
|
+
var ACMCertificateProvider = class {
|
|
32559
|
+
acmClient;
|
|
32560
|
+
logger = getLogger().child("ACMCertificateProvider");
|
|
32561
|
+
maxPollAttempts = Number(process.env["CDKD_ACM_POLL_ATTEMPTS"] ?? 60);
|
|
32562
|
+
pollIntervalMs = Number(process.env["CDKD_ACM_POLL_INTERVAL_MS"] ?? 1e4);
|
|
32563
|
+
constructor() {
|
|
32564
|
+
this.acmClient = getAwsClients().acm;
|
|
32565
|
+
}
|
|
32566
|
+
handledProperties = new Map([["AWS::CertificateManager::Certificate", new Set([
|
|
32567
|
+
"DomainName",
|
|
32568
|
+
"ValidationMethod",
|
|
32569
|
+
"SubjectAlternativeNames",
|
|
32570
|
+
"DomainValidationOptions",
|
|
32571
|
+
"CertificateAuthorityArn",
|
|
32572
|
+
"CertificateTransparencyLoggingPreference",
|
|
32573
|
+
"CertificateExport",
|
|
32574
|
+
"KeyAlgorithm",
|
|
32575
|
+
"Tags"
|
|
32576
|
+
])]]);
|
|
32577
|
+
async create(logicalId, resourceType, properties) {
|
|
32578
|
+
this.logger.debug(`Requesting ACM certificate ${logicalId}`);
|
|
32579
|
+
const domainName = properties["DomainName"];
|
|
32580
|
+
if (!domainName) throw new ProvisioningError(`DomainName is required for ACM certificate ${logicalId}`, resourceType, logicalId);
|
|
32581
|
+
const input = { DomainName: domainName };
|
|
32582
|
+
if (properties["ValidationMethod"]) input["ValidationMethod"] = properties["ValidationMethod"];
|
|
32583
|
+
if (Array.isArray(properties["SubjectAlternativeNames"])) input["SubjectAlternativeNames"] = properties["SubjectAlternativeNames"];
|
|
32584
|
+
if (Array.isArray(properties["DomainValidationOptions"])) input["DomainValidationOptions"] = properties["DomainValidationOptions"].map((opt) => {
|
|
32585
|
+
const cleaned = { DomainName: opt["DomainName"] };
|
|
32586
|
+
if (opt["ValidationDomain"]) cleaned["ValidationDomain"] = opt["ValidationDomain"];
|
|
32587
|
+
return cleaned;
|
|
32588
|
+
}).filter((opt) => opt["DomainName"]);
|
|
32589
|
+
if (properties["CertificateAuthorityArn"]) input["CertificateAuthorityArn"] = properties["CertificateAuthorityArn"];
|
|
32590
|
+
if (properties["KeyAlgorithm"]) input["KeyAlgorithm"] = properties["KeyAlgorithm"];
|
|
32591
|
+
const options = {};
|
|
32592
|
+
if (properties["CertificateTransparencyLoggingPreference"]) options["CertificateTransparencyLoggingPreference"] = properties["CertificateTransparencyLoggingPreference"];
|
|
32593
|
+
if (properties["CertificateExport"]) options["Export"] = properties["CertificateExport"];
|
|
32594
|
+
if (Object.keys(options).length > 0) input["Options"] = options;
|
|
32595
|
+
const tags = properties["Tags"];
|
|
32596
|
+
if (tags && Array.isArray(tags) && tags.length > 0) input["Tags"] = tags;
|
|
32597
|
+
try {
|
|
32598
|
+
const certificateArn = (await this.acmClient.send(new RequestCertificateCommand(input))).CertificateArn;
|
|
32599
|
+
if (!certificateArn) throw new ProvisioningError(`RequestCertificate succeeded but no CertificateArn returned for ${logicalId}`, resourceType, logicalId);
|
|
32600
|
+
this.logger.debug(`Requested ACM certificate: ${certificateArn}`);
|
|
32601
|
+
if (!(process.env["CDKD_NO_WAIT"] === "true")) await this.waitForCertificateIssued(certificateArn, logicalId);
|
|
32602
|
+
else this.logger.warn(`Skipping wait for ACM certificate ${logicalId} (CDKD_NO_WAIT=true). Downstream consumers (CloudFront / ALB) will fail until the cert reaches ISSUED.`);
|
|
32603
|
+
return {
|
|
32604
|
+
physicalId: certificateArn,
|
|
32605
|
+
attributes: {
|
|
32606
|
+
Arn: certificateArn,
|
|
32607
|
+
CertificateArn: certificateArn
|
|
32608
|
+
}
|
|
32609
|
+
};
|
|
32610
|
+
} catch (error) {
|
|
32611
|
+
const cause = error instanceof Error ? error : void 0;
|
|
32612
|
+
throw new ProvisioningError(`Failed to create ACM certificate ${logicalId}: ${error instanceof Error ? error.message : String(error)}`, resourceType, logicalId, void 0, cause);
|
|
32613
|
+
}
|
|
32614
|
+
}
|
|
32615
|
+
async update(logicalId, physicalId, resourceType, properties, previousProperties) {
|
|
32616
|
+
this.logger.debug(`Updating ACM certificate ${logicalId}: ${physicalId}`);
|
|
32617
|
+
const changedImmutable = [
|
|
32618
|
+
"DomainName",
|
|
32619
|
+
"ValidationMethod",
|
|
32620
|
+
"SubjectAlternativeNames",
|
|
32621
|
+
"DomainValidationOptions",
|
|
32622
|
+
"CertificateAuthorityArn",
|
|
32623
|
+
"KeyAlgorithm"
|
|
32624
|
+
].find((k) => JSON.stringify(properties[k]) !== JSON.stringify(previousProperties[k]));
|
|
32625
|
+
if (changedImmutable) {
|
|
32626
|
+
this.logger.debug(`${changedImmutable} changed, replacing ACM certificate: ${physicalId}`);
|
|
32627
|
+
const createResult = await this.create(logicalId, resourceType, properties);
|
|
32628
|
+
try {
|
|
32629
|
+
await this.delete(logicalId, physicalId, resourceType, previousProperties);
|
|
32630
|
+
} catch (error) {
|
|
32631
|
+
this.logger.warn(`Failed to delete old ACM certificate ${physicalId} during replacement: ${String(error)}. The old certificate may be orphaned and require manual cleanup.`);
|
|
32632
|
+
}
|
|
32633
|
+
const result = {
|
|
32634
|
+
physicalId: createResult.physicalId,
|
|
32635
|
+
wasReplaced: true
|
|
32636
|
+
};
|
|
32637
|
+
if (createResult.attributes) result.attributes = createResult.attributes;
|
|
32638
|
+
return result;
|
|
32639
|
+
}
|
|
32640
|
+
try {
|
|
32641
|
+
const newCt = properties["CertificateTransparencyLoggingPreference"];
|
|
32642
|
+
const oldCt = previousProperties["CertificateTransparencyLoggingPreference"];
|
|
32643
|
+
const newExport = properties["CertificateExport"];
|
|
32644
|
+
const oldExport = previousProperties["CertificateExport"];
|
|
32645
|
+
if (newCt !== oldCt || newExport !== oldExport) {
|
|
32646
|
+
const options = {};
|
|
32647
|
+
if (newCt) options["CertificateTransparencyLoggingPreference"] = newCt;
|
|
32648
|
+
if (newExport) options["Export"] = newExport;
|
|
32649
|
+
if (Object.keys(options).length > 0) {
|
|
32650
|
+
await this.acmClient.send(new UpdateCertificateOptionsCommand({
|
|
32651
|
+
CertificateArn: physicalId,
|
|
32652
|
+
Options: options
|
|
32653
|
+
}));
|
|
32654
|
+
this.logger.debug(`Updated certificate Options on ${physicalId}`);
|
|
32655
|
+
}
|
|
32656
|
+
}
|
|
32657
|
+
await this.updateTags(physicalId, properties["Tags"], previousProperties["Tags"]);
|
|
32658
|
+
return {
|
|
32659
|
+
physicalId,
|
|
32660
|
+
wasReplaced: false,
|
|
32661
|
+
attributes: {
|
|
32662
|
+
Arn: physicalId,
|
|
32663
|
+
CertificateArn: physicalId
|
|
32664
|
+
}
|
|
32665
|
+
};
|
|
32666
|
+
} catch (error) {
|
|
32667
|
+
const cause = error instanceof Error ? error : void 0;
|
|
32668
|
+
throw new ProvisioningError(`Failed to update ACM certificate ${logicalId}: ${error instanceof Error ? error.message : String(error)}`, resourceType, logicalId, physicalId, cause);
|
|
32669
|
+
}
|
|
32670
|
+
}
|
|
32671
|
+
async delete(logicalId, physicalId, resourceType, _properties, context) {
|
|
32672
|
+
this.logger.debug(`Deleting ACM certificate ${logicalId}: ${physicalId}`);
|
|
32673
|
+
try {
|
|
32674
|
+
try {
|
|
32675
|
+
await this.acmClient.send(new DeleteCertificateCommand({ CertificateArn: physicalId }));
|
|
32676
|
+
} catch (error) {
|
|
32677
|
+
if (error instanceof ResourceNotFoundException$6) {
|
|
32678
|
+
assertRegionMatch(await this.acmClient.config.region(), context?.expectedRegion, resourceType, logicalId, physicalId);
|
|
32679
|
+
this.logger.debug(`Certificate ${physicalId} does not exist, skipping deletion`);
|
|
32680
|
+
return;
|
|
32681
|
+
}
|
|
32682
|
+
throw error;
|
|
32683
|
+
}
|
|
32684
|
+
this.logger.debug(`Successfully deleted ACM certificate ${logicalId}`);
|
|
32685
|
+
} catch (error) {
|
|
32686
|
+
const cause = error instanceof Error ? error : void 0;
|
|
32687
|
+
throw new ProvisioningError(`Failed to delete ACM certificate ${logicalId}: ${error instanceof Error ? error.message : String(error)}`, resourceType, logicalId, physicalId, cause);
|
|
32688
|
+
}
|
|
32689
|
+
}
|
|
32690
|
+
async getAttribute(physicalId, _resourceType, attributeName) {
|
|
32691
|
+
if (attributeName === "Arn" || attributeName === "CertificateArn") return physicalId;
|
|
32692
|
+
}
|
|
32693
|
+
/**
|
|
32694
|
+
* Read the AWS-current certificate properties in CFn-property shape.
|
|
32695
|
+
*
|
|
32696
|
+
* Coverage:
|
|
32697
|
+
* - `DomainName`, `SubjectAlternativeNames`, `KeyAlgorithm` straight from
|
|
32698
|
+
* `DescribeCertificate.Certificate.*`.
|
|
32699
|
+
* - `CertificateTransparencyLoggingPreference` extracted from the nested
|
|
32700
|
+
* `Options` field and flattened to match CFn shape.
|
|
32701
|
+
* - `Tags` via `ListTagsForCertificate`, with the `aws:cdk:path` etc.
|
|
32702
|
+
* auto-tags filtered out by `normalizeAwsTagsToCfn`.
|
|
32703
|
+
* - `ValidationMethod` / `DomainValidationOptions` are intentionally NOT
|
|
32704
|
+
* surfaced — the deployed cert's validation state is observation-only;
|
|
32705
|
+
* cdkd state stores the request-time input, which can legitimately
|
|
32706
|
+
* diverge from the observed state without indicating drift.
|
|
32707
|
+
*
|
|
32708
|
+
* Returns `undefined` when the cert is gone (`ResourceNotFoundException`).
|
|
32709
|
+
*/
|
|
32710
|
+
async readCurrentState(physicalId, _logicalId, _resourceType, _properties) {
|
|
32711
|
+
let cert;
|
|
32712
|
+
try {
|
|
32713
|
+
cert = (await this.acmClient.send(new DescribeCertificateCommand({ CertificateArn: physicalId }))).Certificate;
|
|
32714
|
+
} catch (err) {
|
|
32715
|
+
if (err instanceof ResourceNotFoundException$6) return void 0;
|
|
32716
|
+
throw err;
|
|
32717
|
+
}
|
|
32718
|
+
if (!cert) return void 0;
|
|
32719
|
+
const result = {};
|
|
32720
|
+
if (cert.DomainName !== void 0) result["DomainName"] = cert.DomainName;
|
|
32721
|
+
if (Array.isArray(cert.SubjectAlternativeNames)) result["SubjectAlternativeNames"] = cert.SubjectAlternativeNames;
|
|
32722
|
+
if (cert.KeyAlgorithm !== void 0) result["KeyAlgorithm"] = cert.KeyAlgorithm;
|
|
32723
|
+
if (cert.CertificateAuthorityArn !== void 0) result["CertificateAuthorityArn"] = cert.CertificateAuthorityArn;
|
|
32724
|
+
if (cert.Options?.CertificateTransparencyLoggingPreference !== void 0) result["CertificateTransparencyLoggingPreference"] = cert.Options.CertificateTransparencyLoggingPreference;
|
|
32725
|
+
if (cert.Options?.Export !== void 0) result["CertificateExport"] = cert.Options.Export;
|
|
32726
|
+
try {
|
|
32727
|
+
result["Tags"] = normalizeAwsTagsToCfn((await this.acmClient.send(new ListTagsForCertificateCommand({ CertificateArn: physicalId }))).Tags);
|
|
32728
|
+
} catch (err) {
|
|
32729
|
+
if (!(err instanceof ResourceNotFoundException$6)) throw err;
|
|
32730
|
+
}
|
|
32731
|
+
return result;
|
|
32732
|
+
}
|
|
32733
|
+
/**
|
|
32734
|
+
* Path the deploy engine queries to compare drift snapshots — paths
|
|
32735
|
+
* `readCurrentState` deliberately does NOT round-trip.
|
|
32736
|
+
*/
|
|
32737
|
+
getDriftUnknownPaths(_resourceType) {
|
|
32738
|
+
return ["ValidationMethod", "DomainValidationOptions"];
|
|
32739
|
+
}
|
|
32740
|
+
/**
|
|
32741
|
+
* Adopt an existing certificate into cdkd state.
|
|
32742
|
+
*
|
|
32743
|
+
* Lookup order:
|
|
32744
|
+
* 1. `--resource` override (must be an ARN — ACM has no other unique id).
|
|
32745
|
+
* 2. Tag-based `aws:cdk:path` match across `ListCertificates` +
|
|
32746
|
+
* `ListTagsForCertificate`. NOTE: ACM has no `Scope: Local` filter —
|
|
32747
|
+
* `ListCertificates` returns customer-managed certs only (AWS-managed
|
|
32748
|
+
* certs are not surfaced via this API), so no extra guard is needed.
|
|
32749
|
+
*/
|
|
32750
|
+
async import(input) {
|
|
32751
|
+
if (input.knownPhysicalId) {
|
|
32752
|
+
const arn = input.knownPhysicalId;
|
|
32753
|
+
if (!arn.startsWith("arn:")) throw new Error(`--resource override for ${input.logicalId} must be an ARN (got '${arn}'). ACM certificates have no human-readable physical id.`);
|
|
32754
|
+
try {
|
|
32755
|
+
await this.acmClient.send(new DescribeCertificateCommand({ CertificateArn: arn }));
|
|
32756
|
+
return {
|
|
32757
|
+
physicalId: arn,
|
|
32758
|
+
attributes: {
|
|
32759
|
+
Arn: arn,
|
|
32760
|
+
CertificateArn: arn
|
|
32761
|
+
}
|
|
32762
|
+
};
|
|
32763
|
+
} catch (err) {
|
|
32764
|
+
if (err instanceof ResourceNotFoundException$6) return null;
|
|
32765
|
+
throw err;
|
|
32766
|
+
}
|
|
32767
|
+
}
|
|
32768
|
+
if (!input.cdkPath) return null;
|
|
32769
|
+
let nextToken;
|
|
32770
|
+
do {
|
|
32771
|
+
const list = await this.acmClient.send(new ListCertificatesCommand({ ...nextToken ? { NextToken: nextToken } : {} }));
|
|
32772
|
+
for (const summary of list.CertificateSummaryList ?? []) {
|
|
32773
|
+
if (!summary.CertificateArn) continue;
|
|
32774
|
+
try {
|
|
32775
|
+
if (matchesCdkPath((await this.acmClient.send(new ListTagsForCertificateCommand({ CertificateArn: summary.CertificateArn }))).Tags, input.cdkPath)) return {
|
|
32776
|
+
physicalId: summary.CertificateArn,
|
|
32777
|
+
attributes: {
|
|
32778
|
+
Arn: summary.CertificateArn,
|
|
32779
|
+
CertificateArn: summary.CertificateArn
|
|
32780
|
+
}
|
|
32781
|
+
};
|
|
32782
|
+
} catch (err) {
|
|
32783
|
+
if (err instanceof ResourceNotFoundException$6) continue;
|
|
32784
|
+
throw err;
|
|
32785
|
+
}
|
|
32786
|
+
}
|
|
32787
|
+
nextToken = list.NextToken;
|
|
32788
|
+
} while (nextToken);
|
|
32789
|
+
return null;
|
|
32790
|
+
}
|
|
32791
|
+
/**
|
|
32792
|
+
* Poll `DescribeCertificate` until status === `ISSUED`. On the FIRST poll
|
|
32793
|
+
* that returns PENDING_VALIDATION, log the DomainValidationOptions AWS
|
|
32794
|
+
* posted so the user knows which CNAME records to add to their DNS zone.
|
|
32795
|
+
*
|
|
32796
|
+
* Throws on `VALIDATION_TIMED_OUT` / `FAILED` (terminal failures) and on
|
|
32797
|
+
* polling-cap exhaustion (treated as timeout). SIGINT short-circuits the
|
|
32798
|
+
* loop and returns control to the deploy engine's cleanup path.
|
|
32799
|
+
*/
|
|
32800
|
+
async waitForCertificateIssued(certificateArn, logicalId) {
|
|
32801
|
+
this.logger.debug(`Waiting for ACM certificate ${certificateArn} to reach ISSUED status...`);
|
|
32802
|
+
let interrupted = false;
|
|
32803
|
+
let validationOptionsLogged = false;
|
|
32804
|
+
const sigintHandler = () => {
|
|
32805
|
+
interrupted = true;
|
|
32806
|
+
};
|
|
32807
|
+
process.on("SIGINT", sigintHandler);
|
|
32808
|
+
try {
|
|
32809
|
+
for (let attempt = 1; attempt <= this.maxPollAttempts; attempt++) {
|
|
32810
|
+
if (interrupted) {
|
|
32811
|
+
this.logger.debug(`ACM certificate ${certificateArn} wait interrupted by SIGINT, proceeding`);
|
|
32812
|
+
return;
|
|
32813
|
+
}
|
|
32814
|
+
const resp = await this.acmClient.send(new DescribeCertificateCommand({ CertificateArn: certificateArn }));
|
|
32815
|
+
const status = resp.Certificate?.Status;
|
|
32816
|
+
const validations = resp.Certificate?.DomainValidationOptions ?? [];
|
|
32817
|
+
if (status === "ISSUED") {
|
|
32818
|
+
this.logger.debug(`ACM certificate ${certificateArn} is ISSUED`);
|
|
32819
|
+
return;
|
|
32820
|
+
}
|
|
32821
|
+
if (status === "FAILED" || status === "VALIDATION_TIMED_OUT" || status === "INACTIVE" || status === "REVOKED" || status === "EXPIRED") throw new Error(`ACM certificate ${logicalId} (${certificateArn}) entered terminal status ${status} during validation. Check ACM console / DNS records to diagnose.`);
|
|
32822
|
+
if (status === "PENDING_VALIDATION" && !validationOptionsLogged && validations.length > 0) {
|
|
32823
|
+
this.logValidationOptions(validations);
|
|
32824
|
+
validationOptionsLogged = true;
|
|
32825
|
+
}
|
|
32826
|
+
this.logger.debug(`ACM certificate ${certificateArn} status: ${status} (attempt ${attempt}/${this.maxPollAttempts})`);
|
|
32827
|
+
const sleepEnd = Date.now() + this.pollIntervalMs;
|
|
32828
|
+
const tickMs = Math.min(1e3, this.pollIntervalMs);
|
|
32829
|
+
while (Date.now() < sleepEnd && !interrupted) await new Promise((resolve) => setTimeout(resolve, tickMs));
|
|
32830
|
+
}
|
|
32831
|
+
throw new Error(`ACM certificate ${logicalId} (${certificateArn}) did not reach ISSUED status within ${this.maxPollAttempts * this.pollIntervalMs / 1e3}s. If your DNS zone is manually managed, you may need to increase --resource-timeout AWS::CertificateManager::Certificate=<duration> or set CDKD_NO_WAIT=true.`);
|
|
32832
|
+
} finally {
|
|
32833
|
+
process.removeListener("SIGINT", sigintHandler);
|
|
32834
|
+
}
|
|
32835
|
+
}
|
|
32836
|
+
/**
|
|
32837
|
+
* Pretty-print the validation records AWS expects in the DNS zone, so the
|
|
32838
|
+
* user can copy / paste them into Route 53 / Cloudflare / etc. while the
|
|
32839
|
+
* cert is still PENDING_VALIDATION.
|
|
32840
|
+
*/
|
|
32841
|
+
logValidationOptions(validations) {
|
|
32842
|
+
const lines = ["ACM certificate is PENDING_VALIDATION. Add the following DNS records to validate:"];
|
|
32843
|
+
for (const v of validations) if (v.ValidationMethod === "DNS" && v.ResourceRecord) {
|
|
32844
|
+
const r = v.ResourceRecord;
|
|
32845
|
+
lines.push(` ${v.DomainName} — ${r.Type} ${r.Name} -> ${r.Value}`);
|
|
32846
|
+
} else if (v.ValidationMethod === "EMAIL") {
|
|
32847
|
+
const emails = (v.ValidationEmails ?? []).join(", ");
|
|
32848
|
+
lines.push(` ${v.DomainName} — confirmation email sent to: ${emails || "<none>"}`);
|
|
32849
|
+
}
|
|
32850
|
+
this.logger.info(lines.join("\n"));
|
|
32851
|
+
}
|
|
32852
|
+
async updateTags(certificateArn, newTags, oldTags) {
|
|
32853
|
+
const newTagMap = new Map((newTags || []).map((t) => [t.Key, t.Value]));
|
|
32854
|
+
const oldTagMap = new Map((oldTags || []).map((t) => [t.Key, t.Value]));
|
|
32855
|
+
const tagsToRemove = [];
|
|
32856
|
+
for (const key of oldTagMap.keys()) if (!newTagMap.has(key)) tagsToRemove.push({ Key: key });
|
|
32857
|
+
const tagsToAdd = [];
|
|
32858
|
+
for (const [key, value] of newTagMap) if (oldTagMap.get(key) !== value) tagsToAdd.push({
|
|
32859
|
+
Key: key,
|
|
32860
|
+
Value: value
|
|
32861
|
+
});
|
|
32862
|
+
if (tagsToRemove.length > 0) await this.acmClient.send(new RemoveTagsFromCertificateCommand({
|
|
32863
|
+
CertificateArn: certificateArn,
|
|
32864
|
+
Tags: tagsToRemove
|
|
32865
|
+
}));
|
|
32866
|
+
if (tagsToAdd.length > 0) await this.acmClient.send(new AddTagsToCertificateCommand({
|
|
32867
|
+
CertificateArn: certificateArn,
|
|
32868
|
+
Tags: tagsToAdd
|
|
32869
|
+
}));
|
|
32870
|
+
}
|
|
32871
|
+
};
|
|
32872
|
+
|
|
32500
32873
|
//#endregion
|
|
32501
32874
|
//#region src/provisioning/register-providers.ts
|
|
32502
32875
|
/**
|
|
@@ -32592,6 +32965,7 @@ function registerAllProviders(registry) {
|
|
|
32592
32965
|
registry.register("AWS::Route53::RecordSet", route53Provider);
|
|
32593
32966
|
registry.register("AWS::WAFv2::WebACL", new WAFv2WebACLProvider());
|
|
32594
32967
|
registry.register("AWS::Cognito::UserPool", new CognitoUserPoolProvider());
|
|
32968
|
+
registry.register("AWS::CertificateManager::Certificate", new ACMCertificateProvider());
|
|
32595
32969
|
const elasticacheProvider = new ElastiCacheProvider();
|
|
32596
32970
|
registry.register("AWS::ElastiCache::SubnetGroup", elasticacheProvider);
|
|
32597
32971
|
registry.register("AWS::ElastiCache::CacheCluster", elasticacheProvider);
|
|
@@ -32904,6 +33278,7 @@ async function deployCommand(stacks, options) {
|
|
|
32904
33278
|
registerAllProviders(stackProviderRegistry);
|
|
32905
33279
|
stackProviderRegistry.setCustomResourceResponseBucket(stateBucket, baseRegion);
|
|
32906
33280
|
if (options.allowUnsupportedTypes?.length) stackProviderRegistry.allowUnsupportedTypes(options.allowUnsupportedTypes);
|
|
33281
|
+
if (options.allowUnsupportedProperties?.length) stackProviderRegistry.allowUnsupportedProperties(options.allowUnsupportedProperties);
|
|
32907
33282
|
try {
|
|
32908
33283
|
if (skipPrefix) {
|
|
32909
33284
|
const existing = await stackStateBackend.getState(stackInfo.stackName, stackRegion);
|
|
@@ -58580,7 +58955,7 @@ function reorderArgs(argv) {
|
|
|
58580
58955
|
*/
|
|
58581
58956
|
async function main() {
|
|
58582
58957
|
const program = new Command();
|
|
58583
|
-
program.name("cdkd").description("CDK Direct - Deploy AWS CDK apps directly via SDK/Cloud Control API").version("0.
|
|
58958
|
+
program.name("cdkd").description("CDK Direct - Deploy AWS CDK apps directly via SDK/Cloud Control API").version("0.157.0");
|
|
58584
58959
|
program.addCommand(createBootstrapCommand());
|
|
58585
58960
|
program.addCommand(createSynthCommand());
|
|
58586
58961
|
program.addCommand(createListCommand());
|