@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.
- package/LICENSE.txt +674 -0
- package/README.md +269 -0
- package/dist/cjs/cli.d.ts +3 -0
- package/dist/cjs/cli.d.ts.map +1 -0
- package/dist/cjs/cli.js +76 -0
- package/dist/cjs/cli.js.map +1 -0
- package/dist/cjs/cli_utils.d.ts +27 -0
- package/dist/cjs/cli_utils.d.ts.map +1 -0
- package/dist/cjs/cli_utils.js +69 -0
- package/dist/cjs/cli_utils.js.map +1 -0
- package/dist/cjs/expand.d.ts +69 -0
- package/dist/cjs/expand.d.ts.map +1 -0
- package/dist/cjs/expand.js +118 -0
- package/dist/cjs/expand.js.map +1 -0
- package/dist/cjs/index.d.ts +2 -0
- package/dist/cjs/index.d.ts.map +1 -0
- package/dist/cjs/index.js +18 -0
- package/dist/cjs/index.js.map +1 -0
- package/dist/cjs/package.json +3 -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/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +67 -0
- package/dist/cli.js.map +1 -0
- package/dist/cli_utils.d.ts +27 -0
- package/dist/cli_utils.d.ts.map +1 -0
- package/dist/cli_utils.js +57 -0
- package/dist/cli_utils.js.map +1 -0
- package/dist/cli_utils.test.d.ts +2 -0
- package/dist/cli_utils.test.d.ts.map +1 -0
- package/dist/cli_utils.test.js +90 -0
- package/dist/cli_utils.test.js.map +1 -0
- package/dist/esm/cli.d.ts +3 -0
- package/dist/esm/cli.d.ts.map +1 -0
- package/dist/esm/cli.js +74 -0
- package/dist/esm/cli.js.map +1 -0
- package/dist/esm/cli_utils.d.ts +27 -0
- package/dist/esm/cli_utils.d.ts.map +1 -0
- package/dist/esm/cli_utils.js +63 -0
- package/dist/esm/cli_utils.js.map +1 -0
- package/dist/esm/expand.d.ts +69 -0
- package/dist/esm/expand.d.ts.map +1 -0
- package/dist/esm/expand.js +114 -0
- package/dist/esm/expand.js.map +1 -0
- package/dist/esm/index.d.ts +2 -0
- package/dist/esm/index.d.ts.map +1 -0
- package/dist/esm/index.js +2 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/package.json +3 -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/expand.d.ts +55 -0
- package/dist/expand.d.ts.map +1 -0
- package/dist/expand.js +94 -0
- package/dist/expand.js.map +1 -0
- package/dist/expand.test.d.ts +2 -0
- package/dist/expand.test.d.ts.map +1 -0
- package/dist/expand.test.js +382 -0
- package/dist/expand.test.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +18 -0
- package/dist/index.js.map +1 -0
- package/dist/stdin.d.ts +7 -0
- package/dist/stdin.d.ts.map +1 -0
- package/dist/stdin.js +35 -0
- package/dist/stdin.js.map +1 -0
- package/package.json +33 -0
- package/postbuild.sh +13 -0
- package/src/cli.ts +82 -0
- package/src/cli_utils.test.ts +131 -0
- package/src/cli_utils.ts +78 -0
- package/src/expand.test.ts +523 -0
- package/src/expand.ts +185 -0
- package/src/index.ts +1 -0
- package/src/stdin.ts +34 -0
- package/tsconfig.cjs.json +11 -0
- package/tsconfig.esm.json +14 -0
- package/tsconfig.json +22 -0
|
@@ -0,0 +1,523 @@
|
|
|
1
|
+
import { iamActionExists, iamActionsForService, iamServiceExists, iamServiceKeys } from '@cloud-copilot/iam-data'
|
|
2
|
+
import { beforeEach, describe, expect, it, vi } from 'vitest'
|
|
3
|
+
import { expandIamActions, InvalidActionBehavior } from "./expand.js"
|
|
4
|
+
|
|
5
|
+
vi.mock('@cloud-copilot/iam-data')
|
|
6
|
+
|
|
7
|
+
beforeEach(() => {
|
|
8
|
+
vi.resetAllMocks()
|
|
9
|
+
// jest.resetAllMocks()
|
|
10
|
+
})
|
|
11
|
+
|
|
12
|
+
describe("expand", () => {
|
|
13
|
+
it("should return an empty array when actionString is null", () => {
|
|
14
|
+
//Given actionString is null
|
|
15
|
+
const actionString = null
|
|
16
|
+
//When expand is called with actionString
|
|
17
|
+
const result = expandIamActions(actionString as any)
|
|
18
|
+
//Then result should be an empty array
|
|
19
|
+
expect(result).toEqual([])
|
|
20
|
+
})
|
|
21
|
+
|
|
22
|
+
it("should return '*' when actionString is '*' and expandAsterik is false", () => {
|
|
23
|
+
//Given actionString is '*'
|
|
24
|
+
const actionString = '*'
|
|
25
|
+
//When expand is called with actionString
|
|
26
|
+
const result = expandIamActions(actionString)
|
|
27
|
+
//Then result should be '*'
|
|
28
|
+
expect(result).toEqual(['*'])
|
|
29
|
+
})
|
|
30
|
+
|
|
31
|
+
it('should return "*" when action string multiple asteriks and expandAsterik is false', () => {
|
|
32
|
+
//Given actionString is multiple asteriks
|
|
33
|
+
const actionString = '***'
|
|
34
|
+
|
|
35
|
+
//And expandAsterik is false
|
|
36
|
+
const options = { expandAsterik: false }
|
|
37
|
+
|
|
38
|
+
//When expand is called with actionString and options
|
|
39
|
+
const result = expandIamActions(actionString, options)
|
|
40
|
+
|
|
41
|
+
//Then result should be '*'
|
|
42
|
+
expect(result).toEqual(['*'])
|
|
43
|
+
})
|
|
44
|
+
|
|
45
|
+
it("should expand all actions for all services when actionString is '*' and expandAsterik is true", () => {
|
|
46
|
+
//Given actionString is '*'
|
|
47
|
+
const actionString = '*'
|
|
48
|
+
//And expandAsterik is true
|
|
49
|
+
const options = { expandAsterik: true }
|
|
50
|
+
//And there are services
|
|
51
|
+
vi.mocked(iamServiceKeys).mockReturnValue(['s3', 'ec2'])
|
|
52
|
+
|
|
53
|
+
//And there are actions for the services
|
|
54
|
+
vi.mocked(iamActionsForService).mockImplementation(service => {
|
|
55
|
+
if(service === 's3') {
|
|
56
|
+
return ['action1', 'action2']
|
|
57
|
+
}
|
|
58
|
+
if(service === 'ec2') {
|
|
59
|
+
return ['action3', 'action4']
|
|
60
|
+
}
|
|
61
|
+
return []
|
|
62
|
+
})
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
//When expand is called with actionString and options
|
|
67
|
+
const result = expandIamActions(actionString, options)
|
|
68
|
+
//Then result should be an array of all actions for all services
|
|
69
|
+
expect(result.sort()).toEqual([
|
|
70
|
+
'ec2:action3',
|
|
71
|
+
'ec2:action4',
|
|
72
|
+
's3:action1',
|
|
73
|
+
's3:action2'
|
|
74
|
+
])
|
|
75
|
+
})
|
|
76
|
+
|
|
77
|
+
it("should do a case insensitive match for the service in the action string", () => {
|
|
78
|
+
//Given actionString is 'S3:GetObject'
|
|
79
|
+
const actionString = 'S3:get*'
|
|
80
|
+
//And s3 service exists
|
|
81
|
+
vi.mocked(iamServiceExists).mockImplementation((s) => s === 's3')
|
|
82
|
+
//And there are matching actions
|
|
83
|
+
vi.mocked(iamActionsForService).mockReturnValue(['GetObject'])
|
|
84
|
+
|
|
85
|
+
//When expand is called with actionString
|
|
86
|
+
const result = expandIamActions(actionString)
|
|
87
|
+
|
|
88
|
+
//Then result should be an array with the actionString
|
|
89
|
+
expect(result).toEqual(['s3:GetObject'])
|
|
90
|
+
})
|
|
91
|
+
|
|
92
|
+
describe("invalid action name", () => {
|
|
93
|
+
it('should return an action without wildcards if it is a valid action', () => {
|
|
94
|
+
//Given actionString contains a valid action
|
|
95
|
+
const actionString = 's3:GetObject'
|
|
96
|
+
//And s3 the service exists
|
|
97
|
+
vi.mocked(iamServiceExists).mockReturnValue(true)
|
|
98
|
+
//And the action does not
|
|
99
|
+
vi.mocked(iamActionExists).mockReturnValue(true)
|
|
100
|
+
|
|
101
|
+
//When expand is called with actionString
|
|
102
|
+
const result = expandIamActions(actionString)
|
|
103
|
+
|
|
104
|
+
//Then result should be an array with the actionString
|
|
105
|
+
expect(result).toEqual([actionString])
|
|
106
|
+
})
|
|
107
|
+
|
|
108
|
+
it("should remove an invalid action if invalidActionBehavior is Remove", () => {
|
|
109
|
+
//Given actionString contains an invalid action
|
|
110
|
+
const actionString = 's3:DoSomethingDumb'
|
|
111
|
+
//And invalidActionBehavior is Remove
|
|
112
|
+
const options = { invalidActionBehavior: InvalidActionBehavior.Remove }
|
|
113
|
+
//And s3 the service exists
|
|
114
|
+
vi.mocked(iamServiceExists).mockReturnValue(true)
|
|
115
|
+
//And the action does not
|
|
116
|
+
vi.mocked(iamActionExists).mockReturnValue(false)
|
|
117
|
+
|
|
118
|
+
//When expand is called with actionString
|
|
119
|
+
const result = expandIamActions(actionString, options)
|
|
120
|
+
|
|
121
|
+
//Then result should be an array with the valid action
|
|
122
|
+
expect(result).toEqual([])
|
|
123
|
+
})
|
|
124
|
+
|
|
125
|
+
it("should include an invalid action if invalidActionBehavior is Include", () => {
|
|
126
|
+
//Given actionString contains an invalid action
|
|
127
|
+
const actionString = 's3:DoSomethingSilly'
|
|
128
|
+
//And invalidActionBehavior is Include
|
|
129
|
+
const options = { invalidActionBehavior: InvalidActionBehavior.Include }
|
|
130
|
+
//And s3 the service exists
|
|
131
|
+
vi.mocked(iamServiceExists).mockReturnValue(true)
|
|
132
|
+
//And the action does not
|
|
133
|
+
vi.mocked(iamActionExists).mockReturnValue(false)
|
|
134
|
+
|
|
135
|
+
//When expand is called with actionString
|
|
136
|
+
const result = expandIamActions(actionString, options)
|
|
137
|
+
|
|
138
|
+
//Then result should be an array with the invalid action
|
|
139
|
+
expect(result).toEqual([actionString])
|
|
140
|
+
})
|
|
141
|
+
|
|
142
|
+
it('should throw an error if the action is invalid and invalidActionBehavior is Error', () => {
|
|
143
|
+
//Given actionString contains an invalid action
|
|
144
|
+
const actionString = 's3:AbsurdlyInvalidAction'
|
|
145
|
+
//And invalidActionBehavior is Error
|
|
146
|
+
const options = { invalidActionBehavior: InvalidActionBehavior.Error }
|
|
147
|
+
//And s3 the service exists
|
|
148
|
+
vi.mocked(iamServiceExists).mockReturnValue(true)
|
|
149
|
+
//And the action does not
|
|
150
|
+
vi.mocked(iamActionExists).mockReturnValue(false)
|
|
151
|
+
|
|
152
|
+
//When expand is called with actionString
|
|
153
|
+
//Then an error should be thrown
|
|
154
|
+
expect(() => expandIamActions(actionString, options)).toThrowError('Invalid action')
|
|
155
|
+
})
|
|
156
|
+
})
|
|
157
|
+
|
|
158
|
+
describe("when the actions string is in the wrong format", () => {
|
|
159
|
+
it("should return an empty array when there are too many parts and errorOnInvalidFormat is false", () => {
|
|
160
|
+
//Given actionString is in the wrong format
|
|
161
|
+
const actionString = 's3:GetObject:Extra*'
|
|
162
|
+
//And errorOnInvalidFormat is false
|
|
163
|
+
const options = { errorOnInvalidFormat: false }
|
|
164
|
+
|
|
165
|
+
//When expand is called with actionString
|
|
166
|
+
const result = expandIamActions(actionString, options)
|
|
167
|
+
|
|
168
|
+
//Then result should be an empty array
|
|
169
|
+
expect(result).toEqual([])
|
|
170
|
+
})
|
|
171
|
+
|
|
172
|
+
it("should return an empty array when there are too few parts and errorOnInvalidFormat is false", () => {
|
|
173
|
+
//Given actionString has no :
|
|
174
|
+
const actionString = 's3GetObject*'
|
|
175
|
+
//And errorOnInvalidFormat is false
|
|
176
|
+
const options = { errorOnInvalidFormat: false }
|
|
177
|
+
|
|
178
|
+
//When expand is called with actionString
|
|
179
|
+
const result = expandIamActions(actionString, options)
|
|
180
|
+
|
|
181
|
+
//Then result should be an empty array
|
|
182
|
+
expect(result).toEqual([])
|
|
183
|
+
})
|
|
184
|
+
|
|
185
|
+
it("should throw an error when there are too many parts and errorOnInvalidFormat is true", () => {
|
|
186
|
+
//Given actionString is in the wrong format
|
|
187
|
+
const actionString = 's3:GetObject:Extra*'
|
|
188
|
+
//And errorOnInvalidFormat is true
|
|
189
|
+
const options = { errorOnInvalidFormat: true }
|
|
190
|
+
|
|
191
|
+
//When expand is called with actionString
|
|
192
|
+
//Then an error should be thrown
|
|
193
|
+
expect(() => expandIamActions(actionString, options)).toThrowError('Invalid action format')
|
|
194
|
+
})
|
|
195
|
+
|
|
196
|
+
it("should throw an error when there are too few parts and errorOnInvalidFormat is true", () => {
|
|
197
|
+
//Given actionString has no :
|
|
198
|
+
const actionString = 's3GetObject*'
|
|
199
|
+
//And errorOnInvalidFormat is true
|
|
200
|
+
const options = { errorOnInvalidFormat: true }
|
|
201
|
+
|
|
202
|
+
//When expand is called with actionString
|
|
203
|
+
//Then an error should be thrown
|
|
204
|
+
expect(() => expandIamActions(actionString, options)).toThrowError('Invalid action format')
|
|
205
|
+
})
|
|
206
|
+
})
|
|
207
|
+
|
|
208
|
+
describe("when the service in the action string does not exist", () => {
|
|
209
|
+
it("should return an empty array when errorOnMissingService is false", () => {
|
|
210
|
+
//Given actionString contains a service that does not exist
|
|
211
|
+
const actionString = 'fake:GetObject*'
|
|
212
|
+
//And errorOnMissingService is false
|
|
213
|
+
const options = { errorOnMissingService: false }
|
|
214
|
+
|
|
215
|
+
//When expand is called with actionString
|
|
216
|
+
const result = expandIamActions(actionString, options)
|
|
217
|
+
|
|
218
|
+
//Then result should be an empty array
|
|
219
|
+
expect(result).toEqual([])
|
|
220
|
+
})
|
|
221
|
+
|
|
222
|
+
it("should throw an error when errorOnMissingService is true", () => {
|
|
223
|
+
//Given actionString contains a service that does not exist
|
|
224
|
+
const actionString = 'fake:GetObject*'
|
|
225
|
+
//And errorOnMissingService is true
|
|
226
|
+
const options = { errorOnMissingService: true }
|
|
227
|
+
|
|
228
|
+
//When expand is called with actionString
|
|
229
|
+
//Then an error should be thrown
|
|
230
|
+
expect(() => expandIamActions(actionString, options)).toThrowError('Service not found')
|
|
231
|
+
})
|
|
232
|
+
})
|
|
233
|
+
|
|
234
|
+
describe("when the action string contains a wildcard for a service", () => {
|
|
235
|
+
it("should expand not expand the wildcard when expandServiceAsterik is false", () => {
|
|
236
|
+
//Given actionString is 's3:*'
|
|
237
|
+
const actionString = 's3:*'
|
|
238
|
+
//And expandServiceAsterik is false
|
|
239
|
+
const options = { expandServiceAsterik: false }
|
|
240
|
+
//And s3 service exists
|
|
241
|
+
vi.mocked(iamServiceExists).mockReturnValue(true)
|
|
242
|
+
//And there are matching actions
|
|
243
|
+
vi.mocked(iamActionsForService).mockReturnValue(['GetObject', 'PutObject'])
|
|
244
|
+
|
|
245
|
+
//When expand is called with actionString
|
|
246
|
+
const result = expandIamActions(actionString, options)
|
|
247
|
+
|
|
248
|
+
//Then result should be an array with the original string
|
|
249
|
+
expect(result).toEqual([actionString])
|
|
250
|
+
})
|
|
251
|
+
|
|
252
|
+
it("should expand not expand the wildcard when there are multiple asteriks and expandServiceAsterik is false", () => {
|
|
253
|
+
//Given actionString has multiple asteriks for the actions
|
|
254
|
+
const actionString = 's3:****'
|
|
255
|
+
//And expandServiceAsterik is false
|
|
256
|
+
const options = { expandServiceAsterik: false }
|
|
257
|
+
//And s3 service exists
|
|
258
|
+
vi.mocked(iamServiceExists).mockReturnValue(true)
|
|
259
|
+
//And there are matching actions
|
|
260
|
+
vi.mocked(iamActionsForService).mockReturnValue(['GetObject', 'PutObject'])
|
|
261
|
+
|
|
262
|
+
//When expand is called with actionString
|
|
263
|
+
const result = expandIamActions(actionString, options)
|
|
264
|
+
|
|
265
|
+
//Then result should be an array with the original string
|
|
266
|
+
expect(result).toEqual(['s3:*'])
|
|
267
|
+
})
|
|
268
|
+
|
|
269
|
+
it("should expand the wildcard when expandServiceAsterik is true", () => {
|
|
270
|
+
//Given actionString is 's3:*'
|
|
271
|
+
const actionString = 's3:*'
|
|
272
|
+
//And expandServiceAsterik is true
|
|
273
|
+
const options = { expandServiceAsterik: true }
|
|
274
|
+
//And s3 service exists
|
|
275
|
+
vi.mocked(iamServiceExists).mockReturnValue(true)
|
|
276
|
+
//And there are matching actions
|
|
277
|
+
vi.mocked(iamActionsForService).mockReturnValue(['GetObject', 'PutObject'])
|
|
278
|
+
|
|
279
|
+
//When expand is called with actionString
|
|
280
|
+
const result = expandIamActions(actionString, options)
|
|
281
|
+
|
|
282
|
+
//Then result should be an array of actions
|
|
283
|
+
expect(result).toEqual([
|
|
284
|
+
's3:GetObject',
|
|
285
|
+
's3:PutObject'
|
|
286
|
+
])
|
|
287
|
+
})
|
|
288
|
+
})
|
|
289
|
+
|
|
290
|
+
|
|
291
|
+
describe("when the action string contains wildcards", () => {
|
|
292
|
+
it('should expand the wildcard actions at the end', () => {
|
|
293
|
+
//Given actionString is 's3:Get*'
|
|
294
|
+
const actionString = 's3:Get*'
|
|
295
|
+
//And s3 service exists
|
|
296
|
+
vi.mocked(iamServiceExists).mockReturnValue(true)
|
|
297
|
+
//And there are matching actions
|
|
298
|
+
vi.mocked(iamActionsForService).mockReturnValue([
|
|
299
|
+
'GetObject',
|
|
300
|
+
'GetObjectAcl',
|
|
301
|
+
'GetObjectTagging',
|
|
302
|
+
'GetObjectTorrent',
|
|
303
|
+
'PutObject',
|
|
304
|
+
'PutObjectAcl',
|
|
305
|
+
'SomethingGetSomething'
|
|
306
|
+
])
|
|
307
|
+
|
|
308
|
+
//When expand is called with actionString
|
|
309
|
+
const result = expandIamActions(actionString)
|
|
310
|
+
//Then result should be an array of actions
|
|
311
|
+
expect(result).toEqual([
|
|
312
|
+
's3:GetObject',
|
|
313
|
+
's3:GetObjectAcl',
|
|
314
|
+
's3:GetObjectTagging',
|
|
315
|
+
's3:GetObjectTorrent'
|
|
316
|
+
])
|
|
317
|
+
})
|
|
318
|
+
|
|
319
|
+
it('should expand the wildcard actions at the beginning', () => {
|
|
320
|
+
//Given actionString is 's3:*Object'
|
|
321
|
+
const actionString = 's3:*Object'
|
|
322
|
+
//And s3 service exists
|
|
323
|
+
vi.mocked(iamServiceExists).mockReturnValue(true)
|
|
324
|
+
//And there are matching actions
|
|
325
|
+
vi.mocked(iamActionsForService).mockReturnValue([
|
|
326
|
+
'GetObject',
|
|
327
|
+
'GetObjectAcl',
|
|
328
|
+
'GetObjectTagging',
|
|
329
|
+
'GetObjectTorrent',
|
|
330
|
+
'PutObject',
|
|
331
|
+
'PutObjectAcl',
|
|
332
|
+
'SomethingGetSomething'
|
|
333
|
+
])
|
|
334
|
+
|
|
335
|
+
//When expand is called with actionString
|
|
336
|
+
const result = expandIamActions(actionString)
|
|
337
|
+
//Then result should be an array of actions
|
|
338
|
+
expect(result).toEqual([
|
|
339
|
+
's3:GetObject',
|
|
340
|
+
's3:PutObject'
|
|
341
|
+
])
|
|
342
|
+
})
|
|
343
|
+
|
|
344
|
+
it('should expand the wildcard actions in the middle', () => {
|
|
345
|
+
//Given actionString is 's3:Get*Tagging'
|
|
346
|
+
const actionString = 's3:Get*Tagging'
|
|
347
|
+
//And s3 service exists
|
|
348
|
+
vi.mocked(iamServiceExists).mockReturnValue(true)
|
|
349
|
+
//And there are matching actions
|
|
350
|
+
vi.mocked(iamActionsForService).mockReturnValue([
|
|
351
|
+
'GetObject',
|
|
352
|
+
'GetObjectAcl',
|
|
353
|
+
'GetObjectTagging',
|
|
354
|
+
'GetBanskyTagging',
|
|
355
|
+
'GetObjectTorrent',
|
|
356
|
+
'PutObject',
|
|
357
|
+
'PutObjectAcl',
|
|
358
|
+
'SomethingGetSomething'
|
|
359
|
+
])
|
|
360
|
+
|
|
361
|
+
//When expand is called with actionString
|
|
362
|
+
const result = expandIamActions(actionString)
|
|
363
|
+
//Then result should be an array of actions
|
|
364
|
+
expect(result).toEqual([
|
|
365
|
+
's3:GetObjectTagging',
|
|
366
|
+
's3:GetBanskyTagging'
|
|
367
|
+
])
|
|
368
|
+
})
|
|
369
|
+
|
|
370
|
+
it('should expand multiple wildcards', () => {
|
|
371
|
+
//Given actionString is 's3:Get*Tagging*'
|
|
372
|
+
const actionString = 's3:Get*Tagging*'
|
|
373
|
+
//And s3 service exists
|
|
374
|
+
vi.mocked(iamServiceExists).mockReturnValue(true)
|
|
375
|
+
//And there are matching actions
|
|
376
|
+
vi.mocked(iamActionsForService).mockReturnValue([
|
|
377
|
+
'GetObject',
|
|
378
|
+
'GetObjectAcl',
|
|
379
|
+
'GetObjectTagging',
|
|
380
|
+
'GetBanskyTagging',
|
|
381
|
+
'GetTagging',
|
|
382
|
+
'GetObjectTorrent',
|
|
383
|
+
'GetSomethingTaggingSomething',
|
|
384
|
+
'PutObject',
|
|
385
|
+
'PutObjectAcl',
|
|
386
|
+
'SomethingGetSomething'
|
|
387
|
+
])
|
|
388
|
+
|
|
389
|
+
//When expand is called with actionString
|
|
390
|
+
const result = expandIamActions(actionString)
|
|
391
|
+
//Then result should be an array of actions
|
|
392
|
+
expect(result).toEqual([
|
|
393
|
+
's3:GetObjectTagging',
|
|
394
|
+
's3:GetBanskyTagging',
|
|
395
|
+
's3:GetTagging',
|
|
396
|
+
's3:GetSomethingTaggingSomething'
|
|
397
|
+
])
|
|
398
|
+
})
|
|
399
|
+
})
|
|
400
|
+
|
|
401
|
+
describe("when actionStrings is an array", () => {
|
|
402
|
+
it("should return an empty array when actionStrings is an empty array", () => {
|
|
403
|
+
//Given actionStrings is an empty array
|
|
404
|
+
const actionStrings: string[] = []
|
|
405
|
+
|
|
406
|
+
//When expand is called with actionStrings
|
|
407
|
+
const result = expandIamActions(actionStrings)
|
|
408
|
+
|
|
409
|
+
//Then result should be an empty array
|
|
410
|
+
expect(result).toEqual([])
|
|
411
|
+
})
|
|
412
|
+
|
|
413
|
+
it("should return an array of expanded actions when actionStrings is an array of action strings", () => {
|
|
414
|
+
//Given actionStrings is an array of action strings
|
|
415
|
+
const actionStrings = [
|
|
416
|
+
's3:Get*',
|
|
417
|
+
'ec2:*Instances'
|
|
418
|
+
]
|
|
419
|
+
//And s3 and ec2 services exist
|
|
420
|
+
vi.mocked(iamServiceExists).mockReturnValue(true)
|
|
421
|
+
//And there are actions for the services
|
|
422
|
+
vi.mocked(iamActionsForService).mockImplementation(service => {
|
|
423
|
+
if(service === 's3') {
|
|
424
|
+
return ['GetObject', 'GetObjectTagging', 'PutObject', 'PutObjectTagging']
|
|
425
|
+
}
|
|
426
|
+
if(service === 'ec2') {
|
|
427
|
+
return ['RunInstances', 'TerminateInstances']
|
|
428
|
+
}
|
|
429
|
+
return []
|
|
430
|
+
})
|
|
431
|
+
|
|
432
|
+
//When expand is called with actionStrings
|
|
433
|
+
const result = expandIamActions(actionStrings)
|
|
434
|
+
|
|
435
|
+
//Then result should be an array of expanded actions
|
|
436
|
+
expect(result.sort()).toEqual([
|
|
437
|
+
'ec2:RunInstances',
|
|
438
|
+
'ec2:TerminateInstances',
|
|
439
|
+
's3:GetObject',
|
|
440
|
+
's3:GetObjectTagging',
|
|
441
|
+
])
|
|
442
|
+
})
|
|
443
|
+
})
|
|
444
|
+
|
|
445
|
+
describe("distinct option", () => {
|
|
446
|
+
it('should return all values when distinct is false', () => {
|
|
447
|
+
//Given two action strings
|
|
448
|
+
const actionString = ['s3:Get*','s3:*Object']
|
|
449
|
+
//And s3 service exists
|
|
450
|
+
vi.mocked(iamServiceExists).mockReturnValue(true)
|
|
451
|
+
//And there are matching actions
|
|
452
|
+
vi.mocked(iamActionsForService).mockReturnValue(['GetObject', 'PutObject', 'GetOtherObject'])
|
|
453
|
+
|
|
454
|
+
//When expand is called with actionString and distinct is false
|
|
455
|
+
const result = expandIamActions(actionString, { distinct: false })
|
|
456
|
+
|
|
457
|
+
//Then result should be an array of actions, even if they are duplicates
|
|
458
|
+
expect(result).toEqual(['s3:GetObject', 's3:GetOtherObject', 's3:GetObject', 's3:PutObject', 's3:GetOtherObject'])
|
|
459
|
+
})
|
|
460
|
+
|
|
461
|
+
it('should return only unique values when distinct is true, and maintain order', () => {
|
|
462
|
+
//Given two action strings
|
|
463
|
+
const actionString = ['s3:Get*','s3:*Object']
|
|
464
|
+
//And s3 service exists
|
|
465
|
+
vi.mocked(iamServiceExists).mockReturnValue(true)
|
|
466
|
+
//And there are matching actions
|
|
467
|
+
vi.mocked(iamActionsForService).mockReturnValue(['GetObject', 'PutObject', 'GetOtherObject'])
|
|
468
|
+
|
|
469
|
+
//When expand is called with actionStrings and distinct is true
|
|
470
|
+
const result = expandIamActions(actionString, { distinct: true })
|
|
471
|
+
//Then result should be an array of unique actions
|
|
472
|
+
expect(result).toEqual(['s3:GetObject', 's3:GetOtherObject', 's3:PutObject'])
|
|
473
|
+
})
|
|
474
|
+
})
|
|
475
|
+
|
|
476
|
+
describe("sort option", () => {
|
|
477
|
+
it('should return values in the order they were expanded when sort is false', () => {
|
|
478
|
+
//Given two action strings
|
|
479
|
+
const actionString = ['s3:Get*','ec2:Describe*']
|
|
480
|
+
//And s3 service exists
|
|
481
|
+
vi.mocked(iamServiceExists).mockReturnValue(true)
|
|
482
|
+
//And there are matching actions
|
|
483
|
+
vi.mocked(iamActionsForService).mockImplementation(service => {
|
|
484
|
+
if(service === 's3') {
|
|
485
|
+
return ['GetObject', 'GetBucket']
|
|
486
|
+
}
|
|
487
|
+
if(service === 'ec2') {
|
|
488
|
+
return ['DescribeInstances', 'DescribeVolumes']
|
|
489
|
+
}
|
|
490
|
+
return []
|
|
491
|
+
})
|
|
492
|
+
|
|
493
|
+
//When expand is called with actionStrings and sort is false
|
|
494
|
+
const result = expandIamActions(actionString, { sort: false })
|
|
495
|
+
//Then result should be an array of actions in the order they were expanded
|
|
496
|
+
expect(result).toEqual(['s3:GetObject', 's3:GetBucket', 'ec2:DescribeInstances', 'ec2:DescribeVolumes'])
|
|
497
|
+
})
|
|
498
|
+
|
|
499
|
+
it('should return values sorted when sort is true', () => {
|
|
500
|
+
//Given two action strings
|
|
501
|
+
const actionString = ['s3:Get*','ec2:Describe*']
|
|
502
|
+
//And s3 service exists
|
|
503
|
+
vi.mocked(iamServiceExists).mockReturnValue(true)
|
|
504
|
+
//And there are matching actions
|
|
505
|
+
vi.mocked(iamActionsForService).mockImplementation(service => {
|
|
506
|
+
if(service === 's3') {
|
|
507
|
+
return ['GetObject', 'GetBucket']
|
|
508
|
+
}
|
|
509
|
+
if(service === 'ec2') {
|
|
510
|
+
return ['DescribeInstances', 'DescribeVolumes']
|
|
511
|
+
}
|
|
512
|
+
return []
|
|
513
|
+
})
|
|
514
|
+
|
|
515
|
+
//When expand is called with actionStrings and sort is false
|
|
516
|
+
const result = expandIamActions(actionString, { sort: true })
|
|
517
|
+
//Then result should be an array of actions in the order they were expanded
|
|
518
|
+
expect(result).toEqual(['ec2:DescribeInstances', 'ec2:DescribeVolumes', 's3:GetBucket', 's3:GetObject'])
|
|
519
|
+
})
|
|
520
|
+
})
|
|
521
|
+
|
|
522
|
+
|
|
523
|
+
})
|