@cloud-copilot/iam-shrink 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE.txt +674 -0
- package/README.md +187 -0
- package/dist/cjs/cli.d.ts +2 -0
- package/dist/cjs/cli.d.ts.map +1 -0
- package/dist/cjs/cli.js +78 -0
- package/dist/cjs/cli.js.map +1 -0
- package/dist/cjs/cli_utils.d.ts +30 -0
- package/dist/cjs/cli_utils.d.ts.map +1 -0
- package/dist/cjs/cli_utils.js +75 -0
- package/dist/cjs/cli_utils.js.map +1 -0
- package/dist/cjs/errors.d.ts +13 -0
- package/dist/cjs/errors.d.ts.map +1 -0
- package/dist/cjs/errors.js +56 -0
- package/dist/cjs/errors.js.map +1 -0
- package/dist/cjs/index.d.ts +3 -0
- package/dist/cjs/index.d.ts.map +1 -0
- package/dist/cjs/index.js +8 -0
- package/dist/cjs/index.js.map +1 -0
- package/dist/cjs/package.json +3 -0
- package/dist/cjs/shrink.d.ts +131 -0
- package/dist/cjs/shrink.d.ts.map +1 -0
- package/dist/cjs/shrink.js +358 -0
- package/dist/cjs/shrink.js.map +1 -0
- package/dist/cjs/shrink_file.d.ts +12 -0
- package/dist/cjs/shrink_file.d.ts.map +1 -0
- package/dist/cjs/shrink_file.js +38 -0
- package/dist/cjs/shrink_file.js.map +1 -0
- package/dist/cjs/stdin.d.ts +7 -0
- package/dist/cjs/stdin.d.ts.map +1 -0
- package/dist/cjs/stdin.js +34 -0
- package/dist/cjs/stdin.js.map +1 -0
- package/dist/cjs/validate.d.ts +11 -0
- package/dist/cjs/validate.d.ts.map +1 -0
- package/dist/cjs/validate.js +30 -0
- package/dist/cjs/validate.js.map +1 -0
- package/dist/esm/cli.d.ts +2 -0
- package/dist/esm/cli.d.ts.map +1 -0
- package/dist/esm/cli.js +76 -0
- package/dist/esm/cli.js.map +1 -0
- package/dist/esm/cli_utils.d.ts +30 -0
- package/dist/esm/cli_utils.d.ts.map +1 -0
- package/dist/esm/cli_utils.js +69 -0
- package/dist/esm/cli_utils.js.map +1 -0
- package/dist/esm/errors.d.ts +13 -0
- package/dist/esm/errors.d.ts.map +1 -0
- package/dist/esm/errors.js +50 -0
- package/dist/esm/errors.js.map +1 -0
- package/dist/esm/index.d.ts +3 -0
- package/dist/esm/index.d.ts.map +1 -0
- package/dist/esm/index.js +3 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/package.json +3 -0
- package/dist/esm/shrink.d.ts +131 -0
- package/dist/esm/shrink.d.ts.map +1 -0
- package/dist/esm/shrink.js +343 -0
- package/dist/esm/shrink.js.map +1 -0
- package/dist/esm/shrink_file.d.ts +12 -0
- package/dist/esm/shrink_file.d.ts.map +1 -0
- package/dist/esm/shrink_file.js +35 -0
- package/dist/esm/shrink_file.js.map +1 -0
- package/dist/esm/stdin.d.ts +7 -0
- package/dist/esm/stdin.d.ts.map +1 -0
- package/dist/esm/stdin.js +31 -0
- package/dist/esm/stdin.js.map +1 -0
- package/dist/esm/validate.d.ts +11 -0
- package/dist/esm/validate.d.ts.map +1 -0
- package/dist/esm/validate.js +27 -0
- package/dist/esm/validate.js.map +1 -0
- package/package.json +43 -0
- package/postbuild.sh +13 -0
- package/src/cli.ts +83 -0
- package/src/cli_utils.test.ts +117 -0
- package/src/cli_utils.ts +82 -0
- package/src/errors.ts +52 -0
- package/src/index.ts +3 -0
- package/src/shrink.test.ts +594 -0
- package/src/shrink.ts +385 -0
- package/src/shrink_file.test.ts +72 -0
- package/src/shrink_file.ts +38 -0
- package/src/stdin.ts +34 -0
- package/src/validate.test.ts +55 -0
- package/src/validate.ts +29 -0
- package/tsconfig.cjs.json +12 -0
- package/tsconfig.esm.json +15 -0
- package/tsconfig.json +23 -0
|
@@ -0,0 +1,358 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.shrink = shrink;
|
|
4
|
+
exports.mapActions = mapActions;
|
|
5
|
+
exports.groupActionsByService = groupActionsByService;
|
|
6
|
+
exports.shrinkResolvedList = shrinkResolvedList;
|
|
7
|
+
exports.shrinkIteration = shrinkIteration;
|
|
8
|
+
exports.reduceAction = reduceAction;
|
|
9
|
+
exports.collapseAsterisks = collapseAsterisks;
|
|
10
|
+
exports.regexForWildcardAction = regexForWildcardAction;
|
|
11
|
+
exports.wildcardActionMatchesAnyString = wildcardActionMatchesAnyString;
|
|
12
|
+
exports.splitActionIntoParts = splitActionIntoParts;
|
|
13
|
+
exports.countSubstrings = countSubstrings;
|
|
14
|
+
exports.findCommonSequences = findCommonSequences;
|
|
15
|
+
exports.consolidateWildcardPatterns = consolidateWildcardPatterns;
|
|
16
|
+
const iam_expand_1 = require("@cloud-copilot/iam-expand");
|
|
17
|
+
const errors_js_1 = require("./errors.js");
|
|
18
|
+
const validate_js_1 = require("./validate.js");
|
|
19
|
+
const defaultOptions = {
|
|
20
|
+
iterations: 2
|
|
21
|
+
};
|
|
22
|
+
//TODO: Add stats for how many iterations were run?
|
|
23
|
+
/**
|
|
24
|
+
* Shrink the list of desired patterns minus the excluded patterns to the smallest list of patterns
|
|
25
|
+
* that still includes the actions you want and only the actions you want.
|
|
26
|
+
*
|
|
27
|
+
* This will create a Target Set of actions that match the patterns in {@link desiredPatterns}, and do
|
|
28
|
+
* not match any pattern in {@link excludedPatterns}.
|
|
29
|
+
*
|
|
30
|
+
* It will then derive the list of wildcard patterns that match the Target Set and no other actions.
|
|
31
|
+
*
|
|
32
|
+
* @param desiredPatterns the list of patterns you want to include, e.g. ['s3:Get*', 's3:PutObject', 's3:*Tag*']
|
|
33
|
+
* @param iterations the number of iterations to run the shrink operations
|
|
34
|
+
* @returns the smallest list of patterns that will match only the actions specified by desiredPatterns and not match any of the excludedPatterns or any actions not specified by desiredPatterns.
|
|
35
|
+
*/
|
|
36
|
+
async function shrink(desiredPatterns, shrinkOptions) {
|
|
37
|
+
//Check for an all actions wildcard
|
|
38
|
+
const wildCard = desiredPatterns.find(pattern => collapseAsterisks(pattern) === '*');
|
|
39
|
+
if (wildCard) {
|
|
40
|
+
return ["*"];
|
|
41
|
+
}
|
|
42
|
+
const options = { ...defaultOptions, ...shrinkOptions };
|
|
43
|
+
const targetActions = await (0, iam_expand_1.expandIamActions)(desiredPatterns, { expandServiceAsterisk: true });
|
|
44
|
+
const expandedActionsByService = groupActionsByService(targetActions);
|
|
45
|
+
const services = Array.from(expandedActionsByService.keys()).sort();
|
|
46
|
+
const reducedActions = [];
|
|
47
|
+
for (const service of services) {
|
|
48
|
+
const desiredActions = expandedActionsByService.get(service);
|
|
49
|
+
const possibleActions = mapActions(await (0, iam_expand_1.expandIamActions)(`${service}:*`, { expandServiceAsterisk: true }));
|
|
50
|
+
const reducedServiceActions = shrinkResolvedList(desiredActions.withoutService, possibleActions, options.iterations);
|
|
51
|
+
//Validation
|
|
52
|
+
const reducedServiceActionsWithService = reducedServiceActions.map(action => `${service}:${action}`);
|
|
53
|
+
const invalidMatch = await (0, validate_js_1.validateShrinkResults)(desiredActions.withService, reducedServiceActionsWithService);
|
|
54
|
+
if (invalidMatch) {
|
|
55
|
+
throw new errors_js_1.ShrinkValidationError(desiredPatterns, invalidMatch);
|
|
56
|
+
}
|
|
57
|
+
reducedActions.push(...reducedServiceActionsWithService);
|
|
58
|
+
}
|
|
59
|
+
return reducedActions;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Map an array of service:action strings to just the action
|
|
63
|
+
*
|
|
64
|
+
* @param actions the array of service:action strings such as ['s3:GetObject', 'ec2:DescribeInstances']
|
|
65
|
+
* @returns an array of just the action strings such as ['GetObject', 'DescribeInstances']
|
|
66
|
+
*/
|
|
67
|
+
function mapActions(actions) {
|
|
68
|
+
return actions.map(action => action.split(":")[1]);
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Groups an array of service:action strings by service
|
|
72
|
+
*
|
|
73
|
+
* Returns a map of service to an object with two arrays: withService and withoutService
|
|
74
|
+
* * withService contains the full service:action strings
|
|
75
|
+
* * withoutService contains just the action strings
|
|
76
|
+
*
|
|
77
|
+
* @param actions the array of service:action strings such as ['s3:GetObject', 'ec2:DescribeInstances']
|
|
78
|
+
* @returns a map of service to an object with two arrays: withService and withoutService
|
|
79
|
+
*/
|
|
80
|
+
function groupActionsByService(actions) {
|
|
81
|
+
const serviceMap = new Map();
|
|
82
|
+
actions.forEach(actionString => {
|
|
83
|
+
const [service, action] = actionString.split(":");
|
|
84
|
+
if (!serviceMap.has(service)) {
|
|
85
|
+
serviceMap.set(service, { withService: [], withoutService: [] });
|
|
86
|
+
}
|
|
87
|
+
serviceMap.get(service).withService.push(actionString);
|
|
88
|
+
serviceMap.get(service).withoutService.push(action);
|
|
89
|
+
});
|
|
90
|
+
return serviceMap;
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Shrink a list of desired actions to the smallest number of patterns that match the desired actions
|
|
94
|
+
* from the possible actions and no other actions.
|
|
95
|
+
*
|
|
96
|
+
* @param desiredActions the list of actions you want to include
|
|
97
|
+
* @param possibleActions the list of actions that are possible
|
|
98
|
+
* @param iterations the number of iterations to run the shrink operations
|
|
99
|
+
* @returns the smallest list of patterns that when compared to possibleActions will match only the desiredActions and no others
|
|
100
|
+
*/
|
|
101
|
+
function shrinkResolvedList(desiredActions, possibleActions, iterations) {
|
|
102
|
+
const desiredActionSet = new Set(desiredActions);
|
|
103
|
+
const undesiredActions = possibleActions.filter(action => !desiredActionSet.has(action));
|
|
104
|
+
if (undesiredActions.length === 0) {
|
|
105
|
+
// If there are no undesired actions, that means we want all actions
|
|
106
|
+
return ["*"];
|
|
107
|
+
}
|
|
108
|
+
// Iteratively shrink based on the most commmon sequence until we can't shrink anymore
|
|
109
|
+
let previousActionListLength = desiredActions.length;
|
|
110
|
+
let actionList = desiredActions.slice();
|
|
111
|
+
do {
|
|
112
|
+
previousActionListLength = actionList.length;
|
|
113
|
+
actionList = shrinkIteration(actionList, undesiredActions, false);
|
|
114
|
+
iterations = iterations - 1;
|
|
115
|
+
if (iterations <= 0) {
|
|
116
|
+
return actionList;
|
|
117
|
+
}
|
|
118
|
+
} while (actionList.length < previousActionListLength);
|
|
119
|
+
// Iteratively shrink based on all common sequences until we can't shrink anymore
|
|
120
|
+
do {
|
|
121
|
+
previousActionListLength = actionList.length;
|
|
122
|
+
actionList = shrinkIteration(actionList, undesiredActions, true);
|
|
123
|
+
iterations = iterations - 1;
|
|
124
|
+
if (iterations <= 0) {
|
|
125
|
+
return actionList;
|
|
126
|
+
}
|
|
127
|
+
} while (actionList.length < previousActionListLength);
|
|
128
|
+
return actionList;
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Shrink the list of desired actions for while excluding the undesired actions
|
|
132
|
+
*
|
|
133
|
+
* @param desiredActions the list of actions you want to include, can be a mix of full actions and wildcards
|
|
134
|
+
* @param undesiredActions the list of actions you want to exclude no matter what
|
|
135
|
+
* @param deep if true, will shrink based on all common sequences, otherwise will only shrink based on the most common sequence
|
|
136
|
+
* @returns the smallest list of actions that will match only the desiredActions and not match any of the undesiredActions or any actions not specified by desiredActions.
|
|
137
|
+
*/
|
|
138
|
+
function shrinkIteration(desiredActions, undesiredActions, deep) {
|
|
139
|
+
// Find all common words in the strings in the desiredActions array
|
|
140
|
+
const commonSequences = findCommonSequences(desiredActions).filter(sequence => sequence.sequence != "*");
|
|
141
|
+
;
|
|
142
|
+
commonSequences.sort((a, b) => {
|
|
143
|
+
return b.frequency - a.frequency;
|
|
144
|
+
});
|
|
145
|
+
const sequencesToProcess = deep ? commonSequences : commonSequences.slice(0, 1);
|
|
146
|
+
// Reduce the actions based on the common sequences
|
|
147
|
+
let reducedActions = desiredActions;
|
|
148
|
+
for (const sequence of sequencesToProcess) {
|
|
149
|
+
const reducedIteration = Array.from(new Set(reducedActions.map(action => reduceAction(action, sequence.sequence, undesiredActions))));
|
|
150
|
+
reducedActions = consolidateWildcardPatterns(reducedIteration);
|
|
151
|
+
}
|
|
152
|
+
return reducedActions;
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* Reduces a singele action into a smaller number of parts by replace one part at a time with an asterisk
|
|
156
|
+
* and validating that there are no undesired actions that match the new action
|
|
157
|
+
*
|
|
158
|
+
* @param desiredAction the action to reduce
|
|
159
|
+
* @param sequence the sequence to reduce the action by
|
|
160
|
+
* @param undesiredActions the list of actions that should not match the reduced action
|
|
161
|
+
* @returns the reduced action with as many parts replaced with asterisks as possible while still matching the desired actions and not matching any of the undesired actions
|
|
162
|
+
*/
|
|
163
|
+
function reduceAction(desiredAction, sequence, undesiredActions) {
|
|
164
|
+
const testArray = splitActionIntoParts(desiredAction);
|
|
165
|
+
if (testArray.length === 1) {
|
|
166
|
+
return desiredAction;
|
|
167
|
+
}
|
|
168
|
+
const indexOfSequence = testArray.indexOf(sequence);
|
|
169
|
+
let shorterValue = desiredAction;
|
|
170
|
+
if (indexOfSequence === 0) {
|
|
171
|
+
const tempArray = testArray.slice();
|
|
172
|
+
//Iterate though ever following element and see if replacing the sequence with the first common sequence results in a failure
|
|
173
|
+
for (let i = 1; i < testArray.length; i++) {
|
|
174
|
+
tempArray[i] = "*";
|
|
175
|
+
const tempString = collapseAsterisks(tempArray.join(""));
|
|
176
|
+
const problemMatch = wildcardActionMatchesAnyString(tempString, undesiredActions);
|
|
177
|
+
if (problemMatch) {
|
|
178
|
+
// Stopping here seems to work the best
|
|
179
|
+
break;
|
|
180
|
+
}
|
|
181
|
+
shorterValue = tempString;
|
|
182
|
+
}
|
|
183
|
+
//its at the beginning
|
|
184
|
+
}
|
|
185
|
+
else if (indexOfSequence === testArray.length - 1) {
|
|
186
|
+
//its at the end
|
|
187
|
+
const tempArray = testArray.slice();
|
|
188
|
+
//Iterate through the array backwards and see if replace the items with * results in a failure
|
|
189
|
+
for (let i = testArray.length - 2; i >= 0; i--) {
|
|
190
|
+
tempArray[i] = "*";
|
|
191
|
+
const tempString = collapseAsterisks(tempArray.join(""));
|
|
192
|
+
const problemMatch = wildcardActionMatchesAnyString(tempString, undesiredActions);
|
|
193
|
+
if (problemMatch) {
|
|
194
|
+
// Stopping here seems to work the best
|
|
195
|
+
break;
|
|
196
|
+
}
|
|
197
|
+
shorterValue = tempString;
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
else if (indexOfSequence > 0) {
|
|
201
|
+
//its in the middle
|
|
202
|
+
const tempArray = testArray.slice();
|
|
203
|
+
//Iterate forward through the array and see if replacing the items with * results in a failure
|
|
204
|
+
for (let i = indexOfSequence + 1; i < testArray.length; i++) {
|
|
205
|
+
tempArray[i] = "*";
|
|
206
|
+
const tempString = collapseAsterisks(tempArray.join(""));
|
|
207
|
+
const problemMatch = wildcardActionMatchesAnyString(tempString, undesiredActions);
|
|
208
|
+
if (problemMatch) {
|
|
209
|
+
//This replacement cased a prolem match, so revert it before going backwards in the strings
|
|
210
|
+
tempArray[i] = testArray[i];
|
|
211
|
+
// Stopping here seems to work the best
|
|
212
|
+
break;
|
|
213
|
+
}
|
|
214
|
+
shorterValue = tempString;
|
|
215
|
+
}
|
|
216
|
+
//Iterate through the array backwards and see if replace the items with * results in a failure
|
|
217
|
+
for (let i = indexOfSequence - 1; i >= 0; i--) {
|
|
218
|
+
tempArray[i] = "*";
|
|
219
|
+
const tempString = collapseAsterisks(tempArray.join(""));
|
|
220
|
+
const problemMatch = wildcardActionMatchesAnyString(tempString, undesiredActions);
|
|
221
|
+
if (problemMatch) {
|
|
222
|
+
// Stopping here seems to work the best
|
|
223
|
+
break;
|
|
224
|
+
}
|
|
225
|
+
shorterValue = tempString;
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
return shorterValue;
|
|
229
|
+
}
|
|
230
|
+
/**
|
|
231
|
+
* Consolidate multile consecutive asterisks into a single asterisk
|
|
232
|
+
*
|
|
233
|
+
* @param wildcardAction the action to collapse
|
|
234
|
+
* @returns the action with consecutive asterisks collapsed into a single asterisk
|
|
235
|
+
*/
|
|
236
|
+
function collapseAsterisks(wildcardAction) {
|
|
237
|
+
return wildcardAction.replace(/\*+/g, '*');
|
|
238
|
+
}
|
|
239
|
+
/**
|
|
240
|
+
* Convert a wildcard action into a regular expression
|
|
241
|
+
*
|
|
242
|
+
* @param wildcardAction the wildcard action to convert
|
|
243
|
+
* @returns a regular expression that will match the wildcard action
|
|
244
|
+
*/
|
|
245
|
+
function regexForWildcardAction(wildcardAction) {
|
|
246
|
+
wildcardAction = collapseAsterisks(wildcardAction);
|
|
247
|
+
const pattern = "^" + wildcardAction.replace(/\*/g, '.*?') + "$";
|
|
248
|
+
return new RegExp(pattern, 'i');
|
|
249
|
+
}
|
|
250
|
+
/**
|
|
251
|
+
* Checks to see if a wildcard action matches any of the strings in a list
|
|
252
|
+
*
|
|
253
|
+
* @param wildcardAction the wildcard action to check
|
|
254
|
+
* @param strings the list of strings to check against
|
|
255
|
+
* @returns true if the wildcard action matches any of the strings
|
|
256
|
+
*/
|
|
257
|
+
function wildcardActionMatchesAnyString(wildcardAction, strings) {
|
|
258
|
+
const regex = regexForWildcardAction(wildcardAction);
|
|
259
|
+
for (const string of strings) {
|
|
260
|
+
if (regex.test(string)) {
|
|
261
|
+
return true;
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
return false;
|
|
265
|
+
}
|
|
266
|
+
/**
|
|
267
|
+
* Split an IAM Action into parts based on capital letters and asterisks
|
|
268
|
+
* For a new part to start there must be a transition from a lowercase letter to an uppercase letter or an asterisk
|
|
269
|
+
* For example :
|
|
270
|
+
* * "CreateAccessPointForObjectLambda" would be split into ["Create", "Access", "Point", "For", "Object", "Lambda"]
|
|
271
|
+
* * "*ObjectTagging*" would be split into ["*", "Object", "Tagging", "*"]
|
|
272
|
+
*
|
|
273
|
+
* @param input the IAM Action to split
|
|
274
|
+
* @returns the parts of the IAM Action
|
|
275
|
+
*/
|
|
276
|
+
function splitActionIntoParts(input) {
|
|
277
|
+
// Split the string using a regex that finds transitions from lower to upper case or asterisks
|
|
278
|
+
// and keeps sequences of uppercase letters together
|
|
279
|
+
// return input.split(/(?<=[a-z])(?=[A-Z])|(?<=[A-Z])(?=[A-Z][a-z])/);
|
|
280
|
+
return input.split(/(?<=[a-z])(?=[A-Z])|(?<=[A-Z])(?=[A-Z][a-z])|(?=[*])|(?<=[*])/);
|
|
281
|
+
}
|
|
282
|
+
/**
|
|
283
|
+
* Given a list of strings and a list of strings those parts are in, count the number of times each part appears in the strings
|
|
284
|
+
*
|
|
285
|
+
* @param substrings the sub strings to count
|
|
286
|
+
* @param actions the list of strings to count the substrings in
|
|
287
|
+
* @returns Returns a map of the substring to the number of times it appears in the actions
|
|
288
|
+
*/
|
|
289
|
+
function countSubstrings(substrings, actions) {
|
|
290
|
+
const substringCount = new Map();
|
|
291
|
+
substrings.forEach(substring => {
|
|
292
|
+
let count = 0;
|
|
293
|
+
actions.forEach(action => {
|
|
294
|
+
if (action.includes(substring)) {
|
|
295
|
+
count++;
|
|
296
|
+
}
|
|
297
|
+
});
|
|
298
|
+
if (count > 0) {
|
|
299
|
+
substringCount.set(substring, count);
|
|
300
|
+
}
|
|
301
|
+
});
|
|
302
|
+
return substringCount;
|
|
303
|
+
}
|
|
304
|
+
/**
|
|
305
|
+
* Finds all the the common sequences in a list of actions strings and counts their frequency and length.
|
|
306
|
+
*
|
|
307
|
+
* @param actions the list of actions to find common sequences in
|
|
308
|
+
* @returns an array of objects with the sequence, frequency, and length of the common sequences
|
|
309
|
+
*/
|
|
310
|
+
function findCommonSequences(actions) {
|
|
311
|
+
const allSubstrings = new Set();
|
|
312
|
+
actions.forEach(action => {
|
|
313
|
+
splitActionIntoParts(action).forEach(substring => allSubstrings.add(substring));
|
|
314
|
+
});
|
|
315
|
+
const substringCount = countSubstrings(Array.from(allSubstrings), actions);
|
|
316
|
+
const result = [];
|
|
317
|
+
substringCount.forEach((frequency, sequence) => {
|
|
318
|
+
result.push({ sequence, frequency, length: sequence.length });
|
|
319
|
+
});
|
|
320
|
+
return result;
|
|
321
|
+
}
|
|
322
|
+
/**
|
|
323
|
+
* Consolidates overlapping wildcards into their most general form
|
|
324
|
+
*
|
|
325
|
+
* For example:
|
|
326
|
+
* ['*Object', 'Object*', '*Object*'] will be consolidated into ['*Object*']
|
|
327
|
+
* ['Get*', '*Get*'] will be consolidated into ['*Get*']
|
|
328
|
+
*
|
|
329
|
+
* @param patterns the list of patterns to consolidate
|
|
330
|
+
* @returns the consolidated list of patterns
|
|
331
|
+
*/
|
|
332
|
+
function consolidateWildcardPatterns(patterns) {
|
|
333
|
+
// Sort patterns to handle simpler cases first
|
|
334
|
+
patterns.sort((a, b) => b.length - a.length);
|
|
335
|
+
let consolidatedPatterns = [];
|
|
336
|
+
for (const pattern of patterns) {
|
|
337
|
+
//If it's already covered, skip it
|
|
338
|
+
const coveredByExistingPattern = consolidatedPatterns.some(consolidated => matchesPattern(consolidated, pattern));
|
|
339
|
+
if (coveredByExistingPattern) {
|
|
340
|
+
continue;
|
|
341
|
+
}
|
|
342
|
+
//If it subsumes any existing patterns, remove them
|
|
343
|
+
consolidatedPatterns = consolidatedPatterns.filter(consolidated => !matchesPattern(pattern, consolidated));
|
|
344
|
+
consolidatedPatterns.push(pattern);
|
|
345
|
+
}
|
|
346
|
+
return consolidatedPatterns;
|
|
347
|
+
}
|
|
348
|
+
/**
|
|
349
|
+
* Checks a specific string against a general pattern
|
|
350
|
+
* @param general the general pattern, e.g. 's3:Get*'
|
|
351
|
+
* @param specific the specific string, e.g. 's3:GetObject'
|
|
352
|
+
* @returns true if the specific string matches the general pattern
|
|
353
|
+
*/
|
|
354
|
+
function matchesPattern(general, specific) {
|
|
355
|
+
const regex = new RegExp("^" + general.replace(/\*/g, ".*") + "$");
|
|
356
|
+
return regex.test(specific);
|
|
357
|
+
}
|
|
358
|
+
//# sourceMappingURL=shrink.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shrink.js","sourceRoot":"","sources":["../../src/shrink.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { ShrinkOptions } from "./shrink.js";
|
|
2
|
+
/**
|
|
3
|
+
* Takes any JSON document and shrinks any Action or NotAction array of strings in the document.
|
|
4
|
+
* *MODIFIES THE DOCUMENT IN PLACE*
|
|
5
|
+
*
|
|
6
|
+
* @param options the options to use when shrinking the actions
|
|
7
|
+
* @param document the JSON document to expand
|
|
8
|
+
* @param key the key of the current node in the document
|
|
9
|
+
* @returns the original JSON document with any actions expanded in place
|
|
10
|
+
*/
|
|
11
|
+
export declare function shrinkJsonDocument(options: Partial<ShrinkOptions>, document: any, key?: string): Promise<any>;
|
|
12
|
+
//# sourceMappingURL=shrink_file.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shrink_file.d.ts","sourceRoot":"","sources":["../../src/shrink_file.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAU,MAAM,aAAa,CAAC;AAEpD;;;;;;;;GAQG;AACH,wBAAsB,kBAAkB,CAAC,OAAO,EAAE,OAAO,CAAC,aAAa,CAAC,EAAE,QAAQ,EAAE,GAAG,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,CA0BnH"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.shrinkJsonDocument = shrinkJsonDocument;
|
|
4
|
+
const shrink_js_1 = require("./shrink.js");
|
|
5
|
+
/**
|
|
6
|
+
* Takes any JSON document and shrinks any Action or NotAction array of strings in the document.
|
|
7
|
+
* *MODIFIES THE DOCUMENT IN PLACE*
|
|
8
|
+
*
|
|
9
|
+
* @param options the options to use when shrinking the actions
|
|
10
|
+
* @param document the JSON document to expand
|
|
11
|
+
* @param key the key of the current node in the document
|
|
12
|
+
* @returns the original JSON document with any actions expanded in place
|
|
13
|
+
*/
|
|
14
|
+
async function shrinkJsonDocument(options, document, key) {
|
|
15
|
+
if (key === 'Action' || key === 'NotAction') {
|
|
16
|
+
// if (typeof document === 'string') {
|
|
17
|
+
// // return shrink([document], options);
|
|
18
|
+
// }
|
|
19
|
+
if (Array.isArray(document) && document.length > 0 && typeof document[0] === 'string') {
|
|
20
|
+
return (0, shrink_js_1.shrink)(document, options);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
if (Array.isArray(document)) {
|
|
24
|
+
const results = [];
|
|
25
|
+
for (const item of document) {
|
|
26
|
+
results.push(await shrinkJsonDocument(options, item));
|
|
27
|
+
}
|
|
28
|
+
return results;
|
|
29
|
+
}
|
|
30
|
+
if (typeof document === 'object' && document !== null) {
|
|
31
|
+
for (const key of Object.keys(document)) {
|
|
32
|
+
document[key] = await shrinkJsonDocument(options, document[key], key);
|
|
33
|
+
}
|
|
34
|
+
return document;
|
|
35
|
+
}
|
|
36
|
+
return document;
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=shrink_file.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shrink_file.js","sourceRoot":"","sources":["../../src/shrink_file.ts"],"names":[],"mappings":";;AAWA,gDA0BC;AArCD,2CAAoD;AAEpD;;;;;;;;GAQG;AACI,KAAK,UAAU,kBAAkB,CAAC,OAA+B,EAAE,QAAa,EAAE,GAAY;IACnG,IAAI,GAAG,KAAK,QAAQ,IAAI,GAAG,KAAK,WAAW,EAAE,CAAC;QAC5C,sCAAsC;QACtC,2CAA2C;QAC3C,IAAI;QACJ,IAAI,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,IAAI,OAAO,QAAQ,CAAC,CAAC,CAAC,KAAK,QAAQ,EAAE,CAAC;YACtF,OAAO,IAAA,kBAAM,EAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;QACnC,CAAC;IACH,CAAC;IAED,IAAI,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC5B,MAAM,OAAO,GAAG,EAAE,CAAC;QACnB,KAAK,MAAM,IAAI,IAAI,QAAQ,EAAE,CAAC;YAC5B,OAAO,CAAC,IAAI,CAAC,MAAM,kBAAkB,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC,CAAC;QACxD,CAAC;QACD,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,IAAI,OAAO,QAAQ,KAAK,QAAQ,IAAI,QAAQ,KAAK,IAAI,EAAE,CAAC;QACtD,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC;YACxC,QAAQ,CAAC,GAAG,CAAC,GAAG,MAAM,kBAAkB,CAAC,OAAO,EAAE,QAAQ,CAAC,GAAG,CAAC,EAAE,GAAG,CAAC,CAAC;QACxE,CAAC;QACD,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED,OAAO,QAAQ,CAAC;AAClB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stdin.d.ts","sourceRoot":"","sources":["../../src/stdin.ts"],"names":[],"mappings":"AACA;;;;GAIG;AACH,wBAAsB,SAAS,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAAC,MAAM,CAAC,CA2B7E"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.readStdin = readStdin;
|
|
4
|
+
const process_1 = require("process");
|
|
5
|
+
/**
|
|
6
|
+
* Read from stdin until the stream ends, timeout, or an error occurs
|
|
7
|
+
*
|
|
8
|
+
* @returns the string input from stdin
|
|
9
|
+
*/
|
|
10
|
+
async function readStdin(readWait) {
|
|
11
|
+
return new Promise((resolve, reject) => {
|
|
12
|
+
// If the input is not a TTY, we are most likely receiving data from a pipe.
|
|
13
|
+
const definitelyReceivingData = !process.stdin.isTTY;
|
|
14
|
+
if (!readWait || readWait <= 0) {
|
|
15
|
+
readWait = definitelyReceivingData ? 10_000 : 20;
|
|
16
|
+
}
|
|
17
|
+
let data = '';
|
|
18
|
+
setTimeout(() => {
|
|
19
|
+
if (data.length === 0) {
|
|
20
|
+
resolve(data);
|
|
21
|
+
}
|
|
22
|
+
}, readWait);
|
|
23
|
+
process_1.stdin.on('data', (chunk) => {
|
|
24
|
+
data += chunk;
|
|
25
|
+
});
|
|
26
|
+
process_1.stdin.on('end', () => {
|
|
27
|
+
resolve(data);
|
|
28
|
+
});
|
|
29
|
+
process_1.stdin.on('error', (err) => {
|
|
30
|
+
reject(err);
|
|
31
|
+
});
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=stdin.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stdin.js","sourceRoot":"","sources":["../../src/stdin.ts"],"names":[],"mappings":";;AAMA,8BA2BC;AAjCD,qCAAgC;AAChC;;;;GAIG;AACI,KAAK,UAAU,SAAS,CAAC,QAA4B;IAC1D,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACrC,4EAA4E;QAC5E,MAAM,uBAAuB,GAAG,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,CAAA;QACpD,IAAG,CAAC,QAAQ,IAAI,QAAQ,IAAI,CAAC,EAAE,CAAC;YAC9B,QAAQ,GAAG,uBAAuB,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAA;QAClD,CAAC;QAED,IAAI,IAAI,GAAG,EAAE,CAAC;QACd,UAAU,CAAC,GAAG,EAAE;YACd,IAAG,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBACrB,OAAO,CAAC,IAAI,CAAC,CAAA;YACf,CAAC;QACH,CAAC,EAAE,QAAQ,CAAC,CAAA;QAEZ,eAAK,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,KAAK,EAAE,EAAE;YACzB,IAAI,IAAI,KAAK,CAAC;QAChB,CAAC,CAAC,CAAC;QAEH,eAAK,CAAC,EAAE,CAAC,KAAK,EAAE,GAAG,EAAE;YACnB,OAAO,CAAC,IAAI,CAAC,CAAC;QAChB,CAAC,CAAC,CAAC;QAEH,eAAK,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,GAAG,EAAE,EAAE;YACxB,MAAM,CAAC,GAAG,CAAC,CAAC;QACd,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Checks a list of patterns against a list of desired actions to validate:
|
|
3
|
+
* * All desired actions are matched by the patterns
|
|
4
|
+
* * No undesired actions are matched by the patterns
|
|
5
|
+
*
|
|
6
|
+
* @param desiredActions The actions that should be in the list
|
|
7
|
+
* @param patterns The list of patterns that the algorithm has derived
|
|
8
|
+
* @returns the first match error if any, otherwise undefined
|
|
9
|
+
*/
|
|
10
|
+
export declare function validateShrinkResults(desiredActions: string[], patterns: string[]): Promise<string | undefined>;
|
|
11
|
+
//# sourceMappingURL=validate.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validate.d.ts","sourceRoot":"","sources":["../../src/validate.ts"],"names":[],"mappings":"AAEA;;;;;;;;GAQG;AACH,wBAAsB,qBAAqB,CAAC,cAAc,EAAE,MAAM,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAiBrH"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.validateShrinkResults = validateShrinkResults;
|
|
4
|
+
const iam_expand_1 = require("@cloud-copilot/iam-expand");
|
|
5
|
+
/**
|
|
6
|
+
* Checks a list of patterns against a list of desired actions to validate:
|
|
7
|
+
* * All desired actions are matched by the patterns
|
|
8
|
+
* * No undesired actions are matched by the patterns
|
|
9
|
+
*
|
|
10
|
+
* @param desiredActions The actions that should be in the list
|
|
11
|
+
* @param patterns The list of patterns that the algorithm has derived
|
|
12
|
+
* @returns the first match error if any, otherwise undefined
|
|
13
|
+
*/
|
|
14
|
+
async function validateShrinkResults(desiredActions, patterns) {
|
|
15
|
+
const desiredActionSet = new Set(desiredActions);
|
|
16
|
+
const expandedAfterActions = await (0, iam_expand_1.expandIamActions)(patterns, { expandServiceAsterisk: true });
|
|
17
|
+
const expandedAfterActionSet = new Set(expandedAfterActions);
|
|
18
|
+
for (const afterAction of expandedAfterActions) {
|
|
19
|
+
if (!desiredActionSet.has(afterAction)) {
|
|
20
|
+
return `Undesired action: ${afterAction}`;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
for (const desiredAction of desiredActions) {
|
|
24
|
+
if (!expandedAfterActionSet.has(desiredAction)) {
|
|
25
|
+
return `Missing action ${desiredAction}`;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
return undefined;
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=validate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validate.js","sourceRoot":"","sources":["../../src/validate.ts"],"names":[],"mappings":";;AAWA,sDAiBC;AA5BD,0DAA6D;AAE7D;;;;;;;;GAQG;AACI,KAAK,UAAU,qBAAqB,CAAC,cAAwB,EAAE,QAAkB;IACtF,MAAM,gBAAgB,GAAG,IAAI,GAAG,CAAC,cAAc,CAAC,CAAC;IACjD,MAAM,oBAAoB,GAAG,MAAM,IAAA,6BAAgB,EAAC,QAAQ,EAAE,EAAC,qBAAqB,EAAE,IAAI,EAAC,CAAC,CAAC;IAC7F,MAAM,sBAAsB,GAAG,IAAI,GAAG,CAAC,oBAAoB,CAAC,CAAC;IAC7D,KAAI,MAAM,WAAW,IAAI,oBAAoB,EAAE,CAAC;QAC9C,IAAG,CAAC,gBAAgB,CAAC,GAAG,CAAC,WAAW,CAAC,EAAE,CAAC;YACtC,OAAO,qBAAqB,WAAW,EAAE,CAAC;QAC5C,CAAC;IACH,CAAC;IAED,KAAI,MAAM,aAAa,IAAI,cAAc,EAAE,CAAC;QAC1C,IAAG,CAAC,sBAAsB,CAAC,GAAG,CAAC,aAAa,CAAC,EAAE,CAAC;YAC9C,OAAO,kBAAkB,aAAa,EAAE,CAAA;QAC1C,CAAC;IACH,CAAC;IAED,OAAO,SAAS,CAAC;AACnB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../../src/cli.ts"],"names":[],"mappings":""}
|
package/dist/esm/cli.js
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { iamDataUpdatedAt, iamDataVersion } from "@cloud-copilot/iam-data";
|
|
2
|
+
import { convertOptions, parseStdIn } from "./cli_utils.js";
|
|
3
|
+
import { shrink } from "./shrink.js";
|
|
4
|
+
const commandName = 'iam-shrink';
|
|
5
|
+
const dataPackage = '@cloud-copilot/iam-data';
|
|
6
|
+
async function shrinkAandPrint(actions, shrinkOptions) {
|
|
7
|
+
try {
|
|
8
|
+
const result = await shrink(actions, shrinkOptions);
|
|
9
|
+
for (const action of result) {
|
|
10
|
+
console.log(action);
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
catch (e) {
|
|
14
|
+
console.error(e.message);
|
|
15
|
+
process.exit(1);
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
function printUsage() {
|
|
19
|
+
console.log('No arguments provided or input from stdin');
|
|
20
|
+
console.log('Usage:');
|
|
21
|
+
console.log(` ${commandName} [options] [action1] [action2] ...`);
|
|
22
|
+
console.log(` <input from stdout> | ${commandName} [options]`);
|
|
23
|
+
console.log('Shrink ActionOptions:');
|
|
24
|
+
console.log(' --iterations: How many iterations of shrinking should be executed, defaults to 2; zero or less means no limit');
|
|
25
|
+
console.log(' Example: --iterations=5');
|
|
26
|
+
console.log(' Example: --iterations=-1');
|
|
27
|
+
console.log('CLI Behavior Options:');
|
|
28
|
+
console.log(' --show-data-version: Print the version of the iam-data package being used and exit');
|
|
29
|
+
console.log(' --read-wait-ms: Millisenconds to wait for the first byte from stdin before timing out.');
|
|
30
|
+
console.log(' Example: --read-wait-ms=10_000');
|
|
31
|
+
process.exit(1);
|
|
32
|
+
}
|
|
33
|
+
const args = process.argv.slice(2); // Ignore the first two elements
|
|
34
|
+
const actionStrings = [];
|
|
35
|
+
const optionStrings = [];
|
|
36
|
+
for (const arg of args) {
|
|
37
|
+
if (arg.startsWith('--')) {
|
|
38
|
+
optionStrings.push(arg);
|
|
39
|
+
}
|
|
40
|
+
else {
|
|
41
|
+
actionStrings.push(arg);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
async function run() {
|
|
45
|
+
const options = convertOptions(optionStrings);
|
|
46
|
+
if (options.showDataVersion) {
|
|
47
|
+
const version = await iamDataVersion();
|
|
48
|
+
console.log(`${dataPackage} version: ${version}`);
|
|
49
|
+
console.log(`Data last updated: ${await iamDataUpdatedAt()}`);
|
|
50
|
+
console.log(`Update with either:`);
|
|
51
|
+
console.log(` npm update ${dataPackage}`);
|
|
52
|
+
console.log(` npm update -g ${dataPackage}`);
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
if (actionStrings.length === 0) {
|
|
56
|
+
//If no actions are provided, read from stdin
|
|
57
|
+
const stdInResult = await parseStdIn(options);
|
|
58
|
+
if (stdInResult.object) {
|
|
59
|
+
console.log(JSON.stringify(stdInResult.object, null, 2));
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
else if (stdInResult.strings) {
|
|
63
|
+
actionStrings.push(...stdInResult.strings);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
if (actionStrings.length > 0) {
|
|
67
|
+
await shrinkAandPrint(actionStrings, options);
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
printUsage();
|
|
71
|
+
}
|
|
72
|
+
run().catch((e) => {
|
|
73
|
+
console.error(e);
|
|
74
|
+
process.exit(1);
|
|
75
|
+
}).then(() => process.exit(0)).finally(() => { });
|
|
76
|
+
//# sourceMappingURL=cli.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../../src/cli.ts"],"names":[],"mappings":"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"}
|