@go-to-k/cdkd 0.153.0 → 0.155.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,14 +1,14 @@
1
1
  #!/usr/bin/env node
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-EtWSTAje.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-9Ct1Z9oH.js";
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
4
  import { a as setAwsClients, i as resetAwsClients, r as getAwsClients, t as AwsClients } from "./aws-clients-BF03Alpe.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";
8
- import { AddRoleToInstanceProfileCommand, AddUserToGroupCommand, AttachGroupPolicyCommand, AttachUserPolicyCommand, CreateGroupCommand, CreateInstanceProfileCommand, CreateLoginProfileCommand, CreateUserCommand, DeleteAccessKeyCommand, DeleteGroupCommand, DeleteGroupPolicyCommand, DeleteInstanceProfileCommand, DeleteLoginProfileCommand, DeleteRolePolicyCommand, DeleteUserCommand, DeleteUserPermissionsBoundaryCommand, DeleteUserPolicyCommand, DetachGroupPolicyCommand, DetachUserPolicyCommand, GetGroupCommand, GetGroupPolicyCommand, GetInstanceProfileCommand, GetRolePolicyCommand, GetUserCommand, GetUserPolicyCommand, IAMClient, ListAccessKeysCommand, ListAttachedGroupPoliciesCommand, ListAttachedUserPoliciesCommand, ListGroupPoliciesCommand, ListGroupsForUserCommand, ListInstanceProfilesCommand, ListUserPoliciesCommand, ListUserTagsCommand, ListUsersCommand, NoSuchEntityException, PutGroupPolicyCommand, PutRolePolicyCommand, PutUserPermissionsBoundaryCommand, PutUserPolicyCommand, RemoveRoleFromInstanceProfileCommand, RemoveUserFromGroupCommand, TagUserCommand, UntagUserCommand, UpdateLoginProfileCommand } from "@aws-sdk/client-iam";
8
+ import { AddRoleToInstanceProfileCommand, AddUserToGroupCommand, AttachGroupPolicyCommand, AttachRolePolicyCommand, AttachUserPolicyCommand, CreateGroupCommand, CreateInstanceProfileCommand, CreateLoginProfileCommand, CreatePolicyCommand, CreatePolicyVersionCommand, CreateUserCommand, DeleteAccessKeyCommand, DeleteGroupCommand, DeleteGroupPolicyCommand, DeleteInstanceProfileCommand, DeleteLoginProfileCommand, DeletePolicyCommand, DeletePolicyVersionCommand, DeleteRolePolicyCommand, DeleteUserCommand, DeleteUserPermissionsBoundaryCommand, DeleteUserPolicyCommand, DetachGroupPolicyCommand, DetachRolePolicyCommand, DetachUserPolicyCommand, GetGroupCommand, GetGroupPolicyCommand, GetInstanceProfileCommand, GetPolicyCommand, GetPolicyVersionCommand, GetRolePolicyCommand, GetUserCommand, GetUserPolicyCommand, IAMClient, ListAccessKeysCommand, ListAttachedGroupPoliciesCommand, ListAttachedUserPoliciesCommand, ListEntitiesForPolicyCommand, ListGroupPoliciesCommand, ListGroupsForUserCommand, ListInstanceProfilesCommand, ListPoliciesCommand, ListPolicyTagsCommand, ListPolicyVersionsCommand, ListUserPoliciesCommand, ListUserTagsCommand, ListUsersCommand, NoSuchEntityException, PutGroupPolicyCommand, PutRolePolicyCommand, PutUserPermissionsBoundaryCommand, PutUserPolicyCommand, RemoveRoleFromInstanceProfileCommand, RemoveUserFromGroupCommand, TagPolicyCommand, TagUserCommand, UntagPolicyCommand, UntagUserCommand, UpdateLoginProfileCommand } from "@aws-sdk/client-iam";
9
9
  import { CreateQueueCommand, DeleteQueueCommand, GetQueueAttributesCommand, GetQueueUrlCommand, ListQueueTagsCommand, ListQueuesCommand, QueueDoesNotExist, SQSClient, SetQueueAttributesCommand, TagQueueCommand, UntagQueueCommand } from "@aws-sdk/client-sqs";
10
10
  import { CreateTopicCommand, DeleteTopicCommand, GetSubscriptionAttributesCommand, GetTopicAttributesCommand, ListTagsForResourceCommand, ListTopicsCommand, NotFoundException, SNSClient, SetTopicAttributesCommand, SubscribeCommand, TagResourceCommand, UnsubscribeCommand, UntagResourceCommand } from "@aws-sdk/client-sns";
11
- import { AddPermissionCommand, CreateEventSourceMappingCommand, CreateFunctionCommand, CreateFunctionUrlConfigCommand, DeleteEventSourceMappingCommand, DeleteFunctionCommand, DeleteFunctionUrlConfigCommand, DeleteLayerVersionCommand, GetEventSourceMappingCommand, GetFunctionCommand, GetFunctionUrlConfigCommand, GetLayerVersionByArnCommand, GetPolicyCommand, LambdaClient, ListFunctionsCommand, ListLayersCommand, ListTagsCommand, PublishLayerVersionCommand, RemovePermissionCommand, ResourceNotFoundException, TagResourceCommand as TagResourceCommand$1, UntagResourceCommand as UntagResourceCommand$1, UpdateEventSourceMappingCommand, UpdateFunctionCodeCommand, UpdateFunctionConfigurationCommand, UpdateFunctionUrlConfigCommand, waitUntilFunctionUpdatedV2 } from "@aws-sdk/client-lambda";
11
+ import { AddPermissionCommand, CreateEventSourceMappingCommand, CreateFunctionCommand, CreateFunctionUrlConfigCommand, DeleteEventSourceMappingCommand, DeleteFunctionCommand, DeleteFunctionUrlConfigCommand, DeleteLayerVersionCommand, GetEventSourceMappingCommand, GetFunctionCommand, GetFunctionUrlConfigCommand, GetLayerVersionByArnCommand, GetPolicyCommand as GetPolicyCommand$1, LambdaClient, ListFunctionsCommand, ListLayersCommand, ListTagsCommand, PublishLayerVersionCommand, RemovePermissionCommand, ResourceNotFoundException, TagResourceCommand as TagResourceCommand$1, UntagResourceCommand as UntagResourceCommand$1, UpdateEventSourceMappingCommand, UpdateFunctionCodeCommand, UpdateFunctionConfigurationCommand, UpdateFunctionUrlConfigCommand, waitUntilFunctionUpdatedV2 } from "@aws-sdk/client-lambda";
12
12
  import { AssumeRoleCommand, GetCallerIdentityCommand, STSClient } from "@aws-sdk/client-sts";
