@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-lambda/handler.mjs
CHANGED
|
@@ -9,7 +9,7 @@ import { getSignedUrl } from "@aws-sdk/s3-request-presigner";
|
|
|
9
9
|
import { OrganizationsClient as OrganizationsClient3 } from "@aws-sdk/client-organizations";
|
|
10
10
|
import { SSOAdminClient as SSOAdminClient3 } from "@aws-sdk/client-sso-admin";
|
|
11
11
|
import { IdentitystoreClient as IdentitystoreClient3 } from "@aws-sdk/client-identitystore";
|
|
12
|
-
import { AccountClient as
|
|
12
|
+
import { AccountClient as AccountClient3 } from "@aws-sdk/client-account";
|
|
13
13
|
|
|
14
14
|
// node_modules/valibot/dist/index.mjs
|
|
15
15
|
var store$4;
|
|
@@ -806,6 +806,79 @@ var revokeIdcAccountAssignmentOperationSchema = strictObject({
|
|
|
806
806
|
principalType: picklist(["GROUP", "USER"]),
|
|
807
807
|
principalName: string()
|
|
808
808
|
});
|
|
809
|
+
var setIdcAccessControlAttributesOperationSchema = strictObject({
|
|
810
|
+
kind: literal("setIdcAccessControlAttributes"),
|
|
811
|
+
attributes: array(
|
|
812
|
+
strictObject({
|
|
813
|
+
key: string(),
|
|
814
|
+
source: array(string())
|
|
815
|
+
})
|
|
816
|
+
)
|
|
817
|
+
});
|
|
818
|
+
var alternateContactTypeSchema = picklist([
|
|
819
|
+
"BILLING",
|
|
820
|
+
"OPERATIONS",
|
|
821
|
+
"SECURITY"
|
|
822
|
+
]);
|
|
823
|
+
var putAlternateContactOperationSchema = strictObject({
|
|
824
|
+
kind: literal("putAlternateContact"),
|
|
825
|
+
accountId: string(),
|
|
826
|
+
accountName: string(),
|
|
827
|
+
contactType: alternateContactTypeSchema,
|
|
828
|
+
name: string(),
|
|
829
|
+
email: string(),
|
|
830
|
+
phone: string(),
|
|
831
|
+
title: optional(string())
|
|
832
|
+
});
|
|
833
|
+
var deleteAlternateContactOperationSchema = strictObject({
|
|
834
|
+
kind: literal("deleteAlternateContact"),
|
|
835
|
+
accountId: string(),
|
|
836
|
+
accountName: string(),
|
|
837
|
+
contactType: alternateContactTypeSchema
|
|
838
|
+
});
|
|
839
|
+
var createOrgPolicyOperationSchema = strictObject({
|
|
840
|
+
kind: literal("createOrgPolicy"),
|
|
841
|
+
policyName: string(),
|
|
842
|
+
policyType: picklist([
|
|
843
|
+
"SERVICE_CONTROL_POLICY",
|
|
844
|
+
"RESOURCE_CONTROL_POLICY",
|
|
845
|
+
"TAG_POLICY",
|
|
846
|
+
"AISERVICES_OPT_OUT_POLICY"
|
|
847
|
+
]),
|
|
848
|
+
description: string(),
|
|
849
|
+
content: string()
|
|
850
|
+
});
|
|
851
|
+
var updateOrgPolicyContentOperationSchema = strictObject({
|
|
852
|
+
kind: literal("updateOrgPolicyContent"),
|
|
853
|
+
policyId: string(),
|
|
854
|
+
policyName: string(),
|
|
855
|
+
content: string()
|
|
856
|
+
});
|
|
857
|
+
var updateOrgPolicyDescriptionOperationSchema = strictObject({
|
|
858
|
+
kind: literal("updateOrgPolicyDescription"),
|
|
859
|
+
policyId: string(),
|
|
860
|
+
policyName: string(),
|
|
861
|
+
description: string()
|
|
862
|
+
});
|
|
863
|
+
var attachOrgPolicyOperationSchema = strictObject({
|
|
864
|
+
kind: literal("attachOrgPolicy"),
|
|
865
|
+
policyId: string(),
|
|
866
|
+
policyName: string(),
|
|
867
|
+
targetId: string(),
|
|
868
|
+
targetName: string()
|
|
869
|
+
});
|
|
870
|
+
var detachOrgPolicyOperationSchema = strictObject({
|
|
871
|
+
kind: literal("detachOrgPolicy"),
|
|
872
|
+
policyId: string(),
|
|
873
|
+
policyName: string(),
|
|
874
|
+
targetId: string(),
|
|
875
|
+
targetName: string()
|
|
876
|
+
});
|
|
877
|
+
var deleteOrgPolicyOperationSchema = strictObject({
|
|
878
|
+
kind: literal("deleteOrgPolicy"),
|
|
879
|
+
policyId: string(),
|
|
880
|
+
policyName: string()
|
|
881
|
+
});
|
|
809
882
|
var operationSchema = variant("kind", [
|
|
810
883
|
moveAccountOperationSchema,
|
|
811
884
|
createOuOperationSchema,
|
|
@@ -835,7 +908,16 @@ var operationSchema = variant("kind", [
|
|
|
835
908
|
detachIdcCustomerManagedPolicyReferenceFromPermissionSetOperationSchema,
|
|
836
909
|
provisionIdcPermissionSetOperationSchema,
|
|
837
910
|
grantIdcAccountAssignmentOperationSchema,
|
|
838
|
-
revokeIdcAccountAssignmentOperationSchema
|
|
911
|
+
revokeIdcAccountAssignmentOperationSchema,
|
|
912
|
+
createOrgPolicyOperationSchema,
|
|
913
|
+
updateOrgPolicyContentOperationSchema,
|
|
914
|
+
updateOrgPolicyDescriptionOperationSchema,
|
|
915
|
+
attachOrgPolicyOperationSchema,
|
|
916
|
+
detachOrgPolicyOperationSchema,
|
|
917
|
+
deleteOrgPolicyOperationSchema,
|
|
918
|
+
putAlternateContactOperationSchema,
|
|
919
|
+
deleteAlternateContactOperationSchema,
|
|
920
|
+
setIdcAccessControlAttributesOperationSchema
|
|
839
921
|
]);
|
|
840
922
|
var unsupportedDiffKindSchema = picklist([
|
|
841
923
|
"ambiguousOuRename",
|
|
@@ -885,10 +967,36 @@ var organizationalUnitSchema = strictObject({
|
|
|
885
967
|
arn: nonEmptyString,
|
|
886
968
|
name: nonEmptyString
|
|
887
969
|
});
|
|
970
|
+
var orgPolicyTypeSchema = picklist([
|
|
971
|
+
"SERVICE_CONTROL_POLICY",
|
|
972
|
+
"RESOURCE_CONTROL_POLICY",
|
|
973
|
+
"TAG_POLICY",
|
|
974
|
+
"AISERVICES_OPT_OUT_POLICY"
|
|
975
|
+
]);
|
|
976
|
+
var orgPolicySchema = strictObject({
|
|
977
|
+
id: nonEmptyString,
|
|
978
|
+
arn: nonEmptyString,
|
|
979
|
+
name: nonEmptyString,
|
|
980
|
+
description: string(),
|
|
981
|
+
type: orgPolicyTypeSchema,
|
|
982
|
+
content: nonEmptyString
|
|
983
|
+
});
|
|
984
|
+
var orgPolicyAttachmentSchema = strictObject({
|
|
985
|
+
policyId: nonEmptyString,
|
|
986
|
+
targetId: nonEmptyString,
|
|
987
|
+
targetType: picklist(["ROOT", "ORGANIZATIONAL_UNIT", "ACCOUNT"])
|
|
988
|
+
});
|
|
888
989
|
var accountTagSchema = strictObject({
|
|
889
990
|
key: nonEmptyString,
|
|
890
991
|
value: string()
|
|
891
992
|
});
|
|
993
|
+
var alternateContactSchema = strictObject({
|
|
994
|
+
contactType: picklist(["BILLING", "OPERATIONS", "SECURITY"]),
|
|
995
|
+
name: string(),
|
|
996
|
+
email: string(),
|
|
997
|
+
phone: string(),
|
|
998
|
+
title: optional(string())
|
|
999
|
+
});
|
|
892
1000
|
var accountSchema = strictObject({
|
|
893
1001
|
id: nonEmptyString,
|
|
894
1002
|
arn: nonEmptyString,
|
|
@@ -896,7 +1004,8 @@ var accountSchema = strictObject({
|
|
|
896
1004
|
email: nonEmptyString,
|
|
897
1005
|
status: nonEmptyString,
|
|
898
1006
|
parentId: nonEmptyString,
|
|
899
|
-
tags: array(accountTagSchema)
|
|
1007
|
+
tags: array(accountTagSchema),
|
|
1008
|
+
alternateContacts: optional(array(alternateContactSchema))
|
|
900
1009
|
});
|
|
901
1010
|
var userSchema = strictObject({
|
|
902
1011
|
userId: nonEmptyString,
|
|
@@ -940,13 +1049,19 @@ var accessRoleSchema = strictObject({
|
|
|
940
1049
|
principalType: principalTypeSchema,
|
|
941
1050
|
roleName: nonEmptyString
|
|
942
1051
|
});
|
|
1052
|
+
var accessControlAttributeSchema = strictObject({
|
|
1053
|
+
key: nonEmptyString,
|
|
1054
|
+
source: array(nonEmptyString)
|
|
1055
|
+
});
|
|
943
1056
|
var stateSchema = strictObject({
|
|
944
1057
|
version: nonEmptyString,
|
|
945
1058
|
generatedAt: nonEmptyString,
|
|
946
1059
|
organization: strictObject({
|
|
947
1060
|
rootId: nonEmptyString,
|
|
948
1061
|
organizationalUnits: array(organizationalUnitSchema),
|
|
949
|
-
accounts: array(accountSchema)
|
|
1062
|
+
accounts: array(accountSchema),
|
|
1063
|
+
policies: optional(array(orgPolicySchema)),
|
|
1064
|
+
policyAttachments: optional(array(orgPolicyAttachmentSchema))
|
|
950
1065
|
}),
|
|
951
1066
|
identityCenter: strictObject({
|
|
952
1067
|
instanceArn: nonEmptyString,
|
|
@@ -956,10 +1071,13 @@ var stateSchema = strictObject({
|
|
|
956
1071
|
groupMemberships: array(groupMembershipSchema),
|
|
957
1072
|
permissionSets: array(permissionSetSchema),
|
|
958
1073
|
accountAssignments: array(accountAssignmentSchema),
|
|
959
|
-
accessRoles: array(accessRoleSchema)
|
|
1074
|
+
accessRoles: array(accessRoleSchema),
|
|
1075
|
+
accessControlAttributes: array(accessControlAttributeSchema)
|
|
960
1076
|
})
|
|
961
1077
|
});
|
|
962
1078
|
function createWorkingState(props) {
|
|
1079
|
+
const policies = props.state.organization.policies ?? [];
|
|
1080
|
+
const policyAttachments = props.state.organization.policyAttachments ?? [];
|
|
963
1081
|
return {
|
|
964
1082
|
version: props.state.version,
|
|
965
1083
|
generatedAt: props.state.generatedAt,
|
|
@@ -973,6 +1091,13 @@ function createWorkingState(props) {
|
|
|
973
1091
|
accountsByName: toRecordByProperty(
|
|
974
1092
|
props.state.organization.accounts,
|
|
975
1093
|
"name"
|
|
1094
|
+
),
|
|
1095
|
+
policiesById: toRecordByProperty(policies, "id"),
|
|
1096
|
+
policiesByName: toRecordByProperty(policies, "name"),
|
|
1097
|
+
policyAttachments: structuredClone(policyAttachments),
|
|
1098
|
+
policyAttachmentsByKey: toRecordByProperty(
|
|
1099
|
+
policyAttachments,
|
|
1100
|
+
createOrgPolicyAttachmentKey
|
|
976
1101
|
)
|
|
977
1102
|
},
|
|
978
1103
|
identityCenter: createWorkingIdentityCenterState({
|
|
@@ -989,7 +1114,11 @@ function materializeWorkingState(props) {
|
|
|
989
1114
|
organizationalUnits: Object.values(
|
|
990
1115
|
props.workingState.organization.organizationalUnitsById
|
|
991
1116
|
),
|
|
992
|
-
accounts: Object.values(props.workingState.organization.accountsById)
|
|
1117
|
+
accounts: Object.values(props.workingState.organization.accountsById),
|
|
1118
|
+
policies: Object.values(props.workingState.organization.policiesById),
|
|
1119
|
+
policyAttachments: structuredClone(
|
|
1120
|
+
props.workingState.organization.policyAttachments
|
|
1121
|
+
)
|
|
993
1122
|
},
|
|
994
1123
|
identityCenter: {
|
|
995
1124
|
instanceArn: props.workingState.identityCenter.instanceArn,
|
|
@@ -1007,6 +1136,9 @@ function materializeWorkingState(props) {
|
|
|
1007
1136
|
),
|
|
1008
1137
|
accessRoles: structuredClone(
|
|
1009
1138
|
props.workingState.identityCenter.accessRoles
|
|
1139
|
+
),
|
|
1140
|
+
accessControlAttributes: structuredClone(
|
|
1141
|
+
props.workingState.identityCenter.accessControlAttributes
|
|
1010
1142
|
)
|
|
1011
1143
|
}
|
|
1012
1144
|
};
|
|
@@ -1361,6 +1493,101 @@ function removeAccountAssignmentFromWorkingState(props) {
|
|
|
1361
1493
|
})
|
|
1362
1494
|
};
|
|
1363
1495
|
}
|
|
1496
|
+
function createOrgPolicyAttachmentKey(props) {
|
|
1497
|
+
return [props.policyId, props.targetId].join("|");
|
|
1498
|
+
}
|
|
1499
|
+
function upsertOrgPolicyInWorkingState(props) {
|
|
1500
|
+
const currentPolicy = props.workingState.organization.policiesById[props.policy.id];
|
|
1501
|
+
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) {
|
|
1502
|
+
return props.workingState;
|
|
1503
|
+
}
|
|
1504
|
+
const remainingPolicies = Object.values(
|
|
1505
|
+
props.workingState.organization.policiesById
|
|
1506
|
+
).filter((p) => p.id !== props.policy.id);
|
|
1507
|
+
const nextPolicies = [...remainingPolicies, props.policy];
|
|
1508
|
+
return {
|
|
1509
|
+
...props.workingState,
|
|
1510
|
+
organization: {
|
|
1511
|
+
...props.workingState.organization,
|
|
1512
|
+
policiesById: toRecordByProperty(nextPolicies, "id"),
|
|
1513
|
+
policiesByName: toRecordByProperty(nextPolicies, "name")
|
|
1514
|
+
}
|
|
1515
|
+
};
|
|
1516
|
+
}
|
|
1517
|
+
function removeOrgPolicyFromWorkingState(props) {
|
|
1518
|
+
if (props.workingState.organization.policiesById[props.policyId] == null) {
|
|
1519
|
+
return props.workingState;
|
|
1520
|
+
}
|
|
1521
|
+
const nextPolicies = Object.values(
|
|
1522
|
+
props.workingState.organization.policiesById
|
|
1523
|
+
).filter((p) => p.id !== props.policyId);
|
|
1524
|
+
const nextAttachments = props.workingState.organization.policyAttachments.filter(
|
|
1525
|
+
(a) => a.policyId !== props.policyId
|
|
1526
|
+
);
|
|
1527
|
+
return {
|
|
1528
|
+
...props.workingState,
|
|
1529
|
+
organization: {
|
|
1530
|
+
...props.workingState.organization,
|
|
1531
|
+
policiesById: toRecordByProperty(nextPolicies, "id"),
|
|
1532
|
+
policiesByName: toRecordByProperty(nextPolicies, "name"),
|
|
1533
|
+
policyAttachments: nextAttachments,
|
|
1534
|
+
policyAttachmentsByKey: toRecordByProperty(
|
|
1535
|
+
nextAttachments,
|
|
1536
|
+
createOrgPolicyAttachmentKey
|
|
1537
|
+
)
|
|
1538
|
+
}
|
|
1539
|
+
};
|
|
1540
|
+
}
|
|
1541
|
+
function addOrgPolicyAttachmentToWorkingState(props) {
|
|
1542
|
+
const key = createOrgPolicyAttachmentKey({
|
|
1543
|
+
policyId: props.attachment.policyId,
|
|
1544
|
+
targetId: props.attachment.targetId
|
|
1545
|
+
});
|
|
1546
|
+
if (props.workingState.organization.policyAttachmentsByKey[key] != null) {
|
|
1547
|
+
return props.workingState;
|
|
1548
|
+
}
|
|
1549
|
+
const nextAttachments = [
|
|
1550
|
+
...props.workingState.organization.policyAttachments,
|
|
1551
|
+
props.attachment
|
|
1552
|
+
];
|
|
1553
|
+
return {
|
|
1554
|
+
...props.workingState,
|
|
1555
|
+
organization: {
|
|
1556
|
+
...props.workingState.organization,
|
|
1557
|
+
policyAttachments: nextAttachments,
|
|
1558
|
+
policyAttachmentsByKey: toRecordByProperty(
|
|
1559
|
+
nextAttachments,
|
|
1560
|
+
createOrgPolicyAttachmentKey
|
|
1561
|
+
)
|
|
1562
|
+
}
|
|
1563
|
+
};
|
|
1564
|
+
}
|
|
1565
|
+
function removeOrgPolicyAttachmentFromWorkingState(props) {
|
|
1566
|
+
const key = createOrgPolicyAttachmentKey({
|
|
1567
|
+
policyId: props.policyId,
|
|
1568
|
+
targetId: props.targetId
|
|
1569
|
+
});
|
|
1570
|
+
if (props.workingState.organization.policyAttachmentsByKey[key] == null) {
|
|
1571
|
+
return props.workingState;
|
|
1572
|
+
}
|
|
1573
|
+
const nextAttachments = props.workingState.organization.policyAttachments.filter(
|
|
1574
|
+
(a) => createOrgPolicyAttachmentKey({
|
|
1575
|
+
policyId: a.policyId,
|
|
1576
|
+
targetId: a.targetId
|
|
1577
|
+
}) !== key
|
|
1578
|
+
);
|
|
1579
|
+
return {
|
|
1580
|
+
...props.workingState,
|
|
1581
|
+
organization: {
|
|
1582
|
+
...props.workingState.organization,
|
|
1583
|
+
policyAttachments: nextAttachments,
|
|
1584
|
+
policyAttachmentsByKey: toRecordByProperty(
|
|
1585
|
+
nextAttachments,
|
|
1586
|
+
createOrgPolicyAttachmentKey
|
|
1587
|
+
)
|
|
1588
|
+
}
|
|
1589
|
+
};
|
|
1590
|
+
}
|
|
1364
1591
|
function createAccessRoleName(assignment) {
|
|
1365
1592
|
return `AWSReservedSSO_${assignment.permissionSetArn.split("/").at(-1) ?? "PermissionSet"}_${assignment.accountId}`;
|
|
1366
1593
|
}
|
|
@@ -1395,7 +1622,10 @@ function createWorkingIdentityCenterState(props) {
|
|
|
1395
1622
|
),
|
|
1396
1623
|
accessRoles: createAccessRoles({
|
|
1397
1624
|
accountAssignments
|
|
1398
|
-
})
|
|
1625
|
+
}),
|
|
1626
|
+
accessControlAttributes: structuredClone(
|
|
1627
|
+
props.identityCenter.accessControlAttributes ?? []
|
|
1628
|
+
)
|
|
1399
1629
|
};
|
|
1400
1630
|
}
|
|
1401
1631
|
function materializeWorkingIdentityCenterState(props) {
|
|
@@ -1409,7 +1639,10 @@ function materializeWorkingIdentityCenterState(props) {
|
|
|
1409
1639
|
accountAssignments: structuredClone(
|
|
1410
1640
|
props.identityCenter.accountAssignments
|
|
1411
1641
|
),
|
|
1412
|
-
accessRoles: structuredClone(props.identityCenter.accessRoles)
|
|
1642
|
+
accessRoles: structuredClone(props.identityCenter.accessRoles),
|
|
1643
|
+
accessControlAttributes: structuredClone(
|
|
1644
|
+
props.identityCenter.accessControlAttributes
|
|
1645
|
+
)
|
|
1413
1646
|
};
|
|
1414
1647
|
}
|
|
1415
1648
|
function createAccessRoles(props) {
|
|
@@ -1448,11 +1681,15 @@ import {
|
|
|
1448
1681
|
ListUsersCommand
|
|
1449
1682
|
} from "@aws-sdk/client-identitystore";
|
|
1450
1683
|
import {
|
|
1684
|
+
DescribeOrganizationCommand,
|
|
1685
|
+
DescribePolicyCommand,
|
|
1451
1686
|
ListAccountsCommand,
|
|
1452
1687
|
ListOrganizationalUnitsForParentCommand,
|
|
1453
1688
|
ListParentsCommand,
|
|
1689
|
+
ListPoliciesCommand,
|
|
1454
1690
|
ListRootsCommand,
|
|
1455
|
-
ListTagsForResourceCommand
|
|
1691
|
+
ListTagsForResourceCommand,
|
|
1692
|
+
ListTargetsForPolicyCommand
|
|
1456
1693
|
} from "@aws-sdk/client-organizations";
|
|
1457
1694
|
import {
|
|
1458
1695
|
DescribePermissionSetCommand,
|
|
@@ -1460,16 +1697,24 @@ import {
|
|
|
1460
1697
|
ListAccountAssignmentsCommand,
|
|
1461
1698
|
ListAccountsForProvisionedPermissionSetCommand,
|
|
1462
1699
|
ListCustomerManagedPolicyReferencesInPermissionSetCommand,
|
|
1700
|
+
DescribeInstanceAccessControlAttributeConfigurationCommand,
|
|
1463
1701
|
ListInstancesCommand,
|
|
1464
1702
|
ListManagedPoliciesInPermissionSetCommand,
|
|
1465
1703
|
ListPermissionSetsCommand
|
|
1466
1704
|
} from "@aws-sdk/client-sso-admin";
|
|
1705
|
+
import {
|
|
1706
|
+
GetAlternateContactCommand
|
|
1707
|
+
} from "@aws-sdk/client-account";
|
|
1467
1708
|
async function scanOrganization(props) {
|
|
1468
|
-
const
|
|
1469
|
-
|
|
1709
|
+
const [rootsResponse, orgResponse] = await Promise.all([
|
|
1710
|
+
props.organizationsClient.send(new ListRootsCommand({})),
|
|
1711
|
+
props.organizationsClient.send(new DescribeOrganizationCommand({}))
|
|
1712
|
+
]);
|
|
1713
|
+
const root = rootsResponse.Roots?.[0];
|
|
1470
1714
|
if (root?.Id == null) {
|
|
1471
1715
|
throw new Error("No organization root found.");
|
|
1472
1716
|
}
|
|
1717
|
+
const managementAccountId = orgResponse.Organization?.MasterAccountId;
|
|
1473
1718
|
const organizationalUnits = await collectOrganizationalUnits({
|
|
1474
1719
|
organizationsClient: props.organizationsClient,
|
|
1475
1720
|
parentId: root.Id
|
|
@@ -1493,6 +1738,11 @@ async function scanOrganization(props) {
|
|
|
1493
1738
|
ResourceId: account.Id
|
|
1494
1739
|
})
|
|
1495
1740
|
);
|
|
1741
|
+
const alternateContacts = await scanAlternateContacts({
|
|
1742
|
+
accountClient: props.accountClient,
|
|
1743
|
+
accountId: account.Id,
|
|
1744
|
+
isManagementAccount: account.Id === managementAccountId
|
|
1745
|
+
});
|
|
1496
1746
|
accounts.push({
|
|
1497
1747
|
id: account.Id,
|
|
1498
1748
|
arn: account.Arn,
|
|
@@ -1510,17 +1760,95 @@ async function scanOrganization(props) {
|
|
|
1510
1760
|
value: tag.Value ?? ""
|
|
1511
1761
|
}
|
|
1512
1762
|
];
|
|
1513
|
-
})
|
|
1763
|
+
}),
|
|
1764
|
+
alternateContacts: alternateContacts.length > 0 ? alternateContacts : void 0
|
|
1514
1765
|
});
|
|
1515
1766
|
}
|
|
1516
1767
|
nextToken = response.NextToken;
|
|
1517
1768
|
} while (nextToken != null);
|
|
1769
|
+
const { policies, policyAttachments } = await scanOrganizationPolicies({
|
|
1770
|
+
organizationsClient: props.organizationsClient
|
|
1771
|
+
});
|
|
1518
1772
|
return {
|
|
1519
1773
|
rootId: root.Id,
|
|
1520
1774
|
organizationalUnits,
|
|
1521
|
-
accounts
|
|
1775
|
+
accounts,
|
|
1776
|
+
policies,
|
|
1777
|
+
policyAttachments
|
|
1522
1778
|
};
|
|
1523
1779
|
}
|
|
1780
|
+
var ORG_POLICY_TYPES = [
|
|
1781
|
+
"SERVICE_CONTROL_POLICY",
|
|
1782
|
+
"RESOURCE_CONTROL_POLICY",
|
|
1783
|
+
"TAG_POLICY",
|
|
1784
|
+
"AISERVICES_OPT_OUT_POLICY"
|
|
1785
|
+
];
|
|
1786
|
+
async function scanOrganizationPolicies(props) {
|
|
1787
|
+
const policies = [];
|
|
1788
|
+
const policyAttachments = [];
|
|
1789
|
+
for (const policyType of ORG_POLICY_TYPES) {
|
|
1790
|
+
let nextToken;
|
|
1791
|
+
const policyIds = [];
|
|
1792
|
+
do {
|
|
1793
|
+
const response = await props.organizationsClient.send(
|
|
1794
|
+
new ListPoliciesCommand({ Filter: policyType, NextToken: nextToken })
|
|
1795
|
+
);
|
|
1796
|
+
for (const summary of response.Policies ?? []) {
|
|
1797
|
+
if (summary.Id == null || summary.AwsManaged === true) {
|
|
1798
|
+
continue;
|
|
1799
|
+
}
|
|
1800
|
+
policyIds.push(summary.Id);
|
|
1801
|
+
}
|
|
1802
|
+
nextToken = response.NextToken;
|
|
1803
|
+
} while (nextToken != null);
|
|
1804
|
+
for (const policyId of policyIds) {
|
|
1805
|
+
const describeResponse = await props.organizationsClient.send(
|
|
1806
|
+
new DescribePolicyCommand({ PolicyId: policyId })
|
|
1807
|
+
);
|
|
1808
|
+
const policy = describeResponse.Policy;
|
|
1809
|
+
if (policy?.PolicySummary?.Id == null || policy.PolicySummary.Arn == null || policy.PolicySummary.Name == null) {
|
|
1810
|
+
continue;
|
|
1811
|
+
}
|
|
1812
|
+
const content = policy.Content;
|
|
1813
|
+
if (content == null || content.length === 0) {
|
|
1814
|
+
continue;
|
|
1815
|
+
}
|
|
1816
|
+
policies.push({
|
|
1817
|
+
id: policy.PolicySummary.Id,
|
|
1818
|
+
arn: policy.PolicySummary.Arn,
|
|
1819
|
+
name: policy.PolicySummary.Name,
|
|
1820
|
+
description: policy.PolicySummary.Description ?? "",
|
|
1821
|
+
type: policyType,
|
|
1822
|
+
content
|
|
1823
|
+
});
|
|
1824
|
+
let targetsNextToken;
|
|
1825
|
+
do {
|
|
1826
|
+
const targetsResponse = await props.organizationsClient.send(
|
|
1827
|
+
new ListTargetsForPolicyCommand({
|
|
1828
|
+
PolicyId: policyId,
|
|
1829
|
+
NextToken: targetsNextToken
|
|
1830
|
+
})
|
|
1831
|
+
);
|
|
1832
|
+
for (const target of targetsResponse.Targets ?? []) {
|
|
1833
|
+
if (target.TargetId == null || target.Type == null) {
|
|
1834
|
+
continue;
|
|
1835
|
+
}
|
|
1836
|
+
const targetType = target.Type;
|
|
1837
|
+
if (targetType !== "ROOT" && targetType !== "ORGANIZATIONAL_UNIT" && targetType !== "ACCOUNT") {
|
|
1838
|
+
continue;
|
|
1839
|
+
}
|
|
1840
|
+
policyAttachments.push({
|
|
1841
|
+
policyId,
|
|
1842
|
+
targetId: target.TargetId,
|
|
1843
|
+
targetType
|
|
1844
|
+
});
|
|
1845
|
+
}
|
|
1846
|
+
targetsNextToken = targetsResponse.NextToken;
|
|
1847
|
+
} while (targetsNextToken != null);
|
|
1848
|
+
}
|
|
1849
|
+
}
|
|
1850
|
+
return { policies, policyAttachments };
|
|
1851
|
+
}
|
|
1524
1852
|
async function collectOrganizationalUnits(props) {
|
|
1525
1853
|
const children = [];
|
|
1526
1854
|
let nextToken;
|
|
@@ -1563,7 +1891,7 @@ async function scanIdentityCenter(props) {
|
|
|
1563
1891
|
instances,
|
|
1564
1892
|
requestedInstanceArn: props.requestedInstanceArn
|
|
1565
1893
|
});
|
|
1566
|
-
const [users, groups, permissionSets] = await Promise.all([
|
|
1894
|
+
const [users, groups, permissionSets, accessControlAttributes] = await Promise.all([
|
|
1567
1895
|
listIdentityStoreUsers({
|
|
1568
1896
|
identityStoreClient: props.identityStoreClient,
|
|
1569
1897
|
identityStoreId: instance.identityStoreId
|
|
@@ -1575,6 +1903,10 @@ async function scanIdentityCenter(props) {
|
|
|
1575
1903
|
listPermissionSets({
|
|
1576
1904
|
ssoAdminClient: props.ssoAdminClient,
|
|
1577
1905
|
instanceArn: instance.instanceArn
|
|
1906
|
+
}),
|
|
1907
|
+
scanAccessControlAttributes({
|
|
1908
|
+
ssoAdminClient: props.ssoAdminClient,
|
|
1909
|
+
instanceArn: instance.instanceArn
|
|
1578
1910
|
})
|
|
1579
1911
|
]);
|
|
1580
1912
|
const groupMemberships = await listGroupMemberships({
|
|
@@ -1599,9 +1931,30 @@ async function scanIdentityCenter(props) {
|
|
|
1599
1931
|
groupMemberships,
|
|
1600
1932
|
permissionSets,
|
|
1601
1933
|
accountAssignments,
|
|
1602
|
-
accessRoles
|
|
1934
|
+
accessRoles,
|
|
1935
|
+
accessControlAttributes
|
|
1603
1936
|
};
|
|
1604
1937
|
}
|
|
1938
|
+
async function scanAccessControlAttributes(props) {
|
|
1939
|
+
let response;
|
|
1940
|
+
try {
|
|
1941
|
+
response = await props.ssoAdminClient.send(
|
|
1942
|
+
new DescribeInstanceAccessControlAttributeConfigurationCommand({
|
|
1943
|
+
InstanceArn: props.instanceArn
|
|
1944
|
+
})
|
|
1945
|
+
);
|
|
1946
|
+
} catch (err) {
|
|
1947
|
+
if (err != null && typeof err === "object" && "name" in err && err.name === "ResourceNotFoundException") {
|
|
1948
|
+
return [];
|
|
1949
|
+
}
|
|
1950
|
+
throw err;
|
|
1951
|
+
}
|
|
1952
|
+
const attributes = response.InstanceAccessControlAttributeConfiguration?.AccessControlAttributes ?? [];
|
|
1953
|
+
return attributes.filter((attr) => attr.Key != null).map((attr) => ({
|
|
1954
|
+
key: attr.Key,
|
|
1955
|
+
source: attr.Value?.Source ?? []
|
|
1956
|
+
}));
|
|
1957
|
+
}
|
|
1605
1958
|
function selectIdentityCenterInstance(props) {
|
|
1606
1959
|
if (props.requestedInstanceArn != null) {
|
|
1607
1960
|
const selected2 = props.instances.find(
|
|
@@ -1892,18 +2245,63 @@ async function listAccountsForPermissionSet(props) {
|
|
|
1892
2245
|
} while (nextToken != null);
|
|
1893
2246
|
return accountIds;
|
|
1894
2247
|
}
|
|
2248
|
+
var ALTERNATE_CONTACT_TYPES = [
|
|
2249
|
+
"BILLING",
|
|
2250
|
+
"OPERATIONS",
|
|
2251
|
+
"SECURITY"
|
|
2252
|
+
];
|
|
2253
|
+
async function scanAlternateContacts(props) {
|
|
2254
|
+
const results = await Promise.all(
|
|
2255
|
+
ALTERNATE_CONTACT_TYPES.map(async (contactType) => {
|
|
2256
|
+
try {
|
|
2257
|
+
const response = await props.accountClient.send(
|
|
2258
|
+
new GetAlternateContactCommand({
|
|
2259
|
+
AccountId: props.isManagementAccount ? void 0 : props.accountId,
|
|
2260
|
+
AlternateContactType: contactType
|
|
2261
|
+
})
|
|
2262
|
+
);
|
|
2263
|
+
const c = response.AlternateContact;
|
|
2264
|
+
if (c == null || c.EmailAddress == null || c.Name == null) {
|
|
2265
|
+
return null;
|
|
2266
|
+
}
|
|
2267
|
+
return {
|
|
2268
|
+
contactType,
|
|
2269
|
+
name: c.Name,
|
|
2270
|
+
email: c.EmailAddress,
|
|
2271
|
+
phone: c.PhoneNumber ?? "",
|
|
2272
|
+
...c.Title != null ? { title: c.Title } : {}
|
|
2273
|
+
};
|
|
2274
|
+
} catch (error) {
|
|
2275
|
+
if (error != null && typeof error === "object" && "name" in error && error.name === "ResourceNotFoundException") {
|
|
2276
|
+
return null;
|
|
2277
|
+
}
|
|
2278
|
+
throw error;
|
|
2279
|
+
}
|
|
2280
|
+
})
|
|
2281
|
+
);
|
|
2282
|
+
return results.filter((c) => c != null);
|
|
2283
|
+
}
|
|
1895
2284
|
|
|
1896
2285
|
// src/applyLogic.ts
|
|
1897
|
-
import { PutAccountNameCommand } from "@aws-sdk/client-account";
|
|
1898
2286
|
import {
|
|
2287
|
+
DeleteAlternateContactCommand,
|
|
2288
|
+
PutAccountNameCommand,
|
|
2289
|
+
PutAlternateContactCommand
|
|
2290
|
+
} from "@aws-sdk/client-account";
|
|
2291
|
+
import {
|
|
2292
|
+
AttachPolicyCommand,
|
|
1899
2293
|
CreateOrganizationalUnitCommand,
|
|
2294
|
+
CreatePolicyCommand,
|
|
1900
2295
|
DeleteOrganizationalUnitCommand,
|
|
2296
|
+
DeletePolicyCommand,
|
|
2297
|
+
DetachPolicyCommand,
|
|
1901
2298
|
ListAccountsForParentCommand,
|
|
1902
2299
|
ListOrganizationalUnitsForParentCommand as ListOrganizationalUnitsForParentCommand2,
|
|
1903
2300
|
MoveAccountCommand as MoveAccountCommand2,
|
|
1904
2301
|
TagResourceCommand,
|
|
1905
2302
|
UntagResourceCommand,
|
|
1906
|
-
UpdateOrganizationalUnitCommand
|
|
2303
|
+
UpdateOrganizationalUnitCommand,
|
|
2304
|
+
UpdatePolicyCommand
|
|
1907
2305
|
} from "@aws-sdk/client-organizations";
|
|
1908
2306
|
import {
|
|
1909
2307
|
CreateGroupMembershipCommand,
|
|
@@ -1931,6 +2329,7 @@ import {
|
|
|
1931
2329
|
DetachManagedPolicyFromPermissionSetCommand,
|
|
1932
2330
|
ProvisionPermissionSetCommand,
|
|
1933
2331
|
PutInlinePolicyToPermissionSetCommand,
|
|
2332
|
+
UpdateInstanceAccessControlAttributeConfigurationCommand,
|
|
1934
2333
|
UpdatePermissionSetCommand
|
|
1935
2334
|
} from "@aws-sdk/client-sso-admin";
|
|
1936
2335
|
|
|
@@ -2920,6 +3319,218 @@ async function executeOperation(props) {
|
|
|
2920
3319
|
}
|
|
2921
3320
|
});
|
|
2922
3321
|
}
|
|
3322
|
+
if (operation.kind === "createOrgPolicy") {
|
|
3323
|
+
props.logger.log(
|
|
3324
|
+
`Creating org policy "${operation.policyName}" (${operation.policyType})...`
|
|
3325
|
+
);
|
|
3326
|
+
const response = await props.organizationsClient.send(
|
|
3327
|
+
new CreatePolicyCommand({
|
|
3328
|
+
Name: operation.policyName,
|
|
3329
|
+
Description: operation.description.length > 0 ? operation.description : void 0,
|
|
3330
|
+
Content: operation.content,
|
|
3331
|
+
Type: operation.policyType
|
|
3332
|
+
})
|
|
3333
|
+
);
|
|
3334
|
+
const policy = response.Policy?.PolicySummary;
|
|
3335
|
+
if (policy?.Id == null || policy.Arn == null) {
|
|
3336
|
+
throw new Error(
|
|
3337
|
+
`CreatePolicy for "${operation.policyName}" returned incomplete data.`
|
|
3338
|
+
);
|
|
3339
|
+
}
|
|
3340
|
+
props.logger.log(`Done: "${operation.policyName}"`);
|
|
3341
|
+
return upsertOrgPolicyInWorkingState({
|
|
3342
|
+
workingState: props.state,
|
|
3343
|
+
policy: {
|
|
3344
|
+
id: policy.Id,
|
|
3345
|
+
arn: policy.Arn,
|
|
3346
|
+
name: operation.policyName,
|
|
3347
|
+
description: operation.description,
|
|
3348
|
+
type: operation.policyType,
|
|
3349
|
+
content: operation.content
|
|
3350
|
+
}
|
|
3351
|
+
});
|
|
3352
|
+
}
|
|
3353
|
+
if (operation.kind === "updateOrgPolicyContent") {
|
|
3354
|
+
props.logger.log(`Updating org policy content "${operation.policyName}"...`);
|
|
3355
|
+
await props.organizationsClient.send(
|
|
3356
|
+
new UpdatePolicyCommand({
|
|
3357
|
+
PolicyId: operation.policyId,
|
|
3358
|
+
Content: operation.content
|
|
3359
|
+
})
|
|
3360
|
+
);
|
|
3361
|
+
props.logger.log(`Done: "${operation.policyName}"`);
|
|
3362
|
+
const currentPolicy = props.state.organization.policiesById[operation.policyId];
|
|
3363
|
+
if (currentPolicy == null) {
|
|
3364
|
+
return props.state;
|
|
3365
|
+
}
|
|
3366
|
+
return upsertOrgPolicyInWorkingState({
|
|
3367
|
+
workingState: props.state,
|
|
3368
|
+
policy: { ...currentPolicy, content: operation.content }
|
|
3369
|
+
});
|
|
3370
|
+
}
|
|
3371
|
+
if (operation.kind === "updateOrgPolicyDescription") {
|
|
3372
|
+
props.logger.log(
|
|
3373
|
+
`Updating org policy description "${operation.policyName}"...`
|
|
3374
|
+
);
|
|
3375
|
+
await props.organizationsClient.send(
|
|
3376
|
+
new UpdatePolicyCommand({
|
|
3377
|
+
PolicyId: operation.policyId,
|
|
3378
|
+
Description: operation.description
|
|
3379
|
+
})
|
|
3380
|
+
);
|
|
3381
|
+
props.logger.log(`Done: "${operation.policyName}"`);
|
|
3382
|
+
const currentPolicy = props.state.organization.policiesById[operation.policyId];
|
|
3383
|
+
if (currentPolicy == null) {
|
|
3384
|
+
return props.state;
|
|
3385
|
+
}
|
|
3386
|
+
return upsertOrgPolicyInWorkingState({
|
|
3387
|
+
workingState: props.state,
|
|
3388
|
+
policy: { ...currentPolicy, description: operation.description }
|
|
3389
|
+
});
|
|
3390
|
+
}
|
|
3391
|
+
if (operation.kind === "attachOrgPolicy") {
|
|
3392
|
+
props.logger.log(
|
|
3393
|
+
`Attaching org policy "${operation.policyName}" to "${operation.targetName}"...`
|
|
3394
|
+
);
|
|
3395
|
+
const resolvedPolicyId = resolvePolicyId({
|
|
3396
|
+
state: props.state,
|
|
3397
|
+
policyId: operation.policyId,
|
|
3398
|
+
policyName: operation.policyName
|
|
3399
|
+
});
|
|
3400
|
+
await props.organizationsClient.send(
|
|
3401
|
+
new AttachPolicyCommand({
|
|
3402
|
+
PolicyId: resolvedPolicyId,
|
|
3403
|
+
TargetId: operation.targetId
|
|
3404
|
+
})
|
|
3405
|
+
);
|
|
3406
|
+
props.logger.log(`Done: "${operation.policyName}" -> "${operation.targetName}"`);
|
|
3407
|
+
const targetType = operation.targetId === props.context.organization.rootId ? "ROOT" : props.state.organization.organizationalUnitsById[operation.targetId] != null ? "ORGANIZATIONAL_UNIT" : "ACCOUNT";
|
|
3408
|
+
return addOrgPolicyAttachmentToWorkingState({
|
|
3409
|
+
workingState: props.state,
|
|
3410
|
+
attachment: {
|
|
3411
|
+
policyId: resolvedPolicyId,
|
|
3412
|
+
targetId: operation.targetId,
|
|
3413
|
+
targetType
|
|
3414
|
+
}
|
|
3415
|
+
});
|
|
3416
|
+
}
|
|
3417
|
+
if (operation.kind === "detachOrgPolicy") {
|
|
3418
|
+
props.logger.log(
|
|
3419
|
+
`Detaching org policy "${operation.policyName}" from "${operation.targetName}"...`
|
|
3420
|
+
);
|
|
3421
|
+
await props.organizationsClient.send(
|
|
3422
|
+
new DetachPolicyCommand({
|
|
3423
|
+
PolicyId: operation.policyId,
|
|
3424
|
+
TargetId: operation.targetId
|
|
3425
|
+
})
|
|
3426
|
+
);
|
|
3427
|
+
props.logger.log(`Done: "${operation.policyName}" x "${operation.targetName}"`);
|
|
3428
|
+
return removeOrgPolicyAttachmentFromWorkingState({
|
|
3429
|
+
workingState: props.state,
|
|
3430
|
+
policyId: operation.policyId,
|
|
3431
|
+
targetId: operation.targetId
|
|
3432
|
+
});
|
|
3433
|
+
}
|
|
3434
|
+
if (operation.kind === "deleteOrgPolicy") {
|
|
3435
|
+
props.logger.log(`Deleting org policy "${operation.policyName}"...`);
|
|
3436
|
+
await props.organizationsClient.send(
|
|
3437
|
+
new DeletePolicyCommand({ PolicyId: operation.policyId })
|
|
3438
|
+
);
|
|
3439
|
+
props.logger.log(`Done: "${operation.policyName}"`);
|
|
3440
|
+
return removeOrgPolicyFromWorkingState({
|
|
3441
|
+
workingState: props.state,
|
|
3442
|
+
policyId: operation.policyId
|
|
3443
|
+
});
|
|
3444
|
+
}
|
|
3445
|
+
if (operation.kind === "putAlternateContact") {
|
|
3446
|
+
props.logger.log(
|
|
3447
|
+
`Setting ${operation.contactType} alternate contact for "${operation.accountName}" (${operation.accountId})...`
|
|
3448
|
+
);
|
|
3449
|
+
await props.accountClient.send(
|
|
3450
|
+
new PutAlternateContactCommand({
|
|
3451
|
+
AccountId: operation.accountId,
|
|
3452
|
+
AlternateContactType: operation.contactType,
|
|
3453
|
+
Name: operation.name,
|
|
3454
|
+
EmailAddress: operation.email,
|
|
3455
|
+
PhoneNumber: operation.phone,
|
|
3456
|
+
Title: operation.title
|
|
3457
|
+
})
|
|
3458
|
+
);
|
|
3459
|
+
props.logger.log(`Done: ${operation.contactType} contact for "${operation.accountName}"`);
|
|
3460
|
+
const account = props.state.organization.accountsById[operation.accountId];
|
|
3461
|
+
if (account == null) {
|
|
3462
|
+
throw new Error(
|
|
3463
|
+
`Could not resolve account (${operation.accountId}) in working state.`
|
|
3464
|
+
);
|
|
3465
|
+
}
|
|
3466
|
+
const updatedContacts = [
|
|
3467
|
+
...(account.alternateContacts ?? []).filter(
|
|
3468
|
+
(c) => c.contactType !== operation.contactType
|
|
3469
|
+
),
|
|
3470
|
+
{
|
|
3471
|
+
contactType: operation.contactType,
|
|
3472
|
+
name: operation.name,
|
|
3473
|
+
email: operation.email,
|
|
3474
|
+
phone: operation.phone,
|
|
3475
|
+
title: operation.title
|
|
3476
|
+
}
|
|
3477
|
+
];
|
|
3478
|
+
return upsertAccountInWorkingState({
|
|
3479
|
+
workingState: props.state,
|
|
3480
|
+
account: { ...account, alternateContacts: updatedContacts }
|
|
3481
|
+
});
|
|
3482
|
+
}
|
|
3483
|
+
if (operation.kind === "deleteAlternateContact") {
|
|
3484
|
+
props.logger.log(
|
|
3485
|
+
`Deleting ${operation.contactType} alternate contact for "${operation.accountName}" (${operation.accountId})...`
|
|
3486
|
+
);
|
|
3487
|
+
await props.accountClient.send(
|
|
3488
|
+
new DeleteAlternateContactCommand({
|
|
3489
|
+
AccountId: operation.accountId,
|
|
3490
|
+
AlternateContactType: operation.contactType
|
|
3491
|
+
})
|
|
3492
|
+
);
|
|
3493
|
+
props.logger.log(`Done: removed ${operation.contactType} contact for "${operation.accountName}"`);
|
|
3494
|
+
const account = props.state.organization.accountsById[operation.accountId];
|
|
3495
|
+
if (account == null) {
|
|
3496
|
+
throw new Error(
|
|
3497
|
+
`Could not resolve account (${operation.accountId}) in working state.`
|
|
3498
|
+
);
|
|
3499
|
+
}
|
|
3500
|
+
return upsertAccountInWorkingState({
|
|
3501
|
+
workingState: props.state,
|
|
3502
|
+
account: {
|
|
3503
|
+
...account,
|
|
3504
|
+
alternateContacts: (account.alternateContacts ?? []).filter(
|
|
3505
|
+
(c) => c.contactType !== operation.contactType
|
|
3506
|
+
)
|
|
3507
|
+
}
|
|
3508
|
+
});
|
|
3509
|
+
}
|
|
3510
|
+
if (operation.kind === "setIdcAccessControlAttributes") {
|
|
3511
|
+
props.logger.log(
|
|
3512
|
+
`Setting IdC access control attributes (${operation.attributes.length} attribute(s))...`
|
|
3513
|
+
);
|
|
3514
|
+
await props.ssoAdminClient.send(
|
|
3515
|
+
new UpdateInstanceAccessControlAttributeConfigurationCommand({
|
|
3516
|
+
InstanceArn: props.state.identityCenter.instanceArn,
|
|
3517
|
+
InstanceAccessControlAttributeConfiguration: {
|
|
3518
|
+
AccessControlAttributes: operation.attributes.map((attr) => ({
|
|
3519
|
+
Key: attr.key,
|
|
3520
|
+
Value: { Source: attr.source }
|
|
3521
|
+
}))
|
|
3522
|
+
}
|
|
3523
|
+
})
|
|
3524
|
+
);
|
|
3525
|
+
props.logger.log(`Done: access control attributes updated`);
|
|
3526
|
+
return {
|
|
3527
|
+
...props.state,
|
|
3528
|
+
identityCenter: {
|
|
3529
|
+
...props.state.identityCenter,
|
|
3530
|
+
accessControlAttributes: operation.attributes
|
|
3531
|
+
}
|
|
3532
|
+
};
|
|
3533
|
+
}
|
|
2923
3534
|
assertUnreachable(operation, "Unsupported operation kind in apply.");
|
|
2924
3535
|
}
|
|
2925
3536
|
function resolveAssignmentDependencies(props) {
|
|
@@ -2980,6 +3591,16 @@ function resolveGroupByDisplayName(props) {
|
|
|
2980
3591
|
}
|
|
2981
3592
|
return group;
|
|
2982
3593
|
}
|
|
3594
|
+
function resolvePolicyId(props) {
|
|
3595
|
+
if (props.policyId !== "__pending_creation__") return props.policyId;
|
|
3596
|
+
const policy = props.state.organization.policiesByName[props.policyName];
|
|
3597
|
+
if (policy == null) {
|
|
3598
|
+
throw new Error(
|
|
3599
|
+
`Could not resolve policy "${props.policyName}" in working state.`
|
|
3600
|
+
);
|
|
3601
|
+
}
|
|
3602
|
+
return policy.id;
|
|
3603
|
+
}
|
|
2983
3604
|
function resolvePermissionSetByName(props) {
|
|
2984
3605
|
const permissionSet = props.state.identityCenter.permissionSetsByName[props.permissionSetName];
|
|
2985
3606
|
if (permissionSet == null) {
|
|
@@ -3269,7 +3890,9 @@ var scanResponseSchema = strictObject({
|
|
|
3269
3890
|
users: number(),
|
|
3270
3891
|
groups: number(),
|
|
3271
3892
|
permissionSets: number(),
|
|
3272
|
-
accountAssignments: number()
|
|
3893
|
+
accountAssignments: number(),
|
|
3894
|
+
policies: number(),
|
|
3895
|
+
policyAttachments: number()
|
|
3273
3896
|
}),
|
|
3274
3897
|
state: stateSchema
|
|
3275
3898
|
});
|
|
@@ -3339,7 +3962,7 @@ var s3Client = new S3Client({});
|
|
|
3339
3962
|
var organizationsClient = new OrganizationsClient3({});
|
|
3340
3963
|
var ssoAdminClient = new SSOAdminClient3({});
|
|
3341
3964
|
var identityStoreClient = new IdentitystoreClient3({});
|
|
3342
|
-
var accountClient = new
|
|
3965
|
+
var accountClient = new AccountClient3({});
|
|
3343
3966
|
async function handler(event) {
|
|
3344
3967
|
try {
|
|
3345
3968
|
const parseResult = safeParse(lambdaRequestSchema, event);
|
|
@@ -3364,7 +3987,7 @@ async function handler(event) {
|
|
|
3364
3987
|
return validateResponse(response);
|
|
3365
3988
|
}
|
|
3366
3989
|
if (request.action === "scan") {
|
|
3367
|
-
const response = await handleScan({ s3Client, bucket, organizationsClient, ssoAdminClient, identityStoreClient });
|
|
3990
|
+
const response = await handleScan({ s3Client, bucket, organizationsClient, ssoAdminClient, identityStoreClient, accountClient });
|
|
3368
3991
|
return validateResponse(response);
|
|
3369
3992
|
}
|
|
3370
3993
|
if (request.action === "getStateUrl") {
|
|
@@ -3453,7 +4076,7 @@ function isS3PreconditionFailed(error) {
|
|
|
3453
4076
|
async function handleScan(props) {
|
|
3454
4077
|
const identityCenterInstanceArn = process.env.IDENTITY_CENTER_INSTANCE_ARN || void 0;
|
|
3455
4078
|
const [organization, identityCenter] = await Promise.all([
|
|
3456
|
-
scanOrganization({ organizationsClient: props.organizationsClient }),
|
|
4079
|
+
scanOrganization({ organizationsClient: props.organizationsClient, accountClient: props.accountClient }),
|
|
3457
4080
|
scanIdentityCenter({
|
|
3458
4081
|
ssoAdminClient: props.ssoAdminClient,
|
|
3459
4082
|
identityStoreClient: props.identityStoreClient,
|
|
@@ -3480,7 +4103,9 @@ async function handleScan(props) {
|
|
|
3480
4103
|
users: state.identityCenter.users.length,
|
|
3481
4104
|
groups: state.identityCenter.groups.length,
|
|
3482
4105
|
permissionSets: state.identityCenter.permissionSets.length,
|
|
3483
|
-
accountAssignments: state.identityCenter.accountAssignments.length
|
|
4106
|
+
accountAssignments: state.identityCenter.accountAssignments.length,
|
|
4107
|
+
policies: state.organization.policies?.length ?? 0,
|
|
4108
|
+
policyAttachments: state.organization.policyAttachments?.length ?? 0
|
|
3484
4109
|
},
|
|
3485
4110
|
state
|
|
3486
4111
|
};
|