@beesolve/aws-accounts 1.0.7 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +80 -11
- package/dist/applyLogic.js +288 -19
- package/dist/awsConfig.js +414 -32
- package/dist/cli.js +95 -25
- package/dist/commands/graveyard.js +27 -0
- package/dist/commands/profile.js +116 -0
- package/dist/commands/remote.js +152 -47
- package/dist/commands/validate.js +125 -0
- package/dist/diff.js +278 -22
- package/dist/lambda/handler.js +8 -4
- package/dist/lambdaClient.js +5 -2
- package/dist/operations.js +91 -2
- package/dist/scanLogic.js +164 -7
- package/dist/state.js +164 -7
- package/dist-lambda/handler.mjs +707 -40
- package/dist-lambda/lambda.zip +0 -0
- package/package.json +1 -1
package/dist/scanLogic.js
CHANGED
|
@@ -4,11 +4,15 @@ import {
|
|
|
4
4
|
ListUsersCommand
|
|
5
5
|
} from "@aws-sdk/client-identitystore";
|
|
6
6
|
import {
|
|
7
|
+
DescribeOrganizationCommand,
|
|
8
|
+
DescribePolicyCommand,
|
|
7
9
|
ListAccountsCommand,
|
|
8
10
|
ListOrganizationalUnitsForParentCommand,
|
|
9
11
|
ListParentsCommand,
|
|
12
|
+
ListPoliciesCommand,
|
|
10
13
|
ListRootsCommand,
|
|
11
|
-
ListTagsForResourceCommand
|
|
14
|
+
ListTagsForResourceCommand,
|
|
15
|
+
ListTargetsForPolicyCommand
|
|
12
16
|
} from "@aws-sdk/client-organizations";
|
|
13
17
|
import {
|
|
14
18
|
DescribePermissionSetCommand,
|
|
@@ -16,19 +20,27 @@ import {
|
|
|
16
20
|
ListAccountAssignmentsCommand,
|
|
17
21
|
ListAccountsForProvisionedPermissionSetCommand,
|
|
18
22
|
ListCustomerManagedPolicyReferencesInPermissionSetCommand,
|
|
23
|
+
DescribeInstanceAccessControlAttributeConfigurationCommand,
|
|
19
24
|
ListInstancesCommand,
|
|
20
25
|
ListManagedPoliciesInPermissionSetCommand,
|
|
21
26
|
ListPermissionSetsCommand
|
|
22
27
|
} from "@aws-sdk/client-sso-admin";
|
|
28
|
+
import {
|
|
29
|
+
GetAlternateContactCommand
|
|
30
|
+
} from "@aws-sdk/client-account";
|
|
23
31
|
import {
|
|
24
32
|
createAccessRoleName
|
|
25
33
|
} from "./state.js";
|
|
26
34
|
async function scanOrganization(props) {
|
|
27
|
-
const
|
|
28
|
-
|
|
35
|
+
const [rootsResponse, orgResponse] = await Promise.all([
|
|
36
|
+
props.organizationsClient.send(new ListRootsCommand({})),
|
|
37
|
+
props.organizationsClient.send(new DescribeOrganizationCommand({}))
|
|
38
|
+
]);
|
|
39
|
+
const root = rootsResponse.Roots?.[0];
|
|
29
40
|
if (root?.Id == null) {
|
|
30
41
|
throw new Error("No organization root found.");
|
|
31
42
|
}
|
|
43
|
+
const managementAccountId = orgResponse.Organization?.MasterAccountId;
|
|
32
44
|
const organizationalUnits = await collectOrganizationalUnits({
|
|
33
45
|
organizationsClient: props.organizationsClient,
|
|
34
46
|
parentId: root.Id
|
|
@@ -52,6 +64,11 @@ async function scanOrganization(props) {
|
|
|
52
64
|
ResourceId: account.Id
|
|
53
65
|
})
|
|
54
66
|
);
|
|
67
|
+
const alternateContacts = await scanAlternateContacts({
|
|
68
|
+
accountClient: props.accountClient,
|
|
69
|
+
accountId: account.Id,
|
|
70
|
+
isManagementAccount: account.Id === managementAccountId
|
|
71
|
+
});
|
|
55
72
|
accounts.push({
|
|
56
73
|
id: account.Id,
|
|
57
74
|
arn: account.Arn,
|
|
@@ -69,17 +86,95 @@ async function scanOrganization(props) {
|
|
|
69
86
|
value: tag.Value ?? ""
|
|
70
87
|
}
|
|
71
88
|
];
|
|
72
|
-
})
|
|
89
|
+
}),
|
|
90
|
+
alternateContacts: alternateContacts.length > 0 ? alternateContacts : void 0
|
|
73
91
|
});
|
|
74
92
|
}
|
|
75
93
|
nextToken = response.NextToken;
|
|
76
94
|
} while (nextToken != null);
|
|
95
|
+
const { policies, policyAttachments } = await scanOrganizationPolicies({
|
|
96
|
+
organizationsClient: props.organizationsClient
|
|
97
|
+
});
|
|
77
98
|
return {
|
|
78
99
|
rootId: root.Id,
|
|
79
100
|
organizationalUnits,
|
|
80
|
-
accounts
|
|
101
|
+
accounts,
|
|
102
|
+
policies,
|
|
103
|
+
policyAttachments
|
|
81
104
|
};
|
|
82
105
|
}
|
|
106
|
+
const ORG_POLICY_TYPES = [
|
|
107
|
+
"SERVICE_CONTROL_POLICY",
|
|
108
|
+
"RESOURCE_CONTROL_POLICY",
|
|
109
|
+
"TAG_POLICY",
|
|
110
|
+
"AISERVICES_OPT_OUT_POLICY"
|
|
111
|
+
];
|
|
112
|
+
async function scanOrganizationPolicies(props) {
|
|
113
|
+
const policies = [];
|
|
114
|
+
const policyAttachments = [];
|
|
115
|
+
for (const policyType of ORG_POLICY_TYPES) {
|
|
116
|
+
let nextToken;
|
|
117
|
+
const policyIds = [];
|
|
118
|
+
do {
|
|
119
|
+
const response = await props.organizationsClient.send(
|
|
120
|
+
new ListPoliciesCommand({ Filter: policyType, NextToken: nextToken })
|
|
121
|
+
);
|
|
122
|
+
for (const summary of response.Policies ?? []) {
|
|
123
|
+
if (summary.Id == null || summary.AwsManaged === true) {
|
|
124
|
+
continue;
|
|
125
|
+
}
|
|
126
|
+
policyIds.push(summary.Id);
|
|
127
|
+
}
|
|
128
|
+
nextToken = response.NextToken;
|
|
129
|
+
} while (nextToken != null);
|
|
130
|
+
for (const policyId of policyIds) {
|
|
131
|
+
const describeResponse = await props.organizationsClient.send(
|
|
132
|
+
new DescribePolicyCommand({ PolicyId: policyId })
|
|
133
|
+
);
|
|
134
|
+
const policy = describeResponse.Policy;
|
|
135
|
+
if (policy?.PolicySummary?.Id == null || policy.PolicySummary.Arn == null || policy.PolicySummary.Name == null) {
|
|
136
|
+
continue;
|
|
137
|
+
}
|
|
138
|
+
const content = policy.Content;
|
|
139
|
+
if (content == null || content.length === 0) {
|
|
140
|
+
continue;
|
|
141
|
+
}
|
|
142
|
+
policies.push({
|
|
143
|
+
id: policy.PolicySummary.Id,
|
|
144
|
+
arn: policy.PolicySummary.Arn,
|
|
145
|
+
name: policy.PolicySummary.Name,
|
|
146
|
+
description: policy.PolicySummary.Description ?? "",
|
|
147
|
+
type: policyType,
|
|
148
|
+
content
|
|
149
|
+
});
|
|
150
|
+
let targetsNextToken;
|
|
151
|
+
do {
|
|
152
|
+
const targetsResponse = await props.organizationsClient.send(
|
|
153
|
+
new ListTargetsForPolicyCommand({
|
|
154
|
+
PolicyId: policyId,
|
|
155
|
+
NextToken: targetsNextToken
|
|
156
|
+
})
|
|
157
|
+
);
|
|
158
|
+
for (const target of targetsResponse.Targets ?? []) {
|
|
159
|
+
if (target.TargetId == null || target.Type == null) {
|
|
160
|
+
continue;
|
|
161
|
+
}
|
|
162
|
+
const targetType = target.Type;
|
|
163
|
+
if (targetType !== "ROOT" && targetType !== "ORGANIZATIONAL_UNIT" && targetType !== "ACCOUNT") {
|
|
164
|
+
continue;
|
|
165
|
+
}
|
|
166
|
+
policyAttachments.push({
|
|
167
|
+
policyId,
|
|
168
|
+
targetId: target.TargetId,
|
|
169
|
+
targetType
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
targetsNextToken = targetsResponse.NextToken;
|
|
173
|
+
} while (targetsNextToken != null);
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
return { policies, policyAttachments };
|
|
177
|
+
}
|
|
83
178
|
async function collectOrganizationalUnits(props) {
|
|
84
179
|
const children = [];
|
|
85
180
|
let nextToken;
|
|
@@ -122,7 +217,7 @@ async function scanIdentityCenter(props) {
|
|
|
122
217
|
instances,
|
|
123
218
|
requestedInstanceArn: props.requestedInstanceArn
|
|
124
219
|
});
|
|
125
|
-
const [users, groups, permissionSets] = await Promise.all([
|
|
220
|
+
const [users, groups, permissionSets, accessControlAttributes] = await Promise.all([
|
|
126
221
|
listIdentityStoreUsers({
|
|
127
222
|
identityStoreClient: props.identityStoreClient,
|
|
128
223
|
identityStoreId: instance.identityStoreId
|
|
@@ -134,6 +229,10 @@ async function scanIdentityCenter(props) {
|
|
|
134
229
|
listPermissionSets({
|
|
135
230
|
ssoAdminClient: props.ssoAdminClient,
|
|
136
231
|
instanceArn: instance.instanceArn
|
|
232
|
+
}),
|
|
233
|
+
scanAccessControlAttributes({
|
|
234
|
+
ssoAdminClient: props.ssoAdminClient,
|
|
235
|
+
instanceArn: instance.instanceArn
|
|
137
236
|
})
|
|
138
237
|
]);
|
|
139
238
|
const groupMemberships = await listGroupMemberships({
|
|
@@ -158,9 +257,30 @@ async function scanIdentityCenter(props) {
|
|
|
158
257
|
groupMemberships,
|
|
159
258
|
permissionSets,
|
|
160
259
|
accountAssignments,
|
|
161
|
-
accessRoles
|
|
260
|
+
accessRoles,
|
|
261
|
+
accessControlAttributes
|
|
162
262
|
};
|
|
163
263
|
}
|
|
264
|
+
async function scanAccessControlAttributes(props) {
|
|
265
|
+
let response;
|
|
266
|
+
try {
|
|
267
|
+
response = await props.ssoAdminClient.send(
|
|
268
|
+
new DescribeInstanceAccessControlAttributeConfigurationCommand({
|
|
269
|
+
InstanceArn: props.instanceArn
|
|
270
|
+
})
|
|
271
|
+
);
|
|
272
|
+
} catch (err) {
|
|
273
|
+
if (err != null && typeof err === "object" && "name" in err && err.name === "ResourceNotFoundException") {
|
|
274
|
+
return [];
|
|
275
|
+
}
|
|
276
|
+
throw err;
|
|
277
|
+
}
|
|
278
|
+
const attributes = response.InstanceAccessControlAttributeConfiguration?.AccessControlAttributes ?? [];
|
|
279
|
+
return attributes.filter((attr) => attr.Key != null).map((attr) => ({
|
|
280
|
+
key: attr.Key,
|
|
281
|
+
source: attr.Value?.Source ?? []
|
|
282
|
+
}));
|
|
283
|
+
}
|
|
164
284
|
function selectIdentityCenterInstance(props) {
|
|
165
285
|
if (props.requestedInstanceArn != null) {
|
|
166
286
|
const selected2 = props.instances.find(
|
|
@@ -333,6 +453,7 @@ async function listPermissionSets(props) {
|
|
|
333
453
|
permissionSetArn: permissionSet.PermissionSetArn,
|
|
334
454
|
name: permissionSet.Name,
|
|
335
455
|
description: permissionSet.Description ?? "",
|
|
456
|
+
sessionDuration: permissionSet.SessionDuration ?? null,
|
|
336
457
|
inlinePolicy,
|
|
337
458
|
awsManagedPolicies,
|
|
338
459
|
customerManagedPolicies
|
|
@@ -450,6 +571,42 @@ async function listAccountsForPermissionSet(props) {
|
|
|
450
571
|
} while (nextToken != null);
|
|
451
572
|
return accountIds;
|
|
452
573
|
}
|
|
574
|
+
const ALTERNATE_CONTACT_TYPES = [
|
|
575
|
+
"BILLING",
|
|
576
|
+
"OPERATIONS",
|
|
577
|
+
"SECURITY"
|
|
578
|
+
];
|
|
579
|
+
async function scanAlternateContacts(props) {
|
|
580
|
+
const results = await Promise.all(
|
|
581
|
+
ALTERNATE_CONTACT_TYPES.map(async (contactType) => {
|
|
582
|
+
try {
|
|
583
|
+
const response = await props.accountClient.send(
|
|
584
|
+
new GetAlternateContactCommand({
|
|
585
|
+
AccountId: props.isManagementAccount ? void 0 : props.accountId,
|
|
586
|
+
AlternateContactType: contactType
|
|
587
|
+
})
|
|
588
|
+
);
|
|
589
|
+
const c = response.AlternateContact;
|
|
590
|
+
if (c == null || c.EmailAddress == null || c.Name == null) {
|
|
591
|
+
return null;
|
|
592
|
+
}
|
|
593
|
+
return {
|
|
594
|
+
contactType,
|
|
595
|
+
name: c.Name,
|
|
596
|
+
email: c.EmailAddress,
|
|
597
|
+
phone: c.PhoneNumber ?? "",
|
|
598
|
+
...c.Title != null ? { title: c.Title } : {}
|
|
599
|
+
};
|
|
600
|
+
} catch (error) {
|
|
601
|
+
if (error != null && typeof error === "object" && "name" in error && error.name === "ResourceNotFoundException") {
|
|
602
|
+
return null;
|
|
603
|
+
}
|
|
604
|
+
throw error;
|
|
605
|
+
}
|
|
606
|
+
})
|
|
607
|
+
);
|
|
608
|
+
return results.filter((c) => c != null);
|
|
609
|
+
}
|
|
453
610
|
export {
|
|
454
611
|
scanIdentityCenter,
|
|
455
612
|
scanOrganization
|
package/dist/state.js
CHANGED
|
@@ -9,10 +9,36 @@ const organizationalUnitSchema = v.strictObject({
|
|
|
9
9
|
arn: nonEmptyString,
|
|
10
10
|
name: nonEmptyString
|
|
11
11
|
});
|
|
12
|
+
const orgPolicyTypeSchema = v.picklist([
|
|
13
|
+
"SERVICE_CONTROL_POLICY",
|
|
14
|
+
"RESOURCE_CONTROL_POLICY",
|
|
15
|
+
"TAG_POLICY",
|
|
16
|
+
"AISERVICES_OPT_OUT_POLICY"
|
|
17
|
+
]);
|
|
18
|
+
const orgPolicySchema = v.strictObject({
|
|
19
|
+
id: nonEmptyString,
|
|
20
|
+
arn: nonEmptyString,
|
|
21
|
+
name: nonEmptyString,
|
|
22
|
+
description: v.string(),
|
|
23
|
+
type: orgPolicyTypeSchema,
|
|
24
|
+
content: nonEmptyString
|
|
25
|
+
});
|
|
26
|
+
const orgPolicyAttachmentSchema = v.strictObject({
|
|
27
|
+
policyId: nonEmptyString,
|
|
28
|
+
targetId: nonEmptyString,
|
|
29
|
+
targetType: v.picklist(["ROOT", "ORGANIZATIONAL_UNIT", "ACCOUNT"])
|
|
30
|
+
});
|
|
12
31
|
const accountTagSchema = v.strictObject({
|
|
13
32
|
key: nonEmptyString,
|
|
14
33
|
value: v.string()
|
|
15
34
|
});
|
|
35
|
+
const alternateContactSchema = v.strictObject({
|
|
36
|
+
contactType: v.picklist(["BILLING", "OPERATIONS", "SECURITY"]),
|
|
37
|
+
name: v.string(),
|
|
38
|
+
email: v.string(),
|
|
39
|
+
phone: v.string(),
|
|
40
|
+
title: v.optional(v.string())
|
|
41
|
+
});
|
|
16
42
|
const accountSchema = v.strictObject({
|
|
17
43
|
id: nonEmptyString,
|
|
18
44
|
arn: nonEmptyString,
|
|
@@ -20,7 +46,8 @@ const accountSchema = v.strictObject({
|
|
|
20
46
|
email: nonEmptyString,
|
|
21
47
|
status: nonEmptyString,
|
|
22
48
|
parentId: nonEmptyString,
|
|
23
|
-
tags: v.array(accountTagSchema)
|
|
49
|
+
tags: v.array(accountTagSchema),
|
|
50
|
+
alternateContacts: v.optional(v.array(alternateContactSchema))
|
|
24
51
|
});
|
|
25
52
|
const userSchema = v.strictObject({
|
|
26
53
|
userId: nonEmptyString,
|
|
@@ -46,6 +73,7 @@ const permissionSetSchema = v.strictObject({
|
|
|
46
73
|
permissionSetArn: nonEmptyString,
|
|
47
74
|
name: nonEmptyString,
|
|
48
75
|
description: v.string(),
|
|
76
|
+
sessionDuration: v.nullable(v.string()),
|
|
49
77
|
inlinePolicy: v.nullable(nonEmptyString),
|
|
50
78
|
awsManagedPolicies: v.array(nonEmptyString),
|
|
51
79
|
customerManagedPolicies: v.array(customerManagedPolicyReferenceSchema)
|
|
@@ -63,13 +91,19 @@ const accessRoleSchema = v.strictObject({
|
|
|
63
91
|
principalType: principalTypeSchema,
|
|
64
92
|
roleName: nonEmptyString
|
|
65
93
|
});
|
|
94
|
+
const accessControlAttributeSchema = v.strictObject({
|
|
95
|
+
key: nonEmptyString,
|
|
96
|
+
source: v.array(nonEmptyString)
|
|
97
|
+
});
|
|
66
98
|
const stateSchema = v.strictObject({
|
|
67
99
|
version: nonEmptyString,
|
|
68
100
|
generatedAt: nonEmptyString,
|
|
69
101
|
organization: v.strictObject({
|
|
70
102
|
rootId: nonEmptyString,
|
|
71
103
|
organizationalUnits: v.array(organizationalUnitSchema),
|
|
72
|
-
accounts: v.array(accountSchema)
|
|
104
|
+
accounts: v.array(accountSchema),
|
|
105
|
+
policies: v.optional(v.array(orgPolicySchema)),
|
|
106
|
+
policyAttachments: v.optional(v.array(orgPolicyAttachmentSchema))
|
|
73
107
|
}),
|
|
74
108
|
identityCenter: v.strictObject({
|
|
75
109
|
instanceArn: nonEmptyString,
|
|
@@ -79,13 +113,16 @@ const stateSchema = v.strictObject({
|
|
|
79
113
|
groupMemberships: v.array(groupMembershipSchema),
|
|
80
114
|
permissionSets: v.array(permissionSetSchema),
|
|
81
115
|
accountAssignments: v.array(accountAssignmentSchema),
|
|
82
|
-
accessRoles: v.array(accessRoleSchema)
|
|
116
|
+
accessRoles: v.array(accessRoleSchema),
|
|
117
|
+
accessControlAttributes: v.array(accessControlAttributeSchema)
|
|
83
118
|
})
|
|
84
119
|
});
|
|
85
120
|
function validateState(value) {
|
|
86
121
|
return v.parse(stateSchema, value);
|
|
87
122
|
}
|
|
88
123
|
function createWorkingState(props) {
|
|
124
|
+
const policies = props.state.organization.policies ?? [];
|
|
125
|
+
const policyAttachments = props.state.organization.policyAttachments ?? [];
|
|
89
126
|
return {
|
|
90
127
|
version: props.state.version,
|
|
91
128
|
generatedAt: props.state.generatedAt,
|
|
@@ -99,6 +136,13 @@ function createWorkingState(props) {
|
|
|
99
136
|
accountsByName: toRecordByProperty(
|
|
100
137
|
props.state.organization.accounts,
|
|
101
138
|
"name"
|
|
139
|
+
),
|
|
140
|
+
policiesById: toRecordByProperty(policies, "id"),
|
|
141
|
+
policiesByName: toRecordByProperty(policies, "name"),
|
|
142
|
+
policyAttachments: structuredClone(policyAttachments),
|
|
143
|
+
policyAttachmentsByKey: toRecordByProperty(
|
|
144
|
+
policyAttachments,
|
|
145
|
+
createOrgPolicyAttachmentKey
|
|
102
146
|
)
|
|
103
147
|
},
|
|
104
148
|
identityCenter: createWorkingIdentityCenterState({
|
|
@@ -115,7 +159,11 @@ function materializeWorkingState(props) {
|
|
|
115
159
|
organizationalUnits: Object.values(
|
|
116
160
|
props.workingState.organization.organizationalUnitsById
|
|
117
161
|
),
|
|
118
|
-
accounts: Object.values(props.workingState.organization.accountsById)
|
|
162
|
+
accounts: Object.values(props.workingState.organization.accountsById),
|
|
163
|
+
policies: Object.values(props.workingState.organization.policiesById),
|
|
164
|
+
policyAttachments: structuredClone(
|
|
165
|
+
props.workingState.organization.policyAttachments
|
|
166
|
+
)
|
|
119
167
|
},
|
|
120
168
|
identityCenter: {
|
|
121
169
|
instanceArn: props.workingState.identityCenter.instanceArn,
|
|
@@ -133,6 +181,9 @@ function materializeWorkingState(props) {
|
|
|
133
181
|
),
|
|
134
182
|
accessRoles: structuredClone(
|
|
135
183
|
props.workingState.identityCenter.accessRoles
|
|
184
|
+
),
|
|
185
|
+
accessControlAttributes: structuredClone(
|
|
186
|
+
props.workingState.identityCenter.accessControlAttributes
|
|
136
187
|
)
|
|
137
188
|
}
|
|
138
189
|
};
|
|
@@ -345,7 +396,7 @@ function removeIdcGroupFromWorkingState(props) {
|
|
|
345
396
|
}
|
|
346
397
|
function upsertIdcPermissionSetInWorkingState(props) {
|
|
347
398
|
const currentPermissionSet = props.workingState.identityCenter.permissionSetsByName[props.permissionSet.name];
|
|
348
|
-
if (currentPermissionSet != null && currentPermissionSet.permissionSetArn === props.permissionSet.permissionSetArn && currentPermissionSet.name === props.permissionSet.name && currentPermissionSet.description === props.permissionSet.description && currentPermissionSet.inlinePolicy === props.permissionSet.inlinePolicy && JSON.stringify(currentPermissionSet.awsManagedPolicies) === JSON.stringify(props.permissionSet.awsManagedPolicies) && JSON.stringify(currentPermissionSet.customerManagedPolicies) === JSON.stringify(props.permissionSet.customerManagedPolicies)) {
|
|
399
|
+
if (currentPermissionSet != null && currentPermissionSet.permissionSetArn === props.permissionSet.permissionSetArn && currentPermissionSet.name === props.permissionSet.name && currentPermissionSet.description === props.permissionSet.description && currentPermissionSet.sessionDuration === props.permissionSet.sessionDuration && currentPermissionSet.inlinePolicy === props.permissionSet.inlinePolicy && JSON.stringify(currentPermissionSet.awsManagedPolicies) === JSON.stringify(props.permissionSet.awsManagedPolicies) && JSON.stringify(currentPermissionSet.customerManagedPolicies) === JSON.stringify(props.permissionSet.customerManagedPolicies)) {
|
|
349
400
|
return props.workingState;
|
|
350
401
|
}
|
|
351
402
|
const remainingPermissionSets = props.workingState.identityCenter.permissionSets.filter(
|
|
@@ -487,6 +538,101 @@ function removeAccountAssignmentFromWorkingState(props) {
|
|
|
487
538
|
})
|
|
488
539
|
};
|
|
489
540
|
}
|
|
541
|
+
function createOrgPolicyAttachmentKey(props) {
|
|
542
|
+
return [props.policyId, props.targetId].join("|");
|
|
543
|
+
}
|
|
544
|
+
function upsertOrgPolicyInWorkingState(props) {
|
|
545
|
+
const currentPolicy = props.workingState.organization.policiesById[props.policy.id];
|
|
546
|
+
if (currentPolicy != null && currentPolicy.id === props.policy.id && currentPolicy.arn === props.policy.arn && currentPolicy.name === props.policy.name && currentPolicy.description === props.policy.description && currentPolicy.type === props.policy.type && currentPolicy.content === props.policy.content) {
|
|
547
|
+
return props.workingState;
|
|
548
|
+
}
|
|
549
|
+
const remainingPolicies = Object.values(
|
|
550
|
+
props.workingState.organization.policiesById
|
|
551
|
+
).filter((p) => p.id !== props.policy.id);
|
|
552
|
+
const nextPolicies = [...remainingPolicies, props.policy];
|
|
553
|
+
return {
|
|
554
|
+
...props.workingState,
|
|
555
|
+
organization: {
|
|
556
|
+
...props.workingState.organization,
|
|
557
|
+
policiesById: toRecordByProperty(nextPolicies, "id"),
|
|
558
|
+
policiesByName: toRecordByProperty(nextPolicies, "name")
|
|
559
|
+
}
|
|
560
|
+
};
|
|
561
|
+
}
|
|
562
|
+
function removeOrgPolicyFromWorkingState(props) {
|
|
563
|
+
if (props.workingState.organization.policiesById[props.policyId] == null) {
|
|
564
|
+
return props.workingState;
|
|
565
|
+
}
|
|
566
|
+
const nextPolicies = Object.values(
|
|
567
|
+
props.workingState.organization.policiesById
|
|
568
|
+
).filter((p) => p.id !== props.policyId);
|
|
569
|
+
const nextAttachments = props.workingState.organization.policyAttachments.filter(
|
|
570
|
+
(a) => a.policyId !== props.policyId
|
|
571
|
+
);
|
|
572
|
+
return {
|
|
573
|
+
...props.workingState,
|
|
574
|
+
organization: {
|
|
575
|
+
...props.workingState.organization,
|
|
576
|
+
policiesById: toRecordByProperty(nextPolicies, "id"),
|
|
577
|
+
policiesByName: toRecordByProperty(nextPolicies, "name"),
|
|
578
|
+
policyAttachments: nextAttachments,
|
|
579
|
+
policyAttachmentsByKey: toRecordByProperty(
|
|
580
|
+
nextAttachments,
|
|
581
|
+
createOrgPolicyAttachmentKey
|
|
582
|
+
)
|
|
583
|
+
}
|
|
584
|
+
};
|
|
585
|
+
}
|
|
586
|
+
function addOrgPolicyAttachmentToWorkingState(props) {
|
|
587
|
+
const key = createOrgPolicyAttachmentKey({
|
|
588
|
+
policyId: props.attachment.policyId,
|
|
589
|
+
targetId: props.attachment.targetId
|
|
590
|
+
});
|
|
591
|
+
if (props.workingState.organization.policyAttachmentsByKey[key] != null) {
|
|
592
|
+
return props.workingState;
|
|
593
|
+
}
|
|
594
|
+
const nextAttachments = [
|
|
595
|
+
...props.workingState.organization.policyAttachments,
|
|
596
|
+
props.attachment
|
|
597
|
+
];
|
|
598
|
+
return {
|
|
599
|
+
...props.workingState,
|
|
600
|
+
organization: {
|
|
601
|
+
...props.workingState.organization,
|
|
602
|
+
policyAttachments: nextAttachments,
|
|
603
|
+
policyAttachmentsByKey: toRecordByProperty(
|
|
604
|
+
nextAttachments,
|
|
605
|
+
createOrgPolicyAttachmentKey
|
|
606
|
+
)
|
|
607
|
+
}
|
|
608
|
+
};
|
|
609
|
+
}
|
|
610
|
+
function removeOrgPolicyAttachmentFromWorkingState(props) {
|
|
611
|
+
const key = createOrgPolicyAttachmentKey({
|
|
612
|
+
policyId: props.policyId,
|
|
613
|
+
targetId: props.targetId
|
|
614
|
+
});
|
|
615
|
+
if (props.workingState.organization.policyAttachmentsByKey[key] == null) {
|
|
616
|
+
return props.workingState;
|
|
617
|
+
}
|
|
618
|
+
const nextAttachments = props.workingState.organization.policyAttachments.filter(
|
|
619
|
+
(a) => createOrgPolicyAttachmentKey({
|
|
620
|
+
policyId: a.policyId,
|
|
621
|
+
targetId: a.targetId
|
|
622
|
+
}) !== key
|
|
623
|
+
);
|
|
624
|
+
return {
|
|
625
|
+
...props.workingState,
|
|
626
|
+
organization: {
|
|
627
|
+
...props.workingState.organization,
|
|
628
|
+
policyAttachments: nextAttachments,
|
|
629
|
+
policyAttachmentsByKey: toRecordByProperty(
|
|
630
|
+
nextAttachments,
|
|
631
|
+
createOrgPolicyAttachmentKey
|
|
632
|
+
)
|
|
633
|
+
}
|
|
634
|
+
};
|
|
635
|
+
}
|
|
490
636
|
async function readStateFile(path) {
|
|
491
637
|
const content = await readFile(path, "utf8");
|
|
492
638
|
const parsed = JSON.parse(content);
|
|
@@ -526,7 +672,10 @@ function createWorkingIdentityCenterState(props) {
|
|
|
526
672
|
),
|
|
527
673
|
accessRoles: createAccessRoles({
|
|
528
674
|
accountAssignments
|
|
529
|
-
})
|
|
675
|
+
}),
|
|
676
|
+
accessControlAttributes: structuredClone(
|
|
677
|
+
props.identityCenter.accessControlAttributes ?? []
|
|
678
|
+
)
|
|
530
679
|
};
|
|
531
680
|
}
|
|
532
681
|
function materializeWorkingIdentityCenterState(props) {
|
|
@@ -540,7 +689,10 @@ function materializeWorkingIdentityCenterState(props) {
|
|
|
540
689
|
accountAssignments: structuredClone(
|
|
541
690
|
props.identityCenter.accountAssignments
|
|
542
691
|
),
|
|
543
|
-
accessRoles: structuredClone(props.identityCenter.accessRoles)
|
|
692
|
+
accessRoles: structuredClone(props.identityCenter.accessRoles),
|
|
693
|
+
accessControlAttributes: structuredClone(
|
|
694
|
+
props.identityCenter.accessControlAttributes
|
|
695
|
+
)
|
|
544
696
|
};
|
|
545
697
|
}
|
|
546
698
|
function createAccessRoles(props) {
|
|
@@ -595,8 +747,10 @@ function sortJsonValue(value) {
|
|
|
595
747
|
export {
|
|
596
748
|
addAccountAssignmentToWorkingState,
|
|
597
749
|
addGroupMembershipToWorkingState,
|
|
750
|
+
addOrgPolicyAttachmentToWorkingState,
|
|
598
751
|
createAccessRoleName,
|
|
599
752
|
createGroupMembershipKey,
|
|
753
|
+
createOrgPolicyAttachmentKey,
|
|
600
754
|
createWorkingState,
|
|
601
755
|
materializeWorkingState,
|
|
602
756
|
moveAccountInWorkingState,
|
|
@@ -606,6 +760,8 @@ export {
|
|
|
606
760
|
removeIdcGroupFromWorkingState,
|
|
607
761
|
removeIdcPermissionSetFromWorkingState,
|
|
608
762
|
removeIdcUserFromWorkingState,
|
|
763
|
+
removeOrgPolicyAttachmentFromWorkingState,
|
|
764
|
+
removeOrgPolicyFromWorkingState,
|
|
609
765
|
removeOrganizationalUnitFromWorkingState,
|
|
610
766
|
renameOrganizationalUnitInWorkingState,
|
|
611
767
|
stateSchema,
|
|
@@ -613,6 +769,7 @@ export {
|
|
|
613
769
|
upsertIdcGroupInWorkingState,
|
|
614
770
|
upsertIdcPermissionSetInWorkingState,
|
|
615
771
|
upsertIdcUserInWorkingState,
|
|
772
|
+
upsertOrgPolicyInWorkingState,
|
|
616
773
|
upsertOrganizationalUnitInWorkingState,
|
|
617
774
|
validateState
|
|
618
775
|
};
|