@cloud-copilot/iam-lens 0.1.44 → 0.1.45
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/dist/cjs/cli.js +3 -3
- package/dist/cjs/cli.js.map +1 -1
- package/dist/cjs/collect/client.d.ts +1 -0
- package/dist/cjs/collect/client.d.ts.map +1 -1
- package/dist/cjs/collect/client.js +11 -0
- package/dist/cjs/collect/client.js.map +1 -1
- package/dist/cjs/index.d.ts +1 -1
- package/dist/cjs/index.d.ts.map +1 -1
- package/dist/cjs/index.js +3 -3
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/{canWhat → principalCan}/permission.d.ts +3 -0
- package/dist/cjs/principalCan/permission.d.ts.map +1 -0
- package/dist/cjs/{canWhat → principalCan}/permission.js +3 -0
- package/dist/cjs/principalCan/permission.js.map +1 -0
- package/dist/cjs/principalCan/permissionSet.d.ts +129 -0
- package/dist/cjs/principalCan/permissionSet.d.ts.map +1 -0
- package/dist/cjs/{canWhat → principalCan}/permissionSet.js +122 -26
- package/dist/cjs/principalCan/permissionSet.js.map +1 -0
- package/dist/cjs/{canWhat/canWhat.d.ts → principalCan/principalCan.d.ts} +3 -3
- package/dist/cjs/principalCan/principalCan.d.ts.map +1 -0
- package/dist/cjs/{canWhat/canWhat.js → principalCan/principalCan.js} +16 -3
- package/dist/cjs/principalCan/principalCan.js.map +1 -0
- package/dist/cjs/principalCan/resources/actions.d.ts +9 -0
- package/dist/cjs/principalCan/resources/actions.d.ts.map +1 -0
- package/dist/cjs/principalCan/resources/actions.js +27 -0
- package/dist/cjs/principalCan/resources/actions.js.map +1 -0
- package/dist/cjs/principalCan/resources/resourceTypes/s3Buckets.d.ts +14 -0
- package/dist/cjs/principalCan/resources/resourceTypes/s3Buckets.d.ts.map +1 -0
- package/dist/cjs/principalCan/resources/resourceTypes/s3Buckets.js +64 -0
- package/dist/cjs/principalCan/resources/resourceTypes/s3Buckets.js.map +1 -0
- package/dist/cjs/principalCan/resources/statements.d.ts +27 -0
- package/dist/cjs/principalCan/resources/statements.d.ts.map +1 -0
- package/dist/cjs/principalCan/resources/statements.js +113 -0
- package/dist/cjs/principalCan/resources/statements.js.map +1 -0
- package/dist/esm/cli.js +3 -3
- package/dist/esm/cli.js.map +1 -1
- package/dist/esm/collect/client.d.ts +1 -0
- package/dist/esm/collect/client.d.ts.map +1 -1
- package/dist/esm/collect/client.js +11 -0
- package/dist/esm/collect/client.js.map +1 -1
- package/dist/esm/index.d.ts +1 -1
- package/dist/esm/index.d.ts.map +1 -1
- package/dist/esm/index.js +1 -1
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/{canWhat → principalCan}/permission.d.ts +3 -0
- package/dist/esm/principalCan/permission.d.ts.map +1 -0
- package/dist/esm/{canWhat → principalCan}/permission.js +3 -0
- package/dist/esm/principalCan/permission.js.map +1 -0
- package/dist/esm/principalCan/permissionSet.d.ts +129 -0
- package/dist/esm/principalCan/permissionSet.d.ts.map +1 -0
- package/dist/esm/{canWhat → principalCan}/permissionSet.js +121 -26
- package/dist/esm/principalCan/permissionSet.js.map +1 -0
- package/dist/esm/{canWhat/canWhat.d.ts → principalCan/principalCan.d.ts} +3 -3
- package/dist/esm/principalCan/principalCan.d.ts.map +1 -0
- package/dist/esm/{canWhat/canWhat.js → principalCan/principalCan.js} +16 -3
- package/dist/esm/principalCan/principalCan.js.map +1 -0
- package/dist/esm/principalCan/resources/actions.d.ts +9 -0
- package/dist/esm/principalCan/resources/actions.d.ts.map +1 -0
- package/dist/esm/principalCan/resources/actions.js +24 -0
- package/dist/esm/principalCan/resources/actions.js.map +1 -0
- package/dist/esm/principalCan/resources/resourceTypes/s3Buckets.d.ts +14 -0
- package/dist/esm/principalCan/resources/resourceTypes/s3Buckets.d.ts.map +1 -0
- package/dist/esm/principalCan/resources/resourceTypes/s3Buckets.js +61 -0
- package/dist/esm/principalCan/resources/resourceTypes/s3Buckets.js.map +1 -0
- package/dist/esm/principalCan/resources/statements.d.ts +27 -0
- package/dist/esm/principalCan/resources/statements.d.ts.map +1 -0
- package/dist/esm/principalCan/resources/statements.js +109 -0
- package/dist/esm/principalCan/resources/statements.js.map +1 -0
- package/package.json +1 -1
- package/dist/cjs/canWhat/canWhat.d.ts.map +0 -1
- package/dist/cjs/canWhat/canWhat.js.map +0 -1
- package/dist/cjs/canWhat/permission.d.ts.map +0 -1
- package/dist/cjs/canWhat/permission.js.map +0 -1
- package/dist/cjs/canWhat/permissionSet.d.ts +0 -59
- package/dist/cjs/canWhat/permissionSet.d.ts.map +0 -1
- package/dist/cjs/canWhat/permissionSet.js.map +0 -1
- package/dist/esm/canWhat/canWhat.d.ts.map +0 -1
- package/dist/esm/canWhat/canWhat.js.map +0 -1
- package/dist/esm/canWhat/permission.d.ts.map +0 -1
- package/dist/esm/canWhat/permission.js.map +0 -1
- package/dist/esm/canWhat/permissionSet.d.ts +0 -59
- package/dist/esm/canWhat/permissionSet.d.ts.map +0 -1
- package/dist/esm/canWhat/permissionSet.js.map +0 -1
|
@@ -10,6 +10,12 @@ export class PermissionSet {
|
|
|
10
10
|
this.effect = effect;
|
|
11
11
|
this.permissions = {};
|
|
12
12
|
}
|
|
13
|
+
/**
|
|
14
|
+
* Add a new permission to the set. If the new permission overlaps with an existing one,
|
|
15
|
+
* they will be unioned together to avoid redundancy.
|
|
16
|
+
*
|
|
17
|
+
* @param newPermission the permission to add
|
|
18
|
+
*/
|
|
13
19
|
addPermission(newPermission) {
|
|
14
20
|
if (newPermission.effect !== this.effect) {
|
|
15
21
|
throw new Error(`Permission effect ${newPermission.effect} does not match PermissionSet effect ${this.effect}`);
|
|
@@ -65,18 +71,50 @@ export class PermissionSet {
|
|
|
65
71
|
}
|
|
66
72
|
this.permissions[service][action] = newPermissions;
|
|
67
73
|
}
|
|
74
|
+
/**
|
|
75
|
+
* Get the permissions for a specific service and action.
|
|
76
|
+
*
|
|
77
|
+
* @param service the service to get permissions for
|
|
78
|
+
* @param action the action to get permissions for
|
|
79
|
+
* @returns the permissions that match the service and action
|
|
80
|
+
*/
|
|
68
81
|
getPermissions(service, action) {
|
|
69
82
|
if (!this.permissions[service] || !this.permissions[service][action]) {
|
|
70
83
|
return [];
|
|
71
84
|
}
|
|
72
85
|
return this.permissions[service][action];
|
|
73
86
|
}
|
|
87
|
+
/**
|
|
88
|
+
* Check if the permission set has any permissions for a specific service
|
|
89
|
+
*
|
|
90
|
+
* @param service the service to check permissions for
|
|
91
|
+
* @returns true if the permission set has permissions for the service, false otherwise
|
|
92
|
+
*/
|
|
74
93
|
hasService(service) {
|
|
75
94
|
return !!this.permissions[service];
|
|
76
95
|
}
|
|
96
|
+
/**
|
|
97
|
+
* Check if the permission set has any permissions for a specific action
|
|
98
|
+
*
|
|
99
|
+
* @param service the service the action belongs to
|
|
100
|
+
* @param action the action to check permissions for
|
|
101
|
+
* @returns true if the permission set has permissions for the action, false otherwise
|
|
102
|
+
*/
|
|
77
103
|
hasAction(service, action) {
|
|
78
104
|
return !!(this.permissions[service] && this.permissions[service][action]);
|
|
79
105
|
}
|
|
106
|
+
/**
|
|
107
|
+
* Check if the permission set is empty (has no permissions)
|
|
108
|
+
* @returns true if the permission set is empty, false otherwise
|
|
109
|
+
*/
|
|
110
|
+
isEmpty() {
|
|
111
|
+
return Object.keys(this.permissions).length === 0;
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Get all the permissions in the permission set
|
|
115
|
+
*
|
|
116
|
+
* @returns a copy of all the permissions in the permission set
|
|
117
|
+
*/
|
|
80
118
|
getAllPermissions() {
|
|
81
119
|
const allPermissions = [];
|
|
82
120
|
for (const service in this.permissions) {
|
|
@@ -90,6 +128,10 @@ export class PermissionSet {
|
|
|
90
128
|
* Return a new PermissionSet containing the intersection of this set and another.
|
|
91
129
|
* Only permissions that overlap (same effect, service, action, and intersecting resources/conditions)
|
|
92
130
|
* will be included.
|
|
131
|
+
*
|
|
132
|
+
* @param other The other PermissionSet to intersect with.
|
|
133
|
+
* @returns A new PermissionSet containing the intersecting permissions.
|
|
134
|
+
* @throws Error if the effects of the two PermissionSets do not match.
|
|
93
135
|
*/
|
|
94
136
|
intersection(other) {
|
|
95
137
|
if (this.effect !== other.effect) {
|
|
@@ -116,6 +158,15 @@ export class PermissionSet {
|
|
|
116
158
|
}
|
|
117
159
|
return result;
|
|
118
160
|
}
|
|
161
|
+
/**
|
|
162
|
+
* Subtract a Deny PermissionSet from this Allow PermissionSet.
|
|
163
|
+
*
|
|
164
|
+
* Returns two PermissionSets: one with the remaining Allow permissions,
|
|
165
|
+
* and one with any Deny permissions that were created as a result of the subtraction.
|
|
166
|
+
*
|
|
167
|
+
* @param deny the Deny PermissionSet to subtract
|
|
168
|
+
* @returns an object containing the resulting Allow and Deny PermissionSets
|
|
169
|
+
*/
|
|
119
170
|
subtract(deny) {
|
|
120
171
|
if (this.effect !== 'Allow' || deny.effect !== 'Deny') {
|
|
121
172
|
throw new Error('Can only subtract a Deny PermissionSet from an Allow PermissionSet');
|
|
@@ -161,6 +212,27 @@ export class PermissionSet {
|
|
|
161
212
|
}
|
|
162
213
|
return { allow: allowSet, deny: denySet };
|
|
163
214
|
}
|
|
215
|
+
/**
|
|
216
|
+
* Add all permissions from another PermissionSet to this one.
|
|
217
|
+
*
|
|
218
|
+
* @param others the other PermissionSet (or array of PermissionSets) to add permissions from
|
|
219
|
+
* @throws Error if the effects of the two PermissionSets do not match
|
|
220
|
+
*/
|
|
221
|
+
addAll(others) {
|
|
222
|
+
if (!Array.isArray(others)) {
|
|
223
|
+
others = [others];
|
|
224
|
+
}
|
|
225
|
+
for (const other of others) {
|
|
226
|
+
if (other.effect !== this.effect) {
|
|
227
|
+
throw new Error('Cannot add PermissionSets with different effects');
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
for (const other of others) {
|
|
231
|
+
for (const perm of other.getAllPermissions()) {
|
|
232
|
+
this.addPermission(perm);
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
}
|
|
164
236
|
/**
|
|
165
237
|
* Deep clones the PermissionSet.
|
|
166
238
|
*
|
|
@@ -212,37 +284,54 @@ export async function addPoliciesToPermissionSet(permissionSet, effect, policies
|
|
|
212
284
|
if (effect === 'Allow' && !stmt.isAllow()) {
|
|
213
285
|
continue; // skip Deny or any other non-Allow effect
|
|
214
286
|
}
|
|
215
|
-
else if (effect === 'Deny' && stmt.
|
|
287
|
+
else if (effect === 'Deny' && !stmt.isDeny()) {
|
|
216
288
|
continue; // skip Allow statements if we're building a Deny set
|
|
217
289
|
}
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
290
|
+
await addStatementToPermissionSet(stmt, permissionSet);
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
/**
|
|
295
|
+
* Add a single Statement to a PermissionSet, expanding it into one or more Permissions as needed.
|
|
296
|
+
*
|
|
297
|
+
* @param statement the IAM policy statement to add
|
|
298
|
+
* @param permissionSet the PermissionSet to add the statement to
|
|
299
|
+
* @returns nothing; the PermissionSet is modified in place
|
|
300
|
+
*/
|
|
301
|
+
export async function addStatementToPermissionSet(statement, permissionSet) {
|
|
302
|
+
const effect = statement.effect();
|
|
303
|
+
let statementActions;
|
|
304
|
+
if (statement.isActionStatement()) {
|
|
305
|
+
const allActions = statement.actions().map((a) => a.value());
|
|
306
|
+
statementActions = await expandIamActions(allActions, { expandAsterisk: true });
|
|
307
|
+
}
|
|
308
|
+
else if (statement.isNotActionStatement()) {
|
|
309
|
+
statementActions = await invertIamActions(statement.notActions().map((a) => a.value()));
|
|
310
|
+
}
|
|
311
|
+
else {
|
|
312
|
+
return;
|
|
313
|
+
}
|
|
314
|
+
for (const fullAction of statementActions) {
|
|
315
|
+
const [service, actionName] = fullAction.split(':');
|
|
316
|
+
if (!service || !actionName)
|
|
317
|
+
continue;
|
|
318
|
+
let resource = undefined;
|
|
319
|
+
let notResource = undefined;
|
|
320
|
+
if (statement.isResourceStatement()) {
|
|
321
|
+
resource = statement.resources().map((r) => r.value());
|
|
243
322
|
}
|
|
323
|
+
else if (statement.isNotResourceStatement()) {
|
|
324
|
+
notResource = statement.notResources().map((r) => r.value());
|
|
325
|
+
}
|
|
326
|
+
permissionSet.addPermission(new Permission(effect, service, actionName, resource, notResource, statement.conditionMap()));
|
|
244
327
|
}
|
|
245
328
|
}
|
|
329
|
+
/**
|
|
330
|
+
* Create a consistent key for any permission
|
|
331
|
+
*
|
|
332
|
+
* @param p the permission to create a key for
|
|
333
|
+
* @returns a string key that uniquely identifies the permission's resources and conditions
|
|
334
|
+
*/
|
|
246
335
|
function canonicalKey(p) {
|
|
247
336
|
// Sort resource arrays so ["B","A"] == ["A","B"]
|
|
248
337
|
const resources = p.resource?.slice().sort() ?? null;
|
|
@@ -262,6 +351,12 @@ function canonicalKey(p) {
|
|
|
262
351
|
// Effect is fixed for the whole PermissionSet, so not needed in the key.
|
|
263
352
|
return JSON.stringify({ resources, notResource, canonicalCond });
|
|
264
353
|
}
|
|
354
|
+
/**
|
|
355
|
+
* Convert a PermissionSet into an array of IAM policy statements.
|
|
356
|
+
*
|
|
357
|
+
* @param set the PermissionSet to convert
|
|
358
|
+
* @returns an array of IAM policy statements
|
|
359
|
+
*/
|
|
265
360
|
export function toPolicyStatements(set) {
|
|
266
361
|
const buckets = new Map();
|
|
267
362
|
for (const perm of set.getAllPermissions()) {
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"permissionSet.js","sourceRoot":"","sources":["../../../src/principalCan/permissionSet.ts"],"names":[],"mappings":"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"}
|
|
@@ -2,7 +2,7 @@ import { IamCollectClient } from '../collect/client.js';
|
|
|
2
2
|
/**
|
|
3
3
|
* Input for the can-what command.
|
|
4
4
|
*/
|
|
5
|
-
export interface
|
|
5
|
+
export interface PrincipalCanInput {
|
|
6
6
|
/**
|
|
7
7
|
* The ARN of the principal to check permissions for.
|
|
8
8
|
*/
|
|
@@ -19,8 +19,8 @@ export interface CanWhatInput {
|
|
|
19
19
|
* @param input the input containing the principal and options.
|
|
20
20
|
* @returns A promise that resolves to the permissions the principal can perform, or void if the implementation is incomplete.
|
|
21
21
|
*/
|
|
22
|
-
export declare function
|
|
22
|
+
export declare function principalCan(collectClient: IamCollectClient, input: PrincipalCanInput): Promise<{
|
|
23
23
|
Version: string;
|
|
24
24
|
Statement: any[];
|
|
25
25
|
}>;
|
|
26
|
-
//# sourceMappingURL=
|
|
26
|
+
//# sourceMappingURL=principalCan.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"principalCan.d.ts","sourceRoot":"","sources":["../../../src/principalCan/principalCan.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAA;AAUvD;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC;;OAEG;IACH,SAAS,EAAE,MAAM,CAAA;IAEjB;;OAEG;IACH,iBAAiB,EAAE,OAAO,CAAA;CAC3B;AAED;;;;;;GAMG;AACH,wBAAsB,YAAY,CAAC,aAAa,EAAE,gBAAgB,EAAE,KAAK,EAAE,iBAAiB;;;GAwF3F"}
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import { loadPolicy } from '@cloud-copilot/iam-policy';
|
|
2
2
|
import { shrinkJsonDocument } from '@cloud-copilot/iam-shrink';
|
|
3
|
+
import { splitArnParts } from '@cloud-copilot/iam-utils';
|
|
3
4
|
import { getAllPoliciesForPrincipal } from '../principals.js';
|
|
4
|
-
import { addPoliciesToPermissionSet, buildPermissionSetFromPolicies, toPolicyStatements } from './permissionSet.js';
|
|
5
|
+
import { addPoliciesToPermissionSet, buildPermissionSetFromPolicies, PermissionSet, toPolicyStatements } from './permissionSet.js';
|
|
6
|
+
import { s3BucketsSameAccount } from './resources/resourceTypes/s3Buckets.js';
|
|
5
7
|
/**
|
|
6
8
|
* Get what actions a principal can perform based on their policies.
|
|
7
9
|
*
|
|
@@ -9,11 +11,13 @@ import { addPoliciesToPermissionSet, buildPermissionSetFromPolicies, toPolicySta
|
|
|
9
11
|
* @param input the input containing the principal and options.
|
|
10
12
|
* @returns A promise that resolves to the permissions the principal can perform, or void if the implementation is incomplete.
|
|
11
13
|
*/
|
|
12
|
-
export async function
|
|
14
|
+
export async function principalCan(collectClient, input) {
|
|
13
15
|
const { principal } = input;
|
|
14
16
|
if (!principal) {
|
|
15
17
|
throw new Error('Principal must be provided for can-what command');
|
|
16
18
|
}
|
|
19
|
+
const principalArnParts = splitArnParts(principal);
|
|
20
|
+
const principalAccountId = principalArnParts.accountId;
|
|
17
21
|
const principalPolicies = await getAllPoliciesForPrincipal(collectClient, principal);
|
|
18
22
|
const identityPolicies = [
|
|
19
23
|
...principalPolicies.managedPolicies,
|
|
@@ -24,6 +28,13 @@ export async function canWhat(collectClient, input) {
|
|
|
24
28
|
const allowedPermissions = await buildPermissionSetFromPolicies('Allow', identityPolicies);
|
|
25
29
|
const identityDenyPermissions = await buildPermissionSetFromPolicies('Deny', identityPolicies);
|
|
26
30
|
let finalPermissions = allowedPermissions;
|
|
31
|
+
/*********** Start Buckets *************/
|
|
32
|
+
const resourceDenyPermissions = new PermissionSet('Deny');
|
|
33
|
+
const { allows: bucketAllows, denies: bucketDenies } = await s3BucketsSameAccount(collectClient, principal);
|
|
34
|
+
finalPermissions.addAll(bucketAllows);
|
|
35
|
+
resourceDenyPermissions.addAll(bucketDenies);
|
|
36
|
+
/*********** End Buckets *************/
|
|
37
|
+
// TODO: There is a slight wrinkle where same account resource policies can override implicit denies from Permission Boundaries.
|
|
27
38
|
if (principalPolicies.permissionBoundary) {
|
|
28
39
|
const boundaryPolicy = loadPolicy(principalPolicies.permissionBoundary.policy);
|
|
29
40
|
const boundaryPermissions = await buildPermissionSetFromPolicies('Allow', [boundaryPolicy]);
|
|
@@ -48,6 +59,8 @@ export async function canWhat(collectClient, input) {
|
|
|
48
59
|
for (const rcpAllow of rcpAllowsByLevel) {
|
|
49
60
|
finalPermissions = finalPermissions.intersection(rcpAllow);
|
|
50
61
|
}
|
|
62
|
+
//Put together all the denies
|
|
63
|
+
principalAccountDenyPermissions.addAll(resourceDenyPermissions);
|
|
51
64
|
const permissionsAfterDeny = finalPermissions.subtract(principalAccountDenyPermissions);
|
|
52
65
|
finalPermissions = permissionsAfterDeny.allow;
|
|
53
66
|
const deniedPermissions = permissionsAfterDeny.deny;
|
|
@@ -62,4 +75,4 @@ export async function canWhat(collectClient, input) {
|
|
|
62
75
|
}
|
|
63
76
|
return policyDocument;
|
|
64
77
|
}
|
|
65
|
-
//# sourceMappingURL=
|
|
78
|
+
//# sourceMappingURL=principalCan.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"principalCan.js","sourceRoot":"","sources":["../../../src/principalCan/principalCan.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Get the actions for a resource type in a service.
|
|
3
|
+
*
|
|
4
|
+
* @param service the service to get actions for
|
|
5
|
+
* @param resourceType the resource type to get the actions for
|
|
6
|
+
* @returns the actions that can be performed on the resource type
|
|
7
|
+
*/
|
|
8
|
+
export declare function actionsForResourceType(service: string, resourceType: string): Promise<string[]>;
|
|
9
|
+
//# sourceMappingURL=actions.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"actions.d.ts","sourceRoot":"","sources":["../../../../src/principalCan/resources/actions.ts"],"names":[],"mappings":"AAMA;;;;;;GAMG;AACH,wBAAsB,sBAAsB,CAAC,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,qBAgBjF"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { iamActionDetails, iamActionsForService, iamResourceTypeExists } from '@cloud-copilot/iam-data';
|
|
2
|
+
/**
|
|
3
|
+
* Get the actions for a resource type in a service.
|
|
4
|
+
*
|
|
5
|
+
* @param service the service to get actions for
|
|
6
|
+
* @param resourceType the resource type to get the actions for
|
|
7
|
+
* @returns the actions that can be performed on the resource type
|
|
8
|
+
*/
|
|
9
|
+
export async function actionsForResourceType(service, resourceType) {
|
|
10
|
+
const resourceTypeExists = await iamResourceTypeExists(service, resourceType);
|
|
11
|
+
if (!resourceTypeExists) {
|
|
12
|
+
throw new Error(`Resource type ${resourceType} does not exist in service ${service}`);
|
|
13
|
+
}
|
|
14
|
+
const actions = await iamActionsForService(service);
|
|
15
|
+
const matchingAction = [];
|
|
16
|
+
for (const action of actions) {
|
|
17
|
+
const actionDetails = await iamActionDetails(service, action);
|
|
18
|
+
if (actionDetails?.resourceTypes?.some((rt) => rt.name === resourceType)) {
|
|
19
|
+
matchingAction.push(action);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
return matchingAction;
|
|
23
|
+
}
|
|
24
|
+
//# sourceMappingURL=actions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"actions.js","sourceRoot":"","sources":["../../../../src/principalCan/resources/actions.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,gBAAgB,EAChB,oBAAoB,EACpB,qBAAqB,EACtB,MAAM,yBAAyB,CAAA;AAEhC;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,sBAAsB,CAAC,OAAe,EAAE,YAAoB;IAChF,MAAM,kBAAkB,GAAG,MAAM,qBAAqB,CAAC,OAAO,EAAE,YAAY,CAAC,CAAA;IAC7E,IAAI,CAAC,kBAAkB,EAAE,CAAC;QACxB,MAAM,IAAI,KAAK,CAAC,iBAAiB,YAAY,8BAA8B,OAAO,EAAE,CAAC,CAAA;IACvF,CAAC;IACD,MAAM,OAAO,GAAG,MAAM,oBAAoB,CAAC,OAAO,CAAC,CAAA;IAEnD,MAAM,cAAc,GAAa,EAAE,CAAA;IACnC,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;QAC7B,MAAM,aAAa,GAAG,MAAM,gBAAgB,CAAC,OAAO,EAAE,MAAM,CAAC,CAAA;QAC7D,IAAI,aAAa,EAAE,aAAa,EAAE,IAAI,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,IAAI,KAAK,YAAY,CAAC,EAAE,CAAC;YACzE,cAAc,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;QAC7B,CAAC;IACH,CAAC;IAED,OAAO,cAAc,CAAA;AACvB,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { IamCollectClient } from '../../../collect/client.js';
|
|
2
|
+
import { PermissionSet } from '../../permissionSet.js';
|
|
3
|
+
/**
|
|
4
|
+
* Get the permission sets for S3 buckets in the same account as the principal.
|
|
5
|
+
*
|
|
6
|
+
* @param collectClient the IAM collect client to use for retrieving policies and resources
|
|
7
|
+
* @param principal the ARN of the principal to check
|
|
8
|
+
* @returns the Allow and Deny permission sets for S3 buckets in the same account as the principal
|
|
9
|
+
*/
|
|
10
|
+
export declare function s3BucketsSameAccount(collectClient: IamCollectClient, principal: string): Promise<{
|
|
11
|
+
allows: PermissionSet[];
|
|
12
|
+
denies: PermissionSet[];
|
|
13
|
+
}>;
|
|
14
|
+
//# sourceMappingURL=s3Buckets.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"s3Buckets.d.ts","sourceRoot":"","sources":["../../../../../src/principalCan/resources/resourceTypes/s3Buckets.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,gBAAgB,EAAE,MAAM,4BAA4B,CAAA;AAE7D,OAAO,EAA+B,aAAa,EAAE,MAAM,wBAAwB,CAAA;AAInF;;;;;;GAMG;AACH,wBAAsB,oBAAoB,CACxC,aAAa,EAAE,gBAAgB,EAC/B,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC;IAAE,MAAM,EAAE,aAAa,EAAE,CAAC;IAAC,MAAM,EAAE,aAAa,EAAE,CAAA;CAAE,CAAC,CA+D/D"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { loadPolicy } from '@cloud-copilot/iam-policy';
|
|
2
|
+
import { splitArnParts } from '@cloud-copilot/iam-utils';
|
|
3
|
+
import { Permission } from '../../permission.js';
|
|
4
|
+
import { addStatementToPermissionSet, PermissionSet } from '../../permissionSet.js';
|
|
5
|
+
import { actionsForResourceType } from '../actions.js';
|
|
6
|
+
import { statementAppliesToPrincipal } from '../statements.js';
|
|
7
|
+
/**
|
|
8
|
+
* Get the permission sets for S3 buckets in the same account as the principal.
|
|
9
|
+
*
|
|
10
|
+
* @param collectClient the IAM collect client to use for retrieving policies and resources
|
|
11
|
+
* @param principal the ARN of the principal to check
|
|
12
|
+
* @returns the Allow and Deny permission sets for S3 buckets in the same account as the principal
|
|
13
|
+
*/
|
|
14
|
+
export async function s3BucketsSameAccount(collectClient, principal) {
|
|
15
|
+
const principalArnParts = splitArnParts(principal);
|
|
16
|
+
const principalAccountId = principalArnParts.accountId;
|
|
17
|
+
const allBuckets = await collectClient.listResources(principalAccountId, 's3', 'bucket', undefined);
|
|
18
|
+
const bucketActions = await actionsForResourceType('s3', 'bucket');
|
|
19
|
+
const objectActions = await actionsForResourceType('s3', 'object');
|
|
20
|
+
const s3Actions = [...bucketActions, ...objectActions];
|
|
21
|
+
const bucketAllowPermissionSets = [];
|
|
22
|
+
const bucketDenyPermissionSets = [];
|
|
23
|
+
for (const bucket of allBuckets) {
|
|
24
|
+
const bucketPolicy = await collectClient.getResourcePolicyForArn(bucket, principalAccountId);
|
|
25
|
+
if (bucketPolicy) {
|
|
26
|
+
const loadedPolicy = loadPolicy(bucketPolicy);
|
|
27
|
+
if (loadedPolicy) {
|
|
28
|
+
const bucketArns = [bucket, `${bucket}/*`];
|
|
29
|
+
const bucketAllowPerimeter = new PermissionSet('Allow');
|
|
30
|
+
const bucketDenyPerimeter = new PermissionSet('Deny');
|
|
31
|
+
for (const action of s3Actions) {
|
|
32
|
+
bucketAllowPerimeter.addPermission(new Permission('Allow', 's3', action, bucketArns, undefined, undefined));
|
|
33
|
+
bucketDenyPerimeter.addPermission(new Permission('Deny', 's3', action, bucketArns, undefined, undefined));
|
|
34
|
+
}
|
|
35
|
+
const allowPermissionSet = new PermissionSet('Allow');
|
|
36
|
+
const denyPermissionSet = new PermissionSet('Deny');
|
|
37
|
+
for (const statement of loadedPolicy.statements()) {
|
|
38
|
+
const applies = await statementAppliesToPrincipal(statement, principal, collectClient);
|
|
39
|
+
if (applies === 'PrincipalMatch') {
|
|
40
|
+
if (statement.isAllow()) {
|
|
41
|
+
await addStatementToPermissionSet(statement, allowPermissionSet);
|
|
42
|
+
}
|
|
43
|
+
else {
|
|
44
|
+
await addStatementToPermissionSet(statement, denyPermissionSet);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
const effectiveAllows = allowPermissionSet.intersection(bucketAllowPerimeter);
|
|
49
|
+
const effectiveDenies = denyPermissionSet.intersection(bucketDenyPerimeter);
|
|
50
|
+
if (!effectiveAllows.isEmpty()) {
|
|
51
|
+
bucketAllowPermissionSets.push(effectiveAllows);
|
|
52
|
+
}
|
|
53
|
+
if (!effectiveDenies.isEmpty()) {
|
|
54
|
+
bucketDenyPermissionSets.push(effectiveDenies);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
return { allows: bucketAllowPermissionSets, denies: bucketDenyPermissionSets };
|
|
60
|
+
}
|
|
61
|
+
//# sourceMappingURL=s3Buckets.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"s3Buckets.js","sourceRoot":"","sources":["../../../../../src/principalCan/resources/resourceTypes/s3Buckets.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { Policy, Statement } from '@cloud-copilot/iam-policy';
|
|
2
|
+
import { IamCollectClient } from '../../collect/client.js';
|
|
3
|
+
export type StatementPrincipalMatchType = 'PrincipalMatch' | 'AccountMatch' | 'NoMatch';
|
|
4
|
+
/**
|
|
5
|
+
* Checks to see if a statement applies to a principal by running a simulation.
|
|
6
|
+
*
|
|
7
|
+
* If the principal is a match return 'PrincipalMatch'
|
|
8
|
+
* If the account is a match return 'AccountMatch'
|
|
9
|
+
* Otherwise return 'NoMatch'
|
|
10
|
+
*
|
|
11
|
+
* @param statement the statement to check
|
|
12
|
+
* @param principalArn the arn of the principal to check
|
|
13
|
+
* @param client the IAM collect client to use for retrieving principal information
|
|
14
|
+
* @returns Whether the statement applies to the principal
|
|
15
|
+
*/
|
|
16
|
+
export declare function statementAppliesToPrincipal(statement: Statement, principalArn: string, client: IamCollectClient): Promise<StatementPrincipalMatchType>;
|
|
17
|
+
/**
|
|
18
|
+
* Makes a policy that captures the principal and principal conditions from a statement
|
|
19
|
+
* and allows all actions on all resources.
|
|
20
|
+
*
|
|
21
|
+
* The conditions returned are only those that relate to the principal.
|
|
22
|
+
*
|
|
23
|
+
* @param statement the statement to extract the principal from
|
|
24
|
+
* @returns
|
|
25
|
+
*/
|
|
26
|
+
export declare function makePrincipalOnlyPolicyFromStatement(statement: Statement): Policy;
|
|
27
|
+
//# sourceMappingURL=statements.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"statements.d.ts","sourceRoot":"","sources":["../../../../src/principalCan/resources/statements.ts"],"names":[],"mappings":"AAAA,OAAO,EAAc,MAAM,EAAE,SAAS,EAAE,MAAM,2BAA2B,CAAA;AAGzE,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAA;AAI1D,MAAM,MAAM,2BAA2B,GAAG,gBAAgB,GAAG,cAAc,GAAG,SAAS,CAAA;AAEvF;;;;;;;;;;;GAWG;AACH,wBAAsB,2BAA2B,CAC/C,SAAS,EAAE,SAAS,EACpB,YAAY,EAAE,MAAM,EACpB,MAAM,EAAE,gBAAgB,GACvB,OAAO,CAAC,2BAA2B,CAAC,CA2CtC;AAeD;;;;;;;;GAQG;AACH,wBAAgB,oCAAoC,CAAC,SAAS,EAAE,SAAS,GAAG,MAAM,CAiCjF"}
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import { loadPolicy } from '@cloud-copilot/iam-policy';
|
|
2
|
+
import { runSimulation } from '@cloud-copilot/iam-simulate';
|
|
3
|
+
import { splitArnParts } from '@cloud-copilot/iam-utils';
|
|
4
|
+
import { createContextKeys } from '../../simulate/contextKeys.js';
|
|
5
|
+
/**
|
|
6
|
+
* Checks to see if a statement applies to a principal by running a simulation.
|
|
7
|
+
*
|
|
8
|
+
* If the principal is a match return 'PrincipalMatch'
|
|
9
|
+
* If the account is a match return 'AccountMatch'
|
|
10
|
+
* Otherwise return 'NoMatch'
|
|
11
|
+
*
|
|
12
|
+
* @param statement the statement to check
|
|
13
|
+
* @param principalArn the arn of the principal to check
|
|
14
|
+
* @param client the IAM collect client to use for retrieving principal information
|
|
15
|
+
* @returns Whether the statement applies to the principal
|
|
16
|
+
*/
|
|
17
|
+
export async function statementAppliesToPrincipal(statement, principalArn, client) {
|
|
18
|
+
const principalAccount = splitArnParts(principalArn).accountId;
|
|
19
|
+
const resourcePolicy = makePrincipalOnlyPolicyFromStatement(statement);
|
|
20
|
+
const simulationRequest = {
|
|
21
|
+
principal: principalArn,
|
|
22
|
+
action: 's3:ListBucket',
|
|
23
|
+
resourceAccount: principalAccount,
|
|
24
|
+
resourceArn: undefined,
|
|
25
|
+
customContextKeys: {},
|
|
26
|
+
simulationMode: 'Strict'
|
|
27
|
+
};
|
|
28
|
+
const contextKeys = await createContextKeys(client, simulationRequest, 's3', {});
|
|
29
|
+
const request = {
|
|
30
|
+
action: 's3:ListBucket',
|
|
31
|
+
resource: {
|
|
32
|
+
resource: 'arn:aws:s3:::example-bucket',
|
|
33
|
+
accountId: principalAccount
|
|
34
|
+
},
|
|
35
|
+
principal: principalArn,
|
|
36
|
+
contextVariables: contextKeys
|
|
37
|
+
};
|
|
38
|
+
const simulation = {
|
|
39
|
+
request,
|
|
40
|
+
identityPolicies: [],
|
|
41
|
+
resourcePolicy: resourcePolicy.toJSON(),
|
|
42
|
+
serviceControlPolicies: [],
|
|
43
|
+
resourceControlPolicies: []
|
|
44
|
+
};
|
|
45
|
+
const result = await runSimulation(simulation, {
|
|
46
|
+
simulationMode: simulationRequest.simulationMode
|
|
47
|
+
});
|
|
48
|
+
if (result.analysis?.result === 'Allowed') {
|
|
49
|
+
return 'PrincipalMatch';
|
|
50
|
+
}
|
|
51
|
+
if (result.analysis?.resourceAnalysis?.result === 'AllowedForAccount') {
|
|
52
|
+
return 'AccountMatch';
|
|
53
|
+
}
|
|
54
|
+
return 'NoMatch';
|
|
55
|
+
}
|
|
56
|
+
const principalKeys = new Set([
|
|
57
|
+
'aws:PrincipalArn',
|
|
58
|
+
'aws:PrincipalAccount',
|
|
59
|
+
'aws:PrincipalOrgId',
|
|
60
|
+
'aws:PrincipalOrgPaths',
|
|
61
|
+
'aws:PrincipalType',
|
|
62
|
+
'aws:userid',
|
|
63
|
+
'aws:username',
|
|
64
|
+
'aws:PrincipalIsAWSService'
|
|
65
|
+
].map((k) => k.toLowerCase()));
|
|
66
|
+
/**
|
|
67
|
+
* Makes a policy that captures the principal and principal conditions from a statement
|
|
68
|
+
* and allows all actions on all resources.
|
|
69
|
+
*
|
|
70
|
+
* The conditions returned are only those that relate to the principal.
|
|
71
|
+
*
|
|
72
|
+
* @param statement the statement to extract the principal from
|
|
73
|
+
* @returns
|
|
74
|
+
*/
|
|
75
|
+
export function makePrincipalOnlyPolicyFromStatement(statement) {
|
|
76
|
+
const rawStatement = structuredClone(statement.toJSON());
|
|
77
|
+
const rawStatementValues = {};
|
|
78
|
+
if (statement.isPrincipalStatement()) {
|
|
79
|
+
rawStatementValues.Principal = rawStatement.Principal;
|
|
80
|
+
}
|
|
81
|
+
else if (statement.isNotPrincipalStatement()) {
|
|
82
|
+
rawStatementValues.NotPrincipal = rawStatement.NotPrincipal;
|
|
83
|
+
}
|
|
84
|
+
if (rawStatement.Condition) {
|
|
85
|
+
for (const operator of Object.keys(rawStatement.Condition)) {
|
|
86
|
+
for (const key of Object.keys(rawStatement.Condition[operator])) {
|
|
87
|
+
if (!principalKeys.has(key.toLowerCase())) {
|
|
88
|
+
delete rawStatement.Condition[operator][key];
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
if (Object.keys(rawStatement.Condition[operator]).length === 0) {
|
|
92
|
+
delete rawStatement.Condition[operator];
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
if (Object.keys(rawStatement.Condition).length > 0) {
|
|
96
|
+
rawStatementValues.Condition = rawStatement.Condition;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
return loadPolicy({
|
|
100
|
+
Version: '2012-10-17',
|
|
101
|
+
Statement: {
|
|
102
|
+
Effect: 'Allow',
|
|
103
|
+
Resource: '*',
|
|
104
|
+
Action: '*',
|
|
105
|
+
...rawStatementValues
|
|
106
|
+
}
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
//# sourceMappingURL=statements.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"statements.js","sourceRoot":"","sources":["../../../../src/principalCan/resources/statements.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"canWhat.d.ts","sourceRoot":"","sources":["../../../src/canWhat/canWhat.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAA;AASvD;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B;;OAEG;IACH,SAAS,EAAE,MAAM,CAAA;IAEjB;;OAEG;IACH,iBAAiB,EAAE,OAAO,CAAA;CAC3B;AAED;;;;;;GAMG;AACH,wBAAsB,OAAO,CAAC,aAAa,EAAE,gBAAgB,EAAE,KAAK,EAAE,YAAY;;;GAoEjF"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"canWhat.js","sourceRoot":"","sources":["../../../src/canWhat/canWhat.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"permission.d.ts","sourceRoot":"","sources":["../../../src/canWhat/permission.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,gBAAgB,GAAG,OAAO,GAAG,MAAM,CAAA;AAE/C,MAAM,MAAM,oBAAoB,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC,CAAA;AAU3E;;;;;;GAMG;AACH,qBAAa,UAAU;aAEH,MAAM,EAAE,gBAAgB;aACxB,OAAO,EAAE,MAAM;aACf,MAAM,EAAE,MAAM;aACd,QAAQ,EAAE,MAAM,EAAE,GAAG,SAAS;aAC9B,WAAW,EAAE,MAAM,EAAE,GAAG,SAAS;aACjC,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC,GAAG,SAAS;gBALhE,MAAM,EAAE,gBAAgB,EACxB,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,EAAE,GAAG,SAAS,EAC9B,WAAW,EAAE,MAAM,EAAE,GAAG,SAAS,EACjC,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC,GAAG,SAAS;IASlF;;;OAGG;IACI,QAAQ,CAAC,KAAK,EAAE,UAAU,GAAG,OAAO;IAyH3C;;;;;OAKG;IACI,KAAK,CAAC,KAAK,EAAE,UAAU,GAAG,UAAU,EAAE;IAiE7C;;;;OAIG;IACI,YAAY,CAAC,KAAK,EAAE,UAAU,GAAG,UAAU,GAAG,SAAS;IAkL9D;;;OAGG;IACI,QAAQ,CAAC,KAAK,EAAE,UAAU,GAAG,UAAU,EAAE;CA6HjD;AAmKD;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,oBAAoB,GAAG,oBAAoB,CAWxF;AA+BD;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAC9B,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC,GAC9C,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC,CAqB1C"}
|