@beesolve/aws-accounts 1.0.7 → 1.2.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/awsConfig.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { randomUUID } from "node:crypto";
2
2
  import { readFile, unlink, writeFile } from "node:fs/promises";
3
- import { join, resolve } from "node:path";
3
+ import { dirname, join, resolve } from "node:path";
4
4
  import { fileURLToPath, pathToFileURL } from "node:url";
5
5
  import { build as esbuildBuild } from "esbuild";
6
6
  import * as v from "valibot";
@@ -36,7 +36,8 @@ const deploymentSchema = v.strictObject({
36
36
  region: v.string(),
37
37
  lambdaArn: v.string(),
38
38
  stateBucketName: v.string(),
39
- stateCacheTtlSeconds: v.number()
39
+ stateCacheTtlSeconds: v.number(),
40
+ cliVersion: v.string()
40
41
  });
41
42
  const awsContextSchema = v.strictObject({
42
43
  version: nonEmptyString,
@@ -66,6 +67,17 @@ const awsConfigModelSchema = v.strictObject({
66
67
  key: v.string(),
67
68
  value: v.string()
68
69
  })
70
+ ),
71
+ alternateContacts: v.optional(
72
+ v.array(
73
+ v.strictObject({
74
+ contactType: v.picklist(["BILLING", "OPERATIONS", "SECURITY"]),
75
+ name: v.string(),
76
+ email: v.string(),
77
+ phone: v.string(),
78
+ title: v.optional(v.string())
79
+ })
80
+ )
69
81
  )
70
82
  })
71
83
  )