13
13
  import { AssociateRouteTableCommand, AttachInternetGatewayCommand, AuthorizeSecurityGroupEgressCommand, AuthorizeSecurityGroupIngressCommand, CreateInternetGatewayCommand, CreateNatGatewayCommand, CreateNetworkAclCommand, CreateNetworkAclEntryCommand, CreateRouteCommand, CreateRouteTableCommand, CreateSecurityGroupCommand, CreateSubnetCommand, CreateTagsCommand, CreateVpcCommand, DeleteInternetGatewayCommand, DeleteNatGatewayCommand, DeleteNetworkAclCommand, DeleteNetworkAclEntryCommand, DeleteNetworkInterfaceCommand, DeleteRouteCommand, DeleteRouteTableCommand, DeleteSecurityGroupCommand, DeleteSubnetCommand, DeleteTagsCommand, DeleteVpcCommand, DescribeAvailabilityZonesCommand, DescribeInstanceAttributeCommand, DescribeInstancesCommand, DescribeInternetGatewaysCommand, DescribeNatGatewaysCommand, DescribeNetworkAclsCommand, DescribeNetworkInterfacesCommand, DescribeRouteTablesCommand, DescribeSecurityGroupsCommand, DescribeSubnetsCommand, DescribeVolumesCommand, DescribeVpcAttributeCommand, DescribeVpcsCommand, DetachInternetGatewayCommand, DisassociateRouteTableCommand, EC2Client, ModifyInstanceAttributeCommand, ModifySubnetAttributeCommand, ModifyVpcAttributeCommand, ReplaceNetworkAclAssociationCommand, RevokeSecurityGroupEgressCommand, RevokeSecurityGroupIngressCommand, RunInstancesCommand, TerminateInstancesCommand, waitUntilInstanceRunning, waitUntilInstanceTerminated, waitUntilNatGatewayAvailable, waitUntilNatGatewayDeleted } from "@aws-sdk/client-ec2";
14
14
  import { CreateTableCommand, DeleteTableCommand, DescribeContinuousBackupsCommand, DescribeContributorInsightsCommand, DescribeKinesisStreamingDestinationCommand, DescribeTableCommand, DescribeTimeToLiveCommand, DynamoDBClient, ListTablesCommand, ListTagsOfResourceCommand, ResourceNotFoundException as ResourceNotFoundException$1, TagResourceCommand as TagResourceCommand$2, UntagResourceCommand as UntagResourceCommand$2, UpdateTableCommand, UpdateTimeToLiveCommand } from "@aws-sdk/client-dynamodb";
@@ -377,8 +377,24 @@ const noWaitOption = new Option("--no-wait", "Skip waiting for async resources t
377
377
  */
378
378
  const aggressiveVpcParallelOption = new Option("--no-aggressive-vpc-parallel", "Disable the default relaxation of CDK-injected VPC route DependsOn (on by default; opt out to keep the strict CDK ordering)");
379
379
  /**
380
- * Deploy options
380
+ * Escape hatch for the pre-flight unsupported-type rejection. Comma-separated
381
+ * (and repeatable) resource types that cdkd will attempt via Cloud Control
382
+ * even though it reports them unsupported (AWS NON_PROVISIONABLE). Shared by
383
+ * `cdkd deploy` and `cdkd destroy` so a stack deployed with the flag can also
384
+ * be destroyed. Per-type (not blanket) so the user explicitly names each type.
385
+ *
386
+ * Format-checks each token against the CFn resource-type shape
387
+ * (`Namespace::Service::Type` / `Custom::Foo`) so a typo like
388
+ * `--allow-unsupported-types AWS::AppMash::Mesh` aborts at parse time
389
+ * instead of silently being added to the allowlist with no effect.
381
390
  */
391
+ const RESOURCE_TYPE_FORMAT = /^[A-Z][A-Za-z0-9]+(::[A-Z][A-Za-z0-9]+)+$/;
392
+ function parseAllowUnsupportedTypesToken(value, previous) {
393
+ const parsed = value.split(",").map((s) => s.trim()).filter(Boolean);
394
+ for (const token of parsed) if (!RESOURCE_TYPE_FORMAT.test(token)) throw new Error(`Invalid --allow-unsupported-types value "${token}": expected a CloudFormation resource type like AWS::Service::Type or Custom::Foo.`);
395
+ return [...previous ?? [], ...parsed];
396
+ }
397
+ 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);
382
398
  const deployOptions = [
383
399
  new Option("--concurrency <number>", "Maximum concurrent resource operations").default(10).argParser((value) => parseInt(value, 10)),
384
400
  new Option("--stack-concurrency <number>", "Maximum concurrent stack deployments").default(4).argParser((value) => parseInt(value, 10)),
@@ -392,6 +408,7 @@ const deployOptions = [
392
408
  noWaitOption,
393
409
  aggressiveVpcParallelOption,
394
410
  new Option("-e, --exclusively", "Only deploy requested stacks, do not include dependencies").default(false),
411
+ allowUnsupportedTypesOption,
395
412
  ...resourceTimeoutOptions
396
413
  ];
397
414
  /**
@@ -444,7 +461,11 @@ function effectiveAssumeRoleArn(logicalId, opt) {
444
461
  * never calls `provider.delete()` — does not advertise per-resource timeout
445
462
  * flags it would silently ignore.
446
463
  */
447
- const destroyOptions = [new Option("-f, --force", "Do not ask for confirmation before destroying the stacks").default(false), new Option("--remove-protection", "Bypass deletion protection on protected resources by flipping the per-resource protection flag off in-place before delete. Covers stack-level terminationProtection (CDK property) and resource-level protection on AWS::Logs::LogGroup, AWS::RDS::DBInstance, AWS::RDS::DBCluster, AWS::DocDB::DBCluster, AWS::Neptune::DBCluster, AWS::Neptune::DBInstance, AWS::DynamoDB::Table, AWS::EC2::Instance, AWS::Cognito::UserPool, AWS::AutoScaling::AutoScalingGroup, and AWS::ElasticLoadBalancingV2::LoadBalancer.").default(false)];
464
+ const destroyOptions = [
465
+ new Option("-f, --force", "Do not ask for confirmation before destroying the stacks").default(false),
466
+ new Option("--remove-protection", "Bypass deletion protection on protected resources by flipping the per-resource protection flag off in-place before delete. Covers stack-level terminationProtection (CDK property) and resource-level protection on AWS::Logs::LogGroup, AWS::RDS::DBInstance, AWS::RDS::DBCluster, AWS::DocDB::DBCluster, AWS::Neptune::DBCluster, AWS::Neptune::DBInstance, AWS::DynamoDB::Table, AWS::EC2::Instance, AWS::Cognito::UserPool, AWS::AutoScaling::AutoScalingGroup, and AWS::ElasticLoadBalancingV2::LoadBalancer.").default(false),
467
+ allowUnsupportedTypesOption
468
+ ];
448
469
 
449
470
  //#endregion
450
471
  //#region src/cli/commands/bootstrap.ts
@@ -1511,6 +1532,517 @@ var IAMPolicyProvider = class {
1511
1532
  }
1512
1533
  };
