@beesolve/aws-accounts 1.2.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.
@@ -7,12 +7,14 @@ import {
7
7
  AttachPolicyCommand,
8
8
  CreateOrganizationalUnitCommand,
9
9
  CreatePolicyCommand,
10
+ DeregisterDelegatedAdministratorCommand,
10
11
  DeleteOrganizationalUnitCommand,
11
12
  DeletePolicyCommand,
12
13
  DetachPolicyCommand,
13
14
  ListAccountsForParentCommand,
14
15
  ListOrganizationalUnitsForParentCommand,
15
16
  MoveAccountCommand,
17
+ RegisterDelegatedAdministratorCommand,
16
18
  TagResourceCommand,
17
19
  UntagResourceCommand,
18
20
  UpdateOrganizationalUnitCommand,
@@ -36,6 +38,7 @@ import {
36
38
  CreatePermissionSetCommand,
37
39
  DeleteAccountAssignmentCommand,
38
40
  DeleteInlinePolicyFromPermissionSetCommand,
41
+ DeletePermissionsBoundaryFromPermissionSetCommand,
39
42
  DeletePermissionSetCommand,
40
43
  DescribeAccountAssignmentCreationStatusCommand,
41
44
  DescribeAccountAssignmentDeletionStatusCommand,
@@ -44,6 +47,7 @@ import {
44
47
  DetachManagedPolicyFromPermissionSetCommand,
45
48
  ProvisionPermissionSetCommand,
46
49
  PutInlinePolicyToPermissionSetCommand,
50
+ PutPermissionsBoundaryToPermissionSetCommand,
47
51
  UpdateInstanceAccessControlAttributeConfigurationCommand,
48
52
  UpdatePermissionSetCommand
49
53
  } from "@aws-sdk/client-sso-admin";
@@ -56,6 +60,7 @@ import {
56
60
  createGroupMembershipKey,
57
61
  moveAccountInWorkingState,
58
62
  removeAccountAssignmentFromWorkingState,
63
+ removeDelegatedAdministratorFromWorkingState,
59
64
  removeGroupMembershipFromWorkingState,
60
65
  removeIdcGroupFromWorkingState,
61
66
  removeIdcPermissionSetFromWorkingState,
@@ -64,6 +69,7 @@ import {
64
69
  removeOrgPolicyAttachmentFromWorkingState,
65
70
  removeOrgPolicyFromWorkingState,
66
71
  renameOrganizationalUnitInWorkingState,
72
+ upsertDelegatedAdministratorInWorkingState,
67
73
  upsertIdcGroupInWorkingState,
68
74
  upsertIdcPermissionSetInWorkingState,
69
75
  upsertIdcUserInWorkingState,
@@ -72,39 +78,38 @@ import {
72
78
  upsertOrgPolicyInWorkingState
73
79
  } from "./state.js";
74
80
  async function executeOperation(props) {
75
- const operation = props.operation;
76
- if (operation.kind === "moveAccount") {
81
+ if (props.operation.kind === "moveAccount") {
77
82
  props.logger.log(
78
- `Moving "${operation.accountName}" (${operation.accountId}): ${operation.fromOuName} -> ${operation.toOuName}`
83
+ `Moving "${props.operation.accountName}" (${props.operation.accountId}): ${props.operation.fromOuName} -> ${props.operation.toOuName}`
79
84
  );
80
85
  await props.organizationsClient.send(
81
86
  new MoveAccountCommand({
82
- AccountId: operation.accountId,
83
- SourceParentId: operation.fromOuId,
84
- DestinationParentId: operation.toOuId
87
+ AccountId: props.operation.accountId,
88
+ SourceParentId: props.operation.fromOuId,
89
+ DestinationParentId: props.operation.toOuId
85
90
  })
86
91
  );
87
- props.logger.log(`Done: "${operation.accountName}"`);
92
+ props.logger.log(`Done: "${props.operation.accountName}"`);
88
93
  return moveAccountInWorkingState({
89
94
  workingState: props.state,
90
- accountId: operation.accountId,
91
- parentId: operation.toOuId
95
+ accountId: props.operation.accountId,
96
+ parentId: props.operation.toOuId
92
97
  });
93
98
  }
94
- if (operation.kind === "createOu") {
99
+ if (props.operation.kind === "createOu") {
95
100
  props.logger.log(
96
- `Creating OU "${operation.ouName}" under ${operation.parentOuName}...`
101
+ `Creating OU "${props.operation.ouName}" under ${props.operation.parentOuName}...`
97
102
  );
98
103
  const response = await props.organizationsClient.send(
99
104
  new CreateOrganizationalUnitCommand({
100
- ParentId: operation.parentOuId,
101
- Name: operation.ouName
105
+ ParentId: props.operation.parentOuId,
106
+ Name: props.operation.ouName
102
107
  })
103
108
  );
104
109
  const createdOu = response.OrganizationalUnit;
105
110
  if (createdOu?.Id == null || createdOu.Arn == null || createdOu.Name == null) {
106
111
  throw new Error(
107
- `CreateOrganizationalUnit for "${operation.ouName}" returned incomplete OU data.`
112
+ `CreateOrganizationalUnit for "${props.operation.ouName}" returned incomplete OU data.`
108
113
  );
109
114
  }
110
115
  props.logger.log(`Done: "${createdOu.Name}"`);
@@ -112,55 +117,55 @@ async function executeOperation(props) {
112
117
  workingState: props.state,
113
118
  organizationalUnit: {
114
119
  id: createdOu.Id,
115
- parentId: operation.parentOuId,
120
+ parentId: props.operation.parentOuId,
116
121
  arn: createdOu.Arn,
117
122
  name: createdOu.Name
118
123
  }
119
124
  });
120
125
  }
121
- if (operation.kind === "renameOu") {
126
+ if (props.operation.kind === "renameOu") {
122
127
  props.logger.log(
123
- `Renaming OU "${operation.fromOuName}" -> "${operation.toOuName}"...`
128
+ `Renaming OU "${props.operation.fromOuName}" -> "${props.operation.toOuName}"...`
124
129
  );
125
130
  await props.organizationsClient.send(
126
131
  new UpdateOrganizationalUnitCommand({
127
- OrganizationalUnitId: operation.ouId,
128
- Name: operation.toOuName
132
+ OrganizationalUnitId: props.operation.ouId,
133
+ Name: props.operation.toOuName
129
134
  })
130
135
  );
131
- props.logger.log(`Done: "${operation.toOuName}"`);
136
+ props.logger.log(`Done: "${props.operation.toOuName}"`);
132
137
  return renameOrganizationalUnitInWorkingState({
133
138
  workingState: props.state,
134
- organizationalUnitId: operation.ouId,
135
- name: operation.toOuName
139
+ organizationalUnitId: props.operation.ouId,
140
+ name: props.operation.toOuName
136
141
  });
137
142
  }
138
- if (operation.kind === "deleteOu") {
139
- props.logger.log(`Deleting OU "${operation.ouName}"...`);
143
+ if (props.operation.kind === "deleteOu") {
144
+ props.logger.log(`Deleting OU "${props.operation.ouName}"...`);
140
145
  await assertOrganizationalUnitIsEmpty({
141
146
  organizationsClient: props.organizationsClient,
142
- organizationalUnitId: operation.ouId,
143
- organizationalUnitName: operation.ouName
147
+ organizationalUnitId: props.operation.ouId,
148
+ organizationalUnitName: props.operation.ouName
144
149
  });
145
150
  await props.organizationsClient.send(
146
151
  new DeleteOrganizationalUnitCommand({
147
- OrganizationalUnitId: operation.ouId
152
+ OrganizationalUnitId: props.operation.ouId
148
153
  })
149
154
  );
150
- props.logger.log(`Done: "${operation.ouName}"`);
155
+ props.logger.log(`Done: "${props.operation.ouName}"`);
151
156
  return removeOrganizationalUnitFromWorkingState({
152
157
  workingState: props.state,
153
- organizationalUnitId: operation.ouId
158
+ organizationalUnitId: props.operation.ouId
154
159
  });
155
160
  }
156
- if (operation.kind === "createAccount") {
161
+ if (props.operation.kind === "createAccount") {
157
162
  const result = await createAccountAndMoveToOu({
158
163
  organizationsClient: props.organizationsClient,
159
164
  logger: props.logger,
160
- accountName: operation.accountName,
161
- accountEmail: operation.accountEmail,
165
+ accountName: props.operation.accountName,
166
+ accountEmail: props.operation.accountEmail,
162
167
  sourceParentId: props.context.organization.rootId,
163
- destinationParentId: operation.targetOuId,
168
+ destinationParentId: props.operation.targetOuId,
164
169
  timeoutInMs: props.runtime.createAccount.timeoutInMs,
165
170
  pollIntervalInMs: props.runtime.createAccount.pollIntervalInMs
166
171
  });
@@ -172,33 +177,33 @@ async function executeOperation(props) {
172
177
  name: result.account.name,
173
178
  email: result.account.email,
174
179
  status: result.account.status,
175
- parentId: operation.targetOuId,
180
+ parentId: props.operation.targetOuId,
176
181
  tags: []
177
182
  }
178
183
  });
179
184
  }
180
- if (operation.kind === "updateAccountTags") {
181
- const account = props.state.organization.accountsById[operation.accountId];
185
+ if (props.operation.kind === "updateAccountTags") {
186
+ const account = props.state.organization.accountsById[props.operation.accountId];
182
187
  if (account == null) {
183
188
  throw new Error(
184
- `Could not resolve account "${operation.accountName}" (${operation.accountId}) in working state.`
189
+ `Could not resolve account "${props.operation.accountName}" (${props.operation.accountId}) in working state.`
185
190
  );
186
191
  }
187
192
  const currentTags = new Map(
188
193
  (account.tags ?? []).map((tag) => [tag.key, tag.value])
189
194
  );
190
- const desiredTags = new Map(Object.entries(operation.tags));
195
+ const desiredTags = new Map(Object.entries(props.operation.tags));
191
196
  const tagsToApply = [...desiredTags.entries()].filter(([key, value]) => currentTags.get(key) !== value).map(([Key, Value]) => ({ Key, Value }));
192
197
  const tagKeysToRemove = [...currentTags.keys()].filter(
193
198
  (key) => desiredTags.has(key) === false
194
199
  );
195
200
  props.logger.log(
196
- `Updating account tags "${operation.accountName}" (${operation.accountId})...`
201
+ `Updating account tags "${props.operation.accountName}" (${props.operation.accountId})...`
197
202
  );
198
203
  if (tagsToApply.length > 0) {
199
204
  await props.organizationsClient.send(
200
205
  new TagResourceCommand({
201
- ResourceId: operation.accountId,
206
+ ResourceId: props.operation.accountId,
202
207
  Tags: tagsToApply
203
208
  })
204
209
  );
@@ -206,84 +211,84 @@ async function executeOperation(props) {
206
211
  if (tagKeysToRemove.length > 0) {
207
212
  await props.organizationsClient.send(
208
213
  new UntagResourceCommand({
209
- ResourceId: operation.accountId,
214
+ ResourceId: props.operation.accountId,
210
215
  TagKeys: tagKeysToRemove
211
216
  })
212
217
  );
213
218
  }
214
- props.logger.log(`Done: tags updated for "${operation.accountName}"`);
219
+ props.logger.log(`Done: tags updated for "${props.operation.accountName}"`);
215
220
  return upsertAccountInWorkingState({
216
221
  workingState: props.state,
217
222
  account: {
218
223
  ...account,
219
- tags: Object.entries(operation.tags).map(([key, value]) => ({
224
+ tags: Object.entries(props.operation.tags).map(([key, value]) => ({
220
225
  key,
221
226
  value
222
227
  }))
223
228
  }
224
229
  });
225
230
  }
226
- if (operation.kind === "updateAccountName") {
231
+ if (props.operation.kind === "updateAccountName") {
227
232
  props.logger.log(
228
- `Renaming account (${operation.accountId}): "${operation.fromAccountName}" -> "${operation.toAccountName}"...`
233
+ `Renaming account (${props.operation.accountId}): "${props.operation.fromAccountName}" -> "${props.operation.toAccountName}"...`
229
234
  );
230
235
  await props.accountClient.send(
231
236
  new PutAccountNameCommand({
232
- AccountId: operation.accountId,
233
- AccountName: operation.toAccountName
237
+ AccountId: props.operation.accountId,
238
+ AccountName: props.operation.toAccountName
234
239
  })
235
240
  );
236
241
  props.logger.log(
237
- `Done: account "${operation.toAccountName}" (${operation.accountId})`
242
+ `Done: account "${props.operation.toAccountName}" (${props.operation.accountId})`
238
243
  );
239
- const account = props.state.organization.accountsById[operation.accountId];
244
+ const account = props.state.organization.accountsById[props.operation.accountId];
240
245
  if (account == null) {
241
246
  throw new Error(
242
- `Could not resolve account (${operation.accountId}) in working state after rename.`
247
+ `Could not resolve account (${props.operation.accountId}) in working state after rename.`
243
248
  );
244
249
  }
245
250
  return upsertAccountInWorkingState({
246
251
  workingState: props.state,
247
252
  account: {
248
253
  ...account,
249
- name: operation.toAccountName
254
+ name: props.operation.toAccountName
250
255
  }
251
256
  });
252
257
  }
253
- if (operation.kind === "removeAccount") {
258
+ if (props.operation.kind === "removeAccount") {
254
259
  props.logger.log(
255
- `Moving removed account "${operation.accountName}" (${operation.accountId}) to ${operation.toOuName}...`
260
+ `Moving removed account "${props.operation.accountName}" (${props.operation.accountId}) to ${props.operation.toOuName}...`
256
261
  );
257
262
  await props.organizationsClient.send(
258
263
  new MoveAccountCommand({
259
- AccountId: operation.accountId,
260
- SourceParentId: operation.fromOuId,
261
- DestinationParentId: operation.toOuId
264
+ AccountId: props.operation.accountId,
265
+ SourceParentId: props.operation.fromOuId,
266
+ DestinationParentId: props.operation.toOuId
262
267
  })
263
268
  );
264
269
  props.logger.log(
265
- `Done: "${operation.accountName}" -> ${operation.toOuName}`
270
+ `Done: "${props.operation.accountName}" -> ${props.operation.toOuName}`
266
271
  );
267
272
  return moveAccountInWorkingState({
268
273
  workingState: props.state,
269
- accountId: operation.accountId,
270
- parentId: operation.toOuId
274
+ accountId: props.operation.accountId,
275
+ parentId: props.operation.toOuId
271
276
  });
272
277
  }
273
- if (operation.kind === "createIdcUser") {
274
- props.logger.log(`Creating IdC user "${operation.userName}"...`);
278
+ if (props.operation.kind === "createIdcUser") {
279
+ props.logger.log(`Creating IdC user "${props.operation.userName}"...`);
275
280
  const response = await props.identityStoreClient.send(
276
281
  new CreateUserCommand({
277
282
  IdentityStoreId: props.state.identityCenter.identityStoreId,
278
- UserName: operation.userName,
279
- DisplayName: operation.displayName,
283
+ UserName: props.operation.userName,
284
+ DisplayName: props.operation.displayName,
280
285
  Name: buildIdentityStoreUserName({
281
- userName: operation.userName,
282
- displayName: operation.displayName
286
+ userName: props.operation.userName,
287
+ displayName: props.operation.displayName
283
288
  }),
284
- Emails: operation.email.length > 0 ? [
289
+ Emails: props.operation.email.length > 0 ? [
285
290
  {
286
- Value: operation.email,
291
+ Value: props.operation.email,
287
292
  Type: "Work",
288
293
  Primary: true
289
294
  }
@@ -292,45 +297,45 @@ async function executeOperation(props) {
292
297
  );
293
298
  if (response.UserId == null) {
294
299
  throw new Error(
295
- `CreateUser for "${operation.userName}" returned no user id.`
300
+ `CreateUser for "${props.operation.userName}" returned no user id.`
296
301
  );
297
302
  }
298
- props.logger.log(`Done: "${operation.userName}"`);
303
+ props.logger.log(`Done: "${props.operation.userName}"`);
299
304
  return upsertIdcUserInWorkingState({
300
305
  workingState: props.state,
301
306
  user: {
302
307
  userId: response.UserId,
303
- userName: operation.userName,
304
- displayName: operation.displayName,
305
- email: operation.email
308
+ userName: props.operation.userName,
309
+ displayName: props.operation.displayName,
310
+ email: props.operation.email
306
311
  }
307
312
  });
308
313
  }
309
- if (operation.kind === "updateIdcUser") {
314
+ if (props.operation.kind === "updateIdcUser") {
310
315
  const user = resolveUserByName({
311
316
  state: props.state,
312
- userName: operation.userName
317
+ userName: props.operation.userName
313
318
  });
314
319
  const operations = [];
315
- if (user.displayName !== operation.displayName) {
320
+ if (user.displayName !== props.operation.displayName) {
316
321
  operations.push({
317
322
  AttributePath: "displayName",
318
- AttributeValue: operation.displayName
323
+ AttributeValue: props.operation.displayName
319
324
  });
320
325
  operations.push({
321
326
  AttributePath: "name",
322
327
  AttributeValue: buildIdentityStoreUserName({
323
- userName: operation.userName,
324
- displayName: operation.displayName
328
+ userName: props.operation.userName,
329
+ displayName: props.operation.displayName
325
330
  })
326
331
  });
327
332
  }
328
- if (user.email !== operation.email && operation.email.length > 0) {
333
+ if (user.email !== props.operation.email && props.operation.email.length > 0) {
329
334
  operations.push({
330
335
  AttributePath: "emails",
331
336
  AttributeValue: [
332
337
  {
333
- Value: operation.email,
338
+ Value: props.operation.email,
334
339
  Type: "Work",
335
340
  Primary: true
336
341
  }
@@ -340,7 +345,7 @@ async function executeOperation(props) {
340
345
  if (operations.length === 0) {
341
346
  return props.state;
342
347
  }
343
- props.logger.log(`Updating IdC user "${operation.userName}"...`);
348
+ props.logger.log(`Updating IdC user "${props.operation.userName}"...`);
344
349
  await props.identityStoreClient.send(
345
350
  new UpdateUserCommand({
346
351
  IdentityStoreId: props.state.identityCenter.identityStoreId,
@@ -348,65 +353,65 @@ async function executeOperation(props) {
348
353
  Operations: operations
349
354
  })
350
355
  );
351
- props.logger.log(`Done: "${operation.userName}"`);
356
+ props.logger.log(`Done: "${props.operation.userName}"`);
352
357
  return upsertIdcUserInWorkingState({
353
358
  workingState: props.state,
354
359
  user: {
355
360
  ...user,
356
- displayName: operation.displayName,
357
- email: operation.email.length > 0 ? operation.email : user.email
361
+ displayName: props.operation.displayName,
362
+ email: props.operation.email.length > 0 ? props.operation.email : user.email
358
363
  }
359
364
  });
360
365
  }
361
- if (operation.kind === "deleteIdcUser") {
366
+ if (props.operation.kind === "deleteIdcUser") {
362
367
  const user = resolveUserByName({
363
368
  state: props.state,
364
- userName: operation.userName
369
+ userName: props.operation.userName
365
370
  });
366
- props.logger.log(`Deleting IdC user "${operation.userName}"...`);
371
+ props.logger.log(`Deleting IdC user "${props.operation.userName}"...`);
367
372
  await props.identityStoreClient.send(
368
373
  new DeleteUserCommand({
369
374
  IdentityStoreId: props.state.identityCenter.identityStoreId,
370
375
  UserId: user.userId
371
376
  })
372
377
  );
373
- props.logger.log(`Done: "${operation.userName}"`);
378
+ props.logger.log(`Done: "${props.operation.userName}"`);
374
379
  return removeIdcUserFromWorkingState({
375
380
  workingState: props.state,
376
- userName: operation.userName
381
+ userName: props.operation.userName
377
382
  });
378
383
  }
379
- if (operation.kind === "createIdcGroup") {
380
- props.logger.log(`Creating IdC group "${operation.groupDisplayName}"...`);
384
+ if (props.operation.kind === "createIdcGroup") {
385
+ props.logger.log(`Creating IdC group "${props.operation.groupDisplayName}"...`);
381
386
  const response = await props.identityStoreClient.send(
382
387
  new CreateGroupCommand({
383
388
  IdentityStoreId: props.state.identityCenter.identityStoreId,
384
- DisplayName: operation.groupDisplayName,
385
- Description: operation.description.trim().length > 0 ? operation.description : void 0
389
+ DisplayName: props.operation.groupDisplayName,
390
+ Description: props.operation.description.trim().length > 0 ? props.operation.description : void 0
386
391
  })
387
392
  );
388
393
  if (response.GroupId == null) {
389
394
  throw new Error(
390
- `CreateGroup for "${operation.groupDisplayName}" returned no group id.`
395
+ `CreateGroup for "${props.operation.groupDisplayName}" returned no group id.`
391
396
  );
392
397
  }
393
- props.logger.log(`Done: "${operation.groupDisplayName}"`);
398
+ props.logger.log(`Done: "${props.operation.groupDisplayName}"`);
394
399
  return upsertIdcGroupInWorkingState({
395
400
  workingState: props.state,
396
401
  group: {
397
402
  groupId: response.GroupId,
398
- displayName: operation.groupDisplayName,
399
- description: operation.description
403
+ displayName: props.operation.groupDisplayName,
404
+ description: props.operation.description
400
405
  }
401
406
  });
402
407
  }
403
- if (operation.kind === "updateIdcGroupDescription") {
408
+ if (props.operation.kind === "updateIdcGroupDescription") {
404
409
  const group = resolveGroupByDisplayName({
405
410
  state: props.state,
406
- groupDisplayName: operation.groupDisplayName
411
+ groupDisplayName: props.operation.groupDisplayName
407
412
  });
408
413
  props.logger.log(
409
- `Updating IdC group description for "${operation.groupDisplayName}"...`
414
+ `Updating IdC group description for "${props.operation.groupDisplayName}"...`
410
415
  );
411
416
  await props.identityStoreClient.send(
412
417
  new UpdateGroupCommand({
@@ -415,46 +420,46 @@ async function executeOperation(props) {
415
420
  Operations: [
416
421
  {
417
422
  AttributePath: "description",
418
- AttributeValue: operation.description
423
+ AttributeValue: props.operation.description
419
424
  }
420
425
  ]
421
426
  })
422
427
  );
423
- props.logger.log(`Done: group "${operation.groupDisplayName}"`);
428
+ props.logger.log(`Done: group "${props.operation.groupDisplayName}"`);
424
429
  return upsertIdcGroupInWorkingState({
425
430
  workingState: props.state,
426
431
  group: {
427
432
  ...group,
428
- description: operation.description
433
+ description: props.operation.description
429
434
  }
430
435
  });
431
436
  }
432
- if (operation.kind === "deleteIdcGroup") {
437
+ if (props.operation.kind === "deleteIdcGroup") {
433
438
  const group = resolveGroupByDisplayName({
434
439
  state: props.state,
435
- groupDisplayName: operation.groupDisplayName
440
+ groupDisplayName: props.operation.groupDisplayName
436
441
  });
437
- props.logger.log(`Deleting IdC group "${operation.groupDisplayName}"...`);
442
+ props.logger.log(`Deleting IdC group "${props.operation.groupDisplayName}"...`);
438
443
  await props.identityStoreClient.send(
439
444
  new DeleteGroupCommand({
440
445
  IdentityStoreId: props.state.identityCenter.identityStoreId,
441
446
  GroupId: group.groupId
442
447
  })
443
448
  );
444
- props.logger.log(`Done: "${operation.groupDisplayName}"`);
449
+ props.logger.log(`Done: "${props.operation.groupDisplayName}"`);
445
450
  return removeIdcGroupFromWorkingState({
446
451
  workingState: props.state,
447
- groupDisplayName: operation.groupDisplayName
452
+ groupDisplayName: props.operation.groupDisplayName
448
453
  });
449
454
  }
450
- if (operation.kind === "addIdcGroupMembership") {
455
+ if (props.operation.kind === "addIdcGroupMembership") {
451
456
  const resolvedMembership = resolveGroupMembershipDependencies({
452
457
  state: props.state,
453
- groupDisplayName: operation.groupDisplayName,
454
- userName: operation.userName
458
+ groupDisplayName: props.operation.groupDisplayName,
459
+ userName: props.operation.userName
455
460
  });
456
461
  props.logger.log(
457
- `Adding user "${operation.userName}" to IdC group "${operation.groupDisplayName}"...`
462
+ `Adding user "${props.operation.userName}" to IdC group "${props.operation.groupDisplayName}"...`
458
463
  );
459
464
  const response = await props.identityStoreClient.send(
460
465
  new CreateGroupMembershipCommand({
@@ -467,11 +472,11 @@ async function executeOperation(props) {
467
472
  );
468
473
  if (response.MembershipId == null) {
469
474
  throw new Error(
470
- `CreateGroupMembership for group "${operation.groupDisplayName}" and user "${operation.userName}" returned no membership id.`
475
+ `CreateGroupMembership for group "${props.operation.groupDisplayName}" and user "${props.operation.userName}" returned no membership id.`
471
476
  );
472
477
  }
473
478
  props.logger.log(
474
- `Done: user "${operation.userName}" -> group "${operation.groupDisplayName}"`
479
+ `Done: user "${props.operation.userName}" -> group "${props.operation.groupDisplayName}"`
475
480
  );
476
481
  return addGroupMembershipToWorkingState({
477
482
  workingState: props.state,
@@ -482,93 +487,94 @@ async function executeOperation(props) {
482
487
  }
483
488
  });
484
489
  }
485
- if (operation.kind === "createIdcPermissionSet") {
490
+ if (props.operation.kind === "createIdcPermissionSet") {
486
491
  props.logger.log(
487
- `Creating IdC permission set "${operation.permissionSetName}"...`
492
+ `Creating IdC permission set "${props.operation.permissionSetName}"...`
488
493
  );
489
494
  const response = await props.ssoAdminClient.send(
490
495
  new CreatePermissionSetCommand({
491
496
  InstanceArn: props.state.identityCenter.instanceArn,
492
- Name: operation.permissionSetName,
493
- Description: operation.description.length > 0 ? operation.description : void 0,
494
- SessionDuration: operation.sessionDuration ?? void 0
497
+ Name: props.operation.permissionSetName,
498
+ Description: props.operation.description.length > 0 ? props.operation.description : void 0,
499
+ SessionDuration: props.operation.sessionDuration ?? void 0
495
500
  })
496
501
  );
497
502
  const permissionSetArn = response.PermissionSet?.PermissionSetArn;
498
503
  if (permissionSetArn == null) {
499
504
  throw new Error(
500
- `CreatePermissionSet for "${operation.permissionSetName}" returned no permission set arn.`
505
+ `CreatePermissionSet for "${props.operation.permissionSetName}" returned no permission set arn.`
501
506
  );
502
507
  }
503
- props.logger.log(`Done: "${operation.permissionSetName}"`);
508
+ props.logger.log(`Done: "${props.operation.permissionSetName}"`);
504
509
  return upsertIdcPermissionSetInWorkingState({
505
510
  workingState: props.state,
506
511
  permissionSet: {
507
512
  permissionSetArn,
508
- name: operation.permissionSetName,
509
- description: operation.description,
510
- sessionDuration: operation.sessionDuration,
513
+ name: props.operation.permissionSetName,
514
+ description: props.operation.description,
515
+ sessionDuration: props.operation.sessionDuration,
511
516
  inlinePolicy: null,
512
517
  awsManagedPolicies: [],
513
- customerManagedPolicies: []
518
+ customerManagedPolicies: [],
519
+ permissionsBoundary: null
514
520
  }
515
521
  });
516
522
  }
517
- if (operation.kind === "updateIdcPermissionSetDescription") {
523
+ if (props.operation.kind === "updateIdcPermissionSetDescription") {
518
524
  const permissionSet = resolvePermissionSetByName({
519
525
  state: props.state,
520
- permissionSetName: operation.permissionSetName
526
+ permissionSetName: props.operation.permissionSetName
521
527
  });
522
528
  props.logger.log(
523
- `Updating IdC permission set description for "${operation.permissionSetName}"...`
529
+ `Updating IdC permission set description for "${props.operation.permissionSetName}"...`
524
530
  );
525
531
  await props.ssoAdminClient.send(
526
532
  new UpdatePermissionSetCommand({
527
533
  InstanceArn: props.state.identityCenter.instanceArn,
528
534
  PermissionSetArn: permissionSet.permissionSetArn,
529
- Description: operation.description.trim().length > 0 ? operation.description : void 0
535
+ Description: props.operation.description.trim().length > 0 ? props.operation.description : void 0
530
536
  })
531
537
  );
532
- props.logger.log(`Done: "${operation.permissionSetName}"`);
538
+ props.logger.log(`Done: "${props.operation.permissionSetName}"`);
533
539
  return upsertIdcPermissionSetInWorkingState({
534
540
  workingState: props.state,
535
541
  permissionSet: {
536
542
  ...permissionSet,
537
- description: operation.description
543
+ description: props.operation.description
538
544
  }
539
545
  });
540
546
  }
541
- if (operation.kind === "updateIdcPermissionSetSessionDuration") {
547
+ if (props.operation.kind === "updateIdcPermissionSetSessionDuration") {
542
548
  const permissionSet = resolvePermissionSetByName({
543
549
  state: props.state,
544
- permissionSetName: operation.permissionSetName
550
+ permissionSetName: props.operation.permissionSetName
545
551
  });
546
552
  props.logger.log(
547
- `Updating IdC permission set session duration for "${operation.permissionSetName}"...`
553
+ `Updating IdC permission set session duration for "${props.operation.permissionSetName}"...`
548
554
  );
549
555
  await props.ssoAdminClient.send(
550
556
  new UpdatePermissionSetCommand({
551
557
  InstanceArn: props.state.identityCenter.instanceArn,
552
558
  PermissionSetArn: permissionSet.permissionSetArn,
553
- SessionDuration: operation.sessionDuration ?? void 0
559
+ SessionDuration: props.operation.sessionDuration ?? void 0
554
560
  })
555
561
  );
556
- props.logger.log(`Done: "${operation.permissionSetName}"`);
562
+ props.logger.log(`Done: "${props.operation.permissionSetName}"`);
557
563
  return upsertIdcPermissionSetInWorkingState({
558
564
  workingState: props.state,
559
565
  permissionSet: {
560
566
  ...permissionSet,
561
- sessionDuration: operation.sessionDuration
567
+ sessionDuration: props.operation.sessionDuration
562
568
  }
563
569
  });
564
570
  }
565
- if (operation.kind === "deleteIdcPermissionSet") {
571
+ if (props.operation.kind === "deleteIdcPermissionSet") {
566
572
  const permissionSet = resolvePermissionSetByName({
567
573
  state: props.state,
568
- permissionSetName: operation.permissionSetName
574
+ permissionSetName: props.operation.permissionSetName
569
575
  });
570
576
  props.logger.log(
571
- `Deleting IdC permission set "${operation.permissionSetName}"...`
577
+ `Deleting IdC permission set "${props.operation.permissionSetName}"...`
572
578
  );
573
579
  await props.ssoAdminClient.send(
574
580
  new DeletePermissionSetCommand({
@@ -576,44 +582,45 @@ async function executeOperation(props) {
576
582
  PermissionSetArn: permissionSet.permissionSetArn
577
583
  })
578
584
  );
579
- props.logger.log(`Done: "${operation.permissionSetName}"`);
585
+ props.logger.log(`Done: "${props.operation.permissionSetName}"`);
580
586
  return removeIdcPermissionSetFromWorkingState({
581
587
  workingState: props.state,
582
- permissionSetName: operation.permissionSetName
588
+ permissionSetName: props.operation.permissionSetName
583
589
  });
584
590
  }
585
- if (operation.kind === "putIdcPermissionSetInlinePolicy") {
591
+ if (props.operation.kind === "putIdcPermissionSetInlinePolicy") {
592
+ const { inlinePolicy } = props.operation;
586
593
  const permissionSet = resolvePermissionSetByName({
587
594
  state: props.state,
588
- permissionSetName: operation.permissionSetName
595
+ permissionSetName: props.operation.permissionSetName
589
596
  });
590
597
  props.logger.log(
591
- `Putting inline policy on IdC permission set "${operation.permissionSetName}"...`
598
+ `Putting inline policy on IdC permission set "${props.operation.permissionSetName}"...`
592
599
  );
593
600
  await props.ssoAdminClient.send(
594
601
  new PutInlinePolicyToPermissionSetCommand({
595
602
  InstanceArn: props.state.identityCenter.instanceArn,
596
603
  PermissionSetArn: permissionSet.permissionSetArn,
597
- InlinePolicy: operation.inlinePolicy
604
+ InlinePolicy: inlinePolicy
598
605
  })
599
606
  );
600
- props.logger.log(`Done: "${operation.permissionSetName}"`);
607
+ props.logger.log(`Done: "${props.operation.permissionSetName}"`);
601
608
  return upsertPermissionSetPolicyState({
602
609
  state: props.state,
603
- permissionSetName: operation.permissionSetName,
610
+ permissionSetName: props.operation.permissionSetName,
604
611
  update: (currentPermissionSet) => ({
605
612
  ...currentPermissionSet,
606
- inlinePolicy: operation.inlinePolicy
613
+ inlinePolicy
607
614
  })
608
615
  });
609
616
  }
610
- if (operation.kind === "deleteIdcPermissionSetInlinePolicy") {
617
+ if (props.operation.kind === "deleteIdcPermissionSetInlinePolicy") {
611
618
  const permissionSet = resolvePermissionSetByName({
612
619
  state: props.state,
613
- permissionSetName: operation.permissionSetName
620
+ permissionSetName: props.operation.permissionSetName
614
621
  });
615
622
  props.logger.log(
616
- `Deleting inline policy from IdC permission set "${operation.permissionSetName}"...`
623
+ `Deleting inline policy from IdC permission set "${props.operation.permissionSetName}"...`
617
624
  );
618
625
  await props.ssoAdminClient.send(
619
626
  new DeleteInlinePolicyFromPermissionSetCommand({
@@ -621,154 +628,158 @@ async function executeOperation(props) {
621
628
  PermissionSetArn: permissionSet.permissionSetArn
622
629
  })
623
630
  );
624
- props.logger.log(`Done: "${operation.permissionSetName}"`);
631
+ props.logger.log(`Done: "${props.operation.permissionSetName}"`);
625
632
  return upsertPermissionSetPolicyState({
626
633
  state: props.state,
627
- permissionSetName: operation.permissionSetName,
634
+ permissionSetName: props.operation.permissionSetName,
628
635
  update: (currentPermissionSet) => ({
629
636
  ...currentPermissionSet,
630
637
  inlinePolicy: null
631
638
  })
632
639
  });
633
640
  }
634
- if (operation.kind === "attachIdcManagedPolicyToPermissionSet") {
641
+ if (props.operation.kind === "attachIdcManagedPolicyToPermissionSet") {
642
+ const { managedPolicyArn } = props.operation;
635
643
  const permissionSet = resolvePermissionSetByName({
636
644
  state: props.state,
637
- permissionSetName: operation.permissionSetName
645
+ permissionSetName: props.operation.permissionSetName
638
646
  });
639
647
  props.logger.log(
640
- `Attaching managed policy "${operation.managedPolicyArn}" to IdC permission set "${operation.permissionSetName}"...`
648
+ `Attaching managed policy "${managedPolicyArn}" to IdC permission set "${props.operation.permissionSetName}"...`
641
649
  );
642
650
  await props.ssoAdminClient.send(
643
651
  new AttachManagedPolicyToPermissionSetCommand({
644
652
  InstanceArn: props.state.identityCenter.instanceArn,
645
653
  PermissionSetArn: permissionSet.permissionSetArn,
646
- ManagedPolicyArn: operation.managedPolicyArn
654
+ ManagedPolicyArn: managedPolicyArn
647
655
  })
648
656
  );
649
- props.logger.log(`Done: "${operation.permissionSetName}"`);
657
+ props.logger.log(`Done: "${props.operation.permissionSetName}"`);
650
658
  return upsertPermissionSetPolicyState({
651
659
  state: props.state,
652
- permissionSetName: operation.permissionSetName,
660
+ permissionSetName: props.operation.permissionSetName,
653
661
  update: (currentPermissionSet) => ({
654
662
  ...currentPermissionSet,
655
663
  awsManagedPolicies: [
656
664
  ...currentPermissionSet.awsManagedPolicies,
657
- operation.managedPolicyArn
665
+ managedPolicyArn
658
666
  ]
659
667
  })
660
668
  });
661
669
  }
662
- if (operation.kind === "detachIdcManagedPolicyFromPermissionSet") {
670
+ if (props.operation.kind === "detachIdcManagedPolicyFromPermissionSet") {
671
+ const { managedPolicyArn } = props.operation;
663
672
  const permissionSet = resolvePermissionSetByName({
664
673
  state: props.state,
665
- permissionSetName: operation.permissionSetName
674
+ permissionSetName: props.operation.permissionSetName
666
675
  });
667
676
  props.logger.log(
668
- `Detaching managed policy "${operation.managedPolicyArn}" from IdC permission set "${operation.permissionSetName}"...`
677
+ `Detaching managed policy "${managedPolicyArn}" from IdC permission set "${props.operation.permissionSetName}"...`
669
678
  );
670
679
  await props.ssoAdminClient.send(
671
680
  new DetachManagedPolicyFromPermissionSetCommand({
672
681
  InstanceArn: props.state.identityCenter.instanceArn,
673
682
  PermissionSetArn: permissionSet.permissionSetArn,
674
- ManagedPolicyArn: operation.managedPolicyArn
683
+ ManagedPolicyArn: managedPolicyArn
675
684
  })
676
685
  );
677
- props.logger.log(`Done: "${operation.permissionSetName}"`);
686
+ props.logger.log(`Done: "${props.operation.permissionSetName}"`);
678
687
  return upsertPermissionSetPolicyState({
679
688
  state: props.state,
680
- permissionSetName: operation.permissionSetName,
689
+ permissionSetName: props.operation.permissionSetName,
681
690
  update: (currentPermissionSet) => ({
682
691
  ...currentPermissionSet,
683
692
  awsManagedPolicies: currentPermissionSet.awsManagedPolicies.filter(
684
- (managedPolicyArn) => managedPolicyArn !== operation.managedPolicyArn
693
+ (arn) => arn !== managedPolicyArn
685
694
  )
686
695
  })
687
696
  });
688
697
  }
689
- if (operation.kind === "attachIdcCustomerManagedPolicyReferenceToPermissionSet") {
698
+ if (props.operation.kind === "attachIdcCustomerManagedPolicyReferenceToPermissionSet") {
699
+ const { customerManagedPolicyName, customerManagedPolicyPath } = props.operation;
690
700
  const permissionSet = resolvePermissionSetByName({
691
701
  state: props.state,
692
- permissionSetName: operation.permissionSetName
702
+ permissionSetName: props.operation.permissionSetName
693
703
  });
694
704
  props.logger.log(
695
- `Attaching customer-managed policy "${operation.customerManagedPolicyPath}${operation.customerManagedPolicyName}" to IdC permission set "${operation.permissionSetName}"...`
705
+ `Attaching customer-managed policy "${customerManagedPolicyPath}${customerManagedPolicyName}" to IdC permission set "${props.operation.permissionSetName}"...`
696
706
  );
697
707
  await props.ssoAdminClient.send(
698
708
  new AttachCustomerManagedPolicyReferenceToPermissionSetCommand({
699
709
  InstanceArn: props.state.identityCenter.instanceArn,
700
710
  PermissionSetArn: permissionSet.permissionSetArn,
701
711
  CustomerManagedPolicyReference: {
702
- Name: operation.customerManagedPolicyName,
703
- Path: operation.customerManagedPolicyPath
712
+ Name: customerManagedPolicyName,
713
+ Path: customerManagedPolicyPath
704
714
  }
705
715
  })
706
716
  );
707
- props.logger.log(`Done: "${operation.permissionSetName}"`);
717
+ props.logger.log(`Done: "${props.operation.permissionSetName}"`);
708
718
  return upsertPermissionSetPolicyState({
709
719
  state: props.state,
710
- permissionSetName: operation.permissionSetName,
720
+ permissionSetName: props.operation.permissionSetName,
711
721
  update: (currentPermissionSet) => ({
712
722
  ...currentPermissionSet,
713
723
  customerManagedPolicies: [
714
724
  ...currentPermissionSet.customerManagedPolicies,
715
725
  {
716
- name: operation.customerManagedPolicyName,
717
- path: operation.customerManagedPolicyPath
726
+ name: customerManagedPolicyName,
727
+ path: customerManagedPolicyPath
718
728
  }
719
729
  ]
720
730
  })
721
731
  });
722
732
  }
723
- if (operation.kind === "detachIdcCustomerManagedPolicyReferenceFromPermissionSet") {
733
+ if (props.operation.kind === "detachIdcCustomerManagedPolicyReferenceFromPermissionSet") {
734
+ const { customerManagedPolicyName, customerManagedPolicyPath } = props.operation;
724
735
  const permissionSet = resolvePermissionSetByName({
725
736
  state: props.state,
726
- permissionSetName: operation.permissionSetName
737
+ permissionSetName: props.operation.permissionSetName
727
738
  });
728
739
  props.logger.log(
729
- `Detaching customer-managed policy "${operation.customerManagedPolicyPath}${operation.customerManagedPolicyName}" from IdC permission set "${operation.permissionSetName}"...`
740
+ `Detaching customer-managed policy "${customerManagedPolicyPath}${customerManagedPolicyName}" from IdC permission set "${props.operation.permissionSetName}"...`
730
741
  );
731
742
  await props.ssoAdminClient.send(
732
743
  new DetachCustomerManagedPolicyReferenceFromPermissionSetCommand({
733
744
  InstanceArn: props.state.identityCenter.instanceArn,
734
745
  PermissionSetArn: permissionSet.permissionSetArn,
735
746
  CustomerManagedPolicyReference: {
736
- Name: operation.customerManagedPolicyName,
737
- Path: operation.customerManagedPolicyPath
747
+ Name: customerManagedPolicyName,
748
+ Path: customerManagedPolicyPath
738
749
  }
739
750
  })
740
751
  );
741
- props.logger.log(`Done: "${operation.permissionSetName}"`);
752
+ props.logger.log(`Done: "${props.operation.permissionSetName}"`);
742
753
  return upsertPermissionSetPolicyState({
743
754
  state: props.state,
744
- permissionSetName: operation.permissionSetName,
755
+ permissionSetName: props.operation.permissionSetName,
745
756
  update: (currentPermissionSet) => ({
746
757
  ...currentPermissionSet,
747
758
  customerManagedPolicies: currentPermissionSet.customerManagedPolicies.filter(
748
- (customerManagedPolicy) => customerManagedPolicy.name !== operation.customerManagedPolicyName || customerManagedPolicy.path !== operation.customerManagedPolicyPath
759
+ (policy) => policy.name !== customerManagedPolicyName || policy.path !== customerManagedPolicyPath
749
760
  )
750
761
  })
751
762
  });
752
763
  }
753
- if (operation.kind === "provisionIdcPermissionSet") {
764
+ if (props.operation.kind === "provisionIdcPermissionSet") {
754
765
  const permissionSet = resolvePermissionSetByName({
755
766
  state: props.state,
756
- permissionSetName: operation.permissionSetName
767
+ permissionSetName: props.operation.permissionSetName
757
768
  });
758
769
  props.logger.log(
759
- `Provisioning IdC permission set "${operation.permissionSetName}" to all provisioned accounts...`
770
+ `Provisioning IdC permission set "${props.operation.permissionSetName}" to all provisioned accounts...`
760
771
  );
761
772
  const response = await props.ssoAdminClient.send(
762
773
  new ProvisionPermissionSetCommand({
763
774
  InstanceArn: props.state.identityCenter.instanceArn,
764
775
  PermissionSetArn: permissionSet.permissionSetArn,
765
- TargetType: operation.targetScope
776
+ TargetType: props.operation.targetScope
766
777
  })
767
778
  );
768
779
  const requestId = response.PermissionSetProvisioningStatus?.RequestId ?? void 0;
769
780
  if (requestId == null) {
770
781
  throw new Error(
771
- `ProvisionPermissionSet for "${operation.permissionSetName}" returned no request id.`
782
+ `ProvisionPermissionSet for "${props.operation.permissionSetName}" returned no request id.`
772
783
  );
773
784
  }
774
785
  await waitForPermissionSetProvisioningSuccess({
@@ -778,16 +789,63 @@ async function executeOperation(props) {
778
789
  requestId,
779
790
  timeoutInMs: props.runtime.permissionSetProvisioning.timeoutInMs,
780
791
  pollIntervalInMs: props.runtime.permissionSetProvisioning.pollIntervalInMs,
781
- operationLabel: `"${operation.permissionSetName}"`
792
+ operationLabel: `"${props.operation.permissionSetName}"`
782
793
  });
783
- props.logger.log(`Done: "${operation.permissionSetName}"`);
794
+ props.logger.log(`Done: "${props.operation.permissionSetName}"`);
784
795
  return props.state;
785
796
  }
786
- if (operation.kind === "removeIdcGroupMembership") {
797
+ if (props.operation.kind === "putIdcPermissionSetPermissionsBoundary") {
798
+ const permissionSet = resolvePermissionSetByName({
799
+ state: props.state,
800
+ permissionSetName: props.operation.permissionSetName
801
+ });
802
+ props.logger.log(
803
+ `Putting permissions boundary on IdC permission set "${props.operation.permissionSetName}"...`
804
+ );
805
+ const boundary = props.operation.permissionsBoundary;
806
+ await props.ssoAdminClient.send(
807
+ new PutPermissionsBoundaryToPermissionSetCommand({
808
+ InstanceArn: props.state.identityCenter.instanceArn,
809
+ PermissionSetArn: permissionSet.permissionSetArn,
810
+ PermissionsBoundary: "managedPolicyArn" in boundary ? { ManagedPolicyArn: boundary.managedPolicyArn } : {
811
+ CustomerManagedPolicyReference: {
812
+ Name: boundary.customerManagedPolicyName,
813
+ Path: boundary.customerManagedPolicyPath
814
+ }
815
+ }
816
+ })
817
+ );
818
+ props.logger.log(`Done: "${props.operation.permissionSetName}"`);
819
+ return upsertIdcPermissionSetInWorkingState({
820
+ workingState: props.state,
821
+ permissionSet: { ...permissionSet, permissionsBoundary: boundary }
822
+ });
823
+ }
824
+ if (props.operation.kind === "deleteIdcPermissionSetPermissionsBoundary") {
825
+ const permissionSet = resolvePermissionSetByName({
826
+ state: props.state,
827
+ permissionSetName: props.operation.permissionSetName
828
+ });
829
+ props.logger.log(
830
+ `Deleting permissions boundary from IdC permission set "${props.operation.permissionSetName}"...`
831
+ );
832
+ await props.ssoAdminClient.send(
833
+ new DeletePermissionsBoundaryFromPermissionSetCommand({
834
+ InstanceArn: props.state.identityCenter.instanceArn,
835
+ PermissionSetArn: permissionSet.permissionSetArn
836
+ })
837
+ );
838
+ props.logger.log(`Done: "${props.operation.permissionSetName}"`);
839
+ return upsertIdcPermissionSetInWorkingState({
840
+ workingState: props.state,
841
+ permissionSet: { ...permissionSet, permissionsBoundary: null }
842
+ });
843
+ }
844
+ if (props.operation.kind === "removeIdcGroupMembership") {
787
845
  const resolvedMembership = resolveGroupMembershipDependencies({
788
846
  state: props.state,
789
- groupDisplayName: operation.groupDisplayName,
790
- userName: operation.userName
847
+ groupDisplayName: props.operation.groupDisplayName,
848
+ userName: props.operation.userName
791
849
  });
792
850
  const membershipId = await resolveGroupMembershipId({
793
851
  state: props.state,
@@ -796,7 +854,7 @@ async function executeOperation(props) {
796
854
  userId: resolvedMembership.userId
797
855
  });
798
856
  props.logger.log(
799
- `Removing user "${operation.userName}" from IdC group "${operation.groupDisplayName}"...`
857
+ `Removing user "${props.operation.userName}" from IdC group "${props.operation.groupDisplayName}"...`
800
858
  );
801
859
  await props.identityStoreClient.send(
802
860
  new DeleteGroupMembershipCommand({
@@ -805,7 +863,7 @@ async function executeOperation(props) {
805
863
  })
806
864
  );
807
865
  props.logger.log(
808
- `Done: user "${operation.userName}" x group "${operation.groupDisplayName}"`
866
+ `Done: user "${props.operation.userName}" x group "${props.operation.groupDisplayName}"`
809
867
  );
810
868
  return removeGroupMembershipFromWorkingState({
811
869
  workingState: props.state,
@@ -815,21 +873,21 @@ async function executeOperation(props) {
815
873
  }
816
874
  });
817
875
  }
818
- if (operation.kind === "grantIdcAccountAssignment") {
876
+ if (props.operation.kind === "grantIdcAccountAssignment") {
819
877
  const resolvedAssignment = resolveAssignmentDependencies({
820
878
  state: props.state,
821
- accountName: operation.accountName,
822
- permissionSetName: operation.permissionSetName,
823
- principalType: operation.principalType,
824
- principalName: operation.principalName
879
+ accountName: props.operation.accountName,
880
+ permissionSetName: props.operation.permissionSetName,
881
+ principalType: props.operation.principalType,
882
+ principalName: props.operation.principalName
825
883
  });
826
884
  props.logger.log(
827
- `Granting IdC assignment "${operation.permissionSetName}" to ${formatPrincipalLabel(
885
+ `Granting IdC assignment "${props.operation.permissionSetName}" to ${formatPrincipalLabel(
828
886
  {
829
- principalType: operation.principalType,
830
- principalName: operation.principalName
887
+ principalType: props.operation.principalType,
888
+ principalName: props.operation.principalName
831
889
  }
832
- )} on "${operation.accountName}"...`
890
+ )} on "${props.operation.accountName}"...`
833
891
  );
834
892
  const response = await props.ssoAdminClient.send(
835
893
  new CreateAccountAssignmentCommand({
@@ -844,7 +902,7 @@ async function executeOperation(props) {
844
902
  const requestId = response.AccountAssignmentCreationStatus?.RequestId;
845
903
  if (requestId == null) {
846
904
  throw new Error(
847
- `CreateAccountAssignment for "${operation.permissionSetName}" on "${operation.accountName}" returned no request id.`
905
+ `CreateAccountAssignment for "${props.operation.permissionSetName}" on "${props.operation.accountName}" returned no request id.`
848
906
  );
849
907
  }
850
908
  await waitForAccountAssignmentCreationSuccess({
@@ -854,10 +912,10 @@ async function executeOperation(props) {
854
912
  requestId,
855
913
  timeoutInMs: props.runtime.accountAssignment.timeoutInMs,
856
914
  pollIntervalInMs: props.runtime.accountAssignment.pollIntervalInMs,
857
- operationLabel: `"${operation.permissionSetName}" on "${operation.accountName}"`
915
+ operationLabel: `"${props.operation.permissionSetName}" on "${props.operation.accountName}"`
858
916
  });
859
917
  props.logger.log(
860
- `Done: "${operation.permissionSetName}" -> "${operation.accountName}"`
918
+ `Done: "${props.operation.permissionSetName}" -> "${props.operation.accountName}"`
861
919
  );
862
920
  return addAccountAssignmentToWorkingState({
863
921
  workingState: props.state,
@@ -869,21 +927,21 @@ async function executeOperation(props) {
869
927
  }
870
928
  });
871
929
  }
872
- if (operation.kind === "revokeIdcAccountAssignment") {
930
+ if (props.operation.kind === "revokeIdcAccountAssignment") {
873
931
  const resolvedAssignment = resolveAssignmentDependencies({
874
932
  state: props.state,
875
- accountName: operation.accountName,
876
- permissionSetName: operation.permissionSetName,
877
- principalType: operation.principalType,
878
- principalName: operation.principalName
933
+ accountName: props.operation.accountName,
934
+ permissionSetName: props.operation.permissionSetName,
935
+ principalType: props.operation.principalType,
936
+ principalName: props.operation.principalName
879
937
  });
880
938
  props.logger.log(
881
- `Revoking IdC assignment "${operation.permissionSetName}" from ${formatPrincipalLabel(
939
+ `Revoking IdC assignment "${props.operation.permissionSetName}" from ${formatPrincipalLabel(
882
940
  {
883
- principalType: operation.principalType,
884
- principalName: operation.principalName
941
+ principalType: props.operation.principalType,
942
+ principalName: props.operation.principalName
885
943
  }
886
- )} on "${operation.accountName}"...`
944
+ )} on "${props.operation.accountName}"...`
887
945
  );
888
946
  const response = await props.ssoAdminClient.send(
889
947
  new DeleteAccountAssignmentCommand({
@@ -898,7 +956,7 @@ async function executeOperation(props) {
898
956
  const requestId = response.AccountAssignmentDeletionStatus?.RequestId;
899
957
  if (requestId == null) {
900
958
  throw new Error(
901
- `DeleteAccountAssignment for "${operation.permissionSetName}" on "${operation.accountName}" returned no request id.`
959
+ `DeleteAccountAssignment for "${props.operation.permissionSetName}" on "${props.operation.accountName}" returned no request id.`
902
960
  );
903
961
  }
904
962
  await waitForAccountAssignmentDeletionSuccess({
@@ -908,10 +966,10 @@ async function executeOperation(props) {
908
966
  requestId,
909
967
  timeoutInMs: props.runtime.accountAssignment.timeoutInMs,
910
968
  pollIntervalInMs: props.runtime.accountAssignment.pollIntervalInMs,
911
- operationLabel: `"${operation.permissionSetName}" on "${operation.accountName}"`
969
+ operationLabel: `"${props.operation.permissionSetName}" on "${props.operation.accountName}"`
912
970
  });
913
971
  props.logger.log(
914
- `Done: "${operation.permissionSetName}" x "${operation.accountName}"`
972
+ `Done: "${props.operation.permissionSetName}" x "${props.operation.accountName}"`
915
973
  );
916
974
  return removeAccountAssignmentFromWorkingState({
917
975
  workingState: props.state,
@@ -923,160 +981,169 @@ async function executeOperation(props) {
923
981
  }
924
982
  });
925
983
  }
926
- if (operation.kind === "createOrgPolicy") {
984
+ if (props.operation.kind === "createOrgPolicy") {
927
985
  props.logger.log(
928
- `Creating org policy "${operation.policyName}" (${operation.policyType})...`
986
+ `Creating org policy "${props.operation.policyName}" (${props.operation.policyType})...`
929
987
  );
930
988
  const response = await props.organizationsClient.send(
931
989
  new CreatePolicyCommand({
932
- Name: operation.policyName,
933
- Description: operation.description.length > 0 ? operation.description : void 0,
934
- Content: operation.content,
935
- Type: operation.policyType
990
+ Name: props.operation.policyName,
991
+ Description: props.operation.description.length > 0 ? props.operation.description : void 0,
992
+ Content: props.operation.content,
993
+ Type: props.operation.policyType
936
994
  })
937
995
  );
938
996
  const policy = response.Policy?.PolicySummary;
939
997
  if (policy?.Id == null || policy.Arn == null) {
940
998
  throw new Error(
941
- `CreatePolicy for "${operation.policyName}" returned incomplete data.`
999
+ `CreatePolicy for "${props.operation.policyName}" returned incomplete data.`
942
1000
  );
943
1001
  }
944
- props.logger.log(`Done: "${operation.policyName}"`);
1002
+ props.logger.log(`Done: "${props.operation.policyName}"`);
945
1003
  return upsertOrgPolicyInWorkingState({
946
1004
  workingState: props.state,
947
1005
  policy: {
948
1006
  id: policy.Id,
949
1007
  arn: policy.Arn,
950
- name: operation.policyName,
951
- description: operation.description,
952
- type: operation.policyType,
953
- content: operation.content
1008
+ name: props.operation.policyName,
1009
+ description: props.operation.description,
1010
+ type: props.operation.policyType,
1011
+ content: props.operation.content
954
1012
  }
955
1013
  });
956
1014
  }
957
- if (operation.kind === "updateOrgPolicyContent") {
958
- props.logger.log(`Updating org policy content "${operation.policyName}"...`);
1015
+ if (props.operation.kind === "updateOrgPolicyContent") {
1016
+ props.logger.log(
1017
+ `Updating org policy content "${props.operation.policyName}"...`
1018
+ );
959
1019
  await props.organizationsClient.send(
960
1020
  new UpdatePolicyCommand({
961
- PolicyId: operation.policyId,
962
- Content: operation.content
1021
+ PolicyId: props.operation.policyId,
1022
+ Content: props.operation.content
963
1023
  })
964
1024
  );
965
- props.logger.log(`Done: "${operation.policyName}"`);
966
- const currentPolicy = props.state.organization.policiesById[operation.policyId];
1025
+ props.logger.log(`Done: "${props.operation.policyName}"`);
1026
+ const currentPolicy = props.state.organization.policiesById[props.operation.policyId];
967
1027
  if (currentPolicy == null) {
968
1028
  return props.state;
969
1029
  }
970
1030
  return upsertOrgPolicyInWorkingState({
971
1031
  workingState: props.state,
972
- policy: { ...currentPolicy, content: operation.content }
1032
+ policy: { ...currentPolicy, content: props.operation.content }
973
1033
  });
974
1034
  }
975
- if (operation.kind === "updateOrgPolicyDescription") {
1035
+ if (props.operation.kind === "updateOrgPolicyDescription") {
976
1036
  props.logger.log(
977
- `Updating org policy description "${operation.policyName}"...`
1037
+ `Updating org policy description "${props.operation.policyName}"...`
978
1038
  );
979
1039
  await props.organizationsClient.send(
980
1040
  new UpdatePolicyCommand({
981
- PolicyId: operation.policyId,
982
- Description: operation.description
1041
+ PolicyId: props.operation.policyId,
1042
+ Description: props.operation.description
983
1043
  })
984
1044
  );
985
- props.logger.log(`Done: "${operation.policyName}"`);
986
- const currentPolicy = props.state.organization.policiesById[operation.policyId];
1045
+ props.logger.log(`Done: "${props.operation.policyName}"`);
1046
+ const currentPolicy = props.state.organization.policiesById[props.operation.policyId];
987
1047
  if (currentPolicy == null) {
988
1048
  return props.state;
989
1049
  }
990
1050
  return upsertOrgPolicyInWorkingState({
991
1051
  workingState: props.state,
992
- policy: { ...currentPolicy, description: operation.description }
1052
+ policy: { ...currentPolicy, description: props.operation.description }
993
1053
  });
994
1054
  }
995
- if (operation.kind === "attachOrgPolicy") {
1055
+ if (props.operation.kind === "attachOrgPolicy") {
996
1056
  props.logger.log(
997
- `Attaching org policy "${operation.policyName}" to "${operation.targetName}"...`
1057
+ `Attaching org policy "${props.operation.policyName}" to "${props.operation.targetName}"...`
998
1058
  );
999
1059
  const resolvedPolicyId = resolvePolicyId({
1000
1060
  state: props.state,
1001
- policyId: operation.policyId,
1002
- policyName: operation.policyName
1061
+ policyId: props.operation.policyId,
1062
+ policyName: props.operation.policyName
1003
1063
  });
1004
1064
  await props.organizationsClient.send(
1005
1065
  new AttachPolicyCommand({
1006
1066
  PolicyId: resolvedPolicyId,
1007
- TargetId: operation.targetId
1067
+ TargetId: props.operation.targetId
1008
1068
  })
1009
1069
  );
1010
- props.logger.log(`Done: "${operation.policyName}" -> "${operation.targetName}"`);
1011
- const targetType = operation.targetId === props.context.organization.rootId ? "ROOT" : props.state.organization.organizationalUnitsById[operation.targetId] != null ? "ORGANIZATIONAL_UNIT" : "ACCOUNT";
1070
+ props.logger.log(
1071
+ `Done: "${props.operation.policyName}" -> "${props.operation.targetName}"`
1072
+ );
1073
+ const targetType = props.operation.targetId === props.context.organization.rootId ? "ROOT" : props.state.organization.organizationalUnitsById[props.operation.targetId] != null ? "ORGANIZATIONAL_UNIT" : "ACCOUNT";
1012
1074
  return addOrgPolicyAttachmentToWorkingState({
1013
1075
  workingState: props.state,
1014
1076
  attachment: {
1015
1077
  policyId: resolvedPolicyId,
1016
- targetId: operation.targetId,
1078
+ targetId: props.operation.targetId,
1017
1079
  targetType
1018
1080
  }
1019
1081
  });
1020
1082
  }
1021
- if (operation.kind === "detachOrgPolicy") {
1083
+ if (props.operation.kind === "detachOrgPolicy") {
1022
1084
  props.logger.log(
1023
- `Detaching org policy "${operation.policyName}" from "${operation.targetName}"...`
1085
+ `Detaching org policy "${props.operation.policyName}" from "${props.operation.targetName}"...`
1024
1086
  );
1025
1087
  await props.organizationsClient.send(
1026
1088
  new DetachPolicyCommand({
1027
- PolicyId: operation.policyId,
1028
- TargetId: operation.targetId
1089
+ PolicyId: props.operation.policyId,
1090
+ TargetId: props.operation.targetId
1029
1091
  })
1030
1092
  );
1031
- props.logger.log(`Done: "${operation.policyName}" x "${operation.targetName}"`);
1093
+ props.logger.log(
1094
+ `Done: "${props.operation.policyName}" x "${props.operation.targetName}"`
1095
+ );
1032
1096
  return removeOrgPolicyAttachmentFromWorkingState({
1033
1097
  workingState: props.state,
1034
- policyId: operation.policyId,
1035
- targetId: operation.targetId
1098
+ policyId: props.operation.policyId,
1099
+ targetId: props.operation.targetId
1036
1100
  });
1037
1101
  }
1038
- if (operation.kind === "deleteOrgPolicy") {
1039
- props.logger.log(`Deleting org policy "${operation.policyName}"...`);
1102
+ if (props.operation.kind === "deleteOrgPolicy") {
1103
+ props.logger.log(`Deleting org policy "${props.operation.policyName}"...`);
1040
1104
  await props.organizationsClient.send(
1041
- new DeletePolicyCommand({ PolicyId: operation.policyId })
1105
+ new DeletePolicyCommand({ PolicyId: props.operation.policyId })
1042
1106
  );
1043
- props.logger.log(`Done: "${operation.policyName}"`);
1107
+ props.logger.log(`Done: "${props.operation.policyName}"`);
1044
1108
  return removeOrgPolicyFromWorkingState({
1045
1109
  workingState: props.state,
1046
- policyId: operation.policyId
1110
+ policyId: props.operation.policyId
1047
1111
  });
1048
1112
  }
1049
- if (operation.kind === "putAlternateContact") {
1113
+ if (props.operation.kind === "putAlternateContact") {
1114
+ const { contactType } = props.operation;
1050
1115
  props.logger.log(
1051
- `Setting ${operation.contactType} alternate contact for "${operation.accountName}" (${operation.accountId})...`
1116
+ `Setting ${contactType} alternate contact for "${props.operation.accountName}" (${props.operation.accountId})...`
1052
1117
  );
1053
1118
  await props.accountClient.send(
1054
1119
  new PutAlternateContactCommand({
1055
- AccountId: operation.accountId,
1056
- AlternateContactType: operation.contactType,
1057
- Name: operation.name,
1058
- EmailAddress: operation.email,
1059
- PhoneNumber: operation.phone,
1060
- Title: operation.title
1120
+ AccountId: props.operation.accountId,
1121
+ AlternateContactType: contactType,
1122
+ Name: props.operation.name,
1123
+ EmailAddress: props.operation.email,
1124
+ PhoneNumber: props.operation.phone,
1125
+ Title: props.operation.title
1061
1126
  })
1062
1127
  );
1063
- props.logger.log(`Done: ${operation.contactType} contact for "${operation.accountName}"`);
1064
- const account = props.state.organization.accountsById[operation.accountId];
1128
+ props.logger.log(
1129
+ `Done: ${contactType} contact for "${props.operation.accountName}"`
1130
+ );
1131
+ const account = props.state.organization.accountsById[props.operation.accountId];
1065
1132
  if (account == null) {
1066
1133
  throw new Error(
1067
- `Could not resolve account (${operation.accountId}) in working state.`
1134
+ `Could not resolve account (${props.operation.accountId}) in working state.`
1068
1135
  );
1069
1136
  }
1070
1137
  const updatedContacts = [
1071
1138
  ...(account.alternateContacts ?? []).filter(
1072
- (c) => c.contactType !== operation.contactType
1139
+ (c) => c.contactType !== contactType
1073
1140
  ),
1074
1141
  {
1075
- contactType: operation.contactType,
1076
- name: operation.name,
1077
- email: operation.email,
1078
- phone: operation.phone,
1079
- title: operation.title
1142
+ contactType,
1143
+ name: props.operation.name,
1144
+ email: props.operation.email,
1145
+ phone: props.operation.phone,
1146
+ title: props.operation.title
1080
1147
  }
1081
1148
  ];
1082
1149
  return upsertAccountInWorkingState({
@@ -1084,21 +1151,24 @@ async function executeOperation(props) {
1084
1151
  account: { ...account, alternateContacts: updatedContacts }
1085
1152
  });
1086
1153
  }
1087
- if (operation.kind === "deleteAlternateContact") {
1154
+ if (props.operation.kind === "deleteAlternateContact") {
1155
+ const { contactType } = props.operation;
1088
1156
  props.logger.log(
1089
- `Deleting ${operation.contactType} alternate contact for "${operation.accountName}" (${operation.accountId})...`
1157
+ `Deleting ${contactType} alternate contact for "${props.operation.accountName}" (${props.operation.accountId})...`
1090
1158
  );
1091
1159
  await props.accountClient.send(
1092
1160
  new DeleteAlternateContactCommand({
1093
- AccountId: operation.accountId,
1094
- AlternateContactType: operation.contactType
1161
+ AccountId: props.operation.accountId,
1162
+ AlternateContactType: contactType
1095
1163
  })
1096
1164
  );
1097
- props.logger.log(`Done: removed ${operation.contactType} contact for "${operation.accountName}"`);
1098
- const account = props.state.organization.accountsById[operation.accountId];
1165
+ props.logger.log(
1166
+ `Done: removed ${contactType} contact for "${props.operation.accountName}"`
1167
+ );
1168
+ const account = props.state.organization.accountsById[props.operation.accountId];
1099
1169
  if (account == null) {
1100
1170
  throw new Error(
1101
- `Could not resolve account (${operation.accountId}) in working state.`
1171
+ `Could not resolve account (${props.operation.accountId}) in working state.`
1102
1172
  );
1103
1173
  }
1104
1174
  return upsertAccountInWorkingState({
@@ -1106,20 +1176,20 @@ async function executeOperation(props) {
1106
1176
  account: {
1107
1177
  ...account,
1108
1178
  alternateContacts: (account.alternateContacts ?? []).filter(
1109
- (c) => c.contactType !== operation.contactType
1179
+ (c) => c.contactType !== contactType
1110
1180
  )
1111
1181
  }
1112
1182
  });
1113
1183
  }
1114
- if (operation.kind === "setIdcAccessControlAttributes") {
1184
+ if (props.operation.kind === "setIdcAccessControlAttributes") {
1115
1185
  props.logger.log(
1116
- `Setting IdC access control attributes (${operation.attributes.length} attribute(s))...`
1186
+ `Setting IdC access control attributes (${props.operation.attributes.length} attribute(s))...`
1117
1187
  );
1118
1188
  await props.ssoAdminClient.send(
1119
1189
  new UpdateInstanceAccessControlAttributeConfigurationCommand({
1120
1190
  InstanceArn: props.state.identityCenter.instanceArn,
1121
1191
  InstanceAccessControlAttributeConfiguration: {
1122
- AccessControlAttributes: operation.attributes.map((attr) => ({
1192
+ AccessControlAttributes: props.operation.attributes.map((attr) => ({
1123
1193
  Key: attr.key,
1124
1194
  Value: { Source: attr.source }
1125
1195
  }))
@@ -1131,11 +1201,51 @@ async function executeOperation(props) {
1131
1201
  ...props.state,
1132
1202
  identityCenter: {
1133
1203
  ...props.state.identityCenter,
1134
- accessControlAttributes: operation.attributes
1204
+ accessControlAttributes: props.operation.attributes
1135
1205
  }
1136
1206
  };
1137
1207
  }
1138
- assertUnreachable(operation, "Unsupported operation kind in apply.");
1208
+ if (props.operation.kind === "registerDelegatedAdministrator") {
1209
+ props.logger.log(
1210
+ `Registering delegated administrator "${props.operation.accountName}" (${props.operation.accountId}) for ${props.operation.servicePrincipal}...`
1211
+ );
1212
+ await props.organizationsClient.send(
1213
+ new RegisterDelegatedAdministratorCommand({
1214
+ AccountId: props.operation.accountId,
1215
+ ServicePrincipal: props.operation.servicePrincipal
1216
+ })
1217
+ );
1218
+ props.logger.log(
1219
+ `Done: "${props.operation.accountName}" for ${props.operation.servicePrincipal}`
1220
+ );
1221
+ return upsertDelegatedAdministratorInWorkingState({
1222
+ workingState: props.state,
1223
+ delegatedAdministrator: {
1224
+ accountId: props.operation.accountId,
1225
+ servicePrincipal: props.operation.servicePrincipal
1226
+ }
1227
+ });
1228
+ }
1229
+ if (props.operation.kind === "deregisterDelegatedAdministrator") {
1230
+ props.logger.log(
1231
+ `Deregistering delegated administrator "${props.operation.accountName}" (${props.operation.accountId}) for ${props.operation.servicePrincipal}...`
1232
+ );
1233
+ await props.organizationsClient.send(
1234
+ new DeregisterDelegatedAdministratorCommand({
1235
+ AccountId: props.operation.accountId,
1236
+ ServicePrincipal: props.operation.servicePrincipal
1237
+ })
1238
+ );
1239
+ props.logger.log(
1240
+ `Done: removed "${props.operation.accountName}" for ${props.operation.servicePrincipal}`
1241
+ );
1242
+ return removeDelegatedAdministratorFromWorkingState({
1243
+ workingState: props.state,
1244
+ accountId: props.operation.accountId,
1245
+ servicePrincipal: props.operation.servicePrincipal
1246
+ });
1247
+ }
1248
+ assertUnreachable(props.operation, "Unsupported operation kind in apply.");
1139
1249
  }
1140
1250
  function resolveAssignmentDependencies(props) {
1141
1251
  const account = props.state.organization.accountsByName[props.accountName];