@@ -89,6 +101,7 @@ const awsConfigModelSchema = v.strictObject({
89
101
  v.strictObject({
90
102
  name: v.string(),
91
103
  description: v.string(),
104
+ sessionDuration: v.optional(v.string()),
92
105
  inlinePolicy: v.optional(iamPolicyDocumentSchema),
93
106
  awsManagedPolicies: v.array(v.string()),
94
107
  customerManagedPolicies: v.array(
@@ -106,6 +119,58 @@ const awsConfigModelSchema = v.strictObject({
106
119
  user: v.optional(v.string()),
107
120
  accounts: v.array(v.string())
108
121
  })
122
+ ),
123
+ accessControlAttributes: v.optional(
124
+ v.array(
125
+ v.strictObject({
126
+ key: v.string(),
127
+ source: v.array(v.string())
128
+ })
129
+ )
130
+ ),
131
+ policies: v.optional(
132
+ v.strictObject({
133
+ serviceControlPolicies: v.optional(
134
+ v.array(
135
+ v.strictObject({
136
+ name: v.string(),
137
+ description: v.optional(v.string()),
138
+ content: v.record(v.string(), v.unknown()),
139
+ targets: v.array(v.string())
140
+ })
141
+ )
142
+ ),
143
+ resourceControlPolicies: v.optional(
144
+ v.array(
145
+ v.strictObject({
146
+ name: v.string(),
147
+ description: v.optional(v.string()),
148
+ content: v.record(v.string(), v.unknown()),
149
+ targets: v.array(v.string())
150
+ })
151
+ )
152
+ ),
153
+ tagPolicies: v.optional(
154
+ v.array(
155
+ v.strictObject({
156
+ name: v.string(),
157
+ description: v.optional(v.string()),
158
+ content: v.record(v.string(), v.unknown()),
159
+ targets: v.array(v.string())
160
+ })
161
+ )
162
+ ),
163
+ aiServicesOptOutPolicies: v.optional(
164
+ v.array(
165
+ v.strictObject({
166
+ name: v.string(),
167
+ description: v.optional(v.string()),
168
+ content: v.record(v.string(), v.unknown()),
169
+ targets: v.array(v.string())
170
+ })
171
+ )
172
+ )
173
+ })
109
174
  )
110
175
  });
111
176
  const moduleDirectoryPath = resolve(
@@ -119,11 +184,13 @@ async function writeAwsConfigFromState(props) {
119
184
  state,
120
185
  context
121
186
  });
122
- const mappedConfig = mapStateToAwsConfig({
123
- state
124
- });
187
+ const mappedConfig = mapStateToAwsConfig({ state });
188
+ const mergedConfig = props.existingConfig != null ? {
189
+ ...props.existingConfig,
190
+ policies: props.existingConfig.policies ?? mappedConfig.policies
191
+ } : mappedConfig;
125
192
  const sortedConfig = sortAwsConfigModel({
126
- config: mappedConfig
193
+ config: mergedConfig
127
194
  });
128
195
  const nextConfigContent = renderAwsConfigTs({
129
196
  config: sortedConfig
@@ -327,10 +394,12 @@ function mapStateToAwsConfig(props) {
327
394
  `Could not map account "${account.name}" to organizational unit "${ownerOuName}".`
328
395
  );
329
396
  }
397
+ const contacts = account.alternateContacts;
330
398
  ownerOu.accounts.push({
331
399
  name: account.name,
332
400
  email: account.email,
333
- tags: account.tags ?? []
401
+ tags: account.tags ?? [],
402
+ alternateContacts: contacts != null && contacts.length > 0 ? contacts : void 0
334
403
  });
335
404
  }
336
405
  const permissionSetByArn = toRecordByProperty(
@@ -416,6 +485,73 @@ function mapStateToAwsConfig(props) {
416
485
  members.push(userName);
417
486
  }
418
487
  }
488
+ const orgPolicies = props.state.organization.policies ?? [];
489
+ const orgPolicyAttachments = props.state.organization.policyAttachments ?? [];
490
+ const ouById = toRecordByProperty(
491
+ props.state.organization.organizationalUnits,
492
+ "id"
493
+ );
494
+ const orgAccountById = toRecordByProperty(
495
+ props.state.organization.accounts,
496
+ "id"
497
+ );
498
+ function resolveTargetName(targetId, targetType) {
499
+ if (targetType === "ROOT") {
500
+ return "root";
501
+ }
502
+ if (targetType === "ORGANIZATIONAL_UNIT") {
503
+ return ouById[targetId]?.name ?? null;
504
+ }
505
+ if (targetType === "ACCOUNT") {
506
+ return orgAccountById[targetId]?.name ?? null;
507
+ }
508
+ return null;
509
+ }
510
+ const attachmentsByPolicyId = /* @__PURE__ */ new Map();
511
+ for (const attachment of orgPolicyAttachments) {
512
+ const targetName = resolveTargetName(
513
+ attachment.targetId,
514
+ attachment.targetType
515
+ );
516
+ if (targetName == null) {
517
+ continue;
518
+ }
519
+ const targets = attachmentsByPolicyId.get(attachment.policyId) ?? [];
520
+ targets.push(targetName);
521
+ attachmentsByPolicyId.set(attachment.policyId, targets);
522
+ }
523
+ const scps = orgPolicies.filter((p) => p.type === "SERVICE_CONTROL_POLICY").map((p) => ({
524
+ name: p.name,
525
+ description: p.description.length > 0 ? p.description : void 0,
526
+ content: JSON.parse(p.content),
527
+ targets: [...attachmentsByPolicyId.get(p.id) ?? []].sort(
528
+ (a, b) => a.localeCompare(b)
529
+ )
530
+ }));
531
+ const rcps = orgPolicies.filter((p) => p.type === "RESOURCE_CONTROL_POLICY").map((p) => ({
532
+ name: p.name,
533
+ description: p.description.length > 0 ? p.description : void 0,
534
+ content: JSON.parse(p.content),
535
+ targets: [...attachmentsByPolicyId.get(p.id) ?? []].sort(
536
+ (a, b) => a.localeCompare(b)
537
+ )
538
+ }));
539
+ const tagPolicies = orgPolicies.filter((p) => p.type === "TAG_POLICY").map((p) => ({
540
+ name: p.name,
541
+ description: p.description.length > 0 ? p.description : void 0,
542
+ content: JSON.parse(p.content),
543
+ targets: [...attachmentsByPolicyId.get(p.id) ?? []].sort(
544
+ (a, b) => a.localeCompare(b)
545
+ )
546
+ }));
547
+ const aiServicesOptOutPolicies = orgPolicies.filter((p) => p.type === "AISERVICES_OPT_OUT_POLICY").map((p) => ({
548
+ name: p.name,
549
+ description: p.description.length > 0 ? p.description : void 0,
550
+ content: JSON.parse(p.content),
551
+ targets: [...attachmentsByPolicyId.get(p.id) ?? []].sort(
552
+ (a, b) => a.localeCompare(b)
553
+ )
554
+ }));
419
555
  const mapped = {
420
556
  organizationalUnits,
421
557
  users: props.state.identityCenter.users.map((user) => ({
@@ -432,6 +568,7 @@ function mapStateToAwsConfig(props) {
432
568
  (permissionSet) => ({
433
569
  name: permissionSet.name,
434
570
  description: permissionSet.description,
571
+ sessionDuration: permissionSet.sessionDuration ?? void 0,
435
572
  inlinePolicy: permissionSet.inlinePolicy == null ? void 0 : parseInlinePolicyForConfig({
436
573
  permissionSetName: permissionSet.name,
437
574
  inlinePolicy: permissionSet.inlinePolicy
@@ -445,7 +582,17 @@ function mapStateToAwsConfig(props) {
445
582
  )
446
583
  })
447
584
  ),
448
- assignments: [...assignmentsByKey.values()]
585
+ assignments: [...assignmentsByKey.values()],
586
+ accessControlAttributes: props.state.identityCenter.accessControlAttributes.length > 0 ? props.state.identityCenter.accessControlAttributes.map((attr) => ({
587
+ key: attr.key,
588
+ source: [...attr.source]
589
+ })) : void 0,
590
+ policies: scps.length > 0 || rcps.length > 0 || tagPolicies.length > 0 || aiServicesOptOutPolicies.length > 0 ? {
591
+ serviceControlPolicies: scps.length > 0 ? scps : void 0,
592
+ resourceControlPolicies: rcps.length > 0 ? rcps : void 0,
593
+ tagPolicies: tagPolicies.length > 0 ? tagPolicies : void 0,
594
+ aiServicesOptOutPolicies: aiServicesOptOutPolicies.length > 0 ? aiServicesOptOutPolicies : void 0
595
+ } : void 0
449
596
  };
450
597
  assertUniqueNames({
451
598
  values: mapped.organizationalUnits.map((ou) => ou.name),
@@ -612,7 +759,8 @@ function mapAwsConfigToState(props) {
612
759
  email: account.email,
613
760
  status: matchedAccount?.status ?? "ACTIVE",
614
761
  parentId: ownerParentId,
615
- tags: account.tags
762
+ tags: account.tags,
763
+ alternateContacts: account.alternateContacts != null && account.alternateContacts.length > 0 ? account.alternateContacts : void 0
616
764
  });
617
765
  mappedAccountIdByName.set(account.name, mappedId);
618
766
  }
@@ -626,10 +774,7 @@ function mapAwsConfigToState(props) {
626
774
  email: user.email
627
775
  };
628
776
  });
629
- const mappedUserByUserName = toRecordByProperty(
630
- mappedUsers,
631
- "userName"
632
- );
777
+ const mappedUserByUserName = toRecordByProperty(mappedUsers, "userName");
633
778
  const mappedGroups = props.config.groups.map((group) => {
634
779
  const matchedGroup = groupByDisplayName[group.displayName];
635
780
  return {
@@ -667,6 +812,7 @@ function mapAwsConfigToState(props) {
667
812
  permissionSetArn: matchedPermissionSet?.permissionSetArn ?? pendingCreationId,
668
813
  name: permissionSet.name,
669
814
  description: permissionSet.description,
815
+ sessionDuration: permissionSet.sessionDuration ?? null,
670
816
  inlinePolicy: stableStringifyInlinePolicy(permissionSet.inlinePolicy),
671
817
  awsManagedPolicies: [...permissionSet.awsManagedPolicies],
672
818
  customerManagedPolicies: permissionSet.customerManagedPolicies.map(
@@ -707,13 +853,107 @@ function mapAwsConfigToState(props) {
707
853
  });
708
854
  }
709
855
  }
856
+ const configPolicies = props.config.policies;
857
+ const allConfigPolicies = [];
858
+ const ouByName = toRecordByProperty(
859
+ props.currentState.organization.organizationalUnits,
860
+ "name"
861
+ );
862
+ const stateAccountByName = toRecordByProperty(
863
+ props.currentState.organization.accounts,
864
+ "name"
865
+ );
866
+ function resolveTargetId(targetName) {
867
+ if (targetName === "root") {
868
+ return {
869
+ targetId: props.context.organization.rootId,
870
+ targetType: "ROOT"
871
+ };
872
+ }
873
+ const ou = ouByName[targetName];
874
+ if (ou != null) {
875
+ return { targetId: ou.id, targetType: "ORGANIZATIONAL_UNIT" };
876
+ }
877
+ const acct = stateAccountByName[targetName];
878
+ if (acct != null) {
879
+ return { targetId: acct.id, targetType: "ACCOUNT" };
880
+ }
881
+ return { targetId: pendingCreationId, targetType: "ACCOUNT" };
882
+ }
883
+ for (const policy of configPolicies?.serviceControlPolicies ?? []) {
884
+ allConfigPolicies.push({
885
+ name: policy.name,
886
+ description: policy.description ?? "",
887
+ type: "SERVICE_CONTROL_POLICY",
888
+ content: JSON.stringify(policy.content),
889
+ targets: policy.targets.map((t) => resolveTargetId(t))
890
+ });
891
+ }
892
+ for (const policy of configPolicies?.resourceControlPolicies ?? []) {
893
+ allConfigPolicies.push({
894
+ name: policy.name,
895
+ description: policy.description ?? "",
896
+ type: "RESOURCE_CONTROL_POLICY",
897
+ content: JSON.stringify(policy.content),
898
+ targets: policy.targets.map((t) => resolveTargetId(t))
899
+ });
900
+ }
901
+ for (const policy of configPolicies?.tagPolicies ?? []) {
902
+ allConfigPolicies.push({
903
+ name: policy.name,
904
+ description: policy.description ?? "",
905
+ type: "TAG_POLICY",
906
+ content: JSON.stringify(policy.content),
907
+ targets: policy.targets.map((t) => resolveTargetId(t))
908
+ });
909
+ }
910
+ for (const policy of configPolicies?.aiServicesOptOutPolicies ?? []) {
911
+ allConfigPolicies.push({
912
+ name: policy.name,
913
+ description: policy.description ?? "",
914
+ type: "AISERVICES_OPT_OUT_POLICY",
915
+ content: JSON.stringify(policy.content),
916
+ targets: policy.targets.map((t) => resolveTargetId(t))
917
+ });
918
+ }
919
+ const currentPoliciesByNameAndType = new Map(
920
+ (props.currentState.organization.policies ?? []).map((p) => [
921
+ `${p.type}|${p.name}`,
922
+ p
923
+ ])
924
+ );
925
+ const mappedPolicies = allConfigPolicies.map((p) => {
926
+ const current = currentPoliciesByNameAndType.get(`${p.type}|${p.name}`);
927
+ return {
928
+ id: current?.id ?? pendingCreationId,
929
+ arn: current?.arn ?? pendingCreationId,
930
+ name: p.name,
931
+ description: p.description,
932
+ type: p.type,
933
+ content: p.content
934
+ };
935
+ });
936
+ const mappedPolicyAttachments = [];
937
+ for (let i = 0; i < allConfigPolicies.length; i++) {
938
+ const configPolicy = allConfigPolicies[i];
939
+ const mappedPolicy = mappedPolicies[i];
940
+ for (const target of configPolicy.targets) {
941
+ mappedPolicyAttachments.push({
942
+ policyId: mappedPolicy.id,
943
+ targetId: target.targetId,
944
+ targetType: target.targetType
945
+ });
946
+ }
947
+ }
710
948
  const mapped = {
711
949
  version: props.currentState.version,
712
950
  generatedAt: props.currentState.generatedAt,
713
951
  organization: {
714
952
  rootId: props.context.organization.rootId,
715
953
  organizationalUnits: mappedOrganizationalUnits,
716
- accounts: mappedAccounts
954
+ accounts: mappedAccounts,
955
+ policies: mappedPolicies,
956
+ policyAttachments: mappedPolicyAttachments
717
957
  },
718
958
  identityCenter: {
719
959
  instanceArn: props.context.identityCenter.instanceArn,
@@ -729,7 +969,10 @@ function mapAwsConfigToState(props) {
729
969
  principalId: assignment.principalId,
730
970
  principalType: assignment.principalType,
731
971
  roleName: createAccessRoleName(assignment)
732
- }))
972
+ })),
973
+ accessControlAttributes: (props.config.accessControlAttributes ?? []).map(
974
+ (attr) => ({ key: attr.key, source: [...attr.source] })
975
+ )
733
976
  }
734
977
  };
735
978
  assertUniqueNames({
@@ -758,6 +1001,28 @@ function mapAwsConfigToState(props) {
758
1001
  ),
759
1002
  entityName: "permission set"
760
1003
  });
1004
+ assertUniqueNames({
1005
+ values: (props.config.policies?.serviceControlPolicies ?? []).map(
1006
+ (p) => p.name
1007
+ ),
1008
+ entityName: "SCP"
1009
+ });
1010
+ assertUniqueNames({
1011
+ values: (props.config.policies?.resourceControlPolicies ?? []).map(
1012
+ (p) => p.name
1013
+ ),
1014
+ entityName: "RCP"
1015
+ });
1016
+ assertUniqueNames({
1017
+ values: (props.config.policies?.tagPolicies ?? []).map((p) => p.name),
1018
+ entityName: "tag policy"
1019
+ });
1020
+ assertUniqueNames({
1021
+ values: (props.config.policies?.aiServicesOptOutPolicies ?? []).map(
1022
+ (p) => p.name
1023
+ ),
1024
+ entityName: "AI services opt-out policy"
1025
+ });
761
1026
  return validateState(mapped);
762
1027
  }
763
1028
  function sortAwsConfigModel(props) {
@@ -792,9 +1057,12 @@ function sortAwsConfigModel(props) {
792
1057
  for (const child of children) {
793
1058
  orderedOrganizationalUnits.push({
794
1059
  ...child,
795
- accounts: [...child.accounts].sort(
796
- (left, right) => left.name.localeCompare(right.name)
797
- )
1060
+ accounts: [...child.accounts].sort((left, right) => left.name.localeCompare(right.name)).map((account) => ({
1061
+ ...account,
1062
+ alternateContacts: account.alternateContacts == null ? void 0 : [...account.alternateContacts].sort(
1063
+ (a, b) => a.contactType.localeCompare(b.contactType)
1064
+ )
1065
+ }))
798
1066
  });
799
1067
  queue.push(child.name);
800
1068
  }
@@ -816,7 +1084,9 @@ function sortAwsConfigModel(props) {
816
1084
  awsManagedPolicies: [...permissionSet.awsManagedPolicies].sort(
817
1085
  (left, right) => left.localeCompare(right)
818
1086
  ),
819
- customerManagedPolicies: [...permissionSet.customerManagedPolicies].sort(
1087
+ customerManagedPolicies: [
1088
+ ...permissionSet.customerManagedPolicies
1089
+ ].sort(
820
1090
  (left, right) => compareStringKeys(left.path, right.path, left.name, right.name)
821
1091
  )
822
1092
  })).sort((left, right) => left.name.localeCompare(right.name)),
@@ -833,7 +1103,41 @@ function sortAwsConfigModel(props) {
833
1103
  return principalComparison;
834
1104
  }
835
1105
  return left.permissionSet.localeCompare(right.permissionSet);
836
- })
1106
+ }),
1107
+ accessControlAttributes: props.config.accessControlAttributes == null ? void 0 : [...props.config.accessControlAttributes].map((attr) => ({
1108
+ ...attr,
1109
+ source: [...attr.source].sort((a, b) => a.localeCompare(b))
1110
+ })).sort((a, b) => a.key.localeCompare(b.key)),
1111
+ policies: props.config.policies == null ? void 0 : {
1112
+ serviceControlPolicies: props.config.policies.serviceControlPolicies == null ? void 0 : [...props.config.policies.serviceControlPolicies].map((p) => ({
1113
+ ...p,
1114
+ content: sortJsonRecord(p.content),
1115
+ targets: [...p.targets].sort(
1116
+ (a, b) => a.localeCompare(b)
1117
+ )
1118
+ })).sort((a, b) => a.name.localeCompare(b.name)),
1119
+ resourceControlPolicies: props.config.policies.resourceControlPolicies == null ? void 0 : [...props.config.policies.resourceControlPolicies].map((p) => ({
1120
+ ...p,
1121
+ content: sortJsonRecord(p.content),
1122
+ targets: [...p.targets].sort(
1123
+ (a, b) => a.localeCompare(b)
1124
+ )
1125
+ })).sort((a, b) => a.name.localeCompare(b.name)),
1126
+ tagPolicies: props.config.policies.tagPolicies == null ? void 0 : [...props.config.policies.tagPolicies].map((p) => ({
1127
+ ...p,
1128
+ content: sortJsonRecord(p.content),
1129
+ targets: [...p.targets].sort(
1130
+ (a, b) => a.localeCompare(b)
1131
+ )
1132
+ })).sort((a, b) => a.name.localeCompare(b.name)),
1133
+ aiServicesOptOutPolicies: props.config.policies.aiServicesOptOutPolicies == null ? void 0 : [...props.config.policies.aiServicesOptOutPolicies].map((p) => ({
1134
+ ...p,
1135
+ content: sortJsonRecord(p.content),
1136
+ targets: [...p.targets].sort(
1137
+ (a, b) => a.localeCompare(b)
1138
+ )
1139
+ })).sort((a, b) => a.name.localeCompare(b.name))
1140
+ }
837
1141
  };