1513
1534
 
1535
+ //#endregion
1536
+ //#region src/provisioning/providers/iam-managed-policy-provider.ts
1537
+ /**
1538
+ * AWS IAM Managed Policy Provider
1539
+ *
1540
+ * Implements resource provisioning for AWS::IAM::ManagedPolicy using the IAM SDK.
1541
+ * Cloud Control API does support this type, but a dedicated SDK provider wins
1542
+ * via Tier 1 of the provider registry and gives cdkd direct control over:
1543
+ * - PolicyDocument updates (via CreatePolicyVersion + SetDefaultPolicyVersion +
1544
+ * prune oldest non-default when at the 5-version limit)
1545
+ * - Attachment fan-out (Groups / Roles / Users) on create + update
1546
+ * - Detach-before-delete cleanup (a ManagedPolicy with attached principals
1547
+ * or with non-default versions cannot be deleted directly)
1548
+ *
1549
+ * Physical id is the policy ARN (`arn:aws:iam::<account>:policy/<path><name>`)
1550
+ * since path is part of the identity — two policies with the same name in
1551
+ * different paths are distinct.
1552
+ */
1553
+ var IAMManagedPolicyProvider = class {
1554
+ iamClient;
1555
+ logger = getLogger().child("IAMManagedPolicyProvider");
1556
+ handledProperties = new Map([["AWS::IAM::ManagedPolicy", new Set([
1557
+ "ManagedPolicyName",
1558
+ "Description",
1559
+ "Path",
1560
+ "PolicyDocument",
1561
+ "Groups",
1562
+ "Roles",
1563
+ "Users",
1564
+ "Tags"
1565
+ ])]]);
1566
+ constructor() {
1567
+ const awsClients = getAwsClients();
1568
+ this.iamClient = awsClients.iam;
1569
+ }
1570
+ async create(logicalId, resourceType, properties) {
1571
+ this.logger.debug(`Creating IAM managed policy ${logicalId}`);
1572
+ const policyName = generateResourceNameWithFallback(properties["ManagedPolicyName"], logicalId, { maxLength: 128 });
1573
+ const policyDocument = properties["PolicyDocument"];
1574
+ if (!policyDocument) throw new ProvisioningError(`PolicyDocument is required for IAM managed policy ${logicalId}`, resourceType, logicalId);
1575
+ const policyDoc = typeof policyDocument === "string" ? policyDocument : JSON.stringify(policyDocument);
1576
+ try {
1577
+ const createParams = {
1578
+ PolicyName: policyName,
1579
+ PolicyDocument: policyDoc
1580
+ };
1581
+ if (properties["Description"]) createParams.Description = properties["Description"];
1582
+ if (properties["Path"]) createParams.Path = properties["Path"];
1583
+ const tags = properties["Tags"];
1584
+ if (tags && Array.isArray(tags) && tags.length > 0) createParams.Tags = tags;
1585
+ const policyArn = (await this.iamClient.send(new CreatePolicyCommand(createParams))).Policy?.Arn;
1586
+ if (!policyArn) throw new ProvisioningError(`CreatePolicy succeeded but no Arn returned for ${logicalId}`, resourceType, logicalId, policyName);
1587
+ this.logger.debug(`Created IAM managed policy: ${policyArn}`);
1588
+ try {
1589
+ await this.attachToPrincipals(policyArn, properties["Groups"], properties["Roles"], properties["Users"]);
1590
+ } catch (innerError) {
1591
+ try {
1592
+ await this.detachAllPrincipals(policyArn);
1593
+ await this.deleteAllNonDefaultVersions(policyArn);
1594
+ await this.iamClient.send(new DeletePolicyCommand({ PolicyArn: policyArn }));
1595
+ this.logger.debug(`Cleaned up partially-created managed policy ${logicalId} (${policyArn}) after attachment failure`);
1596
+ } catch (cleanupError) {
1597
+ this.logger.warn(`Failed to clean up partially-created managed policy ${logicalId} (${policyArn}): ${cleanupError instanceof Error ? cleanupError.message : String(cleanupError)}. Manual deletion may be required: detach principals (aws iam list-entities-for-policy --policy-arn ${policyArn}), delete versions (aws iam list-policy-versions --policy-arn ${policyArn} then aws iam delete-policy-version), then aws iam delete-policy --policy-arn ${policyArn}`);
1598
+ }
1599
+ throw innerError;
1600
+ }
1601
+ return {
1602
+ physicalId: policyArn,
1603
+ attributes: { PolicyArn: policyArn }
1604
+ };
1605
+ } catch (error) {
1606
+ const cause = error instanceof Error ? error : void 0;
1607
+ throw new ProvisioningError(`Failed to create IAM managed policy ${logicalId}: ${error instanceof Error ? error.message : String(error)}`, resourceType, logicalId, policyName, cause);
1608
+ }
1609
+ }
1610
+ async update(logicalId, physicalId, resourceType, properties, previousProperties) {
1611
+ this.logger.debug(`Updating IAM managed policy ${logicalId}: ${physicalId}`);
1612
+ const newPolicyName = generateResourceNameWithFallback(properties["ManagedPolicyName"], logicalId, { maxLength: 128 });
1613
+ const oldPolicyName = derivePolicyNameFromArn(physicalId);
1614
+ const newPath = properties["Path"] || "/";
1615
+ const oldPath = previousProperties["Path"] || "/";
1616
+ const newDescription = properties["Description"];
1617
+ const oldDescription = previousProperties["Description"];
1618
+ if (newPolicyName !== oldPolicyName || newPath !== oldPath || (newDescription ?? "") !== (oldDescription ?? "")) {
1619
+ const reason = newPolicyName !== oldPolicyName ? "ManagedPolicyName" : newPath !== oldPath ? "Path" : "Description";
1620
+ this.logger.debug(`${reason} changed, replacing managed policy: ${physicalId} (${reason} mutation)`);
1621
+ const createResult = await this.create(logicalId, resourceType, properties);
1622
+ try {
1623
+ await this.delete(logicalId, physicalId, resourceType, previousProperties);
1624
+ } catch (error) {
1625
+ this.logger.warn(`Failed to delete old managed policy ${physicalId} during replacement: ${String(error)}. The old policy may be orphaned and require manual cleanup.`);
1626
+ }
1627
+ const result = {
1628
+ physicalId: createResult.physicalId,
1629
+ wasReplaced: true
1630
+ };
1631
+ if (createResult.attributes) result.attributes = createResult.attributes;
1632
+ return result;
1633
+ }
1634
+ try {
1635
+ const newDocument = properties["PolicyDocument"];
1636
+ const oldDocument = previousProperties["PolicyDocument"];
1637
+ if (newDocument) {
1638
+ const newDocStr = typeof newDocument === "string" ? newDocument : JSON.stringify(newDocument);
1639
+ if (newDocStr !== (oldDocument ? typeof oldDocument === "string" ? oldDocument : JSON.stringify(oldDocument) : "")) {
1640
+ await this.ensureVersionCapacity(physicalId);
1641
+ await this.iamClient.send(new CreatePolicyVersionCommand({
1642
+ PolicyArn: physicalId,
1643
+ PolicyDocument: newDocStr,
1644
+ SetAsDefault: true
1645
+ }));
1646
+ this.logger.debug(`Updated PolicyDocument for ${physicalId}`);
1647
+ }
1648
+ }
1649
+ await this.updatePrincipals(physicalId, properties["Groups"], previousProperties["Groups"], properties["Roles"], previousProperties["Roles"], properties["Users"], previousProperties["Users"]);
1650
+ await this.updateTags(physicalId, properties["Tags"], previousProperties["Tags"]);
1651
+ return {
1652
+ physicalId,
1653
+ wasReplaced: false,
1654
+ attributes: { PolicyArn: physicalId }
1655
+ };
1656
+ } catch (error) {
1657
+ const cause = error instanceof Error ? error : void 0;
1658
+ throw new ProvisioningError(`Failed to update IAM managed policy ${logicalId}: ${error instanceof Error ? error.message : String(error)}`, resourceType, logicalId, physicalId, cause);
1659
+ }
1660
+ }
1661
+ async delete(logicalId, physicalId, resourceType, _properties, context) {
1662
+ this.logger.debug(`Deleting IAM managed policy ${logicalId}: ${physicalId}`);
1663
+ try {
1664
+ try {
1665
+ await this.iamClient.send(new GetPolicyCommand({ PolicyArn: physicalId }));
1666
+ } catch (error) {
1667
+ if (error instanceof NoSuchEntityException) {
1668
+ assertRegionMatch(await this.iamClient.config.region(), context?.expectedRegion, resourceType, logicalId, physicalId);
1669
+ this.logger.debug(`Managed policy ${physicalId} does not exist, skipping deletion`);
1670
+ return;
1671
+ }
1672
+ throw error;
1673
+ }
1674
+ await this.detachAllPrincipals(physicalId);
1675
+ await this.deleteAllNonDefaultVersions(physicalId);
1676
+ await this.iamClient.send(new DeletePolicyCommand({ PolicyArn: physicalId }));
1677
+ this.logger.debug(`Successfully deleted IAM managed policy ${logicalId}`);
1678
+ } catch (error) {
1679
+ const cause = error instanceof Error ? error : void 0;
1680
+ throw new ProvisioningError(`Failed to delete IAM managed policy ${logicalId}: ${error instanceof Error ? error.message : String(error)}`, resourceType, logicalId, physicalId, cause);
1681
+ }
1682
+ }
1683
+ async getAttribute(physicalId, _resourceType, attributeName) {
1684
+ if (attributeName === "PolicyArn") return physicalId;
1685
+ }
1686
+ /**
1687
+ * Read the AWS-current managed policy configuration in CFn-property shape.
1688
+ *
1689
+ * Coverage:
1690
+ * - `ManagedPolicyName`, `Description`, `Path` — straight from `GetPolicy`.
1691
+ * - `PolicyDocument` — fetched via `GetPolicyVersion` on the default
1692
+ * version, URL-decoded + JSON-parsed.
1693
+ * - `Groups` / `Roles` / `Users` — string arrays from
1694
+ * `ListEntitiesForPolicy`.
1695
+ * - `Tags` — via `ListPolicyTags`, with the `aws:cdk:path` etc. filtered
1696
+ * out by `normalizeAwsTagsToCfn`.
1697
+ *
1698
+ * Returns `undefined` when the policy is gone (`NoSuchEntityException`).
1699
+ */
1700
+ async readCurrentState(physicalId, _logicalId, _resourceType, _properties) {
1701
+ let policy;
1702
+ try {
1703
+ policy = (await this.iamClient.send(new GetPolicyCommand({ PolicyArn: physicalId }))).Policy;
1704
+ } catch (err) {
1705
+ if (err instanceof NoSuchEntityException) return void 0;
1706
+ throw err;
1707
+ }
1708
+ if (!policy) return void 0;
1709
+ const result = {};
1710
+ if (policy.PolicyName !== void 0) result["ManagedPolicyName"] = policy.PolicyName;
1711
+ result["Description"] = policy.Description ?? "";
1712
+ if (policy.Path !== void 0) result["Path"] = policy.Path;
1713
+ if (policy.DefaultVersionId) try {
1714
+ const doc = (await this.iamClient.send(new GetPolicyVersionCommand({
1715
+ PolicyArn: physicalId,
1716
+ VersionId: policy.DefaultVersionId
1717
+ }))).PolicyVersion?.Document;
1718
+ if (typeof doc === "string") try {
1719
+ result["PolicyDocument"] = JSON.parse(decodeURIComponent(doc));
1720
+ } catch {
1721
+ result["PolicyDocument"] = doc;
1722
+ }
1723
+ } catch (err) {
1724
+ if (!(err instanceof NoSuchEntityException)) throw err;
1725
+ }
1726
+ try {
1727
+ const groups = [];
1728
+ const roles = [];
1729
+ const users = [];
1730
+ let marker;
1731
+ while (true) {
1732
+ const resp = await this.iamClient.send(new ListEntitiesForPolicyCommand({
1733
+ PolicyArn: physicalId,
1734
+ ...marker ? { Marker: marker } : {}
1735
+ }));
1736
+ for (const g of resp.PolicyGroups ?? []) if (g.GroupName) groups.push(g.GroupName);
1737
+ for (const r of resp.PolicyRoles ?? []) if (r.RoleName) roles.push(r.RoleName);
1738
+ for (const u of resp.PolicyUsers ?? []) if (u.UserName) users.push(u.UserName);
1739
+ if (!resp.IsTruncated) break;
1740
+ marker = resp.Marker;
1741
+ }
1742
+ result["Groups"] = groups;
1743
+ result["Roles"] = roles;
1744
+ result["Users"] = users;
1745
+ } catch (err) {
1746
+ if (!(err instanceof NoSuchEntityException)) throw err;
1747
+ }
1748
+ try {
1749
+ const collected = [];
1750
+ let marker;
1751
+ while (true) {
1752
+ const tagsResp = await this.iamClient.send(new ListPolicyTagsCommand({
1753
+ PolicyArn: physicalId,
1754
+ ...marker ? { Marker: marker } : {}
1755
+ }));
1756
+ for (const t of tagsResp.Tags ?? []) collected.push({
1757
+ Key: t.Key,
1758
+ Value: t.Value
1759
+ });
1760
+ if (!tagsResp.IsTruncated) break;
1761
+ marker = tagsResp.Marker;
1762
+ }
1763
+ result["Tags"] = normalizeAwsTagsToCfn(collected);
1764
+ } catch (err) {
1765
+ if (!(err instanceof NoSuchEntityException)) throw err;
1766
+ }
1767
+ return result;
1768
+ }
1769
+ /**
1770
+ * Adopt an existing IAM managed policy into cdkd state.
1771
+ *
1772
+ * Lookup order:
1773
+ * 1. `--resource` override or `Properties.ManagedPolicyName` → walk
1774
+ * `ListPolicies(Scope: 'Local')` to find the matching ARN.
1775
+ * 2. `ListPolicies(Scope: 'Local')` → for each candidate, `ListPolicyTags`
1776
+ * and match against `aws:cdk:path`.
1777
+ *
1778
+ * Scope is forced to `'Local'` (customer-managed policies) — adopting an
1779
+ * AWS-managed policy would let cdkd delete it on next destroy, which would
1780
+ * be a major footgun.
1781
+ */
1782
+ async import(input) {
1783
+ const explicit = resolveExplicitPhysicalId(input, "ManagedPolicyName");
1784
+ if (explicit) {
1785
+ if (explicit.startsWith("arn:")) {
1786
+ if (explicit.startsWith("arn:aws:iam::aws:")) throw new Error(`Refusing to import AWS-managed policy ${explicit}: cdkd only adopts customer-managed policies. If you need to attach an AWS-managed policy to a role / user / group, reference it via ManagedPolicyArns on the principal instead.`);
1787
+ try {
1788
+ await this.iamClient.send(new GetPolicyCommand({ PolicyArn: explicit }));
1789
+ return {
1790
+ physicalId: explicit,
1791
+ attributes: { PolicyArn: explicit }
1792
+ };
1793
+ } catch (err) {
1794
+ if (err instanceof NoSuchEntityException) return null;
1795
+ throw err;
1796
+ }
1797
+ }
1798
+ const arnByName = await this.findPolicyArnByName(explicit);
1799
+ if (arnByName) return {
1800
+ physicalId: arnByName,
1801
+ attributes: { PolicyArn: arnByName }
1802
+ };
1803
+ return null;
1804
+ }
1805
+ if (!input.cdkPath) return null;
1806
+ let marker;
1807
+ do {
1808
+ const list = await this.iamClient.send(new ListPoliciesCommand({
1809
+ Scope: "Local",
1810
+ ...marker ? { Marker: marker } : {}
1811
+ }));
1812
+ for (const policy of list.Policies ?? []) {
1813
+ if (!policy.Arn) continue;
1814
+ try {
1815
+ if (matchesCdkPath((await this.iamClient.send(new ListPolicyTagsCommand({ PolicyArn: policy.Arn }))).Tags, input.cdkPath)) return {
1816
+ physicalId: policy.Arn,
1817
+ attributes: { PolicyArn: policy.Arn }
1818
+ };
1819
+ } catch (err) {
1820
+ if (err instanceof NoSuchEntityException) continue;
1821
+ throw err;
1822
+ }
1823
+ }
1824
+ marker = list.IsTruncated ? list.Marker : void 0;
1825
+ } while (marker);
1826
+ return null;
1827
+ }
1828
+ async attachToPrincipals(policyArn, groups, roles, users) {
1829
+ if (groups && Array.isArray(groups)) for (const groupName of groups) {
1830
+ await this.iamClient.send(new AttachGroupPolicyCommand({
1831
+ GroupName: groupName,
1832
+ PolicyArn: policyArn
1833
+ }));
1834
+ this.logger.debug(`Attached ${policyArn} to group ${groupName}`);
1835
+ }
1836
+ if (roles && Array.isArray(roles)) for (const roleName of roles) {
1837
+ await this.iamClient.send(new AttachRolePolicyCommand({
1838
+ RoleName: roleName,
1839
+ PolicyArn: policyArn
1840
+ }));
1841
+ this.logger.debug(`Attached ${policyArn} to role ${roleName}`);
1842
+ }
1843
+ if (users && Array.isArray(users)) for (const userName of users) {
1844
+ await this.iamClient.send(new AttachUserPolicyCommand({
1845
+ UserName: userName,
1846
+ PolicyArn: policyArn
1847
+ }));
1848
+ this.logger.debug(`Attached ${policyArn} to user ${userName}`);
1849
+ }
1850
+ }
1851
+ async updatePrincipals(policyArn, newGroups, oldGroups, newRoles, oldRoles, newUsers, oldUsers) {
1852
+ const newGroupSet = new Set(newGroups || []);
1853
+ const oldGroupSet = new Set(oldGroups || []);
1854
+ for (const g of newGroupSet) if (!oldGroupSet.has(g)) {
1855
+ await this.iamClient.send(new AttachGroupPolicyCommand({
1856
+ GroupName: g,
1857
+ PolicyArn: policyArn
1858
+ }));
1859
+ this.logger.debug(`Attached ${policyArn} to group ${g}`);
1860
+ }
1861
+ for (const g of oldGroupSet) if (!newGroupSet.has(g)) try {
1862
+ await this.iamClient.send(new DetachGroupPolicyCommand({
1863
+ GroupName: g,
1864
+ PolicyArn: policyArn
1865
+ }));
1866
+ this.logger.debug(`Detached ${policyArn} from group ${g}`);
1867
+ } catch (err) {
1868
+ if (!(err instanceof NoSuchEntityException)) throw err;
1869
+ }
1870
+ const newRoleSet = new Set(newRoles || []);
1871
+ const oldRoleSet = new Set(oldRoles || []);
1872
+ for (const r of newRoleSet) if (!oldRoleSet.has(r)) {
1873
+ await this.iamClient.send(new AttachRolePolicyCommand({
1874
+ RoleName: r,
1875
+ PolicyArn: policyArn
1876
+ }));
1877
+ this.logger.debug(`Attached ${policyArn} to role ${r}`);
1878
+ }
1879
+ for (const r of oldRoleSet) if (!newRoleSet.has(r)) try {
1880
+ await this.iamClient.send(new DetachRolePolicyCommand({
1881
+ RoleName: r,
1882
+ PolicyArn: policyArn
1883
+ }));
1884
+ this.logger.debug(`Detached ${policyArn} from role ${r}`);
1885
+ } catch (err) {
1886
+ if (!(err instanceof NoSuchEntityException)) throw err;
1887
+ }
1888
+ const newUserSet = new Set(newUsers || []);
1889
+ const oldUserSet = new Set(oldUsers || []);
1890
+ for (const u of newUserSet) if (!oldUserSet.has(u)) {
1891
+ await this.iamClient.send(new AttachUserPolicyCommand({
1892
+ UserName: u,
1893
+ PolicyArn: policyArn
1894
+ }));
1895
+ this.logger.debug(`Attached ${policyArn} to user ${u}`);
1896
+ }
1897
+ for (const u of oldUserSet) if (!newUserSet.has(u)) try {
1898
+ await this.iamClient.send(new DetachUserPolicyCommand({
1899
+ UserName: u,
1900
+ PolicyArn: policyArn
1901
+ }));
1902
+ this.logger.debug(`Detached ${policyArn} from user ${u}`);
1903
+ } catch (err) {
1904
+ if (!(err instanceof NoSuchEntityException)) throw err;
1905
+ }
1906
+ }
1907
+ async detachAllPrincipals(policyArn) {
1908
+ try {
1909
+ let marker;
1910
+ while (true) {
1911
+ const resp = await this.iamClient.send(new ListEntitiesForPolicyCommand({
1912
+ PolicyArn: policyArn,
1913
+ ...marker ? { Marker: marker } : {}
1914
+ }));
1915
+ for (const g of resp.PolicyGroups ?? []) {
1916
+ if (!g.GroupName) continue;
1917
+ try {
1918
+ await this.iamClient.send(new DetachGroupPolicyCommand({
1919
+ GroupName: g.GroupName,
1920
+ PolicyArn: policyArn
1921
+ }));
1922
+ } catch (err) {
1923
+ if (!(err instanceof NoSuchEntityException)) throw err;
1924
+ }
1925
+ }
1926
+ for (const r of resp.PolicyRoles ?? []) {
1927
+ if (!r.RoleName) continue;
1928
+ try {
1929
+ await this.iamClient.send(new DetachRolePolicyCommand({
1930
+ RoleName: r.RoleName,
1931
+ PolicyArn: policyArn
1932
+ }));
1933
+ } catch (err) {
1934
+ if (!(err instanceof NoSuchEntityException)) throw err;
1935
+ }
1936
+ }
1937
+ for (const u of resp.PolicyUsers ?? []) {
1938
+ if (!u.UserName) continue;
1939
+ try {
1940
+ await this.iamClient.send(new DetachUserPolicyCommand({
1941
+ UserName: u.UserName,
1942
+ PolicyArn: policyArn
1943
+ }));
1944
+ } catch (err) {
1945
+ if (!(err instanceof NoSuchEntityException)) throw err;
1946
+ }
1947
+ }
1948
+ if (!resp.IsTruncated) break;
1949
+ marker = resp.Marker;
1950
+ }
1951
+ } catch (err) {
1952
+ if (err instanceof NoSuchEntityException) return;
1953
+ throw err;
1954
+ }
1955
+ }
1956
+ /**
1957
+ * Delete every non-default version of the policy. Required before
1958
+ * `DeletePolicy` — AWS refuses to delete a policy that still has
1959
+ * non-default versions.
1960
+ */
1961
+ async deleteAllNonDefaultVersions(policyArn) {
1962
+ try {
1963
+ let marker;
1964
+ while (true) {
1965
+ const resp = await this.iamClient.send(new ListPolicyVersionsCommand({
1966
+ PolicyArn: policyArn,
1967
+ ...marker ? { Marker: marker } : {}
1968
+ }));
1969
+ for (const v of resp.Versions ?? []) {
1970
+ if (v.IsDefaultVersion) continue;
1971
+ if (!v.VersionId) continue;
1972
+ try {
1973
+ await this.iamClient.send(new DeletePolicyVersionCommand({
1974
+ PolicyArn: policyArn,
1975
+ VersionId: v.VersionId
1976
+ }));
1977
+ } catch (err) {
1978
+ if (!(err instanceof NoSuchEntityException)) throw err;
1979
+ }
1980
+ }
1981
+ if (!resp.IsTruncated) break;
1982
+ marker = resp.Marker;
1983
+ }
1984
+ } catch (err) {
1985
+ if (err instanceof NoSuchEntityException) return;
1986
+ throw err;
1987
+ }
1988
+ }
1989
+ /**
1990
+ * AWS caps managed policies at 5 versions. Before creating a new version,
1991
+ * prune the oldest non-default version if at the cap.
1992
+ */
1993
+ async ensureVersionCapacity(policyArn) {
1994
+ const versions = (await this.iamClient.send(new ListPolicyVersionsCommand({ PolicyArn: policyArn }))).Versions ?? [];
1995
+ if (versions.length < 5) return;
1996
+ const victim = versions.filter((v) => !v.IsDefaultVersion && v.VersionId).sort((a, b) => (a.CreateDate?.getTime() ?? 0) - (b.CreateDate?.getTime() ?? 0))[0];
1997
+ if (!victim?.VersionId) return;
1998
+ await this.iamClient.send(new DeletePolicyVersionCommand({
1999
+ PolicyArn: policyArn,
2000
+ VersionId: victim.VersionId
2001
+ }));
2002
+ this.logger.debug(`Pruned oldest non-default version ${victim.VersionId} of ${policyArn}`);
2003
+ }
2004
+ async updateTags(policyArn, newTags, oldTags) {
2005
+ const newTagMap = new Map((newTags || []).map((t) => [t.Key, t.Value]));
2006
+ const oldTagMap = new Map((oldTags || []).map((t) => [t.Key, t.Value]));
2007
+ const tagsToRemove = [];
2008
+ for (const key of oldTagMap.keys()) if (!newTagMap.has(key)) tagsToRemove.push(key);
2009
+ const tagsToAdd = [];
2010
+ for (const [key, value] of newTagMap) if (oldTagMap.get(key) !== value) tagsToAdd.push({
2011
+ Key: key,
2012
+ Value: value
2013
+ });
2014
+ if (tagsToRemove.length > 0) await this.iamClient.send(new UntagPolicyCommand({
2015
+ PolicyArn: policyArn,
2016
+ TagKeys: tagsToRemove
2017
+ }));
2018
+ if (tagsToAdd.length > 0) await this.iamClient.send(new TagPolicyCommand({
2019
+ PolicyArn: policyArn,
2020
+ Tags: tagsToAdd
2021
+ }));
2022
+ }
2023
+ async findPolicyArnByName(policyName) {
2024
+ let marker;
2025
+ do {
2026
+ const resp = await this.iamClient.send(new ListPoliciesCommand({
2027
+ Scope: "Local",
2028
+ ...marker ? { Marker: marker } : {}
2029
+ }));
2030
+ for (const p of resp.Policies ?? []) if (p.PolicyName === policyName && p.Arn) return p.Arn;
2031
+ marker = resp.IsTruncated ? resp.Marker : void 0;
2032
+ } while (marker);
2033
+ }
2034
+ };
2035
+ /**
2036
+ * Recover the policy name from `arn:aws:iam::<account>:policy/<path><name>`.
2037
+ * Used to decide whether `ManagedPolicyName` was mutated relative to the
2038
+ * physical id we recorded — name + path are immutable on AWS, so any
2039
+ * difference is a replacement signal.
2040
+ */
2041
+ function derivePolicyNameFromArn(arn) {
2042
+ const ix = arn.lastIndexOf("/");
2043
+ return ix >= 0 ? arn.slice(ix + 1) : arn;
2044
+ }
2045
+
1514
2046
  //#endregion
