@beesolve/aws-accounts 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +189 -0
- package/dist/accountCreation.js +135 -0
- package/dist/applyLogic.js +1203 -0
- package/dist/awsClientConfig.js +26 -0
- package/dist/awsConfig.js +1365 -0
- package/dist/cli.js +201 -0
- package/dist/commands/graveyard.js +46 -0
- package/dist/commands/regenerate.js +17 -0
- package/dist/commands/remote.js +925 -0
- package/dist/diff.js +1012 -0
- package/dist/error.js +66 -0
- package/dist/helpers.js +21 -0
- package/dist/lambda/handler.js +375 -0
- package/dist/lambdaClient.js +220 -0
- package/dist/logger.js +26 -0
- package/dist/operations.js +218 -0
- package/dist/remoteStateCache.js +38 -0
- package/dist/reservedOuDeletion.js +46 -0
- package/dist/scanLogic.js +456 -0
- package/dist/state.js +618 -0
- package/dist/tags.js +14 -0
- package/dist-lambda/handler.mjs +3558 -0
- package/dist-lambda/lambda.zip +0 -0
- package/package.json +59 -0
package/dist/diff.js
ADDED
|
@@ -0,0 +1,1012 @@
|
|
|
1
|
+
import * as v from "valibot";
|
|
2
|
+
import {
|
|
3
|
+
planSchema
|
|
4
|
+
} from "./operations.js";
|
|
5
|
+
const pendingCreationId = "__pending_creation__";
|
|
6
|
+
const operationExecutionPriority = {
|
|
7
|
+
createOu: 1,
|
|
8
|
+
renameOu: 2,
|
|
9
|
+
createAccount: 3,
|
|
10
|
+
updateAccountTags: 4,
|
|
11
|
+
updateAccountName: 5,
|
|
12
|
+
moveAccount: 6,
|
|
13
|
+
removeAccount: 7,
|
|
14
|
+
createIdcUser: 8,
|
|
15
|
+
updateIdcUser: 9,
|
|
16
|
+
createIdcGroup: 10,
|
|
17
|
+
updateIdcGroupDescription: 11,
|
|
18
|
+
addIdcGroupMembership: 12,
|
|
19
|
+
createIdcPermissionSet: 13,
|
|
20
|
+
updateIdcPermissionSetDescription: 14,
|
|
21
|
+
putIdcPermissionSetInlinePolicy: 15,
|
|
22
|
+
deleteIdcPermissionSetInlinePolicy: 16,
|
|
23
|
+
attachIdcManagedPolicyToPermissionSet: 17,
|
|
24
|
+
detachIdcManagedPolicyFromPermissionSet: 18,
|
|
25
|
+
attachIdcCustomerManagedPolicyReferenceToPermissionSet: 19,
|
|
26
|
+
detachIdcCustomerManagedPolicyReferenceFromPermissionSet: 20,
|
|
27
|
+
provisionIdcPermissionSet: 21,
|
|
28
|
+
grantIdcAccountAssignment: 22,
|
|
29
|
+
removeIdcGroupMembership: 23,
|
|
30
|
+
revokeIdcAccountAssignment: 24,
|
|
31
|
+
deleteIdcUser: 25,
|
|
32
|
+
deleteIdcGroup: 26,
|
|
33
|
+
deleteIdcPermissionSet: 27,
|
|
34
|
+
deleteOu: 28
|
|
35
|
+
};
|
|
36
|
+
function diffStates(props) {
|
|
37
|
+
const operations = [];
|
|
38
|
+
const unsupported = [];
|
|
39
|
+
const currentOrganization = normalizeOrganizationState({
|
|
40
|
+
state: props.current,
|
|
41
|
+
includeDepthById: true
|
|
42
|
+
});
|
|
43
|
+
const nextOrganization = normalizeOrganizationState({
|
|
44
|
+
state: props.next
|
|
45
|
+
});
|
|
46
|
+
const nextAccountIds = new Set(
|
|
47
|
+
nextOrganization.accounts.filter((account) => account.id !== pendingCreationId).map((account) => account.id)
|
|
48
|
+
);
|
|
49
|
+
for (const nextAccount of nextOrganization.accounts) {
|
|
50
|
+
const currentAccount = nextAccount.id !== pendingCreationId ? currentOrganization.accountById.get(nextAccount.id) : void 0;
|
|
51
|
+
if (currentAccount == null) {
|
|
52
|
+
if (nextAccount.id === pendingCreationId) {
|
|
53
|
+
const targetOuName = resolveOrganizationalUnitName({
|
|
54
|
+
organizationalUnitNameById: nextOrganization.organizationalUnitNameById,
|
|
55
|
+
rootId: nextOrganization.rootId,
|
|
56
|
+
organizationalUnitId: nextAccount.parentId
|
|
57
|
+
});
|
|
58
|
+
if (isResolvableOrganizationalUnitId({
|
|
59
|
+
rootId: nextOrganization.rootId,
|
|
60
|
+
organizationalUnitNameById: nextOrganization.organizationalUnitNameById,
|
|
61
|
+
organizationalUnitId: nextAccount.parentId
|
|
62
|
+
}) === false) {
|
|
63
|
+
unsupported.push({
|
|
64
|
+
kind: "newAccountWithUnknownOu",
|
|
65
|
+
category: "unsupportedMutation",
|
|
66
|
+
description: `new account "${nextAccount.name}" has unresolved target OU "${targetOuName}" (${nextAccount.parentId})`
|
|
67
|
+
});
|
|
68
|
+
continue;
|
|
69
|
+
}
|
|
70
|
+
operations.push({
|
|
71
|
+
kind: "createAccount",
|
|
72
|
+
accountName: nextAccount.name,
|
|
73
|
+
accountEmail: nextAccount.email,
|
|
74
|
+
targetOuId: nextAccount.parentId,
|
|
75
|
+
targetOuName
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
continue;
|
|
79
|
+
}
|
|
80
|
+
if (nextAccount.parentId === currentAccount.parentId) {
|
|
81
|
+
if (currentAccount.name !== nextAccount.name) {
|
|
82
|
+
operations.push({
|
|
83
|
+
kind: "updateAccountName",
|
|
84
|
+
accountId: nextAccount.id,
|
|
85
|
+
fromAccountName: currentAccount.name,
|
|
86
|
+
toAccountName: nextAccount.name
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
const currentTags = normalizeAccountTags(currentAccount.tags);
|
|
90
|
+
const nextTags = normalizeAccountTags(nextAccount.tags);
|
|
91
|
+
if (JSON.stringify(currentTags) !== JSON.stringify(nextTags)) {
|
|
92
|
+
operations.push({
|
|
93
|
+
kind: "updateAccountTags",
|
|
94
|
+
accountId: nextAccount.id,
|
|
95
|
+
accountName: nextAccount.name,
|
|
96
|
+
tags: Object.fromEntries(
|
|
97
|
+
(nextTags ?? []).map((tag) => [tag.key, tag.value])
|
|
98
|
+
)
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
continue;
|
|
102
|
+
}
|
|
103
|
+
if (currentAccount.id === pendingCreationId || nextAccount.id === pendingCreationId || currentAccount.parentId === pendingCreationId || nextAccount.parentId === pendingCreationId) {
|
|
104
|
+
continue;
|
|
105
|
+
}
|
|
106
|
+
const fromOuName = resolveOrganizationalUnitName({
|
|
107
|
+
organizationalUnitNameById: currentOrganization.organizationalUnitNameById,
|
|
108
|
+
rootId: currentOrganization.rootId,
|
|
109
|
+
organizationalUnitId: currentAccount.parentId
|
|
110
|
+
});
|
|
111
|
+
const toOuName = resolveOrganizationalUnitName({
|
|
112
|
+
organizationalUnitNameById: nextOrganization.organizationalUnitNameById,
|
|
113
|
+
rootId: nextOrganization.rootId,
|
|
114
|
+
organizationalUnitId: nextAccount.parentId
|
|
115
|
+
});
|
|
116
|
+
if (currentAccount.name !== nextAccount.name) {
|
|
117
|
+
operations.push({
|
|
118
|
+
kind: "updateAccountName",
|
|
119
|
+
accountId: nextAccount.id,
|
|
120
|
+
fromAccountName: currentAccount.name,
|
|
121
|
+
toAccountName: nextAccount.name
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
operations.push({
|
|
125
|
+
kind: "moveAccount",
|
|
126
|
+
accountId: nextAccount.id,
|
|
127
|
+
accountName: nextAccount.name,
|
|
128
|
+
fromOuId: currentAccount.parentId,
|
|
129
|
+
fromOuName,
|
|
130
|
+
toOuId: nextAccount.parentId,
|
|
131
|
+
toOuName
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
const graveyardOrganizationalUnit = currentOrganization.organizationalUnitByName.get("Graveyard");
|
|
135
|
+
for (const currentAccount of currentOrganization.accounts) {
|
|
136
|
+
if (currentAccount.id !== pendingCreationId && nextAccountIds.has(currentAccount.id)) {
|
|
137
|
+
continue;
|
|
138
|
+
}
|
|
139
|
+
if (graveyardOrganizationalUnit == null) {
|
|
140
|
+
unsupported.push({
|
|
141
|
+
kind: "removedOu",
|
|
142
|
+
category: "destructive",
|
|
143
|
+
description: `removed account "${currentAccount.name}" cannot be reconciled because reserved OU "Graveyard" was not found in state`
|
|
144
|
+
});
|
|
145
|
+
continue;
|
|
146
|
+
}
|
|
147
|
+
if (currentAccount.parentId === graveyardOrganizationalUnit.id) {
|
|
148
|
+
continue;
|
|
149
|
+
}
|
|
150
|
+
const fromOuName = resolveOrganizationalUnitName({
|
|
151
|
+
organizationalUnitNameById: currentOrganization.organizationalUnitNameById,
|
|
152
|
+
rootId: currentOrganization.rootId,
|
|
153
|
+
organizationalUnitId: currentAccount.parentId
|
|
154
|
+
});
|
|
155
|
+
operations.push({
|
|
156
|
+
kind: "removeAccount",
|
|
157
|
+
accountId: currentAccount.id,
|
|
158
|
+
accountName: currentAccount.name,
|
|
159
|
+
fromOuId: currentAccount.parentId,
|
|
160
|
+
fromOuName,
|
|
161
|
+
toOuId: graveyardOrganizationalUnit.id,
|
|
162
|
+
toOuName: graveyardOrganizationalUnit.name
|
|
163
|
+
});
|
|
164
|
+
}
|
|
165
|
+
for (const nextOrganizationalUnit of nextOrganization.organizationalUnits) {
|
|
166
|
+
const currentOrganizationalUnit = currentOrganization.organizationalUnitByName.get(
|
|
167
|
+
nextOrganizationalUnit.name
|
|
168
|
+
);
|
|
169
|
+
if (currentOrganizationalUnit == null) {
|
|
170
|
+
continue;
|
|
171
|
+
}
|
|
172
|
+
if (currentOrganizationalUnit.parentId === nextOrganizationalUnit.parentId) {
|
|
173
|
+
continue;
|
|
174
|
+
}
|
|
175
|
+
const fromParentOuName = resolveOrganizationalUnitName({
|
|
176
|
+
organizationalUnitNameById: currentOrganization.organizationalUnitNameById,
|
|
177
|
+
rootId: currentOrganization.rootId,
|
|
178
|
+
organizationalUnitId: currentOrganizationalUnit.parentId
|
|
179
|
+
});
|
|
180
|
+
const toParentOuName = resolveOrganizationalUnitName({
|
|
181
|
+
organizationalUnitNameById: nextOrganization.organizationalUnitNameById,
|
|
182
|
+
rootId: nextOrganization.rootId,
|
|
183
|
+
organizationalUnitId: nextOrganizationalUnit.parentId
|
|
184
|
+
});
|
|
185
|
+
unsupported.push({
|
|
186
|
+
kind: "reparentedOu",
|
|
187
|
+
category: "unsupportedMutation",
|
|
188
|
+
description: `OU "${nextOrganizationalUnit.name}" changed parent from "${fromParentOuName}" to "${toParentOuName}"`
|
|
189
|
+
});
|
|
190
|
+
}
|
|
191
|
+
const addedOrganizationalUnits = [];
|
|
192
|
+
const removedOrganizationalUnits = [];
|
|
193
|
+
for (const nextOrganizationalUnit of nextOrganization.organizationalUnits) {
|
|
194
|
+
if (currentOrganization.organizationalUnitByName.has(nextOrganizationalUnit.name)) {
|
|
195
|
+
continue;
|
|
196
|
+
}
|
|
197
|
+
addedOrganizationalUnits.push(nextOrganizationalUnit);
|
|
198
|
+
}
|
|
199
|
+
for (const currentOrganizationalUnit of currentOrganization.organizationalUnits) {
|
|
200
|
+
if (nextOrganization.organizationalUnitByName.has(currentOrganizationalUnit.name)) {
|
|
201
|
+
continue;
|
|
202
|
+
}
|
|
203
|
+
removedOrganizationalUnits.push(currentOrganizationalUnit);
|
|
204
|
+
}
|
|
205
|
+
const addedByParentId = groupOrganizationalUnitsByParentId({
|
|
206
|
+
organizationalUnits: addedOrganizationalUnits
|
|
207
|
+
});
|
|
208
|
+
const removedByParentId = groupOrganizationalUnitsByParentId({
|
|
209
|
+
organizationalUnits: removedOrganizationalUnits
|
|
210
|
+
});
|
|
211
|
+
const plannedMoveAccountDeparturesByOuId = countMoveAccountDeparturesByOuId({
|
|
212
|
+
operations
|
|
213
|
+
});
|
|
214
|
+
const consumedAddedOrganizationalUnitNames = /* @__PURE__ */ new Set();
|
|
215
|
+
const consumedRemovedOrganizationalUnitNames = /* @__PURE__ */ new Set();
|
|
216
|
+
const parentIds = /* @__PURE__ */ new Set([
|
|
217
|
+
...addedByParentId.keys(),
|
|
218
|
+
...removedByParentId.keys()
|
|
219
|
+
]);
|
|
220
|
+
for (const parentId of parentIds) {
|
|
221
|
+
const parentAdded = (addedByParentId.get(parentId) ?? []).filter(
|
|
222
|
+
(organizationalUnit) => consumedAddedOrganizationalUnitNames.has(organizationalUnit.name) === false
|
|
223
|
+
);
|
|
224
|
+
const parentRemoved = (removedByParentId.get(parentId) ?? []).filter(
|
|
225
|
+
(organizationalUnit) => consumedRemovedOrganizationalUnitNames.has(organizationalUnit.name) === false
|
|
226
|
+
);
|
|
227
|
+
if (parentAdded.length === 1 && parentRemoved.length === 1) {
|
|
228
|
+
const added = parentAdded[0];
|
|
229
|
+
const removed = parentRemoved[0];
|
|
230
|
+
consumedAddedOrganizationalUnitNames.add(added.name);
|
|
231
|
+
consumedRemovedOrganizationalUnitNames.add(removed.name);
|
|
232
|
+
const parentOuName = resolveOrganizationalUnitName({
|
|
233
|
+
organizationalUnitNameById: nextOrganization.organizationalUnitNameById,
|
|
234
|
+
rootId: nextOrganization.rootId,
|
|
235
|
+
organizationalUnitId: parentId
|
|
236
|
+
});
|
|
237
|
+
operations.push({
|
|
238
|
+
kind: "renameOu",
|
|
239
|
+
ouId: removed.id,
|
|
240
|
+
fromOuName: removed.name,
|
|
241
|
+
toOuName: added.name,
|
|
242
|
+
parentOuId: parentId,
|
|
243
|
+
parentOuName
|
|
244
|
+
});
|
|
245
|
+
continue;
|
|
246
|
+
}
|
|
247
|
+
if (parentAdded.length > 0 && parentRemoved.length > 0) {
|
|
248
|
+
const parentOuName = resolveOrganizationalUnitName({
|
|
249
|
+
organizationalUnitNameById: nextOrganization.organizationalUnitNameById,
|
|
250
|
+
rootId: nextOrganization.rootId,
|
|
251
|
+
organizationalUnitId: parentId
|
|
252
|
+
});
|
|
253
|
+
unsupported.push({
|
|
254
|
+
kind: "ambiguousOuRename",
|
|
255
|
+
category: "unsupportedMutation",
|
|
256
|
+
description: `ambiguous OU rename under "${parentOuName}" (added: ${parentAdded.map((organizationalUnit) => organizationalUnit.name).sort((left, right) => left.localeCompare(right)).join(", ")}; removed: ${parentRemoved.map((organizationalUnit) => organizationalUnit.name).sort((left, right) => left.localeCompare(right)).join(", ")})`
|
|
257
|
+
});
|
|
258
|
+
for (const organizationalUnit of parentAdded) {
|
|
259
|
+
consumedAddedOrganizationalUnitNames.add(organizationalUnit.name);
|
|
260
|
+
}
|
|
261
|
+
for (const organizationalUnit of parentRemoved) {
|
|
262
|
+
consumedRemovedOrganizationalUnitNames.add(organizationalUnit.name);
|
|
263
|
+
}
|
|
264
|
+
continue;
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
for (const addedOrganizationalUnit of addedOrganizationalUnits) {
|
|
268
|
+
if (consumedAddedOrganizationalUnitNames.has(addedOrganizationalUnit.name)) {
|
|
269
|
+
continue;
|
|
270
|
+
}
|
|
271
|
+
const parentOuName = resolveOrganizationalUnitName({
|
|
272
|
+
organizationalUnitNameById: nextOrganization.organizationalUnitNameById,
|
|
273
|
+
rootId: nextOrganization.rootId,
|
|
274
|
+
organizationalUnitId: addedOrganizationalUnit.parentId
|
|
275
|
+
});
|
|
276
|
+
if (isResolvableOrganizationalUnitId({
|
|
277
|
+
rootId: nextOrganization.rootId,
|
|
278
|
+
organizationalUnitNameById: nextOrganization.organizationalUnitNameById,
|
|
279
|
+
organizationalUnitId: addedOrganizationalUnit.parentId
|
|
280
|
+
}) === false) {
|
|
281
|
+
unsupported.push({
|
|
282
|
+
kind: "newOuWithUnknownParent",
|
|
283
|
+
category: "unsupportedMutation",
|
|
284
|
+
description: `new OU "${addedOrganizationalUnit.name}" has unresolved parent "${parentOuName}" (${addedOrganizationalUnit.parentId})`
|
|
285
|
+
});
|
|
286
|
+
continue;
|
|
287
|
+
}
|
|
288
|
+
operations.push({
|
|
289
|
+
kind: "createOu",
|
|
290
|
+
ouName: addedOrganizationalUnit.name,
|
|
291
|
+
parentOuId: addedOrganizationalUnit.parentId,
|
|
292
|
+
parentOuName
|
|
293
|
+
});
|
|
294
|
+
}
|
|
295
|
+
const pendingRemovedOrganizationalUnits = removedOrganizationalUnits.filter(
|
|
296
|
+
(organizationalUnit) => consumedRemovedOrganizationalUnitNames.has(organizationalUnit.name) === false
|
|
297
|
+
);
|
|
298
|
+
const pendingRemovedOrganizationalUnitIds = new Set(
|
|
299
|
+
pendingRemovedOrganizationalUnits.map(
|
|
300
|
+
(organizationalUnit) => organizationalUnit.id
|
|
301
|
+
)
|
|
302
|
+
);
|
|
303
|
+
const deleteEligibilityByOuId = createDeleteEligibilityByOuId({
|
|
304
|
+
removedOrganizationalUnits: pendingRemovedOrganizationalUnits,
|
|
305
|
+
removedOrganizationalUnitIds: pendingRemovedOrganizationalUnitIds,
|
|
306
|
+
currentOrganizationalUnitsByParentId: currentOrganization.organizationalUnitsByParentId,
|
|
307
|
+
currentAccountsByParentId: currentOrganization.accountsByParentId,
|
|
308
|
+
plannedMoveAccountDeparturesByOuId
|
|
309
|
+
});
|
|
310
|
+
for (const removedOrganizationalUnit of pendingRemovedOrganizationalUnits) {
|
|
311
|
+
if (deleteEligibilityByOuId.get(removedOrganizationalUnit.id) === true) {
|
|
312
|
+
const parentOuName = resolveOrganizationalUnitName({
|
|
313
|
+
organizationalUnitNameById: currentOrganization.organizationalUnitNameById,
|
|
314
|
+
rootId: currentOrganization.rootId,
|
|
315
|
+
organizationalUnitId: removedOrganizationalUnit.parentId
|
|
316
|
+
});
|
|
317
|
+
operations.push({
|
|
318
|
+
kind: "deleteOu",
|
|
319
|
+
ouId: removedOrganizationalUnit.id,
|
|
320
|
+
ouName: removedOrganizationalUnit.name,
|
|
321
|
+
parentOuId: removedOrganizationalUnit.parentId,
|
|
322
|
+
parentOuName
|
|
323
|
+
});
|
|
324
|
+
continue;
|
|
325
|
+
}
|
|
326
|
+
unsupported.push({
|
|
327
|
+
kind: "removedOu",
|
|
328
|
+
category: "destructive",
|
|
329
|
+
description: `removed OU "${removedOrganizationalUnit.name}"`
|
|
330
|
+
});
|
|
331
|
+
}
|
|
332
|
+
const currentIdcView = normalizeIdentityCenterState({
|
|
333
|
+
state: props.current
|
|
334
|
+
});
|
|
335
|
+
const nextIdcView = normalizeIdentityCenterState({
|
|
336
|
+
state: props.next
|
|
337
|
+
});
|
|
338
|
+
for (const nextUser of props.next.identityCenter.users) {
|
|
339
|
+
if (currentIdcView.usersByUserName.has(nextUser.userName)) {
|
|
340
|
+
continue;
|
|
341
|
+
}
|
|
342
|
+
operations.push({
|
|
343
|
+
kind: "createIdcUser",
|
|
344
|
+
userName: nextUser.userName,
|
|
345
|
+
displayName: nextUser.displayName,
|
|
346
|
+
email: nextUser.email
|
|
347
|
+
});
|
|
348
|
+
}
|
|
349
|
+
for (const nextUser of props.next.identityCenter.users) {
|
|
350
|
+
const currentUser = currentIdcView.usersByUserName.get(nextUser.userName);
|
|
351
|
+
if (currentUser == null) {
|
|
352
|
+
continue;
|
|
353
|
+
}
|
|
354
|
+
const emailWouldChange = currentUser.email !== nextUser.email && nextUser.email.length > 0;
|
|
355
|
+
if (currentUser.displayName === nextUser.displayName && emailWouldChange === false) {
|
|
356
|
+
continue;
|
|
357
|
+
}
|
|
358
|
+
operations.push({
|
|
359
|
+
kind: "updateIdcUser",
|
|
360
|
+
userName: nextUser.userName,
|
|
361
|
+
displayName: nextUser.displayName,
|
|
362
|
+
email: nextUser.email
|
|
363
|
+
});
|
|
364
|
+
}
|
|
365
|
+
for (const nextGroup of props.next.identityCenter.groups) {
|
|
366
|
+
if (currentIdcView.groupsByDisplayName.has(nextGroup.displayName)) {
|
|
367
|
+
continue;
|
|
368
|
+
}
|
|
369
|
+
operations.push({
|
|
370
|
+
kind: "createIdcGroup",
|
|
371
|
+
groupDisplayName: nextGroup.displayName,
|
|
372
|
+
description: nextGroup.description ?? ""
|
|
373
|
+
});
|
|
374
|
+
}
|
|
375
|
+
for (const nextGroup of props.next.identityCenter.groups) {
|
|
376
|
+
const currentGroup = currentIdcView.groupsByDisplayName.get(
|
|
377
|
+
nextGroup.displayName
|
|
378
|
+
);
|
|
379
|
+
if (currentGroup == null) {
|
|
380
|
+
continue;
|
|
381
|
+
}
|
|
382
|
+
if ((currentGroup.description ?? "") === (nextGroup.description ?? "")) {
|
|
383
|
+
continue;
|
|
384
|
+
}
|
|
385
|
+
operations.push({
|
|
386
|
+
kind: "updateIdcGroupDescription",
|
|
387
|
+
groupDisplayName: nextGroup.displayName,
|
|
388
|
+
description: nextGroup.description ?? ""
|
|
389
|
+
});
|
|
390
|
+
}
|
|
391
|
+
const removedUserNames = new Set(
|
|
392
|
+
props.current.identityCenter.users.filter(
|
|
393
|
+
(user) => nextIdcView.usersByUserName.has(user.userName) === false
|
|
394
|
+
).map((user) => user.userName)
|
|
395
|
+
);
|
|
396
|
+
const removedGroupDisplayNames = new Set(
|
|
397
|
+
props.current.identityCenter.groups.filter(
|
|
398
|
+
(group) => nextIdcView.groupsByDisplayName.has(group.displayName) === false
|
|
399
|
+
).map((group) => group.displayName)
|
|
400
|
+
);
|
|
401
|
+
const removedPermissionSetNames = new Set(
|
|
402
|
+
props.current.identityCenter.permissionSets.filter(
|
|
403
|
+
(permissionSet) => nextIdcView.permissionSetsByName.has(permissionSet.name) === false
|
|
404
|
+
).map((permissionSet) => permissionSet.name)
|
|
405
|
+
);
|
|
406
|
+
const permissionSetNamesWithDesiredAssignments = new Set(
|
|
407
|
+
[...nextIdcView.assignmentsByKey.values()].map(
|
|
408
|
+
(assignment) => assignment.permissionSetName
|
|
409
|
+
)
|
|
410
|
+
);
|
|
411
|
+
for (const nextMembership of nextIdcView.membershipsByKey.values()) {
|
|
412
|
+
const membershipKey = createNormalizedIdcMembershipKey({
|
|
413
|
+
membership: nextMembership
|
|
414
|
+
});
|
|
415
|
+
if (currentIdcView.membershipsByKey.has(membershipKey)) {
|
|
416
|
+
continue;
|
|
417
|
+
}
|
|
418
|
+
operations.push({
|
|
419
|
+
kind: "addIdcGroupMembership",
|
|
420
|
+
groupDisplayName: nextMembership.groupDisplayName,
|
|
421
|
+
userName: nextMembership.userName
|
|
422
|
+
});
|
|
423
|
+
}
|
|
424
|
+
for (const currentMembership of currentIdcView.membershipsByKey.values()) {
|
|
425
|
+
const membershipKey = createNormalizedIdcMembershipKey({
|
|
426
|
+
membership: currentMembership
|
|
427
|
+
});
|
|
428
|
+
if (nextIdcView.membershipsByKey.has(membershipKey) && removedUserNames.has(currentMembership.userName) === false && removedGroupDisplayNames.has(currentMembership.groupDisplayName) === false) {
|
|
429
|
+
continue;
|
|
430
|
+
}
|
|
431
|
+
operations.push({
|
|
432
|
+
kind: "removeIdcGroupMembership",
|
|
433
|
+
groupDisplayName: currentMembership.groupDisplayName,
|
|
434
|
+
userName: currentMembership.userName
|
|
435
|
+
});
|
|
436
|
+
}
|
|
437
|
+
for (const nextPermissionSet of props.next.identityCenter.permissionSets) {
|
|
438
|
+
const currentPermissionSet = currentIdcView.permissionSetsByName.get(nextPermissionSet.name);
|
|
439
|
+
if (currentPermissionSet == null) {
|
|
440
|
+
operations.push({
|
|
441
|
+
kind: "createIdcPermissionSet",
|
|
442
|
+
permissionSetName: nextPermissionSet.name,
|
|
443
|
+
description: nextPermissionSet.description
|
|
444
|
+
});
|
|
445
|
+
}
|
|
446
|
+
const permissionSetMutationStartIndex = operations.length;
|
|
447
|
+
if (currentPermissionSet != null) {
|
|
448
|
+
if (currentPermissionSet.description !== nextPermissionSet.description) {
|
|
449
|
+
operations.push({
|
|
450
|
+
kind: "updateIdcPermissionSetDescription",
|
|
451
|
+
permissionSetName: nextPermissionSet.name,
|
|
452
|
+
description: nextPermissionSet.description
|
|
453
|
+
});
|
|
454
|
+
}
|
|
455
|
+
}
|
|
456
|
+
const currentInlinePolicy = normalizeInlinePolicyString(
|
|
457
|
+
currentPermissionSet?.inlinePolicy ?? null
|
|
458
|
+
);
|
|
459
|
+
const nextInlinePolicy = normalizeInlinePolicyString(
|
|
460
|
+
nextPermissionSet.inlinePolicy
|
|
461
|
+
);
|
|
462
|
+
if (nextInlinePolicy != null && nextInlinePolicy !== currentInlinePolicy) {
|
|
463
|
+
operations.push({
|
|
464
|
+
kind: "putIdcPermissionSetInlinePolicy",
|
|
465
|
+
permissionSetName: nextPermissionSet.name,
|
|
466
|
+
inlinePolicy: nextInlinePolicy
|
|
467
|
+
});
|
|
468
|
+
}
|
|
469
|
+
if (nextInlinePolicy == null && currentInlinePolicy != null) {
|
|
470
|
+
operations.push({
|
|
471
|
+
kind: "deleteIdcPermissionSetInlinePolicy",
|
|
472
|
+
permissionSetName: nextPermissionSet.name
|
|
473
|
+
});
|
|
474
|
+
}
|
|
475
|
+
const currentAwsManagedPolicies = new Set(
|
|
476
|
+
currentPermissionSet?.awsManagedPolicies ?? []
|
|
477
|
+
);
|
|
478
|
+
const nextAwsManagedPolicies = new Set(nextPermissionSet.awsManagedPolicies);
|
|
479
|
+
for (const managedPolicyArn of nextAwsManagedPolicies) {
|
|
480
|
+
if (currentAwsManagedPolicies.has(managedPolicyArn)) {
|
|
481
|
+
continue;
|
|
482
|
+
}
|
|
483
|
+
operations.push({
|
|
484
|
+
kind: "attachIdcManagedPolicyToPermissionSet",
|
|
485
|
+
permissionSetName: nextPermissionSet.name,
|
|
486
|
+
managedPolicyArn
|
|
487
|
+
});
|
|
488
|
+
}
|
|
489
|
+
for (const managedPolicyArn of currentAwsManagedPolicies) {
|
|
490
|
+
if (nextAwsManagedPolicies.has(managedPolicyArn)) {
|
|
491
|
+
continue;
|
|
492
|
+
}
|
|
493
|
+
operations.push({
|
|
494
|
+
kind: "detachIdcManagedPolicyFromPermissionSet",
|
|
495
|
+
permissionSetName: nextPermissionSet.name,
|
|
496
|
+
managedPolicyArn
|
|
497
|
+
});
|
|
498
|
+
}
|
|
499
|
+
const currentCustomerManagedPolicies = new Map(
|
|
500
|
+
(currentPermissionSet?.customerManagedPolicies ?? []).map((policy) => [
|
|
501
|
+
createCustomerManagedPolicyReferenceKey(policy),
|
|
502
|
+
policy
|
|
503
|
+
])
|
|
504
|
+
);
|
|
505
|
+
const nextCustomerManagedPolicies = new Map(
|
|
506
|
+
nextPermissionSet.customerManagedPolicies.map((policy) => [
|
|
507
|
+
createCustomerManagedPolicyReferenceKey(policy),
|
|
508
|
+
policy
|
|
509
|
+
])
|
|
510
|
+
);
|
|
511
|
+
for (const [policyKey, customerManagedPolicy] of nextCustomerManagedPolicies) {
|
|
512
|
+
if (currentCustomerManagedPolicies.has(policyKey)) {
|
|
513
|
+
continue;
|
|
514
|
+
}
|
|
515
|
+
operations.push({
|
|
516
|
+
kind: "attachIdcCustomerManagedPolicyReferenceToPermissionSet",
|
|
517
|
+
permissionSetName: nextPermissionSet.name,
|
|
518
|
+
customerManagedPolicyName: customerManagedPolicy.name,
|
|
519
|
+
customerManagedPolicyPath: customerManagedPolicy.path
|
|
520
|
+
});
|
|
521
|
+
}
|
|
522
|
+
for (const [policyKey, customerManagedPolicy] of currentCustomerManagedPolicies) {
|
|
523
|
+
if (nextCustomerManagedPolicies.has(policyKey)) {
|
|
524
|
+
continue;
|
|
525
|
+
}
|
|
526
|
+
operations.push({
|
|
527
|
+
kind: "detachIdcCustomerManagedPolicyReferenceFromPermissionSet",
|
|
528
|
+
permissionSetName: nextPermissionSet.name,
|
|
529
|
+
customerManagedPolicyName: customerManagedPolicy.name,
|
|
530
|
+
customerManagedPolicyPath: customerManagedPolicy.path
|
|
531
|
+
});
|
|
532
|
+
}
|
|
533
|
+
if (currentPermissionSet != null && operations.length > permissionSetMutationStartIndex && permissionSetNamesWithDesiredAssignments.has(nextPermissionSet.name)) {
|
|
534
|
+
operations.push({
|
|
535
|
+
kind: "provisionIdcPermissionSet",
|
|
536
|
+
permissionSetName: nextPermissionSet.name,
|
|
537
|
+
targetScope: "ALL_PROVISIONED_ACCOUNTS"
|
|
538
|
+
});
|
|
539
|
+
}
|
|
540
|
+
}
|
|
541
|
+
for (const nextAssignment of nextIdcView.assignmentsByKey.values()) {
|
|
542
|
+
const assignmentKey = createNormalizedIdcAssignmentKey({
|
|
543
|
+
assignment: nextAssignment
|
|
544
|
+
});
|
|
545
|
+
if (currentIdcView.assignmentsByKey.has(assignmentKey)) {
|
|
546
|
+
continue;
|
|
547
|
+
}
|
|
548
|
+
operations.push({
|
|
549
|
+
kind: "grantIdcAccountAssignment",
|
|
550
|
+
accountName: nextAssignment.accountName,
|
|
551
|
+
permissionSetName: nextAssignment.permissionSetName,
|
|
552
|
+
principalType: nextAssignment.principalType,
|
|
553
|
+
principalName: nextAssignment.principalName
|
|
554
|
+
});
|
|
555
|
+
}
|
|
556
|
+
for (const currentAssignment of currentIdcView.assignmentsByKey.values()) {
|
|
557
|
+
const assignmentKey = createNormalizedIdcAssignmentKey({
|
|
558
|
+
assignment: currentAssignment
|
|
559
|
+
});
|
|
560
|
+
if (nextIdcView.assignmentsByKey.has(assignmentKey) && removedPermissionSetNames.has(currentAssignment.permissionSetName) === false && (currentAssignment.principalType === "USER" ? removedUserNames.has(currentAssignment.principalName) === false : removedGroupDisplayNames.has(currentAssignment.principalName) === false)) {
|
|
561
|
+
continue;
|
|
562
|
+
}
|
|
563
|
+
operations.push({
|
|
564
|
+
kind: "revokeIdcAccountAssignment",
|
|
565
|
+
accountName: currentAssignment.accountName,
|
|
566
|
+
permissionSetName: currentAssignment.permissionSetName,
|
|
567
|
+
principalType: currentAssignment.principalType,
|
|
568
|
+
principalName: currentAssignment.principalName
|
|
569
|
+
});
|
|
570
|
+
}
|
|
571
|
+
for (const removedUserName of removedUserNames) {
|
|
572
|
+
operations.push({
|
|
573
|
+
kind: "deleteIdcUser",
|
|
574
|
+
userName: removedUserName
|
|
575
|
+
});
|
|
576
|
+
}
|
|
577
|
+
for (const removedGroupDisplayName of removedGroupDisplayNames) {
|
|
578
|
+
operations.push({
|
|
579
|
+
kind: "deleteIdcGroup",
|
|
580
|
+
groupDisplayName: removedGroupDisplayName
|
|
581
|
+
});
|
|
582
|
+
}
|
|
583
|
+
for (const removedPermissionSetName of removedPermissionSetNames) {
|
|
584
|
+
operations.push({
|
|
585
|
+
kind: "deleteIdcPermissionSet",
|
|
586
|
+
permissionSetName: removedPermissionSetName
|
|
587
|
+
});
|
|
588
|
+
}
|
|
589
|
+
operations.sort((left, right) => {
|
|
590
|
+
const priorityComparison = getOperationExecutionPriority(left) - getOperationExecutionPriority(right);
|
|
591
|
+
if (priorityComparison !== 0) {
|
|
592
|
+
return priorityComparison;
|
|
593
|
+
}
|
|
594
|
+
if (left.kind === "deleteOu" && right.kind === "deleteOu") {
|
|
595
|
+
const depthComparison = (currentOrganization.organizationalUnitDepthById.get(right.ouId) ?? 0) - (currentOrganization.organizationalUnitDepthById.get(left.ouId) ?? 0);
|
|
596
|
+
if (depthComparison !== 0) {
|
|
597
|
+
return depthComparison;
|
|
598
|
+
}
|
|
599
|
+
}
|
|
600
|
+
return getOperationSortKey(left).localeCompare(getOperationSortKey(right));
|
|
601
|
+
});
|
|
602
|
+
unsupported.sort((left, right) => {
|
|
603
|
+
const kindComparison = left.kind.localeCompare(right.kind);
|
|
604
|
+
if (kindComparison !== 0) {
|
|
605
|
+
return kindComparison;
|
|
606
|
+
}
|
|
607
|
+
return left.description.localeCompare(right.description);
|
|
608
|
+
});
|
|
609
|
+
return v.parse(planSchema, {
|
|
610
|
+
operations,
|
|
611
|
+
unsupported
|
|
612
|
+
});
|
|
613
|
+
}
|
|
614
|
+
function groupOrganizationalUnitsByParentId(props) {
|
|
615
|
+
const grouped = /* @__PURE__ */ new Map();
|
|
616
|
+
for (const organizationalUnit of props.organizationalUnits) {
|
|
617
|
+
const existing = grouped.get(organizationalUnit.parentId) ?? [];
|
|
618
|
+
existing.push(organizationalUnit);
|
|
619
|
+
grouped.set(organizationalUnit.parentId, existing);
|
|
620
|
+
}
|
|
621
|
+
return grouped;
|
|
622
|
+
}
|
|
623
|
+
function countChildrenByParentId(props) {
|
|
624
|
+
const counts = /* @__PURE__ */ new Map();
|
|
625
|
+
for (const value of props.values) {
|
|
626
|
+
counts.set(value.parentId, (counts.get(value.parentId) ?? 0) + 1);
|
|
627
|
+
}
|
|
628
|
+
return counts;
|
|
629
|
+
}
|
|
630
|
+
function countMoveAccountDeparturesByOuId(props) {
|
|
631
|
+
const counts = /* @__PURE__ */ new Map();
|
|
632
|
+
for (const operation of props.operations) {
|
|
633
|
+
if (operation.kind !== "moveAccount") {
|
|
634
|
+
continue;
|
|
635
|
+
}
|
|
636
|
+
counts.set(operation.fromOuId, (counts.get(operation.fromOuId) ?? 0) + 1);
|
|
637
|
+
}
|
|
638
|
+
return counts;
|
|
639
|
+
}
|
|
640
|
+
function normalizeOrganizationState(props) {
|
|
641
|
+
const organizationalUnitByName = new Map(
|
|
642
|
+
props.state.organization.organizationalUnits.map((organizationalUnit) => [
|
|
643
|
+
organizationalUnit.name,
|
|
644
|
+
organizationalUnit
|
|
645
|
+
])
|
|
646
|
+
);
|
|
647
|
+
const organizationalUnitById = new Map(
|
|
648
|
+
props.state.organization.organizationalUnits.map((organizationalUnit) => [
|
|
649
|
+
organizationalUnit.id,
|
|
650
|
+
organizationalUnit
|
|
651
|
+
])
|
|
652
|
+
);
|
|
653
|
+
const accountByName = new Map(
|
|
654
|
+
props.state.organization.accounts.map((account) => [account.name, account])
|
|
655
|
+
);
|
|
656
|
+
const accountById = /* @__PURE__ */ new Map();
|
|
657
|
+
for (const account of props.state.organization.accounts) {
|
|
658
|
+
if (account.id !== pendingCreationId) {
|
|
659
|
+
accountById.set(account.id, account);
|
|
660
|
+
}
|
|
661
|
+
}
|
|
662
|
+
const organizationalUnitNameById = new Map(
|
|
663
|
+
props.state.organization.organizationalUnits.map((organizationalUnit) => [
|
|
664
|
+
organizationalUnit.id,
|
|
665
|
+
organizationalUnit.name
|
|
666
|
+
])
|
|
667
|
+
);
|
|
668
|
+
const organizationalUnitsByParentId = groupOrganizationalUnitsByParentId({
|
|
669
|
+
organizationalUnits: props.state.organization.organizationalUnits
|
|
670
|
+
});
|
|
671
|
+
const accountsByParentId = countChildrenByParentId({
|
|
672
|
+
values: props.state.organization.accounts
|
|
673
|
+
});
|
|
674
|
+
return {
|
|
675
|
+
rootId: props.state.organization.rootId,
|
|
676
|
+
organizationalUnits: props.state.organization.organizationalUnits,
|
|
677
|
+
accounts: props.state.organization.accounts,
|
|
678
|
+
organizationalUnitByName,
|
|
679
|
+
accountByName,
|
|
680
|
+
accountById,
|
|
681
|
+
organizationalUnitNameById,
|
|
682
|
+
organizationalUnitsByParentId,
|
|
683
|
+
accountsByParentId,
|
|
684
|
+
organizationalUnitDepthById: props.includeDepthById ? createOrganizationalUnitDepthById({
|
|
685
|
+
rootId: props.state.organization.rootId,
|
|
686
|
+
organizationalUnitById
|
|
687
|
+
}) : /* @__PURE__ */ new Map()
|
|
688
|
+
};
|
|
689
|
+
}
|
|
690
|
+
function createDeleteEligibilityByOuId(props) {
|
|
691
|
+
const eligibilityByOuId = /* @__PURE__ */ new Map();
|
|
692
|
+
function canDeleteOrganizationalUnit(organizationalUnitId) {
|
|
693
|
+
const cachedEligibility = eligibilityByOuId.get(organizationalUnitId);
|
|
694
|
+
if (cachedEligibility != null) {
|
|
695
|
+
return cachedEligibility;
|
|
696
|
+
}
|
|
697
|
+
const currentChildren = props.currentOrganizationalUnitsByParentId.get(organizationalUnitId) ?? [];
|
|
698
|
+
for (const childOrganizationalUnit of currentChildren) {
|
|
699
|
+
if (props.removedOrganizationalUnitIds.has(childOrganizationalUnit.id) === false) {
|
|
700
|
+
eligibilityByOuId.set(organizationalUnitId, false);
|
|
701
|
+
return false;
|
|
702
|
+
}
|
|
703
|
+
if (canDeleteOrganizationalUnit(childOrganizationalUnit.id) === false) {
|
|
704
|
+
eligibilityByOuId.set(organizationalUnitId, false);
|
|
705
|
+
return false;
|
|
706
|
+
}
|
|
707
|
+
}
|
|
708
|
+
const projectedRemainingAccounts = (props.currentAccountsByParentId.get(organizationalUnitId) ?? 0) - (props.plannedMoveAccountDeparturesByOuId.get(organizationalUnitId) ?? 0);
|
|
709
|
+
const canDelete = projectedRemainingAccounts === 0;
|
|
710
|
+
eligibilityByOuId.set(organizationalUnitId, canDelete);
|
|
711
|
+
return canDelete;
|
|
712
|
+
}
|
|
713
|
+
for (const removedOrganizationalUnit of props.removedOrganizationalUnits) {
|
|
714
|
+
canDeleteOrganizationalUnit(removedOrganizationalUnit.id);
|
|
715
|
+
}
|
|
716
|
+
return eligibilityByOuId;
|
|
717
|
+
}
|
|
718
|
+
function createOrganizationalUnitDepthById(props) {
|
|
719
|
+
const depthById = /* @__PURE__ */ new Map();
|
|
720
|
+
function getDepth(organizationalUnitId) {
|
|
721
|
+
const cachedDepth = depthById.get(organizationalUnitId);
|
|
722
|
+
if (cachedDepth != null) {
|
|
723
|
+
return cachedDepth;
|
|
724
|
+
}
|
|
725
|
+
const organizationalUnit = props.organizationalUnitById.get(organizationalUnitId);
|
|
726
|
+
if (organizationalUnit == null) {
|
|
727
|
+
return 0;
|
|
728
|
+
}
|
|
729
|
+
if (organizationalUnit.parentId === props.rootId) {
|
|
730
|
+
depthById.set(organizationalUnitId, 1);
|
|
731
|
+
return 1;
|
|
732
|
+
}
|
|
733
|
+
const depth = getDepth(organizationalUnit.parentId) + 1;
|
|
734
|
+
depthById.set(organizationalUnitId, depth);
|
|
735
|
+
return depth;
|
|
736
|
+
}
|
|
737
|
+
for (const organizationalUnitId of props.organizationalUnitById.keys()) {
|
|
738
|
+
getDepth(organizationalUnitId);
|
|
739
|
+
}
|
|
740
|
+
return depthById;
|
|
741
|
+
}
|
|
742
|
+
function getOperationExecutionPriority(operation) {
|
|
743
|
+
return operationExecutionPriority[operation.kind];
|
|
744
|
+
}
|
|
745
|
+
function getOperationSortKey(operation) {
|
|
746
|
+
if (operation.kind === "moveAccount") {
|
|
747
|
+
return `${operation.kind}|${operation.accountName}|${operation.accountId}`;
|
|
748
|
+
}
|
|
749
|
+
if (operation.kind === "createOu") {
|
|
750
|
+
return `${operation.kind}|${operation.ouName}|${operation.parentOuName}`;
|
|
751
|
+
}
|
|
752
|
+
if (operation.kind === "renameOu") {
|
|
753
|
+
return `${operation.kind}|${operation.fromOuName}|${operation.toOuName}`;
|
|
754
|
+
}
|
|
755
|
+
if (operation.kind === "createAccount") {
|
|
756
|
+
return `${operation.kind}|${operation.accountName}|${operation.targetOuName}`;
|
|
757
|
+
}
|
|
758
|
+
if (operation.kind === "updateAccountTags") {
|
|
759
|
+
return `${operation.kind}|${operation.accountName}|${operation.accountId}`;
|
|
760
|
+
}
|
|
761
|
+
if (operation.kind === "updateAccountName") {
|
|
762
|
+
return `${operation.kind}|${operation.accountId}|${operation.toAccountName}`;
|
|
763
|
+
}
|
|
764
|
+
if (operation.kind === "removeAccount") {
|
|
765
|
+
return `${operation.kind}|${operation.accountName}|${operation.accountId}`;
|
|
766
|
+
}
|
|
767
|
+
if (operation.kind === "deleteOu") {
|
|
768
|
+
return `${operation.kind}|${operation.ouName}|${operation.parentOuName}`;
|
|
769
|
+
}
|
|
770
|
+
if (operation.kind === "createIdcUser") {
|
|
771
|
+
return `${operation.kind}|${operation.userName}`;
|
|
772
|
+
}
|
|
773
|
+
if (operation.kind === "updateIdcUser") {
|
|
774
|
+
return `${operation.kind}|${operation.userName}`;
|
|
775
|
+
}
|
|
776
|
+
if (operation.kind === "deleteIdcUser") {
|
|
777
|
+
return `${operation.kind}|${operation.userName}`;
|
|
778
|
+
}
|
|
779
|
+
if (operation.kind === "createIdcGroup") {
|
|
780
|
+
return `${operation.kind}|${operation.groupDisplayName}`;
|
|
781
|
+
}
|
|
782
|
+
if (operation.kind === "updateIdcGroupDescription") {
|
|
783
|
+
return `${operation.kind}|${operation.groupDisplayName}`;
|
|
784
|
+
}
|
|
785
|
+
if (operation.kind === "deleteIdcGroup") {
|
|
786
|
+
return `${operation.kind}|${operation.groupDisplayName}`;
|
|
787
|
+
}
|
|
788
|
+
if (operation.kind === "addIdcGroupMembership" || operation.kind === "removeIdcGroupMembership") {
|
|
789
|
+
return `${operation.kind}|${operation.groupDisplayName}|${operation.userName}`;
|
|
790
|
+
}
|
|
791
|
+
if (operation.kind === "createIdcPermissionSet") {
|
|
792
|
+
return `${operation.kind}|${operation.permissionSetName}`;
|
|
793
|
+
}
|
|
794
|
+
if (operation.kind === "deleteIdcPermissionSet") {
|
|
795
|
+
return `${operation.kind}|${operation.permissionSetName}`;
|
|
796
|
+
}
|
|
797
|
+
if (operation.kind === "putIdcPermissionSetInlinePolicy" || operation.kind === "deleteIdcPermissionSetInlinePolicy" || operation.kind === "updateIdcPermissionSetDescription" || operation.kind === "provisionIdcPermissionSet") {
|
|
798
|
+
return `${operation.kind}|${operation.permissionSetName}`;
|
|
799
|
+
}
|
|
800
|
+
if (operation.kind === "attachIdcManagedPolicyToPermissionSet" || operation.kind === "detachIdcManagedPolicyFromPermissionSet") {
|
|
801
|
+
return [
|
|
802
|
+
operation.kind,
|
|
803
|
+
operation.permissionSetName,
|
|
804
|
+
operation.managedPolicyArn
|
|
805
|
+
].join("|");
|
|
806
|
+
}
|
|
807
|
+
if (operation.kind === "attachIdcCustomerManagedPolicyReferenceToPermissionSet" || operation.kind === "detachIdcCustomerManagedPolicyReferenceFromPermissionSet") {
|
|
808
|
+
return [
|
|
809
|
+
operation.kind,
|
|
810
|
+
operation.permissionSetName,
|
|
811
|
+
operation.customerManagedPolicyPath,
|
|
812
|
+
operation.customerManagedPolicyName
|
|
813
|
+
].join("|");
|
|
814
|
+
}
|
|
815
|
+
if (operation.kind === "grantIdcAccountAssignment" || operation.kind === "revokeIdcAccountAssignment") {
|
|
816
|
+
return [
|
|
817
|
+
operation.kind,
|
|
818
|
+
operation.accountName,
|
|
819
|
+
operation.permissionSetName,
|
|
820
|
+
operation.principalType,
|
|
821
|
+
operation.principalName
|
|
822
|
+
].join("|");
|
|
823
|
+
}
|
|
824
|
+
return "zzzz";
|
|
825
|
+
}
|
|
826
|
+
function normalizeAccountTags(tags) {
|
|
827
|
+
if (tags == null || tags.length === 0) {
|
|
828
|
+
return [];
|
|
829
|
+
}
|
|
830
|
+
return [...tags].sort(
|
|
831
|
+
(left, right) => [left.key, left.value].join("|").localeCompare([right.key, right.value].join("|"))
|
|
832
|
+
);
|
|
833
|
+
}
|
|
834
|
+
function normalizeIdentityCenterState(props) {
|
|
835
|
+
const usersByUserName = new Map(
|
|
836
|
+
props.state.identityCenter.users.map((user) => [user.userName, user])
|
|
837
|
+
);
|
|
838
|
+
const groupsByDisplayName = new Map(
|
|
839
|
+
props.state.identityCenter.groups.map((group) => [
|
|
840
|
+
group.displayName,
|
|
841
|
+
group
|
|
842
|
+
])
|
|
843
|
+
);
|
|
844
|
+
const groupDisplayNameById = new Map(
|
|
845
|
+
props.state.identityCenter.groups.map((group) => [
|
|
846
|
+
group.groupId,
|
|
847
|
+
group.displayName
|
|
848
|
+
])
|
|
849
|
+
);
|
|
850
|
+
const userNameById = new Map(
|
|
851
|
+
props.state.identityCenter.users.map((user) => [
|
|
852
|
+
user.userId,
|
|
853
|
+
user.userName
|
|
854
|
+
])
|
|
855
|
+
);
|
|
856
|
+
const membershipsByKey = /* @__PURE__ */ new Map();
|
|
857
|
+
for (const groupMembership of props.state.identityCenter.groupMemberships) {
|
|
858
|
+
const groupDisplayName = groupDisplayNameById.get(groupMembership.groupId);
|
|
859
|
+
if (groupDisplayName == null) {
|
|
860
|
+
throw new Error(
|
|
861
|
+
`Could not resolve group display name for IdC membership groupId "${groupMembership.groupId}".`
|
|
862
|
+
);
|
|
863
|
+
}
|
|
864
|
+
const userName = userNameById.get(groupMembership.userId);
|
|
865
|
+
if (userName == null) {
|
|
866
|
+
throw new Error(
|
|
867
|
+
`Could not resolve user name for IdC membership userId "${groupMembership.userId}".`
|
|
868
|
+
);
|
|
869
|
+
}
|
|
870
|
+
const normalizedMembership = {
|
|
871
|
+
groupDisplayName,
|
|
872
|
+
userName
|
|
873
|
+
};
|
|
874
|
+
membershipsByKey.set(
|
|
875
|
+
createNormalizedIdcMembershipKey({
|
|
876
|
+
membership: normalizedMembership
|
|
877
|
+
}),
|
|
878
|
+
normalizedMembership
|
|
879
|
+
);
|
|
880
|
+
}
|
|
881
|
+
const permissionSetsByName = new Map(
|
|
882
|
+
props.state.identityCenter.permissionSets.map((permissionSet) => [
|
|
883
|
+
permissionSet.name,
|
|
884
|
+
permissionSet
|
|
885
|
+
])
|
|
886
|
+
);
|
|
887
|
+
const accountNameById = new Map(
|
|
888
|
+
props.state.organization.accounts.map((account) => [
|
|
889
|
+
account.id,
|
|
890
|
+
account.name
|
|
891
|
+
])
|
|
892
|
+
);
|
|
893
|
+
const permissionSetNameByArn = new Map(
|
|
894
|
+
props.state.identityCenter.permissionSets.map((permissionSet) => [
|
|
895
|
+
permissionSet.permissionSetArn,
|
|
896
|
+
permissionSet.name
|
|
897
|
+
])
|
|
898
|
+
);
|
|
899
|
+
const assignmentsByKey = /* @__PURE__ */ new Map();
|
|
900
|
+
for (const accountAssignment of props.state.identityCenter.accountAssignments) {
|
|
901
|
+
const accountName = accountNameById.get(accountAssignment.accountId);
|
|
902
|
+
if (accountName == null) {
|
|
903
|
+
throw new Error(
|
|
904
|
+
`Could not resolve account name for IdC assignment accountId "${accountAssignment.accountId}".`
|
|
905
|
+
);
|
|
906
|
+
}
|
|
907
|
+
const permissionSetName = permissionSetNameByArn.get(
|
|
908
|
+
accountAssignment.permissionSetArn
|
|
909
|
+
);
|
|
910
|
+
if (permissionSetName == null) {
|
|
911
|
+
throw new Error(
|
|
912
|
+
`Could not resolve permission set name for IdC assignment permissionSetArn "${accountAssignment.permissionSetArn}".`
|
|
913
|
+
);
|
|
914
|
+
}
|
|
915
|
+
const principalName = resolveAssignmentPrincipalName({
|
|
916
|
+
principalId: accountAssignment.principalId,
|
|
917
|
+
principalType: accountAssignment.principalType,
|
|
918
|
+
groupDisplayNameById,
|
|
919
|
+
userNameById
|
|
920
|
+
});
|
|
921
|
+
const normalizedAssignment = {
|
|
922
|
+
accountName,
|
|
923
|
+
permissionSetName,
|
|
924
|
+
principalType: accountAssignment.principalType,
|
|
925
|
+
principalName
|
|
926
|
+
};
|
|
927
|
+
assignmentsByKey.set(
|
|
928
|
+
createNormalizedIdcAssignmentKey({
|
|
929
|
+
assignment: normalizedAssignment
|
|
930
|
+
}),
|
|
931
|
+
normalizedAssignment
|
|
932
|
+
);
|
|
933
|
+
}
|
|
934
|
+
return {
|
|
935
|
+
usersByUserName,
|
|
936
|
+
groupsByDisplayName,
|
|
937
|
+
membershipsByKey,
|
|
938
|
+
permissionSetsByName,
|
|
939
|
+
assignmentsByKey
|
|
940
|
+
};
|
|
941
|
+
}
|
|
942
|
+
function createNormalizedIdcMembershipKey(props) {
|
|
943
|
+
return [props.membership.groupDisplayName, props.membership.userName].join("|");
|
|
944
|
+
}
|
|
945
|
+
function resolveAssignmentPrincipalName(props) {
|
|
946
|
+
if (props.principalType === "GROUP") {
|
|
947
|
+
const groupDisplayName = props.groupDisplayNameById.get(props.principalId);
|
|
948
|
+
if (groupDisplayName == null) {
|
|
949
|
+
throw new Error(
|
|
950
|
+
`Could not resolve group display name for IdC assignment principalId "${props.principalId}".`
|
|
951
|
+
);
|
|
952
|
+
}
|
|
953
|
+
return groupDisplayName;
|
|
954
|
+
}
|
|
955
|
+
const userName = props.userNameById.get(props.principalId);
|
|
956
|
+
if (userName == null) {
|
|
957
|
+
throw new Error(
|
|
958
|
+
`Could not resolve user name for IdC assignment principalId "${props.principalId}".`
|
|
959
|
+
);
|
|
960
|
+
}
|
|
961
|
+
return userName;
|
|
962
|
+
}
|
|
963
|
+
function createNormalizedIdcAssignmentKey(props) {
|
|
964
|
+
return [
|
|
965
|
+
props.assignment.accountName,
|
|
966
|
+
props.assignment.permissionSetName,
|
|
967
|
+
props.assignment.principalType,
|
|
968
|
+
props.assignment.principalName
|
|
969
|
+
].join("|");
|
|
970
|
+
}
|
|
971
|
+
function createCustomerManagedPolicyReferenceKey(props) {
|
|
972
|
+
return [props.path, props.name].join("|");
|
|
973
|
+
}
|
|
974
|
+
function normalizeInlinePolicyString(value) {
|
|
975
|
+
if (value == null) {
|
|
976
|
+
return null;
|
|
977
|
+
}
|
|
978
|
+
try {
|
|
979
|
+
return JSON.stringify(sortJsonValue(JSON.parse(value)));
|
|
980
|
+
} catch {
|
|
981
|
+
return value;
|
|
982
|
+
}
|
|
983
|
+
}
|
|
984
|
+
function sortJsonValue(value) {
|
|
985
|
+
if (Array.isArray(value)) {
|
|
986
|
+
return value.map((entry) => sortJsonValue(entry));
|
|
987
|
+
}
|
|
988
|
+
if (value != null && typeof value === "object") {
|
|
989
|
+
return Object.fromEntries(
|
|
990
|
+
Object.entries(value).sort(([leftKey], [rightKey]) => leftKey.localeCompare(rightKey)).map(([key, nestedValue]) => [key, sortJsonValue(nestedValue)])
|
|
991
|
+
);
|
|
992
|
+
}
|
|
993
|
+
return value;
|
|
994
|
+
}
|
|
995
|
+
function resolveOrganizationalUnitName(props) {
|
|
996
|
+
if (props.organizationalUnitId === props.rootId) {
|
|
997
|
+
return "root";
|
|
998
|
+
}
|
|
999
|
+
return props.organizationalUnitNameById.get(props.organizationalUnitId) ?? "unknown";
|
|
1000
|
+
}
|
|
1001
|
+
function isResolvableOrganizationalUnitId(props) {
|
|
1002
|
+
if (props.organizationalUnitId === pendingCreationId) {
|
|
1003
|
+
return false;
|
|
1004
|
+
}
|
|
1005
|
+
if (props.organizationalUnitId === props.rootId) {
|
|
1006
|
+
return true;
|
|
1007
|
+
}
|
|
1008
|
+
return props.organizationalUnitNameById.has(props.organizationalUnitId);
|
|
1009
|
+
}
|
|
1010
|
+
export {
|
|
1011
|
+
diffStates
|
|
1012
|
+
};
|