@terra-graph/conventions-aws 1.0.0-rc.1

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 (91) hide show
  1. package/CHANGELOG.md +35 -0
  2. package/README.md +25 -0
  3. package/dist/cjs/conventions/dataflow/profiles/base.js +89 -0
  4. package/dist/cjs/conventions/dataflow/profiles/dot.js +44 -0
  5. package/dist/cjs/conventions/dataflow/profiles/dot.test.js +147 -0
  6. package/dist/cjs/conventions/dataflow/rules.js +4 -0
  7. package/dist/cjs/conventions/dataflow/rules.test.js +11 -0
  8. package/dist/cjs/conventions/dataflow/rulesets.js +751 -0
  9. package/dist/cjs/conventions/dataflow/rulesets.test.js +27 -0
  10. package/dist/cjs/conventions/index.js +7 -0
  11. package/dist/cjs/conventions/index.test.js +8 -0
  12. package/dist/cjs/index.js +70 -0
  13. package/dist/cjs/index.test.js +58 -0
  14. package/dist/cjs/namespaces.js +14 -0
  15. package/dist/cjs/namespaces.test.js +17 -0
  16. package/dist/cjs/package.json +1 -0
  17. package/dist/cjs/plugins/AwsApiGateway.js +218 -0
  18. package/dist/cjs/plugins/AwsApiGateway.test.js +427 -0
  19. package/dist/cjs/plugins/AwsIam.js +432 -0
  20. package/dist/cjs/plugins/AwsIam.test.js +468 -0
  21. package/dist/cjs/plugins/AwsS3.js +107 -0
  22. package/dist/cjs/plugins/AwsS3.test.js +102 -0
  23. package/dist/cjs/plugins/AwsSns.js +52 -0
  24. package/dist/cjs/plugins/AwsSns.test.js +55 -0
  25. package/dist/cjs/plugins/AwsTransferFamily.js +105 -0
  26. package/dist/cjs/plugins/AwsTransferFamily.test.js +279 -0
  27. package/dist/cjs/rules/dot.js +36 -0
  28. package/dist/cjs/rules/dot.test.js +42 -0
  29. package/dist/cjs/rules/general.js +69 -0
  30. package/dist/cjs/rules/general.test.js +47 -0
  31. package/dist/cjs/rulesets/dot.js +25 -0
  32. package/dist/cjs/rulesets/dot.test.js +48 -0
  33. package/dist/esm/conventions/dataflow/profiles/base.d.ts +4 -0
  34. package/dist/esm/conventions/dataflow/profiles/base.js +86 -0
  35. package/dist/esm/conventions/dataflow/profiles/dot.d.ts +4 -0
  36. package/dist/esm/conventions/dataflow/profiles/dot.js +38 -0
  37. package/dist/esm/conventions/dataflow/profiles/dot.test.d.ts +1 -0
  38. package/dist/esm/conventions/dataflow/profiles/dot.test.js +109 -0
  39. package/dist/esm/conventions/dataflow/rules.d.ts +3 -0
  40. package/dist/esm/conventions/dataflow/rules.js +2 -0
  41. package/dist/esm/conventions/dataflow/rules.test.d.ts +1 -0
  42. package/dist/esm/conventions/dataflow/rules.test.js +6 -0
  43. package/dist/esm/conventions/dataflow/rulesets.d.ts +3 -0
  44. package/dist/esm/conventions/dataflow/rulesets.js +749 -0
  45. package/dist/esm/conventions/dataflow/rulesets.test.d.ts +1 -0
  46. package/dist/esm/conventions/dataflow/rulesets.test.js +22 -0
  47. package/dist/esm/conventions/index.d.ts +3 -0
  48. package/dist/esm/conventions/index.js +4 -0
  49. package/dist/esm/conventions/index.test.d.ts +1 -0
  50. package/dist/esm/conventions/index.test.js +6 -0
  51. package/dist/esm/index.d.ts +3 -0
  52. package/dist/esm/index.js +32 -0
  53. package/dist/esm/index.test.d.ts +1 -0
  54. package/dist/esm/index.test.js +53 -0
  55. package/dist/esm/namespaces.d.ts +7 -0
  56. package/dist/esm/namespaces.js +6 -0
  57. package/dist/esm/namespaces.test.d.ts +1 -0
  58. package/dist/esm/namespaces.test.js +15 -0
  59. package/dist/esm/plugins/AwsApiGateway.d.ts +6 -0
  60. package/dist/esm/plugins/AwsApiGateway.js +214 -0
  61. package/dist/esm/plugins/AwsApiGateway.test.d.ts +1 -0
  62. package/dist/esm/plugins/AwsApiGateway.test.js +425 -0
  63. package/dist/esm/plugins/AwsIam.d.ts +32 -0
  64. package/dist/esm/plugins/AwsIam.js +428 -0
  65. package/dist/esm/plugins/AwsIam.test.d.ts +1 -0
  66. package/dist/esm/plugins/AwsIam.test.js +466 -0
  67. package/dist/esm/plugins/AwsS3.d.ts +12 -0
  68. package/dist/esm/plugins/AwsS3.js +103 -0
  69. package/dist/esm/plugins/AwsS3.test.d.ts +1 -0
  70. package/dist/esm/plugins/AwsS3.test.js +100 -0
  71. package/dist/esm/plugins/AwsSns.d.ts +6 -0
  72. package/dist/esm/plugins/AwsSns.js +48 -0
  73. package/dist/esm/plugins/AwsSns.test.d.ts +1 -0
  74. package/dist/esm/plugins/AwsSns.test.js +53 -0
  75. package/dist/esm/plugins/AwsTransferFamily.d.ts +6 -0
  76. package/dist/esm/plugins/AwsTransferFamily.js +101 -0
  77. package/dist/esm/plugins/AwsTransferFamily.test.d.ts +1 -0
  78. package/dist/esm/plugins/AwsTransferFamily.test.js +277 -0
  79. package/dist/esm/rules/dot.d.ts +3 -0
  80. package/dist/esm/rules/dot.js +34 -0
  81. package/dist/esm/rules/dot.test.d.ts +1 -0
  82. package/dist/esm/rules/dot.test.js +37 -0
  83. package/dist/esm/rules/general.d.ts +3 -0
  84. package/dist/esm/rules/general.js +67 -0
  85. package/dist/esm/rules/general.test.d.ts +1 -0
  86. package/dist/esm/rules/general.test.js +42 -0
  87. package/dist/esm/rulesets/dot.d.ts +3 -0
  88. package/dist/esm/rulesets/dot.js +23 -0
  89. package/dist/esm/rulesets/dot.test.d.ts +1 -0
  90. package/dist/esm/rulesets/dot.test.js +43 -0
  91. package/package.json +45 -0