1515
2047
  //#region src/provisioning/providers/iam-instance-profile-provider.ts
1516
2048
  /**
@@ -6663,7 +7195,7 @@ var LambdaPermissionProvider = class {
6663
7195
  const statementId = physicalId.includes("|") ? physicalId.split("|").pop() : physicalId;
6664
7196
  let policyDoc;
6665
7197
  try {
6666
- policyDoc = (await this.lambdaClient.send(new GetPolicyCommand({ FunctionName: functionName }))).Policy;
7198
+ policyDoc = (await this.lambdaClient.send(new GetPolicyCommand$1({ FunctionName: functionName }))).Policy;
6667
7199
  } catch (err) {
6668
7200
  if (err instanceof ResourceNotFoundException) return void 0;
6669
7201
  throw err;
@@ -31504,6 +32036,7 @@ async function runDestroyForStack(stackName, state, ctx) {
31504
32036
  destroyProviderRegistry = new ProviderRegistry();
31505
32037
  registerAllProviders(destroyProviderRegistry);
31506
32038
  destroyProviderRegistry.setCustomResourceResponseBucket(ctx.stateBucket);
32039
+ if (ctx.allowUnsupportedTypes?.length) destroyProviderRegistry.allowUnsupportedTypes(ctx.allowUnsupportedTypes);
31507
32040
  }
31508
32041
  logger.info(`\nAcquiring lock for stack ${stackName}...`);
31509
32042
  await ctx.lockManager.acquireLock(stackName, regionForState, void 0, "destroy");
@@ -31973,6 +32506,7 @@ var NestedStackProvider = class {
31973
32506
  function registerAllProviders(registry) {
31974
32507
  registry.register("AWS::IAM::Role", new IAMRoleProvider());
31975
32508
  registry.register("AWS::IAM::Policy", new IAMPolicyProvider());
32509
+ registry.register("AWS::IAM::ManagedPolicy", new IAMManagedPolicyProvider());
31976
32510
  registry.register("AWS::IAM::InstanceProfile", new IAMInstanceProfileProvider());
31977
32511
  const iamUserGroupProvider = new IAMUserGroupProvider();
31978
32512
  registry.register("AWS::IAM::User", iamUserGroupProvider);
@@ -32369,6 +32903,7 @@ async function deployCommand(stacks, options) {
32369
32903
  const stackProviderRegistry = new ProviderRegistry();
32370
32904
  registerAllProviders(stackProviderRegistry);
32371
32905
  stackProviderRegistry.setCustomResourceResponseBucket(stateBucket, baseRegion);
32906
+ if (options.allowUnsupportedTypes?.length) stackProviderRegistry.allowUnsupportedTypes(options.allowUnsupportedTypes);
32372
32907
  try {
32373
32908
  if (skipPrefix) {
32374
32909
  const existing = await stackStateBackend.getState(stackInfo.stackName, stackRegion);
@@ -33847,7 +34382,6 @@ function isPlainObject(value) {
33847
34382
  * `Record<string, string>` for trivial JSON serialization if ever needed).
33848
34383
  */
