@beesolve/aws-accounts 1.1.0 → 1.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/applyLogic.js +571 -225
- package/dist/awsConfig.js +441 -30
- package/dist/cli.js +86 -23
- package/dist/commands/graveyard.js +27 -0
- package/dist/commands/remote.js +206 -39
- package/dist/commands/validate.js +75 -0
- package/dist/diff.js +336 -14
- package/dist/lambda/handler.js +8 -4
- package/dist/lambdaClient.js +5 -2
- package/dist/operations.js +116 -1
- package/dist/scanLogic.js +237 -9
- package/dist/state.js +244 -8
- package/dist-lambda/handler.mjs +1164 -248
- package/dist-lambda/lambda.zip +0 -0
- package/package.json +2 -1
package/dist/operations.js
CHANGED
|
@@ -153,6 +153,22 @@ const provisionIdcPermissionSetOperationSchema = v.strictObject({
|
|
|
153
153
|
permissionSetName: v.string(),
|
|
154
154
|
targetScope: v.literal("ALL_PROVISIONED_ACCOUNTS")
|
|
155
155
|
});
|
|
156
|
+
const permissionsBoundaryOperationValueSchema = v.union([
|
|
157
|
+
v.strictObject({ managedPolicyArn: v.string() }),
|
|
158
|
+
v.strictObject({
|
|
159
|
+
customerManagedPolicyName: v.string(),
|
|
160
|
+
customerManagedPolicyPath: v.string()
|
|
161
|
+
})
|
|
162
|
+
]);
|
|
163
|
+
const putIdcPermissionSetPermissionsBoundaryOperationSchema = v.strictObject({
|
|
164
|
+
kind: v.literal("putIdcPermissionSetPermissionsBoundary"),
|
|
165
|
+
permissionSetName: v.string(),
|
|
166
|
+
permissionsBoundary: permissionsBoundaryOperationValueSchema
|
|
167
|
+
});
|
|
168
|
+
const deleteIdcPermissionSetPermissionsBoundaryOperationSchema = v.strictObject({
|
|
169
|
+
kind: v.literal("deleteIdcPermissionSetPermissionsBoundary"),
|
|
170
|
+
permissionSetName: v.string()
|
|
171
|
+
});
|
|
156
172
|
const grantIdcAccountAssignmentOperationSchema = v.strictObject({
|
|
157
173
|
kind: v.literal("grantIdcAccountAssignment"),
|
|
158
174
|
accountName: v.string(),
|
|
@@ -167,6 +183,92 @@ const revokeIdcAccountAssignmentOperationSchema = v.strictObject({
|
|
|
167
183
|
principalType: v.picklist(["GROUP", "USER"]),
|
|
168
184
|
principalName: v.string()
|
|
169
185
|
});
|
|
186
|
+
const setIdcAccessControlAttributesOperationSchema = v.strictObject({
|
|
187
|
+
kind: v.literal("setIdcAccessControlAttributes"),
|
|
188
|
+
attributes: v.array(
|
|
189
|
+
v.strictObject({
|
|
190
|
+
key: v.string(),
|
|
191
|
+
source: v.array(v.string())
|
|
192
|
+
})
|
|
193
|
+
)
|
|
194
|
+
});
|
|
195
|
+
const alternateContactTypeSchema = v.picklist([
|
|
196
|
+
"BILLING",
|
|
197
|
+
"OPERATIONS",
|
|
198
|
+
"SECURITY"
|
|
199
|
+
]);
|
|
200
|
+
const putAlternateContactOperationSchema = v.strictObject({
|
|
201
|
+
kind: v.literal("putAlternateContact"),
|
|
202
|
+
accountId: v.string(),
|
|
203
|
+
accountName: v.string(),
|
|
204
|
+
contactType: alternateContactTypeSchema,
|
|
205
|
+
name: v.string(),
|
|
206
|
+
email: v.string(),
|
|
207
|
+
phone: v.string(),
|
|
208
|
+
title: v.optional(v.string())
|
|
209
|
+
});
|
|
210
|
+
const deleteAlternateContactOperationSchema = v.strictObject({
|
|
211
|
+
kind: v.literal("deleteAlternateContact"),
|
|
212
|
+
accountId: v.string(),
|
|
213
|
+
accountName: v.string(),
|
|
214
|
+
contactType: alternateContactTypeSchema
|
|
215
|
+
});
|
|
216
|
+
const registerDelegatedAdministratorOperationSchema = v.strictObject({
|
|
217
|
+
kind: v.literal("registerDelegatedAdministrator"),
|
|
218
|
+
accountId: v.string(),
|
|
219
|
+
accountName: v.string(),
|
|
220
|
+
servicePrincipal: v.string()
|
|
221
|
+
});
|
|
222
|
+
const deregisterDelegatedAdministratorOperationSchema = v.strictObject({
|
|
223
|
+
kind: v.literal("deregisterDelegatedAdministrator"),
|
|
224
|
+
accountId: v.string(),
|
|
225
|
+
accountName: v.string(),
|
|
226
|
+
servicePrincipal: v.string()
|
|
227
|
+
});
|
|
228
|
+
const createOrgPolicyOperationSchema = v.strictObject({
|
|
229
|
+
kind: v.literal("createOrgPolicy"),
|
|
230
|
+
policyName: v.string(),
|
|
231
|
+
policyType: v.picklist([
|
|
232
|
+
"SERVICE_CONTROL_POLICY",
|
|
233
|
+
"RESOURCE_CONTROL_POLICY",
|
|
234
|
+
"TAG_POLICY",
|
|
235
|
+
"AISERVICES_OPT_OUT_POLICY",
|
|
236
|
+
"BACKUP_POLICY"
|
|
237
|
+
]),
|
|
238
|
+
description: v.string(),
|
|
239
|
+
content: v.string()
|
|
240
|
+
});
|
|
241
|
+
const updateOrgPolicyContentOperationSchema = v.strictObject({
|
|
242
|
+
kind: v.literal("updateOrgPolicyContent"),
|
|
243
|
+
policyId: v.string(),
|
|
244
|
+
policyName: v.string(),
|
|
245
|
+
content: v.string()
|
|
246
|
+
});
|
|
247
|
+
const updateOrgPolicyDescriptionOperationSchema = v.strictObject({
|
|
248
|
+
kind: v.literal("updateOrgPolicyDescription"),
|
|
249
|
+
policyId: v.string(),
|
|
250
|
+
policyName: v.string(),
|
|
251
|
+
description: v.string()
|
|
252
|
+
});
|
|
253
|
+
const attachOrgPolicyOperationSchema = v.strictObject({
|
|
254
|
+
kind: v.literal("attachOrgPolicy"),
|
|
255
|
+
policyId: v.string(),
|
|
256
|
+
policyName: v.string(),
|
|
257
|
+
targetId: v.string(),
|
|
258
|
+
targetName: v.string()
|
|
259
|
+
});
|
|
260
|
+
const detachOrgPolicyOperationSchema = v.strictObject({
|
|
261
|
+
kind: v.literal("detachOrgPolicy"),
|
|
262
|
+
policyId: v.string(),
|
|
263
|
+
policyName: v.string(),
|
|
264
|
+
targetId: v.string(),
|
|
265
|
+
targetName: v.string()
|
|
266
|
+
});
|
|
267
|
+
const deleteOrgPolicyOperationSchema = v.strictObject({
|
|
268
|
+
kind: v.literal("deleteOrgPolicy"),
|
|
269
|
+
policyId: v.string(),
|
|
270
|
+
policyName: v.string()
|
|
271
|
+
});
|
|
170
272
|
const operationSchema = v.variant("kind", [
|
|
171
273
|
moveAccountOperationSchema,
|
|
172
274
|
createOuOperationSchema,
|
|
@@ -195,8 +297,21 @@ const operationSchema = v.variant("kind", [
|
|
|
195
297
|
attachIdcCustomerManagedPolicyReferenceToPermissionSetOperationSchema,
|
|
196
298
|
detachIdcCustomerManagedPolicyReferenceFromPermissionSetOperationSchema,
|
|
197
299
|
provisionIdcPermissionSetOperationSchema,
|
|
300
|
+
putIdcPermissionSetPermissionsBoundaryOperationSchema,
|
|
301
|
+
deleteIdcPermissionSetPermissionsBoundaryOperationSchema,
|
|
198
302
|
grantIdcAccountAssignmentOperationSchema,
|
|
199
|
-
revokeIdcAccountAssignmentOperationSchema
|
|
303
|
+
revokeIdcAccountAssignmentOperationSchema,
|
|
304
|
+
createOrgPolicyOperationSchema,
|
|
305
|
+
updateOrgPolicyContentOperationSchema,
|
|
306
|
+
updateOrgPolicyDescriptionOperationSchema,
|
|
307
|
+
attachOrgPolicyOperationSchema,
|
|
308
|
+
detachOrgPolicyOperationSchema,
|
|
309
|
+
deleteOrgPolicyOperationSchema,
|
|
310
|
+
putAlternateContactOperationSchema,
|
|
311
|
+
deleteAlternateContactOperationSchema,
|
|
312
|
+
setIdcAccessControlAttributesOperationSchema,
|
|
313
|
+
registerDelegatedAdministratorOperationSchema,
|
|
314
|
+
deregisterDelegatedAdministratorOperationSchema
|
|
200
315
|
]);
|
|
201
316
|
const unsupportedDiffKindSchema = v.picklist([
|
|
202
317
|
"ambiguousOuRename",
|
package/dist/scanLogic.js
CHANGED
|
@@ -4,31 +4,46 @@ import {
|
|
|
4
4
|
ListUsersCommand
|
|
5
5
|
} from "@aws-sdk/client-identitystore";
|
|
6
6
|
import {
|
|
7
|
+
DescribeOrganizationCommand,
|
|
8
|
+
DescribePolicyCommand,
|
|
7
9
|
ListAccountsCommand,
|
|
10
|
+
ListDelegatedAdministratorsCommand,
|
|
11
|
+
ListDelegatedServicesForAccountCommand,
|
|
8
12
|
ListOrganizationalUnitsForParentCommand,
|
|
9
13
|
ListParentsCommand,
|
|
14
|
+
ListPoliciesCommand,
|
|
10
15
|
ListRootsCommand,
|
|
11
|
-
ListTagsForResourceCommand
|
|
16
|
+
ListTagsForResourceCommand,
|
|
17
|
+
ListTargetsForPolicyCommand
|
|
12
18
|
} from "@aws-sdk/client-organizations";
|
|
13
19
|
import {
|
|
14
20
|
DescribePermissionSetCommand,
|
|
15
21
|
GetInlinePolicyForPermissionSetCommand,
|
|
22
|
+
GetPermissionsBoundaryForPermissionSetCommand,
|
|
16
23
|
ListAccountAssignmentsCommand,
|
|
17
24
|
ListAccountsForProvisionedPermissionSetCommand,
|
|
18
25
|
ListCustomerManagedPolicyReferencesInPermissionSetCommand,
|
|
26
|
+
DescribeInstanceAccessControlAttributeConfigurationCommand,
|
|
19
27
|
ListInstancesCommand,
|
|
20
28
|
ListManagedPoliciesInPermissionSetCommand,
|
|
21
29
|
ListPermissionSetsCommand
|
|
22
30
|
} from "@aws-sdk/client-sso-admin";
|
|
31
|
+
import {
|
|
32
|
+
GetAlternateContactCommand
|
|
33
|
+
} from "@aws-sdk/client-account";
|
|
23
34
|
import {
|
|
24
35
|
createAccessRoleName
|
|
25
36
|
} from "./state.js";
|
|
26
37
|
async function scanOrganization(props) {
|
|
27
|
-
const
|
|
28
|
-
|
|
38
|
+
const [rootsResponse, orgResponse] = await Promise.all([
|
|
39
|
+
props.organizationsClient.send(new ListRootsCommand({})),
|
|
40
|
+
props.organizationsClient.send(new DescribeOrganizationCommand({}))
|
|
41
|
+
]);
|
|
42
|
+
const root = rootsResponse.Roots?.[0];
|
|
29
43
|
if (root?.Id == null) {
|
|
30
44
|
throw new Error("No organization root found.");
|
|
31
45
|
}
|
|
46
|
+
const managementAccountId = orgResponse.Organization?.MasterAccountId;
|
|
32
47
|
const organizationalUnits = await collectOrganizationalUnits({
|
|
33
48
|
organizationsClient: props.organizationsClient,
|
|
34
49
|
parentId: root.Id
|
|
@@ -52,6 +67,11 @@ async function scanOrganization(props) {
|
|
|
52
67
|
ResourceId: account.Id
|
|
53
68
|
})
|
|
54
69
|
);
|
|
70
|
+
const alternateContacts = await scanAlternateContacts({
|
|
71
|
+
accountClient: props.accountClient,
|
|
72
|
+
accountId: account.Id,
|
|
73
|
+
isManagementAccount: account.Id === managementAccountId
|
|
74
|
+
});
|
|
55
75
|
accounts.push({
|
|
56
76
|
id: account.Id,
|
|
57
77
|
arn: account.Arn,
|
|
@@ -69,17 +89,138 @@ async function scanOrganization(props) {
|
|
|
69
89
|
value: tag.Value ?? ""
|
|
70
90
|
}
|
|
71
91
|
];
|
|
72
|
-
})
|
|
92
|
+
}),
|
|
93
|
+
alternateContacts: alternateContacts.length > 0 ? alternateContacts : void 0
|
|
73
94
|
});
|
|
74
95
|
}
|
|
75
96
|
nextToken = response.NextToken;
|
|
76
97
|
} while (nextToken != null);
|
|
98
|
+
const [{ policies, policyAttachments }, delegatedAdministrators] = await Promise.all([
|
|
99
|
+
scanOrganizationPolicies({
|
|
100
|
+
organizationsClient: props.organizationsClient
|
|
101
|
+
}),
|
|
102
|
+
scanDelegatedAdministrators({
|
|
103
|
+
organizationsClient: props.organizationsClient
|
|
104
|
+
})
|
|
105
|
+
]);
|
|
77
106
|
return {
|
|
78
107
|
rootId: root.Id,
|
|
79
108
|
organizationalUnits,
|
|
80
|
-
accounts
|
|
109
|
+
accounts,
|
|
110
|
+
policies,
|
|
111
|
+
policyAttachments,
|
|
112
|
+
delegatedAdministrators: delegatedAdministrators.length > 0 ? delegatedAdministrators : void 0
|
|
81
113
|
};
|
|
82
114
|
}
|
|
115
|
+
async function scanDelegatedAdministrators(props) {
|
|
116
|
+
const accountIds = new Array();
|
|
117
|
+
let nextToken;
|
|
118
|
+
do {
|
|
119
|
+
const response = await props.organizationsClient.send(
|
|
120
|
+
new ListDelegatedAdministratorsCommand({ NextToken: nextToken })
|
|
121
|
+
);
|
|
122
|
+
for (const admin of response.DelegatedAdministrators ?? []) {
|
|
123
|
+
if (admin.Id == null) {
|
|
124
|
+
continue;
|
|
125
|
+
}
|
|
126
|
+
accountIds.push(admin.Id);
|
|
127
|
+
}
|
|
128
|
+
nextToken = response.NextToken;
|
|
129
|
+
} while (nextToken != null);
|
|
130
|
+
const results = [];
|
|
131
|
+
for (const accountId of accountIds) {
|
|
132
|
+
let servicesNextToken;
|
|
133
|
+
do {
|
|
134
|
+
const response = await props.organizationsClient.send(
|
|
135
|
+
new ListDelegatedServicesForAccountCommand({
|
|
136
|
+
AccountId: accountId,
|
|
137
|
+
NextToken: servicesNextToken
|
|
138
|
+
})
|
|
139
|
+
);
|
|
140
|
+
for (const service of response.DelegatedServices ?? []) {
|
|
141
|
+
if (service.ServicePrincipal == null) {
|
|
142
|
+
continue;
|
|
143
|
+
}
|
|
144
|
+
results.push({ accountId, servicePrincipal: service.ServicePrincipal });
|
|
145
|
+
}
|
|
146
|
+
servicesNextToken = response.NextToken;
|
|
147
|
+
} while (servicesNextToken != null);
|
|
148
|
+
}
|
|
149
|
+
return results;
|
|
150
|
+
}
|
|
151
|
+
const ORG_POLICY_TYPES = [
|
|
152
|
+
"SERVICE_CONTROL_POLICY",
|
|
153
|
+
"RESOURCE_CONTROL_POLICY",
|
|
154
|
+
"TAG_POLICY",
|
|
155
|
+
"AISERVICES_OPT_OUT_POLICY",
|
|
156
|
+
"BACKUP_POLICY"
|
|
157
|
+
];
|
|
158
|
+
async function scanOrganizationPolicies(props) {
|
|
159
|
+
const policies = [];
|
|
160
|
+
const policyAttachments = [];
|
|
161
|
+
for (const policyType of ORG_POLICY_TYPES) {
|
|
162
|
+
let nextToken;
|
|
163
|
+
const policyIds = [];
|
|
164
|
+
do {
|
|
165
|
+
const response = await props.organizationsClient.send(
|
|
166
|
+
new ListPoliciesCommand({ Filter: policyType, NextToken: nextToken })
|
|
167
|
+
);
|
|
168
|
+
for (const summary of response.Policies ?? []) {
|
|
169
|
+
if (summary.Id == null || summary.AwsManaged === true) {
|
|
170
|
+
continue;
|
|
171
|
+
}
|
|
172
|
+
policyIds.push(summary.Id);
|
|
173
|
+
}
|
|
174
|
+
nextToken = response.NextToken;
|
|
175
|
+
} while (nextToken != null);
|
|
176
|
+
for (const policyId of policyIds) {
|
|
177
|
+
const describeResponse = await props.organizationsClient.send(
|
|
178
|
+
new DescribePolicyCommand({ PolicyId: policyId })
|
|
179
|
+
);
|
|
180
|
+
const policy = describeResponse.Policy;
|
|
181
|
+
if (policy?.PolicySummary?.Id == null || policy.PolicySummary.Arn == null || policy.PolicySummary.Name == null) {
|
|
182
|
+
continue;
|
|
183
|
+
}
|
|
184
|
+
const content = policy.Content;
|
|
185
|
+
if (content == null || content.length === 0) {
|
|
186
|
+
continue;
|
|
187
|
+
}
|
|
188
|
+
policies.push({
|
|
189
|
+
id: policy.PolicySummary.Id,
|
|
190
|
+
arn: policy.PolicySummary.Arn,
|
|
191
|
+
name: policy.PolicySummary.Name,
|
|
192
|
+
description: policy.PolicySummary.Description ?? "",
|
|
193
|
+
type: policyType,
|
|
194
|
+
content
|
|
195
|
+
});
|
|
196
|
+
let targetsNextToken;
|
|
197
|
+
do {
|
|
198
|
+
const targetsResponse = await props.organizationsClient.send(
|
|
199
|
+
new ListTargetsForPolicyCommand({
|
|
200
|
+
PolicyId: policyId,
|
|
201
|
+
NextToken: targetsNextToken
|
|
202
|
+
})
|
|
203
|
+
);
|
|
204
|
+
for (const target of targetsResponse.Targets ?? []) {
|
|
205
|
+
if (target.TargetId == null || target.Type == null) {
|
|
206
|
+
continue;
|
|
207
|
+
}
|
|
208
|
+
const targetType = target.Type;
|
|
209
|
+
if (targetType !== "ROOT" && targetType !== "ORGANIZATIONAL_UNIT" && targetType !== "ACCOUNT") {
|
|
210
|
+
continue;
|
|
211
|
+
}
|
|
212
|
+
policyAttachments.push({
|
|
213
|
+
policyId,
|
|
214
|
+
targetId: target.TargetId,
|
|
215
|
+
targetType
|
|
216
|
+
});
|
|
217
|
+
}
|
|
218
|
+
targetsNextToken = targetsResponse.NextToken;
|
|
219
|
+
} while (targetsNextToken != null);
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
return { policies, policyAttachments };
|
|
223
|
+
}
|
|
83
224
|
async function collectOrganizationalUnits(props) {
|
|
84
225
|
const children = [];
|
|
85
226
|
let nextToken;
|
|
@@ -122,7 +263,7 @@ async function scanIdentityCenter(props) {
|
|
|
122
263
|
instances,
|
|
123
264
|
requestedInstanceArn: props.requestedInstanceArn
|
|
124
265
|
});
|
|
125
|
-
const [users, groups, permissionSets] = await Promise.all([
|
|
266
|
+
const [users, groups, permissionSets, accessControlAttributes] = await Promise.all([
|
|
126
267
|
listIdentityStoreUsers({
|
|
127
268
|
identityStoreClient: props.identityStoreClient,
|
|
128
269
|
identityStoreId: instance.identityStoreId
|
|
@@ -134,6 +275,10 @@ async function scanIdentityCenter(props) {
|
|
|
134
275
|
listPermissionSets({
|
|
135
276
|
ssoAdminClient: props.ssoAdminClient,
|
|
136
277
|
instanceArn: instance.instanceArn
|
|
278
|
+
}),
|
|
279
|
+
scanAccessControlAttributes({
|
|
280
|
+
ssoAdminClient: props.ssoAdminClient,
|
|
281
|
+
instanceArn: instance.instanceArn
|
|
137
282
|
})
|
|
138
283
|
]);
|
|
139
284
|
const groupMemberships = await listGroupMemberships({
|
|
@@ -158,9 +303,30 @@ async function scanIdentityCenter(props) {
|
|
|
158
303
|
groupMemberships,
|
|
159
304
|
permissionSets,
|
|
160
305
|
accountAssignments,
|
|
161
|
-
accessRoles
|
|
306
|
+
accessRoles,
|
|
307
|
+
accessControlAttributes
|
|
162
308
|
};
|
|
163
309
|
}
|
|
310
|
+
async function scanAccessControlAttributes(props) {
|
|
311
|
+
let response;
|
|
312
|
+
try {
|
|
313
|
+
response = await props.ssoAdminClient.send(
|
|
314
|
+
new DescribeInstanceAccessControlAttributeConfigurationCommand({
|
|
315
|
+
InstanceArn: props.instanceArn
|
|
316
|
+
})
|
|
317
|
+
);
|
|
318
|
+
} catch (err) {
|
|
319
|
+
if (err != null && typeof err === "object" && "name" in err && err.name === "ResourceNotFoundException") {
|
|
320
|
+
return [];
|
|
321
|
+
}
|
|
322
|
+
throw err;
|
|
323
|
+
}
|
|
324
|
+
const attributes = response.InstanceAccessControlAttributeConfiguration?.AccessControlAttributes ?? [];
|
|
325
|
+
return attributes.filter((attr) => attr.Key != null).map((attr) => ({
|
|
326
|
+
key: attr.Key,
|
|
327
|
+
source: attr.Value?.Source ?? []
|
|
328
|
+
}));
|
|
329
|
+
}
|
|
164
330
|
function selectIdentityCenterInstance(props) {
|
|
165
331
|
if (props.requestedInstanceArn != null) {
|
|
166
332
|
const selected2 = props.instances.find(
|
|
@@ -311,7 +477,8 @@ async function listPermissionSets(props) {
|
|
|
311
477
|
const [
|
|
312
478
|
inlinePolicy,
|
|
313
479
|
awsManagedPolicies,
|
|
314
|
-
customerManagedPolicies
|
|
480
|
+
customerManagedPolicies,
|
|
481
|
+
permissionsBoundary
|
|
315
482
|
] = await Promise.all([
|
|
316
483
|
getInlinePolicyForPermissionSet({
|
|
317
484
|
ssoAdminClient: props.ssoAdminClient,
|
|
@@ -327,6 +494,11 @@ async function listPermissionSets(props) {
|
|
|
327
494
|
ssoAdminClient: props.ssoAdminClient,
|
|
328
495
|
instanceArn: props.instanceArn,
|
|
329
496
|
permissionSetArn: permissionSet.PermissionSetArn
|
|
497
|
+
}),
|
|
498
|
+
getPermissionsBoundaryForPermissionSet({
|
|
499
|
+
ssoAdminClient: props.ssoAdminClient,
|
|
500
|
+
instanceArn: props.instanceArn,
|
|
501
|
+
permissionSetArn: permissionSet.PermissionSetArn
|
|
330
502
|
})
|
|
331
503
|
]);
|
|
332
504
|
return {
|
|
@@ -336,7 +508,8 @@ async function listPermissionSets(props) {
|
|
|
336
508
|
sessionDuration: permissionSet.SessionDuration ?? null,
|
|
337
509
|
inlinePolicy,
|
|
338
510
|
awsManagedPolicies,
|
|
339
|
-
customerManagedPolicies
|
|
511
|
+
customerManagedPolicies,
|
|
512
|
+
permissionsBoundary
|
|
340
513
|
};
|
|
341
514
|
})
|
|
342
515
|
);
|
|
@@ -354,6 +527,29 @@ async function getInlinePolicyForPermissionSet(props) {
|
|
|
354
527
|
const inlinePolicy = response.InlinePolicy?.trim();
|
|
355
528
|
return inlinePolicy != null && inlinePolicy.length > 0 ? inlinePolicy : null;
|
|
356
529
|
}
|
|
530
|
+
async function getPermissionsBoundaryForPermissionSet(props) {
|
|
531
|
+
const response = await props.ssoAdminClient.send(
|
|
532
|
+
new GetPermissionsBoundaryForPermissionSetCommand({
|
|
533
|
+
InstanceArn: props.instanceArn,
|
|
534
|
+
PermissionSetArn: props.permissionSetArn
|
|
535
|
+
})
|
|
536
|
+
);
|
|
537
|
+
const boundary = response.PermissionsBoundary;
|
|
538
|
+
if (boundary == null) {
|
|
539
|
+
return null;
|
|
540
|
+
}
|
|
541
|
+
if (boundary.ManagedPolicyArn != null) {
|
|
542
|
+
return { managedPolicyArn: boundary.ManagedPolicyArn };
|
|
543
|
+
}
|
|
544
|
+
const ref = boundary.CustomerManagedPolicyReference;
|
|
545
|
+
if (ref?.Name != null) {
|
|
546
|
+
return {
|
|
547
|
+
customerManagedPolicyName: ref.Name,
|
|
548
|
+
customerManagedPolicyPath: ref.Path ?? "/"
|
|
549
|
+
};
|
|
550
|
+
}
|
|
551
|
+
return null;
|
|
552
|
+
}
|
|
357
553
|
async function listManagedPoliciesInPermissionSet(props) {
|
|
358
554
|
const managedPolicies = [];
|
|
359
555
|
let nextToken;
|
|
@@ -451,6 +647,38 @@ async function listAccountsForPermissionSet(props) {
|
|
|
451
647
|
} while (nextToken != null);
|
|
452
648
|
return accountIds;
|
|
453
649
|
}
|
|
650
|
+
const ALTERNATE_CONTACT_TYPES = ["BILLING", "OPERATIONS", "SECURITY"];
|
|
651
|
+
async function scanAlternateContacts(props) {
|
|
652
|
+
const results = await Promise.all(
|
|
653
|
+
ALTERNATE_CONTACT_TYPES.map(async (contactType) => {
|
|
654
|
+
try {
|
|
655
|
+
const response = await props.accountClient.send(
|
|
656
|
+
new GetAlternateContactCommand({
|
|
657
|
+
AccountId: props.isManagementAccount ? void 0 : props.accountId,
|
|
658
|
+
AlternateContactType: contactType
|
|
659
|
+
})
|
|
660
|
+
);
|
|
661
|
+
const c = response.AlternateContact;
|
|
662
|
+
if (c == null || c.EmailAddress == null || c.Name == null) {
|
|
663
|
+
return null;
|
|
664
|
+
}
|
|
665
|
+
return {
|
|
666
|
+
contactType,
|
|
667
|
+
name: c.Name,
|
|
668
|
+
email: c.EmailAddress,
|
|
669
|
+
phone: c.PhoneNumber ?? "",
|
|
670
|
+
...c.Title != null ? { title: c.Title } : {}
|
|
671
|
+
};
|
|
672
|
+
} catch (error) {
|
|
673
|
+
if (error != null && typeof error === "object" && "name" in error && error.name === "ResourceNotFoundException") {
|
|
674
|
+
return null;
|
|
675
|
+
}
|
|
676
|
+
throw error;
|
|
677
|
+
}
|
|
678
|
+
})
|
|
679
|
+
);
|
|
680
|
+
return results.filter((c) => c != null);
|
|
681
|
+
}
|
|
454
682
|
export {
|
|
455
683
|
scanIdentityCenter,
|
|
456
684
|
scanOrganization
|