@mitre/hdf-converters 2.6.21 → 2.6.24

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 (67) hide show
  1. package/lib/index.d.ts +2 -1
  2. package/lib/index.js +4 -2
  3. package/lib/index.js.map +1 -1
  4. package/lib/package.json +4 -4
  5. package/lib/src/asff-mapper/asff-mapper.d.ts +106 -0
  6. package/lib/src/asff-mapper/asff-mapper.js +462 -0
  7. package/lib/src/asff-mapper/asff-mapper.js.map +1 -0
  8. package/lib/src/asff-mapper/case-firewall-manager.d.ts +1 -0
  9. package/lib/src/asff-mapper/case-firewall-manager.js +27 -0
  10. package/lib/src/asff-mapper/case-firewall-manager.js.map +1 -0
  11. package/lib/src/asff-mapper/case-hdf2asff.d.ts +1 -0
  12. package/lib/src/asff-mapper/case-hdf2asff.js +192 -0
  13. package/lib/src/asff-mapper/case-hdf2asff.js.map +1 -0
  14. package/lib/src/asff-mapper/case-prowler.d.ts +1 -0
  15. package/lib/src/asff-mapper/case-prowler.js +39 -0
  16. package/lib/src/asff-mapper/case-prowler.js.map +1 -0
  17. package/lib/src/asff-mapper/case-security-hub.d.ts +1 -0
  18. package/lib/src/asff-mapper/case-security-hub.js +136 -0
  19. package/lib/src/asff-mapper/case-security-hub.js.map +1 -0
  20. package/lib/src/asff-mapper/case-trivy.d.ts +1 -0
  21. package/lib/src/asff-mapper/case-trivy.js +71 -0
  22. package/lib/src/asff-mapper/case-trivy.js.map +1 -0
  23. package/lib/src/base-converter.js +8 -12
  24. package/lib/src/base-converter.js.map +1 -1
  25. package/lib/src/burpsuite-mapper.js +2 -2
  26. package/lib/src/burpsuite-mapper.js.map +1 -1
  27. package/lib/src/converters-from-hdf/asff/transformers.js +8 -4
  28. package/lib/src/converters-from-hdf/asff/transformers.js.map +1 -1
  29. package/lib/src/converters-from-hdf/splunk/reverse-splunk-mapper.d.ts +2 -2
  30. package/lib/src/converters-from-hdf/splunk/reverse-splunk-mapper.js +2 -2
  31. package/lib/src/converters-from-hdf/splunk/reverse-splunk-mapper.js.map +1 -1
  32. package/lib/src/converters-from-hdf/splunk/splunk-profile-types.d.ts +1 -1
  33. package/lib/src/converters-from-hdf/splunk/splunk-report-types.d.ts +2 -1
  34. package/lib/src/fortify-mapper.js +1 -3
  35. package/lib/src/fortify-mapper.js.map +1 -1
  36. package/lib/src/ionchannel-mapper.d.ts +27 -0
  37. package/lib/src/ionchannel-mapper.js +268 -0
  38. package/lib/src/ionchannel-mapper.js.map +1 -0
  39. package/lib/src/jfrog-xray-mapper.js +2 -2
  40. package/lib/src/jfrog-xray-mapper.js.map +1 -1
  41. package/lib/src/mappings/ScoutsuiteNistMapping.js +3 -3
  42. package/lib/src/mappings/ScoutsuiteNistMapping.js.map +1 -1
  43. package/lib/src/nessus-mapper.js +8 -3
  44. package/lib/src/nessus-mapper.js.map +1 -1
  45. package/lib/src/netsparker-mapper.js +2 -2
  46. package/lib/src/netsparker-mapper.js.map +1 -1
  47. package/lib/src/prisma-mapper.js +2 -2
  48. package/lib/src/prisma-mapper.js.map +1 -1
  49. package/lib/src/sarif-mapper.js +8 -4
  50. package/lib/src/sarif-mapper.js.map +1 -1
  51. package/lib/src/snyk-mapper.d.ts +3 -1
  52. package/lib/src/snyk-mapper.js +25 -19
  53. package/lib/src/snyk-mapper.js.map +1 -1
  54. package/lib/src/splunk-mapper.d.ts +3 -2
  55. package/lib/src/splunk-mapper.js +5 -5
  56. package/lib/src/splunk-mapper.js.map +1 -1
  57. package/lib/src/utils/global.d.ts +4 -2
  58. package/lib/src/utils/global.js +11 -6
  59. package/lib/src/utils/global.js.map +1 -1
  60. package/lib/src/xccdf-results-mapper.js +2 -2
  61. package/lib/src/xccdf-results-mapper.js.map +1 -1
  62. package/lib/src/zap-mapper.js +2 -8
  63. package/lib/src/zap-mapper.js.map +1 -1
  64. package/package.json +4 -4
  65. package/lib/src/asff-mapper.d.ts +0 -25
  66. package/lib/src/asff-mapper.js +0 -887
  67. package/lib/src/asff-mapper.js.map +0 -1
