@go-to-k/cdkd 0.94.9 → 0.94.11

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,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  import { a as setAwsClients, i as resetAwsClients, r as getAwsClients, t as AwsClients } from "./aws-clients-CuHRHcyW.js";
3
- import { $ as normalizeAwsError, A as resolveSkipPrefix, C as WorkGraph, D as getLegacyStateBucketName, E as getDefaultStateBucketName, G as ResourceTimeoutError, I as resolveBucketRegion, J as StackTerminationProtectionError, K as ResourceUpdateNotSupportedError, M as resolveStateBucketWithDefaultAndSource, N as warnDeprecatedNoPrefixCliFlag, O as resolveApp, P as AssemblyReader, R as CdkdError, S as stringifyValue, T as Synthesizer, U as PartialFailureError, V as LocalInvokeBuildError, W as ProvisioningError, _ as DagBuilder, a as withRetry, at as getLiveRenderer, b as S3StateBackend, c as CDK_PATH_TAG, ct as generateResourceName, d as resolveExplicitPhysicalId, dt as withStackName, et as withErrorHandling, f as ProviderRegistry, g as DiffCalculator, h as IntrinsicFunctionResolver, i as withResourceDeadline, it as runStackBuffered, j as resolveStateBucketWithDefault, k as resolveCaptureObservedState, l as matchesCdkPath, lt as generateResourceNameWithFallback, m as assertRegionMatch, n as DEFAULT_RESOURCE_WARN_AFTER_MS, nt as getLogger, o as IMPLICIT_DELETE_DEPENDENCIES, ot as PATTERN_B_NAME_PROPERTIES, p as CloudControlProvider, q as RouteDiscoveryError, r as DeployEngine, s as IAMRoleProvider, st as PATTERN_B_RESOURCE_TYPES, t as DEFAULT_RESOURCE_TIMEOUT_MS, u as normalizeAwsTagsToCfn, ut as withSkipPrefix, v as TemplateParser, w as buildDockerImage, x as AssetPublisher, y as LockManager } from "./deploy-engine-Cg4l-zyr.js";
3
+ import { A as resolveCaptureObservedState, C as stringifyValue, D as getDefaultStateBucketName, E as Synthesizer, F as AssemblyReader, G as ProvisioningError, H as LocalInvokeBuildError, J as RouteDiscoveryError, K as ResourceTimeoutError, L as resolveBucketRegion, M as resolveStateBucketWithDefault, N as resolveStateBucketWithDefaultAndSource, O as getLegacyStateBucketName, P as warnDeprecatedNoPrefixCliFlag, S as AssetPublisher, T as buildDockerImage, W as PartialFailureError, Y as StackTerminationProtectionError, _ as DiffCalculator, a as withRetry, at as runStackBuffered, b as LockManager, c as collectInlinePolicyNamesManagedBySiblings, ct as PATTERN_B_RESOURCE_TYPES, d as normalizeAwsTagsToCfn, dt as withSkipPrefix, et as normalizeAwsError, f as resolveExplicitPhysicalId, ft as withStackName, g as IntrinsicFunctionResolver, h as assertRegionMatch, i as withResourceDeadline, j as resolveSkipPrefix, k as resolveApp, l as CDK_PATH_TAG, lt as generateResourceName, m as CloudControlProvider, n as DEFAULT_RESOURCE_WARN_AFTER_MS, o as IMPLICIT_DELETE_DEPENDENCIES, ot as getLiveRenderer, p as ProviderRegistry, q as ResourceUpdateNotSupportedError, r as DeployEngine, rt as getLogger, s as IAMRoleProvider, st as PATTERN_B_NAME_PROPERTIES, t as DEFAULT_RESOURCE_TIMEOUT_MS, tt as withErrorHandling, u as matchesCdkPath, ut as generateResourceNameWithFallback, v as DagBuilder, w as WorkGraph, x as S3StateBackend, y as TemplateParser, z as CdkdError } from "./deploy-engine-627W8bPG.js";
4
4
  import { createHash, createPublicKey, createVerify, randomBytes, randomUUID } from "node:crypto";