838
1142
  }
839
1143
  function renderAwsConfigTs(props) {
@@ -864,7 +1168,9 @@ function renderTsValue(value, props) {
864
1168
  return "null";
865
1169
  }
866
1170
  if (value === void 0) {
867
- throw new Error("Undefined values must be handled before TypeScript rendering.");
1171
+ throw new Error(
1172
+ "Undefined values must be handled before TypeScript rendering."
1173
+ );
868
1174
  }
869
1175
  if (typeof value === "string") {
870
1176
  return renderTsStringValue(value, props);
@@ -904,14 +1210,16 @@ ${renderedItems.map((item) => `${childIndent}${item}`).join(",\n")}
904
1210
  ${indent}]`;
905
1211
  }
906
1212
  function renderTsObject(value, props) {
907
- const entries = Object.entries(value).filter(([, entryValue]) => entryValue !== void 0);
1213
+ const entries = Object.entries(value).filter(
1214
+ ([, entryValue]) => entryValue !== void 0
1215
+ );
908
1216
  if (entries.length === 0) {
909
1217
  return "{}";
910
1218
  }
911
1219
  const indent = " ".repeat(props.indentLevel);
912
1220
  const childIndent = " ".repeat(props.indentLevel + 1);
913
1221
  const renderedEntries = entries.map(([key, entryValue]) => {
914
- const nextWithinInlinePolicy = props.withinInlinePolicy || key === "inlinePolicy";
1222
+ const nextWithinInlinePolicy = props.withinInlinePolicy || key === "inlinePolicy" || key === "content";
915
1223
  const renderedValue = renderTsValue(entryValue, {
916
1224
  indentLevel: props.indentLevel + 1,
917
1225
  withinInlinePolicy: nextWithinInlinePolicy,
@@ -934,10 +1242,14 @@ function renderPolicyActionString(value) {
934
1242
  if (knownActions == null || knownActions.includes(actionName) === false) {
935
1243
  return JSON.stringify(value);
936
1244
  }
937
- if (isIdentifierSafeServicePrefix(servicePrefix)) {
938
- return `iam.${servicePrefix}(${JSON.stringify(actionName)})`;
1245
+ const fnName = servicePrefixToCamelCase(servicePrefix);
1246
+ if (isIdentifierSafeServicePrefix(fnName)) {
1247
+ return `iam.${fnName}(${JSON.stringify(actionName)})`;
939
1248
  }
940
- return `iam[${JSON.stringify(servicePrefix)}](${JSON.stringify(actionName)})`;
1249
+ return `iam[${JSON.stringify(fnName)}](${JSON.stringify(actionName)})`;
1250
+ }
1251
+ function servicePrefixToCamelCase(value) {
1252
+ return value.replace(/-([a-z])/g, (_, c) => c.toUpperCase());
941
1253
  }
942
1254
  function isIdentifierSafeServicePrefix(value) {
943
1255
  return /^[A-Za-z_$][A-Za-z0-9_$]*$/u.test(value);
@@ -974,9 +1286,8 @@ function renderAwsConfigTypesTs(props) {
974
1286
  });
975
1287
  return `import * as v from "valibot";
976
1288
  import { iamPolicyDocumentSchema } from "@beesolve/iam-policy-ts";
1289
+ export * as iam from "@beesolve/iam-policy-ts";
977
1290
  export {
978
- iam,
979
- iamAction,
980
1291
  iamActionCatalog,
981
1292
  iamActionCatalogActionCount,
982
1293
  iamActionCatalogSourceSha256,
@@ -992,10 +1303,6 @@ export {
992
1303
  assertIamPolicyDocumentStrict,
993
1304
  } from "@beesolve/iam-policy-ts";
994
1305
  export type {
995
- IamActionCatalog,
996
- IamPolicyServicePrefix,
997
- IamPolicyActionNameByService,
998
- IamPolicyActionForService,
999
1306
  IamPolicyVersion,
1000
1307
  IamPolicyScalar,
1001
1308
  IamPolicyScalarList,
@@ -1033,6 +1340,17 @@ export const awsConfigSchema = v.strictObject({
1033
1340
  value: v.string(),
1034
1341
  }),
1035
1342
  ),
1343
+ alternateContacts: v.optional(
1344
+ v.array(
1345
+ v.strictObject({
1346
+ contactType: v.picklist(["BILLING", "OPERATIONS", "SECURITY"]),
1347
+ name: v.string(),
1348
+ email: v.string(),
1349
+ phone: v.string(),
1350
+ title: v.optional(v.string()),
1351
+ }),
1352
+ ),
1353
+ ),
1036
1354
  }),
