@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/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-DWLTHfXj.js";
4
- import { a as setAwsClients, i as resetAwsClients, r as getAwsClients, t as AwsClients } from "./aws-clients-BF03Alpe.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-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$6, UpdateUserPoolCommand } from "@aws-sdk/client-cognito-identity-provider";
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$7, StartStreamEncryptionCommand, StopStreamEncryptionCommand, TagResourceCommand as TagResourceCommand$14, UntagResourceCommand as UntagResourceCommand$13, UpdateShardCountCommand } from "@aws-sdk/client-kinesis";
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$8, TagDeliveryStreamCommand, UntagDeliveryStreamCommand, UpdateDestinationCommand } from "@aws-sdk/client-firehose";
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$9, UpdateProjectCommand } from "@aws-sdk/client-codebuild";
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$6) {
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$6) {
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$6) return void 0;
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$6) return null;
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$6) continue;
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$7) {
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$7) return void 0;
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$7) return void 0;
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$7) return null;
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$7) {
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$7) return void 0;
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$7) return void 0;
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$8) {
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$8) return void 0;
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$8) return void 0;
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$8) return null;
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$9) {
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$9) return void 0;
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$9) return null;
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.155.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());