@cloud-copilot/iam-expand 0.1.4 → 0.1.5
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 +84 -20
- package/dist/cjs/cli.js +17 -9
- package/dist/cjs/cli.js.map +1 -1
- package/dist/cjs/cli_utils.d.ts +4 -1
- package/dist/cjs/cli_utils.d.ts.map +1 -1
- package/dist/cjs/cli_utils.js +10 -4
- package/dist/cjs/cli_utils.js.map +1 -1
- package/dist/cjs/expand.d.ts +3 -3
- package/dist/cjs/expand.d.ts.map +1 -1
- package/dist/cjs/expand.js +26 -15
- package/dist/cjs/expand.js.map +1 -1
- package/dist/cjs/expand_file.d.ts +11 -0
- package/dist/cjs/expand_file.d.ts.map +1 -0
- package/dist/cjs/expand_file.js +39 -0
- package/dist/cjs/expand_file.js.map +1 -0
- package/dist/esm/cli.js +18 -10
- package/dist/esm/cli.js.map +1 -1
- package/dist/esm/cli_utils.d.ts +4 -1
- package/dist/esm/cli_utils.d.ts.map +1 -1
- package/dist/esm/cli_utils.js +9 -3
- package/dist/esm/cli_utils.js.map +1 -1
- package/dist/esm/expand.d.ts +3 -3
- package/dist/esm/expand.d.ts.map +1 -1
- package/dist/esm/expand.js +26 -15
- package/dist/esm/expand.js.map +1 -1
- package/dist/esm/expand_file.d.ts +11 -0
- package/dist/esm/expand_file.d.ts.map +1 -0
- package/dist/esm/expand_file.js +36 -0
- package/dist/esm/expand_file.js.map +1 -0
- package/package.json +4 -3
- package/src/cli.ts +17 -10
- package/src/cli_utils.test.ts +26 -11
- package/src/cli_utils.ts +10 -4
- package/src/expand.test.ts +112 -106
- package/src/expand.ts +30 -19
- package/src/expand_file.test.ts +107 -0
- package/src/expand_file.ts +39 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli_utils.js","sourceRoot":"","sources":["../../src/cli_utils.ts"],"names":[],"mappings":"AACA,OAAO,EAA2B,qBAAqB,EAAE,MAAM,aAAa,CAAC;AAC7E,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAOvC;;;;GAIG;AACH,MAAM,UAAU,eAAe,CAAC,GAAW;IACzC,GAAG,GAAG,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,CAAA;IACtB,OAAO,GAAG,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC;AAC7D,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,cAAc,CAAC,UAAoB;IACjD,MAAM,OAAO,GAAqC,EAAE,CAAE;IAEtD,KAAI,MAAM,MAAM,IAAI,UAAU,EAAE,CAAC;QAC/B,IAAI,GAAG,GAAW,MAAM,CAAA;QACxB,IAAI,KAAK,GAAqB,IAAI,CAAA;QAClC,IAAG,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;YACxB,CAAC,GAAG,EAAC,KAAK,CAAC,GAAG,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;QACjC,CAAC;QAED,OAAO,CAAC,eAAe,CAAC,GAAG,CAAC,CAAC,GAAG,KAAK,CAAA;IACvC,CAAC;IAED,IAAG,OAAM,CAAC,OAAO,CAAC,qBAAqB,CAAC,KAAK,QAAQ,EAAE,CAAC;QACtD,MAAM,cAAc,GAAG,OAAO,CAAC,qBAA+B,CAAA;QAC9D,MAAM,YAAY,GAAG,cAAc,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,GAAG,cAAc,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC;QACpG,MAAM,QAAQ,GAAG,qBAAqB,CAAC,YAAkD,CAAC,CAAC;QAC3F,IAAG,QAAQ,EAAE,CAAC;YACZ,OAAO,CAAC,qBAAqB,GAAG,QAAQ,CAAA;QAC1C,CAAC;aAAM,CAAC;YACN,OAAO,OAAO,CAAC,uBAAuB,CAAC,CAAA;QACzC,CAAC;IACH,CAAC;IAED,OAAO,OAAO,CAAA;AAChB,CAAC;AAED,MAAM,aAAa,GAAG,mCAAmC,CAAC;AAC1D,MAAM,UAAU,6BAA6B,CAAC,IAAY;IACxD,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAA;IAE5C,OAAO,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC;SACb,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC;SAC5E,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAA;AACvC,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,
|
|
1
|
+
{"version":3,"file":"cli_utils.js","sourceRoot":"","sources":["../../src/cli_utils.ts"],"names":[],"mappings":"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"}
|
package/dist/esm/expand.d.ts
CHANGED
|
@@ -13,13 +13,13 @@ export interface ExpandIamActionsOptions {
|
|
|
13
13
|
* If false, a single `*` will be returned as is
|
|
14
14
|
* Default: false
|
|
15
15
|
*/
|
|
16
|
-
|
|
16
|
+
expandAsterisk: boolean;
|
|
17
17
|
/**
|
|
18
18
|
* If true, `service:*` will be expanded to all actions for that service
|
|
19
19
|
* If false, `service:*` will be returned as is
|
|
20
20
|
* Default: false
|
|
21
21
|
*/
|
|
22
|
-
|
|
22
|
+
expandServiceAsterisk: boolean;
|
|
23
23
|
/**
|
|
24
24
|
* If true, an error will be thrown if the action string is not in the correct format
|
|
25
25
|
* If false, an empty array will be returned
|
|
@@ -65,5 +65,5 @@ export interface ExpandIamActionsOptions {
|
|
|
65
65
|
* @param overrideOptions Options to override the default behavior
|
|
66
66
|
* @returns An array of expanded action strings flattend to a single array
|
|
67
67
|
*/
|
|
68
|
-
export declare function expandIamActions(actionStringOrStrings: string | string[], overrideOptions?: Partial<ExpandIamActionsOptions>): string[]
|
|
68
|
+
export declare function expandIamActions(actionStringOrStrings: string | string[], overrideOptions?: Partial<ExpandIamActionsOptions>): Promise<string[]>;
|
|
69
69
|
//# sourceMappingURL=expand.d.ts.map
|
package/dist/esm/expand.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"expand.d.ts","sourceRoot":"","sources":["../../src/expand.ts"],"names":[],"mappings":"AAEA,oBAAY,qBAAqB;IAC/B,MAAM,WAAW;IACjB,KAAK,UAAU;IACf,OAAO,YAAY;CACpB;AAED;;;GAGG;AACH,MAAM,WAAW,uBAAuB;IACtC;;;;OAIG;IACH,
|
|
1
|
+
{"version":3,"file":"expand.d.ts","sourceRoot":"","sources":["../../src/expand.ts"],"names":[],"mappings":"AAEA,oBAAY,qBAAqB;IAC/B,MAAM,WAAW;IACjB,KAAK,UAAU;IACf,OAAO,YAAY;CACpB;AAED;;;GAGG;AACH,MAAM,WAAW,uBAAuB;IACtC;;;;OAIG;IACH,cAAc,EAAE,OAAO,CAAA;IAEvB;;;;OAIG;IACH,qBAAqB,EAAE,OAAO,CAAA;IAE9B;;;;OAIG;IACH,oBAAoB,EAAE,OAAO,CAAA;IAE7B;;;;OAIG;IACH,qBAAqB,EAAE,OAAO,CAAA;IAE9B;;;;OAIG;IACH,QAAQ,EAAE,OAAO,CAAA;IAGjB;;;;;;;OAOG;IACH,qBAAqB,EAAE,qBAAqB,CAAA;IAE5C;;;;OAIG;IACH,IAAI,EAAE,OAAO,CAAA;CACd;AAcD;;;;;;;;;;GAUG;AACH,wBAAsB,gBAAgB,CAAC,qBAAqB,EAAE,MAAM,GAAG,MAAM,EAAE,EAAE,eAAe,CAAC,EAAE,OAAO,CAAC,uBAAuB,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CA0GtJ"}
|
package/dist/esm/expand.js
CHANGED
|
@@ -6,15 +6,15 @@ export var InvalidActionBehavior;
|
|
|
6
6
|
InvalidActionBehavior["Include"] = "Include";
|
|
7
7
|
})(InvalidActionBehavior || (InvalidActionBehavior = {}));
|
|
8
8
|
const defaultOptions = {
|
|
9
|
-
|
|
10
|
-
|
|
9
|
+
expandAsterisk: false,
|
|
10
|
+
expandServiceAsterisk: false,
|
|
11
11
|
errorOnInvalidFormat: false,
|
|
12
12
|
errorOnMissingService: false,
|
|
13
13
|
invalidActionBehavior: InvalidActionBehavior.Remove,
|
|
14
14
|
distinct: false,
|
|
15
15
|
sort: false
|
|
16
16
|
};
|
|
17
|
-
const
|
|
17
|
+
const allAsterisksPattern = /^\*+$/i;
|
|
18
18
|
/**
|
|
19
19
|
* Expands an IAM action string that contains wildcards.
|
|
20
20
|
* If the action string contains no wildcards, it is returned as is.
|
|
@@ -26,14 +26,17 @@ const allAsteriksPattern = /^\*+$/i;
|
|
|
26
26
|
* @param overrideOptions Options to override the default behavior
|
|
27
27
|
* @returns An array of expanded action strings flattend to a single array
|
|
28
28
|
*/
|
|
29
|
-
export function expandIamActions(actionStringOrStrings, overrideOptions) {
|
|
29
|
+
export async function expandIamActions(actionStringOrStrings, overrideOptions) {
|
|
30
30
|
const options = { ...defaultOptions, ...overrideOptions };
|
|
31
31
|
if (!actionStringOrStrings) {
|
|
32
32
|
//Just in case the user passes in null or undefined
|
|
33
33
|
return [];
|
|
34
34
|
}
|
|
35
35
|
if (Array.isArray(actionStringOrStrings)) {
|
|
36
|
-
|
|
36
|
+
const actionLists = await Promise.all(actionStringOrStrings.map(async (actionString) => {
|
|
37
|
+
return expandIamActions(actionString, options);
|
|
38
|
+
}));
|
|
39
|
+
let allMatches = actionLists.flat();
|
|
37
40
|
if (options.distinct) {
|
|
38
41
|
const aSet = new Set();
|
|
39
42
|
allMatches = allMatches.filter((value) => {
|
|
@@ -50,10 +53,16 @@ export function expandIamActions(actionStringOrStrings, overrideOptions) {
|
|
|
50
53
|
return allMatches;
|
|
51
54
|
}
|
|
52
55
|
const actionString = actionStringOrStrings.trim();
|
|
53
|
-
if (actionString.match(
|
|
54
|
-
if (options.
|
|
56
|
+
if (actionString.match(allAsterisksPattern)) {
|
|
57
|
+
if (options.expandAsterisk) {
|
|
55
58
|
//If that's really what you want...
|
|
56
|
-
|
|
59
|
+
const allActions = [];
|
|
60
|
+
const serviceKeys = await iamServiceKeys();
|
|
61
|
+
for await (const service of serviceKeys) {
|
|
62
|
+
const serviceActions = await iamActionsForService(service);
|
|
63
|
+
allActions.push(...serviceActions.map(action => `${service}:${action}`));
|
|
64
|
+
}
|
|
65
|
+
return allActions;
|
|
57
66
|
}
|
|
58
67
|
return ['*'];
|
|
59
68
|
}
|
|
@@ -71,22 +80,24 @@ export function expandIamActions(actionStringOrStrings, overrideOptions) {
|
|
|
71
80
|
return [];
|
|
72
81
|
}
|
|
73
82
|
const [service, wildcardActions] = parts.map(part => part.toLowerCase());
|
|
74
|
-
if (!iamServiceExists(service)) {
|
|
83
|
+
if (!await iamServiceExists(service)) {
|
|
75
84
|
if (options.errorOnMissingService) {
|
|
76
85
|
throw new Error(`Service not found: ${service}`);
|
|
77
86
|
}
|
|
78
87
|
return [];
|
|
79
88
|
}
|
|
80
|
-
if (wildcardActions.match(
|
|
81
|
-
if (options.
|
|
82
|
-
|
|
89
|
+
if (wildcardActions.match(allAsterisksPattern)) {
|
|
90
|
+
if (options.expandServiceAsterisk) {
|
|
91
|
+
const actionsForService = await iamActionsForService(service);
|
|
92
|
+
return actionsForService.map(action => `${service}:${action}`);
|
|
83
93
|
}
|
|
84
94
|
return [`${service}:*`];
|
|
85
95
|
}
|
|
86
96
|
if (!actionString.includes('*')) {
|
|
87
|
-
const actionExists = iamActionExists(service, wildcardActions);
|
|
97
|
+
const actionExists = await iamActionExists(service, wildcardActions);
|
|
88
98
|
if (actionExists) {
|
|
89
|
-
|
|
99
|
+
const details = await iamActionDetails(service, wildcardActions);
|
|
100
|
+
return [service + ":" + details.name];
|
|
90
101
|
}
|
|
91
102
|
if (options.invalidActionBehavior === InvalidActionBehavior.Remove) {
|
|
92
103
|
return [];
|
|
@@ -102,7 +113,7 @@ export function expandIamActions(actionStringOrStrings, overrideOptions) {
|
|
|
102
113
|
throw new Error(`Invalid invalidActionBehavior: ${options.invalidActionBehavior}`);
|
|
103
114
|
}
|
|
104
115
|
}
|
|
105
|
-
const allActions = iamActionsForService(service);
|
|
116
|
+
const allActions = await iamActionsForService(service);
|
|
106
117
|
const pattern = "^" + wildcardActions.replace(/\*/g, '.*?') + "$";
|
|
107
118
|
const regex = new RegExp(pattern, 'i');
|
|
108
119
|
const matchingActions = allActions.filter(action => regex.test(action)).map(action => `${service}:${action}`);
|
package/dist/esm/expand.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"expand.js","sourceRoot":"","sources":["../../src/expand.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,eAAe,EAAE,oBAAoB,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAA;AAEnI,MAAM,CAAN,IAAY,qBAIX;AAJD,WAAY,qBAAqB;IAC/B,0CAAiB,CAAA;IACjB,wCAAe,CAAA;IACf,4CAAmB,CAAA;AACrB,CAAC,EAJW,qBAAqB,KAArB,qBAAqB,QAIhC;AA6DD,MAAM,cAAc,GAA4B;IAC9C,
|
|
1
|
+
{"version":3,"file":"expand.js","sourceRoot":"","sources":["../../src/expand.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { ExpandIamActionsOptions } from "./expand.js";
|
|
2
|
+
/**
|
|
3
|
+
* Takes any JSON document and expands any Action found in the document
|
|
4
|
+
*
|
|
5
|
+
* @param options the options to use when expanding the actions
|
|
6
|
+
* @param document the JSON document to expand
|
|
7
|
+
* @param key the key of the current node in the document
|
|
8
|
+
* @returns the expanded JSON document
|
|
9
|
+
*/
|
|
10
|
+
export declare function expandJsonDocument(options: Partial<ExpandIamActionsOptions>, document: any, key?: string): Promise<any>;
|
|
11
|
+
//# sourceMappingURL=expand_file.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"expand_file.d.ts","sourceRoot":"","sources":["../../src/expand_file.ts"],"names":[],"mappings":"AAAA,OAAO,EAAoB,uBAAuB,EAAE,MAAM,aAAa,CAAA;AAEvE;;;;;;;GAOG;AACH,wBAAsB,kBAAkB,CAAC,OAAO,EAAE,OAAO,CAAC,uBAAuB,CAAC,EAAE,QAAQ,EAAE,GAAG,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,CA4B7H"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { expandIamActions } from "./expand.js";
|
|
2
|
+
/**
|
|
3
|
+
* Takes any JSON document and expands any Action found in the document
|
|
4
|
+
*
|
|
5
|
+
* @param options the options to use when expanding the actions
|
|
6
|
+
* @param document the JSON document to expand
|
|
7
|
+
* @param key the key of the current node in the document
|
|
8
|
+
* @returns the expanded JSON document
|
|
9
|
+
*/
|
|
10
|
+
export async function expandJsonDocument(options, document, key) {
|
|
11
|
+
if (key === 'Action') {
|
|
12
|
+
if (typeof document === 'string') {
|
|
13
|
+
return await expandIamActions(document, options);
|
|
14
|
+
}
|
|
15
|
+
if (Array.isArray(document) && document.length > 0 && typeof document[0] === 'string') {
|
|
16
|
+
const value = await expandIamActions(document, { ...options, distinct: true });
|
|
17
|
+
return value;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
if (Array.isArray(document)) {
|
|
21
|
+
return Promise.all(document.map(async (item) => {
|
|
22
|
+
return expandJsonDocument(options, item);
|
|
23
|
+
}));
|
|
24
|
+
}
|
|
25
|
+
if (typeof document === 'object') {
|
|
26
|
+
const keys = Object.keys(document);
|
|
27
|
+
const newObject = {};
|
|
28
|
+
for (const key of keys) {
|
|
29
|
+
const value = document[key];
|
|
30
|
+
newObject[key] = await expandJsonDocument(options, value, key);
|
|
31
|
+
}
|
|
32
|
+
return newObject;
|
|
33
|
+
}
|
|
34
|
+
return document;
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=expand_file.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"expand_file.js","sourceRoot":"","sources":["../../src/expand_file.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAA2B,MAAM,aAAa,CAAA;AAEvE;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,kBAAkB,CAAC,OAAyC,EAAE,QAAa,EAAE,GAAY;IAC7G,IAAG,GAAG,KAAK,QAAQ,EAAE,CAAC;QACpB,IAAG,OAAO,QAAQ,KAAK,QAAQ,EAAE,CAAC;YAChC,OAAO,MAAM,gBAAgB,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAA;QAClD,CAAC;QACD,IAAG,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,IAAI,OAAO,QAAQ,CAAC,CAAC,CAAC,KAAK,QAAQ,EAAE,CAAC;YACrF,MAAM,KAAK,GAAI,MAAM,gBAAgB,CAAC,QAAQ,EAAE,EAAC,GAAG,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAC,CAAC,CAAA;YAC7E,OAAO,KAAK,CAAA;QACd,CAAC;IACH,CAAC;IAED,IAAG,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC3B,OAAO,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE;YAC7C,OAAO,kBAAkB,CAAC,OAAO,EAAE,IAAI,CAAC,CAAA;QAC1C,CAAC,CAAC,CAAC,CAAA;IACL,CAAC;IAED,IAAG,OAAO,QAAQ,KAAK,QAAQ,EAAE,CAAC;QAChC,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAA;QAClC,MAAM,SAAS,GAAQ,EAAE,CAAA;QACzB,KAAI,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;YACtB,MAAM,KAAK,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAA;YAC3B,SAAS,CAAC,GAAG,CAAC,GAAG,MAAM,kBAAkB,CAAC,OAAO,EAAE,KAAK,EAAE,GAAG,CAAC,CAAA;QAChE,CAAC;QACD,OAAO,SAAS,CAAA;IAClB,CAAC;IAED,OAAO,QAAQ,CAAA;AACjB,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cloud-copilot/iam-expand",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.5",
|
|
4
4
|
"description": "Expand AWS IAM Actions with Wildcards",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
},
|
|
19
19
|
"scripts": {
|
|
20
20
|
"build": "npx tsc -p tsconfig.cjs.json && npx tsc -p tsconfig.esm.json && ./postbuild.sh",
|
|
21
|
-
"test": "npx vitest --run",
|
|
21
|
+
"test": "npx vitest --run --coverage",
|
|
22
22
|
"prepare": "npm run build"
|
|
23
23
|
},
|
|
24
24
|
"keywords": [
|
|
@@ -33,10 +33,11 @@
|
|
|
33
33
|
"homepage": "https://github.com/cloud-copilot/iam-expand#readme",
|
|
34
34
|
"devDependencies": {
|
|
35
35
|
"@types/node": "^22.5.0",
|
|
36
|
+
"@vitest/coverage-v8": "^2.0.5",
|
|
36
37
|
"typescript": "^5.5.4",
|
|
37
38
|
"vitest": "^2.0.5"
|
|
38
39
|
},
|
|
39
40
|
"peerDependencies": {
|
|
40
|
-
"@cloud-copilot/iam-data": ">=0.
|
|
41
|
+
"@cloud-copilot/iam-data": ">=0.3.0 <1.0.0"
|
|
41
42
|
}
|
|
42
43
|
}
|
package/src/cli.ts
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
import { iamDataVersion } from "@cloud-copilot/iam-data";
|
|
4
|
-
import { convertOptions,
|
|
4
|
+
import { convertOptions, parseStdIn } from "./cli_utils.js";
|
|
5
5
|
import { expandIamActions, ExpandIamActionsOptions } from "./expand.js";
|
|
6
6
|
|
|
7
7
|
const commandName = 'iam-expand'
|
|
8
8
|
|
|
9
|
-
function expandAndPrint(actionStrings: string[], options: Partial<ExpandIamActionsOptions>) {
|
|
9
|
+
async function expandAndPrint(actionStrings: string[], options: Partial<ExpandIamActionsOptions>) {
|
|
10
10
|
try {
|
|
11
|
-
const result = expandIamActions(actionStrings, options)
|
|
11
|
+
const result = await expandIamActions(actionStrings, options)
|
|
12
12
|
for (const action of result) {
|
|
13
13
|
console.log(action)
|
|
14
14
|
}
|
|
@@ -26,8 +26,8 @@ function printUsage() {
|
|
|
26
26
|
console.log('Action Expanding Options:')
|
|
27
27
|
console.log(' --distinct: Remove duplicate actions')
|
|
28
28
|
console.log(' --sort: Sort the actions')
|
|
29
|
-
console.log(' --expand-
|
|
30
|
-
console.log(' --expand-service-
|
|
29
|
+
console.log(' --expand-asterisk: Expand the * action to all actions')
|
|
30
|
+
console.log(' --expand-service-asterisk: Expand service:* to all actions for that service')
|
|
31
31
|
console.log(' --error-on-missing-service: Throw an error if a service is not found')
|
|
32
32
|
console.log(' --error-on-invalid-format: Throw an error if the action string is not in the correct format')
|
|
33
33
|
console.log(' --invalid-action-behavior: What to do when an invalid action is encountered:')
|
|
@@ -61,15 +61,22 @@ async function run() {
|
|
|
61
61
|
}
|
|
62
62
|
|
|
63
63
|
if(actionStrings.length === 0) {
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
64
|
+
//If no actions are provided, read from stdin
|
|
65
|
+
const stdInResult = await parseStdIn(options)
|
|
66
|
+
if(stdInResult.object) {
|
|
67
|
+
console.log(JSON.stringify(stdInResult.object, null, 2))
|
|
68
|
+
return
|
|
69
|
+
} else if (stdInResult.strings) {
|
|
70
|
+
const otherActions = stdInResult.strings
|
|
71
|
+
if(otherActions.length > 0 && options.expandAsterisk) {
|
|
72
|
+
console.warn('Notice: --expand-asterisk is not supported when reading from stdin, ignoring.')
|
|
73
|
+
}
|
|
74
|
+
actionStrings.push(...otherActions)
|
|
67
75
|
}
|
|
68
|
-
actionStrings.push(...otherActions)
|
|
69
76
|
}
|
|
70
77
|
|
|
71
78
|
if(actionStrings.length > 0) {
|
|
72
|
-
expandAndPrint(actionStrings, options)
|
|
79
|
+
await expandAndPrint(actionStrings, options)
|
|
73
80
|
return
|
|
74
81
|
}
|
|
75
82
|
|
package/src/cli_utils.test.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
|
2
|
-
import { convertOptions, dashToCamelCase, extractActionsFromLineOfInput,
|
|
2
|
+
import { convertOptions, dashToCamelCase, extractActionsFromLineOfInput, parseStdIn } from "./cli_utils";
|
|
3
3
|
import { InvalidActionBehavior } from './expand.js';
|
|
4
4
|
import { readStdin } from './stdin';
|
|
5
5
|
vi.mock('./stdin')
|
|
@@ -25,8 +25,8 @@ const extractScenarios = [
|
|
|
25
25
|
const dashToCamelCaseScenarios = [
|
|
26
26
|
{input: "--distinct", expected: "distinct"},
|
|
27
27
|
{input: "--sort", expected: "sort"},
|
|
28
|
-
{input: "--expand-
|
|
29
|
-
{input: "--expand-service-
|
|
28
|
+
{input: "--expand-asterisk", expected: "expandAsterisk"},
|
|
29
|
+
{input: "--expand-service-asterisk", expected: "expandServiceAsterisk"},
|
|
30
30
|
{input: "--error-on-missing-service", expected: "errorOnMissingService"},
|
|
31
31
|
{input: "--error-on-invalid-format", expected: "errorOnInvalidFormat"},
|
|
32
32
|
{input: "--show-data-version", expected: "showDataVersion"},
|
|
@@ -105,27 +105,42 @@ describe('cli_utils', () => {
|
|
|
105
105
|
})
|
|
106
106
|
})
|
|
107
107
|
|
|
108
|
-
describe('
|
|
109
|
-
it('should return an empty
|
|
108
|
+
describe('parseStdIn', () => {
|
|
109
|
+
it('should return an empty object if no data is provided', async () => {
|
|
110
110
|
// Given no data is provided
|
|
111
111
|
vi.mocked(readStdin).mockResolvedValue('')
|
|
112
112
|
|
|
113
113
|
// When the actions are parsed
|
|
114
|
-
const result = await
|
|
114
|
+
const result = await parseStdIn({})
|
|
115
115
|
|
|
116
|
-
// Then I should get an empty
|
|
117
|
-
expect(result).toEqual(
|
|
116
|
+
// Then I should get an empty object
|
|
117
|
+
expect(result).toEqual({})
|
|
118
118
|
})
|
|
119
119
|
|
|
120
|
-
it('should return an array of actions from the data', async () => {
|
|
120
|
+
it('should return an array of actions from the data if it cannot be parsed', async () => {
|
|
121
121
|
// Given there is data with actions in multiple lines
|
|
122
122
|
vi.mocked(readStdin).mockResolvedValue('s3:GetObject\ns3:PutObject\ns3:DeleteObject\n')
|
|
123
123
|
|
|
124
124
|
// When the actions are parsed
|
|
125
|
-
const result = await
|
|
125
|
+
const result = await parseStdIn({})
|
|
126
126
|
|
|
127
127
|
// Then I should get the expected actions
|
|
128
|
-
expect(result).toEqual(['s3:GetObject', 's3:PutObject', 's3:DeleteObject'])
|
|
128
|
+
expect(result).toEqual({strings: ['s3:GetObject', 's3:PutObject', 's3:DeleteObject']})
|
|
129
|
+
})
|
|
130
|
+
|
|
131
|
+
it('should return an object if the data can be parsed', async () => {
|
|
132
|
+
// Given there is data that can be parsed
|
|
133
|
+
const dataValue = {
|
|
134
|
+
Action: ["s3:GetObject"],
|
|
135
|
+
Version: "2012-10-17"
|
|
136
|
+
}
|
|
137
|
+
vi.mocked(readStdin).mockResolvedValue(JSON.stringify(dataValue))
|
|
138
|
+
|
|
139
|
+
// When the actions are parsed
|
|
140
|
+
const result = await parseStdIn({})
|
|
141
|
+
|
|
142
|
+
// Then I should get the expected object
|
|
143
|
+
expect(result).toEqual({object: dataValue})
|
|
129
144
|
})
|
|
130
145
|
})
|
|
131
146
|
})
|
package/src/cli_utils.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
|
|
2
2
|
import { ExpandIamActionsOptions, InvalidActionBehavior } from "./expand.js";
|
|
3
|
+
import { expandJsonDocument } from "./expand_file.js";
|
|
3
4
|
import { readStdin } from "./stdin.js";
|
|
4
5
|
|
|
5
6
|
interface CliOptions extends ExpandIamActionsOptions {
|
|
@@ -64,15 +65,20 @@ export function extractActionsFromLineOfInput(line: string): string[] {
|
|
|
64
65
|
*
|
|
65
66
|
* @returns an array of strings from stdin
|
|
66
67
|
*/
|
|
67
|
-
export async function
|
|
68
|
+
export async function parseStdIn(options: Partial<CliOptions>): Promise<{strings?: string[], object?: any}> {
|
|
68
69
|
const delay = options.readWaitTime ? parseInt(options.readWaitTime.replaceAll(/\D/g, '')) : undefined
|
|
69
70
|
const data = await readStdin(delay)
|
|
70
71
|
if(data.length === 0) {
|
|
71
|
-
return
|
|
72
|
+
return {}
|
|
72
73
|
}
|
|
73
74
|
|
|
74
|
-
|
|
75
|
+
try {
|
|
76
|
+
const object = await expandJsonDocument(options, JSON.parse(data))
|
|
77
|
+
return {object}
|
|
78
|
+
} catch (err: any) {}
|
|
79
|
+
|
|
75
80
|
|
|
81
|
+
const lines = data.split('\n')
|
|
76
82
|
const actions = lines.flatMap(line => extractActionsFromLineOfInput(line))
|
|
77
|
-
return actions
|
|
83
|
+
return {strings: actions}
|
|
78
84
|
}
|