@cloud-copilot/iam-expand 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.
Files changed (84) hide show
  1. package/LICENSE.txt +674 -0
  2. package/README.md +269 -0
  3. package/dist/cjs/cli.d.ts +3 -0
  4. package/dist/cjs/cli.d.ts.map +1 -0
  5. package/dist/cjs/cli.js +76 -0
  6. package/dist/cjs/cli.js.map +1 -0
  7. package/dist/cjs/cli_utils.d.ts +27 -0
  8. package/dist/cjs/cli_utils.d.ts.map +1 -0
  9. package/dist/cjs/cli_utils.js +69 -0
  10. package/dist/cjs/cli_utils.js.map +1 -0
  11. package/dist/cjs/expand.d.ts +69 -0
  12. package/dist/cjs/expand.d.ts.map +1 -0
  13. package/dist/cjs/expand.js +118 -0
  14. package/dist/cjs/expand.js.map +1 -0
  15. package/dist/cjs/index.d.ts +2 -0
  16. package/dist/cjs/index.d.ts.map +1 -0
  17. package/dist/cjs/index.js +18 -0
  18. package/dist/cjs/index.js.map +1 -0
  19. package/dist/cjs/package.json +3 -0
  20. package/dist/cjs/stdin.d.ts +7 -0
  21. package/dist/cjs/stdin.d.ts.map +1 -0
  22. package/dist/cjs/stdin.js +34 -0
  23. package/dist/cjs/stdin.js.map +1 -0
  24. package/dist/cli.d.ts +3 -0
  25. package/dist/cli.d.ts.map +1 -0
  26. package/dist/cli.js +67 -0
  27. package/dist/cli.js.map +1 -0
  28. package/dist/cli_utils.d.ts +27 -0
  29. package/dist/cli_utils.d.ts.map +1 -0
  30. package/dist/cli_utils.js +57 -0
  31. package/dist/cli_utils.js.map +1 -0
  32. package/dist/cli_utils.test.d.ts +2 -0
  33. package/dist/cli_utils.test.d.ts.map +1 -0
  34. package/dist/cli_utils.test.js +90 -0
  35. package/dist/cli_utils.test.js.map +1 -0
  36. package/dist/esm/cli.d.ts +3 -0
  37. package/dist/esm/cli.d.ts.map +1 -0
  38. package/dist/esm/cli.js +74 -0
  39. package/dist/esm/cli.js.map +1 -0
  40. package/dist/esm/cli_utils.d.ts +27 -0
  41. package/dist/esm/cli_utils.d.ts.map +1 -0
  42. package/dist/esm/cli_utils.js +63 -0
  43. package/dist/esm/cli_utils.js.map +1 -0
  44. package/dist/esm/expand.d.ts +69 -0
  45. package/dist/esm/expand.d.ts.map +1 -0
  46. package/dist/esm/expand.js +114 -0
  47. package/dist/esm/expand.js.map +1 -0
  48. package/dist/esm/index.d.ts +2 -0
  49. package/dist/esm/index.d.ts.map +1 -0
  50. package/dist/esm/index.js +2 -0
  51. package/dist/esm/index.js.map +1 -0
  52. package/dist/esm/package.json +3 -0
  53. package/dist/esm/stdin.d.ts +7 -0
  54. package/dist/esm/stdin.d.ts.map +1 -0
  55. package/dist/esm/stdin.js +31 -0
  56. package/dist/esm/stdin.js.map +1 -0
  57. package/dist/expand.d.ts +55 -0
  58. package/dist/expand.d.ts.map +1 -0
  59. package/dist/expand.js +94 -0
  60. package/dist/expand.js.map +1 -0
  61. package/dist/expand.test.d.ts +2 -0
  62. package/dist/expand.test.d.ts.map +1 -0
  63. package/dist/expand.test.js +382 -0
  64. package/dist/expand.test.js.map +1 -0
  65. package/dist/index.d.ts +2 -0
  66. package/dist/index.d.ts.map +1 -0
  67. package/dist/index.js +18 -0
  68. package/dist/index.js.map +1 -0
  69. package/dist/stdin.d.ts +7 -0
  70. package/dist/stdin.d.ts.map +1 -0
  71. package/dist/stdin.js +35 -0
  72. package/dist/stdin.js.map +1 -0
  73. package/package.json +33 -0
  74. package/postbuild.sh +13 -0
  75. package/src/cli.ts +82 -0
  76. package/src/cli_utils.test.ts +131 -0
  77. package/src/cli_utils.ts +78 -0
  78. package/src/expand.test.ts +523 -0
  79. package/src/expand.ts +185 -0
  80. package/src/index.ts +1 -0
  81. package/src/stdin.ts +34 -0
  82. package/tsconfig.cjs.json +11 -0
  83. package/tsconfig.esm.json +14 -0
  84. package/tsconfig.json +22 -0
