@mitre/inspec-objects 0.0.1 → 0.0.4
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/.github/workflows/e2e-test.yml +38 -0
- package/lib/mappings/CciNistMappingData.d.ts +5100 -0
- package/lib/mappings/CciNistMappingData.js +5103 -0
- package/lib/objects/control.d.ts +7 -3
- package/lib/objects/control.js +8 -1
- package/lib/parsers/oval.d.ts +2 -0
- package/lib/parsers/oval.js +17 -0
- package/lib/parsers/xccdf.d.ts +7 -1
- package/lib/parsers/xccdf.js +231 -50
- package/lib/utilities/diff.d.ts +1 -0
- package/lib/utilities/diff.js +20 -3
- package/lib/utilities/global.d.ts +2 -0
- package/lib/utilities/global.js +24 -1
- package/lib/utilities/xccdf.d.ts +2 -1
- package/lib/utilities/xccdf.js +10 -3
- package/mitre-inspec-objects-v0.0.1.tgz +0 -0
- package/mitre-inspec-objects-v0.0.3.tgz +0 -0
- package/package-lock.json +19 -3198
- package/package.json +4 -4
- package/tsconfig.json +2 -1
- package/src/index.ts +0 -5
- package/src/objects/control.ts +0 -137
- package/src/objects/profile.ts +0 -93
- package/src/parsers/json.ts +0 -92
- package/src/parsers/xccdf.ts +0 -74
- package/src/types/diff.d.ts +0 -9
- package/src/types/xccdf.d.ts +0 -126
- package/src/utilities/diff.ts +0 -54
- package/src/utilities/global.ts +0 -23
- package/src/utilities/xccdf.ts +0 -110
package/lib/objects/control.d.ts
CHANGED
|
@@ -5,11 +5,15 @@ export default class Control {
|
|
|
5
5
|
code?: string | null;
|
|
6
6
|
desc?: string | null;
|
|
7
7
|
descs?: ExecJSON.ControlDescription[] | {
|
|
8
|
-
[key: string]: string;
|
|
8
|
+
[key: string]: string | undefined;
|
|
9
9
|
} | null;
|
|
10
10
|
impact?: number;
|
|
11
11
|
ref?: string;
|
|
12
|
-
refs?: string
|
|
12
|
+
refs?: (string | {
|
|
13
|
+
ref?: string;
|
|
14
|
+
url?: string;
|
|
15
|
+
uri?: string;
|
|
16
|
+
})[];
|
|
13
17
|
tags: {
|
|
14
18
|
check?: string;
|
|
15
19
|
fix?: string;
|
|
@@ -19,7 +23,7 @@ export default class Control {
|
|
|
19
23
|
satisfies?: string[];
|
|
20
24
|
rid?: string;
|
|
21
25
|
stig_id?: string;
|
|
22
|
-
fix_id?: string;
|
|
26
|
+
fix_id?: string | null;
|
|
23
27
|
cci?: string[];
|
|
24
28
|
cis_controls?: Record<string, string[]>[];
|
|
25
29
|
nist?: string[];
|
package/lib/objects/control.js
CHANGED
|
@@ -6,6 +6,8 @@ const flat_1 = require("flat");
|
|
|
6
6
|
const global_1 = require("../utilities/global");
|
|
7
7
|
class Control {
|
|
8
8
|
constructor(data) {
|
|
9
|
+
this.tags = {};
|
|
10
|
+
this.refs = [];
|
|
9
11
|
this.tags = {};
|
|
10
12
|
if (data) {
|
|
11
13
|
Object.entries(data).forEach(([key, value]) => {
|
|
@@ -55,7 +57,12 @@ class Control {
|
|
|
55
57
|
}
|
|
56
58
|
if (this.refs) {
|
|
57
59
|
this.refs.forEach((ref) => {
|
|
58
|
-
|
|
60
|
+
if (typeof ref === 'string') {
|
|
61
|
+
result += ` ref '${(0, global_1.escapeQuotes)(ref)}'\n`;
|
|
62
|
+
}
|
|
63
|
+
else {
|
|
64
|
+
result += ` ref '${(0, global_1.escapeQuotes)(ref.ref || '')}', url: '${(0, global_1.escapeQuotes)(ref.url || '')}'`;
|
|
65
|
+
}
|
|
59
66
|
});
|
|
60
67
|
}
|
|
61
68
|
Object.entries(this.tags).forEach(([tag, value]) => {
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.processOVAL = void 0;
|
|
4
|
+
const xccdf_1 = require("../utilities/xccdf");
|
|
5
|
+
function processOVAL(oval) {
|
|
6
|
+
const parsed = (0, xccdf_1.convertEncodedXmlIntoJson)(oval);
|
|
7
|
+
const extractedDefinitions = {};
|
|
8
|
+
for (const ovalDefinitions of parsed.oval_definitions) {
|
|
9
|
+
for (const definitionList of ovalDefinitions.definitions) {
|
|
10
|
+
for (const definition of definitionList.definition) {
|
|
11
|
+
extractedDefinitions[definition["@_id"]] = definition;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
return extractedDefinitions;
|
|
16
|
+
}
|
|
17
|
+
exports.processOVAL = processOVAL;
|
package/lib/parsers/xccdf.d.ts
CHANGED
|
@@ -1,2 +1,8 @@
|
|
|
1
1
|
import Profile from '../objects/profile';
|
|
2
|
-
|
|
2
|
+
import { BenchmarkGroup, BenchmarkRule } from '../types/xccdf';
|
|
3
|
+
import { OvalDefinitionValue } from '../types/oval';
|
|
4
|
+
export declare type GroupContextualizedRule = BenchmarkRule & {
|
|
5
|
+
group: Omit<BenchmarkGroup, 'Rule' | 'Group'>;
|
|
6
|
+
};
|
|
7
|
+
export declare function extractAllRules(groups: BenchmarkGroup[]): GroupContextualizedRule[];
|
|
8
|
+
export declare function processXCCDF(xml: string, removeNewlines?: boolean, ovalDefinitions?: Record<string, OvalDefinitionValue>): Profile;
|
package/lib/parsers/xccdf.js
CHANGED
|
@@ -1,67 +1,248 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.processXCCDF = void 0;
|
|
3
|
+
exports.processXCCDF = exports.extractAllRules = void 0;
|
|
4
4
|
const tslib_1 = require("tslib");
|
|
5
|
-
const CciNistMappingData_1 = require("@mitre/hdf-converters/lib/src/mappings/CciNistMappingData");
|
|
6
5
|
const profile_1 = tslib_1.__importDefault(require("../objects/profile"));
|
|
7
6
|
const xccdf_1 = require("../utilities/xccdf");
|
|
8
7
|
const control_1 = tslib_1.__importDefault(require("../objects/control"));
|
|
9
8
|
const lodash_1 = tslib_1.__importDefault(require("lodash"));
|
|
10
|
-
|
|
9
|
+
const CciNistMappingData_1 = require("../mappings/CciNistMappingData");
|
|
10
|
+
function extractAllRules(groups) {
|
|
11
|
+
const rules = [];
|
|
12
|
+
groups.forEach((group) => {
|
|
13
|
+
if (group.Rule) {
|
|
14
|
+
rules.push(...(group.Rule.map((rule) => {
|
|
15
|
+
return {
|
|
16
|
+
...rule,
|
|
17
|
+
group: lodash_1.default.omit(group, ['Rule', 'Group'])
|
|
18
|
+
};
|
|
19
|
+
})));
|
|
20
|
+
}
|
|
21
|
+
if (group.Group) {
|
|
22
|
+
rules.push(...extractAllRules(group.Group));
|
|
23
|
+
}
|
|
24
|
+
});
|
|
25
|
+
return rules;
|
|
26
|
+
}
|
|
27
|
+
exports.extractAllRules = extractAllRules;
|
|
28
|
+
function processXCCDF(xml, removeNewlines = false, ovalDefinitions) {
|
|
11
29
|
const parsedXML = (0, xccdf_1.convertEncodedXmlIntoJson)(xml);
|
|
12
|
-
const
|
|
30
|
+
const rules = extractAllRules(parsedXML.Benchmark[0].Group);
|
|
13
31
|
const profile = new profile_1.default({
|
|
14
|
-
name: parsedXML.Benchmark['@_id'],
|
|
15
|
-
title: parsedXML.Benchmark.title,
|
|
16
|
-
summary: parsedXML.Benchmark.description
|
|
32
|
+
name: parsedXML.Benchmark[0]['@_id'],
|
|
33
|
+
title: parsedXML.Benchmark[0].title[0]['#text'],
|
|
34
|
+
summary: parsedXML.Benchmark[0].description[0]['#text']
|
|
17
35
|
});
|
|
18
|
-
|
|
19
|
-
var _a, _b, _c;
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
36
|
+
rules.forEach(rule => {
|
|
37
|
+
var _a, _b, _c, _d;
|
|
38
|
+
let extractedDescription;
|
|
39
|
+
if (Array.isArray(rule.description)) {
|
|
40
|
+
extractedDescription = rule.description[0]['#text'];
|
|
41
|
+
}
|
|
42
|
+
else {
|
|
43
|
+
extractedDescription = (0, xccdf_1.convertEncodedHTMLIntoJson)(rule.description);
|
|
44
|
+
}
|
|
45
|
+
const control = new control_1.default();
|
|
46
|
+
control.id = rule['@_id'];
|
|
47
|
+
if (removeNewlines) {
|
|
48
|
+
const title = (0, xccdf_1.removeXMLSpecialCharacters)(rule['@_severity'] ? rule.title : `[[[MISSING SEVERITY FROM STIG]]] ${rule.title}`);
|
|
49
|
+
control.title = title.replace(/\n/g, '{{{{newlineHERE}}}}');
|
|
50
|
+
const desc = (0, xccdf_1.removeXMLSpecialCharacters)(typeof extractedDescription === 'string' ? extractedDescription : ((_a = extractedDescription.VulnDiscussion) === null || _a === void 0 ? void 0 : _a.split('Satisfies: ')[0]) || 'Missing Description');
|
|
51
|
+
control.desc = desc === null || desc === void 0 ? void 0 : desc.replace(/\n/g, '{{{{newlineHERE}}}}');
|
|
52
|
+
}
|
|
53
|
+
else {
|
|
54
|
+
control.title = (0, xccdf_1.removeXMLSpecialCharacters)(rule['@_severity'] ? rule.title : `[[[MISSING SEVERITY FROM STIG]]] ${rule.title}`);
|
|
55
|
+
control.desc = (0, xccdf_1.removeXMLSpecialCharacters)(typeof extractedDescription === 'string' ? extractedDescription : ((_b = extractedDescription.VulnDiscussion) === null || _b === void 0 ? void 0 : _b.split('Satisfies: ')[0]) || 'Missing Description');
|
|
56
|
+
}
|
|
57
|
+
control.impact = (0, xccdf_1.severityStringToImpact)(rule['@_severity'] || 'critical', rule.group['@_id']);
|
|
58
|
+
if (!control.descs || Array.isArray(control.descs)) {
|
|
59
|
+
control.descs = {};
|
|
60
|
+
}
|
|
61
|
+
if (rule.check) {
|
|
62
|
+
if (rule.check.some((ruleValue) => 'check-content' in ruleValue)) {
|
|
63
|
+
if (removeNewlines) {
|
|
64
|
+
const check = (0, xccdf_1.removeXMLSpecialCharacters)(rule.check ? rule.check[0]['check-content'] : 'Missing description');
|
|
65
|
+
control.descs.check = check.replace(/\n/g, '{{{{newlineHERE}}}}');
|
|
66
|
+
}
|
|
67
|
+
else {
|
|
68
|
+
control.descs.check = (0, xccdf_1.removeXMLSpecialCharacters)(rule.check ? rule.check[0]['check-content'] : 'Missing description');
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
else if (rule.check.some((ruleValue) => 'check-content-ref' in ruleValue) && ovalDefinitions) {
|
|
72
|
+
let referenceID = null;
|
|
73
|
+
for (const checkContent of rule.check) {
|
|
74
|
+
if ('check-content-ref' in checkContent && checkContent['@_system'].includes('oval')) {
|
|
75
|
+
for (const checkContentRef of checkContent['check-content-ref']) {
|
|
76
|
+
if (checkContentRef['@_name']) {
|
|
77
|
+
referenceID = checkContentRef['@_name'];
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
if (referenceID && referenceID in ovalDefinitions) {
|
|
83
|
+
if (removeNewlines) {
|
|
84
|
+
const check = (0, xccdf_1.removeXMLSpecialCharacters)(ovalDefinitions[referenceID].metadata[0].title);
|
|
85
|
+
control.descs.check = check.replace(/\n/g, '{{{{newlineHERE}}}}');
|
|
86
|
+
}
|
|
87
|
+
else {
|
|
88
|
+
control.descs.check = (0, xccdf_1.removeXMLSpecialCharacters)(ovalDefinitions[referenceID].metadata[0].title);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
else if (referenceID) {
|
|
92
|
+
console.warn(`Could not find OVAL definition for ${referenceID}`);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
if (removeNewlines) {
|
|
97
|
+
const fix = (0, xccdf_1.removeXMLSpecialCharacters)(rule.fixtext ? rule.fixtext[0]['#text'] : (rule.fix ? rule.fix[0]['#text'] || 'Missing fix text' : 'Missing fix text'));
|
|
98
|
+
control.descs.fix = fix.replace(/\n/g, '{{{{newlineHERE}}}}');
|
|
99
|
+
}
|
|
100
|
+
else {
|
|
101
|
+
control.descs.fix = (0, xccdf_1.removeXMLSpecialCharacters)(rule.fixtext ? rule.fixtext[0]['#text'] : (rule.fix ? rule.fix[0]['#text'] || 'Missing fix text' : 'Missing fix text'));
|
|
102
|
+
}
|
|
103
|
+
control.tags.severity = (0, xccdf_1.impactNumberToSeverityString)((0, xccdf_1.severityStringToImpact)(rule['@_severity'] || 'critical', control.id));
|
|
104
|
+
control.tags.gid = rule.group['@_id'],
|
|
105
|
+
control.tags.rid = rule['@_id'];
|
|
106
|
+
control.tags.stig_id = rule['version'];
|
|
107
|
+
if (typeof rule.group.title === "string") {
|
|
108
|
+
control.tags.gtitle = (0, xccdf_1.removeXMLSpecialCharacters)(rule.group.title);
|
|
109
|
+
}
|
|
110
|
+
else {
|
|
111
|
+
control.tags.gtitle = (0, xccdf_1.removeXMLSpecialCharacters)(lodash_1.default.get(rule.group, 'title[0].#text'));
|
|
112
|
+
}
|
|
113
|
+
if (rule['fix'] && rule['fix'].length > 0) {
|
|
114
|
+
control.tags.fix_id = rule['fix'][0]['@_id'];
|
|
115
|
+
}
|
|
116
|
+
else {
|
|
117
|
+
control.tags.fix_id = null;
|
|
118
|
+
}
|
|
119
|
+
if (rule['rationale']) {
|
|
120
|
+
control.tags.rationale = rule['rationale'][0]['#text'];
|
|
121
|
+
}
|
|
122
|
+
else {
|
|
123
|
+
control.tags.rationale = null;
|
|
124
|
+
}
|
|
125
|
+
if (typeof extractedDescription === 'object') {
|
|
126
|
+
control.tags.satisfies = ((_c = extractedDescription.VulnDiscussion) === null || _c === void 0 ? void 0 : _c.includes('Satisfies: ')) && extractedDescription.VulnDiscussion.split('Satisfies: ').length >= 1 ? extractedDescription.VulnDiscussion.split('Satisfies: ')[1].split(',').map(satisfaction => satisfaction.trim()) : undefined;
|
|
127
|
+
control.tags.false_negatives = extractedDescription.FalseNegatives || undefined;
|
|
128
|
+
control.tags.false_positives = extractedDescription.FalsePositives || undefined;
|
|
129
|
+
control.tags.documentable = typeof extractedDescription.Documentable === 'boolean' ? extractedDescription.Documentable : undefined;
|
|
130
|
+
control.tags.mitigations = extractedDescription.Mitigations || undefined;
|
|
131
|
+
control.tags.severity_override_guidance = extractedDescription.SeverityOverrideGuidance || undefined;
|
|
132
|
+
control.tags.potential_impacts = extractedDescription.PotentialImpacts || undefined;
|
|
133
|
+
control.tags.third_party_tools = extractedDescription.ThirdPartyTools || undefined;
|
|
134
|
+
control.tags.mitigation_control = extractedDescription.MitigationControl || undefined;
|
|
135
|
+
control.tags.mitigation_controls = extractedDescription.MitigationControls || undefined;
|
|
136
|
+
control.tags.responsibility = extractedDescription.Responsibility || undefined;
|
|
137
|
+
control.tags.ia_controls = extractedDescription.IAControls || undefined;
|
|
138
|
+
}
|
|
139
|
+
control.tags = lodash_1.default.mapValues(lodash_1.default.omitBy(control.tags, (value) => value === undefined), (value) => {
|
|
140
|
+
if (typeof value === 'string') {
|
|
141
|
+
return (0, xccdf_1.removeXMLSpecialCharacters)(value);
|
|
142
|
+
}
|
|
143
|
+
else {
|
|
144
|
+
return value;
|
|
145
|
+
}
|
|
50
146
|
});
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
identifiers.forEach(identifier => {
|
|
147
|
+
// Get all identifiers from the rule
|
|
148
|
+
if (rule.ident) {
|
|
149
|
+
rule.ident.forEach((identifier) => {
|
|
55
150
|
var _a, _b, _c;
|
|
56
|
-
|
|
57
|
-
if (identifier['@_system'].toLowerCase().
|
|
58
|
-
(
|
|
59
|
-
|
|
60
|
-
|
|
151
|
+
// Get CCIs
|
|
152
|
+
if (identifier['@_system'].toLowerCase().includes('cci')) {
|
|
153
|
+
if (!('cci' in control.tags)) {
|
|
154
|
+
control.tags.cci = [];
|
|
155
|
+
}
|
|
156
|
+
(_a = control.tags.cci) === null || _a === void 0 ? void 0 : _a.push(identifier['#text']);
|
|
157
|
+
}
|
|
158
|
+
// Get legacy identifiers
|
|
159
|
+
else if (identifier['@_system'].toLowerCase().includes('legacy')) {
|
|
160
|
+
if (!('legacy' in control.tags)) {
|
|
161
|
+
control.tags.legacy = [];
|
|
162
|
+
}
|
|
163
|
+
(_b = control.tags.legacy) === null || _b === void 0 ? void 0 : _b.push(identifier['#text']);
|
|
164
|
+
}
|
|
165
|
+
// Get NIST identifiers
|
|
166
|
+
else if (identifier['@_system'].toLowerCase().includes('nist')) {
|
|
167
|
+
if (!('nist' in control.tags)) {
|
|
168
|
+
control.tags.nist = [];
|
|
61
169
|
}
|
|
170
|
+
(_c = control.tags.nist) === null || _c === void 0 ? void 0 : _c.push(identifier['#text']);
|
|
171
|
+
}
|
|
172
|
+
else {
|
|
173
|
+
// console.log('Alert')
|
|
174
|
+
// console.log(identifier['@_system'])
|
|
175
|
+
// console.log(identifier['#text'])
|
|
176
|
+
}
|
|
177
|
+
});
|
|
178
|
+
}
|
|
179
|
+
(_d = rule.reference) === null || _d === void 0 ? void 0 : _d.forEach((reference) => {
|
|
180
|
+
var _a, _b, _c, _d;
|
|
181
|
+
if (lodash_1.default.get(reference, '@_href') === '') {
|
|
182
|
+
(_a = control.refs) === null || _a === void 0 ? void 0 : _a.push(lodash_1.default.get(reference, '#text'));
|
|
183
|
+
}
|
|
184
|
+
else {
|
|
185
|
+
try {
|
|
186
|
+
const referenceText = lodash_1.default.get(reference, '#text') || '';
|
|
187
|
+
const referenceURL = lodash_1.default.get(reference, '@_href') || '';
|
|
188
|
+
if (referenceURL) {
|
|
189
|
+
const parsedURL = new URL(lodash_1.default.get(reference, '@_href'));
|
|
190
|
+
if (parsedURL.protocol.toLowerCase().includes('http') || parsedURL.protocol.toLowerCase().includes('https')) {
|
|
191
|
+
(_b = control.refs) === null || _b === void 0 ? void 0 : _b.push({
|
|
192
|
+
ref: referenceText,
|
|
193
|
+
url: referenceURL
|
|
194
|
+
});
|
|
195
|
+
}
|
|
196
|
+
else {
|
|
197
|
+
(_c = control.refs) === null || _c === void 0 ? void 0 : _c.push({
|
|
198
|
+
ref: referenceText,
|
|
199
|
+
uri: referenceURL
|
|
200
|
+
});
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
else {
|
|
204
|
+
if ('title' in reference) {
|
|
205
|
+
(_d = control.refs) === null || _d === void 0 ? void 0 : _d.push(lodash_1.default.get(reference, 'title'));
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
// Add the reference to the control tags when seperated by §
|
|
209
|
+
if (typeof referenceText === 'string' && referenceText.indexOf('§') !== -1) {
|
|
210
|
+
const referenceParts = referenceText.split('§');
|
|
211
|
+
if (referenceParts.length == 2) {
|
|
212
|
+
let [identifierType, identifier] = referenceText.split('§');
|
|
213
|
+
identifierType = identifierType.toLowerCase();
|
|
214
|
+
if (!(identifierType in control.tags)) {
|
|
215
|
+
control.tags[identifierType] = [identifier];
|
|
216
|
+
}
|
|
217
|
+
else if (Array.isArray(control.tags[identifierType])) {
|
|
218
|
+
control.tags[identifierType] = lodash_1.default.union(control.tags[identifierType], [identifier]);
|
|
219
|
+
}
|
|
220
|
+
else {
|
|
221
|
+
console.warn(`Attempted to push identifier to control tags when identifier already exists: ${identifierType}: ${identifier}`);
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
else {
|
|
225
|
+
console.warn("Reference parts of invalid length:");
|
|
226
|
+
console.log(referenceParts);
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
catch (e) {
|
|
231
|
+
console.warn(`Error parsing ref for control ${control.id}: `);
|
|
232
|
+
console.warn(JSON.stringify(reference, null, 2));
|
|
233
|
+
console.warn(e);
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
});
|
|
237
|
+
// Associate any CCIs with NIST tags
|
|
238
|
+
if (control.tags.cci) {
|
|
239
|
+
control.tags.cci.forEach((cci) => {
|
|
240
|
+
var _a;
|
|
241
|
+
if (!('nist' in control.tags)) {
|
|
242
|
+
control.tags.nist = [];
|
|
62
243
|
}
|
|
63
|
-
if (
|
|
64
|
-
(
|
|
244
|
+
if (cci in CciNistMappingData_1.data) {
|
|
245
|
+
(_a = control.tags.nist) === null || _a === void 0 ? void 0 : _a.push(lodash_1.default.get(CciNistMappingData_1.data, cci));
|
|
65
246
|
}
|
|
66
247
|
});
|
|
67
248
|
}
|
package/lib/utilities/diff.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
1
|
import Profile from '../objects/profile';
|
|
2
2
|
import { ProfileDiff } from '../types/diff';
|
|
3
|
+
export declare function removeNewlines(control?: Record<string, unknown>): Record<string, unknown>;
|
|
3
4
|
export declare function diffProfile(fromProfile: Profile, toProfile: Profile): ProfileDiff;
|
package/lib/utilities/diff.js
CHANGED
|
@@ -1,9 +1,24 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.diffProfile = void 0;
|
|
3
|
+
exports.diffProfile = exports.removeNewlines = void 0;
|
|
4
4
|
const tslib_1 = require("tslib");
|
|
5
5
|
const json_diff_1 = require("json-diff");
|
|
6
6
|
const lodash_1 = tslib_1.__importDefault(require("lodash"));
|
|
7
|
+
function removeNewlines(control) {
|
|
8
|
+
if (!control) {
|
|
9
|
+
return {};
|
|
10
|
+
}
|
|
11
|
+
return lodash_1.default.mapValues(control, (value) => {
|
|
12
|
+
if (typeof value === 'string') {
|
|
13
|
+
return value.replace(/\n/g, '{{{{newlineHERE}}}}').trim();
|
|
14
|
+
}
|
|
15
|
+
else if (typeof value === 'object' && value !== null) {
|
|
16
|
+
return removeNewlines(value);
|
|
17
|
+
}
|
|
18
|
+
return value;
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
exports.removeNewlines = removeNewlines;
|
|
7
22
|
function diffProfile(fromProfile, toProfile) {
|
|
8
23
|
const profileDiff = {
|
|
9
24
|
addedControlIDs: [],
|
|
@@ -14,7 +29,7 @@ function diffProfile(fromProfile, toProfile) {
|
|
|
14
29
|
const toControlIDs = toProfile.controls.map((control) => control.id).sort();
|
|
15
30
|
// Find new controls
|
|
16
31
|
const controlIDDiff = (0, json_diff_1.diff)(fromControlIDs, toControlIDs);
|
|
17
|
-
controlIDDiff.forEach((diffValue) => {
|
|
32
|
+
controlIDDiff === null || controlIDDiff === void 0 ? void 0 : controlIDDiff.forEach((diffValue) => {
|
|
18
33
|
if (diffValue[0] === '-') {
|
|
19
34
|
profileDiff.removedControlIDs.push(diffValue[1]);
|
|
20
35
|
}
|
|
@@ -34,13 +49,15 @@ function diffProfile(fromProfile, toProfile) {
|
|
|
34
49
|
const toControl = toProfile.controls.find((control) => control.id === fromControl.id);
|
|
35
50
|
if (toControl) {
|
|
36
51
|
const controlDiff = (0, json_diff_1.diff)(fromControl, toControl);
|
|
52
|
+
console.log(controlDiff);
|
|
37
53
|
if (controlDiff) {
|
|
38
54
|
Object.entries(controlDiff).forEach(([key, value]) => {
|
|
55
|
+
console.log(value);
|
|
39
56
|
if (lodash_1.default.has(value, '__new')) {
|
|
40
57
|
lodash_1.default.set(profileDiff, 'changedControls.' + fromControl.id + '.' + key.replace('.', '\\.'), lodash_1.default.get(controlDiff, key + '.__new'));
|
|
41
58
|
}
|
|
42
59
|
else if (typeof value === 'object') {
|
|
43
|
-
Object.entries(value).forEach(([subKey
|
|
60
|
+
Object.entries(value).forEach(([subKey]) => {
|
|
44
61
|
lodash_1.default.set(profileDiff, 'changedControls.' + fromControl.id + '.' + key.replace('.', '\\.') + '.' + subKey.replace('.', '\\.'), lodash_1.default.get(controlDiff, key + '.' + subKey + '.__new'));
|
|
45
62
|
});
|
|
46
63
|
}
|
|
@@ -4,3 +4,5 @@ declare const escapeQuotes: (s: string) => string;
|
|
|
4
4
|
declare const escapeDoubleQuotes: (s: string) => string;
|
|
5
5
|
declare const wrapAndEscapeQuotes: (s: string, lineLength?: number) => string;
|
|
6
6
|
export { escapeQuotes, escapeDoubleQuotes, wrapAndEscapeQuotes };
|
|
7
|
+
export declare function getFirstPath(object: Record<string, unknown>, paths: string[]): string;
|
|
8
|
+
export declare function hasPath(file: Record<string, unknown>, path: string | string[]): boolean;
|
package/lib/utilities/global.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.wrapAndEscapeQuotes = exports.escapeDoubleQuotes = exports.escapeQuotes = exports.unformatText = exports.wrap = void 0;
|
|
3
|
+
exports.hasPath = exports.getFirstPath = exports.wrapAndEscapeQuotes = exports.escapeDoubleQuotes = exports.escapeQuotes = exports.unformatText = exports.wrap = void 0;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
const lodash_1 = tslib_1.__importDefault(require("lodash"));
|
|
4
6
|
// Breaks lines down to lineLength number of characters
|
|
5
7
|
function wrap(s, lineLength = 80) {
|
|
6
8
|
return s.replace(new RegExp(`(?![^\n]{1,${lineLength}}$)([^\n]{1,${lineLength}})`, "g"), "$1\n");
|
|
@@ -16,3 +18,24 @@ const escapeDoubleQuotes = (s) => s.replace(/\\/g, "\\\\").replace(/"/g, '\\"');
|
|
|
16
18
|
exports.escapeDoubleQuotes = escapeDoubleQuotes;
|
|
17
19
|
const wrapAndEscapeQuotes = (s, lineLength) => escapeDoubleQuotes(wrap(s, lineLength)); // Escape backslashes and quotes, and wrap long lines
|
|
18
20
|
exports.wrapAndEscapeQuotes = wrapAndEscapeQuotes;
|
|
21
|
+
function getFirstPath(object, paths) {
|
|
22
|
+
const index = lodash_1.default.findIndex(paths, (p) => hasPath(object, p));
|
|
23
|
+
if (index === -1) {
|
|
24
|
+
throw new Error(`Attestation is missing one of these paths: ${paths.join(', ')}`);
|
|
25
|
+
}
|
|
26
|
+
else {
|
|
27
|
+
return lodash_1.default.get(object, paths[index]);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
exports.getFirstPath = getFirstPath;
|
|
31
|
+
function hasPath(file, path) {
|
|
32
|
+
let pathArray;
|
|
33
|
+
if (typeof path === 'string') {
|
|
34
|
+
pathArray = [path];
|
|
35
|
+
}
|
|
36
|
+
else {
|
|
37
|
+
pathArray = path;
|
|
38
|
+
}
|
|
39
|
+
return lodash_1.default.some(pathArray, (p) => lodash_1.default.has(file, p));
|
|
40
|
+
}
|
|
41
|
+
exports.hasPath = hasPath;
|
package/lib/utilities/xccdf.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { DecodedDescription } from '../types/xccdf';
|
|
2
2
|
export declare function convertEncodedXmlIntoJson(encodedXml: string): any;
|
|
3
|
-
export declare function
|
|
3
|
+
export declare function removeXMLSpecialCharacters(input: string): string;
|
|
4
|
+
export declare function severityStringToImpact(string: string, id: string): number;
|
|
4
5
|
export declare function impactNumberToSeverityString(impact: number): string;
|
|
5
6
|
export declare function convertEncodedHTMLIntoJson(encodedHTML?: string): DecodedDescription;
|
package/lib/utilities/xccdf.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.convertEncodedHTMLIntoJson = exports.impactNumberToSeverityString = exports.severityStringToImpact = exports.convertEncodedXmlIntoJson = void 0;
|
|
3
|
+
exports.convertEncodedHTMLIntoJson = exports.impactNumberToSeverityString = exports.severityStringToImpact = exports.removeXMLSpecialCharacters = exports.convertEncodedXmlIntoJson = void 0;
|
|
4
4
|
const tslib_1 = require("tslib");
|
|
5
5
|
const fast_xml_parser_1 = tslib_1.__importDefault(require("fast-xml-parser"));
|
|
6
6
|
const htmlparser = tslib_1.__importStar(require("htmlparser2"));
|
|
@@ -8,11 +8,17 @@ const lodash_1 = tslib_1.__importDefault(require("lodash"));
|
|
|
8
8
|
function convertEncodedXmlIntoJson(encodedXml) {
|
|
9
9
|
return fast_xml_parser_1.default.parse(encodedXml, {
|
|
10
10
|
ignoreAttributes: false,
|
|
11
|
+
ignoreNameSpace: true,
|
|
11
12
|
attributeNamePrefix: '@_',
|
|
13
|
+
arrayMode: true
|
|
12
14
|
});
|
|
13
15
|
}
|
|
14
16
|
exports.convertEncodedXmlIntoJson = convertEncodedXmlIntoJson;
|
|
15
|
-
function
|
|
17
|
+
function removeXMLSpecialCharacters(input) {
|
|
18
|
+
return input.replace(/&/gm, '&').replace(/</gm, '<').replace(/>/gm, '>');
|
|
19
|
+
}
|
|
20
|
+
exports.removeXMLSpecialCharacters = removeXMLSpecialCharacters;
|
|
21
|
+
function severityStringToImpact(string, id) {
|
|
16
22
|
var _a, _b, _c, _d, _e;
|
|
17
23
|
if ((_a = string.match(/none|na|n\/a|not[\s()*_|]?applicable/i)) === null || _a === void 0 ? void 0 : _a.length) {
|
|
18
24
|
return 0.0;
|
|
@@ -29,7 +35,8 @@ function severityStringToImpact(string) {
|
|
|
29
35
|
if ((_e = string.match(/crit(ical)?|severe/)) === null || _e === void 0 ? void 0 : _e.length) {
|
|
30
36
|
return 1.0;
|
|
31
37
|
}
|
|
32
|
-
|
|
38
|
+
console.log(`${string} is not a valid severity value. It should be one of the approved keywords. ${id} will be treated as medium severity`);
|
|
39
|
+
return 0.5;
|
|
33
40
|
}
|
|
34
41
|
exports.severityStringToImpact = severityStringToImpact;
|
|
35
42
|
function impactNumberToSeverityString(impact) {
|
|
Binary file
|
|
Binary file
|