1037
1355
  ),
1038
1356
  }),
@@ -1055,6 +1373,7 @@ export const awsConfigSchema = v.strictObject({
1055
1373
  v.strictObject({
1056
1374
  name: v.string(),
1057
1375
  description: v.string(),
1376
+ sessionDuration: v.optional(v.string()),
1058
1377
  inlinePolicy: v.optional(iamPolicyDocumentSchema),
1059
1378
  awsManagedPolicies: v.array(v.string()),
1060
1379
  customerManagedPolicies: v.array(
@@ -1073,6 +1392,58 @@ export const awsConfigSchema = v.strictObject({
1073
1392
  accounts: v.array(accountNameSchema),
1074
1393
  }),
1075
1394
  ),
1395
+ accessControlAttributes: v.optional(
1396
+ v.array(
1397
+ v.strictObject({
1398
+ key: v.string(),
1399
+ source: v.array(v.string()),
1400
+ }),
1401
+ ),
1402
+ ),
1403
+ policies: v.optional(
1404
+ v.strictObject({
1405
+ serviceControlPolicies: v.optional(
1406
+ v.array(
1407
+ v.strictObject({
1408
+ name: v.string(),
1409
+ description: v.optional(v.string()),
1410
+ content: v.record(v.string(), v.unknown()),
1411
+ targets: v.array(v.union([organizationalUnitNameSchema, accountNameSchema])),
1412
+ }),
1413
+ ),
1414
+ ),
1415
+ resourceControlPolicies: v.optional(
1416
+ v.array(
1417
+ v.strictObject({
1418
+ name: v.string(),
1419
+ description: v.optional(v.string()),
1420
+ content: v.record(v.string(), v.unknown()),
1421
+ targets: v.array(v.union([organizationalUnitNameSchema, accountNameSchema])),
1422
+ }),
1423
+ ),
1424
+ ),
1425
+ tagPolicies: v.optional(
1426
+ v.array(
1427
+ v.strictObject({
1428
+ name: v.string(),
1429
+ description: v.optional(v.string()),
1430
+ content: v.record(v.string(), v.unknown()),
1431
+ targets: v.array(v.union([organizationalUnitNameSchema, accountNameSchema])),
1432
+ }),
1433
+ ),
1434
+ ),
1435
+ aiServicesOptOutPolicies: v.optional(
1436
+ v.array(
1437
+ v.strictObject({
1438
+ name: v.string(),
1439
+ description: v.optional(v.string()),
1440
+ content: v.record(v.string(), v.unknown()),
1441
+ targets: v.array(v.union([organizationalUnitNameSchema, accountNameSchema])),
1442
+ }),
1443
+ ),
1444
+ ),
1445
+ }),
1446
+ ),
1076
1447
  });
1077
1448
 
1078
1449
  export type AwsConfig = v.InferOutput<typeof awsConfigSchema>;
@@ -1231,6 +1602,16 @@ async function loadAwsConfigModelFromTsFile(props) {
1231
1602
  async function readAwsContextFromFile(path) {
1232
1603
  return readAwsContextFile(path);
1233
1604
  }
1605
+ async function readPackageVersion() {
1606
+ const thisFile = fileURLToPath(import.meta.url);
1607
+ const packageDir = dirname(dirname(thisFile));
1608
+ const raw = await readFile(join(packageDir, "package.json"), "utf8");
1609
+ const pkg = JSON.parse(raw);
1610
+ if (typeof pkg.version !== "string") {
1611
+ throw new Error("Could not read version from package.json.");
1612
+ }
1613
+ return pkg.version;
1614
+ }
1234
1615
  async function loadAwsConfigTypesModule(props) {
1235
1616
  const loadedModule = await loadTsModule({
1236
1617
  modulePath: props.typesPath
@@ -1358,6 +1739,7 @@ export {
1358
1739
  loadAwsConfigModelFromTsFile,
1359
1740
  mapAwsConfigToState,
1360
1741
  readAwsContextFromFile,
1742
+ readPackageVersion,
1361
1743
  regenerateAwsConfigTypes,
1362
1744
  regenerateTypesFromState,
1363
1745
  writeAwsConfigFromState