@@ -1,887 +0,0 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.ASFFResults = exports.ASFFMapper = void 0;
7
- const html_entities_1 = require("html-entities");
8
- const inspecjs_1 = require("inspecjs");
9
- const lodash_1 = __importDefault(require("lodash"));
10
- const package_json_1 = require("../package.json");
11
- const base_converter_1 = require("./base-converter");
12
- const AwsConfigMapping_1 = require("./mappings/AwsConfigMapping");
13
- const IMPACT_MAPPING = new Map([
14
- ['CRITICAL', 0.9],
15
- ['HIGH', 0.7],
16
- ['MEDIUM', 0.5],
17
- ['LOW', 0.3],
18
- ['INFORMATIONAL', 0.0]
19
- ]);
20
- const DEFAULT_NIST_TAG = ['SA-11', 'RA-5'];
21
- const SEVERITY_LABEL = 'Severity.Label';
22
- const COMPLIANCE_STATUS = 'Compliance.Status';
23
- var SpecialCasing;
24
- (function (SpecialCasing) {
25
- SpecialCasing["FirewallManager"] = "AWS Firewall Manager";
26
- SpecialCasing["Prowler"] = "Prowler";
27
- SpecialCasing["SecurityHub"] = "AWS Security Hub";
28
- SpecialCasing["Trivy"] = "Aqua Trivy";
29
- SpecialCasing["HDF2ASFF"] = "MITRE SAF HDF2ASFF";
30
- SpecialCasing["Default"] = "Default";
31
- })(SpecialCasing || (SpecialCasing = {}));
32
- function whichSpecialCase(finding) {
33
- const productArn = lodash_1.default.get(finding, 'ProductArn');
34
- if (!productArn) {
35
- console.trace(finding, productArn);
36
- }
37
- if (productArn.match(/^arn:[^:]+:securityhub:[^:]+:[^:]*:product\/aws\/firewall-manager$/)) {
38
- return SpecialCasing.FirewallManager;
39
- }
40
- else if (productArn.match(/^arn:[^:]+:securityhub:[^:]+:[^:]*:product\/prowler\/prowler$/)) {
41
- return SpecialCasing.Prowler;
42
- }
43
- else if (productArn.match(/^arn:[^:]+:securityhub:[^:]+:[^:]*:product\/aws\/securityhub$/)) {
44
- return SpecialCasing.SecurityHub;
45
- }
46
- else if (productArn.match(/^arn:[^:]+:securityhub:[^:]+:[^:]*:product\/aquasecurity\/aquasecurity$/)) {
47
- return SpecialCasing.Trivy;
48
- }
49
- else if (lodash_1.default.some(lodash_1.default.get(finding, 'FindingProviderFields.Types'), (type) => {
50
- const version = type.split('/')[2].split('-')[0];
51
- const [major, minor, patch] = version.split('.');
52
- if (parseInt(major) > 1 &&
53
- parseInt(minor) > 5 &&
54
- parseInt(patch) > 20) {
55
- return lodash_1.default.startsWith(type, 'MITRE/SAF/');
56
- }
57
- else {
58
- return false;
59
- }
60
- })) {
61
- return SpecialCasing.HDF2ASFF;
62
- }
63
- else {
64
- return SpecialCasing.Default;
65
- }
66
- }
67
- const SPECIAL_CASE_MAPPING = new Map([
68
- [SpecialCasing.FirewallManager, getFirewallManager()],
69
- [SpecialCasing.Prowler, getProwler()],
70
- [SpecialCasing.SecurityHub, getSecurityHub()],
71
- [SpecialCasing.Trivy, getTrivy()],
72
- [SpecialCasing.HDF2ASFF, getHDF2ASFF()]
73
- ]);
74
- function externalProductHandler(context, product, data, func, defaultVal) {
75
- var _a;
76
- if (product !== SpecialCasing.Default &&
77
- lodash_1.default.has(SPECIAL_CASE_MAPPING.get(product), func)) {
78
- let keywords = {};
79
- if (context.supportingDocs.has(product)) {
80
- keywords = { ...context.supportingDocs.get(product) };
81
- }
82
- return (_a = lodash_1.default.get(SPECIAL_CASE_MAPPING.get(product), func)) === null || _a === void 0 ? void 0 : _a.apply(context, [
83
- data,
84
- keywords
85
- ]);
86
- }
87
- else {
88
- if (typeof defaultVal === 'function') {
89
- return defaultVal();
90
- }
91
- else {
92
- return defaultVal;
93
- }
94
- }
95
- }
96
- function consolidate(context, input, file) {
97
- const allFindings = lodash_1.default.get(file, 'Findings');
98
- if (input.length !== allFindings.length) {
99
- throw new Error('The number of generated controls should be the same as the number of findings at this point in the process.');
100
- }
101
- const idGroups = lodash_1.default.groupBy(lodash_1.default.zip(input, allFindings), (value) => {
102
- const [hdfControl, asffFinding] = value;
103
- return externalProductHandler(context, whichSpecialCase(asffFinding), asffFinding, 'subfindingsId', lodash_1.default.get(hdfControl, 'id'));
104
- });
105
- const output = [];
106
- Object.entries(idGroups || {}).forEach((idGroup) => {
107
- const [id, data] = idGroup;
108
- const group = data.map((d) => d[0]);
109
- const findings = data.map((d) => d[1]);
110
- const productInfo = lodash_1.default.get(findings[0], 'ProductArn')
111
- .split(':')
112
- .slice(-1)[0]
113
- .split('/');
114
- const productName = externalProductHandler(context, whichSpecialCase(findings[0]), findings, 'productName', (0, html_entities_1.encode)(`${productInfo[1]}/${productInfo[2]}`));
115
- const hasNoTitlePrefix = externalProductHandler(context, whichSpecialCase(findings[0]), null, 'doesNotHaveFindingTitlePrefix', false);
116
- const titlePrefix = hasNoTitlePrefix ? '' : `${productName}: `;
117
- const waiverData = externalProductHandler(context, whichSpecialCase(findings[0]), group, 'waiverData', {});
118
- const item = {
119
- id: id,
120
- title: `${titlePrefix}${lodash_1.default.uniq(group.map((d) => d.title)).join(';')}`,
121
- tags: lodash_1.default.mergeWith({}, ...group.map((d) => d.tags), (acc, cur) => {
122
- if (acc === undefined || cur === undefined) {
123
- return acc || cur;
124
- }
125
- else if (lodash_1.default.isEqual(acc, cur)) {
126
- return acc;
127
- }
128
- else {
129
- return lodash_1.default.uniq(lodash_1.default.concat([], acc, cur));
130
- }
131
- }),
132
- impact: Math.max(...group.map((d) => d.impact)),
133
- desc: externalProductHandler(context, whichSpecialCase(findings[0]), group, 'desc', lodash_1.default.uniq(group.map((d) => d.desc)).join('\n')),
134
- descriptions: group
135
- .map((d) => d.descriptions)
136
- .flat()
137
- .filter((element, index, arr) => element !== null &&
138
- element !== undefined &&
139
- element.data !== '' &&
140
- index ===
141
- arr.findIndex((e) => e !== null && e !== undefined && e.data === element.data)),
142
- refs: group
143
- .map((d) => d.refs)
144
- .flat()
145
- .filter((element) => lodash_1.default.get(element, 'url') !== undefined),
146
- source_location: (() => {
147
- const locs = lodash_1.default.uniq(group.map((d) => d.source_location)).filter((loc) => Object.keys(loc || {}).length !== 0);
148
- if (locs.length === 0) {
149
- return {};
150
- }
151
- else if (locs.length === 1) {
152
- return locs[0];
153
- }
154
- else {
155
- return { ref: JSON.stringify(locs) };
156
- }
157
- })(),
158
- ...(Object.keys(waiverData || {}).length !== 0 && {
159
- waiver_data: waiverData
160
- }),
161
- code: externalProductHandler(context, whichSpecialCase(findings[0]), group, 'code', JSON.stringify({ Findings: findings }, null, 2)),
162
- results: group.map((d) => d.results).flat()
163
- };
164
- output.push(item);
165
- });
166
- return output;
167
- }
168
- function wrapWithFindingsObject(output) {
169
- if (!lodash_1.default.has(output, 'Findings')) {
170
- if (Array.isArray(output)) {
171
- output = { Findings: output };
172
- }
173
- else {
174
- output = { Findings: [output] };
175
- }
176
- }
177
- return output;
178
- }
179
- function fixFileInput(asffJson) {
180
- let output = {};
181
- try {
182
- output = JSON.parse(asffJson);
183
- }
184
- catch {
185
- const fixedInput = `[${asffJson
186
- .trim()
187
- .replace(/}\n/g, '},\n')
188
- .replace(/\},\n\$/g, '')}]`;
189
- output = JSON.parse(fixedInput);
190
- }
191
- return wrapWithFindingsObject(output);
192
- }
193
- function getFirewallManager() {
194
- const findingId = (finding) => (0, html_entities_1.encode)(lodash_1.default.get(finding, 'Title'));
195
- const productName = (findings) => {
196
- const finding = Array.isArray(findings) ? findings[0] : findings;
197
- return (0, html_entities_1.encode)(`${lodash_1.default.get(finding, 'ProductFields.aws/securityhub/CompanyName')} ${lodash_1.default.get(finding, 'ProductFields.aws/securityhub/ProductName')}`);
198
- };
199
- const filename = (findingInfo) => {
200
- return `${productName(findingInfo[1])}.json`;
201
- };
202
- return {
203
- findingId,
204
- productName,
205
- filename
206
- };
207
- }
208
- function getProwler() {
209
- const subfindingsCodeDesc = (finding) => (0, html_entities_1.encode)(lodash_1.default.get(finding, 'Description'));
210
- const findingId = (finding) => {
211
- const generatorId = lodash_1.default.get(finding, 'GeneratorId');
212
- const hyphenIndex = generatorId.indexOf('-');
213
- return (0, html_entities_1.encode)(generatorId.slice(hyphenIndex + 1));
214
- };
215
- const productName = (findings) => {
216
- const finding = Array.isArray(findings) ? findings[0] : findings;
217
- return (0, html_entities_1.encode)(lodash_1.default.get(finding, 'ProductFields.ProviderName'));
218
- };
219
- const desc = () => ' ';
220
- const filename = (findingInfo) => {
221
- return `${productName(findingInfo[1])}.json`;
222
- };
223
- const meta = () => {
224
- return { name: 'Prowler', title: 'Prowler Findings' };
225
- };
226
- return {
227
- subfindingsCodeDesc,
228
- findingId,
229
- productName,
230
- desc,
231
- filename,
232
- meta
233
- };
234
- }
235
- function getSecurityHub() {
236
- const FINDING_STANDARDS_CONTROL_ARN = 'ProductFields.StandardsControlArn';
237
- const correspondingControl = (controls, finding) => {
238
- return controls.find((control) => lodash_1.default.get(control, 'StandardsControlArn') ===
239
- lodash_1.default.get(finding, FINDING_STANDARDS_CONTROL_ARN));
240
- };
241
- const securityhubSupportingDocs = (standards) => {
242
- let controls;
243
- try {
244
- if (Array.isArray(standards)) {
245
- controls = standards
246
- .map((standard) => lodash_1.default.get(JSON.parse(standard), 'Controls'))
247
- .flat();
248
- }
249
- else {
250
- controls = null;
251
- }
252
- }
253
- catch (error) {
254
- throw new Error(`Invalid supporting docs for Security Hub:\nException: ${error}`);
255
- }
256
- const AWS_CONFIG_MAPPING = new AwsConfigMapping_1.AwsConfigMapping();
257
- return {
258
- controls,
259
- awsConfigMapping: AWS_CONFIG_MAPPING
260
- };
261
- };
262
- const findingId = (finding, { controls = null }) => {
263
- let output;
264
- let control;
265
- if (controls !== null &&
266
- (control = correspondingControl(controls, finding)) !== null) {
267
- output = lodash_1.default.get(control, 'ControlId');
268
- }
269
- else if (lodash_1.default.has(finding, 'ProductFields.ControlId')) {
270
- output = lodash_1.default.get(finding, 'ProductFields.ControlId');
271
- }
272
- else if (lodash_1.default.has(finding, 'ProductFields.RuleId')) {
273
- output = lodash_1.default.get(finding, 'ProductFields.RuleId');
274
- }
275
- else {
276
- output = lodash_1.default.get(finding, 'GeneratorId').split('/').slice(-1)[0];
277
- }
278
- return (0, html_entities_1.encode)(output);
279
- };
280
- const findingImpact = (finding, { controls = null }) => {
281
- let impact;
282
- let control;
283
- if (controls !== null &&
284
- (control = correspondingControl(controls, finding)) !== null) {
285
- impact = lodash_1.default.get(control, 'SeverityRating');
286
- }
287
- else {
288
- impact =
289
- lodash_1.default.get(finding, SEVERITY_LABEL) ||
290
- lodash_1.default.get(finding, 'Severity.Normalized') / 100.0;
291
- if (typeof impact === 'string' && impact === 'INFORMATIONAL') {
292
- impact = 'MEDIUM';
293
- }
294
- }
295
- return impact;
296
- };
297
- const findingNistTag = (finding, { awsConfigMapping }) => {
298
- if (lodash_1.default.get(finding, 'ProductFields.RelatedAWSResources:0/type') !==
299
- 'AWS::Config::ConfigRule') {
300
- return [];
301
- }
302
- return awsConfigMapping.searchNIST([
303
- lodash_1.default.get(finding, 'ProductFields.RelatedAWSResources:0/name')
304
- ]);
305
- };
306
- const findingTitle = (finding, { controls = null }) => {
307
- let control;
308
- if (controls !== null &&
309
- (control = correspondingControl(controls, finding)) !== null) {
310
- return (0, html_entities_1.encode)(lodash_1.default.get(control, 'Title'));
311
- }
312
- else {
313
- return (0, html_entities_1.encode)(lodash_1.default.get(finding, 'Title'));
314
- }
315
- };
316
- const productName = (findings) => {
317
- const finding = Array.isArray(findings) ? findings[0] : findings;
318
- let standardName;
319
- if (lodash_1.default.get(finding, 'Types[0]')
320
- .split('/')
321
- .slice(-1)[0]
322
- .replace(/-/gi, ' ')
323
- .toLowerCase() ===
324
- lodash_1.default.get(finding, FINDING_STANDARDS_CONTROL_ARN)
325
- .split('/')
326
- .slice(-4)[0]
327
- .replace(/-/gi, ' ')
328
- .toLowerCase()) {
329
- standardName = lodash_1.default.get(finding, 'Types[0]')
330
- .split('/')
331
- .slice(-1)[0]
332
- .replace(/-/gi, ' ');
333
- }
334
- else {
335
- standardName = lodash_1.default.get(finding, FINDING_STANDARDS_CONTROL_ARN)
336
- .split('/')
337
- .slice(-4)[0]
338
- .replace(/-/gi, ' ')
339
- .split(/\s+/)
340
- .map((element) => {
341
- return element.charAt(0).toUpperCase() + element.slice(1);
342
- })
343
- .join(' ');
344
- }
345
- return (0, html_entities_1.encode)(`${standardName} v${lodash_1.default.get(finding, FINDING_STANDARDS_CONTROL_ARN)
346
- .split('/')
347
- .slice(-2)[0]}`);
348
- };
349
- const filename = (findingInfo) => {
350
- return `${productName(findingInfo[0])}.json`;
351
- };
352
- return {
353
- securityhubSupportingDocs,
354
- findingId,
355
- findingImpact,
356
- findingNistTag,
357
- findingTitle,
358
- productName,
359
- filename
360
- };
361
- }
362
- function getTrivy() {
363
- const findingId = (finding) => {
364
- const generatorId = lodash_1.default.get(finding, 'GeneratorId');
365
- const cveId = lodash_1.default.get(finding, 'Resources[0].Details.Other.CVE ID');
366
- if (typeof cveId === 'string') {
367
- return (0, html_entities_1.encode)(`${generatorId}/${cveId}`);
368
- }
369
- else {
370
- const id = lodash_1.default.get(finding, 'Id');
371
- return (0, html_entities_1.encode)(`${generatorId}/${id}`);
372
- }
373
- };
374
- const findingNistTag = (finding) => {
375
- const cveId = lodash_1.default.get(finding, 'Resources[0].Details.Other.CVE ID');
376
- if (typeof cveId === 'string') {
377
- return ['SI-2', 'RA-5'];
378
- }
379
- else {
380
- return [];
381
- }
382
- };
383
- const subfindingsStatus = () => {
384
- return inspecjs_1.ExecJSON.ControlResultStatus.Failed;
385
- };
386
- const subfindingsMessage = (finding) => {
387
- const cveId = lodash_1.default.get(finding, 'Resources[0].Details.Other.CVE ID');
388
- if (typeof cveId === 'string') {
389
- const patchedPackage = lodash_1.default.get(finding, 'Resources[0].Details.Other.Patched Package');
390
- const patchedVersionMessage = patchedPackage.length === 0
391
- ? 'There is no patched version of the package.'
392
- : `The package has been patched since version(s): ${patchedPackage}.`;
393
- return `For package ${lodash_1.default.get(finding, 'Resources[0].Details.Other.PkgName')}, the current version that is installed is ${lodash_1.default.get(finding, 'Resources[0].Details.Other.Installed Package')}. ${patchedVersionMessage}`;
394
- }
395
- else {
396
- return undefined;
397
- }
398
- };
399
- const productName = () => {
400
- return 'Aqua Security - Trivy';
401
- };
402
- const doesNotHaveFindingTitlePrefix = () => true;
403
- const filename = () => {
404
- return `${productName()}.json`;
405
- };
406
- const meta = () => {
407
- return { name: 'Trivy', title: 'Trivy Findings' };
408
- };
409
- return {
410
- findingId,
411
- findingNistTag,
412
- subfindingsStatus,
413
- subfindingsMessage,
414
- doesNotHaveFindingTitlePrefix,
415
- productName,
416
- filename,
417
- meta
418
- };
419
- }
420
- function getHDF2ASFF() {
421
- const replaceTypesSlashes = (type) => {
422
- if (!lodash_1.default.isString(type)) {
423
- return type;
424
- }
425
- const FROM_ASFF_TYPES_SLASH_REPLACEMENT = /{{{SLASH}}}/gi;
426
- return type.replace(FROM_ASFF_TYPES_SLASH_REPLACEMENT, '/');
427
- };
428
- const objectifyTypesArray = (typesArray) => {
429
- if (!Array.isArray(typesArray)) {
430
- typesArray = lodash_1.default.get(typesArray, 'FindingProviderFields.Types');
431
- }
432
- const ret = {};
433
- for (const typeString of typesArray) {
434
- lodash_1.default.merge(ret, (() => {
435
- const [type, attribute, value] = typeString.split('/');
436
- let parsed = replaceTypesSlashes(value);
437
- try {
438
- parsed = JSON.parse(parsed);
439
- }
440
- catch { }
441
- return { [type]: { [attribute]: parsed } };
442
- })());
443
- }
444
- return ret;
445
- };
446
- const findExecutionFindingIndex = (asffOrFindings, asffFindingToMatch) => {
447
- if (asffFindingToMatch) {
448
- const targetToMatch = asffFindingToMatch.Id.split('/')[0];
449
- return lodash_1.default.findIndex(Array.isArray(asffOrFindings)
450
- ? asffOrFindings
451
- : lodash_1.default.get(asffOrFindings, 'Findings'), (finding) => lodash_1.default.get(finding, 'Id').split('/').length === 2 &&
452
- lodash_1.default.get(finding, 'Id').startsWith(targetToMatch));
453
- }
454
- return lodash_1.default.findIndex(Array.isArray(asffOrFindings)
455
- ? asffOrFindings
456
- : lodash_1.default.get(asffOrFindings, 'Findings'), (finding) => lodash_1.default.get(finding, 'Id').split('/').length === 2);
457
- };
458
- const preprocessingASFF = (asff) => {
459
- const clone = lodash_1.default.cloneDeep(asff);
460
- const index = findExecutionFindingIndex(clone);
461
- lodash_1.default.pullAt(lodash_1.default.get(clone, 'Findings'), index);
462
- return clone;
463
- };
464
- const supportingDocs = (input) => {
465
- const [asff, docs] = input;
466
- const index = findExecutionFindingIndex(asff);
467
- const docsClone = lodash_1.default.cloneDeep(docs);
468
- docsClone.set(SpecialCasing.HDF2ASFF, {
469
- execution: lodash_1.default.get(asff, `Findings[${index}]`)
470
- });
471
- return docsClone;
472
- };
473
- const productName = (findings) => {
474
- const finding = Array.isArray(findings) ? findings[0] : findings;
475
- const name = lodash_1.default.get(finding, 'Id');
476
- return (0, html_entities_1.encode)(name.split('/').slice(0, 2).join(' - '));
477
- };
478
- const doesNotHaveFindingTitlePrefix = () => true;
479
- const code = (group) => {
480
- return group[0].code || '';
481
- };
482
- const waiverData = (group) => {
483
- return group[0].waiver_data || {};
484
- };
485
- const filename = (findingInfo) => {
486
- const index = findExecutionFindingIndex(findingInfo[1], findingInfo[0]);
487
- const target = replaceTypesSlashes(lodash_1.default.get(findingInfo[1][index], 'Id').split('/')[0]);
488
- const finding = findingInfo[0];
489
- return `${lodash_1.default.get(objectifyTypesArray(finding), 'File.Input')}-${target}.json`;
490
- };
491
- const mapping = (context) => {
492
- var _a;
493
- const execution = lodash_1.default.get(context.supportingDocs.get(SpecialCasing.HDF2ASFF), 'execution');
494
- const executionTypes = objectifyTypesArray(execution);
495
- const profileNames = Object.keys(executionTypes || {}).filter((type) => !['MITRE', 'File', 'Execution'].includes(type));
496
- return {
497
- shortcircuit: true,
498
- platform: {
499
- ...lodash_1.default.get(executionTypes, 'Execution.platform'),
500
- target_id: ((_a = context.supportingDocs.get(SpecialCasing.HDF2ASFF)) === null || _a === void 0 ? void 0 : _a.execution.Id).split('/')[0]
501
- },
502
- version: lodash_1.default.get(executionTypes, 'Execution.version'),
503
- statistics: lodash_1.default.get(executionTypes, 'Execution.statistics'),
504
- profiles: lodash_1.default.map(profileNames, (profileName, index) => {
505
- return {
506
- name: lodash_1.default.get(executionTypes, `${profileName}.name`),
507
- ...(lodash_1.default.has(executionTypes, `${profileName}.version`) && {
508
- version: lodash_1.default.get(executionTypes, `${profileName}.version`)
509
- }),
510
- ...(lodash_1.default.has(executionTypes, `${profileName}.title`) && {
511
- title: lodash_1.default.get(executionTypes, `${profileName}.title`)
512
- }),
513
- ...(lodash_1.default.has(executionTypes, `${profileName}.maintainer`) && {
514
- maintainer: lodash_1.default.get(executionTypes, `${profileName}.maintainer`)
515
- }),
516
- ...(lodash_1.default.has(executionTypes, `${profileName}.summary`) && {
517
- summary: lodash_1.default.get(executionTypes, `${profileName}.summary`)
518
- }),
519
- ...(lodash_1.default.has(executionTypes, `${profileName}.license`) && {
520
- license: lodash_1.default.get(executionTypes, `${profileName}.license`)
521
- }),
522
- ...(lodash_1.default.has(executionTypes, `${profileName}.copyright`) && {
523
- copyright: lodash_1.default.get(executionTypes, `${profileName}.copyright`)
524
- }),
525
- ...(lodash_1.default.has(executionTypes, `${profileName}.copyright_email`) && {
526
- copyright_email: lodash_1.default.get(executionTypes, `${profileName}.copyright_email`)
527
- }),
528
- supports: lodash_1.default.get(executionTypes, `${profileName}.supports`, []),
529
- attributes: lodash_1.default.get(executionTypes, `${profileName}.attributes`, []),
530
- ...(lodash_1.default.has(executionTypes, `${profileName}.depends`) && {
531
- depends: lodash_1.default.get(executionTypes, `${profileName}.depends`)
532
- }),
533
- groups: [],
534
- ...(lodash_1.default.has(executionTypes, `${profileName}.status`) && {
535
- status: lodash_1.default.get(executionTypes, `${profileName}.status`)
536
- }),
537
- ...(lodash_1.default.has(executionTypes, `${profileName}.description`) && {
538
- description: lodash_1.default.get(executionTypes, `${profileName}.description`)
539
- }),
540
- ...(lodash_1.default.has(executionTypes, `${profileName}.inspec_version`) && {
541
- inspec_version: lodash_1.default.get(executionTypes, `${profileName}.inspec_version`)
542
- }),
543
- ...(lodash_1.default.has(executionTypes, `${profileName}.parent_profile`) && {
544
- parent_profile: lodash_1.default.get(executionTypes, `${profileName}.parent_profile`)
545
- }),
546
- ...(lodash_1.default.has(executionTypes, `${profileName}.skip_message`) && {
547
- skip_message: lodash_1.default.get(executionTypes, `${profileName}.skip_message`)
548
- }),
549
- ...(lodash_1.default.has(executionTypes, `${profileName}.status_message`) && {
550
- status_message: lodash_1.default.get(executionTypes, `${profileName}.status_message`)
551
- }),
552
- controls: consolidate(context, (() => {
553
- console.log('findings length', lodash_1.default.get(context.data, 'Findings')
554
- .length);
555
- return lodash_1.default.map(lodash_1.default.get(context.data, 'Findings'), (finding) => {
556
- const findingTypes = objectifyTypesArray(finding);
557
- return {
558
- id: lodash_1.default.get(findingTypes, 'Control.ID'),
559
- ...(lodash_1.default.has(findingTypes, 'Control.Title') && {
560
- title: lodash_1.default.get(findingTypes, 'Control.Title')
561
- }),
562
- ...(lodash_1.default.has(findingTypes, 'Control.Desc') && {
563
- desc: lodash_1.default.get(findingTypes, 'Control.Desc')
564
- }),
565
- impact: lodash_1.default.get(findingTypes, 'Control.Impact'),
566
- tags: {
567
- ...lodash_1.default.omit(lodash_1.default.get(findingTypes, 'Tags'), ['nist']),
568
- nist: (() => {
569
- const nisttags = lodash_1.default.get(findingTypes, 'Tags.nist');
570
- if (nisttags === undefined || nisttags.length === 0) {
571
- return DEFAULT_NIST_TAG;
572
- }
573
- else {
574
- return nisttags;
575
- }
576
- })()
577
- },
578
- descriptions: lodash_1.default.map(Object.entries(lodash_1.default.get(findingTypes, 'Descriptions') || {}), ([key, value]) => ({ label: key, data: value })),
579
- refs: lodash_1.default.get(findingTypes, 'Control.Refs', []),
580
- source_location: lodash_1.default.get(findingTypes, 'Control.Source_Location', {}),
581
- ...(lodash_1.default.has(findingTypes, 'Control.Waiver_Data') && {
582
- waiver_data: lodash_1.default.get(findingTypes, 'Control.Waiver_Data')
583
- }),
584
- code: '',
585
- results: index === profileNames.length - 1
586
- ? [
587
- {
588
- code_desc: lodash_1.default.get(findingTypes, 'Segment.code_desc'),
589
- start_time: lodash_1.default.get(findingTypes, 'Segment.start_time'),
590
- ...lodash_1.default.omit(lodash_1.default.get(findingTypes, 'Segment'), [
591
- 'code_desc',
592
- 'start_time'
593
- ])
594
- }
595
- ]
596
- : []
597
- };
598
- });
599
- })(), context.data),
600
- sha256: lodash_1.default.get(executionTypes, `${profileName}.sha256`)
601
- };
602
- })
603
- };
604
- };
605
- return {
606
- preprocessingASFF,
607
- supportingDocs,
608
- productName,
609
- doesNotHaveFindingTitlePrefix,
610
- code,
611
- waiverData,
612
- filename,
613
- mapping
614
- };
615
- }
616
- class ASFFMapper extends base_converter_1.BaseConverter {
617
- constructor(asff, supportingDocs, meta = undefined) {
618
- super(asff);
619
- this.meta = meta;
620
- this.supportingDocs = supportingDocs;
621
- this.setMappings();
622
- }
623
- statusReason(finding) {
624
- var _a;
625
- return (_a = lodash_1.default.get(finding, 'Compliance.StatusReasons')) === null || _a === void 0 ? void 0 : _a.map((reason) => Object.entries(reason || {}).map(([key, value]) => {
626
- return `${(0, html_entities_1.encode)(key)}: ${(0, html_entities_1.encode)(value)}`;
627
- })).flat().join('\n');
628
- }
629
- setMappings() {
630
- this.mappings = externalProductHandler(this, whichSpecialCase(lodash_1.default.get(this.data, 'Findings[0]')), this, 'mapping', {
631
- platform: {
632
- name: 'Heimdall Tools',
633
- release: package_json_1.version,
634
- target_id: {
635
- transformer: (record) => {
636
- const productInfo = lodash_1.default.get(record, 'Findings[0].ProductArn')
637
- .split(':')
638
- .slice(-1)[0]
639
- .split('/');
640
- const defaultTargetId = `${productInfo[1]} | ${productInfo[2]}`;
641
- return externalProductHandler(this, whichSpecialCase(lodash_1.default.get(record, 'Findings[0]')), [lodash_1.default.get(record, 'Findings[0]'), record.Findings], 'productName', (0, html_entities_1.encode)(defaultTargetId));
642
- }
643
- }
644
- },
645
- version: package_json_1.version,
646
- statistics: {
647
- duration: null
648
- },
649
- profiles: [
650
- {
651
- name: {
652
- transformer: () => {
653
- var _a;
654
- return ((_a = this.meta) === null || _a === void 0 ? void 0 : _a.name) || 'AWS Security Finding Format';
655
- }
656
- },
657
- version: '',
658
- title: {
659
- transformer: () => {
660
- return lodash_1.default.get(this.meta, 'title') || 'ASFF Findings';
661
- }
662
- },
663
- maintainer: null,
664
- summary: '',
665
- license: null,
666
- copyright: null,
667
- copyright_email: null,
668
- supports: [],
669
- attributes: [],
670
- depends: [],
671
- groups: [],
672
- status: 'loaded',
673
- controls: [
674
- {
675
- path: 'Findings',
676
- key: 'id',
677
- arrayTransformer: consolidate.bind(this, this),
678
- id: {
679
- transformer: (finding) => externalProductHandler(this, whichSpecialCase(finding), finding, 'findingId', (0, html_entities_1.encode)(lodash_1.default.get(finding, 'GeneratorId')))
680
- },
681
- title: {
682
- transformer: (finding) => externalProductHandler(this, whichSpecialCase(finding), finding, 'findingTitle', (0, html_entities_1.encode)(lodash_1.default.get(finding, 'Title')))
683
- },
684
- desc: {
685
- path: 'Description',
686
- transformer: (input) => (0, html_entities_1.encode)(input)
687
- },
688
- impact: {
689
- transformer: (finding) => {
690
- let impact;
691
- if (lodash_1.default.get(finding, 'Workflow.Status') === 'SUPPRESSED') {
692
- impact = 'INFORMATIONAL';
693
- }
694
- else {
695
- const defaultFunc = () => lodash_1.default.get(finding, SEVERITY_LABEL)
696
- ? lodash_1.default.get(finding, SEVERITY_LABEL)
697
- : lodash_1.default.get(finding, 'Severity.Normalized') /
698
- 100.0;
699
- impact = externalProductHandler(this, whichSpecialCase(finding), finding, 'findingImpact', defaultFunc);
700
- }
701
- return typeof impact === 'string'
702
- ? IMPACT_MAPPING.get(impact) || 0
703
- : impact;
704
- }
705
- },
706
- tags: {
707
- transformer: (finding) => externalProductHandler(this, whichSpecialCase(finding), finding, 'findingTags', {}),
708
- nist: {
709
- transformer: (finding) => {
710
- const tags = externalProductHandler(this, whichSpecialCase(finding), finding, 'findingNistTag', []);
711
- if (tags.length === 0) {
712
- return DEFAULT_NIST_TAG;
713
- }
714
- else {
715
- return tags;
716
- }
717
- }
718
- }
719
- },
720
- descriptions: [
721
- {
722
- data: {
723
- path: 'Remediation.Recommendation',
724
- transformer: (input) => {
725
- const data = [];
726
- if (lodash_1.default.has(input, 'Text')) {
727
- data.push(lodash_1.default.get(input, 'Text'));
728
- }
729
- if (lodash_1.default.has(input, 'Url')) {
730
- data.push(lodash_1.default.get(input, 'Url'));
731
- }
732
- return data.join('\n');
733
- }
734
- },
735
- label: 'fix'
736
- }
737
- ],
738
- refs: [
739
- {
740
- transformer: (finding) => {
741
- return {
742
- ...(lodash_1.default.has(finding, 'SourceUrl') && {
743
- url: {
744
- path: 'SourceUrl'
745
- }
746
- })
747
- };
748
- }
749
- }
750
- ],
751
- source_location: {},
752
- code: '',
753
- results: [
754
- {
755
- status: {
756
- transformer: (finding) => {
757
- const defaultFunc = () => {
758
- if (lodash_1.default.has(finding, COMPLIANCE_STATUS)) {
759
- switch (lodash_1.default.get(finding, COMPLIANCE_STATUS)) {
760
- case 'PASSED':
761
- return inspecjs_1.ExecJSON.ControlResultStatus.Passed;
762
- case 'WARNING':
763
- return inspecjs_1.ExecJSON.ControlResultStatus.Skipped;
764
- case 'FAILED':
765
- return inspecjs_1.ExecJSON.ControlResultStatus.Failed;
766
- case 'NOT_AVAILABLE':
767
- return inspecjs_1.ExecJSON.ControlResultStatus.Skipped;
768
- default:
769
- return inspecjs_1.ExecJSON.ControlResultStatus.Error;
770
- }
771
- }
772
- else {
773
- return inspecjs_1.ExecJSON.ControlResultStatus.Skipped;
774
- }
775
- };
776
- return externalProductHandler(this, whichSpecialCase(finding), finding, 'subfindingsStatus', defaultFunc);
777
- }
778
- },
779
- code_desc: {
780
- transformer: (finding) => {
781
- let output = externalProductHandler(this, whichSpecialCase(finding), finding, 'subfindingsCodeDesc', '');
782
- if (output) {
783
- output += '; ';
784
- }
785
- const resources = lodash_1.default.get(finding, 'Resources')
786
- .map((resource) => {
787
- let hash = `Type: ${(0, html_entities_1.encode)(lodash_1.default.get(resource, 'Type'))}, Id: ${(0, html_entities_1.encode)(lodash_1.default.get(resource, 'Id'))}`;
788
- if (lodash_1.default.has(resource, 'Partition')) {
789
- hash += `, Partition: ${(0, html_entities_1.encode)(lodash_1.default.get(resource, 'Partition'))}`;
790
- }
791
- if (lodash_1.default.has(resource, 'Region')) {
792
- hash += `, Region: ${(0, html_entities_1.encode)(lodash_1.default.get(resource, 'Region'))}`;
793
- }
794
- return hash;
795
- })
796
- .join(', ');
797
- output += `Resources: [${resources}]`;
798
- return output;
799
- }
800
- },
801
- transformer: (finding) => {
802
- const message = (() => {
803
- const defaultFunc = () => {
804
- const statusReason = this.statusReason(finding);
805
- switch (lodash_1.default.get(finding, COMPLIANCE_STATUS)) {
806
- case undefined:
807
- return undefined;
808
- case 'PASSED':
809
- return statusReason;
810
- case 'WARNING':
811
- return undefined;
812
- case 'FAILED':
813
- return statusReason;
814
- case 'NOT_AVAILABLE':
815
- return undefined;
816
- default:
817
- return statusReason;
818
- }
819
- };
820
- return externalProductHandler(this, whichSpecialCase(finding), finding, 'subfindingsMessage', defaultFunc);
821
- })();
822
- const skipMessage = (() => {
823
- const statusReason = this.statusReason(finding);
824
- switch (lodash_1.default.get(finding, COMPLIANCE_STATUS)) {
825
- case undefined:
826
- return statusReason;
827
- case 'PASSED':
828
- return undefined;
829
- case 'WARNING':
830
- return statusReason;
831
- case 'FAILED':
832
- return undefined;
833
- case 'NOT_AVAILABLE':
834
- return statusReason;
835
- default:
836
- return undefined;
837
- }
838
- })();
839
- return {
840
- ...(message !== undefined && { message }),
841
- ...(skipMessage !== undefined && {
842
- skip_message: skipMessage
843
- })
844
- };
845
- },
846
- start_time: {
847
- transformer: (finding) => lodash_1.default.get(finding, 'LastObservedAt') ||
848
- lodash_1.default.get(finding, 'UpdatedAt')
849
- }
850
- }
851
- ]
852
- }
853
- ],
854
- sha256: ''
855
- }
856
- ]
857
- });
858
- }
859
- }
860
- exports.ASFFMapper = ASFFMapper;
861
- class ASFFResults {
862
- constructor(asffJson, securityhubStandardsJsonArray = undefined, meta = undefined) {
863
- this.meta = meta;
864
- this.supportingDocs = new Map();
865
- this.supportingDocs.set(SpecialCasing.SecurityHub, lodash_1.default.get(SPECIAL_CASE_MAPPING.get(SpecialCasing.SecurityHub), 'securityhubSupportingDocs', (standards) => {
866
- throw new Error(`supportingDocs function should've been defined: ${standards}`);
867
- })(securityhubStandardsJsonArray));
868
- const findings = lodash_1.default.get(fixFileInput(asffJson), 'Findings');
869
- this.data = lodash_1.default.groupBy(findings, (finding) => {
870
- const productInfo = lodash_1.default.get(finding, 'ProductArn')
871
- .split(':')
872
- .slice(-1)[0]
873
- .split('/');
874
- const defaultFilename = `${productInfo[1]} | ${productInfo[2]}.json`;
875
- return externalProductHandler(this, whichSpecialCase(finding), [finding, findings], 'filename', (0, html_entities_1.encode)(defaultFilename));
876
- });
877
- }
878
- toHdf() {
879
- return lodash_1.default.mapValues(this.data, (val) => {
880
- const wrapped = wrapWithFindingsObject(val);
881
- const ret = new ASFFMapper(externalProductHandler(this, whichSpecialCase(lodash_1.default.get(wrapped, 'Findings[0]')), wrapped, 'preprocessingASFF', wrapped), externalProductHandler(this, whichSpecialCase(lodash_1.default.get(wrapped, 'Findings[0]')), [wrapped, this.supportingDocs], 'supportingDocs', this.supportingDocs), externalProductHandler(this, whichSpecialCase(lodash_1.default.get(wrapped, 'Findings[0]')), undefined, 'meta', this.meta)).toHdf();
882
- return ret;
883
- });
884
- }
885
- }
886
- exports.ASFFResults = ASFFResults;
887
- //# sourceMappingURL=asff-mapper.js.map