33849
34384
  const CC_API_FALLBACK_DENY_LIST = {
33850
- "AWS::IAM::ManagedPolicy": "PolicyDocument is URL-encoded JSON in CC API responses, but cdkd state stores it as a parsed object — needs per-type decode",
33851
34385
  "AWS::ApiGateway::RestApi": "Body / BodyS3Location are write-only inputs not returned by CC API GetResource; cdkd state preserves them",
33852
34386
  "AWS::CloudFormation::Stack": "CC API returns runtime stack state (outputs/status), not the template parameters cdkd state stores",
33853
34387
  "AWS::EC2::LaunchTemplate": "CC API returns version-bumped LaunchTemplateData with synthetic LatestVersionNumber that diverges from the CFn input shape"
@@ -34619,6 +35153,7 @@ async function destroyCommand(stackArgs, options) {
34619
35153
  const providerRegistry = new ProviderRegistry();
34620
35154
  registerAllProviders(providerRegistry);
34621
35155
  providerRegistry.setCustomResourceResponseBucket(stateBucket);
35156
+ if (options.allowUnsupportedTypes?.length) providerRegistry.allowUnsupportedTypes(options.allowUnsupportedTypes);
34622
35157
  const appCmd = options.app || resolveApp();
34623
35158
  let appStacks = [];
34624
35159
  if (appCmd) try {
@@ -34755,6 +35290,7 @@ async function destroyCommand(stackArgs, options) {
34755
35290
  skipConfirmation: options.yes || options.force,
34756
35291
  removeProtection: options.removeProtection === true,
34757
35292
  exportIndexStore,
35293
+ ...options.allowUnsupportedTypes?.length && { allowUnsupportedTypes: options.allowUnsupportedTypes },
34758
35294
  ...options.resourceWarnAfter?.globalMs !== void 0 && { resourceWarnAfterMs: options.resourceWarnAfter.globalMs },
34759
35295
  ...options.resourceTimeout?.globalMs !== void 0 && { resourceTimeoutMs: options.resourceTimeout.globalMs },
34760
35296
  ...options.resourceWarnAfter?.perTypeMs && { resourceWarnAfterByType: options.resourceWarnAfter.perTypeMs },
@@ -39004,6 +39540,7 @@ async function stateDestroyCommand(stackArgs, options) {
39004
39540
  const providerRegistry = new ProviderRegistry();
39005
39541
  registerAllProviders(providerRegistry);
39006
39542
  providerRegistry.setCustomResourceResponseBucket(setup.bucket);
39543
+ if (options.allowUnsupportedTypes?.length) providerRegistry.allowUnsupportedTypes(options.allowUnsupportedTypes);
39007
39544
  try {
39008
39545
  const stateRefs = await setup.stateBackend.listStacks();
39009
39546
  const knownStackNames = new Set(stateRefs.map((r) => r.stackName));
@@ -39087,6 +39624,7 @@ async function stateDestroyCommand(stackArgs, options) {
39087
39624
  skipConfirmation: options.yes || options.all === true,
39088
39625
  removeProtection: options.removeProtection === true,
39089
39626
  exportIndexStore: setup.exportIndexStore,
39627
+ ...options.allowUnsupportedTypes?.length && { allowUnsupportedTypes: options.allowUnsupportedTypes },
39090
39628
  ...options.resourceWarnAfter?.globalMs !== void 0 && { resourceWarnAfterMs: options.resourceWarnAfter.globalMs },
39091
39629
  ...options.resourceTimeout?.globalMs !== void 0 && { resourceTimeoutMs: options.resourceTimeout.globalMs },
39092
39630
  ...options.resourceWarnAfter?.perTypeMs && { resourceWarnAfterByType: options.resourceWarnAfter.perTypeMs },
@@ -39118,7 +39656,8 @@ function createStateDestroyCommand() {
39118
39656
  [
39119
39657
  ...commonOptions,
39120
39658
  ...stateOptions,
39121
- ...resourceTimeoutOptions
39659
+ ...resourceTimeoutOptions,
39660
+ allowUnsupportedTypesOption
39122
39661
  ].forEach((opt) => cmd.addOption(opt));
39123
39662
  cmd.addOption(deprecatedRegionOption);
39124
39663
  return cmd;
@@ -55532,7 +56071,7 @@ function pickEssentialContainerId(instance, service) {
55532
56071
  const defaultWaitForExitImpl = async (containerId) => {
55533
56072
  const { execFile } = await import("node:child_process");
55534
56073
  const { promisify } = await import("node:util");
55535
- const { getDockerCmd } = await import("./docker-cmd-EtWSTAje.js").then((n) => n.t);
56074
+ const { getDockerCmd } = await import("./docker-cmd-iDMcWcre.js").then((n) => n.t);
55536
56075
  const { stdout } = await promisify(execFile)(getDockerCmd(), ["wait", containerId], { maxBuffer: 1024 * 1024 });
55537
56076
  const code = parseInt(stdout.trim(), 10);
55538
56077
  return Number.isFinite(code) ? code : -1;
@@ -58041,7 +58580,7 @@ function reorderArgs(argv) {
58041
58580
  */
58042
58581
  async function main() {
58043
58582
  const program = new Command();
58044
- program.name("cdkd").description("CDK Direct - Deploy AWS CDK apps directly via SDK/Cloud Control API").version("0.153.0");
58583
+ program.name("cdkd").description("CDK Direct - Deploy AWS CDK apps directly via SDK/Cloud Control API").version("0.155.0");
58045
58584
  program.addCommand(createBootstrapCommand());
58046
58585
  program.addCommand(createSynthCommand());
58047
58586
  program.addCommand(createListCommand());