package/README.md ADDED
@@ -0,0 +1,269 @@
1
+ # Expand IAM Actions
2
+ This will expand the actions of the IAM policy to show the individual actions. Useful for when you want to see the individual actions that are included in a wildcard action or are not allowed to use wildcards for security or compliance reasons.
3
+
4
+ Published in ESM and CommonJS and available as a [CLI](#cli).
5
+
6
+ Use this to:
7
+ 1) Expand out wildcards in actions when you are not allowed to use wildcards in your IAM policy.
8
+ 2) Get an exhaustive list of actions that are included in a policy and quickly search it for interesting actions.
9
+ 3) Investigate where dangerous or dubious actions are being used in your policies.
10
+
11
+ ```typescript
12
+ import { expandIamActions } from '@cloud-copilot/iam-expand';
13
+
14
+ expandIamActions('s3:Get*Tagging')
15
+ [
16
+ 's3:GetBucketTagging',
17
+ 's3:GetJobTagging',
18
+ 's3:GetObjectTagging',
19
+ 's3:GetObjectVersionTagging',
20
+ 's3:GetStorageLensConfigurationTagging'
21
+ ]
22
+
23
+ expandIamActions(['s3:Get*Tagging', 's3:Put*Tagging'])
24
+ [
25
+ 's3:GetBucketTagging',
26
+ 's3:GetJobTagging',
27
+ 's3:GetObjectTagging',
28
+ 's3:GetObjectVersionTagging',
29
+ 's3:GetStorageLensConfigurationTagging',
30
+ 's3:PutBucketTagging',
31
+ 's3:PutJobTagging',
32
+ 's3:PutObjectTagging',
33
+ 's3:PutObjectVersionTagging',
34
+ 's3:PutStorageLensConfigurationTagging'
35
+ ]
36
+ ```
37
+
38
+ ## API
39
+ `expandIamActions` is the main function that will expand the actions of the IAM policy. Takes a string or array of strings and returns an array of strings that the input matches.
40
+
41
+ ## Only Valid Values
42
+ `expandIamActions` intends to only return valid actual actions, if any invalid values are passed in such as an invalid format or a service/action that does not exist, they will be left out of the output. There are options to override this behavior.
43
+
44
+ ## Options
45
+ `expandIamActions` takes an optional second argument that is an object with the following options:
46
+
47
+ ### `expandAsterik`
48
+ By default, a single `*` not be expanded. We assume that if you want a list of all IAM actions there are other sources you will check, such as [@cloud-copilot/iam-data](https://github.com/cloud-copilot/iam-data). If you want to expand a single `*` you can set this option to `true`.
49
+
50
+ ```typescript
51
+ import { expandIamActions } from '@cloud-copilot/iam-expand';
52
+
53
+ //Returns the unexpanded value
54
+ expandIamActions('*')
55
+ ['*']
56
+
57
+ //Returns the expanded value
58
+ expandIamActions('*', { expandAsterik: true })
59
+ [
60
+ //Many many strings. 🫢
61
+ ]
62
+ ```
63
+ ### `expandServiceAsterik`
64
+ By default, a service name followed by a `*` (such as `s3:*` or `lambda:*`) will not be expanded. If you want to expand these you can set this option to `true`.
65
+
66
+ ```typescript
67
+ import { expandIamActions } from '@cloud-copilot/iam-expand';
68
+
69
+ //Returns the unexpanded value
70
+ expandIamActions('s3:*')
71
+ ['s3:*']
72
+
73
+ //Returns the expanded value
74
+ expandIamActions('s3:*', { expandServiceAsterik: true })
75
+ [
76
+ //All the s3 actions. 🫢
77
+ ]
78
+ ```
79
+
80
+ ### `distinct`
81
+ If you include multiple patterns that have overlapping matching actions, the same action will be included multiple times in the output. If you want to remove duplicates you can set this option to `true`.
82
+
83
+ ```typescript
84
+ import { expandIamActions } from '@cloud-copilot/iam-expand';
85
+
86
+ //Returns duplication values (s3:GetObjectTagging)
87
+ expandIamActions(['s3:GetObject*','s3:Get*Tagging'])
88
+ [
89
+ 's3:GetObject',
90
+ 's3:GetObjectAcl',
91
+ 's3:GetObjectAttributes',
92
+ 's3:GetObjectLegalHold',
93
+ 's3:GetObjectRetention',
94
+ 's3:GetObjectTagging',
95
+ ...
96
+ 's3:GetObjectTagging',
97
+ 's3:GetObjectVersionTagging',
98
+ 's3:GetStorageLensConfigurationTagging'
99
+ ]
100
+
101
+ //Duplicates removed and order maintained
102
+ expandIamActions(['s3:GetObject*','s3:Get*Tagging'],{distinct:true})
103
+ [
104
+ 's3:GetObject',
105
+ 's3:GetObjectAcl',
106
+ 's3:GetObjectAttributes',
107
+ 's3:GetObjectLegalHold',
108
+ 's3:GetObjectRetention',
109
+ 's3:GetObjectTagging',
110
+ 's3:GetObjectTorrent',
111
+ 's3:GetObjectVersion',
112
+ 's3:GetObjectVersionAcl',
113
+ 's3:GetObjectVersionAttributes',
114
+ 's3:GetObjectVersionForReplication',
115
+ 's3:GetObjectVersionTagging',
116
+ 's3:GetObjectVersionTorrent',
117
+ 's3:GetBucketTagging',
118
+ 's3:GetJobTagging',
119
+ 's3:GetStorageLensConfigurationTagging'
120
+ ]
121
+ ```
122
+
123
+ ### `sort`
124
+ By default, the output will be sorted based on the order of the input. If you want the output to be sorted alphabetically you can set this option to `true`.
125
+
126
+ ```typescript
127
+ import { expandIamActions } from '@cloud-copilot/iam-expand';
128
+
129
+ //By default the output is sorted based on the order of the input
130
+ expandIamActions(['s3:Get*Tagging','ec2:*Tags'])
131
+ [
132
+ 's3:GetBucketTagging',
133
+ 's3:GetJobTagging',
134
+ 's3:GetObjectTagging',
135
+ 's3:GetObjectVersionTagging',
136
+ 's3:GetStorageLensConfigurationTagging',
137
+ 'ec2:CreateTags',
138
+ 'ec2:DeleteTags',
139
+ 'ec2:DescribeTags'
140
+ ]
141
+
142
+ //Output is sorted alphabetically
143
+ expandIamActions(['s3:Get*Tagging','ec2:*Tags'], {sort: true})
144
+ [
145
+ 'ec2:CreateTags',
146
+ 'ec2:DeleteTags',
147
+ 'ec2:DescribeTags',
148
+ 's3:GetBucketTagging',
149
+ 's3:GetJobTagging',
150
+ 's3:GetObjectTagging',
151
+ 's3:GetObjectVersionTagging',
152
+ 's3:GetStorageLensConfigurationTagging'
153
+ ]
154
+
155
+ ```
156
+
157
+ ### `errorOnInvalidFormat`
158
+ By default, if an invalid format is passed in, such as:
159
+ * `s3Get*Tagging` (missing a separator) or
160
+ * `s3:Get:Tagging*` (too many separators)
161
+
162
+ it will be silenty ignored and left out of the output. If you want to throw an error when an invalid format is passed in you can set this option to `true`.
163
+
164
+ ```typescript
165
+ import { expandIamActions } from '@cloud-copilot/iam-expand';
166
+
167
+ //Ignore invalid format
168
+ expandIamActions('s3Get*Tagging')
169
+ []
170
+
171
+ //Throw an error on invalid format
172
+ expandIamActions('s3Get*Tagging', { errorOnInvalidFormat: true })
173
+ //Uncaught Error: Invalid action format: s3Get*Tagging
174
+ ```
175
+
176
+ ### `errorOnMissingService`
177
+ By default, if a service is passed in that does not exist in the IAM data, it will be silently ignored and left out of the output. If you want to throw an error when a service is passed in that does not exist you can set this option to `true`.
178
+
179
+ ```typescript
180
+ import { expandIamActions } from '@cloud-copilot/iam-expand';
181
+
182
+ //Ignore missing service
183
+ expandIamActions('r2:Get*Tagging')
184
+ []
185
+
186
+ //Throw an error on missing service
187
+ expandIamActions('r2:Get*Tagging', { errorOnMissingService: true })
188
+ //Uncaught Error: Service not found: r2
189
+ ```
190
+
191
+ ## CLI
192
+ There is a CLI available to expand IAM Actions!
193
+
194
+ ### Install
195
+ ```bash
196
+ npm install -g @cloud-copilot/iam-expand
197
+ ```
198
+ or
199
+ ```
200
+ yarn global add @cloud-copilot/iam-expand
201
+ ```
202
+
203
+
204
+
205
+ ### Simple Usage
206
+ The simplest usage is to pass in the actions you want to expand.
207
+ ```bash
208
+ iam-expand s3:Get* s3:*Tag*
209
+ ```
210
+
211
+ You can pass in all options available through the api as dash separated flags.
212
+
213
+ _Prints all matching actions for s3:Get*Tagging, s3:*Tag*, and ec2:* in alphabetical order with duplicates removed:_
214
+ ```bash
215
+ iam-expand s3:Get*Tagging s3:*Tag* ec2:* --expand-service-asterik --distinct --sort
216
+ ```
217
+
218
+ ### Help
219
+ Running the command with no options shows usage help;
220
+ ```bash
221
+ iam-expand
222
+ ```
223
+
224
+ ### Read from stdin
225
+ The CLI is able to read from stdin, and this is really meant to be abused. It essentialy greps the content for anything resembling and action and expands it. Throw anything at it and it will find all the actions it can and expand them.
226
+
227
+ If no actions are passed as arguments, the CLI will read from stdin.
228
+
229
+ You can echo some content:
230
+ ```bash
231
+ echo "s3:Get*Tagging" | iam-expand
232
+ ```
233
+
234
+ You can pull out part of a json file and pipe it in:
235
+ ```bash
236
+ cat policy.json | jq '.Statement[].Action' | iam-expand
237
+ ```
238
+
239
+ Or just send in the whole file:
240
+ ```bash
241
+ cat policy.json | iam-expand
242
+ ```
243
+
244
+ Or some Terraform:
245
+ ```bash
246
+ cat main.tf | iam-expand
247
+ ```
248
+
249
+ Or some CloudFormation:
250
+ ```bash
251
+ cat template.yaml | iam-expand
252
+ ```
253
+
254
+ Or even some HTML:
255
+ ```bash
256
+ curl "https://docs.aws.amazon.com/aws-managed-policy/latest/reference/SecurityAudit.html" | iam-expand
257
+ ```
258
+
259
+ Or the output of a command:
260
+
261
+ This will search for all inline policies that have have
262
+ ```bash
263
+ aws iam get-account-authorization-details --output json | iam-expand --expand-service-asterik --read-wait-time=20_000 | grep kms:DisableKey
264
+ ```
265
+ _--expand-service-asterik makes sure kms:* is expaneded out so you can find the DisableKey action. --read-wait-time=20_000 gives the cli command more time to return it's first byte of output_
266
+
267
+ Because of the likelyhood of finding an aseterik `*` in the input, the stdin option will not find or expand a single `*` even if `--expand-asterik` is passed.
268
+
269
+ Please give this anything you can think of and open an issue if you see an opportunity for improvement.
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../../src/cli.ts"],"names":[],"mappings":""}
@@ -0,0 +1,76 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ const iam_data_1 = require("@cloud-copilot/iam-data");
5
+ const cli_utils_js_1 = require("./cli_utils.js");
6
+ const expand_js_1 = require("./expand.js");
7
+ const commandName = 'iam-expand';
8
+ function expandAndPrint(actionStrings, options) {
9
+ try {
10
+ const result = (0, expand_js_1.expandIamActions)(actionStrings, options);
11
+ for (const action of result) {
12
+ console.log(action);
13
+ }
14
+ }
15
+ catch (e) {
16
+ console.error(e.message);
17
+ process.exit(1);
18
+ }
19
+ }
20
+ function printUsage() {
21
+ console.log('No arguments provided or input from stdin.');
22
+ console.log('Usage:');
23
+ console.log(` ${commandName} [options] [action1] [action2] ...`);
24
+ console.log(` <input from stdout> | ${commandName} [options]`);
25
+ console.log('Action Expanding Options:');
26
+ console.log(' --distinct: Remove duplicate actions');
27
+ console.log(' --sort: Sort the actions');
28
+ console.log(' --expand-asterik: Expand the * action to all actions');
29
+ console.log(' --expand-service-asterik: Expand service:* to all actions for that service');
30
+ console.log(' --error-on-missing-service: Throw an error if a service is not found');
31
+ console.log(' --error-on-invalid-format: Throw an error if the action string is not in the correct format');
32
+ console.log(' --invalid-action-behavior: What to do when an invalid action is encountered:');
33
+ console.log(' --invalid-action-behavior=remove: Remove the invalid action');
34
+ console.log(' --invalid-action-behavior=include: Include the invalid action');
35
+ console.log(' --invalid-action-behavior=error: Throw an error if an invalid action is encountered');
36
+ console.log('CLI Behavior Options:');
37
+ console.log(' --show-data-version: Print the version of the iam-data package being used and exit');
38
+ console.log(' --read-wait-time: Millisenconds to wait for input from stdin before timing out.');
39
+ console.log(' Example: --read-wait-time=10_000');
40
+ process.exit(1);
41
+ }
42
+ const args = process.argv.slice(2); // Ignore the first two elements
43
+ const actionStrings = [];
44
+ const optionStrings = [];
45
+ for (const arg of args) {
46
+ if (arg.startsWith('--')) {
47
+ optionStrings.push(arg);
48
+ }
49
+ else {
50
+ actionStrings.push(arg);
51
+ }
52
+ }
53
+ async function run() {
54
+ const options = (0, cli_utils_js_1.convertOptions)(optionStrings);
55
+ if (options.showDataVersion) {
56
+ console.log(`@cloud-copilot/iam-data version: ${(0, iam_data_1.iamDataVersion)()}`);
57
+ return;
58
+ }
59
+ if (actionStrings.length === 0) {
60
+ const otherActions = await (0, cli_utils_js_1.parseStdInActions)(options);
61
+ if (otherActions.length > 0 && options.expandAsterik) {
62
+ console.warn('Notice: --expand-asterik is not supported when reading from stdin, ignoring.');
63
+ }
64
+ actionStrings.push(...otherActions);
65
+ }
66
+ if (actionStrings.length > 0) {
67
+ expandAndPrint(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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"}
@@ -0,0 +1,27 @@
1
+ import { ExpandIamActionsOptions } from "./expand.js";
2
+ interface CliOptions extends ExpandIamActionsOptions {
3
+ showDataVersion: boolean;
4
+ readWaitTime: string;
5
+ }
6
+ /**
7
+ * Convert a dash-case string to camelCase
8
+ * @param str the string to convert
9
+ * @returns the camelCase string
10
+ */
11
+ export declare function dashToCamelCase(str: string): string;
12
+ /**
13
+ * Convert an array of option strings to an object
14
+ *
15
+ * @param optionArgs the array of option strings to convert
16
+ * @returns the object representation of the options
17
+ */
18
+ export declare function convertOptions(optionArgs: string[]): Partial<CliOptions>;
19
+ export declare function extractActionsFromLineOfInput(line: string): string[];
20
+ /**
21
+ * Parse the actions from stdin
22
+ *
23
+ * @returns an array of strings from stdin
24
+ */
25
+ export declare function parseStdInActions(options: Partial<CliOptions>): Promise<string[]>;
26
+ export {};
27
+ //# sourceMappingURL=cli_utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli_utils.d.ts","sourceRoot":"","sources":["../../src/cli_utils.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,uBAAuB,EAAyB,MAAM,aAAa,CAAC;AAG7E,UAAU,UAAW,SAAQ,uBAAuB;IAClD,eAAe,EAAE,OAAO,CAAA;IACxB,YAAY,EAAE,MAAM,CAAA;CACrB;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAGnD;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,UAAU,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,UAAU,CAAC,CAyBxE;AAGD,wBAAgB,6BAA6B,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAMpE;AAED;;;;GAIG;AACH,wBAAsB,iBAAiB,CAAC,OAAO,EAAE,OAAO,CAAC,UAAU,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAWvF"}
@@ -0,0 +1,69 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.dashToCamelCase = dashToCamelCase;
4
+ exports.convertOptions = convertOptions;
5
+ exports.extractActionsFromLineOfInput = extractActionsFromLineOfInput;
6
+ exports.parseStdInActions = parseStdInActions;
7
+ const expand_js_1 = require("./expand.js");
8
+ const stdin_js_1 = require("./stdin.js");
9
+ /**
10
+ * Convert a dash-case string to camelCase
11
+ * @param str the string to convert
12
+ * @returns the camelCase string
13
+ */
14
+ function dashToCamelCase(str) {
15
+ str = str.substring(2);
16
+ return str.replace(/-([a-z])/g, (g) => g[1].toUpperCase());
17
+ }
18
+ /**
19
+ * Convert an array of option strings to an object
20
+ *
21
+ * @param optionArgs the array of option strings to convert
22
+ * @returns the object representation of the options
23
+ */
24
+ function convertOptions(optionArgs) {
25
+ const options = {};
26
+ for (const option of optionArgs) {
27
+ let key = option;
28
+ let value = true;
29
+ if (option.includes('=')) {
30
+ [key, value] = option.split('=');
31
+ }
32
+ options[dashToCamelCase(key)] = value;
33
+ }
34
+ if (typeof (options.invalidActionBehavior) === 'string') {
35
+ const behaviorString = options.invalidActionBehavior;
36
+ const cleanedInput = behaviorString.charAt(0).toUpperCase() + behaviorString.slice(1).toLowerCase();
37
+ const behavior = expand_js_1.InvalidActionBehavior[cleanedInput];
38
+ if (behavior) {
39
+ options.invalidActionBehavior = behavior;
40
+ }
41
+ else {
42
+ delete options['invalidActionBehavior'];
43
+ }
44
+ }
45
+ return options;
46
+ }
47
+ const actionPattern = /\:?([a-zA-Z0-9]+:[a-zA-Z0-9*]+)/g;
48
+ function extractActionsFromLineOfInput(line) {
49
+ const matches = line.matchAll(actionPattern);
50
+ return Array.from(matches)
51
+ .filter((match) => !match[0].startsWith('arn:') && !match[0].startsWith(':'))
52
+ .map((match) => match[1]);
53
+ }
54
+ /**
55
+ * Parse the actions from stdin
56
+ *
57
+ * @returns an array of strings from stdin
58
+ */
59
+ async function parseStdInActions(options) {
60
+ const delay = options.readWaitTime ? parseInt(options.readWaitTime.replaceAll(/\D/g, '')) : undefined;
61
+ const data = await (0, stdin_js_1.readStdin)(delay);
62
+ if (data.length === 0) {
63
+ return [];
64
+ }
65
+ const lines = data.split('\n');
66
+ const actions = lines.flatMap(line => extractActionsFromLineOfInput(line));
67
+ return actions;
68
+ }
69
+ //# sourceMappingURL=cli_utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli_utils.js","sourceRoot":"","sources":["../../src/cli_utils.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,69 @@
1
+ export declare enum InvalidActionBehavior {
2
+ Remove = "Remove",
3
+ Error = "Error",
4
+ Include = "Include"
5
+ }
6
+ /**
7
+ * Options for the expand function
8
+ *
9
+ */
10
+ export interface ExpandIamActionsOptions {
11
+ /**
12
+ * If true, a single `*` will be expanded to all actions for all services
13
+ * If false, a single `*` will be returned as is
14
+ * Default: false
15
+ */
16
+ expandAsterik: boolean;
17
+ /**
18
+ * If true, `service:*` will be expanded to all actions for that service
19
+ * If false, `service:*` will be returned as is
20
+ * Default: false
21
+ */
22
+ expandServiceAsterik: boolean;
23
+ /**
24
+ * If true, an error will be thrown if the action string is not in the correct format
25
+ * If false, an empty array will be returned
26
+ * Default: false
27
+ */
28
+ errorOnInvalidFormat: boolean;
29
+ /**
30
+ * If true, an error will be thrown if the service in the action string does not exist
31
+ * If false, an empty array will be returned
32
+ * Default: false
33
+ */
34
+ errorOnMissingService: boolean;
35
+ /**
36
+ * If true, only unique values will be returned, while maintaining order
37
+ * If false, all values will be returned, even if they are duplicates
38
+ * Default: false
39
+ */
40
+ distinct: boolean;
41
+ /**
42
+ * The behavior to use when an invalid action is encountered without wildcards
43
+ * @{InvalidActionBehavior.Remove} will remove the invalid action from the output
44
+ * @{InvalidActionBehavior.Error} will throw an error if an invalid action is encountered
45
+ * @{InvalidActionBehavior.Include} will include the invalid action in the output
46
+ *
47
+ * Default: InvalidActionBehavior.Remove
48
+ */
49
+ invalidActionBehavior: InvalidActionBehavior;
50
+ /**
51
+ * If true, the returned array will be sorted
52
+ * If false, the returned array will be in the order they were expanded
53
+ * Default: false
54
+ */
55
+ sort: boolean;
56
+ }
57
+ /**
58
+ * Expands an IAM action string that contains wildcards.
59
+ * If the action string contains no wildcards, it is returned as is.
60
+ * @see {@link ExpandIamActionsOptions} for options to customize behavior
61
+ *
62
+ * If any options are set to throw an error, the function will throw an error if validation fails for a single value.
63
+ *
64
+ * @param actionStringOrStrings An IAM action or array IAM action(s) that may contain wildcards
65
+ * @param overrideOptions Options to override the default behavior
66
+ * @returns An array of expanded action strings flattend to a single array
67
+ */
68
+ export declare function expandIamActions(actionStringOrStrings: string | string[], overrideOptions?: Partial<ExpandIamActionsOptions>): string[];
69
+ //# sourceMappingURL=expand.d.ts.map
@@ -0,0 +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,aAAa,EAAE,OAAO,CAAA;IAEtB;;;;OAIG;IACH,oBAAoB,EAAE,OAAO,CAAA;IAE7B;;;;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,wBAAgB,gBAAgB,CAAC,qBAAqB,EAAE,MAAM,GAAG,MAAM,EAAE,EAAE,eAAe,CAAC,EAAE,OAAO,CAAC,uBAAuB,CAAC,GAAG,MAAM,EAAE,CA8FvI"}
@@ -0,0 +1,118 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.InvalidActionBehavior = void 0;
4
+ exports.expandIamActions = expandIamActions;
5
+ const iam_data_1 = require("@cloud-copilot/iam-data");
6
+ var InvalidActionBehavior;
7
+ (function (InvalidActionBehavior) {
8
+ InvalidActionBehavior["Remove"] = "Remove";
9
+ InvalidActionBehavior["Error"] = "Error";
10
+ InvalidActionBehavior["Include"] = "Include";
11
+ })(InvalidActionBehavior || (exports.InvalidActionBehavior = InvalidActionBehavior = {}));
12
+ const defaultOptions = {
13
+ expandAsterik: false,
14
+ expandServiceAsterik: false,
15
+ errorOnInvalidFormat: false,
16
+ errorOnMissingService: false,
17
+ invalidActionBehavior: InvalidActionBehavior.Remove,
18
+ distinct: false,
19
+ sort: false
20
+ };
21
+ const allAsteriksPattern = /^\*+$/i;
22
+ /**
23
+ * Expands an IAM action string that contains wildcards.
24
+ * If the action string contains no wildcards, it is returned as is.
25
+ * @see {@link ExpandIamActionsOptions} for options to customize behavior
26
+ *
27
+ * If any options are set to throw an error, the function will throw an error if validation fails for a single value.
28
+ *
29
+ * @param actionStringOrStrings An IAM action or array IAM action(s) that may contain wildcards
30
+ * @param overrideOptions Options to override the default behavior
31
+ * @returns An array of expanded action strings flattend to a single array
32
+ */
33
+ function expandIamActions(actionStringOrStrings, overrideOptions) {
34
+ const options = { ...defaultOptions, ...overrideOptions };
35
+ if (!actionStringOrStrings) {
36
+ //Just in case the user passes in null or undefined
37
+ return [];
38
+ }
39
+ if (Array.isArray(actionStringOrStrings)) {
40
+ let allMatches = actionStringOrStrings.flatMap(actionString => expandIamActions(actionString, options));
41
+ if (options.distinct) {
42
+ const aSet = new Set();
43
+ allMatches = allMatches.filter((value) => {
44
+ if (aSet.has(value)) {
45
+ return false;
46
+ }
47
+ aSet.add(value);
48
+ return true;
49
+ });
50
+ }
51
+ if (options.sort) {
52
+ allMatches.sort();
53
+ }
54
+ return allMatches;
55
+ }
56
+ const actionString = actionStringOrStrings.trim();
57
+ if (actionString.match(allAsteriksPattern)) {
58
+ if (options.expandAsterik) {
59
+ //If that's really what you want...
60
+ return (0, iam_data_1.iamServiceKeys)().flatMap(service => (0, iam_data_1.iamActionsForService)(service).map(action => `${service}:${action}`));
61
+ }
62
+ return ['*'];
63
+ }
64
+ if (!actionString.includes(':')) {
65
+ if (options.errorOnInvalidFormat) {
66
+ throw new Error(`Invalid action format: ${actionString}`);
67
+ }
68
+ return [];
69
+ }
70
+ const parts = actionString.split(':');
71
+ if (parts.length !== 2) {
72
+ if (options.errorOnInvalidFormat) {
73
+ throw new Error(`Invalid action format: ${actionString}`);
74
+ }
75
+ return [];
76
+ }
77
+ const [service, wildcardActions] = parts.map(part => part.toLowerCase());
78
+ if (!(0, iam_data_1.iamServiceExists)(service)) {
79
+ if (options.errorOnMissingService) {
80
+ throw new Error(`Service not found: ${service}`);
81
+ }
82
+ return [];
83
+ }
84
+ if (wildcardActions.match(allAsteriksPattern)) {
85
+ if (options.expandServiceAsterik) {
86
+ return (0, iam_data_1.iamActionsForService)(service).map(action => `${service}:${action}`);
87
+ }
88
+ return [`${service}:*`];
89
+ }
90
+ if (!actionString.includes('*')) {
91
+ const actionExists = (0, iam_data_1.iamActionExists)(service, wildcardActions);
92
+ if (actionExists) {
93
+ return [actionString];
94
+ }
95
+ if (options.invalidActionBehavior === InvalidActionBehavior.Remove) {
96
+ return [];
97
+ }
98
+ else if (options.invalidActionBehavior === InvalidActionBehavior.Include) {
99
+ return [actionString];
100
+ }
101
+ else if (options.invalidActionBehavior === InvalidActionBehavior.Error) {
102
+ throw new Error(`Invalid action: ${actionString}`);
103
+ }
104
+ else {
105
+ //This should never happen
106
+ throw new Error(`Invalid invalidActionBehavior: ${options.invalidActionBehavior}`);
107
+ }
108
+ }
109
+ const allActions = (0, iam_data_1.iamActionsForService)(service);
110
+ const pattern = "^" + wildcardActions.replace(/\*/g, '.*?') + "$";
111
+ const regex = new RegExp(pattern, 'i');
112
+ const matchingActions = allActions.filter(action => regex.test(action)).map(action => `${service}:${action}`);
113
+ if (options.sort) {
114
+ matchingActions.sort();
115
+ }
116
+ return matchingActions;
117
+ }
118
+ //# sourceMappingURL=expand.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"expand.js","sourceRoot":"","sources":["../../src/expand.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export * from './expand.js';
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC"}