5
5
  import { CopyObjectCommand, CreateBucketCommand, DeleteBucketAnalyticsConfigurationCommand, DeleteBucketCommand, DeleteBucketCorsCommand, DeleteBucketIntelligentTieringConfigurationCommand, DeleteBucketInventoryConfigurationCommand, DeleteBucketLifecycleCommand, DeleteBucketMetricsConfigurationCommand, DeleteBucketPolicyCommand, DeleteBucketReplicationCommand, DeleteBucketTaggingCommand, DeleteBucketWebsiteCommand, DeleteObjectCommand, 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 } from "@aws-sdk/client-s3";
6
6
  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";
@@ -2055,17 +2055,17 @@ var IAMUserGroupProvider = class {
2055
2055
  * Returns `undefined` when the user / group is gone
2056
2056
  * (`NoSuchEntityException`).
2057
2057
  */
2058
- async readCurrentState(physicalId, logicalId, resourceType, properties) {
2058
+ async readCurrentState(physicalId, logicalId, resourceType, properties, context) {
2059
2059
  switch (resourceType) {
2060
- case "AWS::IAM::User": return this.readUserCurrentState(physicalId, properties);
2061
- case "AWS::IAM::Group": return this.readGroupCurrentState(physicalId, properties);
2060
+ case "AWS::IAM::User": return this.readUserCurrentState(physicalId, properties, context);
2061
+ case "AWS::IAM::Group": return this.readGroupCurrentState(physicalId, properties, context);
2062
2062
  case "AWS::IAM::UserToGroupAddition": return;
2063
2063
  default:
2064
2064
  this.logger.debug(`readCurrentState: unsupported resource type ${resourceType} for ${logicalId}`);
2065
2065
  return;
2066
2066
  }
2067
2067
  }
2068
- async readUserCurrentState(physicalId, properties) {
2068
+ async readUserCurrentState(physicalId, properties, context) {
2069
2069
  let user;
2070
2070
  try {
2071
2071
  user = (await this.iamClient.send(new GetUserCommand({ UserName: physicalId }))).User;
@@ -2089,13 +2089,13 @@ var IAMUserGroupProvider = class {
2089
2089
  if (!(err instanceof NoSuchEntityException)) throw err;
2090
2090
  }
2091
2091
  try {
2092
- result["Policies"] = await this.collectInlinePolicies("user", physicalId, properties?.["Policies"] ?? []);
2092
+ result["Policies"] = await this.collectInlinePolicies("user", physicalId, properties?.["Policies"] ?? [], context);
2093
2093
  } catch (err) {
2094
2094
  if (!(err instanceof NoSuchEntityException)) throw err;
2095
2095
  }
2096
2096
  return result;
2097
2097
  }
2098
- async readGroupCurrentState(physicalId, properties) {
2098
+ async readGroupCurrentState(physicalId, properties, context) {
2099
2099
  let group;
2100
2100
  try {
2101
2101
  group = (await this.iamClient.send(new GetGroupCommand({ GroupName: physicalId }))).Group;
@@ -2113,7 +2113,7 @@ var IAMUserGroupProvider = class {
2113
2113
  if (!(err instanceof NoSuchEntityException)) throw err;
2114
2114
  }
2115
2115
  try {
2116
- result["Policies"] = await this.collectInlinePolicies("group", physicalId, properties?.["Policies"] ?? []);
2116
+ result["Policies"] = await this.collectInlinePolicies("group", physicalId, properties?.["Policies"] ?? [], context);
2117
2117
  } catch (err) {
2118
2118
  if (!(err instanceof NoSuchEntityException)) throw err;
2119
2119
  }
@@ -2126,8 +2126,13 @@ var IAMUserGroupProvider = class {
2126
2126
  * for bodies (URL-decoded + JSON-parsed) → reconcile order against
2127
2127
  * `statePolicies` so a positional compare doesn't fire false drift on
2128
2128
  * the lexicographic order returned by AWS.
2129
+ *
2130
+ * Issue #323: filters out policies whose name matches an
2131
+ * `AWS::IAM::Policy` sibling in the same stack (via `Users`/`Groups`
2132
+ * attachment field), so policies attached by `iam.Policy({ users: [u] })` /
2133
+ * `groups: [g]` don't fire false drift on the User / Group itself.
2129
2134
  */
2130
- async collectInlinePolicies(kind, physicalId, statePolicies) {
2135
+ async collectInlinePolicies(kind, physicalId, statePolicies, context) {
2131
2136
  const policyNames = [];
2132
2137
  let marker;
2133
2138
  while (true) {
@@ -2142,8 +2147,10 @@ var IAMUserGroupProvider = class {
2142
2147
  if (!listResp.IsTruncated) break;
2143
2148
  marker = listResp.Marker;
2144
2149
  }
2150
+ const managedByOtherResource = collectInlinePolicyNamesManagedBySiblings(physicalId, context, kind === "user" ? "Users" : "Groups");
2151
+ const filteredNames = policyNames.filter((n) => !managedByOtherResource.has(n));
2145
2152
  const bodies = /* @__PURE__ */ new Map();
2146
- await Promise.all(policyNames.map(async (name) => {
2153
+ await Promise.all(filteredNames.map(async (name) => {
2147
2154
  const resp = kind === "user" ? await this.iamClient.send(new GetUserPolicyCommand({
2148
2155
  UserName: physicalId,
2149
2156
  PolicyName: name
@@ -28070,6 +28077,14 @@ async function runDriftForStack(stackName, region, stateBackend, providerRegistr
28070
28077
  const entries = Object.entries(state.resources ?? {}).sort(([a], [b]) => a.localeCompare(b));
28071
28078
  for (const [logicalId, resource] of entries) {
28072
28079
  if (providerRegistry.shouldSkipResource(resource.resourceType)) continue;
28080
+ if (resource.resourceType.startsWith("Custom::") || resource.resourceType === "AWS::CloudFormation::CustomResource") {
28081
+ outcomes.push({
28082
+ kind: "skipped",
28083
+ logicalId,
28084
+ resourceType: resource.resourceType
28085
+ });
28086
+ continue;
28087
+ }
28073
28088
  let provider;
28074
28089
  try {
28075
28090
  provider = providerRegistry.getProvider(resource.resourceType);
@@ -28082,16 +28097,8 @@ async function runDriftForStack(stackName, region, stateBackend, providerRegistr
28082
28097
  continue;
28083
28098
  }
28084
28099
  let aws;
28085
- if (provider.readCurrentState) aws = await provider.readCurrentState(resource.physicalId, logicalId, resource.resourceType, resource.properties ?? {});
28100
+ if (provider.readCurrentState) aws = await provider.readCurrentState(resource.physicalId, logicalId, resource.resourceType, resource.properties ?? {}, buildReadCurrentStateContext(state, logicalId));
28086
28101
  else {
28087
- if (resource.resourceType.startsWith("Custom::")) {
28088
- outcomes.push({
28089
- kind: "unsupported",
28090
- logicalId,
28091
- resourceType: resource.resourceType
28092
- });
28093
- continue;
28094
- }
28095
28102
  if (CC_API_FALLBACK_DENY_LIST[resource.resourceType]) {
28096
28103
  outcomes.push({
28097
28104
  kind: "unsupported",
@@ -28157,6 +28164,24 @@ async function runDriftForStack(stackName, region, stateBackend, providerRegistr
28157
28164
  * paths through plain objects; arrays and scalars surface as a single drift
28158
28165
  * entry on the parent path. So we do not need to parse `[i]` segments.
28159
28166
  */
28167
+ /**
28168
+ * Issue #323: build the cross-resource context passed to
28169
+ * `provider.readCurrentState` so IAM Role / User / Group readers can
28170
+ * filter out inline policies managed by a sibling `AWS::IAM::Policy`
28171
+ * resource. `excludedLogicalId` is the resource being read — it's
28172
+ * omitted from the siblings map so a self-reference can never collide.
28173
+ */
28174
+ function buildReadCurrentStateContext(state, excludedLogicalId) {
28175
+ const siblings = {};
28176
+ for (const [lid, res] of Object.entries(state.resources ?? {})) {
28177
+ if (lid === excludedLogicalId) continue;
28178
+ siblings[lid] = {
28179
+ resourceType: res.resourceType,
28180
+ properties: res.properties ?? {}
28181
+ };
28182
+ }
28183
+ return { siblings };
28184
+ }
28160
28185
  function setAtPath(target, path, value) {
28161
28186
  if (path.length === 0) return;
28162
28187
  const segments = path.split(".");
@@ -28448,12 +28473,17 @@ function writeJsonReport(reports) {
28448
28473
  logicalId: o.logicalId,
28449
28474
  type: o.resourceType
28450
28475
  }));
28476
+ const skipped = r.outcomes.filter((o) => o.kind === "skipped").map((o) => ({
28477
+ logicalId: o.logicalId,
28478
+ type: o.resourceType
28479
+ }));
28451
28480
  return {
28452
28481
  stack: r.stackName,
28453
28482
  region: r.region,
28454
28483
  drifted,
28455
28484
  clean,
28456
- notSupported
28485
+ notSupported,
28486
+ skipped
28457
28487
  };
28458
28488
  });
28459
28489
  process.stdout.write(`${JSON.stringify(payload, null, 2)}\n`);
@@ -28462,8 +28492,9 @@ function writeHumanReport(reports) {
28462
28492
  for (const report of reports) {
28463
28493
  const drifted = report.outcomes.filter((o) => o.kind === "drifted");
28464
28494
  const unsupported = report.outcomes.filter((o) => o.kind === "unsupported");
28465
- const total = report.outcomes.length;
28466
- if (drifted.length === 0) process.stdout.write(`✓ ${report.stackName} (${report.region}): no drift detected (${total} resource${total === 1 ? "" : "s"} checked, ${unsupported.length} unsupported)\n`);
28495
+ const skippedCount = report.outcomes.filter((o) => o.kind === "skipped").length;
28496
+ const checked = report.outcomes.length - skippedCount;
28497
+ if (drifted.length === 0) process.stdout.write(`✓ ${report.stackName} (${report.region}): no drift detected (${checked} resource${checked === 1 ? "" : "s"} checked, ${unsupported.length} unsupported)\n`);
28467
28498
  else {
28468
28499
  const word = drifted.length === 1 ? "resource" : "resources";
28469
28500
  process.stdout.write(`\n⚠ ${report.stackName} (${report.region}): drift detected on ${drifted.length} ${word}\n\n`);
@@ -31031,7 +31062,7 @@ async function refreshObservedForStack(stackName, region, stateBackend, lockMana
31031
31062
  return;
31032
31063
  }
31033
31064
  try {
31034
- const observed = await provider.readCurrentState(resource.physicalId, logicalId, resource.resourceType, resource.properties ?? {});
31065
+ const observed = await provider.readCurrentState(resource.physicalId, logicalId, resource.resourceType, resource.properties ?? {}, buildReadCurrentStateContext(state, logicalId));
31035
31066
  if (observed === void 0) {
31036
31067
  unsupported++;
31037
31068
  return;
@@ -31872,7 +31903,7 @@ async function captureObservedForImportedResources(stackState, providerRegistry,
31872
31903
  try {
31873
31904
  const provider = providerRegistry.getProvider(resource.resourceType);
31874
31905
  if (!provider.readCurrentState) return;
31875
- const observed = await provider.readCurrentState(resource.physicalId, logicalId, resource.resourceType, resource.properties ?? {});
31906
+ const observed = await provider.readCurrentState(resource.physicalId, logicalId, resource.resourceType, resource.properties ?? {}, buildReadCurrentStateContext(stackState, logicalId));
31876
31907
  if (observed !== void 0) resource.observedProperties = observed;
31877
31908
  } catch (err) {
31878
31909
  logger.debug(`observedProperties capture for imported ${logicalId} (${resource.resourceType}) failed: ${err instanceof Error ? err.message : String(err)} — drift will fall back to template properties for this resource until the next successful deploy.`);
@@ -41661,7 +41692,7 @@ function reorderArgs(argv) {
41661
41692
  */
41662
41693
  async function main() {
41663
41694
  const program = new Command();
41664
- program.name("cdkd").description("CDK Direct - Deploy AWS CDK apps directly via SDK/Cloud Control API").version("0.94.8");
41695
+ program.name("cdkd").description("CDK Direct - Deploy AWS CDK apps directly via SDK/Cloud Control API").version("0.94.10");
41665
41696
  program.addCommand(createBootstrapCommand());
41666
41697
  program.addCommand(createSynthCommand());
41667
41698
  program.addCommand(createListCommand());