@beesolve/aws-accounts 1.1.0 → 1.2.1

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.
@@ -9,7 +9,7 @@ import { getSignedUrl } from "@aws-sdk/s3-request-presigner";
9
9
  import { OrganizationsClient as OrganizationsClient3 } from "@aws-sdk/client-organizations";
10
10
  import { SSOAdminClient as SSOAdminClient3 } from "@aws-sdk/client-sso-admin";
11
11
  import { IdentitystoreClient as IdentitystoreClient3 } from "@aws-sdk/client-identitystore";
12
- import { AccountClient as AccountClient2 } from "@aws-sdk/client-account";
12
+ import { AccountClient as AccountClient3 } from "@aws-sdk/client-account";
13
13
 
14
14
  // node_modules/valibot/dist/index.mjs
15
15
  var store$4;
@@ -792,6 +792,22 @@ var provisionIdcPermissionSetOperationSchema = strictObject({
792
792
  permissionSetName: string(),
793
793
  targetScope: literal("ALL_PROVISIONED_ACCOUNTS")
794
794
  });
795
+ var permissionsBoundaryOperationValueSchema = union([
796
+ strictObject({ managedPolicyArn: string() }),
797
+ strictObject({
798
+ customerManagedPolicyName: string(),
799
+ customerManagedPolicyPath: string()
800
+ })
801
+ ]);
802
+ var putIdcPermissionSetPermissionsBoundaryOperationSchema = strictObject({
803
+ kind: literal("putIdcPermissionSetPermissionsBoundary"),
804
+ permissionSetName: string(),
805
+ permissionsBoundary: permissionsBoundaryOperationValueSchema
806
+ });
807
+ var deleteIdcPermissionSetPermissionsBoundaryOperationSchema = strictObject({
808
+ kind: literal("deleteIdcPermissionSetPermissionsBoundary"),
809
+ permissionSetName: string()
810
+ });
795
811
  var grantIdcAccountAssignmentOperationSchema = strictObject({
796
812
  kind: literal("grantIdcAccountAssignment"),
797
813
  accountName: string(),
@@ -806,6 +822,92 @@ var revokeIdcAccountAssignmentOperationSchema = strictObject({
806
822
  principalType: picklist(["GROUP", "USER"]),
807
823
  principalName: string()
808
824
  });
825
+ var setIdcAccessControlAttributesOperationSchema = strictObject({
826
+ kind: literal("setIdcAccessControlAttributes"),
827
+ attributes: array(
828
+ strictObject({
829
+ key: string(),
830
+ source: array(string())
831
+ })
832
+ )
833
+ });
834
+ var alternateContactTypeSchema = picklist([
835
+ "BILLING",
836
+ "OPERATIONS",
837
+ "SECURITY"
838
+ ]);
839
+ var putAlternateContactOperationSchema = strictObject({
840
+ kind: literal("putAlternateContact"),
841
+ accountId: string(),
842
+ accountName: string(),
843
+ contactType: alternateContactTypeSchema,
844
+ name: string(),
845
+ email: string(),
846
+ phone: string(),
847
+ title: optional(string())
848
+ });
849
+ var deleteAlternateContactOperationSchema = strictObject({
850
+ kind: literal("deleteAlternateContact"),
851
+ accountId: string(),
852
+ accountName: string(),
853
+ contactType: alternateContactTypeSchema
854
+ });
855
+ var registerDelegatedAdministratorOperationSchema = strictObject({
856
+ kind: literal("registerDelegatedAdministrator"),
857
+ accountId: string(),
858
+ accountName: string(),
859
+ servicePrincipal: string()
860
+ });
861
+ var deregisterDelegatedAdministratorOperationSchema = strictObject({
862
+ kind: literal("deregisterDelegatedAdministrator"),
863
+ accountId: string(),
864
+ accountName: string(),
865
+ servicePrincipal: string()
866
+ });
867
+ var createOrgPolicyOperationSchema = strictObject({
868
+ kind: literal("createOrgPolicy"),
869
+ policyName: string(),
870
+ policyType: picklist([
871
+ "SERVICE_CONTROL_POLICY",
872
+ "RESOURCE_CONTROL_POLICY",
873
+ "TAG_POLICY",
874
+ "AISERVICES_OPT_OUT_POLICY",
875
+ "BACKUP_POLICY"
876
+ ]),
877
+ description: string(),
878
+ content: string()
879
+ });
880
+ var updateOrgPolicyContentOperationSchema = strictObject({
881
+ kind: literal("updateOrgPolicyContent"),
882
+ policyId: string(),
883
+ policyName: string(),
884
+ content: string()
885
+ });
886
+ var updateOrgPolicyDescriptionOperationSchema = strictObject({
887
+ kind: literal("updateOrgPolicyDescription"),
888
+ policyId: string(),
889
+ policyName: string(),
890
+ description: string()
891
+ });
892
+ var attachOrgPolicyOperationSchema = strictObject({
893
+ kind: literal("attachOrgPolicy"),
894
+ policyId: string(),
895
+ policyName: string(),
896
+ targetId: string(),
897
+ targetName: string()
898
+ });
899
+ var detachOrgPolicyOperationSchema = strictObject({
900
+ kind: literal("detachOrgPolicy"),
901
+ policyId: string(),
902
+ policyName: string(),
903
+ targetId: string(),
904
+ targetName: string()
905
+ });
906
+ var deleteOrgPolicyOperationSchema = strictObject({
907
+ kind: literal("deleteOrgPolicy"),
908
+ policyId: string(),
909
+ policyName: string()
910
+ });
809
911
  var operationSchema = variant("kind", [
810
912
  moveAccountOperationSchema,
811
913
  createOuOperationSchema,
@@ -834,8 +936,21 @@ var operationSchema = variant("kind", [
834
936
  attachIdcCustomerManagedPolicyReferenceToPermissionSetOperationSchema,
835
937
  detachIdcCustomerManagedPolicyReferenceFromPermissionSetOperationSchema,
836
938
  provisionIdcPermissionSetOperationSchema,
939
+ putIdcPermissionSetPermissionsBoundaryOperationSchema,
940
+ deleteIdcPermissionSetPermissionsBoundaryOperationSchema,
837
941
  grantIdcAccountAssignmentOperationSchema,
838
- revokeIdcAccountAssignmentOperationSchema
942
+ revokeIdcAccountAssignmentOperationSchema,
943
+ createOrgPolicyOperationSchema,
944
+ updateOrgPolicyContentOperationSchema,
945
+ updateOrgPolicyDescriptionOperationSchema,
946
+ attachOrgPolicyOperationSchema,
947
+ detachOrgPolicyOperationSchema,
948
+ deleteOrgPolicyOperationSchema,
949
+ putAlternateContactOperationSchema,
950
+ deleteAlternateContactOperationSchema,
951
+ setIdcAccessControlAttributesOperationSchema,
952
+ registerDelegatedAdministratorOperationSchema,
953
+ deregisterDelegatedAdministratorOperationSchema
839
954
  ]);
840
955
  var unsupportedDiffKindSchema = picklist([
841
956
  "ambiguousOuRename",
@@ -885,10 +1000,37 @@ var organizationalUnitSchema = strictObject({
885
1000
  arn: nonEmptyString,
886
1001
  name: nonEmptyString
887
1002
  });
1003
+ var orgPolicyTypeSchema = picklist([
1004
+ "SERVICE_CONTROL_POLICY",
1005
+ "RESOURCE_CONTROL_POLICY",
1006
+ "TAG_POLICY",
1007
+ "AISERVICES_OPT_OUT_POLICY",
1008
+ "BACKUP_POLICY"
1009
+ ]);
1010
+ var orgPolicySchema = strictObject({
1011
+ id: nonEmptyString,
1012
+ arn: nonEmptyString,
1013
+ name: nonEmptyString,
1014
+ description: string(),
1015
+ type: orgPolicyTypeSchema,
1016
+ content: nonEmptyString
1017
+ });
1018
+ var orgPolicyAttachmentSchema = strictObject({
1019
+ policyId: nonEmptyString,
1020
+ targetId: nonEmptyString,
1021
+ targetType: picklist(["ROOT", "ORGANIZATIONAL_UNIT", "ACCOUNT"])
1022
+ });
888
1023
  var accountTagSchema = strictObject({
889
1024
  key: nonEmptyString,
890
1025
  value: string()
891
1026
  });
1027
+ var alternateContactSchema = strictObject({
1028
+ contactType: picklist(["BILLING", "OPERATIONS", "SECURITY"]),
1029
+ name: string(),
1030
+ email: string(),
1031
+ phone: string(),
1032
+ title: optional(string())
1033
+ });
892
1034
  var accountSchema = strictObject({
893
1035
  id: nonEmptyString,
894
1036
  arn: nonEmptyString,
@@ -896,7 +1038,8 @@ var accountSchema = strictObject({
896
1038
  email: nonEmptyString,
897
1039
  status: nonEmptyString,
898
1040
  parentId: nonEmptyString,
899
- tags: array(accountTagSchema)
1041
+ tags: array(accountTagSchema),
1042
+ alternateContacts: optional(array(alternateContactSchema))
900
1043
  });
901
1044
  var userSchema = strictObject({
902
1045
  userId: nonEmptyString,
@@ -918,6 +1061,13 @@ var customerManagedPolicyReferenceSchema = strictObject({
918
1061
  name: nonEmptyString,
919
1062
  path: nonEmptyString
920
1063
  });
1064
+ var permissionsBoundarySchema = union([
1065
+ strictObject({ managedPolicyArn: nonEmptyString }),
1066
+ strictObject({
1067
+ customerManagedPolicyName: nonEmptyString,
1068
+ customerManagedPolicyPath: nonEmptyString
1069
+ })
1070
+ ]);
921
1071
  var permissionSetSchema = strictObject({
922
1072
  permissionSetArn: nonEmptyString,
923
1073
  name: nonEmptyString,
@@ -925,7 +1075,8 @@ var permissionSetSchema = strictObject({
925
1075
  sessionDuration: nullable(string()),
926
1076
  inlinePolicy: nullable(nonEmptyString),
927
1077
  awsManagedPolicies: array(nonEmptyString),
928
- customerManagedPolicies: array(customerManagedPolicyReferenceSchema)
1078
+ customerManagedPolicies: array(customerManagedPolicyReferenceSchema),
1079
+ permissionsBoundary: nullable(permissionsBoundarySchema)
929
1080
  });
930
1081
  var accountAssignmentSchema = strictObject({
931
1082
  accountId: nonEmptyString,
@@ -940,13 +1091,24 @@ var accessRoleSchema = strictObject({
940
1091
  principalType: principalTypeSchema,
941
1092
  roleName: nonEmptyString
942
1093
  });
1094
+ var accessControlAttributeSchema = strictObject({
1095
+ key: nonEmptyString,
1096
+ source: array(nonEmptyString)
1097
+ });
1098
+ var delegatedAdministratorSchema = strictObject({
1099
+ accountId: nonEmptyString,
1100
+ servicePrincipal: nonEmptyString
1101
+ });
943
1102
  var stateSchema = strictObject({
944
1103
  version: nonEmptyString,
945
1104
  generatedAt: nonEmptyString,
946
1105
  organization: strictObject({
947
1106
  rootId: nonEmptyString,
948
1107
  organizationalUnits: array(organizationalUnitSchema),
949
- accounts: array(accountSchema)
1108
+ accounts: array(accountSchema),
1109
+ policies: optional(array(orgPolicySchema)),
1110
+ policyAttachments: optional(array(orgPolicyAttachmentSchema)),
1111
+ delegatedAdministrators: optional(array(delegatedAdministratorSchema))
950
1112
  }),
951
1113
  identityCenter: strictObject({
952
1114
  instanceArn: nonEmptyString,
@@ -956,10 +1118,14 @@ var stateSchema = strictObject({
956
1118
  groupMemberships: array(groupMembershipSchema),
957
1119
  permissionSets: array(permissionSetSchema),
958
1120
  accountAssignments: array(accountAssignmentSchema),
959
- accessRoles: array(accessRoleSchema)
1121
+ accessRoles: array(accessRoleSchema),
1122
+ accessControlAttributes: array(accessControlAttributeSchema)
960
1123
  })
961
1124
  });
962
1125
  function createWorkingState(props) {
1126
+ const policies = props.state.organization.policies ?? [];
1127
+ const policyAttachments = props.state.organization.policyAttachments ?? [];
1128
+ const delegatedAdministrators = props.state.organization.delegatedAdministrators ?? [];
963
1129
  return {
964
1130
  version: props.state.version,
965
1131
  generatedAt: props.state.generatedAt,
@@ -973,6 +1139,18 @@ function createWorkingState(props) {
973
1139
  accountsByName: toRecordByProperty(
974
1140
  props.state.organization.accounts,
975
1141
  "name"
1142
+ ),
1143
+ policiesById: toRecordByProperty(policies, "id"),
1144
+ policiesByName: toRecordByProperty(policies, "name"),
1145
+ policyAttachments: structuredClone(policyAttachments),
1146
+ policyAttachmentsByKey: toRecordByProperty(
1147
+ policyAttachments,
1148
+ createOrgPolicyAttachmentKey
1149
+ ),
1150
+ delegatedAdministrators: structuredClone(delegatedAdministrators),
1151
+ delegatedAdministratorsByKey: toRecordByProperty(
1152
+ delegatedAdministrators,
1153
+ createDelegatedAdministratorKey
976
1154
  )
977
1155
  },
978
1156
  identityCenter: createWorkingIdentityCenterState({
@@ -989,7 +1167,16 @@ function materializeWorkingState(props) {
989
1167
  organizationalUnits: Object.values(
990
1168
  props.workingState.organization.organizationalUnitsById
991
1169
  ),
992
- accounts: Object.values(props.workingState.organization.accountsById)
1170
+ accounts: Object.values(props.workingState.organization.accountsById),
1171
+ policies: Object.values(props.workingState.organization.policiesById),
1172
+ policyAttachments: structuredClone(
1173
+ props.workingState.organization.policyAttachments
1174
+ ),
1175
+ ...props.workingState.organization.delegatedAdministrators.length > 0 ? {
1176
+ delegatedAdministrators: structuredClone(
1177
+ props.workingState.organization.delegatedAdministrators
1178
+ )
1179
+ } : {}
993
1180
  },
994
1181
  identityCenter: {
995
1182
  instanceArn: props.workingState.identityCenter.instanceArn,
@@ -1007,6 +1194,9 @@ function materializeWorkingState(props) {
1007
1194
  ),
1008
1195
  accessRoles: structuredClone(
1009
1196
  props.workingState.identityCenter.accessRoles
1197
+ ),
1198
+ accessControlAttributes: structuredClone(
1199
+ props.workingState.identityCenter.accessControlAttributes
1010
1200
  )
1011
1201
  }
1012
1202
  };
@@ -1219,7 +1409,7 @@ function removeIdcGroupFromWorkingState(props) {
1219
1409
  }
1220
1410
  function upsertIdcPermissionSetInWorkingState(props) {
1221
1411
  const currentPermissionSet = props.workingState.identityCenter.permissionSetsByName[props.permissionSet.name];
1222
- if (currentPermissionSet != null && currentPermissionSet.permissionSetArn === props.permissionSet.permissionSetArn && currentPermissionSet.name === props.permissionSet.name && currentPermissionSet.description === props.permissionSet.description && currentPermissionSet.sessionDuration === props.permissionSet.sessionDuration && currentPermissionSet.inlinePolicy === props.permissionSet.inlinePolicy && JSON.stringify(currentPermissionSet.awsManagedPolicies) === JSON.stringify(props.permissionSet.awsManagedPolicies) && JSON.stringify(currentPermissionSet.customerManagedPolicies) === JSON.stringify(props.permissionSet.customerManagedPolicies)) {
1412
+ if (currentPermissionSet != null && currentPermissionSet.permissionSetArn === props.permissionSet.permissionSetArn && currentPermissionSet.name === props.permissionSet.name && currentPermissionSet.description === props.permissionSet.description && currentPermissionSet.sessionDuration === props.permissionSet.sessionDuration && currentPermissionSet.inlinePolicy === props.permissionSet.inlinePolicy && JSON.stringify(currentPermissionSet.awsManagedPolicies) === JSON.stringify(props.permissionSet.awsManagedPolicies) && JSON.stringify(currentPermissionSet.customerManagedPolicies) === JSON.stringify(props.permissionSet.customerManagedPolicies) && JSON.stringify(currentPermissionSet.permissionsBoundary) === JSON.stringify(props.permissionSet.permissionsBoundary)) {
1223
1413
  return props.workingState;
1224
1414
  }
1225
1415
  const remainingPermissionSets = props.workingState.identityCenter.permissionSets.filter(
@@ -1361,6 +1551,154 @@ function removeAccountAssignmentFromWorkingState(props) {
1361
1551
  })
1362
1552
  };
1363
1553
  }
1554
+ function createOrgPolicyAttachmentKey(props) {
1555
+ return [props.policyId, props.targetId].join("|");
1556
+ }
1557
+ function upsertOrgPolicyInWorkingState(props) {
1558
+ const currentPolicy = props.workingState.organization.policiesById[props.policy.id];
1559
+ if (currentPolicy != null && currentPolicy.id === props.policy.id && currentPolicy.arn === props.policy.arn && currentPolicy.name === props.policy.name && currentPolicy.description === props.policy.description && currentPolicy.type === props.policy.type && currentPolicy.content === props.policy.content) {
1560
+ return props.workingState;
1561
+ }
1562
+ const remainingPolicies = Object.values(
1563
+ props.workingState.organization.policiesById
1564
+ ).filter((p) => p.id !== props.policy.id);
1565
+ const nextPolicies = [...remainingPolicies, props.policy];
1566
+ return {
1567
+ ...props.workingState,
1568
+ organization: {
1569
+ ...props.workingState.organization,
1570
+ policiesById: toRecordByProperty(nextPolicies, "id"),
1571
+ policiesByName: toRecordByProperty(nextPolicies, "name")
1572
+ }
1573
+ };
1574
+ }
1575
+ function removeOrgPolicyFromWorkingState(props) {
1576
+ if (props.workingState.organization.policiesById[props.policyId] == null) {
1577
+ return props.workingState;
1578
+ }
1579
+ const nextPolicies = Object.values(
1580
+ props.workingState.organization.policiesById
1581
+ ).filter((p) => p.id !== props.policyId);
1582
+ const nextAttachments = props.workingState.organization.policyAttachments.filter(
1583
+ (a) => a.policyId !== props.policyId
1584
+ );
1585
+ return {
1586
+ ...props.workingState,
1587
+ organization: {
1588
+ ...props.workingState.organization,
1589
+ policiesById: toRecordByProperty(nextPolicies, "id"),
1590
+ policiesByName: toRecordByProperty(nextPolicies, "name"),
1591
+ policyAttachments: nextAttachments,
1592
+ policyAttachmentsByKey: toRecordByProperty(
1593
+ nextAttachments,
1594
+ createOrgPolicyAttachmentKey
1595
+ )
1596
+ }
1597
+ };
1598
+ }
1599
+ function addOrgPolicyAttachmentToWorkingState(props) {
1600
+ const key = createOrgPolicyAttachmentKey({
1601
+ policyId: props.attachment.policyId,
1602
+ targetId: props.attachment.targetId
1603
+ });
1604
+ if (props.workingState.organization.policyAttachmentsByKey[key] != null) {
1605
+ return props.workingState;
1606
+ }
1607
+ const nextAttachments = [
1608
+ ...props.workingState.organization.policyAttachments,
1609
+ props.attachment
1610
+ ];
1611
+ return {
1612
+ ...props.workingState,
1613
+ organization: {
1614
+ ...props.workingState.organization,
1615
+ policyAttachments: nextAttachments,
1616
+ policyAttachmentsByKey: toRecordByProperty(
1617
+ nextAttachments,
1618
+ createOrgPolicyAttachmentKey
1619
+ )
1620
+ }
1621
+ };
1622
+ }
1623
+ function removeOrgPolicyAttachmentFromWorkingState(props) {
1624
+ const key = createOrgPolicyAttachmentKey({
1625
+ policyId: props.policyId,
1626
+ targetId: props.targetId
1627
+ });
1628
+ if (props.workingState.organization.policyAttachmentsByKey[key] == null) {
1629
+ return props.workingState;
1630
+ }
1631
+ const nextAttachments = props.workingState.organization.policyAttachments.filter(
1632
+ (a) => createOrgPolicyAttachmentKey({
1633
+ policyId: a.policyId,
1634
+ targetId: a.targetId
1635
+ }) !== key
1636
+ );
1637
+ return {
1638
+ ...props.workingState,
1639
+ organization: {
1640
+ ...props.workingState.organization,
1641
+ policyAttachments: nextAttachments,
1642
+ policyAttachmentsByKey: toRecordByProperty(
1643
+ nextAttachments,
1644
+ createOrgPolicyAttachmentKey
1645
+ )
1646
+ }
1647
+ };
1648
+ }
1649
+ function createDelegatedAdministratorKey(props) {
1650
+ return [props.accountId, props.servicePrincipal].join("|");
1651
+ }
1652
+ function upsertDelegatedAdministratorInWorkingState(props) {
1653
+ const key = createDelegatedAdministratorKey({
1654
+ accountId: props.delegatedAdministrator.accountId,
1655
+ servicePrincipal: props.delegatedAdministrator.servicePrincipal
1656
+ });
1657
+ if (props.workingState.organization.delegatedAdministratorsByKey[key] != null) {
1658
+ return props.workingState;
1659
+ }
1660
+ const nextDelegatedAdministrators = [
1661
+ ...props.workingState.organization.delegatedAdministrators,
1662
+ props.delegatedAdministrator
1663
+ ];
1664
+ return {
1665
+ ...props.workingState,
1666
+ organization: {
1667
+ ...props.workingState.organization,
1668
+ delegatedAdministrators: nextDelegatedAdministrators,
1669
+ delegatedAdministratorsByKey: toRecordByProperty(
1670
+ nextDelegatedAdministrators,
1671
+ createDelegatedAdministratorKey
1672
+ )
1673
+ }
1674
+ };
1675
+ }
1676
+ function removeDelegatedAdministratorFromWorkingState(props) {
1677
+ const key = createDelegatedAdministratorKey({
1678
+ accountId: props.accountId,
1679
+ servicePrincipal: props.servicePrincipal
1680
+ });
1681
+ if (props.workingState.organization.delegatedAdministratorsByKey[key] == null) {
1682
+ return props.workingState;
1683
+ }
1684
+ const nextDelegatedAdministrators = props.workingState.organization.delegatedAdministrators.filter(
1685
+ (da) => createDelegatedAdministratorKey({
1686
+ accountId: da.accountId,
1687
+ servicePrincipal: da.servicePrincipal
1688
+ }) !== key
1689
+ );
1690
+ return {
1691
+ ...props.workingState,
1692
+ organization: {
1693
+ ...props.workingState.organization,
1694
+ delegatedAdministrators: nextDelegatedAdministrators,
1695
+ delegatedAdministratorsByKey: toRecordByProperty(
1696
+ nextDelegatedAdministrators,
1697
+ createDelegatedAdministratorKey
1698
+ )
1699
+ }
1700
+ };
1701
+ }
1364
1702
  function createAccessRoleName(assignment) {
1365
1703
  return `AWSReservedSSO_${assignment.permissionSetArn.split("/").at(-1) ?? "PermissionSet"}_${assignment.accountId}`;
1366
1704
  }
@@ -1395,7 +1733,10 @@ function createWorkingIdentityCenterState(props) {
1395
1733
  ),
1396
1734
  accessRoles: createAccessRoles({
1397
1735
  accountAssignments
1398
- })
1736
+ }),
1737
+ accessControlAttributes: structuredClone(
1738
+ props.identityCenter.accessControlAttributes ?? []
1739
+ )
1399
1740
  };
1400
1741
  }
1401
1742
  function materializeWorkingIdentityCenterState(props) {
@@ -1409,7 +1750,10 @@ function materializeWorkingIdentityCenterState(props) {
1409
1750
  accountAssignments: structuredClone(
1410
1751
  props.identityCenter.accountAssignments
1411
1752
  ),
1412
- accessRoles: structuredClone(props.identityCenter.accessRoles)
1753
+ accessRoles: structuredClone(props.identityCenter.accessRoles),
1754
+ accessControlAttributes: structuredClone(
1755
+ props.identityCenter.accessControlAttributes
1756
+ )
1413
1757
  };
1414
1758
  }
1415
1759
  function createAccessRoles(props) {
@@ -1448,28 +1792,43 @@ import {
1448
1792
  ListUsersCommand
1449
1793
  } from "@aws-sdk/client-identitystore";
1450
1794
  import {
1795
+ DescribeOrganizationCommand,
1796
+ DescribePolicyCommand,
1451
1797
  ListAccountsCommand,
1798
+ ListDelegatedAdministratorsCommand,
1799
+ ListDelegatedServicesForAccountCommand,
1452
1800
  ListOrganizationalUnitsForParentCommand,
1453
1801
  ListParentsCommand,
1802
+ ListPoliciesCommand,
1454
1803
  ListRootsCommand,
1455
- ListTagsForResourceCommand
1804
+ ListTagsForResourceCommand,
1805
+ ListTargetsForPolicyCommand
1456
1806
  } from "@aws-sdk/client-organizations";
1457
1807
  import {
1458
1808
  DescribePermissionSetCommand,
1459
1809
  GetInlinePolicyForPermissionSetCommand,
1810
+ GetPermissionsBoundaryForPermissionSetCommand,
1460
1811
  ListAccountAssignmentsCommand,
1461
1812
  ListAccountsForProvisionedPermissionSetCommand,
1462
1813
  ListCustomerManagedPolicyReferencesInPermissionSetCommand,
1814
+ DescribeInstanceAccessControlAttributeConfigurationCommand,
1463
1815
  ListInstancesCommand,
1464
1816
  ListManagedPoliciesInPermissionSetCommand,
1465
1817
  ListPermissionSetsCommand
1466
1818
  } from "@aws-sdk/client-sso-admin";
1819
+ import {
1820
+ GetAlternateContactCommand
1821
+ } from "@aws-sdk/client-account";
1467
1822
  async function scanOrganization(props) {
1468
- const roots = await props.organizationsClient.send(new ListRootsCommand({}));
1469
- const root = roots.Roots?.[0];
1823
+ const [rootsResponse, orgResponse] = await Promise.all([
1824
+ props.organizationsClient.send(new ListRootsCommand({})),
1825
+ props.organizationsClient.send(new DescribeOrganizationCommand({}))
1826
+ ]);
1827
+ const root = rootsResponse.Roots?.[0];
1470
1828
  if (root?.Id == null) {
1471
1829
  throw new Error("No organization root found.");
1472
1830
  }
1831
+ const managementAccountId = orgResponse.Organization?.MasterAccountId;
1473
1832
  const organizationalUnits = await collectOrganizationalUnits({
1474
1833
  organizationsClient: props.organizationsClient,
1475
1834
  parentId: root.Id
@@ -1493,6 +1852,11 @@ async function scanOrganization(props) {
1493
1852
  ResourceId: account.Id
1494
1853
  })
1495
1854
  );
1855
+ const alternateContacts = await scanAlternateContacts({
1856
+ accountClient: props.accountClient,
1857
+ accountId: account.Id,
1858
+ isManagementAccount: account.Id === managementAccountId
1859
+ });
1496
1860
  accounts.push({
1497
1861
  id: account.Id,
1498
1862
  arn: account.Arn,
@@ -1510,17 +1874,138 @@ async function scanOrganization(props) {
1510
1874
  value: tag.Value ?? ""
1511
1875
  }
1512
1876
  ];
1513
- })
1877
+ }),
1878
+ alternateContacts: alternateContacts.length > 0 ? alternateContacts : void 0
1514
1879
  });
1515
1880
  }
1516
1881
  nextToken = response.NextToken;
1517
1882
  } while (nextToken != null);
1883
+ const [{ policies, policyAttachments }, delegatedAdministrators] = await Promise.all([
1884
+ scanOrganizationPolicies({
1885
+ organizationsClient: props.organizationsClient
1886
+ }),
1887
+ scanDelegatedAdministrators({
1888
+ organizationsClient: props.organizationsClient
1889
+ })
1890
+ ]);
1518
1891
  return {
1519
1892
  rootId: root.Id,
1520
1893
  organizationalUnits,
1521
- accounts
1894
+ accounts,
1895
+ policies,
1896
+ policyAttachments,
1897
+ delegatedAdministrators: delegatedAdministrators.length > 0 ? delegatedAdministrators : void 0
1522
1898
  };
1523
1899
  }
1900
+ async function scanDelegatedAdministrators(props) {
1901
+ const accountIds = new Array();
1902
+ let nextToken;
1903
+ do {
1904
+ const response = await props.organizationsClient.send(
1905
+ new ListDelegatedAdministratorsCommand({ NextToken: nextToken })
1906
+ );
1907
+ for (const admin of response.DelegatedAdministrators ?? []) {
1908
+ if (admin.Id == null) {
1909
+ continue;
1910
+ }
1911
+ accountIds.push(admin.Id);
1912
+ }
1913
+ nextToken = response.NextToken;
1914
+ } while (nextToken != null);
1915
+ const results = [];
1916
+ for (const accountId of accountIds) {
1917
+ let servicesNextToken;
1918
+ do {
1919
+ const response = await props.organizationsClient.send(
1920
+ new ListDelegatedServicesForAccountCommand({
1921
+ AccountId: accountId,
1922
+ NextToken: servicesNextToken
1923
+ })
1924
+ );
1925
+ for (const service of response.DelegatedServices ?? []) {
1926
+ if (service.ServicePrincipal == null) {
1927
+ continue;
1928
+ }
1929
+ results.push({ accountId, servicePrincipal: service.ServicePrincipal });
1930
+ }
1931
+ servicesNextToken = response.NextToken;
1932
+ } while (servicesNextToken != null);
1933
+ }
1934
+ return results;
1935
+ }
1936
+ var ORG_POLICY_TYPES = [
1937
+ "SERVICE_CONTROL_POLICY",
1938
+ "RESOURCE_CONTROL_POLICY",
1939
+ "TAG_POLICY",
1940
+ "AISERVICES_OPT_OUT_POLICY",
1941
+ "BACKUP_POLICY"
1942
+ ];
1943
+ async function scanOrganizationPolicies(props) {
1944
+ const policies = [];
1945
+ const policyAttachments = [];
1946
+ for (const policyType of ORG_POLICY_TYPES) {
1947
+ let nextToken;
1948
+ const policyIds = [];
1949
+ do {
1950
+ const response = await props.organizationsClient.send(
1951
+ new ListPoliciesCommand({ Filter: policyType, NextToken: nextToken })
1952
+ );
1953
+ for (const summary of response.Policies ?? []) {
1954
+ if (summary.Id == null || summary.AwsManaged === true) {
1955
+ continue;
1956
+ }
1957
+ policyIds.push(summary.Id);
1958
+ }
1959
+ nextToken = response.NextToken;
1960
+ } while (nextToken != null);
1961
+ for (const policyId of policyIds) {
1962
+ const describeResponse = await props.organizationsClient.send(
1963
+ new DescribePolicyCommand({ PolicyId: policyId })
1964
+ );
1965
+ const policy = describeResponse.Policy;
1966
+ if (policy?.PolicySummary?.Id == null || policy.PolicySummary.Arn == null || policy.PolicySummary.Name == null) {
1967
+ continue;
1968
+ }
1969
+ const content = policy.Content;
1970
+ if (content == null || content.length === 0) {
1971
+ continue;
1972
+ }
1973
+ policies.push({
1974
+ id: policy.PolicySummary.Id,
1975
+ arn: policy.PolicySummary.Arn,
1976
+ name: policy.PolicySummary.Name,
1977
+ description: policy.PolicySummary.Description ?? "",
1978
+ type: policyType,
1979
+ content
1980
+ });
1981
+ let targetsNextToken;
1982
+ do {
1983
+ const targetsResponse = await props.organizationsClient.send(
1984
+ new ListTargetsForPolicyCommand({
1985
+ PolicyId: policyId,
1986
+ NextToken: targetsNextToken
1987
+ })
1988
+ );
1989
+ for (const target of targetsResponse.Targets ?? []) {
1990
+ if (target.TargetId == null || target.Type == null) {
1991
+ continue;
1992
+ }
1993
+ const targetType = target.Type;
1994
+ if (targetType !== "ROOT" && targetType !== "ORGANIZATIONAL_UNIT" && targetType !== "ACCOUNT") {
1995
+ continue;
1996
+ }
1997
+ policyAttachments.push({
1998
+ policyId,
1999
+ targetId: target.TargetId,
2000
+ targetType
2001
+ });
2002
+ }
2003
+ targetsNextToken = targetsResponse.NextToken;
2004
+ } while (targetsNextToken != null);
2005
+ }
2006
+ }
2007
+ return { policies, policyAttachments };
2008
+ }
1524
2009
  async function collectOrganizationalUnits(props) {
1525
2010
  const children = [];
1526
2011
  let nextToken;
@@ -1563,7 +2048,7 @@ async function scanIdentityCenter(props) {
1563
2048
  instances,
1564
2049
  requestedInstanceArn: props.requestedInstanceArn
1565
2050
  });
1566
- const [users, groups, permissionSets] = await Promise.all([
2051
+ const [users, groups, permissionSets, accessControlAttributes] = await Promise.all([
1567
2052
  listIdentityStoreUsers({
1568
2053
  identityStoreClient: props.identityStoreClient,
1569
2054
  identityStoreId: instance.identityStoreId
@@ -1575,6 +2060,10 @@ async function scanIdentityCenter(props) {
1575
2060
  listPermissionSets({
1576
2061
  ssoAdminClient: props.ssoAdminClient,
1577
2062
  instanceArn: instance.instanceArn
2063
+ }),
2064
+ scanAccessControlAttributes({
2065
+ ssoAdminClient: props.ssoAdminClient,
2066
+ instanceArn: instance.instanceArn
1578
2067
  })
1579
2068
  ]);
1580
2069
  const groupMemberships = await listGroupMemberships({
@@ -1599,9 +2088,30 @@ async function scanIdentityCenter(props) {
1599
2088
  groupMemberships,
1600
2089
  permissionSets,
1601
2090
  accountAssignments,
1602
- accessRoles
2091
+ accessRoles,
2092
+ accessControlAttributes
1603
2093
  };
1604
2094
  }
2095
+ async function scanAccessControlAttributes(props) {
2096
+ let response;
2097
+ try {
2098
+ response = await props.ssoAdminClient.send(
2099
+ new DescribeInstanceAccessControlAttributeConfigurationCommand({
2100
+ InstanceArn: props.instanceArn
2101
+ })
2102
+ );
2103
+ } catch (err) {
2104
+ if (err != null && typeof err === "object" && "name" in err && err.name === "ResourceNotFoundException") {
2105
+ return [];
2106
+ }
2107
+ throw err;
2108
+ }
2109
+ const attributes = response.InstanceAccessControlAttributeConfiguration?.AccessControlAttributes ?? [];
2110
+ return attributes.filter((attr) => attr.Key != null).map((attr) => ({
2111
+ key: attr.Key,
2112
+ source: attr.Value?.Source ?? []
2113
+ }));
2114
+ }
1605
2115
  function selectIdentityCenterInstance(props) {
1606
2116
  if (props.requestedInstanceArn != null) {
1607
2117
  const selected2 = props.instances.find(
@@ -1752,7 +2262,8 @@ async function listPermissionSets(props) {
1752
2262
  const [
1753
2263
  inlinePolicy,
1754
2264
  awsManagedPolicies,
1755
- customerManagedPolicies
2265
+ customerManagedPolicies,
2266
+ permissionsBoundary
1756
2267
  ] = await Promise.all([
1757
2268
  getInlinePolicyForPermissionSet({
1758
2269
  ssoAdminClient: props.ssoAdminClient,
@@ -1768,6 +2279,11 @@ async function listPermissionSets(props) {
1768
2279
  ssoAdminClient: props.ssoAdminClient,
1769
2280
  instanceArn: props.instanceArn,
1770
2281
  permissionSetArn: permissionSet.PermissionSetArn
2282
+ }),
2283
+ getPermissionsBoundaryForPermissionSet({
2284
+ ssoAdminClient: props.ssoAdminClient,
2285
+ instanceArn: props.instanceArn,
2286
+ permissionSetArn: permissionSet.PermissionSetArn
1771
2287
  })
1772
2288
  ]);
1773
2289
  return {
@@ -1777,7 +2293,8 @@ async function listPermissionSets(props) {
1777
2293
  sessionDuration: permissionSet.SessionDuration ?? null,
1778
2294
  inlinePolicy,
1779
2295
  awsManagedPolicies,
1780
- customerManagedPolicies
2296
+ customerManagedPolicies,
2297
+ permissionsBoundary
1781
2298
  };
1782
2299
  })
1783
2300
  );
@@ -1795,6 +2312,29 @@ async function getInlinePolicyForPermissionSet(props) {
1795
2312
  const inlinePolicy = response.InlinePolicy?.trim();
1796
2313
  return inlinePolicy != null && inlinePolicy.length > 0 ? inlinePolicy : null;
1797
2314
  }
2315
+ async function getPermissionsBoundaryForPermissionSet(props) {
2316
+ const response = await props.ssoAdminClient.send(
2317
+ new GetPermissionsBoundaryForPermissionSetCommand({
2318
+ InstanceArn: props.instanceArn,
2319
+ PermissionSetArn: props.permissionSetArn
2320
+ })
2321
+ );
2322
+ const boundary = response.PermissionsBoundary;
2323
+ if (boundary == null) {
2324
+ return null;
2325
+ }
2326
+ if (boundary.ManagedPolicyArn != null) {
2327
+ return { managedPolicyArn: boundary.ManagedPolicyArn };
2328
+ }
2329
+ const ref = boundary.CustomerManagedPolicyReference;
2330
+ if (ref?.Name != null) {
2331
+ return {
2332
+ customerManagedPolicyName: ref.Name,
2333
+ customerManagedPolicyPath: ref.Path ?? "/"
2334
+ };
2335
+ }
2336
+ return null;
2337
+ }
1798
2338
  async function listManagedPoliciesInPermissionSet(props) {
1799
2339
  const managedPolicies = [];
1800
2340
  let nextToken;
@@ -1892,18 +2432,61 @@ async function listAccountsForPermissionSet(props) {
1892
2432
  } while (nextToken != null);
1893
2433
  return accountIds;
1894
2434
  }
2435
+ var ALTERNATE_CONTACT_TYPES = ["BILLING", "OPERATIONS", "SECURITY"];
2436
+ async function scanAlternateContacts(props) {
2437
+ const results = await Promise.all(
2438
+ ALTERNATE_CONTACT_TYPES.map(async (contactType) => {
2439
+ try {
2440
+ const response = await props.accountClient.send(
2441
+ new GetAlternateContactCommand({
2442
+ AccountId: props.isManagementAccount ? void 0 : props.accountId,
2443
+ AlternateContactType: contactType
2444
+ })
2445
+ );
2446
+ const c = response.AlternateContact;
2447
+ if (c == null || c.EmailAddress == null || c.Name == null) {
2448
+ return null;
2449
+ }
2450
+ return {
2451
+ contactType,
2452
+ name: c.Name,
2453
+ email: c.EmailAddress,
2454
+ phone: c.PhoneNumber ?? "",
2455
+ ...c.Title != null ? { title: c.Title } : {}
2456
+ };
2457
+ } catch (error) {
2458
+ if (error != null && typeof error === "object" && "name" in error && error.name === "ResourceNotFoundException") {
2459
+ return null;
2460
+ }
2461
+ throw error;
2462
+ }
2463
+ })
2464
+ );
2465
+ return results.filter((c) => c != null);
2466
+ }
1895
2467
 
1896
2468
  // src/applyLogic.ts
1897
- import { PutAccountNameCommand } from "@aws-sdk/client-account";
1898
2469
  import {
2470
+ DeleteAlternateContactCommand,
2471
+ PutAccountNameCommand,
2472
+ PutAlternateContactCommand
2473
+ } from "@aws-sdk/client-account";
2474
+ import {
2475
+ AttachPolicyCommand,
1899
2476
  CreateOrganizationalUnitCommand,
2477
+ CreatePolicyCommand,
2478
+ DeregisterDelegatedAdministratorCommand,
1900
2479
  DeleteOrganizationalUnitCommand,
2480
+ DeletePolicyCommand,
2481
+ DetachPolicyCommand,
1901
2482
  ListAccountsForParentCommand,
1902
2483
  ListOrganizationalUnitsForParentCommand as ListOrganizationalUnitsForParentCommand2,
1903
2484
  MoveAccountCommand as MoveAccountCommand2,
2485
+ RegisterDelegatedAdministratorCommand,
1904
2486
  TagResourceCommand,
1905
2487
  UntagResourceCommand,
1906
- UpdateOrganizationalUnitCommand
2488
+ UpdateOrganizationalUnitCommand,
2489
+ UpdatePolicyCommand
1907
2490
  } from "@aws-sdk/client-organizations";
1908
2491
  import {
1909
2492
  CreateGroupMembershipCommand,
@@ -1923,6 +2506,7 @@ import {
1923
2506
  CreatePermissionSetCommand,
1924
2507
  DeleteAccountAssignmentCommand,
1925
2508
  DeleteInlinePolicyFromPermissionSetCommand,
2509
+ DeletePermissionsBoundaryFromPermissionSetCommand,
1926
2510
  DeletePermissionSetCommand,
1927
2511
  DescribeAccountAssignmentCreationStatusCommand,
1928
2512
  DescribeAccountAssignmentDeletionStatusCommand,
@@ -1931,6 +2515,8 @@ import {
1931
2515
  DetachManagedPolicyFromPermissionSetCommand,
1932
2516
  ProvisionPermissionSetCommand,
1933
2517
  PutInlinePolicyToPermissionSetCommand,
2518
+ PutPermissionsBoundaryToPermissionSetCommand,
2519
+ UpdateInstanceAccessControlAttributeConfigurationCommand,
1934
2520
  UpdatePermissionSetCommand
1935
2521
  } from "@aws-sdk/client-sso-admin";
1936
2522
 
@@ -2069,39 +2655,38 @@ function isCompleteAccountWithStatus(account, expectedAccountId) {
2069
2655
 
2070
2656
  // src/applyLogic.ts
2071
2657
  async function executeOperation(props) {
2072
- const operation = props.operation;
2073
- if (operation.kind === "moveAccount") {
2658
+ if (props.operation.kind === "moveAccount") {
2074
2659
  props.logger.log(
2075
- `Moving "${operation.accountName}" (${operation.accountId}): ${operation.fromOuName} -> ${operation.toOuName}`
2660
+ `Moving "${props.operation.accountName}" (${props.operation.accountId}): ${props.operation.fromOuName} -> ${props.operation.toOuName}`
2076
2661
  );
2077
2662
  await props.organizationsClient.send(
2078
2663
  new MoveAccountCommand2({
2079
- AccountId: operation.accountId,
2080
- SourceParentId: operation.fromOuId,
2081
- DestinationParentId: operation.toOuId
2664
+ AccountId: props.operation.accountId,
2665
+ SourceParentId: props.operation.fromOuId,
2666
+ DestinationParentId: props.operation.toOuId
2082
2667
  })
2083
2668
  );
2084
- props.logger.log(`Done: "${operation.accountName}"`);
2669
+ props.logger.log(`Done: "${props.operation.accountName}"`);
2085
2670
  return moveAccountInWorkingState({
2086
2671
  workingState: props.state,
2087
- accountId: operation.accountId,
2088
- parentId: operation.toOuId
2672
+ accountId: props.operation.accountId,
2673
+ parentId: props.operation.toOuId
2089
2674
  });
2090
2675
  }
2091
- if (operation.kind === "createOu") {
2676
+ if (props.operation.kind === "createOu") {
2092
2677
  props.logger.log(
2093
- `Creating OU "${operation.ouName}" under ${operation.parentOuName}...`
2678
+ `Creating OU "${props.operation.ouName}" under ${props.operation.parentOuName}...`
2094
2679
  );
2095
2680
  const response = await props.organizationsClient.send(
2096
2681
  new CreateOrganizationalUnitCommand({
2097
- ParentId: operation.parentOuId,
2098
- Name: operation.ouName
2682
+ ParentId: props.operation.parentOuId,
2683
+ Name: props.operation.ouName
2099
2684
  })
2100
2685
  );
2101
2686
  const createdOu = response.OrganizationalUnit;
2102
2687
  if (createdOu?.Id == null || createdOu.Arn == null || createdOu.Name == null) {
2103
2688
  throw new Error(
2104
- `CreateOrganizationalUnit for "${operation.ouName}" returned incomplete OU data.`
2689
+ `CreateOrganizationalUnit for "${props.operation.ouName}" returned incomplete OU data.`
2105
2690
  );
2106
2691
  }
2107
2692
  props.logger.log(`Done: "${createdOu.Name}"`);
@@ -2109,55 +2694,55 @@ async function executeOperation(props) {
2109
2694
  workingState: props.state,
2110
2695
  organizationalUnit: {
2111
2696
  id: createdOu.Id,
2112
- parentId: operation.parentOuId,
2697
+ parentId: props.operation.parentOuId,
2113
2698
  arn: createdOu.Arn,
2114
2699
  name: createdOu.Name
2115
2700
  }
2116
2701
  });
2117
2702
  }
2118
- if (operation.kind === "renameOu") {
2703
+ if (props.operation.kind === "renameOu") {
2119
2704
  props.logger.log(
2120
- `Renaming OU "${operation.fromOuName}" -> "${operation.toOuName}"...`
2705
+ `Renaming OU "${props.operation.fromOuName}" -> "${props.operation.toOuName}"...`
2121
2706
  );
2122
2707
  await props.organizationsClient.send(
2123
2708
  new UpdateOrganizationalUnitCommand({
2124
- OrganizationalUnitId: operation.ouId,
2125
- Name: operation.toOuName
2709
+ OrganizationalUnitId: props.operation.ouId,
2710
+ Name: props.operation.toOuName
2126
2711
  })
2127
2712
  );
2128
- props.logger.log(`Done: "${operation.toOuName}"`);
2713
+ props.logger.log(`Done: "${props.operation.toOuName}"`);
2129
2714
  return renameOrganizationalUnitInWorkingState({
2130
2715
  workingState: props.state,
2131
- organizationalUnitId: operation.ouId,
2132
- name: operation.toOuName
2716
+ organizationalUnitId: props.operation.ouId,
2717
+ name: props.operation.toOuName
2133
2718
  });
2134
2719
  }
2135
- if (operation.kind === "deleteOu") {
2136
- props.logger.log(`Deleting OU "${operation.ouName}"...`);
2720
+ if (props.operation.kind === "deleteOu") {
2721
+ props.logger.log(`Deleting OU "${props.operation.ouName}"...`);
2137
2722
  await assertOrganizationalUnitIsEmpty({
2138
2723
  organizationsClient: props.organizationsClient,
2139
- organizationalUnitId: operation.ouId,
2140
- organizationalUnitName: operation.ouName
2724
+ organizationalUnitId: props.operation.ouId,
2725
+ organizationalUnitName: props.operation.ouName
2141
2726
  });
2142
2727
  await props.organizationsClient.send(
2143
2728
  new DeleteOrganizationalUnitCommand({
2144
- OrganizationalUnitId: operation.ouId
2729
+ OrganizationalUnitId: props.operation.ouId
2145
2730
  })
2146
2731
  );
2147
- props.logger.log(`Done: "${operation.ouName}"`);
2732
+ props.logger.log(`Done: "${props.operation.ouName}"`);
2148
2733
  return removeOrganizationalUnitFromWorkingState({
2149
2734
  workingState: props.state,
2150
- organizationalUnitId: operation.ouId
2735
+ organizationalUnitId: props.operation.ouId
2151
2736
  });
2152
2737
  }
2153
- if (operation.kind === "createAccount") {
2738
+ if (props.operation.kind === "createAccount") {
2154
2739
  const result = await createAccountAndMoveToOu({
2155
2740
  organizationsClient: props.organizationsClient,
2156
2741
  logger: props.logger,
2157
- accountName: operation.accountName,
2158
- accountEmail: operation.accountEmail,
2742
+ accountName: props.operation.accountName,
2743
+ accountEmail: props.operation.accountEmail,
2159
2744
  sourceParentId: props.context.organization.rootId,
2160
- destinationParentId: operation.targetOuId,
2745
+ destinationParentId: props.operation.targetOuId,
2161
2746
  timeoutInMs: props.runtime.createAccount.timeoutInMs,
2162
2747
  pollIntervalInMs: props.runtime.createAccount.pollIntervalInMs
2163
2748
  });
@@ -2169,33 +2754,33 @@ async function executeOperation(props) {
2169
2754
  name: result.account.name,
2170
2755
  email: result.account.email,
2171
2756
  status: result.account.status,
2172
- parentId: operation.targetOuId,
2757
+ parentId: props.operation.targetOuId,
2173
2758
  tags: []
2174
2759
  }
2175
2760
  });
2176
2761
  }
2177
- if (operation.kind === "updateAccountTags") {
2178
- const account = props.state.organization.accountsById[operation.accountId];
2762
+ if (props.operation.kind === "updateAccountTags") {
2763
+ const account = props.state.organization.accountsById[props.operation.accountId];
2179
2764
  if (account == null) {
2180
2765
  throw new Error(
2181
- `Could not resolve account "${operation.accountName}" (${operation.accountId}) in working state.`
2766
+ `Could not resolve account "${props.operation.accountName}" (${props.operation.accountId}) in working state.`
2182
2767
  );
2183
2768
  }
2184
2769
  const currentTags = new Map(
2185
2770
  (account.tags ?? []).map((tag) => [tag.key, tag.value])
2186
2771
  );
2187
- const desiredTags = new Map(Object.entries(operation.tags));
2772
+ const desiredTags = new Map(Object.entries(props.operation.tags));
2188
2773
  const tagsToApply = [...desiredTags.entries()].filter(([key, value]) => currentTags.get(key) !== value).map(([Key, Value]) => ({ Key, Value }));
2189
2774
  const tagKeysToRemove = [...currentTags.keys()].filter(
2190
2775
  (key) => desiredTags.has(key) === false
2191
2776
  );
2192
2777
  props.logger.log(
2193
- `Updating account tags "${operation.accountName}" (${operation.accountId})...`
2778
+ `Updating account tags "${props.operation.accountName}" (${props.operation.accountId})...`
2194
2779
  );
2195
2780
  if (tagsToApply.length > 0) {
2196
2781
  await props.organizationsClient.send(
2197
2782
  new TagResourceCommand({
2198
- ResourceId: operation.accountId,
2783
+ ResourceId: props.operation.accountId,
2199
2784
  Tags: tagsToApply
2200
2785
  })
2201
2786
  );
@@ -2203,84 +2788,84 @@ async function executeOperation(props) {
2203
2788
  if (tagKeysToRemove.length > 0) {
2204
2789
  await props.organizationsClient.send(
2205
2790
  new UntagResourceCommand({
2206
- ResourceId: operation.accountId,
2791
+ ResourceId: props.operation.accountId,
2207
2792
  TagKeys: tagKeysToRemove
2208
2793
  })
2209
2794
  );
2210
2795
  }
2211
- props.logger.log(`Done: tags updated for "${operation.accountName}"`);
2796
+ props.logger.log(`Done: tags updated for "${props.operation.accountName}"`);
2212
2797
  return upsertAccountInWorkingState({
2213
2798
  workingState: props.state,
2214
2799
  account: {
2215
2800
  ...account,
2216
- tags: Object.entries(operation.tags).map(([key, value]) => ({
2801
+ tags: Object.entries(props.operation.tags).map(([key, value]) => ({
2217
2802
  key,
2218
2803
  value
2219
2804
  }))
2220
2805
  }
2221
2806
  });
2222
2807
  }
2223
- if (operation.kind === "updateAccountName") {
2808
+ if (props.operation.kind === "updateAccountName") {
2224
2809
  props.logger.log(
2225
- `Renaming account (${operation.accountId}): "${operation.fromAccountName}" -> "${operation.toAccountName}"...`
2810
+ `Renaming account (${props.operation.accountId}): "${props.operation.fromAccountName}" -> "${props.operation.toAccountName}"...`
2226
2811
  );
2227
2812
  await props.accountClient.send(
2228
2813
  new PutAccountNameCommand({
2229
- AccountId: operation.accountId,
2230
- AccountName: operation.toAccountName
2814
+ AccountId: props.operation.accountId,
2815
+ AccountName: props.operation.toAccountName
2231
2816
  })
2232
2817
  );
2233
2818
  props.logger.log(
2234
- `Done: account "${operation.toAccountName}" (${operation.accountId})`
2819
+ `Done: account "${props.operation.toAccountName}" (${props.operation.accountId})`
2235
2820
  );
2236
- const account = props.state.organization.accountsById[operation.accountId];
2821
+ const account = props.state.organization.accountsById[props.operation.accountId];
2237
2822
  if (account == null) {
2238
2823
  throw new Error(
2239
- `Could not resolve account (${operation.accountId}) in working state after rename.`
2824
+ `Could not resolve account (${props.operation.accountId}) in working state after rename.`
2240
2825
  );
2241
2826
  }
2242
2827
  return upsertAccountInWorkingState({
2243
2828
  workingState: props.state,
2244
2829
  account: {
2245
2830
  ...account,
2246
- name: operation.toAccountName
2831
+ name: props.operation.toAccountName
2247
2832
  }
2248
2833
  });
2249
2834
  }
2250
- if (operation.kind === "removeAccount") {
2835
+ if (props.operation.kind === "removeAccount") {
2251
2836
  props.logger.log(
2252
- `Moving removed account "${operation.accountName}" (${operation.accountId}) to ${operation.toOuName}...`
2837
+ `Moving removed account "${props.operation.accountName}" (${props.operation.accountId}) to ${props.operation.toOuName}...`
2253
2838
  );
2254
2839
  await props.organizationsClient.send(
2255
2840
  new MoveAccountCommand2({
2256
- AccountId: operation.accountId,
2257
- SourceParentId: operation.fromOuId,
2258
- DestinationParentId: operation.toOuId
2841
+ AccountId: props.operation.accountId,
2842
+ SourceParentId: props.operation.fromOuId,
2843
+ DestinationParentId: props.operation.toOuId
2259
2844
  })
2260
2845
  );
2261
2846
  props.logger.log(
2262
- `Done: "${operation.accountName}" -> ${operation.toOuName}`
2847
+ `Done: "${props.operation.accountName}" -> ${props.operation.toOuName}`
2263
2848
  );
2264
2849
  return moveAccountInWorkingState({
2265
2850
  workingState: props.state,
2266
- accountId: operation.accountId,
2267
- parentId: operation.toOuId
2851
+ accountId: props.operation.accountId,
2852
+ parentId: props.operation.toOuId
2268
2853
  });
2269
2854
  }
2270
- if (operation.kind === "createIdcUser") {
2271
- props.logger.log(`Creating IdC user "${operation.userName}"...`);
2855
+ if (props.operation.kind === "createIdcUser") {
2856
+ props.logger.log(`Creating IdC user "${props.operation.userName}"...`);
2272
2857
  const response = await props.identityStoreClient.send(
2273
2858
  new CreateUserCommand({
2274
2859
  IdentityStoreId: props.state.identityCenter.identityStoreId,
2275
- UserName: operation.userName,
2276
- DisplayName: operation.displayName,
2860
+ UserName: props.operation.userName,
2861
+ DisplayName: props.operation.displayName,
2277
2862
  Name: buildIdentityStoreUserName({
2278
- userName: operation.userName,
2279
- displayName: operation.displayName
2863
+ userName: props.operation.userName,
2864
+ displayName: props.operation.displayName
2280
2865
  }),
2281
- Emails: operation.email.length > 0 ? [
2866
+ Emails: props.operation.email.length > 0 ? [
2282
2867
  {
2283
- Value: operation.email,
2868
+ Value: props.operation.email,
2284
2869
  Type: "Work",
2285
2870
  Primary: true
2286
2871
  }
@@ -2289,45 +2874,45 @@ async function executeOperation(props) {
2289
2874
  );
2290
2875
  if (response.UserId == null) {
2291
2876
  throw new Error(
2292
- `CreateUser for "${operation.userName}" returned no user id.`
2877
+ `CreateUser for "${props.operation.userName}" returned no user id.`
2293
2878
  );
2294
2879
  }
2295
- props.logger.log(`Done: "${operation.userName}"`);
2880
+ props.logger.log(`Done: "${props.operation.userName}"`);
2296
2881
  return upsertIdcUserInWorkingState({
2297
2882
  workingState: props.state,
2298
2883
  user: {
2299
2884
  userId: response.UserId,
2300
- userName: operation.userName,
2301
- displayName: operation.displayName,
2302
- email: operation.email
2885
+ userName: props.operation.userName,
2886
+ displayName: props.operation.displayName,
2887
+ email: props.operation.email
2303
2888
  }
2304
2889
  });
2305
2890
  }
2306
- if (operation.kind === "updateIdcUser") {
2891
+ if (props.operation.kind === "updateIdcUser") {
2307
2892
  const user = resolveUserByName({
2308
2893
  state: props.state,
2309
- userName: operation.userName
2894
+ userName: props.operation.userName
2310
2895
  });
2311
2896
  const operations = [];
2312
- if (user.displayName !== operation.displayName) {
2897
+ if (user.displayName !== props.operation.displayName) {
2313
2898
  operations.push({
2314
2899
  AttributePath: "displayName",
2315
- AttributeValue: operation.displayName
2900
+ AttributeValue: props.operation.displayName
2316
2901
  });
2317
2902
  operations.push({
2318
2903
  AttributePath: "name",
2319
2904
  AttributeValue: buildIdentityStoreUserName({
2320
- userName: operation.userName,
2321
- displayName: operation.displayName
2905
+ userName: props.operation.userName,
2906
+ displayName: props.operation.displayName
2322
2907
  })
2323
2908
  });
2324
2909
  }
2325
- if (user.email !== operation.email && operation.email.length > 0) {
2910
+ if (user.email !== props.operation.email && props.operation.email.length > 0) {
2326
2911
  operations.push({
2327
2912
  AttributePath: "emails",
2328
2913
  AttributeValue: [
2329
2914
  {
2330
- Value: operation.email,
2915
+ Value: props.operation.email,
2331
2916
  Type: "Work",
2332
2917
  Primary: true
2333
2918
  }
@@ -2337,7 +2922,7 @@ async function executeOperation(props) {
2337
2922
  if (operations.length === 0) {
2338
2923
  return props.state;
2339
2924
  }
2340
- props.logger.log(`Updating IdC user "${operation.userName}"...`);
2925
+ props.logger.log(`Updating IdC user "${props.operation.userName}"...`);
2341
2926
  await props.identityStoreClient.send(
2342
2927
  new UpdateUserCommand({
2343
2928
  IdentityStoreId: props.state.identityCenter.identityStoreId,
@@ -2345,65 +2930,65 @@ async function executeOperation(props) {
2345
2930
  Operations: operations
2346
2931
  })
2347
2932
  );
2348
- props.logger.log(`Done: "${operation.userName}"`);
2933
+ props.logger.log(`Done: "${props.operation.userName}"`);
2349
2934
  return upsertIdcUserInWorkingState({
2350
2935
  workingState: props.state,
2351
2936
  user: {
2352
2937
  ...user,
2353
- displayName: operation.displayName,
2354
- email: operation.email.length > 0 ? operation.email : user.email
2938
+ displayName: props.operation.displayName,
2939
+ email: props.operation.email.length > 0 ? props.operation.email : user.email
2355
2940
  }
2356
2941
  });
2357
2942
  }
2358
- if (operation.kind === "deleteIdcUser") {
2943
+ if (props.operation.kind === "deleteIdcUser") {
2359
2944
  const user = resolveUserByName({
2360
2945
  state: props.state,
2361
- userName: operation.userName
2946
+ userName: props.operation.userName
2362
2947
  });
2363
- props.logger.log(`Deleting IdC user "${operation.userName}"...`);
2948
+ props.logger.log(`Deleting IdC user "${props.operation.userName}"...`);
2364
2949
  await props.identityStoreClient.send(
2365
2950
  new DeleteUserCommand({
2366
2951
  IdentityStoreId: props.state.identityCenter.identityStoreId,
2367
2952
  UserId: user.userId
2368
2953
  })
2369
2954
  );
2370
- props.logger.log(`Done: "${operation.userName}"`);
2955
+ props.logger.log(`Done: "${props.operation.userName}"`);
2371
2956
  return removeIdcUserFromWorkingState({
2372
2957
  workingState: props.state,
2373
- userName: operation.userName
2958
+ userName: props.operation.userName
2374
2959
  });
2375
2960
  }
2376
- if (operation.kind === "createIdcGroup") {
2377
- props.logger.log(`Creating IdC group "${operation.groupDisplayName}"...`);
2961
+ if (props.operation.kind === "createIdcGroup") {
2962
+ props.logger.log(`Creating IdC group "${props.operation.groupDisplayName}"...`);
2378
2963
  const response = await props.identityStoreClient.send(
2379
2964
  new CreateGroupCommand({
2380
2965
  IdentityStoreId: props.state.identityCenter.identityStoreId,
2381
- DisplayName: operation.groupDisplayName,
2382
- Description: operation.description.trim().length > 0 ? operation.description : void 0
2966
+ DisplayName: props.operation.groupDisplayName,
2967
+ Description: props.operation.description.trim().length > 0 ? props.operation.description : void 0
2383
2968
  })
2384
2969
  );
2385
2970
  if (response.GroupId == null) {
2386
2971
  throw new Error(
2387
- `CreateGroup for "${operation.groupDisplayName}" returned no group id.`
2972
+ `CreateGroup for "${props.operation.groupDisplayName}" returned no group id.`
2388
2973
  );
2389
2974
  }
2390
- props.logger.log(`Done: "${operation.groupDisplayName}"`);
2975
+ props.logger.log(`Done: "${props.operation.groupDisplayName}"`);
2391
2976
  return upsertIdcGroupInWorkingState({
2392
2977
  workingState: props.state,
2393
2978
  group: {
2394
2979
  groupId: response.GroupId,
2395
- displayName: operation.groupDisplayName,
2396
- description: operation.description
2980
+ displayName: props.operation.groupDisplayName,
2981
+ description: props.operation.description
2397
2982
  }
2398
2983
  });
2399
2984
  }
2400
- if (operation.kind === "updateIdcGroupDescription") {
2985
+ if (props.operation.kind === "updateIdcGroupDescription") {
2401
2986
  const group = resolveGroupByDisplayName({
2402
2987
  state: props.state,
2403
- groupDisplayName: operation.groupDisplayName
2988
+ groupDisplayName: props.operation.groupDisplayName
2404
2989
  });
2405
2990
  props.logger.log(
2406
- `Updating IdC group description for "${operation.groupDisplayName}"...`
2991
+ `Updating IdC group description for "${props.operation.groupDisplayName}"...`
2407
2992
  );
2408
2993
  await props.identityStoreClient.send(
2409
2994
  new UpdateGroupCommand({
@@ -2412,46 +2997,46 @@ async function executeOperation(props) {
2412
2997
  Operations: [
2413
2998
  {
2414
2999
  AttributePath: "description",
2415
- AttributeValue: operation.description
3000
+ AttributeValue: props.operation.description
2416
3001
  }
2417
3002
  ]
2418
3003
  })
2419
3004
  );
2420
- props.logger.log(`Done: group "${operation.groupDisplayName}"`);
3005
+ props.logger.log(`Done: group "${props.operation.groupDisplayName}"`);
2421
3006
  return upsertIdcGroupInWorkingState({
2422
3007
  workingState: props.state,
2423
3008
  group: {
2424
3009
  ...group,
2425
- description: operation.description
3010
+ description: props.operation.description
2426
3011
  }
2427
3012
  });
2428
3013
  }
2429
- if (operation.kind === "deleteIdcGroup") {
3014
+ if (props.operation.kind === "deleteIdcGroup") {
2430
3015
  const group = resolveGroupByDisplayName({
2431
3016
  state: props.state,
2432
- groupDisplayName: operation.groupDisplayName
3017
+ groupDisplayName: props.operation.groupDisplayName
2433
3018
  });
2434
- props.logger.log(`Deleting IdC group "${operation.groupDisplayName}"...`);
3019
+ props.logger.log(`Deleting IdC group "${props.operation.groupDisplayName}"...`);
2435
3020
  await props.identityStoreClient.send(
2436
3021
  new DeleteGroupCommand({
2437
3022
  IdentityStoreId: props.state.identityCenter.identityStoreId,
2438
3023
  GroupId: group.groupId
2439
3024
  })
2440
3025
  );
2441
- props.logger.log(`Done: "${operation.groupDisplayName}"`);
3026
+ props.logger.log(`Done: "${props.operation.groupDisplayName}"`);
2442
3027
  return removeIdcGroupFromWorkingState({
2443
3028
  workingState: props.state,
2444
- groupDisplayName: operation.groupDisplayName
3029
+ groupDisplayName: props.operation.groupDisplayName
2445
3030
  });
2446
3031
  }
2447
- if (operation.kind === "addIdcGroupMembership") {
3032
+ if (props.operation.kind === "addIdcGroupMembership") {
2448
3033
  const resolvedMembership = resolveGroupMembershipDependencies({
2449
3034
  state: props.state,
2450
- groupDisplayName: operation.groupDisplayName,
2451
- userName: operation.userName
3035
+ groupDisplayName: props.operation.groupDisplayName,
3036
+ userName: props.operation.userName
2452
3037
  });
2453
3038
  props.logger.log(
2454
- `Adding user "${operation.userName}" to IdC group "${operation.groupDisplayName}"...`
3039
+ `Adding user "${props.operation.userName}" to IdC group "${props.operation.groupDisplayName}"...`
2455
3040
  );
2456
3041
  const response = await props.identityStoreClient.send(
2457
3042
  new CreateGroupMembershipCommand({
@@ -2464,11 +3049,11 @@ async function executeOperation(props) {
2464
3049
  );
2465
3050
  if (response.MembershipId == null) {
2466
3051
  throw new Error(
2467
- `CreateGroupMembership for group "${operation.groupDisplayName}" and user "${operation.userName}" returned no membership id.`
3052
+ `CreateGroupMembership for group "${props.operation.groupDisplayName}" and user "${props.operation.userName}" returned no membership id.`
2468
3053
  );
2469
3054
  }
2470
3055
  props.logger.log(
2471
- `Done: user "${operation.userName}" -> group "${operation.groupDisplayName}"`
3056
+ `Done: user "${props.operation.userName}" -> group "${props.operation.groupDisplayName}"`
2472
3057
  );
2473
3058
  return addGroupMembershipToWorkingState({
2474
3059
  workingState: props.state,
@@ -2479,93 +3064,94 @@ async function executeOperation(props) {
2479
3064
  }
2480
3065
  });
2481
3066
  }
2482
- if (operation.kind === "createIdcPermissionSet") {
3067
+ if (props.operation.kind === "createIdcPermissionSet") {
2483
3068
  props.logger.log(
2484
- `Creating IdC permission set "${operation.permissionSetName}"...`
3069
+ `Creating IdC permission set "${props.operation.permissionSetName}"...`
2485
3070
  );
2486
3071
  const response = await props.ssoAdminClient.send(
2487
3072
  new CreatePermissionSetCommand({
2488
3073
  InstanceArn: props.state.identityCenter.instanceArn,
2489
- Name: operation.permissionSetName,
2490
- Description: operation.description.length > 0 ? operation.description : void 0,
2491
- SessionDuration: operation.sessionDuration ?? void 0
3074
+ Name: props.operation.permissionSetName,
3075
+ Description: props.operation.description.length > 0 ? props.operation.description : void 0,
3076
+ SessionDuration: props.operation.sessionDuration ?? void 0
2492
3077
  })
2493
3078
  );
2494
3079
  const permissionSetArn = response.PermissionSet?.PermissionSetArn;
2495
3080
  if (permissionSetArn == null) {
2496
3081
  throw new Error(
2497
- `CreatePermissionSet for "${operation.permissionSetName}" returned no permission set arn.`
3082
+ `CreatePermissionSet for "${props.operation.permissionSetName}" returned no permission set arn.`
2498
3083
  );
2499
3084
  }
2500
- props.logger.log(`Done: "${operation.permissionSetName}"`);
3085
+ props.logger.log(`Done: "${props.operation.permissionSetName}"`);
2501
3086
  return upsertIdcPermissionSetInWorkingState({
2502
3087
  workingState: props.state,
2503
3088
  permissionSet: {
2504
3089
  permissionSetArn,
2505
- name: operation.permissionSetName,
2506
- description: operation.description,
2507
- sessionDuration: operation.sessionDuration,
3090
+ name: props.operation.permissionSetName,
3091
+ description: props.operation.description,
3092
+ sessionDuration: props.operation.sessionDuration,
2508
3093
  inlinePolicy: null,
2509
3094
  awsManagedPolicies: [],
2510
- customerManagedPolicies: []
3095
+ customerManagedPolicies: [],
3096
+ permissionsBoundary: null
2511
3097
  }
2512
3098
  });
2513
3099
  }
2514
- if (operation.kind === "updateIdcPermissionSetDescription") {
3100
+ if (props.operation.kind === "updateIdcPermissionSetDescription") {
2515
3101
  const permissionSet = resolvePermissionSetByName({
2516
3102
  state: props.state,
2517
- permissionSetName: operation.permissionSetName
3103
+ permissionSetName: props.operation.permissionSetName
2518
3104
  });
2519
3105
  props.logger.log(
2520
- `Updating IdC permission set description for "${operation.permissionSetName}"...`
3106
+ `Updating IdC permission set description for "${props.operation.permissionSetName}"...`
2521
3107
  );
2522
3108
  await props.ssoAdminClient.send(
2523
3109
  new UpdatePermissionSetCommand({
2524
3110
  InstanceArn: props.state.identityCenter.instanceArn,
2525
3111
  PermissionSetArn: permissionSet.permissionSetArn,
2526
- Description: operation.description.trim().length > 0 ? operation.description : void 0
3112
+ Description: props.operation.description.trim().length > 0 ? props.operation.description : void 0
2527
3113
  })
2528
3114
  );
2529
- props.logger.log(`Done: "${operation.permissionSetName}"`);
3115
+ props.logger.log(`Done: "${props.operation.permissionSetName}"`);
2530
3116
  return upsertIdcPermissionSetInWorkingState({
2531
3117
  workingState: props.state,
2532
3118
  permissionSet: {
2533
3119
  ...permissionSet,
2534
- description: operation.description
3120
+ description: props.operation.description
2535
3121
  }
2536
3122
  });
2537
3123
  }
2538
- if (operation.kind === "updateIdcPermissionSetSessionDuration") {
3124
+ if (props.operation.kind === "updateIdcPermissionSetSessionDuration") {
2539
3125
  const permissionSet = resolvePermissionSetByName({
2540
3126
  state: props.state,
2541
- permissionSetName: operation.permissionSetName
3127
+ permissionSetName: props.operation.permissionSetName
2542
3128
  });
2543
3129
  props.logger.log(
2544
- `Updating IdC permission set session duration for "${operation.permissionSetName}"...`
3130
+ `Updating IdC permission set session duration for "${props.operation.permissionSetName}"...`
2545
3131
  );
2546
3132
  await props.ssoAdminClient.send(
2547
3133
  new UpdatePermissionSetCommand({
2548
3134
  InstanceArn: props.state.identityCenter.instanceArn,
2549
3135
  PermissionSetArn: permissionSet.permissionSetArn,
2550
- SessionDuration: operation.sessionDuration ?? void 0
3136
+ SessionDuration: props.operation.sessionDuration ?? void 0
2551
3137
  })
2552
3138
  );
2553
- props.logger.log(`Done: "${operation.permissionSetName}"`);
3139
+ props.logger.log(`Done: "${props.operation.permissionSetName}"`);
2554
3140
  return upsertIdcPermissionSetInWorkingState({
2555
3141
  workingState: props.state,
2556
3142
  permissionSet: {
2557
3143
  ...permissionSet,
2558
- sessionDuration: operation.sessionDuration
3144
+ sessionDuration: props.operation.sessionDuration
2559
3145
  }
2560
3146
  });
2561
3147
  }
2562
- if (operation.kind === "deleteIdcPermissionSet") {
3148
+ if (props.operation.kind === "deleteIdcPermissionSet") {
2563
3149
  const permissionSet = resolvePermissionSetByName({
2564
3150
  state: props.state,
2565
- permissionSetName: operation.permissionSetName
3151
+ permissionSetName: props.operation.permissionSetName
2566
3152
  });
2567
3153
  props.logger.log(
2568
- `Deleting IdC permission set "${operation.permissionSetName}"...`
3154
+ `Deleting IdC permission set "${props.operation.permissionSetName}"...`
2569
3155
  );
2570
3156
  await props.ssoAdminClient.send(
2571
3157
  new DeletePermissionSetCommand({
@@ -2573,44 +3159,45 @@ async function executeOperation(props) {
2573
3159
  PermissionSetArn: permissionSet.permissionSetArn
2574
3160
  })
2575
3161
  );
2576
- props.logger.log(`Done: "${operation.permissionSetName}"`);
3162
+ props.logger.log(`Done: "${props.operation.permissionSetName}"`);
2577
3163
  return removeIdcPermissionSetFromWorkingState({
2578
3164
  workingState: props.state,
2579
- permissionSetName: operation.permissionSetName
3165
+ permissionSetName: props.operation.permissionSetName
2580
3166
  });
2581
3167
  }
2582
- if (operation.kind === "putIdcPermissionSetInlinePolicy") {
3168
+ if (props.operation.kind === "putIdcPermissionSetInlinePolicy") {
3169
+ const { inlinePolicy } = props.operation;
2583
3170
  const permissionSet = resolvePermissionSetByName({
2584
3171
  state: props.state,
2585
- permissionSetName: operation.permissionSetName
3172
+ permissionSetName: props.operation.permissionSetName
2586
3173
  });
2587
3174
  props.logger.log(
2588
- `Putting inline policy on IdC permission set "${operation.permissionSetName}"...`
3175
+ `Putting inline policy on IdC permission set "${props.operation.permissionSetName}"...`
2589
3176
  );
2590
3177
  await props.ssoAdminClient.send(
2591
3178
  new PutInlinePolicyToPermissionSetCommand({
2592
3179
  InstanceArn: props.state.identityCenter.instanceArn,
2593
3180
  PermissionSetArn: permissionSet.permissionSetArn,
2594
- InlinePolicy: operation.inlinePolicy
3181
+ InlinePolicy: inlinePolicy
2595
3182
  })
2596
3183
  );
2597
- props.logger.log(`Done: "${operation.permissionSetName}"`);
3184
+ props.logger.log(`Done: "${props.operation.permissionSetName}"`);
2598
3185
  return upsertPermissionSetPolicyState({
2599
3186
  state: props.state,
2600
- permissionSetName: operation.permissionSetName,
3187
+ permissionSetName: props.operation.permissionSetName,
2601
3188
  update: (currentPermissionSet) => ({
2602
3189
  ...currentPermissionSet,
2603
- inlinePolicy: operation.inlinePolicy
3190
+ inlinePolicy
2604
3191
  })
2605
3192
  });
2606
3193
  }
2607
- if (operation.kind === "deleteIdcPermissionSetInlinePolicy") {
3194
+ if (props.operation.kind === "deleteIdcPermissionSetInlinePolicy") {
2608
3195
  const permissionSet = resolvePermissionSetByName({
2609
3196
  state: props.state,
2610
- permissionSetName: operation.permissionSetName
3197
+ permissionSetName: props.operation.permissionSetName
2611
3198
  });
2612
3199
  props.logger.log(
2613
- `Deleting inline policy from IdC permission set "${operation.permissionSetName}"...`
3200
+ `Deleting inline policy from IdC permission set "${props.operation.permissionSetName}"...`
2614
3201
  );
2615
3202
  await props.ssoAdminClient.send(
2616
3203
  new DeleteInlinePolicyFromPermissionSetCommand({
@@ -2618,154 +3205,158 @@ async function executeOperation(props) {
2618
3205
  PermissionSetArn: permissionSet.permissionSetArn
2619
3206
  })
2620
3207
  );
2621
- props.logger.log(`Done: "${operation.permissionSetName}"`);
3208
+ props.logger.log(`Done: "${props.operation.permissionSetName}"`);
2622
3209
  return upsertPermissionSetPolicyState({
2623
3210
  state: props.state,
2624
- permissionSetName: operation.permissionSetName,
3211
+ permissionSetName: props.operation.permissionSetName,
2625
3212
  update: (currentPermissionSet) => ({
2626
3213
  ...currentPermissionSet,
2627
3214
  inlinePolicy: null
2628
3215
  })
2629
3216
  });
2630
3217
  }
2631
- if (operation.kind === "attachIdcManagedPolicyToPermissionSet") {
3218
+ if (props.operation.kind === "attachIdcManagedPolicyToPermissionSet") {
3219
+ const { managedPolicyArn } = props.operation;
2632
3220
  const permissionSet = resolvePermissionSetByName({
2633
3221
  state: props.state,
2634
- permissionSetName: operation.permissionSetName
3222
+ permissionSetName: props.operation.permissionSetName
2635
3223
  });
2636
3224
  props.logger.log(
2637
- `Attaching managed policy "${operation.managedPolicyArn}" to IdC permission set "${operation.permissionSetName}"...`
3225
+ `Attaching managed policy "${managedPolicyArn}" to IdC permission set "${props.operation.permissionSetName}"...`
2638
3226
  );
2639
3227
  await props.ssoAdminClient.send(
2640
3228
  new AttachManagedPolicyToPermissionSetCommand({
2641
3229
  InstanceArn: props.state.identityCenter.instanceArn,
2642
3230
  PermissionSetArn: permissionSet.permissionSetArn,
2643
- ManagedPolicyArn: operation.managedPolicyArn
3231
+ ManagedPolicyArn: managedPolicyArn
2644
3232
  })
2645
3233
  );
2646
- props.logger.log(`Done: "${operation.permissionSetName}"`);
3234
+ props.logger.log(`Done: "${props.operation.permissionSetName}"`);
2647
3235
  return upsertPermissionSetPolicyState({
2648
3236
  state: props.state,
2649
- permissionSetName: operation.permissionSetName,
3237
+ permissionSetName: props.operation.permissionSetName,
2650
3238
  update: (currentPermissionSet) => ({
2651
3239
  ...currentPermissionSet,
2652
3240
  awsManagedPolicies: [
2653
3241
  ...currentPermissionSet.awsManagedPolicies,
2654
- operation.managedPolicyArn
3242
+ managedPolicyArn
2655
3243
  ]
2656
3244
  })
2657
3245
  });
2658
3246
  }
2659
- if (operation.kind === "detachIdcManagedPolicyFromPermissionSet") {
3247
+ if (props.operation.kind === "detachIdcManagedPolicyFromPermissionSet") {
3248
+ const { managedPolicyArn } = props.operation;
2660
3249
  const permissionSet = resolvePermissionSetByName({
2661
3250
  state: props.state,
2662
- permissionSetName: operation.permissionSetName
3251
+ permissionSetName: props.operation.permissionSetName
2663
3252
  });
2664
3253
  props.logger.log(
2665
- `Detaching managed policy "${operation.managedPolicyArn}" from IdC permission set "${operation.permissionSetName}"...`
3254
+ `Detaching managed policy "${managedPolicyArn}" from IdC permission set "${props.operation.permissionSetName}"...`
2666
3255
  );
2667
3256
  await props.ssoAdminClient.send(
2668
3257
  new DetachManagedPolicyFromPermissionSetCommand({
2669
3258
  InstanceArn: props.state.identityCenter.instanceArn,
2670
3259
  PermissionSetArn: permissionSet.permissionSetArn,
2671
- ManagedPolicyArn: operation.managedPolicyArn
3260
+ ManagedPolicyArn: managedPolicyArn
2672
3261
  })
2673
3262
  );
2674
- props.logger.log(`Done: "${operation.permissionSetName}"`);
3263
+ props.logger.log(`Done: "${props.operation.permissionSetName}"`);
2675
3264
  return upsertPermissionSetPolicyState({
2676
3265
  state: props.state,
2677
- permissionSetName: operation.permissionSetName,
3266
+ permissionSetName: props.operation.permissionSetName,
2678
3267
  update: (currentPermissionSet) => ({
2679
3268
  ...currentPermissionSet,
2680
3269
  awsManagedPolicies: currentPermissionSet.awsManagedPolicies.filter(
2681
- (managedPolicyArn) => managedPolicyArn !== operation.managedPolicyArn
3270
+ (arn) => arn !== managedPolicyArn
2682
3271
  )
2683
3272
  })
2684
3273
  });
2685
3274
  }
2686
- if (operation.kind === "attachIdcCustomerManagedPolicyReferenceToPermissionSet") {
3275
+ if (props.operation.kind === "attachIdcCustomerManagedPolicyReferenceToPermissionSet") {
3276
+ const { customerManagedPolicyName, customerManagedPolicyPath } = props.operation;
2687
3277
  const permissionSet = resolvePermissionSetByName({
2688
3278
  state: props.state,
2689
- permissionSetName: operation.permissionSetName
3279
+ permissionSetName: props.operation.permissionSetName
2690
3280
  });
2691
3281
  props.logger.log(
2692
- `Attaching customer-managed policy "${operation.customerManagedPolicyPath}${operation.customerManagedPolicyName}" to IdC permission set "${operation.permissionSetName}"...`
3282
+ `Attaching customer-managed policy "${customerManagedPolicyPath}${customerManagedPolicyName}" to IdC permission set "${props.operation.permissionSetName}"...`
2693
3283
  );
2694
3284
  await props.ssoAdminClient.send(
2695
3285
  new AttachCustomerManagedPolicyReferenceToPermissionSetCommand({
2696
3286
  InstanceArn: props.state.identityCenter.instanceArn,
2697
3287
  PermissionSetArn: permissionSet.permissionSetArn,
2698
3288
  CustomerManagedPolicyReference: {
2699
- Name: operation.customerManagedPolicyName,
2700
- Path: operation.customerManagedPolicyPath
3289
+ Name: customerManagedPolicyName,
3290
+ Path: customerManagedPolicyPath
2701
3291
  }
2702
3292
  })
2703
3293
  );
2704
- props.logger.log(`Done: "${operation.permissionSetName}"`);
3294
+ props.logger.log(`Done: "${props.operation.permissionSetName}"`);
2705
3295
  return upsertPermissionSetPolicyState({
2706
3296
  state: props.state,
2707
- permissionSetName: operation.permissionSetName,
3297
+ permissionSetName: props.operation.permissionSetName,
2708
3298
  update: (currentPermissionSet) => ({
2709
3299
  ...currentPermissionSet,
2710
3300
  customerManagedPolicies: [
2711
3301
  ...currentPermissionSet.customerManagedPolicies,
2712
3302
  {
2713
- name: operation.customerManagedPolicyName,
2714
- path: operation.customerManagedPolicyPath
3303
+ name: customerManagedPolicyName,
3304
+ path: customerManagedPolicyPath
2715
3305
  }
2716
3306
  ]
2717
3307
  })
2718
3308
  });
2719
3309
  }
2720
- if (operation.kind === "detachIdcCustomerManagedPolicyReferenceFromPermissionSet") {
3310
+ if (props.operation.kind === "detachIdcCustomerManagedPolicyReferenceFromPermissionSet") {
3311
+ const { customerManagedPolicyName, customerManagedPolicyPath } = props.operation;
2721
3312
  const permissionSet = resolvePermissionSetByName({
2722
3313
  state: props.state,
2723
- permissionSetName: operation.permissionSetName
3314
+ permissionSetName: props.operation.permissionSetName
2724
3315
  });
2725
3316
  props.logger.log(
2726
- `Detaching customer-managed policy "${operation.customerManagedPolicyPath}${operation.customerManagedPolicyName}" from IdC permission set "${operation.permissionSetName}"...`
3317
+ `Detaching customer-managed policy "${customerManagedPolicyPath}${customerManagedPolicyName}" from IdC permission set "${props.operation.permissionSetName}"...`
2727
3318
  );
2728
3319
  await props.ssoAdminClient.send(
2729
3320
  new DetachCustomerManagedPolicyReferenceFromPermissionSetCommand({
2730
3321
  InstanceArn: props.state.identityCenter.instanceArn,
2731
3322
  PermissionSetArn: permissionSet.permissionSetArn,
2732
3323
  CustomerManagedPolicyReference: {
2733
- Name: operation.customerManagedPolicyName,
2734
- Path: operation.customerManagedPolicyPath
3324
+ Name: customerManagedPolicyName,
3325
+ Path: customerManagedPolicyPath
2735
3326
  }
2736
3327
  })
2737
3328
  );
2738
- props.logger.log(`Done: "${operation.permissionSetName}"`);
3329
+ props.logger.log(`Done: "${props.operation.permissionSetName}"`);
2739
3330
  return upsertPermissionSetPolicyState({
2740
3331
  state: props.state,
2741
- permissionSetName: operation.permissionSetName,
3332
+ permissionSetName: props.operation.permissionSetName,
2742
3333
  update: (currentPermissionSet) => ({
2743
3334
  ...currentPermissionSet,
2744
3335
  customerManagedPolicies: currentPermissionSet.customerManagedPolicies.filter(
2745
- (customerManagedPolicy) => customerManagedPolicy.name !== operation.customerManagedPolicyName || customerManagedPolicy.path !== operation.customerManagedPolicyPath
3336
+ (policy) => policy.name !== customerManagedPolicyName || policy.path !== customerManagedPolicyPath
2746
3337
  )
2747
3338
  })
2748
3339
  });
2749
3340
  }
2750
- if (operation.kind === "provisionIdcPermissionSet") {
3341
+ if (props.operation.kind === "provisionIdcPermissionSet") {
2751
3342
  const permissionSet = resolvePermissionSetByName({
2752
3343
  state: props.state,
2753
- permissionSetName: operation.permissionSetName
3344
+ permissionSetName: props.operation.permissionSetName
2754
3345
  });
2755
3346
  props.logger.log(
2756
- `Provisioning IdC permission set "${operation.permissionSetName}" to all provisioned accounts...`
3347
+ `Provisioning IdC permission set "${props.operation.permissionSetName}" to all provisioned accounts...`
2757
3348
  );
2758
3349
  const response = await props.ssoAdminClient.send(
2759
3350
  new ProvisionPermissionSetCommand({
2760
3351
  InstanceArn: props.state.identityCenter.instanceArn,
2761
3352
  PermissionSetArn: permissionSet.permissionSetArn,
2762
- TargetType: operation.targetScope
3353
+ TargetType: props.operation.targetScope
2763
3354
  })
2764
3355
  );
2765
3356
  const requestId = response.PermissionSetProvisioningStatus?.RequestId ?? void 0;
2766
3357
  if (requestId == null) {
2767
3358
  throw new Error(
2768
- `ProvisionPermissionSet for "${operation.permissionSetName}" returned no request id.`
3359
+ `ProvisionPermissionSet for "${props.operation.permissionSetName}" returned no request id.`
2769
3360
  );
2770
3361
  }
2771
3362
  await waitForPermissionSetProvisioningSuccess({
@@ -2775,16 +3366,63 @@ async function executeOperation(props) {
2775
3366
  requestId,
2776
3367
  timeoutInMs: props.runtime.permissionSetProvisioning.timeoutInMs,
2777
3368
  pollIntervalInMs: props.runtime.permissionSetProvisioning.pollIntervalInMs,
2778
- operationLabel: `"${operation.permissionSetName}"`
3369
+ operationLabel: `"${props.operation.permissionSetName}"`
2779
3370
  });
2780
- props.logger.log(`Done: "${operation.permissionSetName}"`);
3371
+ props.logger.log(`Done: "${props.operation.permissionSetName}"`);
2781
3372
  return props.state;
2782
3373
  }
2783
- if (operation.kind === "removeIdcGroupMembership") {
3374
+ if (props.operation.kind === "putIdcPermissionSetPermissionsBoundary") {
3375
+ const permissionSet = resolvePermissionSetByName({
3376
+ state: props.state,
3377
+ permissionSetName: props.operation.permissionSetName
3378
+ });
3379
+ props.logger.log(
3380
+ `Putting permissions boundary on IdC permission set "${props.operation.permissionSetName}"...`
3381
+ );
3382
+ const boundary = props.operation.permissionsBoundary;
3383
+ await props.ssoAdminClient.send(
3384
+ new PutPermissionsBoundaryToPermissionSetCommand({
3385
+ InstanceArn: props.state.identityCenter.instanceArn,
3386
+ PermissionSetArn: permissionSet.permissionSetArn,
3387
+ PermissionsBoundary: "managedPolicyArn" in boundary ? { ManagedPolicyArn: boundary.managedPolicyArn } : {
3388
+ CustomerManagedPolicyReference: {
3389
+ Name: boundary.customerManagedPolicyName,
3390
+ Path: boundary.customerManagedPolicyPath
3391
+ }
3392
+ }
3393
+ })
3394
+ );
3395
+ props.logger.log(`Done: "${props.operation.permissionSetName}"`);
3396
+ return upsertIdcPermissionSetInWorkingState({
3397
+ workingState: props.state,
3398
+ permissionSet: { ...permissionSet, permissionsBoundary: boundary }
3399
+ });
3400
+ }
3401
+ if (props.operation.kind === "deleteIdcPermissionSetPermissionsBoundary") {
3402
+ const permissionSet = resolvePermissionSetByName({
3403
+ state: props.state,
3404
+ permissionSetName: props.operation.permissionSetName
3405
+ });
3406
+ props.logger.log(
3407
+ `Deleting permissions boundary from IdC permission set "${props.operation.permissionSetName}"...`
3408
+ );
3409
+ await props.ssoAdminClient.send(
3410
+ new DeletePermissionsBoundaryFromPermissionSetCommand({
3411
+ InstanceArn: props.state.identityCenter.instanceArn,
3412
+ PermissionSetArn: permissionSet.permissionSetArn
3413
+ })
3414
+ );
3415
+ props.logger.log(`Done: "${props.operation.permissionSetName}"`);
3416
+ return upsertIdcPermissionSetInWorkingState({
3417
+ workingState: props.state,
3418
+ permissionSet: { ...permissionSet, permissionsBoundary: null }
3419
+ });
3420
+ }
3421
+ if (props.operation.kind === "removeIdcGroupMembership") {
2784
3422
  const resolvedMembership = resolveGroupMembershipDependencies({
2785
3423
  state: props.state,
2786
- groupDisplayName: operation.groupDisplayName,
2787
- userName: operation.userName
3424
+ groupDisplayName: props.operation.groupDisplayName,
3425
+ userName: props.operation.userName
2788
3426
  });
2789
3427
  const membershipId = await resolveGroupMembershipId({
2790
3428
  state: props.state,
@@ -2793,7 +3431,7 @@ async function executeOperation(props) {
2793
3431
  userId: resolvedMembership.userId
2794
3432
  });
2795
3433
  props.logger.log(
2796
- `Removing user "${operation.userName}" from IdC group "${operation.groupDisplayName}"...`
3434
+ `Removing user "${props.operation.userName}" from IdC group "${props.operation.groupDisplayName}"...`
2797
3435
  );
2798
3436
  await props.identityStoreClient.send(
2799
3437
  new DeleteGroupMembershipCommand({
@@ -2802,7 +3440,7 @@ async function executeOperation(props) {
2802
3440
  })
2803
3441
  );
2804
3442
  props.logger.log(
2805
- `Done: user "${operation.userName}" x group "${operation.groupDisplayName}"`
3443
+ `Done: user "${props.operation.userName}" x group "${props.operation.groupDisplayName}"`
2806
3444
  );
2807
3445
  return removeGroupMembershipFromWorkingState({
2808
3446
  workingState: props.state,
@@ -2812,21 +3450,21 @@ async function executeOperation(props) {
2812
3450
  }
2813
3451
  });
2814
3452
  }
2815
- if (operation.kind === "grantIdcAccountAssignment") {
3453
+ if (props.operation.kind === "grantIdcAccountAssignment") {
2816
3454
  const resolvedAssignment = resolveAssignmentDependencies({
2817
3455
  state: props.state,
2818
- accountName: operation.accountName,
2819
- permissionSetName: operation.permissionSetName,
2820
- principalType: operation.principalType,
2821
- principalName: operation.principalName
3456
+ accountName: props.operation.accountName,
3457
+ permissionSetName: props.operation.permissionSetName,
3458
+ principalType: props.operation.principalType,
3459
+ principalName: props.operation.principalName
2822
3460
  });
2823
3461
  props.logger.log(
2824
- `Granting IdC assignment "${operation.permissionSetName}" to ${formatPrincipalLabel(
3462
+ `Granting IdC assignment "${props.operation.permissionSetName}" to ${formatPrincipalLabel(
2825
3463
  {
2826
- principalType: operation.principalType,
2827
- principalName: operation.principalName
3464
+ principalType: props.operation.principalType,
3465
+ principalName: props.operation.principalName
2828
3466
  }
2829
- )} on "${operation.accountName}"...`
3467
+ )} on "${props.operation.accountName}"...`
2830
3468
  );
2831
3469
  const response = await props.ssoAdminClient.send(
2832
3470
  new CreateAccountAssignmentCommand({
@@ -2841,7 +3479,7 @@ async function executeOperation(props) {
2841
3479
  const requestId = response.AccountAssignmentCreationStatus?.RequestId;
2842
3480
  if (requestId == null) {
2843
3481
  throw new Error(
2844
- `CreateAccountAssignment for "${operation.permissionSetName}" on "${operation.accountName}" returned no request id.`
3482
+ `CreateAccountAssignment for "${props.operation.permissionSetName}" on "${props.operation.accountName}" returned no request id.`
2845
3483
  );
2846
3484
  }
2847
3485
  await waitForAccountAssignmentCreationSuccess({
@@ -2851,10 +3489,10 @@ async function executeOperation(props) {
2851
3489
  requestId,
2852
3490
  timeoutInMs: props.runtime.accountAssignment.timeoutInMs,
2853
3491
  pollIntervalInMs: props.runtime.accountAssignment.pollIntervalInMs,
2854
- operationLabel: `"${operation.permissionSetName}" on "${operation.accountName}"`
3492
+ operationLabel: `"${props.operation.permissionSetName}" on "${props.operation.accountName}"`
2855
3493
  });
2856
3494
  props.logger.log(
2857
- `Done: "${operation.permissionSetName}" -> "${operation.accountName}"`
3495
+ `Done: "${props.operation.permissionSetName}" -> "${props.operation.accountName}"`
2858
3496
  );
2859
3497
  return addAccountAssignmentToWorkingState({
2860
3498
  workingState: props.state,
@@ -2866,21 +3504,21 @@ async function executeOperation(props) {
2866
3504
  }
2867
3505
  });
2868
3506
  }
2869
- if (operation.kind === "revokeIdcAccountAssignment") {
3507
+ if (props.operation.kind === "revokeIdcAccountAssignment") {
2870
3508
  const resolvedAssignment = resolveAssignmentDependencies({
2871
3509
  state: props.state,
2872
- accountName: operation.accountName,
2873
- permissionSetName: operation.permissionSetName,
2874
- principalType: operation.principalType,
2875
- principalName: operation.principalName
3510
+ accountName: props.operation.accountName,
3511
+ permissionSetName: props.operation.permissionSetName,
3512
+ principalType: props.operation.principalType,
3513
+ principalName: props.operation.principalName
2876
3514
  });
2877
3515
  props.logger.log(
2878
- `Revoking IdC assignment "${operation.permissionSetName}" from ${formatPrincipalLabel(
3516
+ `Revoking IdC assignment "${props.operation.permissionSetName}" from ${formatPrincipalLabel(
2879
3517
  {
2880
- principalType: operation.principalType,
2881
- principalName: operation.principalName
3518
+ principalType: props.operation.principalType,
3519
+ principalName: props.operation.principalName
2882
3520
  }
2883
- )} on "${operation.accountName}"...`
3521
+ )} on "${props.operation.accountName}"...`
2884
3522
  );
2885
3523
  const response = await props.ssoAdminClient.send(
2886
3524
  new DeleteAccountAssignmentCommand({
@@ -2895,7 +3533,7 @@ async function executeOperation(props) {
2895
3533
  const requestId = response.AccountAssignmentDeletionStatus?.RequestId;
2896
3534
  if (requestId == null) {
2897
3535
  throw new Error(
2898
- `DeleteAccountAssignment for "${operation.permissionSetName}" on "${operation.accountName}" returned no request id.`
3536
+ `DeleteAccountAssignment for "${props.operation.permissionSetName}" on "${props.operation.accountName}" returned no request id.`
2899
3537
  );
2900
3538
  }
2901
3539
  await waitForAccountAssignmentDeletionSuccess({
@@ -2905,10 +3543,10 @@ async function executeOperation(props) {
2905
3543
  requestId,
2906
3544
  timeoutInMs: props.runtime.accountAssignment.timeoutInMs,
2907
3545
  pollIntervalInMs: props.runtime.accountAssignment.pollIntervalInMs,
2908
- operationLabel: `"${operation.permissionSetName}" on "${operation.accountName}"`
3546
+ operationLabel: `"${props.operation.permissionSetName}" on "${props.operation.accountName}"`
2909
3547
  });
2910
3548
  props.logger.log(
2911
- `Done: "${operation.permissionSetName}" x "${operation.accountName}"`
3549
+ `Done: "${props.operation.permissionSetName}" x "${props.operation.accountName}"`
2912
3550
  );
2913
3551
  return removeAccountAssignmentFromWorkingState({
2914
3552
  workingState: props.state,
@@ -2920,7 +3558,271 @@ async function executeOperation(props) {
2920
3558
  }
2921
3559
  });
2922
3560
  }
2923
- assertUnreachable(operation, "Unsupported operation kind in apply.");
3561
+ if (props.operation.kind === "createOrgPolicy") {
3562
+ props.logger.log(
3563
+ `Creating org policy "${props.operation.policyName}" (${props.operation.policyType})...`
3564
+ );
3565
+ const response = await props.organizationsClient.send(
3566
+ new CreatePolicyCommand({
3567
+ Name: props.operation.policyName,
3568
+ Description: props.operation.description.length > 0 ? props.operation.description : void 0,
3569
+ Content: props.operation.content,
3570
+ Type: props.operation.policyType
3571
+ })
3572
+ );
3573
+ const policy = response.Policy?.PolicySummary;
3574
+ if (policy?.Id == null || policy.Arn == null) {
3575
+ throw new Error(
3576
+ `CreatePolicy for "${props.operation.policyName}" returned incomplete data.`
3577
+ );
3578
+ }
3579
+ props.logger.log(`Done: "${props.operation.policyName}"`);
3580
+ return upsertOrgPolicyInWorkingState({
3581
+ workingState: props.state,
3582
+ policy: {
3583
+ id: policy.Id,
3584
+ arn: policy.Arn,
3585
+ name: props.operation.policyName,
3586
+ description: props.operation.description,
3587
+ type: props.operation.policyType,
3588
+ content: props.operation.content
3589
+ }
3590
+ });
3591
+ }
3592
+ if (props.operation.kind === "updateOrgPolicyContent") {
3593
+ props.logger.log(
3594
+ `Updating org policy content "${props.operation.policyName}"...`
3595
+ );
3596
+ await props.organizationsClient.send(
3597
+ new UpdatePolicyCommand({
3598
+ PolicyId: props.operation.policyId,
3599
+ Content: props.operation.content
3600
+ })
3601
+ );
3602
+ props.logger.log(`Done: "${props.operation.policyName}"`);
3603
+ const currentPolicy = props.state.organization.policiesById[props.operation.policyId];
3604
+ if (currentPolicy == null) {
3605
+ return props.state;
3606
+ }
3607
+ return upsertOrgPolicyInWorkingState({
3608
+ workingState: props.state,
3609
+ policy: { ...currentPolicy, content: props.operation.content }
3610
+ });
3611
+ }
3612
+ if (props.operation.kind === "updateOrgPolicyDescription") {
3613
+ props.logger.log(
3614
+ `Updating org policy description "${props.operation.policyName}"...`
3615
+ );
3616
+ await props.organizationsClient.send(
3617
+ new UpdatePolicyCommand({
3618
+ PolicyId: props.operation.policyId,
3619
+ Description: props.operation.description
3620
+ })
3621
+ );
3622
+ props.logger.log(`Done: "${props.operation.policyName}"`);
3623
+ const currentPolicy = props.state.organization.policiesById[props.operation.policyId];
3624
+ if (currentPolicy == null) {
3625
+ return props.state;
3626
+ }
3627
+ return upsertOrgPolicyInWorkingState({
3628
+ workingState: props.state,
3629
+ policy: { ...currentPolicy, description: props.operation.description }
3630
+ });
3631
+ }
3632
+ if (props.operation.kind === "attachOrgPolicy") {
3633
+ props.logger.log(
3634
+ `Attaching org policy "${props.operation.policyName}" to "${props.operation.targetName}"...`
3635
+ );
3636
+ const resolvedPolicyId = resolvePolicyId({
3637
+ state: props.state,
3638
+ policyId: props.operation.policyId,
3639
+ policyName: props.operation.policyName
3640
+ });
3641
+ await props.organizationsClient.send(
3642
+ new AttachPolicyCommand({
3643
+ PolicyId: resolvedPolicyId,
3644
+ TargetId: props.operation.targetId
3645
+ })
3646
+ );
3647
+ props.logger.log(
3648
+ `Done: "${props.operation.policyName}" -> "${props.operation.targetName}"`
3649
+ );
3650
+ const targetType = props.operation.targetId === props.context.organization.rootId ? "ROOT" : props.state.organization.organizationalUnitsById[props.operation.targetId] != null ? "ORGANIZATIONAL_UNIT" : "ACCOUNT";
3651
+ return addOrgPolicyAttachmentToWorkingState({
3652
+ workingState: props.state,
3653
+ attachment: {
3654
+ policyId: resolvedPolicyId,
3655
+ targetId: props.operation.targetId,
3656
+ targetType
3657
+ }
3658
+ });
3659
+ }
3660
+ if (props.operation.kind === "detachOrgPolicy") {
3661
+ props.logger.log(
3662
+ `Detaching org policy "${props.operation.policyName}" from "${props.operation.targetName}"...`
3663
+ );
3664
+ await props.organizationsClient.send(
3665
+ new DetachPolicyCommand({
3666
+ PolicyId: props.operation.policyId,
3667
+ TargetId: props.operation.targetId
3668
+ })
3669
+ );
3670
+ props.logger.log(
3671
+ `Done: "${props.operation.policyName}" x "${props.operation.targetName}"`
3672
+ );
3673
+ return removeOrgPolicyAttachmentFromWorkingState({
3674
+ workingState: props.state,
3675
+ policyId: props.operation.policyId,
3676
+ targetId: props.operation.targetId
3677
+ });
3678
+ }
3679
+ if (props.operation.kind === "deleteOrgPolicy") {
3680
+ props.logger.log(`Deleting org policy "${props.operation.policyName}"...`);
3681
+ await props.organizationsClient.send(
3682
+ new DeletePolicyCommand({ PolicyId: props.operation.policyId })
3683
+ );
3684
+ props.logger.log(`Done: "${props.operation.policyName}"`);
3685
+ return removeOrgPolicyFromWorkingState({
3686
+ workingState: props.state,
3687
+ policyId: props.operation.policyId
3688
+ });
3689
+ }
3690
+ if (props.operation.kind === "putAlternateContact") {
3691
+ const { contactType } = props.operation;
3692
+ props.logger.log(
3693
+ `Setting ${contactType} alternate contact for "${props.operation.accountName}" (${props.operation.accountId})...`
3694
+ );
3695
+ await props.accountClient.send(
3696
+ new PutAlternateContactCommand({
3697
+ AccountId: props.operation.accountId,
3698
+ AlternateContactType: contactType,
3699
+ Name: props.operation.name,
3700
+ EmailAddress: props.operation.email,
3701
+ PhoneNumber: props.operation.phone,
3702
+ Title: props.operation.title
3703
+ })
3704
+ );
3705
+ props.logger.log(
3706
+ `Done: ${contactType} contact for "${props.operation.accountName}"`
3707
+ );
3708
+ const account = props.state.organization.accountsById[props.operation.accountId];
3709
+ if (account == null) {
3710
+ throw new Error(
3711
+ `Could not resolve account (${props.operation.accountId}) in working state.`
3712
+ );
3713
+ }
3714
+ const updatedContacts = [
3715
+ ...(account.alternateContacts ?? []).filter(
3716
+ (c) => c.contactType !== contactType
3717
+ ),
3718
+ {
3719
+ contactType,
3720
+ name: props.operation.name,
3721
+ email: props.operation.email,
3722
+ phone: props.operation.phone,
3723
+ title: props.operation.title
3724
+ }
3725
+ ];
3726
+ return upsertAccountInWorkingState({
3727
+ workingState: props.state,
3728
+ account: { ...account, alternateContacts: updatedContacts }
3729
+ });
3730
+ }
3731
+ if (props.operation.kind === "deleteAlternateContact") {
3732
+ const { contactType } = props.operation;
3733
+ props.logger.log(
3734
+ `Deleting ${contactType} alternate contact for "${props.operation.accountName}" (${props.operation.accountId})...`
3735
+ );
3736
+ await props.accountClient.send(
3737
+ new DeleteAlternateContactCommand({
3738
+ AccountId: props.operation.accountId,
3739
+ AlternateContactType: contactType
3740
+ })
3741
+ );
3742
+ props.logger.log(
3743
+ `Done: removed ${contactType} contact for "${props.operation.accountName}"`
3744
+ );
3745
+ const account = props.state.organization.accountsById[props.operation.accountId];
3746
+ if (account == null) {
3747
+ throw new Error(
3748
+ `Could not resolve account (${props.operation.accountId}) in working state.`
3749
+ );
3750
+ }
3751
+ return upsertAccountInWorkingState({
3752
+ workingState: props.state,
3753
+ account: {
3754
+ ...account,
3755
+ alternateContacts: (account.alternateContacts ?? []).filter(
3756
+ (c) => c.contactType !== contactType
3757
+ )
3758
+ }
3759
+ });
3760
+ }
3761
+ if (props.operation.kind === "setIdcAccessControlAttributes") {
3762
+ props.logger.log(
3763
+ `Setting IdC access control attributes (${props.operation.attributes.length} attribute(s))...`
3764
+ );
3765
+ await props.ssoAdminClient.send(
3766
+ new UpdateInstanceAccessControlAttributeConfigurationCommand({
3767
+ InstanceArn: props.state.identityCenter.instanceArn,
3768
+ InstanceAccessControlAttributeConfiguration: {
3769
+ AccessControlAttributes: props.operation.attributes.map((attr) => ({
3770
+ Key: attr.key,
3771
+ Value: { Source: attr.source }
3772
+ }))
3773
+ }
3774
+ })
3775
+ );
3776
+ props.logger.log(`Done: access control attributes updated`);
3777
+ return {
3778
+ ...props.state,
3779
+ identityCenter: {
3780
+ ...props.state.identityCenter,
3781
+ accessControlAttributes: props.operation.attributes
3782
+ }
3783
+ };
3784
+ }
3785
+ if (props.operation.kind === "registerDelegatedAdministrator") {
3786
+ props.logger.log(
3787
+ `Registering delegated administrator "${props.operation.accountName}" (${props.operation.accountId}) for ${props.operation.servicePrincipal}...`
3788
+ );
3789
+ await props.organizationsClient.send(
3790
+ new RegisterDelegatedAdministratorCommand({
3791
+ AccountId: props.operation.accountId,
3792
+ ServicePrincipal: props.operation.servicePrincipal
3793
+ })
3794
+ );
3795
+ props.logger.log(
3796
+ `Done: "${props.operation.accountName}" for ${props.operation.servicePrincipal}`
3797
+ );
3798
+ return upsertDelegatedAdministratorInWorkingState({
3799
+ workingState: props.state,
3800
+ delegatedAdministrator: {
3801
+ accountId: props.operation.accountId,
3802
+ servicePrincipal: props.operation.servicePrincipal
3803
+ }
3804
+ });
3805
+ }
3806
+ if (props.operation.kind === "deregisterDelegatedAdministrator") {
3807
+ props.logger.log(
3808
+ `Deregistering delegated administrator "${props.operation.accountName}" (${props.operation.accountId}) for ${props.operation.servicePrincipal}...`
3809
+ );
3810
+ await props.organizationsClient.send(
3811
+ new DeregisterDelegatedAdministratorCommand({
3812
+ AccountId: props.operation.accountId,
3813
+ ServicePrincipal: props.operation.servicePrincipal
3814
+ })
3815
+ );
3816
+ props.logger.log(
3817
+ `Done: removed "${props.operation.accountName}" for ${props.operation.servicePrincipal}`
3818
+ );
3819
+ return removeDelegatedAdministratorFromWorkingState({
3820
+ workingState: props.state,
3821
+ accountId: props.operation.accountId,
3822
+ servicePrincipal: props.operation.servicePrincipal
3823
+ });
3824
+ }
3825
+ assertUnreachable(props.operation, "Unsupported operation kind in apply.");
2924
3826
  }
2925
3827
  function resolveAssignmentDependencies(props) {
2926
3828
  const account = props.state.organization.accountsByName[props.accountName];
@@ -2980,6 +3882,16 @@ function resolveGroupByDisplayName(props) {
2980
3882
  }
2981
3883
  return group;
2982
3884
  }
3885
+ function resolvePolicyId(props) {
3886
+ if (props.policyId !== "__pending_creation__") return props.policyId;
3887
+ const policy = props.state.organization.policiesByName[props.policyName];
3888
+ if (policy == null) {
3889
+ throw new Error(
3890
+ `Could not resolve policy "${props.policyName}" in working state.`
3891
+ );
3892
+ }
3893
+ return policy.id;
3894
+ }
2983
3895
  function resolvePermissionSetByName(props) {
2984
3896
  const permissionSet = props.state.identityCenter.permissionSetsByName[props.permissionSetName];
2985
3897
  if (permissionSet == null) {
@@ -3269,7 +4181,9 @@ var scanResponseSchema = strictObject({
3269
4181
  users: number(),
3270
4182
  groups: number(),
3271
4183
  permissionSets: number(),
3272
- accountAssignments: number()
4184
+ accountAssignments: number(),
4185
+ policies: number(),
4186
+ policyAttachments: number()
3273
4187
  }),
3274
4188
  state: stateSchema
3275
4189
  });
@@ -3339,7 +4253,7 @@ var s3Client = new S3Client({});
3339
4253
  var organizationsClient = new OrganizationsClient3({});
3340
4254
  var ssoAdminClient = new SSOAdminClient3({});
3341
4255
  var identityStoreClient = new IdentitystoreClient3({});
3342
- var accountClient = new AccountClient2({});
4256
+ var accountClient = new AccountClient3({});
3343
4257
  async function handler(event) {
3344
4258
  try {
3345
4259
  const parseResult = safeParse(lambdaRequestSchema, event);
@@ -3364,7 +4278,7 @@ async function handler(event) {
3364
4278
  return validateResponse(response);
3365
4279
  }
3366
4280
  if (request.action === "scan") {
3367
- const response = await handleScan({ s3Client, bucket, organizationsClient, ssoAdminClient, identityStoreClient });
4281
+ const response = await handleScan({ s3Client, bucket, organizationsClient, ssoAdminClient, identityStoreClient, accountClient });
3368
4282
  return validateResponse(response);
3369
4283
  }
3370
4284
  if (request.action === "getStateUrl") {
@@ -3453,7 +4367,7 @@ function isS3PreconditionFailed(error) {
3453
4367
  async function handleScan(props) {
3454
4368
  const identityCenterInstanceArn = process.env.IDENTITY_CENTER_INSTANCE_ARN || void 0;
3455
4369
  const [organization, identityCenter] = await Promise.all([
3456
- scanOrganization({ organizationsClient: props.organizationsClient }),
4370
+ scanOrganization({ organizationsClient: props.organizationsClient, accountClient: props.accountClient }),
3457
4371
  scanIdentityCenter({
3458
4372
  ssoAdminClient: props.ssoAdminClient,
3459
4373
  identityStoreClient: props.identityStoreClient,
@@ -3480,7 +4394,9 @@ async function handleScan(props) {
3480
4394
  users: state.identityCenter.users.length,
3481
4395
  groups: state.identityCenter.groups.length,
3482
4396
  permissionSets: state.identityCenter.permissionSets.length,
3483
- accountAssignments: state.identityCenter.accountAssignments.length
4397
+ accountAssignments: state.identityCenter.accountAssignments.length,
4398
+ policies: state.organization.policies?.length ?? 0,
4399
+ policyAttachments: state.organization.policyAttachments?.length ?? 0
3484
4400
  },
3485
4401
  state
3486
4402
  };