@cloud-copilot/iam-simulate 0.1.102 → 0.1.104
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 +22 -7
- package/dist/cjs/index.d.ts +1 -1
- package/dist/cjs/index.d.ts.map +1 -1
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/request/requestResource.d.ts +12 -0
- package/dist/cjs/request/requestResource.d.ts.map +1 -1
- package/dist/cjs/request/requestResource.js +6 -0
- package/dist/cjs/request/requestResource.js.map +1 -1
- package/dist/cjs/resource/resource.d.ts +11 -2
- package/dist/cjs/resource/resource.d.ts.map +1 -1
- package/dist/cjs/resource/resource.js +170 -8
- package/dist/cjs/resource/resource.js.map +1 -1
- package/dist/cjs/simulation_engine/contextKeys.d.ts +2 -1
- package/dist/cjs/simulation_engine/contextKeys.d.ts.map +1 -1
- package/dist/cjs/simulation_engine/contextKeys.js +13 -8
- package/dist/cjs/simulation_engine/contextKeys.js.map +1 -1
- package/dist/cjs/simulation_engine/overallResult.d.ts +13 -0
- package/dist/cjs/simulation_engine/overallResult.d.ts.map +1 -0
- package/dist/cjs/simulation_engine/overallResult.js +35 -0
- package/dist/cjs/simulation_engine/overallResult.js.map +1 -0
- package/dist/cjs/simulation_engine/policyResources.d.ts +41 -0
- package/dist/cjs/simulation_engine/policyResources.d.ts.map +1 -0
- package/dist/cjs/simulation_engine/policyResources.js +112 -0
- package/dist/cjs/simulation_engine/policyResources.js.map +1 -0
- package/dist/cjs/simulation_engine/resourceTypes.d.ts +18 -0
- package/dist/cjs/simulation_engine/resourceTypes.d.ts.map +1 -0
- package/dist/cjs/simulation_engine/resourceTypes.js +145 -0
- package/dist/cjs/simulation_engine/resourceTypes.js.map +1 -0
- package/dist/cjs/simulation_engine/simulationEngine.d.ts +92 -14
- package/dist/cjs/simulation_engine/simulationEngine.d.ts.map +1 -1
- package/dist/cjs/simulation_engine/simulationEngine.js +74 -16
- package/dist/cjs/simulation_engine/simulationEngine.js.map +1 -1
- package/dist/cjs/util/resourceStrings.d.ts +10 -0
- package/dist/cjs/util/resourceStrings.d.ts.map +1 -0
- package/dist/cjs/util/resourceStrings.js +81 -0
- package/dist/cjs/util/resourceStrings.js.map +1 -0
- package/dist/cjs/util.d.ts +0 -10
- package/dist/cjs/util.d.ts.map +1 -1
- package/dist/cjs/util.js +0 -25
- package/dist/cjs/util.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.map +1 -1
- package/dist/esm/request/requestResource.d.ts +12 -0
- package/dist/esm/request/requestResource.d.ts.map +1 -1
- package/dist/esm/request/requestResource.js +6 -0
- package/dist/esm/request/requestResource.js.map +1 -1
- package/dist/esm/resource/resource.d.ts +11 -2
- package/dist/esm/resource/resource.d.ts.map +1 -1
- package/dist/esm/resource/resource.js +169 -8
- package/dist/esm/resource/resource.js.map +1 -1
- package/dist/esm/simulation_engine/contextKeys.d.ts +2 -1
- package/dist/esm/simulation_engine/contextKeys.d.ts.map +1 -1
- package/dist/esm/simulation_engine/contextKeys.js +14 -9
- package/dist/esm/simulation_engine/contextKeys.js.map +1 -1
- package/dist/esm/simulation_engine/overallResult.d.ts +13 -0
- package/dist/esm/simulation_engine/overallResult.d.ts.map +1 -0
- package/dist/esm/simulation_engine/overallResult.js +32 -0
- package/dist/esm/simulation_engine/overallResult.js.map +1 -0
- package/dist/esm/simulation_engine/policyResources.d.ts +41 -0
- package/dist/esm/simulation_engine/policyResources.d.ts.map +1 -0
- package/dist/esm/simulation_engine/policyResources.js +106 -0
- package/dist/esm/simulation_engine/policyResources.js.map +1 -0
- package/dist/esm/simulation_engine/resourceTypes.d.ts +18 -0
- package/dist/esm/simulation_engine/resourceTypes.d.ts.map +1 -0
- package/dist/esm/simulation_engine/resourceTypes.js +141 -0
- package/dist/esm/simulation_engine/resourceTypes.js.map +1 -0
- package/dist/esm/simulation_engine/simulationEngine.d.ts +92 -14
- package/dist/esm/simulation_engine/simulationEngine.d.ts.map +1 -1
- package/dist/esm/simulation_engine/simulationEngine.js +75 -17
- package/dist/esm/simulation_engine/simulationEngine.js.map +1 -1
- package/dist/esm/util/resourceStrings.d.ts +10 -0
- package/dist/esm/util/resourceStrings.d.ts.map +1 -0
- package/dist/esm/util/resourceStrings.js +78 -0
- package/dist/esm/util/resourceStrings.js.map +1 -0
- package/dist/esm/util.d.ts +0 -10
- package/dist/esm/util.d.ts.map +1 -1
- package/dist/esm/util.js +1 -25
- package/dist/esm/util.js.map +1 -1
- package/package.json +2 -2
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getMatchingResourceStringsForPolicies = getMatchingResourceStringsForPolicies;
|
|
4
|
+
exports.getResourceStringsFromStatement = getResourceStringsFromStatement;
|
|
5
|
+
exports.statementResourceStringsForResourceTypeAndPattern = statementResourceStringsForResourceTypeAndPattern;
|
|
6
|
+
exports.statementAllowsAction = statementAllowsAction;
|
|
7
|
+
const iam_utils_1 = require("@cloud-copilot/iam-utils");
|
|
8
|
+
const resourceStrings_js_1 = require("../util/resourceStrings.js");
|
|
9
|
+
const resourceTypes_js_1 = require("./resourceTypes.js");
|
|
10
|
+
/**
|
|
11
|
+
* Extracts matching resource strings from a set of policies for a given action and resource pattern.
|
|
12
|
+
*
|
|
13
|
+
* @param policies Array of policies to search through (undefined entries are skipped)
|
|
14
|
+
* @param action The action to match against policy statements
|
|
15
|
+
* @param resourceType The resource type to filter resource strings by
|
|
16
|
+
* @param resourceArnPattern The resource ARN pattern to match against
|
|
17
|
+
* @returns Array of unique resource strings that match the criteria
|
|
18
|
+
*/
|
|
19
|
+
function getMatchingResourceStringsForPolicies(policies, action, resourceType, resourceArnPattern) {
|
|
20
|
+
const resourceStrings = new Set();
|
|
21
|
+
for (const policy of policies) {
|
|
22
|
+
if (!policy) {
|
|
23
|
+
continue;
|
|
24
|
+
}
|
|
25
|
+
for (const statement of policy.statements()) {
|
|
26
|
+
const stmtResourceStrings = getResourceStringsFromStatement(statement, action, resourceType, resourceArnPattern);
|
|
27
|
+
for (const rs of stmtResourceStrings) {
|
|
28
|
+
resourceStrings.add(rs);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
return Array.from(resourceStrings);
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Extracts resource strings from a single policy statement that allows the specified action.
|
|
36
|
+
*
|
|
37
|
+
* @param statement The policy statement to analyze
|
|
38
|
+
* @param action The action to check if the statement allows
|
|
39
|
+
* @param resourceType The resource type to filter by
|
|
40
|
+
* @param resourceArnPattern The resource ARN pattern to match
|
|
41
|
+
* @returns Array of resource strings from the statement, or empty array if statement doesn't allow the action
|
|
42
|
+
*/
|
|
43
|
+
function getResourceStringsFromStatement(statement, action, resourceType, resourceArnPattern) {
|
|
44
|
+
if (statementAllowsAction(statement, action)) {
|
|
45
|
+
return statementResourceStringsForResourceTypeAndPattern(statement, resourceType, resourceArnPattern);
|
|
46
|
+
}
|
|
47
|
+
return [];
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Extracts resource strings from a statement's Resource or NotResource elements that match the given criteria.
|
|
51
|
+
*
|
|
52
|
+
* @param statement The policy statement to analyze
|
|
53
|
+
* @param resourceType The resource type to filter by
|
|
54
|
+
* @param resourceArnPattern The resource ARN pattern to check for overlap
|
|
55
|
+
* @returns Array of matching resource strings, or ['*'] for certain NotResource cases
|
|
56
|
+
*/
|
|
57
|
+
function statementResourceStringsForResourceTypeAndPattern(statement, resourceType, resourceArnPattern) {
|
|
58
|
+
if (statement.isResourceStatement() && statement.isAllow()) {
|
|
59
|
+
const resourceStrings = [];
|
|
60
|
+
for (const stmtResource of statement.resources()) {
|
|
61
|
+
if ((0, resourceTypes_js_1.resourceStringMatchesResourceTypePattern)(stmtResource.value(), resourceType.arn)) {
|
|
62
|
+
if ((0, resourceStrings_js_1.resourceArnsOverlap)(resourceArnPattern, stmtResource.value())) {
|
|
63
|
+
resourceStrings.push(stmtResource.value());
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
return resourceStrings;
|
|
68
|
+
}
|
|
69
|
+
if (statement.isNotResourceStatement() && statement.isAllow()) {
|
|
70
|
+
for (const stmtNotResource of statement.notResources()) {
|
|
71
|
+
// If any NotResource string equals or is a superset of the resource type pattern, then the statement does not apply to the string. Otherwise, it should return the string '*'
|
|
72
|
+
if (stmtNotResource.value() === resourceArnPattern ||
|
|
73
|
+
isResourceArnSuperset(stmtNotResource.value(), resourceArnPattern)) {
|
|
74
|
+
return [];
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
return ['*'];
|
|
78
|
+
}
|
|
79
|
+
// If it's a statement that has no Resource or NotResource such as a trust policy, just return the original pattern
|
|
80
|
+
return [resourceArnPattern];
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Determines if a policy statement allows the specified action.
|
|
84
|
+
*
|
|
85
|
+
* @param statement The policy statement to check
|
|
86
|
+
* @param action The action to test against the statement
|
|
87
|
+
* @returns true if the statement allows the action, false otherwise
|
|
88
|
+
*/
|
|
89
|
+
function statementAllowsAction(statement, action) {
|
|
90
|
+
if (statement.isActionStatement() && statement.isAllow()) {
|
|
91
|
+
for (const stmtAction of statement.actions()) {
|
|
92
|
+
if ((0, iam_utils_1.actionMatchesPattern)(action, stmtAction.value())) {
|
|
93
|
+
return true;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
return false;
|
|
97
|
+
}
|
|
98
|
+
else if (statement.isNotActionStatement() && statement.isAllow()) {
|
|
99
|
+
for (const stmtAction of statement.notActions()) {
|
|
100
|
+
if ((0, iam_utils_1.actionMatchesPattern)(action, stmtAction.value())) {
|
|
101
|
+
return false;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
return true;
|
|
105
|
+
}
|
|
106
|
+
return false;
|
|
107
|
+
}
|
|
108
|
+
function isResourceArnSuperset(arnSuperset, arnSubset) {
|
|
109
|
+
const regexSuperset = (0, iam_utils_1.resourceArnWithWildcardsToRegex)(arnSuperset);
|
|
110
|
+
return regexSuperset.test(arnSubset);
|
|
111
|
+
}
|
|
112
|
+
//# sourceMappingURL=policyResources.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"policyResources.js","sourceRoot":"","sources":["../../../src/simulation_engine/policyResources.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { ResourceType } from '@cloud-copilot/iam-data';
|
|
2
|
+
/**
|
|
3
|
+
* Checks to see if a resource string ARN matches a resource pattern from the Service Authorization Reference
|
|
4
|
+
*
|
|
5
|
+
* @param resourceString
|
|
6
|
+
* @param resourcePattern
|
|
7
|
+
*/
|
|
8
|
+
export declare function resourceStringMatchesResourceTypePattern(resourceString: string, resourcePattern: string): boolean;
|
|
9
|
+
/**
|
|
10
|
+
* Get the the possible resource types for an action and resource
|
|
11
|
+
*
|
|
12
|
+
* @param service the service the action belongs to
|
|
13
|
+
* @param action the action to get the resource type for
|
|
14
|
+
* @param resource the resource type matching the action, if any
|
|
15
|
+
* @throws an error if the service or action does not exist, or if the action is a wildcard only action
|
|
16
|
+
*/
|
|
17
|
+
export declare function getResourceTypesForAction(service: string, action: string, resource: string): Promise<ResourceType[]>;
|
|
18
|
+
//# sourceMappingURL=resourceTypes.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resourceTypes.d.ts","sourceRoot":"","sources":["../../../src/simulation_engine/resourceTypes.ts"],"names":[],"mappings":"AAAA,OAAO,EAA4C,YAAY,EAAE,MAAM,yBAAyB,CAAA;AAGhG;;;;;GAKG;AACH,wBAAgB,wCAAwC,CACtD,cAAc,EAAE,MAAM,EACtB,eAAe,EAAE,MAAM,GACtB,OAAO,CA2GT;AAqCD;;;;;;;GAOG;AACH,wBAAsB,yBAAyB,CAC7C,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,YAAY,EAAE,CAAC,CAkBzB"}
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.resourceStringMatchesResourceTypePattern = resourceStringMatchesResourceTypePattern;
|
|
4
|
+
exports.getResourceTypesForAction = getResourceTypesForAction;
|
|
5
|
+
const iam_data_1 = require("@cloud-copilot/iam-data");
|
|
6
|
+
const util_js_1 = require("../util.js");
|
|
7
|
+
/**
|
|
8
|
+
* Checks to see if a resource string ARN matches a resource pattern from the Service Authorization Reference
|
|
9
|
+
*
|
|
10
|
+
* @param resourceString
|
|
11
|
+
* @param resourcePattern
|
|
12
|
+
*/
|
|
13
|
+
function resourceStringMatchesResourceTypePattern(resourceString, resourcePattern) {
|
|
14
|
+
if (resourceString === '*') {
|
|
15
|
+
return true;
|
|
16
|
+
}
|
|
17
|
+
const resourceParts = (0, util_js_1.splitArnParts)(resourceString);
|
|
18
|
+
const patternParts = (0, util_js_1.splitArnParts)(resourcePattern);
|
|
19
|
+
if (!resourceComponentMatchesResourceTypeComponent(resourceParts.partition, patternParts.partition)) {
|
|
20
|
+
return false;
|
|
21
|
+
}
|
|
22
|
+
if (!resourceComponentMatchesResourceTypeComponent(resourceParts.service, patternParts.service)) {
|
|
23
|
+
return false;
|
|
24
|
+
}
|
|
25
|
+
if (!resourceComponentMatchesResourceTypeComponent(resourceParts.region, patternParts.region)) {
|
|
26
|
+
return false;
|
|
27
|
+
}
|
|
28
|
+
if (!resourceComponentMatchesResourceTypeComponent(resourceParts.accountId, patternParts.accountId)) {
|
|
29
|
+
return false;
|
|
30
|
+
}
|
|
31
|
+
const [resourceResourcePartsSegments, resourceResourceParts] = splitResourceTypeComponent(resourceParts.resource);
|
|
32
|
+
const [patternResourcePartsSegments, patternResourceParts] = splitResourceTypeComponent(patternParts.resource);
|
|
33
|
+
// If there are more segments in the resource than the pattern, it cannot match,
|
|
34
|
+
// unless the final pattern component is a variable (e.g. ${ObjectName}) which
|
|
35
|
+
// can span multiple segments (like S3 object keys with slashes).
|
|
36
|
+
if (resourceResourcePartsSegments > patternResourcePartsSegments) {
|
|
37
|
+
const lastPatternComponent = patternResourceParts.at(-1);
|
|
38
|
+
if (!isResourceTypeVariable(lastPatternComponent) || patternResourcePartsSegments === 1) {
|
|
39
|
+
return false;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
// If there are fewer segments with contents in the resource than the pattern, and the last segment of the resource
|
|
43
|
+
// does not end with a wildcard, it cannot match
|
|
44
|
+
if (resourceResourceParts.length < patternResourceParts.length &&
|
|
45
|
+
!resourceResourceParts.at(-1)?.endsWith('*')) {
|
|
46
|
+
return false;
|
|
47
|
+
}
|
|
48
|
+
const compareLen = Math.min(resourceResourceParts.length, patternResourceParts.length);
|
|
49
|
+
for (let i = 0; i < compareLen; i++) {
|
|
50
|
+
const resourceComponent = resourceResourceParts[i];
|
|
51
|
+
const isLastPattern = i === patternResourceParts.length - 1;
|
|
52
|
+
const patternComponent = patternResourceParts[i];
|
|
53
|
+
if (!patternComponent) {
|
|
54
|
+
return false;
|
|
55
|
+
}
|
|
56
|
+
if (isResourceTypeVariable(patternComponent)) {
|
|
57
|
+
if (isLastPattern &&
|
|
58
|
+
resourceResourcePartsSegments > patternResourcePartsSegments &&
|
|
59
|
+
patternResourcePartsSegments > 1) {
|
|
60
|
+
// Variable at the end can absorb additional segments.
|
|
61
|
+
return true;
|
|
62
|
+
}
|
|
63
|
+
if (isLastPattern && resourceComponent?.endsWith('*')) {
|
|
64
|
+
// If the resource component ends with a wildcard, it matches everything after
|
|
65
|
+
break;
|
|
66
|
+
}
|
|
67
|
+
// These match anything, move along.
|
|
68
|
+
continue;
|
|
69
|
+
}
|
|
70
|
+
if (!resourceComponent) {
|
|
71
|
+
return false;
|
|
72
|
+
}
|
|
73
|
+
const resourceComponentPattern = '^' + resourceComponent.replace(/\?/g, '.').replace(/\*/g, '.*?') + '$';
|
|
74
|
+
const regex = new RegExp(resourceComponentPattern);
|
|
75
|
+
const match = patternComponent.match(regex);
|
|
76
|
+
if (match) {
|
|
77
|
+
if (isLastPattern && resourceComponent.endsWith('*')) {
|
|
78
|
+
// If the resource component ends with a wildcard, it matches everything after
|
|
79
|
+
break;
|
|
80
|
+
}
|
|
81
|
+
continue;
|
|
82
|
+
}
|
|
83
|
+
else {
|
|
84
|
+
return false;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
/*
|
|
88
|
+
Matching resource types.
|
|
89
|
+
If the pattern has a slash or colon in the resource portion, those need to exist in the pattern.
|
|
90
|
+
If the pattern ends with a wildcard, that matches everything.
|
|
91
|
+
*/
|
|
92
|
+
return true;
|
|
93
|
+
}
|
|
94
|
+
function splitResourceTypeComponent(component) {
|
|
95
|
+
const parts = component?.split(/[:/]/) ?? [];
|
|
96
|
+
return [parts.length, parts.filter((p) => p && p !== '')];
|
|
97
|
+
}
|
|
98
|
+
function resourceComponentMatchesResourceTypeComponent(resourceComponent, resourceTypeComponent) {
|
|
99
|
+
if (resourceTypeComponent === '*' || resourceTypeComponent === resourceComponent) {
|
|
100
|
+
return true;
|
|
101
|
+
}
|
|
102
|
+
if (!resourceComponent || !resourceTypeComponent) {
|
|
103
|
+
return false;
|
|
104
|
+
}
|
|
105
|
+
if (isResourceTypeVariable(resourceTypeComponent)) {
|
|
106
|
+
// If the entire component is a single variable, it matches anything
|
|
107
|
+
return true;
|
|
108
|
+
}
|
|
109
|
+
const pattern = (0, util_js_1.convertResourcePatternToRegex)(resourceTypeComponent);
|
|
110
|
+
const regex = new RegExp(pattern);
|
|
111
|
+
const match = resourceComponent.match(regex);
|
|
112
|
+
return !!match;
|
|
113
|
+
}
|
|
114
|
+
function isResourceTypeVariable(component) {
|
|
115
|
+
if (!component) {
|
|
116
|
+
return false;
|
|
117
|
+
}
|
|
118
|
+
return component.match(/^\$\{[0-9a-zA-Z]+\}$/) !== null;
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Get the the possible resource types for an action and resource
|
|
122
|
+
*
|
|
123
|
+
* @param service the service the action belongs to
|
|
124
|
+
* @param action the action to get the resource type for
|
|
125
|
+
* @param resource the resource type matching the action, if any
|
|
126
|
+
* @throws an error if the service or action does not exist, or if the action is a wildcard only action
|
|
127
|
+
*/
|
|
128
|
+
async function getResourceTypesForAction(service, action, resource) {
|
|
129
|
+
const actionDetails = await (0, iam_data_1.iamActionDetails)(service, action);
|
|
130
|
+
if (actionDetails.resourceTypes.length === 0) {
|
|
131
|
+
throw new Error(`${service}:${action} does not have any resource types`);
|
|
132
|
+
}
|
|
133
|
+
const matchingResourceTypes = [];
|
|
134
|
+
for (const rt of actionDetails.resourceTypes) {
|
|
135
|
+
const resourceType = await (0, iam_data_1.iamResourceTypeDetails)(service, rt.name);
|
|
136
|
+
// const pattern = convertResourcePatternToRegex(resourceType.arn)
|
|
137
|
+
// const match = resource.match(new RegExp(pattern))
|
|
138
|
+
const match = resourceStringMatchesResourceTypePattern(resource, resourceType.arn);
|
|
139
|
+
if (match) {
|
|
140
|
+
matchingResourceTypes.push(resourceType);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
return matchingResourceTypes;
|
|
144
|
+
}
|
|
145
|
+
//# sourceMappingURL=resourceTypes.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resourceTypes.js","sourceRoot":"","sources":["../../../src/simulation_engine/resourceTypes.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
+
import { ResourceType } from '@cloud-copilot/iam-data';
|
|
1
2
|
import { ValidationError } from '@cloud-copilot/iam-policy';
|
|
2
|
-
import { RequestAnalysis } from '../evaluate.js';
|
|
3
|
+
import { EvaluationResult, RequestAnalysis } from '../evaluate.js';
|
|
3
4
|
import { Simulation } from './simulation.js';
|
|
4
5
|
import { SimulationOptions } from './simulationOptions.js';
|
|
5
6
|
export interface SimulationErrors {
|
|
@@ -12,16 +13,11 @@ export interface SimulationErrors {
|
|
|
12
13
|
vpcEndpointErrors?: Record<string, ValidationError[]>;
|
|
13
14
|
message: string;
|
|
14
15
|
}
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
*
|
|
21
|
-
* Will only be present if the request passes validation to reach the policy
|
|
22
|
-
* evaluation stage and the action is not a wildcard-only action.
|
|
23
|
-
*/
|
|
24
|
-
resourceType?: string;
|
|
16
|
+
/**
|
|
17
|
+
* Result of evaluating a single resource simulation, containing the analysis and any ignored context keys.
|
|
18
|
+
*/
|
|
19
|
+
export interface SimulationResourceResult {
|
|
20
|
+
analysis: RequestAnalysis;
|
|
25
21
|
/**
|
|
26
22
|
* Any context keys provided in the request that were filtered out before
|
|
27
23
|
* policy evaluation because they do not apply to the action/resource type.
|
|
@@ -33,15 +29,97 @@ export interface SimulationResult {
|
|
|
33
29
|
*/
|
|
34
30
|
ignoredContextKeys?: string[];
|
|
35
31
|
}
|
|
32
|
+
/**
|
|
33
|
+
* Extended simulation resource result that includes resource type and pattern information
|
|
34
|
+
* for wildcard resource simulations.
|
|
35
|
+
*/
|
|
36
|
+
export interface WildcardSimulationResourceResult extends SimulationResourceResult {
|
|
37
|
+
/**
|
|
38
|
+
* The resource type that was used for the simulation, if applicable.
|
|
39
|
+
*
|
|
40
|
+
* Will only be present if the request passes validation to reach the policy
|
|
41
|
+
* evaluation stage and the action is not a wildcard-only action.
|
|
42
|
+
*/
|
|
43
|
+
resourceType: string;
|
|
44
|
+
/**
|
|
45
|
+
* The resource pattern that was used for the simulation, if applicable. If a wildcard
|
|
46
|
+
* resource was provided and multiple simulations were run, this will indicate the
|
|
47
|
+
* specific resource string that was simulated.
|
|
48
|
+
*/
|
|
49
|
+
resourcePattern: string;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Simulation result indicating that errors prevented the simulation from running.
|
|
53
|
+
*/
|
|
54
|
+
export interface ErrorSimulationResult {
|
|
55
|
+
resultType: 'error';
|
|
56
|
+
/**
|
|
57
|
+
* Errors in the simulation input that prevented the simulation from being run.
|
|
58
|
+
*/
|
|
59
|
+
errors: SimulationErrors;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Simulation result for a single resource (non-wildcard) evaluation.
|
|
63
|
+
*/
|
|
64
|
+
export interface SingleResourceSimulationResult {
|
|
65
|
+
/**
|
|
66
|
+
* A single resource simulation result.
|
|
67
|
+
*/
|
|
68
|
+
resultType: 'single';
|
|
69
|
+
/**
|
|
70
|
+
* The overall result of the one simulation that was run.
|
|
71
|
+
*/
|
|
72
|
+
overallResult: EvaluationResult;
|
|
73
|
+
/**
|
|
74
|
+
* The detailed result of the simulation that was run and the request analysis
|
|
75
|
+
*/
|
|
76
|
+
result: SimulationResourceResult;
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Simulation results for wildcard resource evaluations, containing multiple individual results.
|
|
80
|
+
*/
|
|
81
|
+
export interface WildcardResourceSimulationResults {
|
|
82
|
+
/**
|
|
83
|
+
* Whether a wildcard was detected in the resource ARN of the request and the
|
|
84
|
+
* simulation was not a wildcard-only action, which can cause multiple simulations to be run.
|
|
85
|
+
*/
|
|
86
|
+
resultType: 'wildcard';
|
|
87
|
+
/**
|
|
88
|
+
* The overall result of the simulation, calculated based on the results of individual simulations if
|
|
89
|
+
* multiple were run.
|
|
90
|
+
*/
|
|
91
|
+
overallResult: EvaluationResult;
|
|
92
|
+
/**
|
|
93
|
+
* The results of the simulation or simulations that were run.
|
|
94
|
+
* If it is a wildcard only action or the resource ARN contains no wildcards, this will contain a single result.
|
|
95
|
+
* If the resource ARN contains a wildcard and the action is not a wildcard-only action, this may contain no
|
|
96
|
+
* results, or one result for each matching pattern found in the provided identity and resource policies.
|
|
97
|
+
*/
|
|
98
|
+
results: WildcardSimulationResourceResult[];
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* The result of running a simulation.
|
|
102
|
+
* Can be an error, a single result, or a wildcard result.
|
|
103
|
+
* Discriminated by the `resultType` field.
|
|
104
|
+
*/
|
|
105
|
+
export type RunSimulationResults = ErrorSimulationResult | SingleResourceSimulationResult | WildcardResourceSimulationResults;
|
|
106
|
+
/**
|
|
107
|
+
* Union type representing successful simulation results (excluding error cases).
|
|
108
|
+
*/
|
|
109
|
+
export type SuccessfulRunSimulationResults = SingleResourceSimulationResult | WildcardResourceSimulationResults;
|
|
110
|
+
/**
|
|
111
|
+
* Discriminant type for the different kinds of simulation results.
|
|
112
|
+
*/
|
|
113
|
+
export type SimulationResultType = RunSimulationResults['resultType'];
|
|
36
114
|
/**
|
|
37
115
|
* Run a simulation with validation
|
|
38
116
|
*
|
|
39
117
|
* @param simulation The simulation to run
|
|
40
118
|
* @param simulationOptions Options for the simulation
|
|
41
|
-
* @returns
|
|
119
|
+
* @returns The results of the simulation, or errors if the simulation could not be run
|
|
42
120
|
*/
|
|
43
|
-
export declare function runSimulation(simulation: Simulation, simulationOptions: Partial<SimulationOptions>): Promise<
|
|
44
|
-
export declare function normalizeSimulationParameters(simulation: Simulation): Promise<{
|
|
121
|
+
export declare function runSimulation(simulation: Simulation, simulationOptions: Partial<SimulationOptions>): Promise<RunSimulationResults>;
|
|
122
|
+
export declare function normalizeSimulationParameters(simulation: Simulation, suggestedResourceType: ResourceType | undefined): Promise<{
|
|
45
123
|
validContextValues: Record<string, string | string[]>;
|
|
46
124
|
ignoredContextKeys: string[];
|
|
47
125
|
}>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"simulationEngine.d.ts","sourceRoot":"","sources":["../../../src/simulation_engine/simulationEngine.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"simulationEngine.d.ts","sourceRoot":"","sources":["../../../src/simulation_engine/simulationEngine.ts"],"names":[],"mappings":"AAAA,OAAO,EAAqC,YAAY,EAAE,MAAM,yBAAyB,CAAA;AACzF,OAAO,EAOL,eAAe,EAChB,MAAM,2BAA2B,CAAA;AAYlC,OAAO,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAA;AAQlE,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAA;AAC5C,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAA;AAiB1D,MAAM,WAAW,gBAAgB;IAC/B,mBAAmB,CAAC,EAAE,eAAe,EAAE,CAAA;IACvC,oBAAoB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,EAAE,CAAC,CAAA;IACxD,0BAA0B,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,EAAE,CAAC,CAAA;IAC9D,2BAA2B,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,EAAE,CAAC,CAAA;IAC/D,wBAAwB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,EAAE,CAAC,CAAA;IAC5D,oBAAoB,CAAC,EAAE,eAAe,EAAE,CAAA;IACxC,iBAAiB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,EAAE,CAAC,CAAA;IACrD,OAAO,EAAE,MAAM,CAAA;CAChB;AAED;;GAEG;AACH,MAAM,WAAW,wBAAwB;IACvC,QAAQ,EAAE,eAAe,CAAA;IAEzB;;;;;;;;OAQG;IACH,kBAAkB,CAAC,EAAE,MAAM,EAAE,CAAA;CAC9B;AAED;;;GAGG;AACH,MAAM,WAAW,gCAAiC,SAAQ,wBAAwB;IAChF;;;;;OAKG;IACH,YAAY,EAAE,MAAM,CAAA;IAEpB;;;;OAIG;IACH,eAAe,EAAE,MAAM,CAAA;CACxB;AAED;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC,UAAU,EAAE,OAAO,CAAA;IAEnB;;OAEG;IACH,MAAM,EAAE,gBAAgB,CAAA;CACzB;AAED;;GAEG;AACH,MAAM,WAAW,8BAA8B;IAC7C;;OAEG;IACH,UAAU,EAAE,QAAQ,CAAA;IAEpB;;OAEG;IACH,aAAa,EAAE,gBAAgB,CAAA;IAE/B;;OAEG;IACH,MAAM,EAAE,wBAAwB,CAAA;CACjC;AAED;;GAEG;AACH,MAAM,WAAW,iCAAiC;IAChD;;;OAGG;IACH,UAAU,EAAE,UAAU,CAAA;IAEtB;;;OAGG;IACH,aAAa,EAAE,gBAAgB,CAAA;IAE/B;;;;;OAKG;IACH,OAAO,EAAE,gCAAgC,EAAE,CAAA;CAC5C;AAED;;;;GAIG;AACH,MAAM,MAAM,oBAAoB,GAC5B,qBAAqB,GACrB,8BAA8B,GAC9B,iCAAiC,CAAA;AAErC;;GAEG;AACH,MAAM,MAAM,8BAA8B,GACtC,8BAA8B,GAC9B,iCAAiC,CAAA;AAErC;;GAEG;AACH,MAAM,MAAM,oBAAoB,GAAG,oBAAoB,CAAC,YAAY,CAAC,CAAA;AAErE;;;;;;GAMG;AACH,wBAAsB,aAAa,CACjC,UAAU,EAAE,UAAU,EACtB,iBAAiB,EAAE,OAAO,CAAC,iBAAiB,CAAC,GAC5C,OAAO,CAAC,oBAAoB,CAAC,CA0T/B;AAED,wBAAsB,6BAA6B,CACjD,UAAU,EAAE,UAAU,EACtB,qBAAqB,EAAE,YAAY,GAAG,SAAS,GAC9C,OAAO,CAAC;IACT,kBAAkB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC,CAAA;IACrD,kBAAkB,EAAE,MAAM,EAAE,CAAA;CAC7B,CAAC,CA0CD"}
|
|
@@ -13,6 +13,9 @@ const request_js_1 = require("../request/request.js");
|
|
|
13
13
|
const requestContext_js_1 = require("../requestContext.js");
|
|
14
14
|
const util_js_1 = require("../util.js");
|
|
15
15
|
const contextKeys_js_2 = require("./contextKeys.js");
|
|
16
|
+
const overallResult_js_1 = require("./overallResult.js");
|
|
17
|
+
const policyResources_js_1 = require("./policyResources.js");
|
|
18
|
+
const resourceTypes_js_1 = require("./resourceTypes.js");
|
|
16
19
|
const DEFAULT_RCP = {
|
|
17
20
|
name: 'RCPFullAWSAccess',
|
|
18
21
|
policy: {
|
|
@@ -32,15 +35,18 @@ const DEFAULT_RCP = {
|
|
|
32
35
|
*
|
|
33
36
|
* @param simulation The simulation to run
|
|
34
37
|
* @param simulationOptions Options for the simulation
|
|
35
|
-
* @returns
|
|
38
|
+
* @returns The results of the simulation, or errors if the simulation could not be run
|
|
36
39
|
*/
|
|
37
40
|
async function runSimulation(simulation, simulationOptions) {
|
|
38
41
|
const principal = simulation.request.principal;
|
|
42
|
+
const resourceArn = simulation.request.resource.resource;
|
|
43
|
+
const resourceHasWildcard = resourceArn.includes('*');
|
|
39
44
|
if (simulation.sessionPolicy) {
|
|
40
45
|
if (!(0, iam_utils_1.isIamRoleArn)(principal) &&
|
|
41
46
|
!(0, iam_utils_1.isAssumedRoleArn)(principal) &&
|
|
42
47
|
!(0, iam_utils_1.isFederatedUserArn)(principal)) {
|
|
43
48
|
return {
|
|
49
|
+
resultType: 'error',
|
|
44
50
|
errors: {
|
|
45
51
|
message: 'session.policy.invalid.principal'
|
|
46
52
|
}
|
|
@@ -143,6 +149,7 @@ async function runSimulation(simulation, simulationOptions) {
|
|
|
143
149
|
resourcePolicyErrors.length > 0 ||
|
|
144
150
|
sessionPolicyErrors.length > 0) {
|
|
145
151
|
return {
|
|
152
|
+
resultType: 'error',
|
|
146
153
|
errors: {
|
|
147
154
|
sessionPolicyErrors,
|
|
148
155
|
identityPolicyErrors,
|
|
@@ -160,6 +167,7 @@ async function runSimulation(simulation, simulationOptions) {
|
|
|
160
167
|
: undefined;
|
|
161
168
|
if (simulation.request.action.split(':').length != 2) {
|
|
162
169
|
return {
|
|
170
|
+
resultType: 'error',
|
|
163
171
|
errors: {
|
|
164
172
|
message: 'invalid.action'
|
|
165
173
|
}
|
|
@@ -169,6 +177,7 @@ async function runSimulation(simulation, simulationOptions) {
|
|
|
169
177
|
const validService = await (0, iam_data_1.iamServiceExists)(service);
|
|
170
178
|
if (!validService) {
|
|
171
179
|
return {
|
|
180
|
+
resultType: 'error',
|
|
172
181
|
errors: {
|
|
173
182
|
message: 'invalid.service'
|
|
174
183
|
}
|
|
@@ -177,17 +186,19 @@ async function runSimulation(simulation, simulationOptions) {
|
|
|
177
186
|
const validAction = await (0, iam_data_1.iamActionExists)(service, action);
|
|
178
187
|
if (!validAction) {
|
|
179
188
|
return {
|
|
189
|
+
resultType: 'error',
|
|
180
190
|
errors: {
|
|
181
191
|
message: 'invalid.action'
|
|
182
192
|
}
|
|
183
193
|
};
|
|
184
194
|
}
|
|
185
|
-
const resourceArn = simulation.request.resource.resource;
|
|
186
195
|
const isWildCardOnlyAction = await (0, util_js_1.isWildcardOnlyAction)(service, action);
|
|
187
|
-
|
|
196
|
+
const runMultipleSimulations = resourceHasWildcard && !isWildCardOnlyAction;
|
|
197
|
+
let resourceTypes = undefined;
|
|
188
198
|
if (isWildCardOnlyAction) {
|
|
189
199
|
if (resourceArn !== '*') {
|
|
190
200
|
return {
|
|
201
|
+
resultType: 'error',
|
|
191
202
|
errors: {
|
|
192
203
|
message: 'must.use.wildcard'
|
|
193
204
|
}
|
|
@@ -195,37 +206,39 @@ async function runSimulation(simulation, simulationOptions) {
|
|
|
195
206
|
}
|
|
196
207
|
}
|
|
197
208
|
else {
|
|
198
|
-
const
|
|
199
|
-
if (
|
|
209
|
+
const actionResourceTypes = await (0, resourceTypes_js_1.getResourceTypesForAction)(service, action, resourceArn);
|
|
210
|
+
if (actionResourceTypes.length === 0) {
|
|
200
211
|
return {
|
|
212
|
+
resultType: 'error',
|
|
201
213
|
errors: {
|
|
202
214
|
message: 'no.resource.types'
|
|
203
215
|
}
|
|
204
216
|
};
|
|
205
217
|
}
|
|
206
|
-
else if (
|
|
218
|
+
else if (actionResourceTypes.length > 1 && !resourceHasWildcard) {
|
|
207
219
|
return {
|
|
220
|
+
resultType: 'error',
|
|
208
221
|
errors: {
|
|
209
222
|
message: 'multiple.resource.types'
|
|
210
223
|
}
|
|
211
224
|
};
|
|
212
225
|
}
|
|
213
226
|
else {
|
|
214
|
-
|
|
227
|
+
resourceTypes = actionResourceTypes.map((item) => item);
|
|
215
228
|
}
|
|
216
229
|
}
|
|
217
|
-
const { validContextValues, ignoredContextKeys } = await normalizeSimulationParameters(simulation);
|
|
218
230
|
const simulationMode = CoreSimulatorEngine_js_1.validSimulationModes.includes(simulationOptions.simulationMode)
|
|
219
231
|
? simulationOptions.simulationMode
|
|
220
232
|
: 'Strict';
|
|
233
|
+
// For each resource type, find the resource patterns, for each pattern, run a simulation
|
|
221
234
|
const strictConditionKeys = simulationMode === 'Discovery'
|
|
222
235
|
? new strictContextKeys_js_1.StrictContextKeys(simulationOptions.strictConditionKeys || [])
|
|
223
236
|
: new strictContextKeys_js_1.StrictContextKeys([]);
|
|
224
|
-
const
|
|
237
|
+
const curriedAuthorize = (curriedResourceString, curriedContextValues) => (0, CoreSimulatorEngine_js_1.authorize)({
|
|
225
238
|
request: new request_js_1.AwsRequestImpl(principal, {
|
|
226
|
-
resource:
|
|
239
|
+
resource: curriedResourceString,
|
|
227
240
|
accountId: simulation.request.resource.accountId
|
|
228
|
-
}, simulation.request.action, new requestContext_js_1.RequestContextImpl(
|
|
241
|
+
}, simulation.request.action, new requestContext_js_1.RequestContextImpl(curriedContextValues)),
|
|
229
242
|
sessionPolicy,
|
|
230
243
|
identityPolicies,
|
|
231
244
|
serviceControlPolicies,
|
|
@@ -238,16 +251,61 @@ async function runSimulation(simulation, simulationOptions) {
|
|
|
238
251
|
strictConditionKeys: strictConditionKeys
|
|
239
252
|
}
|
|
240
253
|
});
|
|
254
|
+
const policiesThatGrantAccess = [resourcePolicy, ...identityPolicies];
|
|
255
|
+
// If there is only one simulation to run, run it
|
|
256
|
+
if (!runMultipleSimulations) {
|
|
257
|
+
const { validContextValues, ignoredContextKeys } = await normalizeSimulationParameters(simulation, undefined);
|
|
258
|
+
const singleResult = curriedAuthorize(resourceArn, validContextValues);
|
|
259
|
+
return {
|
|
260
|
+
resultType: 'single',
|
|
261
|
+
overallResult: singleResult.result,
|
|
262
|
+
result: {
|
|
263
|
+
analysis: singleResult,
|
|
264
|
+
ignoredContextKeys
|
|
265
|
+
}
|
|
266
|
+
};
|
|
267
|
+
}
|
|
268
|
+
// Here, we know it is a wildcard resource and not a wildcard-only action, so we need to run multiple simulations
|
|
269
|
+
const simulationResults = [];
|
|
270
|
+
const resourceTypesToSimulate = resourceTypes && resourceTypes.length > 0 ? resourceTypes : [];
|
|
271
|
+
for (const resourceType of resourceTypesToSimulate) {
|
|
272
|
+
// If "run multiple" get the resource strings that match the wildcard pattern, otherwise, just run the one.
|
|
273
|
+
const { validContextValues, ignoredContextKeys } = await normalizeSimulationParameters(simulation, resourceType);
|
|
274
|
+
//Run the pattern directly first.
|
|
275
|
+
const exactPatternResult = curriedAuthorize(resourceArn, validContextValues);
|
|
276
|
+
if (exactPatternResult.result === 'ExplicitlyDenied') {
|
|
277
|
+
simulationResults.push({
|
|
278
|
+
analysis: exactPatternResult,
|
|
279
|
+
ignoredContextKeys,
|
|
280
|
+
resourceType: resourceType.key,
|
|
281
|
+
resourcePattern: resourceArn
|
|
282
|
+
});
|
|
283
|
+
}
|
|
284
|
+
else {
|
|
285
|
+
let resourceStrings = [simulation.request.resource.resource];
|
|
286
|
+
resourceStrings = (0, policyResources_js_1.getMatchingResourceStringsForPolicies)(policiesThatGrantAccess, simulation.request.action, resourceType, simulation.request.resource.resource);
|
|
287
|
+
for (const resourceString of resourceStrings) {
|
|
288
|
+
const simulationResult = curriedAuthorize(resourceString, validContextValues);
|
|
289
|
+
simulationResults.push({
|
|
290
|
+
analysis: simulationResult,
|
|
291
|
+
ignoredContextKeys,
|
|
292
|
+
resourceType: resourceType.key,
|
|
293
|
+
resourcePattern: resourceString
|
|
294
|
+
});
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
const overallResult = (0, overallResult_js_1.calculateOverallResult)(simulationResults);
|
|
241
299
|
return {
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
300
|
+
resultType: 'wildcard',
|
|
301
|
+
overallResult,
|
|
302
|
+
results: simulationResults
|
|
245
303
|
};
|
|
246
304
|
}
|
|
247
|
-
async function normalizeSimulationParameters(simulation) {
|
|
305
|
+
async function normalizeSimulationParameters(simulation, suggestedResourceType) {
|
|
248
306
|
const [service, action] = simulation.request.action.split(':');
|
|
249
307
|
const resourceArn = simulation.request.resource.resource;
|
|
250
|
-
const contextVariablesForAction = new Set(await (0, contextKeys_js_2.allowedContextKeysForRequest)(service, action, resourceArn, !!simulation.additionalSettings?.s3?.bucketAbacEnabled));
|
|
308
|
+
const contextVariablesForAction = new Set(await (0, contextKeys_js_2.allowedContextKeysForRequest)(service, action, resourceArn, !!simulation.additionalSettings?.s3?.bucketAbacEnabled, suggestedResourceType));
|
|
251
309
|
//Get the types of the context variables and set a string or array of strings based on that.
|
|
252
310
|
const validContextValues = {};
|
|
253
311
|
const ignoredContextKeys = [];
|