@go-to-k/cdkd 0.51.3 → 0.51.4

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
@@ -21733,10 +21733,21 @@ var EC2Provider = class {
21733
21733
  * `AllocationId`, `ConnectivityType`, `PrivateIpAddress`.
21734
21734
  * - **AWS::EC2::RouteTable**: `DescribeRouteTables` for `VpcId`.
21735
21735
  * - **AWS::EC2::SecurityGroup**: `DescribeSecurityGroups` for
21736
- * `GroupName`, `GroupDescription`, `VpcId`. Ingress / egress rules
21737
- * are NOT surfaced — the CFn shape is rule-list-style, while AWS
21738
- * returns IpPermissions in a different normalized form, and a
21739
- * faithful reverse-mapping is out of scope for v1.
21736
+ * `GroupName`, `GroupDescription`, `VpcId`, plus `SecurityGroupIngress`
21737
+ * and `SecurityGroupEgress` reverse-mapped from AWS's normalized
21738
+ * `IpPermissions[]` / `IpPermissionsEgress[]` form. Each AWS
21739
+ * `IpPermission` is flattened into one CFn rule per `IpRanges` /
21740
+ * `Ipv6Ranges` / `UserIdGroupPairs` / `PrefixListIds` entry; field
21741
+ * names follow CFn direction conventions (`Source*` for ingress,
21742
+ * `Destination*` for egress). When state templates ingress/egress
21743
+ * rules, AWS's response is reordered to match state's positional
21744
+ * order via `reconcileSgRules` so the comparator's array compare
21745
+ * doesn't fire false drift on AWS's normalized ordering. The
21746
+ * AWS-auto-attached "allow-all 0.0.0.0/0" egress rule is filtered
21747
+ * out of `SecurityGroupEgress` when state did not template egress
21748
+ * (the auto-default is invisible to drift). Both arrays are
21749
+ * always emitted (even as `[]`) so the v3 `observedProperties`
21750
+ * baseline catches console-side rule ADDs to a templated SG.
21740
21751
  * - **AWS::EC2::Instance**: `DescribeInstances` for `ImageId`,
21741
21752
  * `InstanceType`, `KeyName`, `SubnetId`. SecurityGroupIds /
21742
21753
  * BlockDeviceMappings shape-match is out of scope for v1.
@@ -21761,7 +21772,7 @@ var EC2Provider = class {
21761
21772
  * Returns `undefined` when the resource is gone (any `*NotFound` /
21762
21773
  * `Invalid*` error from the EC2 SDK matches `isNotFoundError`).
21763
21774
  */
21764
- async readCurrentState(physicalId, logicalId, resourceType) {
21775
+ async readCurrentState(physicalId, logicalId, resourceType, properties) {
21765
21776
  try {
21766
21777
  switch (resourceType) {
21767
21778
  case "AWS::EC2::VPC":
@@ -21775,7 +21786,7 @@ var EC2Provider = class {
21775
21786
  case "AWS::EC2::RouteTable":
21776
21787
  return await this.readRouteTableCurrentState(physicalId);
21777
21788
  case "AWS::EC2::SecurityGroup":
21778
- return await this.readSecurityGroupCurrentState(physicalId);
21789
+ return await this.readSecurityGroupCurrentState(physicalId, properties);
21779
21790
  case "AWS::EC2::Instance":
21780
21791
  return await this.readInstanceCurrentState(physicalId);
21781
21792
  case "AWS::EC2::NetworkAcl":
@@ -21884,7 +21895,7 @@ var EC2Provider = class {
21884
21895
  result["VpcId"] = rt.VpcId;
21885
21896
  return result;
21886
21897
  }
21887
- async readSecurityGroupCurrentState(physicalId) {
21898
+ async readSecurityGroupCurrentState(physicalId, properties) {
21888
21899
  const resp = await this.ec2Client.send(
21889
21900
  new DescribeSecurityGroupsCommand2({ GroupIds: [physicalId] })
21890
21901
  );
@@ -21898,6 +21909,15 @@ var EC2Provider = class {
21898
21909
  result["GroupDescription"] = sg.Description;
21899
21910
  if (sg.VpcId !== void 0)
21900
21911
  result["VpcId"] = sg.VpcId;
21912
+ const stateIngress = Array.isArray(properties?.["SecurityGroupIngress"]) ? properties["SecurityGroupIngress"] : void 0;
21913
+ const ingressRules = flattenIpPermissions(sg.IpPermissions ?? [], "ingress");
21914
+ result["SecurityGroupIngress"] = reconcileSgRules(ingressRules, stateIngress, "ingress");
21915
+ const stateEgress = Array.isArray(properties?.["SecurityGroupEgress"]) ? properties["SecurityGroupEgress"] : void 0;
21916
+ let egressRules = flattenIpPermissions(sg.IpPermissionsEgress ?? [], "egress");
21917
+ if (stateEgress === void 0) {
21918
+ egressRules = egressRules.filter((r) => !isDefaultEgressRule(r));
21919
+ }
21920
+ result["SecurityGroupEgress"] = reconcileSgRules(egressRules, stateEgress, "egress");
21901
21921
  return result;
21902
21922
  }
21903
21923
  async readInstanceCurrentState(physicalId) {
@@ -21967,6 +21987,115 @@ var EC2Provider = class {
21967
21987
  }
21968
21988
  }
21969
21989
  };
21990
+ function flattenIpPermissions(perms, direction) {
21991
+ const out = [];
21992
+ for (const p of perms) {
21993
+ const base = {};
21994
+ if (p.IpProtocol !== void 0)
21995
+ base["IpProtocol"] = p.IpProtocol;
21996
+ if (p.FromPort !== void 0)
21997
+ base["FromPort"] = p.FromPort;
21998
+ if (p.ToPort !== void 0)
21999
+ base["ToPort"] = p.ToPort;
22000
+ for (const ip of p.IpRanges ?? []) {
22001
+ const rule = { ...base };
22002
+ if (ip.CidrIp !== void 0)
22003
+ rule["CidrIp"] = ip.CidrIp;
22004
+ if (ip.Description !== void 0)
22005
+ rule["Description"] = ip.Description;
22006
+ out.push(rule);
22007
+ }
22008
+ for (const ipv6 of p.Ipv6Ranges ?? []) {
22009
+ const rule = { ...base };
22010
+ if (ipv6.CidrIpv6 !== void 0)
22011
+ rule["CidrIpv6"] = ipv6.CidrIpv6;
22012
+ if (ipv6.Description !== void 0)
22013
+ rule["Description"] = ipv6.Description;
22014
+ out.push(rule);
22015
+ }
22016
+ for (const grp of p.UserIdGroupPairs ?? []) {
22017
+ const rule = { ...base };
22018
+ if (direction === "ingress") {
22019
+ if (grp.GroupId !== void 0)
22020
+ rule["SourceSecurityGroupId"] = grp.GroupId;
22021
+ if (grp.UserId !== void 0)
22022
+ rule["SourceSecurityGroupOwnerId"] = grp.UserId;
22023
+ } else {
22024
+ if (grp.GroupId !== void 0)
22025
+ rule["DestinationSecurityGroupId"] = grp.GroupId;
22026
+ }
22027
+ if (grp.Description !== void 0)
22028
+ rule["Description"] = grp.Description;
22029
+ out.push(rule);
22030
+ }
22031
+ for (const pl of p.PrefixListIds ?? []) {
22032
+ const rule = { ...base };
22033
+ if (direction === "ingress") {
22034
+ if (pl.PrefixListId !== void 0)
22035
+ rule["SourcePrefixListId"] = pl.PrefixListId;
22036
+ } else {
22037
+ if (pl.PrefixListId !== void 0)
22038
+ rule["DestinationPrefixListId"] = pl.PrefixListId;
22039
+ }
22040
+ if (pl.Description !== void 0)
22041
+ rule["Description"] = pl.Description;
22042
+ out.push(rule);
22043
+ }
22044
+ if ((p.IpRanges?.length ?? 0) === 0 && (p.Ipv6Ranges?.length ?? 0) === 0 && (p.UserIdGroupPairs?.length ?? 0) === 0 && (p.PrefixListIds?.length ?? 0) === 0) {
22045
+ out.push({ ...base });
22046
+ }
22047
+ }
22048
+ return out;
22049
+ }
22050
+ function sgRuleKey(rule, direction) {
22051
+ const peerKey = direction === "egress" ? rule["DestinationSecurityGroupId"] : rule["SourceSecurityGroupId"];
22052
+ const prefixKey = direction === "egress" ? rule["DestinationPrefixListId"] : rule["SourcePrefixListId"];
22053
+ const peerOwner = direction === "ingress" ? rule["SourceSecurityGroupOwnerId"] : void 0;
22054
+ return JSON.stringify({
22055
+ p: rule["IpProtocol"] ?? "-1",
22056
+ f: rule["FromPort"] ?? null,
22057
+ t: rule["ToPort"] ?? null,
22058
+ c4: rule["CidrIp"] ?? null,
22059
+ c6: rule["CidrIpv6"] ?? null,
22060
+ peer: peerKey ?? null,
22061
+ peerOwner: peerOwner ?? null,
22062
+ pl: prefixKey ?? null,
22063
+ d: rule["Description"] ?? null
22064
+ });
22065
+ }
22066
+ function reconcileSgRules(awsRules, stateRules, direction) {
22067
+ if (!stateRules || stateRules.length === 0)
22068
+ return awsRules;
22069
+ const remaining = [...awsRules];
22070
+ const reordered = [];
22071
+ for (const sr of stateRules) {
22072
+ const key = sgRuleKey(sr, direction);
22073
+ const idx = remaining.findIndex((ar) => sgRuleKey(ar, direction) === key);
22074
+ if (idx >= 0) {
22075
+ reordered.push(remaining.splice(idx, 1)[0]);
22076
+ }
22077
+ }
22078
+ return [...reordered, ...remaining];
22079
+ }
22080
+ function isDefaultEgressRule(rule) {
22081
+ if (rule["IpProtocol"] !== "-1")
22082
+ return false;
22083
+ if (rule["CidrIp"] !== "0.0.0.0/0")
22084
+ return false;
22085
+ if (rule["CidrIpv6"] !== void 0)
22086
+ return false;
22087
+ if (rule["DestinationSecurityGroupId"] !== void 0)
22088
+ return false;
22089
+ if (rule["DestinationPrefixListId"] !== void 0)
22090
+ return false;
22091
+ if (rule["Description"] !== void 0)
22092
+ return false;
22093
+ if (rule["FromPort"] !== void 0 && rule["FromPort"] !== -1)
22094
+ return false;
22095
+ if (rule["ToPort"] !== void 0 && rule["ToPort"] !== -1)
22096
+ return false;
22097
+ return true;
22098
+ }
21970
22099
 
21971
22100
  // src/provisioning/providers/apigateway-provider.ts
21972
22101
  import {
@@ -44581,7 +44710,7 @@ function reorderArgs(argv) {
44581
44710
  }
44582
44711
  async function main() {
44583
44712
  const program = new Command14();
44584
- program.name("cdkd").description("CDK Direct - Deploy AWS CDK apps directly via SDK/Cloud Control API").version("0.51.3");
44713
+ program.name("cdkd").description("CDK Direct - Deploy AWS CDK apps directly via SDK/Cloud Control API").version("0.51.4");
44585
44714
  program.addCommand(createBootstrapCommand());
44586
44715
  program.addCommand(createSynthCommand());
44587
44716
  program.addCommand(createListCommand());