@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/state.js
CHANGED
|
@@ -9,10 +9,37 @@ 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
|
+
"BACKUP_POLICY"
|
|
18
|
+
]);
|
|
19
|
+
const orgPolicySchema = v.strictObject({
|
|
20
|
+
id: nonEmptyString,
|
|
21
|
+
arn: nonEmptyString,
|
|
22
|
+
name: nonEmptyString,
|
|
23
|
+
description: v.string(),
|
|
24
|
+
type: orgPolicyTypeSchema,
|
|
25
|
+
content: nonEmptyString
|
|
26
|
+
});
|
|
27
|
+
const orgPolicyAttachmentSchema = v.strictObject({
|
|
28
|
+
policyId: nonEmptyString,
|
|
29
|
+
targetId: nonEmptyString,
|
|
30
|
+
targetType: v.picklist(["ROOT", "ORGANIZATIONAL_UNIT", "ACCOUNT"])
|
|
31
|
+
});
|
|
12
32
|
const accountTagSchema = v.strictObject({
|
|
13
33
|
key: nonEmptyString,
|
|
14
34
|
value: v.string()
|
|
15
35
|
});
|
|
36
|
+
const alternateContactSchema = v.strictObject({
|
|
37
|
+
contactType: v.picklist(["BILLING", "OPERATIONS", "SECURITY"]),
|
|
38
|
+
name: v.string(),
|
|
39
|
+
email: v.string(),
|
|
40
|
+
phone: v.string(),
|
|
41
|
+
title: v.optional(v.string())
|
|
42
|
+
});
|
|
16
43
|
const accountSchema = v.strictObject({
|
|
17
44
|
id: nonEmptyString,
|
|
18
45
|
arn: nonEmptyString,
|
|
@@ -20,7 +47,8 @@ const accountSchema = v.strictObject({
|
|
|
20
47
|
email: nonEmptyString,
|
|
21
48
|
status: nonEmptyString,
|
|
22
49
|
parentId: nonEmptyString,
|
|
23
|
-
tags: v.array(accountTagSchema)
|
|
50
|
+
tags: v.array(accountTagSchema),
|
|
51
|
+
alternateContacts: v.optional(v.array(alternateContactSchema))
|
|
24
52
|
});
|
|
25
53
|
const userSchema = v.strictObject({
|
|
26
54
|
userId: nonEmptyString,
|
|
@@ -42,6 +70,13 @@ const customerManagedPolicyReferenceSchema = v.strictObject({
|
|
|
42
70
|
name: nonEmptyString,
|
|
43
71
|
path: nonEmptyString
|
|
44
72
|
});
|
|
73
|
+
const permissionsBoundarySchema = v.union([
|
|
74
|
+
v.strictObject({ managedPolicyArn: nonEmptyString }),
|
|
75
|
+
v.strictObject({
|
|
76
|
+
customerManagedPolicyName: nonEmptyString,
|
|
77
|
+
customerManagedPolicyPath: nonEmptyString
|
|
78
|
+
})
|
|
79
|
+
]);
|
|
45
80
|
const permissionSetSchema = v.strictObject({
|
|
46
81
|
permissionSetArn: nonEmptyString,
|
|
47
82
|
name: nonEmptyString,
|
|
@@ -49,7 +84,8 @@ const permissionSetSchema = v.strictObject({
|
|
|
49
84
|
sessionDuration: v.nullable(v.string()),
|
|
50
85
|
inlinePolicy: v.nullable(nonEmptyString),
|
|
51
86
|
awsManagedPolicies: v.array(nonEmptyString),
|
|
52
|
-
customerManagedPolicies: v.array(customerManagedPolicyReferenceSchema)
|
|
87
|
+
customerManagedPolicies: v.array(customerManagedPolicyReferenceSchema),
|
|
88
|
+
permissionsBoundary: v.nullable(permissionsBoundarySchema)
|
|
53
89
|
});
|
|
54
90
|
const accountAssignmentSchema = v.strictObject({
|
|
55
91
|
accountId: nonEmptyString,
|
|
@@ -64,13 +100,24 @@ const accessRoleSchema = v.strictObject({
|
|
|
64
100
|
principalType: principalTypeSchema,
|
|
65
101
|
roleName: nonEmptyString
|
|
66
102
|
});
|
|
103
|
+
const accessControlAttributeSchema = v.strictObject({
|
|
104
|
+
key: nonEmptyString,
|
|
105
|
+
source: v.array(nonEmptyString)
|
|
106
|
+
});
|
|
107
|
+
const delegatedAdministratorSchema = v.strictObject({
|
|
108
|
+
accountId: nonEmptyString,
|
|
109
|
+
servicePrincipal: nonEmptyString
|
|
110
|
+
});
|
|
67
111
|
const stateSchema = v.strictObject({
|
|
68
112
|
version: nonEmptyString,
|
|
69
113
|
generatedAt: nonEmptyString,
|
|
70
114
|
organization: v.strictObject({
|
|
71
115
|
rootId: nonEmptyString,
|
|
72
116
|
organizationalUnits: v.array(organizationalUnitSchema),
|
|
73
|
-
accounts: v.array(accountSchema)
|
|
117
|
+
accounts: v.array(accountSchema),
|
|
118
|
+
policies: v.optional(v.array(orgPolicySchema)),
|
|
119
|
+
policyAttachments: v.optional(v.array(orgPolicyAttachmentSchema)),
|
|
120
|
+
delegatedAdministrators: v.optional(v.array(delegatedAdministratorSchema))
|
|
74
121
|
}),
|
|
75
122
|
identityCenter: v.strictObject({
|
|
76
123
|
instanceArn: nonEmptyString,
|
|
@@ -80,13 +127,17 @@ const stateSchema = v.strictObject({
|
|
|
80
127
|
groupMemberships: v.array(groupMembershipSchema),
|
|
81
128
|
permissionSets: v.array(permissionSetSchema),
|
|
82
129
|
accountAssignments: v.array(accountAssignmentSchema),
|
|
83
|
-
accessRoles: v.array(accessRoleSchema)
|
|
130
|
+
accessRoles: v.array(accessRoleSchema),
|
|
131
|
+
accessControlAttributes: v.array(accessControlAttributeSchema)
|
|
84
132
|
})
|
|
85
133
|
});
|
|
86
134
|
function validateState(value) {
|
|
87
135
|
return v.parse(stateSchema, value);
|
|
88
136
|
}
|
|
89
137
|
function createWorkingState(props) {
|
|
138
|
+
const policies = props.state.organization.policies ?? [];
|
|
139
|
+
const policyAttachments = props.state.organization.policyAttachments ?? [];
|
|
140
|
+
const delegatedAdministrators = props.state.organization.delegatedAdministrators ?? [];
|
|
90
141
|
return {
|
|
91
142
|
version: props.state.version,
|
|
92
143
|
generatedAt: props.state.generatedAt,
|
|
@@ -100,6 +151,18 @@ function createWorkingState(props) {
|
|
|
100
151
|
accountsByName: toRecordByProperty(
|
|
101
152
|
props.state.organization.accounts,
|
|
102
153
|
"name"
|
|
154
|
+
),
|
|
155
|
+
policiesById: toRecordByProperty(policies, "id"),
|
|
156
|
+
policiesByName: toRecordByProperty(policies, "name"),
|
|
157
|
+
policyAttachments: structuredClone(policyAttachments),
|
|
158
|
+
policyAttachmentsByKey: toRecordByProperty(
|
|
159
|
+
policyAttachments,
|
|
160
|
+
createOrgPolicyAttachmentKey
|
|
161
|
+
),
|
|
162
|
+
delegatedAdministrators: structuredClone(delegatedAdministrators),
|
|
163
|
+
delegatedAdministratorsByKey: toRecordByProperty(
|
|
164
|
+
delegatedAdministrators,
|
|
165
|
+
createDelegatedAdministratorKey
|
|
103
166
|
)
|
|
104
167
|
},
|
|
105
168
|
identityCenter: createWorkingIdentityCenterState({
|
|
@@ -116,7 +179,16 @@ function materializeWorkingState(props) {
|
|
|
116
179
|
organizationalUnits: Object.values(
|
|
117
180
|
props.workingState.organization.organizationalUnitsById
|
|
118
181
|
),
|
|
119
|
-
accounts: Object.values(props.workingState.organization.accountsById)
|
|
182
|
+
accounts: Object.values(props.workingState.organization.accountsById),
|
|
183
|
+
policies: Object.values(props.workingState.organization.policiesById),
|
|
184
|
+
policyAttachments: structuredClone(
|
|
185
|
+
props.workingState.organization.policyAttachments
|
|
186
|
+
),
|
|
187
|
+
...props.workingState.organization.delegatedAdministrators.length > 0 ? {
|
|
188
|
+
delegatedAdministrators: structuredClone(
|
|
189
|
+
props.workingState.organization.delegatedAdministrators
|
|
190
|
+
)
|
|
191
|
+
} : {}
|
|
120
192
|
},
|
|
121
193
|
identityCenter: {
|
|
122
194
|
instanceArn: props.workingState.identityCenter.instanceArn,
|
|
@@ -134,6 +206,9 @@ function materializeWorkingState(props) {
|
|
|
134
206
|
),
|
|
135
207
|
accessRoles: structuredClone(
|
|
136
208
|
props.workingState.identityCenter.accessRoles
|
|
209
|
+
),
|
|
210
|
+
accessControlAttributes: structuredClone(
|
|
211
|
+
props.workingState.identityCenter.accessControlAttributes
|
|
137
212
|
)
|
|
138
213
|
}
|
|
139
214
|
};
|
|
@@ -346,7 +421,7 @@ function removeIdcGroupFromWorkingState(props) {
|
|
|
346
421
|
}
|
|
347
422
|
function upsertIdcPermissionSetInWorkingState(props) {
|
|
348
423
|
const currentPermissionSet = props.workingState.identityCenter.permissionSetsByName[props.permissionSet.name];
|
|
349
|
-
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)) {
|
|
424
|
+
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) && JSON.stringify(currentPermissionSet.permissionsBoundary) === JSON.stringify(props.permissionSet.permissionsBoundary)) {
|
|
350
425
|
return props.workingState;
|
|
351
426
|
}
|
|
352
427
|
const remainingPermissionSets = props.workingState.identityCenter.permissionSets.filter(
|
|
@@ -488,6 +563,154 @@ function removeAccountAssignmentFromWorkingState(props) {
|
|
|
488
563
|
})
|
|
489
564
|
};
|
|
490
565
|
}
|
|
566
|
+
function createOrgPolicyAttachmentKey(props) {
|
|
567
|
+
return [props.policyId, props.targetId].join("|");
|
|
568
|
+
}
|
|
569
|
+
function upsertOrgPolicyInWorkingState(props) {
|
|
570
|
+
const currentPolicy = props.workingState.organization.policiesById[props.policy.id];
|
|
571
|
+
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) {
|
|
572
|
+
return props.workingState;
|
|
573
|
+
}
|
|
574
|
+
const remainingPolicies = Object.values(
|
|
575
|
+
props.workingState.organization.policiesById
|
|
576
|
+
).filter((p) => p.id !== props.policy.id);
|
|
577
|
+
const nextPolicies = [...remainingPolicies, props.policy];
|
|
578
|
+
return {
|
|
579
|
+
...props.workingState,
|
|
580
|
+
organization: {
|
|
581
|
+
...props.workingState.organization,
|
|
582
|
+
policiesById: toRecordByProperty(nextPolicies, "id"),
|
|
583
|
+
policiesByName: toRecordByProperty(nextPolicies, "name")
|
|
584
|
+
}
|
|
585
|
+
};
|
|
586
|
+
}
|
|
587
|
+
function removeOrgPolicyFromWorkingState(props) {
|
|
588
|
+
if (props.workingState.organization.policiesById[props.policyId] == null) {
|
|
589
|
+
return props.workingState;
|
|
590
|
+
}
|
|
591
|
+
const nextPolicies = Object.values(
|
|
592
|
+
props.workingState.organization.policiesById
|
|
593
|
+
).filter((p) => p.id !== props.policyId);
|
|
594
|
+
const nextAttachments = props.workingState.organization.policyAttachments.filter(
|
|
595
|
+
(a) => a.policyId !== props.policyId
|
|
596
|
+
);
|
|
597
|
+
return {
|
|
598
|
+
...props.workingState,
|
|
599
|
+
organization: {
|
|
600
|
+
...props.workingState.organization,
|
|
601
|
+
policiesById: toRecordByProperty(nextPolicies, "id"),
|
|
602
|
+
policiesByName: toRecordByProperty(nextPolicies, "name"),
|
|
603
|
+
policyAttachments: nextAttachments,
|
|
604
|
+
policyAttachmentsByKey: toRecordByProperty(
|
|
605
|
+
nextAttachments,
|
|
606
|
+
createOrgPolicyAttachmentKey
|
|
607
|
+
)
|
|
608
|
+
}
|
|
609
|
+
};
|
|
610
|
+
}
|
|
611
|
+
function addOrgPolicyAttachmentToWorkingState(props) {
|
|
612
|
+
const key = createOrgPolicyAttachmentKey({
|
|
613
|
+
policyId: props.attachment.policyId,
|
|
614
|
+
targetId: props.attachment.targetId
|
|
615
|
+
});
|
|
616
|
+
if (props.workingState.organization.policyAttachmentsByKey[key] != null) {
|
|
617
|
+
return props.workingState;
|
|
618
|
+
}
|
|
619
|
+
const nextAttachments = [
|
|
620
|
+
...props.workingState.organization.policyAttachments,
|
|
621
|
+
props.attachment
|
|
622
|
+
];
|
|
623
|
+
return {
|
|
624
|
+
...props.workingState,
|
|
625
|
+
organization: {
|
|
626
|
+
...props.workingState.organization,
|
|
627
|
+
policyAttachments: nextAttachments,
|
|
628
|
+
policyAttachmentsByKey: toRecordByProperty(
|
|
629
|
+
nextAttachments,
|
|
630
|
+
createOrgPolicyAttachmentKey
|
|
631
|
+
)
|
|
632
|
+
}
|
|
633
|
+
};
|
|
634
|
+
}
|
|
635
|
+
function removeOrgPolicyAttachmentFromWorkingState(props) {
|
|
636
|
+
const key = createOrgPolicyAttachmentKey({
|
|
637
|
+
policyId: props.policyId,
|
|
638
|
+
targetId: props.targetId
|
|
639
|
+
});
|
|
640
|
+
if (props.workingState.organization.policyAttachmentsByKey[key] == null) {
|
|
641
|
+
return props.workingState;
|
|
642
|
+
}
|
|
643
|
+
const nextAttachments = props.workingState.organization.policyAttachments.filter(
|
|
644
|
+
(a) => createOrgPolicyAttachmentKey({
|
|
645
|
+
policyId: a.policyId,
|
|
646
|
+
targetId: a.targetId
|
|
647
|
+
}) !== key
|
|
648
|
+
);
|
|
649
|
+
return {
|
|
650
|
+
...props.workingState,
|
|
651
|
+
organization: {
|
|
652
|
+
...props.workingState.organization,
|
|
653
|
+
policyAttachments: nextAttachments,
|
|
654
|
+
policyAttachmentsByKey: toRecordByProperty(
|
|
655
|
+
nextAttachments,
|
|
656
|
+
createOrgPolicyAttachmentKey
|
|
657
|
+
)
|
|
658
|
+
}
|
|
659
|
+
};
|
|
660
|
+
}
|
|
661
|
+
function createDelegatedAdministratorKey(props) {
|
|
662
|
+
return [props.accountId, props.servicePrincipal].join("|");
|
|
663
|
+
}
|
|
664
|
+
function upsertDelegatedAdministratorInWorkingState(props) {
|
|
665
|
+
const key = createDelegatedAdministratorKey({
|
|
666
|
+
accountId: props.delegatedAdministrator.accountId,
|
|
667
|
+
servicePrincipal: props.delegatedAdministrator.servicePrincipal
|
|
668
|
+
});
|
|
669
|
+
if (props.workingState.organization.delegatedAdministratorsByKey[key] != null) {
|
|
670
|
+
return props.workingState;
|
|
671
|
+
}
|
|
672
|
+
const nextDelegatedAdministrators = [
|
|
673
|
+
...props.workingState.organization.delegatedAdministrators,
|
|
674
|
+
props.delegatedAdministrator
|
|
675
|
+
];
|
|
676
|
+
return {
|
|
677
|
+
...props.workingState,
|
|
678
|
+
organization: {
|
|
679
|
+
...props.workingState.organization,
|
|
680
|
+
delegatedAdministrators: nextDelegatedAdministrators,
|
|
681
|
+
delegatedAdministratorsByKey: toRecordByProperty(
|
|
682
|
+
nextDelegatedAdministrators,
|
|
683
|
+
createDelegatedAdministratorKey
|
|
684
|
+
)
|
|
685
|
+
}
|
|
686
|
+
};
|
|
687
|
+
}
|
|
688
|
+
function removeDelegatedAdministratorFromWorkingState(props) {
|
|
689
|
+
const key = createDelegatedAdministratorKey({
|
|
690
|
+
accountId: props.accountId,
|
|
691
|
+
servicePrincipal: props.servicePrincipal
|
|
692
|
+
});
|
|
693
|
+
if (props.workingState.organization.delegatedAdministratorsByKey[key] == null) {
|
|
694
|
+
return props.workingState;
|
|
695
|
+
}
|
|
696
|
+
const nextDelegatedAdministrators = props.workingState.organization.delegatedAdministrators.filter(
|
|
697
|
+
(da) => createDelegatedAdministratorKey({
|
|
698
|
+
accountId: da.accountId,
|
|
699
|
+
servicePrincipal: da.servicePrincipal
|
|
700
|
+
}) !== key
|
|
701
|
+
);
|
|
702
|
+
return {
|
|
703
|
+
...props.workingState,
|
|
704
|
+
organization: {
|
|
705
|
+
...props.workingState.organization,
|
|
706
|
+
delegatedAdministrators: nextDelegatedAdministrators,
|
|
707
|
+
delegatedAdministratorsByKey: toRecordByProperty(
|
|
708
|
+
nextDelegatedAdministrators,
|
|
709
|
+
createDelegatedAdministratorKey
|
|
710
|
+
)
|
|
711
|
+
}
|
|
712
|
+
};
|
|
713
|
+
}
|
|
491
714
|
async function readStateFile(path) {
|
|
492
715
|
const content = await readFile(path, "utf8");
|
|
493
716
|
const parsed = JSON.parse(content);
|
|
@@ -527,7 +750,10 @@ function createWorkingIdentityCenterState(props) {
|
|
|
527
750
|
),
|
|
528
751
|
accessRoles: createAccessRoles({
|
|
529
752
|
accountAssignments
|
|
530
|
-
})
|
|
753
|
+
}),
|
|
754
|
+
accessControlAttributes: structuredClone(
|
|
755
|
+
props.identityCenter.accessControlAttributes ?? []
|
|
756
|
+
)
|
|
531
757
|
};
|
|
532
758
|
}
|
|
533
759
|
function materializeWorkingIdentityCenterState(props) {
|
|
@@ -541,7 +767,10 @@ function materializeWorkingIdentityCenterState(props) {
|
|
|
541
767
|
accountAssignments: structuredClone(
|
|
542
768
|
props.identityCenter.accountAssignments
|
|
543
769
|
),
|
|
544
|
-
accessRoles: structuredClone(props.identityCenter.accessRoles)
|
|
770
|
+
accessRoles: structuredClone(props.identityCenter.accessRoles),
|
|
771
|
+
accessControlAttributes: structuredClone(
|
|
772
|
+
props.identityCenter.accessControlAttributes
|
|
773
|
+
)
|
|
545
774
|
};
|
|
546
775
|
}
|
|
547
776
|
function createAccessRoles(props) {
|
|
@@ -596,24 +825,31 @@ function sortJsonValue(value) {
|
|
|
596
825
|
export {
|
|
597
826
|
addAccountAssignmentToWorkingState,
|
|
598
827
|
addGroupMembershipToWorkingState,
|
|
828
|
+
addOrgPolicyAttachmentToWorkingState,
|
|
599
829
|
createAccessRoleName,
|
|
600
830
|
createGroupMembershipKey,
|
|
831
|
+
createOrgPolicyAttachmentKey,
|
|
601
832
|
createWorkingState,
|
|
602
833
|
materializeWorkingState,
|
|
603
834
|
moveAccountInWorkingState,
|
|
604
835
|
readStateFile,
|
|
605
836
|
removeAccountAssignmentFromWorkingState,
|
|
837
|
+
removeDelegatedAdministratorFromWorkingState,
|
|
606
838
|
removeGroupMembershipFromWorkingState,
|
|
607
839
|
removeIdcGroupFromWorkingState,
|
|
608
840
|
removeIdcPermissionSetFromWorkingState,
|
|
609
841
|
removeIdcUserFromWorkingState,
|
|
842
|
+
removeOrgPolicyAttachmentFromWorkingState,
|
|
843
|
+
removeOrgPolicyFromWorkingState,
|
|
610
844
|
removeOrganizationalUnitFromWorkingState,
|
|
611
845
|
renameOrganizationalUnitInWorkingState,
|
|
612
846
|
stateSchema,
|
|
613
847
|
upsertAccountInWorkingState,
|
|
848
|
+
upsertDelegatedAdministratorInWorkingState,
|
|
614
849
|
upsertIdcGroupInWorkingState,
|
|
615
850
|
upsertIdcPermissionSetInWorkingState,
|
|
616
851
|
upsertIdcUserInWorkingState,
|
|
852
|
+
upsertOrgPolicyInWorkingState,
|
|
617
853
|
upsertOrganizationalUnitInWorkingState,
|
|
618
854
|
validateState
|
|
619
855
|
};
|