@beesolve/aws-accounts 1.1.0 → 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 +1 -1
- package/dist/applyLogic.js +239 -3
- package/dist/awsConfig.js +402 -23
- package/dist/cli.js +63 -26
- package/dist/commands/graveyard.js +27 -0
- package/dist/commands/remote.js +139 -38
- package/dist/commands/validate.js +45 -0
- package/dist/diff.js +255 -8
- package/dist/lambda/handler.js +8 -4
- package/dist/lambdaClient.js +5 -2
- package/dist/operations.js +83 -1
- package/dist/scanLogic.js +163 -7
- package/dist/state.js +162 -6
- package/dist-lambda/handler.mjs +647 -22
- 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(
|
|
@@ -451,6 +571,42 @@ async function listAccountsForPermissionSet(props) {
|
|
|
451
571
|
} while (nextToken != null);
|
|
452
572
|
return accountIds;
|
|
453
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
|
+
}
|
|
454
610
|
export {
|
|
455
611
|
scanIdentityCenter,
|
|
456
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,
|
|
@@ -64,13 +91,19 @@ const accessRoleSchema = v.strictObject({
|
|
|
64
91
|
principalType: principalTypeSchema,
|
|
65
92
|
roleName: nonEmptyString
|
|
66
93
|
});
|
|
94
|
+
const accessControlAttributeSchema = v.strictObject({
|
|
95
|
+
key: nonEmptyString,
|
|
96
|
+
source: v.array(nonEmptyString)
|
|
97
|
+
});
|
|
67
98
|
const stateSchema = v.strictObject({
|
|
68
99
|
version: nonEmptyString,
|
|
69
100
|
generatedAt: nonEmptyString,
|
|
70
101
|
organization: v.strictObject({
|
|
71
102
|
rootId: nonEmptyString,
|
|
72
103
|
organizationalUnits: v.array(organizationalUnitSchema),
|
|
73
|
-
accounts: v.array(accountSchema)
|
|
104
|
+
accounts: v.array(accountSchema),
|
|
105
|
+
policies: v.optional(v.array(orgPolicySchema)),
|
|
106
|
+
policyAttachments: v.optional(v.array(orgPolicyAttachmentSchema))
|
|
74
107
|
}),
|
|
75
108
|
identityCenter: v.strictObject({
|
|
76
109
|
instanceArn: nonEmptyString,
|
|
@@ -80,13 +113,16 @@ const stateSchema = v.strictObject({
|
|
|
80
113
|
groupMemberships: v.array(groupMembershipSchema),
|
|
81
114
|
permissionSets: v.array(permissionSetSchema),
|
|
82
115
|
accountAssignments: v.array(accountAssignmentSchema),
|
|
83
|
-
accessRoles: v.array(accessRoleSchema)
|
|
116
|
+
accessRoles: v.array(accessRoleSchema),
|
|
117
|
+
accessControlAttributes: v.array(accessControlAttributeSchema)
|
|
84
118
|
})
|
|
85
119
|
});
|
|
86
120
|
function validateState(value) {
|
|
87
121
|
return v.parse(stateSchema, value);
|
|
88
122
|
}
|
|
89
123
|
function createWorkingState(props) {
|
|
124
|
+
const policies = props.state.organization.policies ?? [];
|
|
125
|
+
const policyAttachments = props.state.organization.policyAttachments ?? [];
|
|
90
126
|
return {
|
|
91
127
|
version: props.state.version,
|
|
92
128
|
generatedAt: props.state.generatedAt,
|
|
@@ -100,6 +136,13 @@ function createWorkingState(props) {
|
|
|
100
136
|
accountsByName: toRecordByProperty(
|
|
101
137
|
props.state.organization.accounts,
|
|
102
138
|
"name"
|
|
139
|
+
),
|
|
140
|
+
policiesById: toRecordByProperty(policies, "id"),
|
|
141
|
+
policiesByName: toRecordByProperty(policies, "name"),
|
|
142
|
+
policyAttachments: structuredClone(policyAttachments),
|
|
143
|
+
policyAttachmentsByKey: toRecordByProperty(
|
|
144
|
+
policyAttachments,
|
|
145
|
+
createOrgPolicyAttachmentKey
|
|
103
146
|
)
|
|
104
147
|
},
|
|
105
148
|
identityCenter: createWorkingIdentityCenterState({
|
|
@@ -116,7 +159,11 @@ function materializeWorkingState(props) {
|
|
|
116
159
|
organizationalUnits: Object.values(
|
|
117
160
|
props.workingState.organization.organizationalUnitsById
|
|
118
161
|
),
|
|
119
|
-
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
|
+
)
|
|
120
167
|
},
|
|
121
168
|
identityCenter: {
|
|
122
169
|
instanceArn: props.workingState.identityCenter.instanceArn,
|
|
@@ -134,6 +181,9 @@ function materializeWorkingState(props) {
|
|
|
134
181
|
),
|
|
135
182
|
accessRoles: structuredClone(
|
|
136
183
|
props.workingState.identityCenter.accessRoles
|
|
184
|
+
),
|
|
185
|
+
accessControlAttributes: structuredClone(
|
|
186
|
+
props.workingState.identityCenter.accessControlAttributes
|
|
137
187
|
)
|
|
138
188
|
}
|
|
139
189
|
};
|
|
@@ -488,6 +538,101 @@ function removeAccountAssignmentFromWorkingState(props) {
|
|
|
488
538
|
})
|
|
489
539
|
};
|
|
490
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
|
+
}
|
|
491
636
|
async function readStateFile(path) {
|
|
492
637
|
const content = await readFile(path, "utf8");
|
|
493
638
|
const parsed = JSON.parse(content);
|
|
@@ -527,7 +672,10 @@ function createWorkingIdentityCenterState(props) {
|
|
|
527
672
|
),
|
|
528
673
|
accessRoles: createAccessRoles({
|
|
529
674
|
accountAssignments
|
|
530
|
-
})
|
|
675
|
+
}),
|
|
676
|
+
accessControlAttributes: structuredClone(
|
|
677
|
+
props.identityCenter.accessControlAttributes ?? []
|
|
678
|
+
)
|
|
531
679
|
};
|
|
532
680
|
}
|
|
533
681
|
function materializeWorkingIdentityCenterState(props) {
|
|
@@ -541,7 +689,10 @@ function materializeWorkingIdentityCenterState(props) {
|
|
|
541
689
|
accountAssignments: structuredClone(
|
|
542
690
|
props.identityCenter.accountAssignments
|
|
543
691
|
),
|
|
544
|
-
accessRoles: structuredClone(props.identityCenter.accessRoles)
|
|
692
|
+
accessRoles: structuredClone(props.identityCenter.accessRoles),
|
|
693
|
+
accessControlAttributes: structuredClone(
|
|
694
|
+
props.identityCenter.accessControlAttributes
|
|
695
|
+
)
|
|
545
696
|
};
|
|
546
697
|
}
|
|
547
698
|
function createAccessRoles(props) {
|
|
@@ -596,8 +747,10 @@ function sortJsonValue(value) {
|
|
|
596
747
|
export {
|
|
597
748
|
addAccountAssignmentToWorkingState,
|
|
598
749
|
addGroupMembershipToWorkingState,
|
|
750
|
+
addOrgPolicyAttachmentToWorkingState,
|
|
599
751
|
createAccessRoleName,
|
|
600
752
|
createGroupMembershipKey,
|
|
753
|
+
createOrgPolicyAttachmentKey,
|
|
601
754
|
createWorkingState,
|
|
602
755
|
materializeWorkingState,
|
|
603
756
|
moveAccountInWorkingState,
|
|
@@ -607,6 +760,8 @@ export {
|
|
|
607
760
|
removeIdcGroupFromWorkingState,
|
|
608
761
|
removeIdcPermissionSetFromWorkingState,
|
|
609
762
|
removeIdcUserFromWorkingState,
|
|
763
|
+
removeOrgPolicyAttachmentFromWorkingState,
|
|
764
|
+
removeOrgPolicyFromWorkingState,
|
|
610
765
|
removeOrganizationalUnitFromWorkingState,
|
|
611
766
|
renameOrganizationalUnitInWorkingState,
|
|
612
767
|
stateSchema,
|
|
@@ -614,6 +769,7 @@ export {
|
|
|
614
769
|
upsertIdcGroupInWorkingState,
|
|
615
770
|
upsertIdcPermissionSetInWorkingState,
|
|
616
771
|
upsertIdcUserInWorkingState,
|
|
772
|
+
upsertOrgPolicyInWorkingState,
|
|
617
773
|
upsertOrganizationalUnitInWorkingState,
|
|
618
774
|
validateState
|
|
619
775
|
};
|