@beesolve/aws-accounts 1.2.0 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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(),
@@ -836,6 +852,18 @@ var deleteAlternateContactOperationSchema = strictObject({
836
852
  accountName: string(),
837
853
  contactType: alternateContactTypeSchema
838
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
+ });
839
867
  var createOrgPolicyOperationSchema = strictObject({
840
868
  kind: literal("createOrgPolicy"),
841
869
  policyName: string(),
@@ -843,7 +871,8 @@ var createOrgPolicyOperationSchema = strictObject({
843
871
  "SERVICE_CONTROL_POLICY",
844
872
  "RESOURCE_CONTROL_POLICY",
845
873
  "TAG_POLICY",
846
- "AISERVICES_OPT_OUT_POLICY"
874
+ "AISERVICES_OPT_OUT_POLICY",
875
+ "BACKUP_POLICY"
847
876
  ]),
848
877
  description: string(),
849
878
  content: string()
@@ -907,6 +936,8 @@ var operationSchema = variant("kind", [
907
936
  attachIdcCustomerManagedPolicyReferenceToPermissionSetOperationSchema,
908
937
  detachIdcCustomerManagedPolicyReferenceFromPermissionSetOperationSchema,
909
938
  provisionIdcPermissionSetOperationSchema,
939
+ putIdcPermissionSetPermissionsBoundaryOperationSchema,
940
+ deleteIdcPermissionSetPermissionsBoundaryOperationSchema,
910
941
  grantIdcAccountAssignmentOperationSchema,
911
942
  revokeIdcAccountAssignmentOperationSchema,
912
943
  createOrgPolicyOperationSchema,
@@ -917,13 +948,16 @@ var operationSchema = variant("kind", [
917
948
  deleteOrgPolicyOperationSchema,
918
949
  putAlternateContactOperationSchema,
919
950
  deleteAlternateContactOperationSchema,
920
- setIdcAccessControlAttributesOperationSchema
951
+ setIdcAccessControlAttributesOperationSchema,
952
+ registerDelegatedAdministratorOperationSchema,
953
+ deregisterDelegatedAdministratorOperationSchema
921
954
  ]);
922
955
  var unsupportedDiffKindSchema = picklist([
923
956
  "ambiguousOuRename",
924
957
  "reparentedOu",
925
958
  "newOuWithUnknownParent",
926
959
  "newAccountWithUnknownOu",
960
+ "existingAccountWithUnknownTargetOu",
927
961
  "removedOu"
928
962
  ]);
929
963
  var unsupportedDiffCategorySchema = picklist([
@@ -971,7 +1005,8 @@ var orgPolicyTypeSchema = picklist([
971
1005
  "SERVICE_CONTROL_POLICY",
972
1006
  "RESOURCE_CONTROL_POLICY",
973
1007
  "TAG_POLICY",
974
- "AISERVICES_OPT_OUT_POLICY"
1008
+ "AISERVICES_OPT_OUT_POLICY",
1009
+ "BACKUP_POLICY"
975
1010
  ]);
976
1011
  var orgPolicySchema = strictObject({
977
1012
  id: nonEmptyString,
@@ -1027,6 +1062,13 @@ var customerManagedPolicyReferenceSchema = strictObject({
1027
1062
  name: nonEmptyString,
1028
1063
  path: nonEmptyString
1029
1064
  });
1065
+ var permissionsBoundarySchema = union([
1066
+ strictObject({ managedPolicyArn: nonEmptyString }),
1067
+ strictObject({
1068
+ customerManagedPolicyName: nonEmptyString,
1069
+ customerManagedPolicyPath: nonEmptyString
1070
+ })
1071
+ ]);
1030
1072
  var permissionSetSchema = strictObject({
1031
1073
  permissionSetArn: nonEmptyString,
1032
1074
  name: nonEmptyString,
@@ -1034,7 +1076,8 @@ var permissionSetSchema = strictObject({
1034
1076
  sessionDuration: nullable(string()),
1035
1077
  inlinePolicy: nullable(nonEmptyString),
1036
1078
  awsManagedPolicies: array(nonEmptyString),
1037
- customerManagedPolicies: array(customerManagedPolicyReferenceSchema)
1079
+ customerManagedPolicies: array(customerManagedPolicyReferenceSchema),
1080
+ permissionsBoundary: nullable(permissionsBoundarySchema)
1038
1081
  });
1039
1082
  var accountAssignmentSchema = strictObject({
1040
1083
  accountId: nonEmptyString,
@@ -1053,6 +1096,10 @@ var accessControlAttributeSchema = strictObject({
1053
1096
  key: nonEmptyString,
1054
1097
  source: array(nonEmptyString)
1055
1098
  });
1099
+ var delegatedAdministratorSchema = strictObject({
1100
+ accountId: nonEmptyString,
1101
+ servicePrincipal: nonEmptyString
1102
+ });
1056
1103
  var stateSchema = strictObject({
1057
1104
  version: nonEmptyString,
1058
1105
  generatedAt: nonEmptyString,
@@ -1061,7 +1108,8 @@ var stateSchema = strictObject({
1061
1108
  organizationalUnits: array(organizationalUnitSchema),
1062
1109
  accounts: array(accountSchema),
1063
1110
  policies: optional(array(orgPolicySchema)),
1064
- policyAttachments: optional(array(orgPolicyAttachmentSchema))
1111
+ policyAttachments: optional(array(orgPolicyAttachmentSchema)),
1112
+ delegatedAdministrators: optional(array(delegatedAdministratorSchema))
1065
1113
  }),
1066
1114
  identityCenter: strictObject({
1067
1115
  instanceArn: nonEmptyString,
@@ -1078,6 +1126,7 @@ var stateSchema = strictObject({
1078
1126
  function createWorkingState(props) {
1079
1127
  const policies = props.state.organization.policies ?? [];
1080
1128
  const policyAttachments = props.state.organization.policyAttachments ?? [];
1129
+ const delegatedAdministrators = props.state.organization.delegatedAdministrators ?? [];
1081
1130
  return {
1082
1131
  version: props.state.version,
1083
1132
  generatedAt: props.state.generatedAt,
@@ -1098,6 +1147,11 @@ function createWorkingState(props) {
1098
1147
  policyAttachmentsByKey: toRecordByProperty(
1099
1148
  policyAttachments,
1100
1149
  createOrgPolicyAttachmentKey
1150
+ ),
1151
+ delegatedAdministrators: structuredClone(delegatedAdministrators),
1152
+ delegatedAdministratorsByKey: toRecordByProperty(
1153
+ delegatedAdministrators,
1154
+ createDelegatedAdministratorKey
1101
1155
  )
1102
1156
  },
1103
1157
  identityCenter: createWorkingIdentityCenterState({
@@ -1118,7 +1172,12 @@ function materializeWorkingState(props) {
1118
1172
  policies: Object.values(props.workingState.organization.policiesById),
1119
1173
  policyAttachments: structuredClone(
1120
1174
  props.workingState.organization.policyAttachments
1121
- )
1175
+ ),
1176
+ ...props.workingState.organization.delegatedAdministrators.length > 0 ? {
1177
+ delegatedAdministrators: structuredClone(
1178
+ props.workingState.organization.delegatedAdministrators
1179
+ )
1180
+ } : {}
1122
1181
  },
1123
1182
  identityCenter: {
1124
1183
  instanceArn: props.workingState.identityCenter.instanceArn,
@@ -1351,7 +1410,7 @@ function removeIdcGroupFromWorkingState(props) {
1351
1410
  }
1352
1411
  function upsertIdcPermissionSetInWorkingState(props) {
1353
1412
  const currentPermissionSet = props.workingState.identityCenter.permissionSetsByName[props.permissionSet.name];
1354
- 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)) {
1413
+ 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)) {
1355
1414
  return props.workingState;
1356
1415
  }
1357
1416
  const remainingPermissionSets = props.workingState.identityCenter.permissionSets.filter(
@@ -1588,6 +1647,59 @@ function removeOrgPolicyAttachmentFromWorkingState(props) {
1588
1647
  }
1589
1648
  };
1590
1649
  }
1650
+ function createDelegatedAdministratorKey(props) {
1651
+ return [props.accountId, props.servicePrincipal].join("|");
1652
+ }
1653
+ function upsertDelegatedAdministratorInWorkingState(props) {
1654
+ const key = createDelegatedAdministratorKey({
1655
+ accountId: props.delegatedAdministrator.accountId,
1656
+ servicePrincipal: props.delegatedAdministrator.servicePrincipal
1657
+ });
1658
+ if (props.workingState.organization.delegatedAdministratorsByKey[key] != null) {
1659
+ return props.workingState;
1660
+ }
1661
+ const nextDelegatedAdministrators = [
1662
+ ...props.workingState.organization.delegatedAdministrators,
1663
+ props.delegatedAdministrator
1664
+ ];
1665
+ return {
1666
+ ...props.workingState,
1667
+ organization: {
1668
+ ...props.workingState.organization,
1669
+ delegatedAdministrators: nextDelegatedAdministrators,
1670
+ delegatedAdministratorsByKey: toRecordByProperty(
1671
+ nextDelegatedAdministrators,
1672
+ createDelegatedAdministratorKey
1673
+ )
1674
+ }
1675
+ };
1676
+ }
1677
+ function removeDelegatedAdministratorFromWorkingState(props) {
1678
+ const key = createDelegatedAdministratorKey({
1679
+ accountId: props.accountId,
1680
+ servicePrincipal: props.servicePrincipal
1681
+ });
1682
+ if (props.workingState.organization.delegatedAdministratorsByKey[key] == null) {
1683
+ return props.workingState;
1684
+ }
1685
+ const nextDelegatedAdministrators = props.workingState.organization.delegatedAdministrators.filter(
1686
+ (da) => createDelegatedAdministratorKey({
1687
+ accountId: da.accountId,
1688
+ servicePrincipal: da.servicePrincipal
1689
+ }) !== key
1690
+ );
1691
+ return {
1692
+ ...props.workingState,
1693
+ organization: {
1694
+ ...props.workingState.organization,
1695
+ delegatedAdministrators: nextDelegatedAdministrators,
1696
+ delegatedAdministratorsByKey: toRecordByProperty(
1697
+ nextDelegatedAdministrators,
1698
+ createDelegatedAdministratorKey
1699
+ )
1700
+ }
1701
+ };
1702
+ }
1591
1703
  function createAccessRoleName(assignment) {
1592
1704
  return `AWSReservedSSO_${assignment.permissionSetArn.split("/").at(-1) ?? "PermissionSet"}_${assignment.accountId}`;
1593
1705
  }
@@ -1684,6 +1796,8 @@ import {
1684
1796
  DescribeOrganizationCommand,
1685
1797
  DescribePolicyCommand,
1686
1798
  ListAccountsCommand,
1799
+ ListDelegatedAdministratorsCommand,
1800
+ ListDelegatedServicesForAccountCommand,
1687
1801
  ListOrganizationalUnitsForParentCommand,
1688
1802
  ListParentsCommand,
1689
1803
  ListPoliciesCommand,
@@ -1694,6 +1808,7 @@ import {
1694
1808
  import {
1695
1809
  DescribePermissionSetCommand,
1696
1810
  GetInlinePolicyForPermissionSetCommand,
1811
+ GetPermissionsBoundaryForPermissionSetCommand,
1697
1812
  ListAccountAssignmentsCommand,
1698
1813
  ListAccountsForProvisionedPermissionSetCommand,
1699
1814
  ListCustomerManagedPolicyReferencesInPermissionSetCommand,
@@ -1766,22 +1881,65 @@ async function scanOrganization(props) {
1766
1881
  }
1767
1882
  nextToken = response.NextToken;
1768
1883
  } while (nextToken != null);
1769
- const { policies, policyAttachments } = await scanOrganizationPolicies({
1770
- organizationsClient: props.organizationsClient
1771
- });
1884
+ const [{ policies, policyAttachments }, delegatedAdministrators] = await Promise.all([
1885
+ scanOrganizationPolicies({
1886
+ organizationsClient: props.organizationsClient
1887
+ }),
1888
+ scanDelegatedAdministrators({
1889
+ organizationsClient: props.organizationsClient
1890
+ })
1891
+ ]);
1772
1892
  return {
1773
1893
  rootId: root.Id,
1774
1894
  organizationalUnits,
1775
1895
  accounts,
1776
1896
  policies,
1777
- policyAttachments
1897
+ policyAttachments,
1898
+ delegatedAdministrators: delegatedAdministrators.length > 0 ? delegatedAdministrators : void 0
1778
1899
  };
1779
1900
  }
1901
+ async function scanDelegatedAdministrators(props) {
1902
+ const accountIds = new Array();
1903
+ let nextToken;
1904
+ do {
1905
+ const response = await props.organizationsClient.send(
1906
+ new ListDelegatedAdministratorsCommand({ NextToken: nextToken })
1907
+ );
1908
+ for (const admin of response.DelegatedAdministrators ?? []) {
1909
+ if (admin.Id == null) {
1910
+ continue;
1911
+ }
1912
+ accountIds.push(admin.Id);
1913
+ }
1914
+ nextToken = response.NextToken;
1915
+ } while (nextToken != null);
1916
+ const results = [];
1917
+ for (const accountId of accountIds) {
1918
+ let servicesNextToken;
1919
+ do {
1920
+ const response = await props.organizationsClient.send(
1921
+ new ListDelegatedServicesForAccountCommand({
1922
+ AccountId: accountId,
1923
+ NextToken: servicesNextToken
1924
+ })
1925
+ );
1926
+ for (const service of response.DelegatedServices ?? []) {
1927
+ if (service.ServicePrincipal == null) {
1928
+ continue;
1929
+ }
1930
+ results.push({ accountId, servicePrincipal: service.ServicePrincipal });
1931
+ }
1932
+ servicesNextToken = response.NextToken;
1933
+ } while (servicesNextToken != null);
1934
+ }
1935
+ return results;
1936
+ }
1780
1937
  var ORG_POLICY_TYPES = [
1781
1938
  "SERVICE_CONTROL_POLICY",
1782
1939
  "RESOURCE_CONTROL_POLICY",
1783
1940
  "TAG_POLICY",
1784
- "AISERVICES_OPT_OUT_POLICY"
1941
+ "AISERVICES_OPT_OUT_POLICY",
1942
+ "BACKUP_POLICY"
1785
1943
  ];
1786
1944
  async function scanOrganizationPolicies(props) {
1787
1945
  const policies = [];
@@ -2105,7 +2263,8 @@ async function listPermissionSets(props) {
2105
2263
  const [
2106
2264
  inlinePolicy,
2107
2265
  awsManagedPolicies,
2108
- customerManagedPolicies
2266
+ customerManagedPolicies,
2267
+ permissionsBoundary
2109
2268
  ] = await Promise.all([
2110
2269
  getInlinePolicyForPermissionSet({
2111
2270
  ssoAdminClient: props.ssoAdminClient,
@@ -2121,6 +2280,11 @@ async function listPermissionSets(props) {
2121
2280
  ssoAdminClient: props.ssoAdminClient,
2122
2281
  instanceArn: props.instanceArn,
2123
2282
  permissionSetArn: permissionSet.PermissionSetArn
2283
+ }),
2284
+ getPermissionsBoundaryForPermissionSet({
2285
+ ssoAdminClient: props.ssoAdminClient,
2286
+ instanceArn: props.instanceArn,
2287
+ permissionSetArn: permissionSet.PermissionSetArn
2124
2288
  })
2125
2289
  ]);
2126
2290
  return {
@@ -2130,7 +2294,8 @@ async function listPermissionSets(props) {
2130
2294
  sessionDuration: permissionSet.SessionDuration ?? null,
2131
2295
  inlinePolicy,
2132
2296
  awsManagedPolicies,
2133
- customerManagedPolicies
2297
+ customerManagedPolicies,
2298
+ permissionsBoundary
2134
2299
  };
2135
2300
  })
2136
2301
  );
@@ -2148,6 +2313,36 @@ async function getInlinePolicyForPermissionSet(props) {
2148
2313
  const inlinePolicy = response.InlinePolicy?.trim();
2149
2314
  return inlinePolicy != null && inlinePolicy.length > 0 ? inlinePolicy : null;
2150
2315
  }
2316
+ async function getPermissionsBoundaryForPermissionSet(props) {
2317
+ try {
2318
+ const response = await props.ssoAdminClient.send(
2319
+ new GetPermissionsBoundaryForPermissionSetCommand({
2320
+ InstanceArn: props.instanceArn,
2321
+ PermissionSetArn: props.permissionSetArn
2322
+ })
2323
+ );
2324
+ const boundary = response.PermissionsBoundary;
2325
+ if (boundary == null) {
2326
+ return null;
2327
+ }
2328
+ if (boundary.ManagedPolicyArn != null) {
2329
+ return { managedPolicyArn: boundary.ManagedPolicyArn };
2330
+ }
2331
+ const ref = boundary.CustomerManagedPolicyReference;
2332
+ if (ref?.Name != null) {
2333
+ return {
2334
+ customerManagedPolicyName: ref.Name,
2335
+ customerManagedPolicyPath: ref.Path ?? "/"
2336
+ };
2337
+ }
2338
+ return null;
2339
+ } catch (err) {
2340
+ if (err != null && typeof err === "object" && "name" in err && err.name === "ResourceNotFoundException") {
2341
+ return null;
2342
+ }
2343
+ throw err;
2344
+ }
2345
+ }
2151
2346
  async function listManagedPoliciesInPermissionSet(props) {
2152
2347
  const managedPolicies = [];
2153
2348
  let nextToken;
@@ -2245,11 +2440,7 @@ async function listAccountsForPermissionSet(props) {
2245
2440
  } while (nextToken != null);
2246
2441
  return accountIds;
2247
2442
  }
2248
- var ALTERNATE_CONTACT_TYPES = [
2249
- "BILLING",
2250
- "OPERATIONS",
2251
- "SECURITY"
2252
- ];
2443
+ var ALTERNATE_CONTACT_TYPES = ["BILLING", "OPERATIONS", "SECURITY"];
2253
2444
  async function scanAlternateContacts(props) {
2254
2445
  const results = await Promise.all(
2255
2446
  ALTERNATE_CONTACT_TYPES.map(async (contactType) => {
@@ -2292,12 +2483,14 @@ import {
2292
2483
  AttachPolicyCommand,
2293
2484
  CreateOrganizationalUnitCommand,
2294
2485
  CreatePolicyCommand,
2486
+ DeregisterDelegatedAdministratorCommand,
2295
2487
  DeleteOrganizationalUnitCommand,
2296
2488
  DeletePolicyCommand,
2297
2489
  DetachPolicyCommand,
2298
2490
  ListAccountsForParentCommand,
2299
2491
  ListOrganizationalUnitsForParentCommand as ListOrganizationalUnitsForParentCommand2,
2300
2492
  MoveAccountCommand as MoveAccountCommand2,
2493
+ RegisterDelegatedAdministratorCommand,
2301
2494
  TagResourceCommand,
2302
2495
  UntagResourceCommand,
2303
2496
  UpdateOrganizationalUnitCommand,
@@ -2321,6 +2514,7 @@ import {
2321
2514
  CreatePermissionSetCommand,
2322
2515
  DeleteAccountAssignmentCommand,
2323
2516
  DeleteInlinePolicyFromPermissionSetCommand,
2517
+ DeletePermissionsBoundaryFromPermissionSetCommand,
2324
2518
  DeletePermissionSetCommand,
2325
2519
  DescribeAccountAssignmentCreationStatusCommand,
2326
2520
  DescribeAccountAssignmentDeletionStatusCommand,
@@ -2329,6 +2523,7 @@ import {
2329
2523
  DetachManagedPolicyFromPermissionSetCommand,
2330
2524
  ProvisionPermissionSetCommand,
2331
2525
  PutInlinePolicyToPermissionSetCommand,
2526
+ PutPermissionsBoundaryToPermissionSetCommand,
2332
2527
  UpdateInstanceAccessControlAttributeConfigurationCommand,
2333
2528
  UpdatePermissionSetCommand
2334
2529
  } from "@aws-sdk/client-sso-admin";
@@ -2468,39 +2663,48 @@ function isCompleteAccountWithStatus(account, expectedAccountId) {
2468
2663
 
2469
2664
  // src/applyLogic.ts
2470
2665
  async function executeOperation(props) {
2471
- const operation = props.operation;
2472
- if (operation.kind === "moveAccount") {
2666
+ if (props.operation.kind === "moveAccount") {
2473
2667
  props.logger.log(
2474
- `Moving "${operation.accountName}" (${operation.accountId}): ${operation.fromOuName} -> ${operation.toOuName}`
2668
+ `Moving "${props.operation.accountName}" (${props.operation.accountId}): ${props.operation.fromOuName} -> ${props.operation.toOuName}`
2475
2669
  );
2670
+ const toOuId = resolveOrganizationalUnitId({
2671
+ state: props.state,
2672
+ organizationalUnitId: props.operation.toOuId,
2673
+ organizationalUnitName: props.operation.toOuName
2674
+ });
2476
2675
  await props.organizationsClient.send(
2477
2676
  new MoveAccountCommand2({
2478
- AccountId: operation.accountId,
2479
- SourceParentId: operation.fromOuId,
2480
- DestinationParentId: operation.toOuId
2677
+ AccountId: props.operation.accountId,
2678
+ SourceParentId: props.operation.fromOuId,
2679
+ DestinationParentId: toOuId
2481
2680
  })
2482
2681
  );
2483
- props.logger.log(`Done: "${operation.accountName}"`);
2682
+ props.logger.log(`Done: "${props.operation.accountName}"`);
2484
2683
  return moveAccountInWorkingState({
2485
2684
  workingState: props.state,
2486
- accountId: operation.accountId,
2487
- parentId: operation.toOuId
2685
+ accountId: props.operation.accountId,
2686
+ parentId: toOuId
2488
2687
  });
2489
2688
  }
2490
- if (operation.kind === "createOu") {
2689
+ if (props.operation.kind === "createOu") {
2491
2690
  props.logger.log(
2492
- `Creating OU "${operation.ouName}" under ${operation.parentOuName}...`
2691
+ `Creating OU "${props.operation.ouName}" under ${props.operation.parentOuName}...`
2493
2692
  );
2693
+ const parentOuId = resolveOrganizationalUnitId({
2694
+ state: props.state,
2695
+ organizationalUnitId: props.operation.parentOuId,
2696
+ organizationalUnitName: props.operation.parentOuName
2697
+ });
2494
2698
  const response = await props.organizationsClient.send(
2495
2699
  new CreateOrganizationalUnitCommand({
2496
- ParentId: operation.parentOuId,
2497
- Name: operation.ouName
2700
+ ParentId: parentOuId,
2701
+ Name: props.operation.ouName
2498
2702
  })
2499
2703
  );
2500
2704
  const createdOu = response.OrganizationalUnit;
2501
2705
  if (createdOu?.Id == null || createdOu.Arn == null || createdOu.Name == null) {
2502
2706
  throw new Error(
2503
- `CreateOrganizationalUnit for "${operation.ouName}" returned incomplete OU data.`
2707
+ `CreateOrganizationalUnit for "${props.operation.ouName}" returned incomplete OU data.`
2504
2708
  );
2505
2709
  }
2506
2710
  props.logger.log(`Done: "${createdOu.Name}"`);
@@ -2508,55 +2712,60 @@ async function executeOperation(props) {
2508
2712
  workingState: props.state,
2509
2713
  organizationalUnit: {
2510
2714
  id: createdOu.Id,
2511
- parentId: operation.parentOuId,
2715
+ parentId: parentOuId,
2512
2716
  arn: createdOu.Arn,
2513
2717
  name: createdOu.Name
2514
2718
  }
2515
2719
  });
2516
2720
  }
2517
- if (operation.kind === "renameOu") {
2721
+ if (props.operation.kind === "renameOu") {
2518
2722
  props.logger.log(
2519
- `Renaming OU "${operation.fromOuName}" -> "${operation.toOuName}"...`
2723
+ `Renaming OU "${props.operation.fromOuName}" -> "${props.operation.toOuName}"...`
2520
2724
  );
2521
2725
  await props.organizationsClient.send(
2522
2726
  new UpdateOrganizationalUnitCommand({
2523
- OrganizationalUnitId: operation.ouId,
2524
- Name: operation.toOuName
2727
+ OrganizationalUnitId: props.operation.ouId,
2728
+ Name: props.operation.toOuName
2525
2729
  })
2526
2730
  );
2527
- props.logger.log(`Done: "${operation.toOuName}"`);
2731
+ props.logger.log(`Done: "${props.operation.toOuName}"`);
2528
2732
  return renameOrganizationalUnitInWorkingState({
2529
2733
  workingState: props.state,
2530
- organizationalUnitId: operation.ouId,
2531
- name: operation.toOuName
2734
+ organizationalUnitId: props.operation.ouId,
2735
+ name: props.operation.toOuName
2532
2736
  });
2533
2737
  }
2534
- if (operation.kind === "deleteOu") {
2535
- props.logger.log(`Deleting OU "${operation.ouName}"...`);
2738
+ if (props.operation.kind === "deleteOu") {
2739
+ props.logger.log(`Deleting OU "${props.operation.ouName}"...`);
2536
2740
  await assertOrganizationalUnitIsEmpty({
2537
2741
  organizationsClient: props.organizationsClient,
2538
- organizationalUnitId: operation.ouId,
2539
- organizationalUnitName: operation.ouName
2742
+ organizationalUnitId: props.operation.ouId,
2743
+ organizationalUnitName: props.operation.ouName
2540
2744
  });
2541
2745
  await props.organizationsClient.send(
2542
2746
  new DeleteOrganizationalUnitCommand({
2543
- OrganizationalUnitId: operation.ouId
2747
+ OrganizationalUnitId: props.operation.ouId
2544
2748
  })
2545
2749
  );
2546
- props.logger.log(`Done: "${operation.ouName}"`);
2750
+ props.logger.log(`Done: "${props.operation.ouName}"`);
2547
2751
  return removeOrganizationalUnitFromWorkingState({
2548
2752
  workingState: props.state,
2549
- organizationalUnitId: operation.ouId
2753
+ organizationalUnitId: props.operation.ouId
2550
2754
  });
2551
2755
  }
2552
- if (operation.kind === "createAccount") {
2756
+ if (props.operation.kind === "createAccount") {
2757
+ const targetOuId = resolveOrganizationalUnitId({
2758
+ state: props.state,
2759
+ organizationalUnitId: props.operation.targetOuId,
2760
+ organizationalUnitName: props.operation.targetOuName
2761
+ });
2553
2762
  const result = await createAccountAndMoveToOu({
2554
2763
  organizationsClient: props.organizationsClient,
2555
2764
  logger: props.logger,
2556
- accountName: operation.accountName,
2557
- accountEmail: operation.accountEmail,
2765
+ accountName: props.operation.accountName,
2766
+ accountEmail: props.operation.accountEmail,
2558
2767
  sourceParentId: props.context.organization.rootId,
2559
- destinationParentId: operation.targetOuId,
2768
+ destinationParentId: targetOuId,
2560
2769
  timeoutInMs: props.runtime.createAccount.timeoutInMs,
2561
2770
  pollIntervalInMs: props.runtime.createAccount.pollIntervalInMs
2562
2771
  });
@@ -2568,33 +2777,33 @@ async function executeOperation(props) {
2568
2777
  name: result.account.name,
2569
2778
  email: result.account.email,
2570
2779
  status: result.account.status,
2571
- parentId: operation.targetOuId,
2780
+ parentId: targetOuId,
2572
2781
  tags: []
2573
2782
  }
2574
2783
  });
2575
2784
  }
2576
- if (operation.kind === "updateAccountTags") {
2577
- const account = props.state.organization.accountsById[operation.accountId];
2785
+ if (props.operation.kind === "updateAccountTags") {
2786
+ const account = props.state.organization.accountsById[props.operation.accountId];
2578
2787
  if (account == null) {
2579
2788
  throw new Error(
2580
- `Could not resolve account "${operation.accountName}" (${operation.accountId}) in working state.`
2789
+ `Could not resolve account "${props.operation.accountName}" (${props.operation.accountId}) in working state.`
2581
2790
  );
2582
2791
  }
2583
2792
  const currentTags = new Map(
2584
2793
  (account.tags ?? []).map((tag) => [tag.key, tag.value])
2585
2794
  );
2586
- const desiredTags = new Map(Object.entries(operation.tags));
2795
+ const desiredTags = new Map(Object.entries(props.operation.tags));
2587
2796
  const tagsToApply = [...desiredTags.entries()].filter(([key, value]) => currentTags.get(key) !== value).map(([Key, Value]) => ({ Key, Value }));
2588
2797
  const tagKeysToRemove = [...currentTags.keys()].filter(
2589
2798
  (key) => desiredTags.has(key) === false
2590
2799
  );
2591
2800
  props.logger.log(
2592
- `Updating account tags "${operation.accountName}" (${operation.accountId})...`
2801
+ `Updating account tags "${props.operation.accountName}" (${props.operation.accountId})...`
2593
2802
  );
2594
2803
  if (tagsToApply.length > 0) {
2595
2804
  await props.organizationsClient.send(
2596
2805
  new TagResourceCommand({
2597
- ResourceId: operation.accountId,
2806
+ ResourceId: props.operation.accountId,
2598
2807
  Tags: tagsToApply
2599
2808
  })
2600
2809
  );
@@ -2602,84 +2811,84 @@ async function executeOperation(props) {
2602
2811
  if (tagKeysToRemove.length > 0) {
2603
2812
  await props.organizationsClient.send(
2604
2813
  new UntagResourceCommand({
2605
- ResourceId: operation.accountId,
2814
+ ResourceId: props.operation.accountId,
2606
2815
  TagKeys: tagKeysToRemove
2607
2816
  })
2608
2817
  );
2609
2818
  }
2610
- props.logger.log(`Done: tags updated for "${operation.accountName}"`);
2819
+ props.logger.log(`Done: tags updated for "${props.operation.accountName}"`);
2611
2820
  return upsertAccountInWorkingState({
2612
2821
  workingState: props.state,
2613
2822
  account: {
2614
2823
  ...account,
2615
- tags: Object.entries(operation.tags).map(([key, value]) => ({
2824
+ tags: Object.entries(props.operation.tags).map(([key, value]) => ({
2616
2825
  key,
2617
2826
  value
2618
2827
  }))
2619
2828
  }
2620
2829
  });
2621
2830
  }
2622
- if (operation.kind === "updateAccountName") {
2831
+ if (props.operation.kind === "updateAccountName") {
2623
2832
  props.logger.log(
2624
- `Renaming account (${operation.accountId}): "${operation.fromAccountName}" -> "${operation.toAccountName}"...`
2833
+ `Renaming account (${props.operation.accountId}): "${props.operation.fromAccountName}" -> "${props.operation.toAccountName}"...`
2625
2834
  );
2626
2835
  await props.accountClient.send(
2627
2836
  new PutAccountNameCommand({
2628
- AccountId: operation.accountId,
2629
- AccountName: operation.toAccountName
2837
+ AccountId: props.operation.accountId,
2838
+ AccountName: props.operation.toAccountName
2630
2839
  })
2631
2840
  );
2632
2841
  props.logger.log(
2633
- `Done: account "${operation.toAccountName}" (${operation.accountId})`
2842
+ `Done: account "${props.operation.toAccountName}" (${props.operation.accountId})`
2634
2843
  );
2635
- const account = props.state.organization.accountsById[operation.accountId];
2844
+ const account = props.state.organization.accountsById[props.operation.accountId];
2636
2845
  if (account == null) {
2637
2846
  throw new Error(
2638
- `Could not resolve account (${operation.accountId}) in working state after rename.`
2847
+ `Could not resolve account (${props.operation.accountId}) in working state after rename.`
2639
2848
  );
2640
2849
  }
2641
2850
  return upsertAccountInWorkingState({
2642
2851
  workingState: props.state,
2643
2852
  account: {
2644
2853
  ...account,
2645
- name: operation.toAccountName
2854
+ name: props.operation.toAccountName
2646
2855
  }
2647
2856
  });
2648
2857
  }
2649
- if (operation.kind === "removeAccount") {
2858
+ if (props.operation.kind === "removeAccount") {
2650
2859
  props.logger.log(
2651
- `Moving removed account "${operation.accountName}" (${operation.accountId}) to ${operation.toOuName}...`
2860
+ `Moving removed account "${props.operation.accountName}" (${props.operation.accountId}) to ${props.operation.toOuName}...`
2652
2861
  );
2653
2862
  await props.organizationsClient.send(
2654
2863
  new MoveAccountCommand2({
2655
- AccountId: operation.accountId,
2656
- SourceParentId: operation.fromOuId,
2657
- DestinationParentId: operation.toOuId
2864
+ AccountId: props.operation.accountId,
2865
+ SourceParentId: props.operation.fromOuId,
2866
+ DestinationParentId: props.operation.toOuId
2658
2867
  })
2659
2868
  );
2660
2869
  props.logger.log(
2661
- `Done: "${operation.accountName}" -> ${operation.toOuName}`
2870
+ `Done: "${props.operation.accountName}" -> ${props.operation.toOuName}`
2662
2871
  );
2663
2872
  return moveAccountInWorkingState({
2664
2873
  workingState: props.state,
2665
- accountId: operation.accountId,
2666
- parentId: operation.toOuId
2874
+ accountId: props.operation.accountId,
2875
+ parentId: props.operation.toOuId
2667
2876
  });
2668
2877
  }
2669
- if (operation.kind === "createIdcUser") {
2670
- props.logger.log(`Creating IdC user "${operation.userName}"...`);
2878
+ if (props.operation.kind === "createIdcUser") {
2879
+ props.logger.log(`Creating IdC user "${props.operation.userName}"...`);
2671
2880
  const response = await props.identityStoreClient.send(
2672
2881
  new CreateUserCommand({
2673
2882
  IdentityStoreId: props.state.identityCenter.identityStoreId,
2674
- UserName: operation.userName,
2675
- DisplayName: operation.displayName,
2883
+ UserName: props.operation.userName,
2884
+ DisplayName: props.operation.displayName,
2676
2885
  Name: buildIdentityStoreUserName({
2677
- userName: operation.userName,
2678
- displayName: operation.displayName
2886
+ userName: props.operation.userName,
2887
+ displayName: props.operation.displayName
2679
2888
  }),
2680
- Emails: operation.email.length > 0 ? [
2889
+ Emails: props.operation.email.length > 0 ? [
2681
2890
  {
2682
- Value: operation.email,
2891
+ Value: props.operation.email,
2683
2892
  Type: "Work",
2684
2893
  Primary: true
2685
2894
  }
@@ -2688,45 +2897,45 @@ async function executeOperation(props) {
2688
2897
  );
2689
2898
  if (response.UserId == null) {
2690
2899
  throw new Error(
2691
- `CreateUser for "${operation.userName}" returned no user id.`
2900
+ `CreateUser for "${props.operation.userName}" returned no user id.`
2692
2901
  );
2693
2902
  }
2694
- props.logger.log(`Done: "${operation.userName}"`);
2903
+ props.logger.log(`Done: "${props.operation.userName}"`);
2695
2904
  return upsertIdcUserInWorkingState({
2696
2905
  workingState: props.state,
2697
2906
  user: {
2698
2907
  userId: response.UserId,
2699
- userName: operation.userName,
2700
- displayName: operation.displayName,
2701
- email: operation.email
2908
+ userName: props.operation.userName,
2909
+ displayName: props.operation.displayName,
2910
+ email: props.operation.email
2702
2911
  }
2703
2912
  });
2704
2913
  }
2705
- if (operation.kind === "updateIdcUser") {
2914
+ if (props.operation.kind === "updateIdcUser") {
2706
2915
  const user = resolveUserByName({
2707
2916
  state: props.state,
2708
- userName: operation.userName
2917
+ userName: props.operation.userName
2709
2918
  });
2710
2919
  const operations = [];
2711
- if (user.displayName !== operation.displayName) {
2920
+ if (user.displayName !== props.operation.displayName) {
2712
2921
  operations.push({
2713
2922
  AttributePath: "displayName",
2714
- AttributeValue: operation.displayName
2923
+ AttributeValue: props.operation.displayName
2715
2924
  });
2716
2925
  operations.push({
2717
2926
  AttributePath: "name",
2718
2927
  AttributeValue: buildIdentityStoreUserName({
2719
- userName: operation.userName,
2720
- displayName: operation.displayName
2928
+ userName: props.operation.userName,
2929
+ displayName: props.operation.displayName
2721
2930
  })
2722
2931
  });
2723
2932
  }
2724
- if (user.email !== operation.email && operation.email.length > 0) {
2933
+ if (user.email !== props.operation.email && props.operation.email.length > 0) {
2725
2934
  operations.push({
2726
2935
  AttributePath: "emails",
2727
2936
  AttributeValue: [
2728
2937
  {
2729
- Value: operation.email,
2938
+ Value: props.operation.email,
2730
2939
  Type: "Work",
2731
2940
  Primary: true
2732
2941
  }
@@ -2736,7 +2945,7 @@ async function executeOperation(props) {
2736
2945
  if (operations.length === 0) {
2737
2946
  return props.state;
2738
2947
  }
2739
- props.logger.log(`Updating IdC user "${operation.userName}"...`);
2948
+ props.logger.log(`Updating IdC user "${props.operation.userName}"...`);
2740
2949
  await props.identityStoreClient.send(
2741
2950
  new UpdateUserCommand({
2742
2951
  IdentityStoreId: props.state.identityCenter.identityStoreId,
@@ -2744,65 +2953,65 @@ async function executeOperation(props) {
2744
2953
  Operations: operations
2745
2954
  })
2746
2955
  );
2747
- props.logger.log(`Done: "${operation.userName}"`);
2956
+ props.logger.log(`Done: "${props.operation.userName}"`);
2748
2957
  return upsertIdcUserInWorkingState({
2749
2958
  workingState: props.state,
2750
2959
  user: {
2751
2960
  ...user,
2752
- displayName: operation.displayName,
2753
- email: operation.email.length > 0 ? operation.email : user.email
2961
+ displayName: props.operation.displayName,
2962
+ email: props.operation.email.length > 0 ? props.operation.email : user.email
2754
2963
  }
2755
2964
  });
2756
2965
  }
2757
- if (operation.kind === "deleteIdcUser") {
2966
+ if (props.operation.kind === "deleteIdcUser") {
2758
2967
  const user = resolveUserByName({
2759
2968
  state: props.state,
2760
- userName: operation.userName
2969
+ userName: props.operation.userName
2761
2970
  });
2762
- props.logger.log(`Deleting IdC user "${operation.userName}"...`);
2971
+ props.logger.log(`Deleting IdC user "${props.operation.userName}"...`);
2763
2972
  await props.identityStoreClient.send(
2764
2973
  new DeleteUserCommand({
2765
2974
  IdentityStoreId: props.state.identityCenter.identityStoreId,
2766
2975
  UserId: user.userId
2767
2976
  })
2768
2977
  );
2769
- props.logger.log(`Done: "${operation.userName}"`);
2978
+ props.logger.log(`Done: "${props.operation.userName}"`);
2770
2979
  return removeIdcUserFromWorkingState({
2771
2980
  workingState: props.state,
2772
- userName: operation.userName
2981
+ userName: props.operation.userName
2773
2982
  });
2774
2983
  }
2775
- if (operation.kind === "createIdcGroup") {
2776
- props.logger.log(`Creating IdC group "${operation.groupDisplayName}"...`);
2984
+ if (props.operation.kind === "createIdcGroup") {
2985
+ props.logger.log(`Creating IdC group "${props.operation.groupDisplayName}"...`);
2777
2986
  const response = await props.identityStoreClient.send(
2778
2987
  new CreateGroupCommand({
2779
2988
  IdentityStoreId: props.state.identityCenter.identityStoreId,
2780
- DisplayName: operation.groupDisplayName,
2781
- Description: operation.description.trim().length > 0 ? operation.description : void 0
2989
+ DisplayName: props.operation.groupDisplayName,
2990
+ Description: props.operation.description.trim().length > 0 ? props.operation.description : void 0
2782
2991
  })
2783
2992
  );
2784
2993
  if (response.GroupId == null) {
2785
2994
  throw new Error(
2786
- `CreateGroup for "${operation.groupDisplayName}" returned no group id.`
2995
+ `CreateGroup for "${props.operation.groupDisplayName}" returned no group id.`
2787
2996
  );
2788
2997
  }
2789
- props.logger.log(`Done: "${operation.groupDisplayName}"`);
2998
+ props.logger.log(`Done: "${props.operation.groupDisplayName}"`);
2790
2999
  return upsertIdcGroupInWorkingState({
2791
3000
  workingState: props.state,
2792
3001
  group: {
2793
3002
  groupId: response.GroupId,
2794
- displayName: operation.groupDisplayName,
2795
- description: operation.description
3003
+ displayName: props.operation.groupDisplayName,
3004
+ description: props.operation.description
2796
3005
  }
2797
3006
  });
2798
3007
  }
2799
- if (operation.kind === "updateIdcGroupDescription") {
3008
+ if (props.operation.kind === "updateIdcGroupDescription") {
2800
3009
  const group = resolveGroupByDisplayName({
2801
3010
  state: props.state,
2802
- groupDisplayName: operation.groupDisplayName
3011
+ groupDisplayName: props.operation.groupDisplayName
2803
3012
  });
2804
3013
  props.logger.log(
2805
- `Updating IdC group description for "${operation.groupDisplayName}"...`
3014
+ `Updating IdC group description for "${props.operation.groupDisplayName}"...`
2806
3015
  );
2807
3016
  await props.identityStoreClient.send(
2808
3017
  new UpdateGroupCommand({
@@ -2811,46 +3020,46 @@ async function executeOperation(props) {
2811
3020
  Operations: [
2812
3021
  {
2813
3022
  AttributePath: "description",
2814
- AttributeValue: operation.description
3023
+ AttributeValue: props.operation.description
2815
3024
  }
2816
3025
  ]
2817
3026
  })
2818
3027
  );
2819
- props.logger.log(`Done: group "${operation.groupDisplayName}"`);
3028
+ props.logger.log(`Done: group "${props.operation.groupDisplayName}"`);
2820
3029
  return upsertIdcGroupInWorkingState({
2821
3030
  workingState: props.state,
2822
3031
  group: {
2823
3032
  ...group,
2824
- description: operation.description
3033
+ description: props.operation.description
2825
3034
  }
2826
3035
  });
2827
3036
  }
2828
- if (operation.kind === "deleteIdcGroup") {
3037
+ if (props.operation.kind === "deleteIdcGroup") {
2829
3038
  const group = resolveGroupByDisplayName({
2830
3039
  state: props.state,
2831
- groupDisplayName: operation.groupDisplayName
3040
+ groupDisplayName: props.operation.groupDisplayName
2832
3041
  });
2833
- props.logger.log(`Deleting IdC group "${operation.groupDisplayName}"...`);
3042
+ props.logger.log(`Deleting IdC group "${props.operation.groupDisplayName}"...`);
2834
3043
  await props.identityStoreClient.send(
2835
3044
  new DeleteGroupCommand({
2836
3045
  IdentityStoreId: props.state.identityCenter.identityStoreId,
2837
3046
  GroupId: group.groupId
2838
3047
  })
2839
3048
  );
2840
- props.logger.log(`Done: "${operation.groupDisplayName}"`);
3049
+ props.logger.log(`Done: "${props.operation.groupDisplayName}"`);
2841
3050
  return removeIdcGroupFromWorkingState({
2842
3051
  workingState: props.state,
2843
- groupDisplayName: operation.groupDisplayName
3052
+ groupDisplayName: props.operation.groupDisplayName
2844
3053
  });
2845
3054
  }
2846
- if (operation.kind === "addIdcGroupMembership") {
3055
+ if (props.operation.kind === "addIdcGroupMembership") {
2847
3056
  const resolvedMembership = resolveGroupMembershipDependencies({
2848
3057
  state: props.state,
2849
- groupDisplayName: operation.groupDisplayName,
2850
- userName: operation.userName
3058
+ groupDisplayName: props.operation.groupDisplayName,
3059
+ userName: props.operation.userName
2851
3060
  });
2852
3061
  props.logger.log(
2853
- `Adding user "${operation.userName}" to IdC group "${operation.groupDisplayName}"...`
3062
+ `Adding user "${props.operation.userName}" to IdC group "${props.operation.groupDisplayName}"...`
2854
3063
  );
2855
3064
  const response = await props.identityStoreClient.send(
2856
3065
  new CreateGroupMembershipCommand({
@@ -2863,11 +3072,11 @@ async function executeOperation(props) {
2863
3072
  );
2864
3073
  if (response.MembershipId == null) {
2865
3074
  throw new Error(
2866
- `CreateGroupMembership for group "${operation.groupDisplayName}" and user "${operation.userName}" returned no membership id.`
3075
+ `CreateGroupMembership for group "${props.operation.groupDisplayName}" and user "${props.operation.userName}" returned no membership id.`
2867
3076
  );
2868
3077
  }
2869
3078
  props.logger.log(
2870
- `Done: user "${operation.userName}" -> group "${operation.groupDisplayName}"`
3079
+ `Done: user "${props.operation.userName}" -> group "${props.operation.groupDisplayName}"`
2871
3080
  );
2872
3081
  return addGroupMembershipToWorkingState({
2873
3082
  workingState: props.state,
@@ -2878,93 +3087,94 @@ async function executeOperation(props) {
2878
3087
  }
2879
3088
  });
2880
3089
  }
2881
- if (operation.kind === "createIdcPermissionSet") {
3090
+ if (props.operation.kind === "createIdcPermissionSet") {
2882
3091
  props.logger.log(
2883
- `Creating IdC permission set "${operation.permissionSetName}"...`
3092
+ `Creating IdC permission set "${props.operation.permissionSetName}"...`
2884
3093
  );
2885
3094
  const response = await props.ssoAdminClient.send(
2886
3095
  new CreatePermissionSetCommand({
2887
3096
  InstanceArn: props.state.identityCenter.instanceArn,
2888
- Name: operation.permissionSetName,
2889
- Description: operation.description.length > 0 ? operation.description : void 0,
2890
- SessionDuration: operation.sessionDuration ?? void 0
3097
+ Name: props.operation.permissionSetName,
3098
+ Description: props.operation.description.length > 0 ? props.operation.description : void 0,
3099
+ SessionDuration: props.operation.sessionDuration ?? void 0
2891
3100
  })
2892
3101
  );
2893
3102
  const permissionSetArn = response.PermissionSet?.PermissionSetArn;
2894
3103
  if (permissionSetArn == null) {
2895
3104
  throw new Error(
2896
- `CreatePermissionSet for "${operation.permissionSetName}" returned no permission set arn.`
3105
+ `CreatePermissionSet for "${props.operation.permissionSetName}" returned no permission set arn.`
2897
3106
  );
2898
3107
  }
2899
- props.logger.log(`Done: "${operation.permissionSetName}"`);
3108
+ props.logger.log(`Done: "${props.operation.permissionSetName}"`);
2900
3109
  return upsertIdcPermissionSetInWorkingState({
2901
3110
  workingState: props.state,
2902
3111
  permissionSet: {
2903
3112
  permissionSetArn,
2904
- name: operation.permissionSetName,
2905
- description: operation.description,
2906
- sessionDuration: operation.sessionDuration,
3113
+ name: props.operation.permissionSetName,
3114
+ description: props.operation.description,
3115
+ sessionDuration: props.operation.sessionDuration,
2907
3116
  inlinePolicy: null,
2908
3117
  awsManagedPolicies: [],
2909
- customerManagedPolicies: []
3118
+ customerManagedPolicies: [],
3119
+ permissionsBoundary: null
2910
3120
  }
2911
3121
  });
2912
3122
  }
2913
- if (operation.kind === "updateIdcPermissionSetDescription") {
3123
+ if (props.operation.kind === "updateIdcPermissionSetDescription") {
2914
3124
  const permissionSet = resolvePermissionSetByName({
2915
3125
  state: props.state,
2916
- permissionSetName: operation.permissionSetName
3126
+ permissionSetName: props.operation.permissionSetName
2917
3127
  });
2918
3128
  props.logger.log(
2919
- `Updating IdC permission set description for "${operation.permissionSetName}"...`
3129
+ `Updating IdC permission set description for "${props.operation.permissionSetName}"...`
2920
3130
  );
2921
3131
  await props.ssoAdminClient.send(
2922
3132
  new UpdatePermissionSetCommand({
2923
3133
  InstanceArn: props.state.identityCenter.instanceArn,
2924
3134
  PermissionSetArn: permissionSet.permissionSetArn,
2925
- Description: operation.description.trim().length > 0 ? operation.description : void 0
3135
+ Description: props.operation.description.trim().length > 0 ? props.operation.description : void 0
2926
3136
  })
2927
3137
  );
2928
- props.logger.log(`Done: "${operation.permissionSetName}"`);
3138
+ props.logger.log(`Done: "${props.operation.permissionSetName}"`);
2929
3139
  return upsertIdcPermissionSetInWorkingState({
2930
3140
  workingState: props.state,
2931
3141
  permissionSet: {
2932
3142
  ...permissionSet,
2933
- description: operation.description
3143
+ description: props.operation.description
2934
3144
  }
2935
3145
  });
2936
3146
  }
2937
- if (operation.kind === "updateIdcPermissionSetSessionDuration") {
3147
+ if (props.operation.kind === "updateIdcPermissionSetSessionDuration") {
2938
3148
  const permissionSet = resolvePermissionSetByName({
2939
3149
  state: props.state,
2940
- permissionSetName: operation.permissionSetName
3150
+ permissionSetName: props.operation.permissionSetName
2941
3151
  });
2942
3152
  props.logger.log(
2943
- `Updating IdC permission set session duration for "${operation.permissionSetName}"...`
3153
+ `Updating IdC permission set session duration for "${props.operation.permissionSetName}"...`
2944
3154
  );
2945
3155
  await props.ssoAdminClient.send(
2946
3156
  new UpdatePermissionSetCommand({
2947
3157
  InstanceArn: props.state.identityCenter.instanceArn,
2948
3158
  PermissionSetArn: permissionSet.permissionSetArn,
2949
- SessionDuration: operation.sessionDuration ?? void 0
3159
+ SessionDuration: props.operation.sessionDuration ?? void 0
2950
3160
  })
2951
3161
  );
2952
- props.logger.log(`Done: "${operation.permissionSetName}"`);
3162
+ props.logger.log(`Done: "${props.operation.permissionSetName}"`);
2953
3163
  return upsertIdcPermissionSetInWorkingState({
2954
3164
  workingState: props.state,
2955
3165
  permissionSet: {
2956
3166
  ...permissionSet,
2957
- sessionDuration: operation.sessionDuration
3167
+ sessionDuration: props.operation.sessionDuration
2958
3168
  }
2959
3169
  });
2960
3170
  }
2961
- if (operation.kind === "deleteIdcPermissionSet") {
3171
+ if (props.operation.kind === "deleteIdcPermissionSet") {
2962
3172
  const permissionSet = resolvePermissionSetByName({
2963
3173
  state: props.state,
2964
- permissionSetName: operation.permissionSetName
3174
+ permissionSetName: props.operation.permissionSetName
2965
3175
  });
2966
3176
  props.logger.log(
2967
- `Deleting IdC permission set "${operation.permissionSetName}"...`
3177
+ `Deleting IdC permission set "${props.operation.permissionSetName}"...`
2968
3178
  );
2969
3179
  await props.ssoAdminClient.send(
2970
3180
  new DeletePermissionSetCommand({
@@ -2972,44 +3182,45 @@ async function executeOperation(props) {
2972
3182
  PermissionSetArn: permissionSet.permissionSetArn
2973
3183
  })
2974
3184
  );
2975
- props.logger.log(`Done: "${operation.permissionSetName}"`);
3185
+ props.logger.log(`Done: "${props.operation.permissionSetName}"`);
2976
3186
  return removeIdcPermissionSetFromWorkingState({
2977
3187
  workingState: props.state,
2978
- permissionSetName: operation.permissionSetName
3188
+ permissionSetName: props.operation.permissionSetName
2979
3189
  });
2980
3190
  }
2981
- if (operation.kind === "putIdcPermissionSetInlinePolicy") {
3191
+ if (props.operation.kind === "putIdcPermissionSetInlinePolicy") {
3192
+ const { inlinePolicy } = props.operation;
2982
3193
  const permissionSet = resolvePermissionSetByName({
2983
3194
  state: props.state,
2984
- permissionSetName: operation.permissionSetName
3195
+ permissionSetName: props.operation.permissionSetName
2985
3196
  });
2986
3197
  props.logger.log(
2987
- `Putting inline policy on IdC permission set "${operation.permissionSetName}"...`
3198
+ `Putting inline policy on IdC permission set "${props.operation.permissionSetName}"...`
2988
3199
  );
2989
3200
  await props.ssoAdminClient.send(
2990
3201
  new PutInlinePolicyToPermissionSetCommand({
2991
3202
  InstanceArn: props.state.identityCenter.instanceArn,
2992
3203
  PermissionSetArn: permissionSet.permissionSetArn,
2993
- InlinePolicy: operation.inlinePolicy
3204
+ InlinePolicy: inlinePolicy
2994
3205
  })
2995
3206
  );
2996
- props.logger.log(`Done: "${operation.permissionSetName}"`);
3207
+ props.logger.log(`Done: "${props.operation.permissionSetName}"`);
2997
3208
  return upsertPermissionSetPolicyState({
2998
3209
  state: props.state,
2999
- permissionSetName: operation.permissionSetName,
3210
+ permissionSetName: props.operation.permissionSetName,
3000
3211
  update: (currentPermissionSet) => ({
3001
3212
  ...currentPermissionSet,
3002
- inlinePolicy: operation.inlinePolicy
3213
+ inlinePolicy
3003
3214
  })
3004
3215
  });
3005
3216
  }
3006
- if (operation.kind === "deleteIdcPermissionSetInlinePolicy") {
3217
+ if (props.operation.kind === "deleteIdcPermissionSetInlinePolicy") {
3007
3218
  const permissionSet = resolvePermissionSetByName({
3008
3219
  state: props.state,
3009
- permissionSetName: operation.permissionSetName
3220
+ permissionSetName: props.operation.permissionSetName
3010
3221
  });
3011
3222
  props.logger.log(
3012
- `Deleting inline policy from IdC permission set "${operation.permissionSetName}"...`
3223
+ `Deleting inline policy from IdC permission set "${props.operation.permissionSetName}"...`
3013
3224
  );
3014
3225
  await props.ssoAdminClient.send(
3015
3226
  new DeleteInlinePolicyFromPermissionSetCommand({
@@ -3017,154 +3228,158 @@ async function executeOperation(props) {
3017
3228
  PermissionSetArn: permissionSet.permissionSetArn
3018
3229
  })
3019
3230
  );
3020
- props.logger.log(`Done: "${operation.permissionSetName}"`);
3231
+ props.logger.log(`Done: "${props.operation.permissionSetName}"`);
3021
3232
  return upsertPermissionSetPolicyState({
3022
3233
  state: props.state,
3023
- permissionSetName: operation.permissionSetName,
3234
+ permissionSetName: props.operation.permissionSetName,
3024
3235
  update: (currentPermissionSet) => ({
3025
3236
  ...currentPermissionSet,
3026
3237
  inlinePolicy: null
3027
3238
  })
3028
3239
  });
3029
3240
  }
3030
- if (operation.kind === "attachIdcManagedPolicyToPermissionSet") {
3241
+ if (props.operation.kind === "attachIdcManagedPolicyToPermissionSet") {
3242
+ const { managedPolicyArn } = props.operation;
3031
3243
  const permissionSet = resolvePermissionSetByName({
3032
3244
  state: props.state,
3033
- permissionSetName: operation.permissionSetName
3245
+ permissionSetName: props.operation.permissionSetName
3034
3246
  });
3035
3247
  props.logger.log(
3036
- `Attaching managed policy "${operation.managedPolicyArn}" to IdC permission set "${operation.permissionSetName}"...`
3248
+ `Attaching managed policy "${managedPolicyArn}" to IdC permission set "${props.operation.permissionSetName}"...`
3037
3249
  );
3038
3250
  await props.ssoAdminClient.send(
3039
3251
  new AttachManagedPolicyToPermissionSetCommand({
3040
3252
  InstanceArn: props.state.identityCenter.instanceArn,
3041
3253
  PermissionSetArn: permissionSet.permissionSetArn,
3042
- ManagedPolicyArn: operation.managedPolicyArn
3254
+ ManagedPolicyArn: managedPolicyArn
3043
3255
  })
3044
3256
  );
3045
- props.logger.log(`Done: "${operation.permissionSetName}"`);
3257
+ props.logger.log(`Done: "${props.operation.permissionSetName}"`);
3046
3258
  return upsertPermissionSetPolicyState({
3047
3259
  state: props.state,
3048
- permissionSetName: operation.permissionSetName,
3260
+ permissionSetName: props.operation.permissionSetName,
3049
3261
  update: (currentPermissionSet) => ({
3050
3262
  ...currentPermissionSet,
3051
3263
  awsManagedPolicies: [
3052
3264
  ...currentPermissionSet.awsManagedPolicies,
3053
- operation.managedPolicyArn
3265
+ managedPolicyArn
3054
3266
  ]
3055
3267
  })
3056
3268
  });
3057
3269
  }
3058
- if (operation.kind === "detachIdcManagedPolicyFromPermissionSet") {
3270
+ if (props.operation.kind === "detachIdcManagedPolicyFromPermissionSet") {
3271
+ const { managedPolicyArn } = props.operation;
3059
3272
  const permissionSet = resolvePermissionSetByName({
3060
3273
  state: props.state,
3061
- permissionSetName: operation.permissionSetName
3274
+ permissionSetName: props.operation.permissionSetName
3062
3275
  });
3063
3276
  props.logger.log(
3064
- `Detaching managed policy "${operation.managedPolicyArn}" from IdC permission set "${operation.permissionSetName}"...`
3277
+ `Detaching managed policy "${managedPolicyArn}" from IdC permission set "${props.operation.permissionSetName}"...`
3065
3278
  );
3066
3279
  await props.ssoAdminClient.send(
3067
3280
  new DetachManagedPolicyFromPermissionSetCommand({
3068
3281
  InstanceArn: props.state.identityCenter.instanceArn,
3069
3282
  PermissionSetArn: permissionSet.permissionSetArn,
3070
- ManagedPolicyArn: operation.managedPolicyArn
3283
+ ManagedPolicyArn: managedPolicyArn
3071
3284
  })
3072
3285
  );
3073
- props.logger.log(`Done: "${operation.permissionSetName}"`);
3286
+ props.logger.log(`Done: "${props.operation.permissionSetName}"`);
3074
3287
  return upsertPermissionSetPolicyState({
3075
3288
  state: props.state,
3076
- permissionSetName: operation.permissionSetName,
3289
+ permissionSetName: props.operation.permissionSetName,
3077
3290
  update: (currentPermissionSet) => ({
3078
3291
  ...currentPermissionSet,
3079
3292
  awsManagedPolicies: currentPermissionSet.awsManagedPolicies.filter(
3080
- (managedPolicyArn) => managedPolicyArn !== operation.managedPolicyArn
3293
+ (arn) => arn !== managedPolicyArn
3081
3294
  )
3082
3295
  })
3083
3296
  });
3084
3297
  }
3085
- if (operation.kind === "attachIdcCustomerManagedPolicyReferenceToPermissionSet") {
3298
+ if (props.operation.kind === "attachIdcCustomerManagedPolicyReferenceToPermissionSet") {
3299
+ const { customerManagedPolicyName, customerManagedPolicyPath } = props.operation;
3086
3300
  const permissionSet = resolvePermissionSetByName({
3087
3301
  state: props.state,
3088
- permissionSetName: operation.permissionSetName
3302
+ permissionSetName: props.operation.permissionSetName
3089
3303
  });
3090
3304
  props.logger.log(
3091
- `Attaching customer-managed policy "${operation.customerManagedPolicyPath}${operation.customerManagedPolicyName}" to IdC permission set "${operation.permissionSetName}"...`
3305
+ `Attaching customer-managed policy "${customerManagedPolicyPath}${customerManagedPolicyName}" to IdC permission set "${props.operation.permissionSetName}"...`
3092
3306
  );
3093
3307
  await props.ssoAdminClient.send(
3094
3308
  new AttachCustomerManagedPolicyReferenceToPermissionSetCommand({
3095
3309
  InstanceArn: props.state.identityCenter.instanceArn,
3096
3310
  PermissionSetArn: permissionSet.permissionSetArn,
3097
3311
  CustomerManagedPolicyReference: {
3098
- Name: operation.customerManagedPolicyName,
3099
- Path: operation.customerManagedPolicyPath
3312
+ Name: customerManagedPolicyName,
3313
+ Path: customerManagedPolicyPath
3100
3314
  }
3101
3315
  })
3102
3316
  );
3103
- props.logger.log(`Done: "${operation.permissionSetName}"`);
3317
+ props.logger.log(`Done: "${props.operation.permissionSetName}"`);
3104
3318
  return upsertPermissionSetPolicyState({
3105
3319
  state: props.state,
3106
- permissionSetName: operation.permissionSetName,
3320
+ permissionSetName: props.operation.permissionSetName,
3107
3321
  update: (currentPermissionSet) => ({
3108
3322
  ...currentPermissionSet,
3109
3323
  customerManagedPolicies: [
3110
3324
  ...currentPermissionSet.customerManagedPolicies,
3111
3325
  {
3112
- name: operation.customerManagedPolicyName,
3113
- path: operation.customerManagedPolicyPath
3326
+ name: customerManagedPolicyName,
3327
+ path: customerManagedPolicyPath
3114
3328
  }
3115
3329
  ]
3116
3330
  })
3117
3331
  });
3118
3332
  }
3119
- if (operation.kind === "detachIdcCustomerManagedPolicyReferenceFromPermissionSet") {
3333
+ if (props.operation.kind === "detachIdcCustomerManagedPolicyReferenceFromPermissionSet") {
3334
+ const { customerManagedPolicyName, customerManagedPolicyPath } = props.operation;
3120
3335
  const permissionSet = resolvePermissionSetByName({
3121
3336
  state: props.state,
3122
- permissionSetName: operation.permissionSetName
3337
+ permissionSetName: props.operation.permissionSetName
3123
3338
  });
3124
3339
  props.logger.log(
3125
- `Detaching customer-managed policy "${operation.customerManagedPolicyPath}${operation.customerManagedPolicyName}" from IdC permission set "${operation.permissionSetName}"...`
3340
+ `Detaching customer-managed policy "${customerManagedPolicyPath}${customerManagedPolicyName}" from IdC permission set "${props.operation.permissionSetName}"...`
3126
3341
  );
3127
3342
  await props.ssoAdminClient.send(
3128
3343
  new DetachCustomerManagedPolicyReferenceFromPermissionSetCommand({
3129
3344
  InstanceArn: props.state.identityCenter.instanceArn,
3130
3345
  PermissionSetArn: permissionSet.permissionSetArn,
3131
3346
  CustomerManagedPolicyReference: {
3132
- Name: operation.customerManagedPolicyName,
3133
- Path: operation.customerManagedPolicyPath
3347
+ Name: customerManagedPolicyName,
3348
+ Path: customerManagedPolicyPath
3134
3349
  }
3135
3350
  })
3136
3351
  );
3137
- props.logger.log(`Done: "${operation.permissionSetName}"`);
3352
+ props.logger.log(`Done: "${props.operation.permissionSetName}"`);
3138
3353
  return upsertPermissionSetPolicyState({
3139
3354
  state: props.state,
3140
- permissionSetName: operation.permissionSetName,
3355
+ permissionSetName: props.operation.permissionSetName,
3141
3356
  update: (currentPermissionSet) => ({
3142
3357
  ...currentPermissionSet,
3143
3358
  customerManagedPolicies: currentPermissionSet.customerManagedPolicies.filter(
3144
- (customerManagedPolicy) => customerManagedPolicy.name !== operation.customerManagedPolicyName || customerManagedPolicy.path !== operation.customerManagedPolicyPath
3359
+ (policy) => policy.name !== customerManagedPolicyName || policy.path !== customerManagedPolicyPath
3145
3360
  )
3146
3361
  })
3147
3362
  });
3148
3363
  }
3149
- if (operation.kind === "provisionIdcPermissionSet") {
3364
+ if (props.operation.kind === "provisionIdcPermissionSet") {
3150
3365
  const permissionSet = resolvePermissionSetByName({
3151
3366
  state: props.state,
3152
- permissionSetName: operation.permissionSetName
3367
+ permissionSetName: props.operation.permissionSetName
3153
3368
  });
3154
3369
  props.logger.log(
3155
- `Provisioning IdC permission set "${operation.permissionSetName}" to all provisioned accounts...`
3370
+ `Provisioning IdC permission set "${props.operation.permissionSetName}" to all provisioned accounts...`
3156
3371
  );
3157
3372
  const response = await props.ssoAdminClient.send(
3158
3373
  new ProvisionPermissionSetCommand({
3159
3374
  InstanceArn: props.state.identityCenter.instanceArn,
3160
3375
  PermissionSetArn: permissionSet.permissionSetArn,
3161
- TargetType: operation.targetScope
3376
+ TargetType: props.operation.targetScope
3162
3377
  })
3163
3378
  );
3164
3379
  const requestId = response.PermissionSetProvisioningStatus?.RequestId ?? void 0;
3165
3380
  if (requestId == null) {
3166
3381
  throw new Error(
3167
- `ProvisionPermissionSet for "${operation.permissionSetName}" returned no request id.`
3382
+ `ProvisionPermissionSet for "${props.operation.permissionSetName}" returned no request id.`
3168
3383
  );
3169
3384
  }
3170
3385
  await waitForPermissionSetProvisioningSuccess({
@@ -3174,16 +3389,63 @@ async function executeOperation(props) {
3174
3389
  requestId,
3175
3390
  timeoutInMs: props.runtime.permissionSetProvisioning.timeoutInMs,
3176
3391
  pollIntervalInMs: props.runtime.permissionSetProvisioning.pollIntervalInMs,
3177
- operationLabel: `"${operation.permissionSetName}"`
3392
+ operationLabel: `"${props.operation.permissionSetName}"`
3178
3393
  });
3179
- props.logger.log(`Done: "${operation.permissionSetName}"`);
3394
+ props.logger.log(`Done: "${props.operation.permissionSetName}"`);
3180
3395
  return props.state;
3181
3396
  }
3182
- if (operation.kind === "removeIdcGroupMembership") {
3397
+ if (props.operation.kind === "putIdcPermissionSetPermissionsBoundary") {
3398
+ const permissionSet = resolvePermissionSetByName({
3399
+ state: props.state,
3400
+ permissionSetName: props.operation.permissionSetName
3401
+ });
3402
+ props.logger.log(
3403
+ `Putting permissions boundary on IdC permission set "${props.operation.permissionSetName}"...`
3404
+ );
3405
+ const boundary = props.operation.permissionsBoundary;
3406
+ await props.ssoAdminClient.send(
3407
+ new PutPermissionsBoundaryToPermissionSetCommand({
3408
+ InstanceArn: props.state.identityCenter.instanceArn,
3409
+ PermissionSetArn: permissionSet.permissionSetArn,
3410
+ PermissionsBoundary: "managedPolicyArn" in boundary ? { ManagedPolicyArn: boundary.managedPolicyArn } : {
3411
+ CustomerManagedPolicyReference: {
3412
+ Name: boundary.customerManagedPolicyName,
3413
+ Path: boundary.customerManagedPolicyPath
3414
+ }
3415
+ }
3416
+ })
3417
+ );
3418
+ props.logger.log(`Done: "${props.operation.permissionSetName}"`);
3419
+ return upsertIdcPermissionSetInWorkingState({
3420
+ workingState: props.state,
3421
+ permissionSet: { ...permissionSet, permissionsBoundary: boundary }
3422
+ });
3423
+ }
3424
+ if (props.operation.kind === "deleteIdcPermissionSetPermissionsBoundary") {
3425
+ const permissionSet = resolvePermissionSetByName({
3426
+ state: props.state,
3427
+ permissionSetName: props.operation.permissionSetName
3428
+ });
3429
+ props.logger.log(
3430
+ `Deleting permissions boundary from IdC permission set "${props.operation.permissionSetName}"...`
3431
+ );
3432
+ await props.ssoAdminClient.send(
3433
+ new DeletePermissionsBoundaryFromPermissionSetCommand({
3434
+ InstanceArn: props.state.identityCenter.instanceArn,
3435
+ PermissionSetArn: permissionSet.permissionSetArn
3436
+ })
3437
+ );
3438
+ props.logger.log(`Done: "${props.operation.permissionSetName}"`);
3439
+ return upsertIdcPermissionSetInWorkingState({
3440
+ workingState: props.state,
3441
+ permissionSet: { ...permissionSet, permissionsBoundary: null }
3442
+ });
3443
+ }
3444
+ if (props.operation.kind === "removeIdcGroupMembership") {
3183
3445
  const resolvedMembership = resolveGroupMembershipDependencies({
3184
3446
  state: props.state,
3185
- groupDisplayName: operation.groupDisplayName,
3186
- userName: operation.userName
3447
+ groupDisplayName: props.operation.groupDisplayName,
3448
+ userName: props.operation.userName
3187
3449
  });
3188
3450
  const membershipId = await resolveGroupMembershipId({
3189
3451
  state: props.state,
@@ -3192,7 +3454,7 @@ async function executeOperation(props) {
3192
3454
  userId: resolvedMembership.userId
3193
3455
  });
3194
3456
  props.logger.log(
3195
- `Removing user "${operation.userName}" from IdC group "${operation.groupDisplayName}"...`
3457
+ `Removing user "${props.operation.userName}" from IdC group "${props.operation.groupDisplayName}"...`
3196
3458
  );
3197
3459
  await props.identityStoreClient.send(
3198
3460
  new DeleteGroupMembershipCommand({
@@ -3201,7 +3463,7 @@ async function executeOperation(props) {
3201
3463
  })
3202
3464
  );
3203
3465
  props.logger.log(
3204
- `Done: user "${operation.userName}" x group "${operation.groupDisplayName}"`
3466
+ `Done: user "${props.operation.userName}" x group "${props.operation.groupDisplayName}"`
3205
3467
  );
3206
3468
  return removeGroupMembershipFromWorkingState({
3207
3469
  workingState: props.state,
@@ -3211,21 +3473,21 @@ async function executeOperation(props) {
3211
3473
  }
3212
3474
  });
3213
3475
  }
3214
- if (operation.kind === "grantIdcAccountAssignment") {
3476
+ if (props.operation.kind === "grantIdcAccountAssignment") {
3215
3477
  const resolvedAssignment = resolveAssignmentDependencies({
3216
3478
  state: props.state,
3217
- accountName: operation.accountName,
3218
- permissionSetName: operation.permissionSetName,
3219
- principalType: operation.principalType,
3220
- principalName: operation.principalName
3479
+ accountName: props.operation.accountName,
3480
+ permissionSetName: props.operation.permissionSetName,
3481
+ principalType: props.operation.principalType,
3482
+ principalName: props.operation.principalName
3221
3483
  });
3222
3484
  props.logger.log(
3223
- `Granting IdC assignment "${operation.permissionSetName}" to ${formatPrincipalLabel(
3485
+ `Granting IdC assignment "${props.operation.permissionSetName}" to ${formatPrincipalLabel(
3224
3486
  {
3225
- principalType: operation.principalType,
3226
- principalName: operation.principalName
3487
+ principalType: props.operation.principalType,
3488
+ principalName: props.operation.principalName
3227
3489
  }
3228
- )} on "${operation.accountName}"...`
3490
+ )} on "${props.operation.accountName}"...`
3229
3491
  );
3230
3492
  const response = await props.ssoAdminClient.send(
3231
3493
  new CreateAccountAssignmentCommand({
@@ -3240,7 +3502,7 @@ async function executeOperation(props) {
3240
3502
  const requestId = response.AccountAssignmentCreationStatus?.RequestId;
3241
3503
  if (requestId == null) {
3242
3504
  throw new Error(
3243
- `CreateAccountAssignment for "${operation.permissionSetName}" on "${operation.accountName}" returned no request id.`
3505
+ `CreateAccountAssignment for "${props.operation.permissionSetName}" on "${props.operation.accountName}" returned no request id.`
3244
3506
  );
3245
3507
  }
3246
3508
  await waitForAccountAssignmentCreationSuccess({
@@ -3250,10 +3512,10 @@ async function executeOperation(props) {
3250
3512
  requestId,
3251
3513
  timeoutInMs: props.runtime.accountAssignment.timeoutInMs,
3252
3514
  pollIntervalInMs: props.runtime.accountAssignment.pollIntervalInMs,
3253
- operationLabel: `"${operation.permissionSetName}" on "${operation.accountName}"`
3515
+ operationLabel: `"${props.operation.permissionSetName}" on "${props.operation.accountName}"`
3254
3516
  });
3255
3517
  props.logger.log(
3256
- `Done: "${operation.permissionSetName}" -> "${operation.accountName}"`
3518
+ `Done: "${props.operation.permissionSetName}" -> "${props.operation.accountName}"`
3257
3519
  );
3258
3520
  return addAccountAssignmentToWorkingState({
3259
3521
  workingState: props.state,
@@ -3265,21 +3527,21 @@ async function executeOperation(props) {
3265
3527
  }
3266
3528
  });
3267
3529
  }
3268
- if (operation.kind === "revokeIdcAccountAssignment") {
3530
+ if (props.operation.kind === "revokeIdcAccountAssignment") {
3269
3531
  const resolvedAssignment = resolveAssignmentDependencies({
3270
3532
  state: props.state,
3271
- accountName: operation.accountName,
3272
- permissionSetName: operation.permissionSetName,
3273
- principalType: operation.principalType,
3274
- principalName: operation.principalName
3533
+ accountName: props.operation.accountName,
3534
+ permissionSetName: props.operation.permissionSetName,
3535
+ principalType: props.operation.principalType,
3536
+ principalName: props.operation.principalName
3275
3537
  });
3276
3538
  props.logger.log(
3277
- `Revoking IdC assignment "${operation.permissionSetName}" from ${formatPrincipalLabel(
3539
+ `Revoking IdC assignment "${props.operation.permissionSetName}" from ${formatPrincipalLabel(
3278
3540
  {
3279
- principalType: operation.principalType,
3280
- principalName: operation.principalName
3541
+ principalType: props.operation.principalType,
3542
+ principalName: props.operation.principalName
3281
3543
  }
3282
- )} on "${operation.accountName}"...`
3544
+ )} on "${props.operation.accountName}"...`
3283
3545
  );
3284
3546
  const response = await props.ssoAdminClient.send(
3285
3547
  new DeleteAccountAssignmentCommand({
@@ -3294,7 +3556,7 @@ async function executeOperation(props) {
3294
3556
  const requestId = response.AccountAssignmentDeletionStatus?.RequestId;
3295
3557
  if (requestId == null) {
3296
3558
  throw new Error(
3297
- `DeleteAccountAssignment for "${operation.permissionSetName}" on "${operation.accountName}" returned no request id.`
3559
+ `DeleteAccountAssignment for "${props.operation.permissionSetName}" on "${props.operation.accountName}" returned no request id.`
3298
3560
  );
3299
3561
  }
3300
3562
  await waitForAccountAssignmentDeletionSuccess({
@@ -3304,10 +3566,10 @@ async function executeOperation(props) {
3304
3566
  requestId,
3305
3567
  timeoutInMs: props.runtime.accountAssignment.timeoutInMs,
3306
3568
  pollIntervalInMs: props.runtime.accountAssignment.pollIntervalInMs,
3307
- operationLabel: `"${operation.permissionSetName}" on "${operation.accountName}"`
3569
+ operationLabel: `"${props.operation.permissionSetName}" on "${props.operation.accountName}"`
3308
3570
  });
3309
3571
  props.logger.log(
3310
- `Done: "${operation.permissionSetName}" x "${operation.accountName}"`
3572
+ `Done: "${props.operation.permissionSetName}" x "${props.operation.accountName}"`
3311
3573
  );
3312
3574
  return removeAccountAssignmentFromWorkingState({
3313
3575
  workingState: props.state,
@@ -3319,160 +3581,169 @@ async function executeOperation(props) {
3319
3581
  }
3320
3582
  });
3321
3583
  }
3322
- if (operation.kind === "createOrgPolicy") {
3584
+ if (props.operation.kind === "createOrgPolicy") {
3323
3585
  props.logger.log(
3324
- `Creating org policy "${operation.policyName}" (${operation.policyType})...`
3586
+ `Creating org policy "${props.operation.policyName}" (${props.operation.policyType})...`
3325
3587
  );
3326
3588
  const response = await props.organizationsClient.send(
3327
3589
  new CreatePolicyCommand({
3328
- Name: operation.policyName,
3329
- Description: operation.description.length > 0 ? operation.description : void 0,
3330
- Content: operation.content,
3331
- Type: operation.policyType
3590
+ Name: props.operation.policyName,
3591
+ Description: props.operation.description.length > 0 ? props.operation.description : void 0,
3592
+ Content: props.operation.content,
3593
+ Type: props.operation.policyType
3332
3594
  })
3333
3595
  );
3334
3596
  const policy = response.Policy?.PolicySummary;
3335
3597
  if (policy?.Id == null || policy.Arn == null) {
3336
3598
  throw new Error(
3337
- `CreatePolicy for "${operation.policyName}" returned incomplete data.`
3599
+ `CreatePolicy for "${props.operation.policyName}" returned incomplete data.`
3338
3600
  );
3339
3601
  }
3340
- props.logger.log(`Done: "${operation.policyName}"`);
3602
+ props.logger.log(`Done: "${props.operation.policyName}"`);
3341
3603
  return upsertOrgPolicyInWorkingState({
3342
3604
  workingState: props.state,
3343
3605
  policy: {
3344
3606
  id: policy.Id,
3345
3607
  arn: policy.Arn,
3346
- name: operation.policyName,
3347
- description: operation.description,
3348
- type: operation.policyType,
3349
- content: operation.content
3608
+ name: props.operation.policyName,
3609
+ description: props.operation.description,
3610
+ type: props.operation.policyType,
3611
+ content: props.operation.content
3350
3612
  }
3351
3613
  });
3352
3614
  }
3353
- if (operation.kind === "updateOrgPolicyContent") {
3354
- props.logger.log(`Updating org policy content "${operation.policyName}"...`);
3615
+ if (props.operation.kind === "updateOrgPolicyContent") {
3616
+ props.logger.log(
3617
+ `Updating org policy content "${props.operation.policyName}"...`
3618
+ );
3355
3619
  await props.organizationsClient.send(
3356
3620
  new UpdatePolicyCommand({
3357
- PolicyId: operation.policyId,
3358
- Content: operation.content
3621
+ PolicyId: props.operation.policyId,
3622
+ Content: props.operation.content
3359
3623
  })
3360
3624
  );
3361
- props.logger.log(`Done: "${operation.policyName}"`);
3362
- const currentPolicy = props.state.organization.policiesById[operation.policyId];
3625
+ props.logger.log(`Done: "${props.operation.policyName}"`);
3626
+ const currentPolicy = props.state.organization.policiesById[props.operation.policyId];
3363
3627
  if (currentPolicy == null) {
3364
3628
  return props.state;
3365
3629
  }
3366
3630
  return upsertOrgPolicyInWorkingState({
3367
3631
  workingState: props.state,
3368
- policy: { ...currentPolicy, content: operation.content }
3632
+ policy: { ...currentPolicy, content: props.operation.content }
3369
3633
  });
3370
3634
  }
3371
- if (operation.kind === "updateOrgPolicyDescription") {
3635
+ if (props.operation.kind === "updateOrgPolicyDescription") {
3372
3636
  props.logger.log(
3373
- `Updating org policy description "${operation.policyName}"...`
3637
+ `Updating org policy description "${props.operation.policyName}"...`
3374
3638
  );
3375
3639
  await props.organizationsClient.send(
3376
3640
  new UpdatePolicyCommand({
3377
- PolicyId: operation.policyId,
3378
- Description: operation.description
3641
+ PolicyId: props.operation.policyId,
3642
+ Description: props.operation.description
3379
3643
  })
3380
3644
  );
3381
- props.logger.log(`Done: "${operation.policyName}"`);
3382
- const currentPolicy = props.state.organization.policiesById[operation.policyId];
3645
+ props.logger.log(`Done: "${props.operation.policyName}"`);
3646
+ const currentPolicy = props.state.organization.policiesById[props.operation.policyId];
3383
3647
  if (currentPolicy == null) {
3384
3648
  return props.state;
3385
3649
  }
3386
3650
  return upsertOrgPolicyInWorkingState({
3387
3651
  workingState: props.state,
3388
- policy: { ...currentPolicy, description: operation.description }
3652
+ policy: { ...currentPolicy, description: props.operation.description }
3389
3653
  });
3390
3654
  }
3391
- if (operation.kind === "attachOrgPolicy") {
3655
+ if (props.operation.kind === "attachOrgPolicy") {
3392
3656
  props.logger.log(
3393
- `Attaching org policy "${operation.policyName}" to "${operation.targetName}"...`
3657
+ `Attaching org policy "${props.operation.policyName}" to "${props.operation.targetName}"...`
3394
3658
  );
3395
3659
  const resolvedPolicyId = resolvePolicyId({
3396
3660
  state: props.state,
3397
- policyId: operation.policyId,
3398
- policyName: operation.policyName
3661
+ policyId: props.operation.policyId,
3662
+ policyName: props.operation.policyName
3399
3663
  });
3400
3664
  await props.organizationsClient.send(
3401
3665
  new AttachPolicyCommand({
3402
3666
  PolicyId: resolvedPolicyId,
3403
- TargetId: operation.targetId
3667
+ TargetId: props.operation.targetId
3404
3668
  })
3405
3669
  );
3406
- props.logger.log(`Done: "${operation.policyName}" -> "${operation.targetName}"`);
3407
- const targetType = operation.targetId === props.context.organization.rootId ? "ROOT" : props.state.organization.organizationalUnitsById[operation.targetId] != null ? "ORGANIZATIONAL_UNIT" : "ACCOUNT";
3670
+ props.logger.log(
3671
+ `Done: "${props.operation.policyName}" -> "${props.operation.targetName}"`
3672
+ );
3673
+ const targetType = props.operation.targetId === props.context.organization.rootId ? "ROOT" : props.state.organization.organizationalUnitsById[props.operation.targetId] != null ? "ORGANIZATIONAL_UNIT" : "ACCOUNT";
3408
3674
  return addOrgPolicyAttachmentToWorkingState({
3409
3675
  workingState: props.state,
3410
3676
  attachment: {
3411
3677
  policyId: resolvedPolicyId,
3412
- targetId: operation.targetId,
3678
+ targetId: props.operation.targetId,
3413
3679
  targetType
3414
3680
  }
3415
3681
  });
3416
3682
  }
3417
- if (operation.kind === "detachOrgPolicy") {
3683
+ if (props.operation.kind === "detachOrgPolicy") {
3418
3684
  props.logger.log(
3419
- `Detaching org policy "${operation.policyName}" from "${operation.targetName}"...`
3685
+ `Detaching org policy "${props.operation.policyName}" from "${props.operation.targetName}"...`
3420
3686
  );
3421
3687
  await props.organizationsClient.send(
3422
3688
  new DetachPolicyCommand({
3423
- PolicyId: operation.policyId,
3424
- TargetId: operation.targetId
3689
+ PolicyId: props.operation.policyId,
3690
+ TargetId: props.operation.targetId
3425
3691
  })
3426
3692
  );
3427
- props.logger.log(`Done: "${operation.policyName}" x "${operation.targetName}"`);
3693
+ props.logger.log(
3694
+ `Done: "${props.operation.policyName}" x "${props.operation.targetName}"`
3695
+ );
3428
3696
  return removeOrgPolicyAttachmentFromWorkingState({
3429
3697
  workingState: props.state,
3430
- policyId: operation.policyId,
3431
- targetId: operation.targetId
3698
+ policyId: props.operation.policyId,
3699
+ targetId: props.operation.targetId
3432
3700
  });
3433
3701
  }
3434
- if (operation.kind === "deleteOrgPolicy") {
3435
- props.logger.log(`Deleting org policy "${operation.policyName}"...`);
3702
+ if (props.operation.kind === "deleteOrgPolicy") {
3703
+ props.logger.log(`Deleting org policy "${props.operation.policyName}"...`);
3436
3704
  await props.organizationsClient.send(
3437
- new DeletePolicyCommand({ PolicyId: operation.policyId })
3705
+ new DeletePolicyCommand({ PolicyId: props.operation.policyId })
3438
3706
  );
3439
- props.logger.log(`Done: "${operation.policyName}"`);
3707
+ props.logger.log(`Done: "${props.operation.policyName}"`);
3440
3708
  return removeOrgPolicyFromWorkingState({
3441
3709
  workingState: props.state,
3442
- policyId: operation.policyId
3710
+ policyId: props.operation.policyId
3443
3711
  });
3444
3712
  }
3445
- if (operation.kind === "putAlternateContact") {
3713
+ if (props.operation.kind === "putAlternateContact") {
3714
+ const { contactType } = props.operation;
3446
3715
  props.logger.log(
3447
- `Setting ${operation.contactType} alternate contact for "${operation.accountName}" (${operation.accountId})...`
3716
+ `Setting ${contactType} alternate contact for "${props.operation.accountName}" (${props.operation.accountId})...`
3448
3717
  );
3449
3718
  await props.accountClient.send(
3450
3719
  new PutAlternateContactCommand({
3451
- AccountId: operation.accountId,
3452
- AlternateContactType: operation.contactType,
3453
- Name: operation.name,
3454
- EmailAddress: operation.email,
3455
- PhoneNumber: operation.phone,
3456
- Title: operation.title
3720
+ AccountId: props.operation.accountId,
3721
+ AlternateContactType: contactType,
3722
+ Name: props.operation.name,
3723
+ EmailAddress: props.operation.email,
3724
+ PhoneNumber: props.operation.phone,
3725
+ Title: props.operation.title
3457
3726
  })
3458
3727
  );
3459
- props.logger.log(`Done: ${operation.contactType} contact for "${operation.accountName}"`);
3460
- const account = props.state.organization.accountsById[operation.accountId];
3728
+ props.logger.log(
3729
+ `Done: ${contactType} contact for "${props.operation.accountName}"`
3730
+ );
3731
+ const account = props.state.organization.accountsById[props.operation.accountId];
3461
3732
  if (account == null) {
3462
3733
  throw new Error(
3463
- `Could not resolve account (${operation.accountId}) in working state.`
3734
+ `Could not resolve account (${props.operation.accountId}) in working state.`
3464
3735
  );
3465
3736
  }
3466
3737
  const updatedContacts = [
3467
3738
  ...(account.alternateContacts ?? []).filter(
3468
- (c) => c.contactType !== operation.contactType
3739
+ (c) => c.contactType !== contactType
3469
3740
  ),
3470
3741
  {
3471
- contactType: operation.contactType,
3472
- name: operation.name,
3473
- email: operation.email,
3474
- phone: operation.phone,
3475
- title: operation.title
3742
+ contactType,
3743
+ name: props.operation.name,
3744
+ email: props.operation.email,
3745
+ phone: props.operation.phone,
3746
+ title: props.operation.title
3476
3747
  }
3477
3748
  ];
3478
3749
  return upsertAccountInWorkingState({
@@ -3480,21 +3751,24 @@ async function executeOperation(props) {
3480
3751
  account: { ...account, alternateContacts: updatedContacts }
3481
3752
  });
3482
3753
  }
3483
- if (operation.kind === "deleteAlternateContact") {
3754
+ if (props.operation.kind === "deleteAlternateContact") {
3755
+ const { contactType } = props.operation;
3484
3756
  props.logger.log(
3485
- `Deleting ${operation.contactType} alternate contact for "${operation.accountName}" (${operation.accountId})...`
3757
+ `Deleting ${contactType} alternate contact for "${props.operation.accountName}" (${props.operation.accountId})...`
3486
3758
  );
3487
3759
  await props.accountClient.send(
3488
3760
  new DeleteAlternateContactCommand({
3489
- AccountId: operation.accountId,
3490
- AlternateContactType: operation.contactType
3761
+ AccountId: props.operation.accountId,
3762
+ AlternateContactType: contactType
3491
3763
  })
3492
3764
  );
3493
- props.logger.log(`Done: removed ${operation.contactType} contact for "${operation.accountName}"`);
3494
- const account = props.state.organization.accountsById[operation.accountId];
3765
+ props.logger.log(
3766
+ `Done: removed ${contactType} contact for "${props.operation.accountName}"`
3767
+ );
3768
+ const account = props.state.organization.accountsById[props.operation.accountId];
3495
3769
  if (account == null) {
3496
3770
  throw new Error(
3497
- `Could not resolve account (${operation.accountId}) in working state.`
3771
+ `Could not resolve account (${props.operation.accountId}) in working state.`
3498
3772
  );
3499
3773
  }
3500
3774
  return upsertAccountInWorkingState({
@@ -3502,20 +3776,20 @@ async function executeOperation(props) {
3502
3776
  account: {
3503
3777
  ...account,
3504
3778
  alternateContacts: (account.alternateContacts ?? []).filter(
3505
- (c) => c.contactType !== operation.contactType
3779
+ (c) => c.contactType !== contactType
3506
3780
  )
3507
3781
  }
3508
3782
  });
3509
3783
  }
3510
- if (operation.kind === "setIdcAccessControlAttributes") {
3784
+ if (props.operation.kind === "setIdcAccessControlAttributes") {
3511
3785
  props.logger.log(
3512
- `Setting IdC access control attributes (${operation.attributes.length} attribute(s))...`
3786
+ `Setting IdC access control attributes (${props.operation.attributes.length} attribute(s))...`
3513
3787
  );
3514
3788
  await props.ssoAdminClient.send(
3515
3789
  new UpdateInstanceAccessControlAttributeConfigurationCommand({
3516
3790
  InstanceArn: props.state.identityCenter.instanceArn,
3517
3791
  InstanceAccessControlAttributeConfiguration: {
3518
- AccessControlAttributes: operation.attributes.map((attr) => ({
3792
+ AccessControlAttributes: props.operation.attributes.map((attr) => ({
3519
3793
  Key: attr.key,
3520
3794
  Value: { Source: attr.source }
3521
3795
  }))
@@ -3527,11 +3801,51 @@ async function executeOperation(props) {
3527
3801
  ...props.state,
3528
3802
  identityCenter: {
3529
3803
  ...props.state.identityCenter,
3530
- accessControlAttributes: operation.attributes
3804
+ accessControlAttributes: props.operation.attributes
3531
3805
  }
3532
3806
  };
3533
3807
  }
3534
- assertUnreachable(operation, "Unsupported operation kind in apply.");
3808
+ if (props.operation.kind === "registerDelegatedAdministrator") {
3809
+ props.logger.log(
3810
+ `Registering delegated administrator "${props.operation.accountName}" (${props.operation.accountId}) for ${props.operation.servicePrincipal}...`
3811
+ );
3812
+ await props.organizationsClient.send(
3813
+ new RegisterDelegatedAdministratorCommand({
3814
+ AccountId: props.operation.accountId,
3815
+ ServicePrincipal: props.operation.servicePrincipal
3816
+ })
3817
+ );
3818
+ props.logger.log(
3819
+ `Done: "${props.operation.accountName}" for ${props.operation.servicePrincipal}`
3820
+ );
3821
+ return upsertDelegatedAdministratorInWorkingState({
3822
+ workingState: props.state,
3823
+ delegatedAdministrator: {
3824
+ accountId: props.operation.accountId,
3825
+ servicePrincipal: props.operation.servicePrincipal
3826
+ }
3827
+ });
3828
+ }
3829
+ if (props.operation.kind === "deregisterDelegatedAdministrator") {
3830
+ props.logger.log(
3831
+ `Deregistering delegated administrator "${props.operation.accountName}" (${props.operation.accountId}) for ${props.operation.servicePrincipal}...`
3832
+ );
3833
+ await props.organizationsClient.send(
3834
+ new DeregisterDelegatedAdministratorCommand({
3835
+ AccountId: props.operation.accountId,
3836
+ ServicePrincipal: props.operation.servicePrincipal
3837
+ })
3838
+ );
3839
+ props.logger.log(
3840
+ `Done: removed "${props.operation.accountName}" for ${props.operation.servicePrincipal}`
3841
+ );
3842
+ return removeDelegatedAdministratorFromWorkingState({
3843
+ workingState: props.state,
3844
+ accountId: props.operation.accountId,
3845
+ servicePrincipal: props.operation.servicePrincipal
3846
+ });
3847
+ }
3848
+ assertUnreachable(props.operation, "Unsupported operation kind in apply.");
3535
3849
  }
3536
3850
  function resolveAssignmentDependencies(props) {
3537
3851
  const account = props.state.organization.accountsByName[props.accountName];
@@ -3591,6 +3905,20 @@ function resolveGroupByDisplayName(props) {
3591
3905
  }
3592
3906
  return group;
3593
3907
  }
3908
+ function resolveOrganizationalUnitId(props) {
3909
+ if (props.organizationalUnitId !== "__pending_creation__") {
3910
+ return props.organizationalUnitId;
3911
+ }
3912
+ const ou = Object.values(
3913
+ props.state.organization.organizationalUnitsById
3914
+ ).find((ou2) => ou2.name === props.organizationalUnitName);
3915
+ if (ou == null) {
3916
+ throw new Error(
3917
+ `Could not resolve OU "${props.organizationalUnitName}" in working state.`
3918
+ );
3919
+ }
3920
+ return ou.id;
3921
+ }
3594
3922
  function resolvePolicyId(props) {
3595
3923
  if (props.policyId !== "__pending_creation__") return props.policyId;
3596
3924
  const policy = props.state.organization.policiesByName[props.policyName];