@@ -0,0 +1,432 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.AwsIamGraphPlugin = exports.AWS_IAM_POLICY_DOCUMENT_MODES = exports.AWS_IAM_ATTACHMENT_MODES = exports.AWS_IAM_PLUGIN_MODES = void 0;
4
+ const core_1 = require("@terra-graph/core");
5
+ const namespaces_js_1 = require("../namespaces.js");
6
+ exports.AWS_IAM_PLUGIN_MODES = ['roles_only', 'roles_policies', 'full'];
7
+ exports.AWS_IAM_ATTACHMENT_MODES = ['remove', 'convert_to_edge', 'keep'];
8
+ exports.AWS_IAM_POLICY_DOCUMENT_MODES = ['none', 'trust_only', 'all'];
9
+ const IAM_ROLE_RESOURCES = ['aws_iam_role'];
10
+ const IAM_POLICY_RESOURCES = ['aws_iam_policy', 'aws_iam_role_policy'];
11
+ const IAM_ATTACHMENT_RESOURCES = ['aws_iam_role_policy_attachment', 'aws_iam_policy_attachment'];
12
+ const IAM_POLICY_DOCUMENT_RESOURCE = 'aws_iam_policy_document';
13
+ const IAM_DATA_POLICY_RESOURCE = 'aws_iam_policy';
14
+ const IAM_ORPHAN_PRUNABLE_RESOURCES = [
15
+ ...IAM_ROLE_RESOURCES,
16
+ ...IAM_POLICY_RESOURCES,
17
+ ...IAM_ATTACHMENT_RESOURCES,
18
+ ];
19
+ const IAM_ORPHAN_PRUNABLE_DATA_RESOURCES = [IAM_POLICY_DOCUMENT_RESOURCE, IAM_DATA_POLICY_RESOURCE];
20
+ class AwsIamGraphPlugin extends core_1.GraphPlugin {
21
+ static id = (0, namespaces_js_1.pluginId)(`aws.${AwsIamGraphPlugin.name}`);
22
+ constructor() {
23
+ super(AwsIamGraphPlugin.id, {
24
+ mode: 'roles_only',
25
+ });
26
+ }
27
+ build({ options, }) {
28
+ const resolved = this.resolveOptions(options);
29
+ const phases = [
30
+ ...this.toPhases('normalize', this.buildIamDirectionPhases()),
31
+ ...this.toPhases('main', this.buildIamLabelHintPhases()),
32
+ ...this.toPhases('main', this.buildAttachmentPhases(resolved)),
33
+ ];
34
+ if (resolved.mode !== 'full') {
35
+ phases.push(...this.toPhases('main', [
36
+ [
37
+ new core_1.RemoveNodeAndReconnectEdges({
38
+ node: {
39
+ and: [
40
+ {
41
+ attr: {
42
+ key: 'terraform.resource',
43
+ startsWith: 'aws_iam_',
44
+ },
45
+ },
46
+ {
47
+ not: {
48
+ attr: {
49
+ key: 'terraform.resource',
50
+ in: this.buildKeepResourcesForMode(resolved),
51
+ },
52
+ },
53
+ },
54
+ ],
55
+ },
56
+ }),
57
+ ],
58
+ ]));
59
+ if (resolved.policyDocuments === 'trust_only') {
60
+ phases.push(...this.toPhases('main', this.buildPolicyDocumentPhases(resolved)));
61
+ }
62
+ phases.push(...this.buildCleanupPhases(resolved));
63
+ return { phases };
64
+ }
65
+ phases.push(...this.toPhases('main', this.buildPolicyDocumentPhases(resolved)));
66
+ phases.push(...this.buildCleanupPhases(resolved));
67
+ return { phases };
68
+ }
69
+ toPhases(phase, phases) {
70
+ return phases.map((rules) => ({ phase, rules }));
71
+ }
72
+ isEnumValue(value, values) {
73
+ return typeof value === 'string' && values.includes(value);
74
+ }
75
+ resolveOptions(options) {
76
+ const mode = options.mode ?? 'roles_only';
77
+ if (!this.isEnumValue(mode, exports.AWS_IAM_PLUGIN_MODES)) {
78
+ throw new Error(`${this.name} options.mode must be one of: ${exports.AWS_IAM_PLUGIN_MODES.join(', ')}`);
79
+ }
80
+ const attachments = options.attachments ?? (mode === 'full' ? 'keep' : 'remove');
81
+ if (!this.isEnumValue(attachments, exports.AWS_IAM_ATTACHMENT_MODES)) {
82
+ throw new Error(`${this.name} options.attachments must be one of: ${exports.AWS_IAM_ATTACHMENT_MODES.join(', ')}`);
83
+ }
84
+ const policyDocuments = options.policyDocuments ?? (mode === 'full' ? 'all' : 'none');
85
+ if (!this.isEnumValue(policyDocuments, exports.AWS_IAM_POLICY_DOCUMENT_MODES)) {
86
+ throw new Error(`${this.name} options.policyDocuments must be one of: ${exports.AWS_IAM_POLICY_DOCUMENT_MODES.join(', ')}`);
87
+ }
88
+ const removeOrphans = options.removeOrphans ?? false;
89
+ if (typeof removeOrphans !== 'boolean') {
90
+ throw new Error(`${this.name} options.removeOrphans must be a boolean`);
91
+ }
92
+ return {
93
+ mode,
94
+ attachments,
95
+ policyDocuments,
96
+ removeOrphans,
97
+ };
98
+ }
99
+ buildKeepResourcesForMode(options) {
100
+ const keep = new Set(IAM_ROLE_RESOURCES);
101
+ if (options.mode === 'roles_policies') {
102
+ for (const resource of IAM_POLICY_RESOURCES) {
103
+ keep.add(resource);
104
+ }
105
+ }
106
+ if (options.attachments === 'keep') {
107
+ for (const resource of IAM_ATTACHMENT_RESOURCES) {
108
+ keep.add(resource);
109
+ }
110
+ }
111
+ if (options.policyDocuments !== 'none') {
112
+ keep.add(IAM_POLICY_DOCUMENT_RESOURCE);
113
+ }
114
+ return [...keep];
115
+ }
116
+ buildAttachmentPhases(options) {
117
+ if (options.attachments === 'keep') {
118
+ return [];
119
+ }
120
+ const phases = [];
121
+ if (options.attachments === 'convert_to_edge') {
122
+ phases.push([
123
+ new core_1.ConvertNodeToEdge({
124
+ node: {
125
+ attr: {
126
+ key: 'terraform.resource',
127
+ in: IAM_ATTACHMENT_RESOURCES,
128
+ },
129
+ },
130
+ }),
131
+ ]);
132
+ }
133
+ phases.push([
134
+ new core_1.RemoveNodeAndReconnectEdges({
135
+ node: {
136
+ attr: {
137
+ key: 'terraform.resource',
138
+ in: IAM_ATTACHMENT_RESOURCES,
139
+ },
140
+ },
141
+ }),
142
+ ]);
143
+ return phases;
144
+ }
145
+ buildIamDirectionPhases() {
146
+ return [
147
+ [
148
+ new core_1.EdgeReverse({
149
+ edge: {
150
+ from: this.iamDataQuery(),
151
+ to: this.iamResourceQuery('aws_iam_role_policy'),
152
+ },
153
+ }),
154
+ new core_1.EdgeReverse({
155
+ edge: {
156
+ from: this.iamResourceQuery('aws_iam_role_policy'),
157
+ to: this.iamResourceQuery('aws_iam_role_policy_attachment'),
158
+ },
159
+ }),
160
+ new core_1.EdgeReverse({
161
+ edge: {
162
+ from: this.iamDataQuery(),
163
+ to: this.iamResourceQuery('aws_iam_policy'),
164
+ },
165
+ }),
166
+ new core_1.EdgeReverse({
167
+ edge: {
168
+ from: this.iamResourceQuery('aws_iam_policy'),
169
+ to: this.iamResourceQuery('aws_iam_role_policy_attachment'),
170
+ },
171
+ }),
172
+ new core_1.EdgeReverse({
173
+ edge: {
174
+ from: this.iamResourceQuery('aws_iam_policy'),
175
+ to: this.iamResourceQuery('aws_iam_policy_attachment'),
176
+ },
177
+ }),
178
+ new core_1.EdgeReverse({
179
+ edge: {
180
+ from: this.iamResourceQuery('aws_iam_role'),
181
+ to: this.iamAttachmentQuery(),
182
+ },
183
+ }),
184
+ new core_1.EdgeReverse({
185
+ edge: {
186
+ from: this.iamAttachmentQuery(),
187
+ to: this.anyNonIamResourceQuery(),
188
+ },
189
+ }),
190
+ new core_1.EdgeReverse({
191
+ edge: {
192
+ from: this.iamDataQuery(),
193
+ to: this.iamResourceQuery('aws_iam_role'),
194
+ },
195
+ }),
196
+ new core_1.EdgeReverse({
197
+ edge: {
198
+ from: this.iamResourceQuery('aws_iam_role'),
199
+ to: this.anyNonIamResourceQuery(),
200
+ },
201
+ }),
202
+ ],
203
+ ];
204
+ }
205
+ buildIamLabelHintPhases() {
206
+ return [
207
+ [
208
+ new core_1.NodeProperties({
209
+ node: {
210
+ and: [
211
+ {
212
+ attr: {
213
+ key: 'terraform.kind',
214
+ in: ['resource', 'data'],
215
+ },
216
+ },
217
+ {
218
+ attr: {
219
+ key: 'terraform.resource',
220
+ startsWith: 'aws_iam_',
221
+ },
222
+ },
223
+ {
224
+ attr: {
225
+ key: 'terraform.moduleAddress',
226
+ exists: true,
227
+ },
228
+ },
229
+ ],
230
+ },
231
+ options: {
232
+ hints: {
233
+ label: {
234
+ end: {
235
+ from: 'terraform.name',
236
+ },
237
+ },
238
+ },
239
+ },
240
+ }),
241
+ ],
242
+ ];
243
+ }
244
+ iamDataQuery() {
245
+ return {
246
+ and: [
247
+ {
248
+ attr: {
249
+ key: 'terraform.kind',
250
+ eq: 'data',
251
+ },
252
+ },
253
+ {
254
+ attr: {
255
+ key: 'terraform.resource',
256
+ startsWith: 'aws_iam_',
257
+ },
258
+ },
259
+ ],
260
+ };
261
+ }
262
+ iamResourceQuery(resource) {
263
+ return {
264
+ and: [
265
+ {
266
+ attr: {
267
+ key: 'terraform.kind',
268
+ eq: 'resource',
269
+ },
270
+ },
271
+ {
272
+ attr: {
273
+ key: 'terraform.resource',
274
+ eq: resource,
275
+ },
276
+ },
277
+ ],
278
+ };
279
+ }
280
+ iamAttachmentQuery() {
281
+ return {
282
+ and: [
283
+ {
284
+ attr: {
285
+ key: 'terraform.kind',
286
+ eq: 'resource',
287
+ },
288
+ },
289
+ {
290
+ attr: {
291
+ key: 'terraform.resource',
292
+ in: IAM_ATTACHMENT_RESOURCES,
293
+ },
294
+ },
295
+ ],
296
+ };
297
+ }
298
+ anyNonIamResourceQuery() {
299
+ return {
300
+ and: [
301
+ {
302
+ attr: {
303
+ key: 'terraform.kind',
304
+ eq: 'resource',
305
+ },
306
+ },
307
+ {
308
+ not: {
309
+ attr: {
310
+ key: 'terraform.resource',
311
+ startsWith: 'aws_iam_',
312
+ },
313
+ },
314
+ },
315
+ ],
316
+ };
317
+ }
318
+ orphanPrunableIamQuery() {
319
+ return {
320
+ or: [
321
+ {
322
+ and: [
323
+ {
324
+ attr: {
325
+ key: 'terraform.kind',
326
+ eq: 'resource',
327
+ },
328
+ },
329
+ {
330
+ attr: {
331
+ key: 'terraform.resource',
332
+ in: IAM_ORPHAN_PRUNABLE_RESOURCES,
333
+ },
334
+ },
335
+ ],
336
+ },
337
+ {
338
+ and: [
339
+ {
340
+ attr: {
341
+ key: 'terraform.kind',
342
+ eq: 'data',
343
+ },
344
+ },
345
+ {
346
+ attr: {
347
+ key: 'terraform.resource',
348
+ in: IAM_ORPHAN_PRUNABLE_DATA_RESOURCES,
349
+ },
350
+ },
351
+ ],
352
+ },
353
+ ],
354
+ };
355
+ }
356
+ buildCleanupPhases(options) {
357
+ const phases = [...this.toPhases('cleanup', this.buildIamDirectionPhases())];
358
+ if (!options.removeOrphans) {
359
+ return phases;
360
+ }
361
+ phases.push(...this.toPhases('cleanup', [
362
+ [
363
+ new core_1.RemoveLeafChain({
364
+ node: this.orphanPrunableIamQuery(),
365
+ }),
366
+ ],
367
+ ]));
368
+ return phases;
369
+ }
370
+ buildPolicyDocumentPhases(options) {
371
+ if (options.policyDocuments === 'all') {
372
+ return [];
373
+ }
374
+ if (options.policyDocuments === 'none') {
375
+ return [
376
+ [
377
+ new core_1.RemoveNodeAndReconnectEdges({
378
+ node: {
379
+ attr: {
380
+ key: 'terraform.resource',
381
+ eq: IAM_POLICY_DOCUMENT_RESOURCE,
382
+ },
383
+ },
384
+ }),
385
+ ],
386
+ ];
387
+ }
388
+ return [
389
+ [
390
+ new core_1.RemoveNodeAndReconnectEdges({
391
+ node: {
392
+ and: [
393
+ {
394
+ attr: {
395
+ key: 'terraform.resource',
396
+ eq: IAM_POLICY_DOCUMENT_RESOURCE,
397
+ },
398
+ },
399
+ {
400
+ not: {
401
+ or: [
402
+ {
403
+ edge: {
404
+ in: {
405
+ attr: {
406
+ key: 'terraform.resource',
407
+ eq: 'aws_iam_role',
408
+ },
409
+ },
410
+ },
411
+ },
412
+ {
413
+ edge: {
414
+ out: {
415
+ attr: {
416
+ key: 'terraform.resource',
417
+ eq: 'aws_iam_role',
418
+ },
419
+ },
420
+ },
421
+ },
422
+ ],
423
+ },
424
+ },
425
+ ],
426
+ },
427
+ }),
428
+ ],
429
+ ];
430
+ }
431
+ }
432
+ exports.AwsIamGraphPlugin = AwsIamGraphPlugin;