@mitre/inspec-objects 0.0.24 → 0.0.27
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/lib/parsers/oval.d.ts +2 -1
- package/lib/parsers/oval.js +95 -1
- package/lib/parsers/xccdf.d.ts +6 -2
- package/lib/parsers/xccdf.js +99 -8
- package/lib/utilities/CciNistMappingData.d.ts +5100 -0
- package/lib/utilities/CciNistMappingData.js +5103 -0
- package/lib/utilities/update.d.ts +1 -1
- package/lib/utilities/update.js +24 -25
- package/lib/utilities/xccdf.d.ts +1 -0
- package/lib/utilities/xccdf.js +7 -1
- package/mitre-inspec-objects-v0.0.27.tgz +0 -0
- package/package.json +5 -1
- package/package-lock.json +0 -8529
package/lib/parsers/oval.d.ts
CHANGED
|
@@ -1,2 +1,3 @@
|
|
|
1
|
-
import { OvalDefinitionValue } from '../types/oval';
|
|
1
|
+
import { OvalDefinitionValue, DefinitionCriterion } from '../types/oval';
|
|
2
|
+
export declare function extractAllCriteriaRefs(initialCriteria: DefinitionCriterion[]): string[];
|
|
2
3
|
export declare function processOVAL(oval?: string): Record<string, OvalDefinitionValue> | undefined;
|
package/lib/parsers/oval.js
CHANGED
|
@@ -1,8 +1,58 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.processOVAL = void 0;
|
|
3
|
+
exports.processOVAL = exports.extractAllCriteriaRefs = void 0;
|
|
4
4
|
const xccdf_1 = require("../utilities/xccdf");
|
|
5
|
+
// https://stackoverflow.com/questions/9133500/how-to-find-a-node-in-a-tree-with-javascript
|
|
6
|
+
function searchTree(aTree, fCompair, bGreedy) {
|
|
7
|
+
var aInnerTree = []; // will contain the inner children
|
|
8
|
+
var oNode; // always the current node
|
|
9
|
+
var aReturnNodes = []; // the nodes array which will returned
|
|
10
|
+
// 1. loop through all root nodes so we don't touch the tree structure
|
|
11
|
+
for (const keysTree in aTree) {
|
|
12
|
+
aInnerTree.push(aTree[keysTree]);
|
|
13
|
+
}
|
|
14
|
+
while (aInnerTree.length > 0) {
|
|
15
|
+
oNode = aInnerTree.pop();
|
|
16
|
+
// check current node
|
|
17
|
+
if (fCompair(oNode)) {
|
|
18
|
+
aReturnNodes.push(oNode);
|
|
19
|
+
if (!bGreedy) {
|
|
20
|
+
return aReturnNodes;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
else { // if (node.children && node.children.length) {
|
|
24
|
+
// find other objects, 1. check all properties of the node if they are arrays
|
|
25
|
+
for (const keysNode in oNode) {
|
|
26
|
+
// true if the property is an array
|
|
27
|
+
if (oNode[keysNode] instanceof Array) {
|
|
28
|
+
// 2. push all array object to aInnerTree to search in those later
|
|
29
|
+
for (var i = 0; i < oNode[keysNode].length; i++) {
|
|
30
|
+
aInnerTree.push(oNode[keysNode][i]);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
return aReturnNodes;
|
|
37
|
+
}
|
|
38
|
+
function extractAllCriteriaRefs(initialCriteria) {
|
|
39
|
+
const criteriaRefs = [];
|
|
40
|
+
initialCriteria.forEach(criteria => {
|
|
41
|
+
var _a;
|
|
42
|
+
(_a = criteria.criterion) === null || _a === void 0 ? void 0 : _a.forEach((criterion) => {
|
|
43
|
+
if (criterion["@_test_ref"]) {
|
|
44
|
+
criteriaRefs.push(criterion["@_test_ref"]);
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
if (criteria.criteria) {
|
|
48
|
+
criteriaRefs.push(...extractAllCriteriaRefs(criteria.criteria));
|
|
49
|
+
}
|
|
50
|
+
});
|
|
51
|
+
return criteriaRefs;
|
|
52
|
+
}
|
|
53
|
+
exports.extractAllCriteriaRefs = extractAllCriteriaRefs;
|
|
5
54
|
function processOVAL(oval) {
|
|
55
|
+
var _a;
|
|
6
56
|
if (!oval) {
|
|
7
57
|
return undefined;
|
|
8
58
|
}
|
|
@@ -12,6 +62,50 @@ function processOVAL(oval) {
|
|
|
12
62
|
for (const definitionList of ovalDefinitions.definitions) {
|
|
13
63
|
for (const definition of definitionList.definition) {
|
|
14
64
|
extractedDefinitions[definition["@_id"]] = definition;
|
|
65
|
+
extractedDefinitions[definition["@_id"]].criteriaRefs = extractAllCriteriaRefs(definition.criteria);
|
|
66
|
+
extractedDefinitions[definition["@_id"]].resolvedValues = (_a = extractedDefinitions[definition["@_id"]].criteriaRefs) === null || _a === void 0 ? void 0 : _a.map((criteriaRef) => {
|
|
67
|
+
// Extract the original criteria from the oval file
|
|
68
|
+
const foundCriteriaRefererence = searchTree(parsed.oval_definitions[0].tests, (oNode) => oNode["@_id"] === criteriaRef, false)[0];
|
|
69
|
+
let foundObjects = [];
|
|
70
|
+
let foundStates = [];
|
|
71
|
+
if (foundCriteriaRefererence) {
|
|
72
|
+
if (foundCriteriaRefererence.object) {
|
|
73
|
+
foundCriteriaRefererence.object.forEach((object) => {
|
|
74
|
+
if (!object["@_object_ref"]) {
|
|
75
|
+
console.warn(`Found object without object_ref in test ${criteriaRef}`);
|
|
76
|
+
}
|
|
77
|
+
else {
|
|
78
|
+
const objectRef = object["@_object_ref"];
|
|
79
|
+
const foundObjectReference = searchTree(parsed.oval_definitions[0].objects, (oNode) => oNode["@_id"] === objectRef, false)[0];
|
|
80
|
+
if (foundObjectReference) {
|
|
81
|
+
foundObjects.push(foundObjectReference);
|
|
82
|
+
}
|
|
83
|
+
else {
|
|
84
|
+
console.warn(`Could not find object ${objectRef} for test ${criteriaRef}`);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
if (foundCriteriaRefererence.state) {
|
|
90
|
+
foundCriteriaRefererence.state.forEach((state) => {
|
|
91
|
+
if (!state["@_state_ref"]) {
|
|
92
|
+
console.warn(`Found state without state_ref in test ${criteriaRef}`);
|
|
93
|
+
}
|
|
94
|
+
else {
|
|
95
|
+
const stateRef = state["@_state_ref"];
|
|
96
|
+
const foundStateReference = searchTree(parsed.oval_definitions[0].states, (oNode) => oNode["@_id"] === stateRef, false)[0];
|
|
97
|
+
if (foundStateReference) {
|
|
98
|
+
foundStates.push(foundStateReference);
|
|
99
|
+
}
|
|
100
|
+
else {
|
|
101
|
+
console.warn(`Could not find state ${stateRef} for test ${criteriaRef}`);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
return { ...foundCriteriaRefererence, resolvedObjects: foundObjects, resolvedStates: foundStates };
|
|
108
|
+
}).filter((value) => value);
|
|
15
109
|
}
|
|
16
110
|
}
|
|
17
111
|
}
|
package/lib/parsers/xccdf.d.ts
CHANGED
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
import Profile from '../objects/profile';
|
|
2
|
-
import { BenchmarkGroup, BenchmarkRule } from '../types/xccdf';
|
|
2
|
+
import { BenchmarkGroup, BenchmarkRule, RuleComplexCheck } from '../types/xccdf';
|
|
3
3
|
import { OvalDefinitionValue } from '../types/oval';
|
|
4
4
|
export declare type GroupContextualizedRule = BenchmarkRule & {
|
|
5
5
|
group: Omit<BenchmarkGroup, 'Rule' | 'Group'>;
|
|
6
6
|
};
|
|
7
7
|
export declare function extractAllRules(groups: BenchmarkGroup[]): GroupContextualizedRule[];
|
|
8
|
-
export declare function
|
|
8
|
+
export declare function extractAllComplexChecks(complexCheck: RuleComplexCheck): Omit<RuleComplexCheck, 'complex-check'>[];
|
|
9
|
+
export declare function processXCCDF(xml: string, removeNewlines: boolean | undefined, useRuleId: 'group' | 'rule' | 'version' | 'cis', ovalDefinitions?: Record<string, OvalDefinitionValue & {
|
|
10
|
+
criteriaRefs?: string[];
|
|
11
|
+
resolvedValues?: any;
|
|
12
|
+
}>): Profile;
|
package/lib/parsers/xccdf.js
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.processXCCDF = exports.extractAllRules = void 0;
|
|
3
|
+
exports.processXCCDF = exports.extractAllComplexChecks = exports.extractAllRules = void 0;
|
|
4
4
|
const tslib_1 = require("tslib");
|
|
5
5
|
const profile_1 = tslib_1.__importDefault(require("../objects/profile"));
|
|
6
6
|
const xccdf_1 = require("../utilities/xccdf");
|
|
7
7
|
const control_1 = tslib_1.__importDefault(require("../objects/control"));
|
|
8
8
|
const lodash_1 = tslib_1.__importDefault(require("lodash"));
|
|
9
9
|
const CciNistMappingData_1 = require("../mappings/CciNistMappingData");
|
|
10
|
+
const pretty_1 = tslib_1.__importDefault(require("pretty"));
|
|
10
11
|
function extractAllRules(groups) {
|
|
11
12
|
const rules = [];
|
|
12
13
|
groups.forEach((group) => {
|
|
@@ -25,6 +26,17 @@ function extractAllRules(groups) {
|
|
|
25
26
|
return rules;
|
|
26
27
|
}
|
|
27
28
|
exports.extractAllRules = extractAllRules;
|
|
29
|
+
function extractAllComplexChecks(complexCheck) {
|
|
30
|
+
const complexChecks = [lodash_1.default.omit(complexCheck, 'complex-check')];
|
|
31
|
+
if (complexCheck['complex-check']) {
|
|
32
|
+
complexChecks.push(...complexCheck['complex-check'].map((subComplexCheck) => lodash_1.default.omit(subComplexCheck, 'complex-check')));
|
|
33
|
+
complexCheck['complex-check'].forEach((subComplexCheck) => {
|
|
34
|
+
complexChecks.push(...extractAllComplexChecks(subComplexCheck));
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
return complexChecks;
|
|
38
|
+
}
|
|
39
|
+
exports.extractAllComplexChecks = extractAllComplexChecks;
|
|
28
40
|
function ensureDecodedXMLStringValue(input) {
|
|
29
41
|
return lodash_1.default.get(input, '[0].#text') ? lodash_1.default.get(input, '[0].#text') : input;
|
|
30
42
|
}
|
|
@@ -39,8 +51,18 @@ function processXCCDF(xml, removeNewlines = false, useRuleId, ovalDefinitions) {
|
|
|
39
51
|
rules.forEach(rule => {
|
|
40
52
|
var _a, _b, _c;
|
|
41
53
|
let extractedDescription;
|
|
42
|
-
if (
|
|
43
|
-
|
|
54
|
+
if (typeof rule.description === 'object') {
|
|
55
|
+
if (Array.isArray(rule.description) && lodash_1.default.get(rule, "description[0]['#text']")) {
|
|
56
|
+
extractedDescription = rule.description[0]['#text'];
|
|
57
|
+
}
|
|
58
|
+
else {
|
|
59
|
+
if (typeof lodash_1.default.get(rule.description, '[0].p') === 'string') {
|
|
60
|
+
extractedDescription = (0, pretty_1.default)(lodash_1.default.get(rule.description, '[0].p'));
|
|
61
|
+
}
|
|
62
|
+
else {
|
|
63
|
+
extractedDescription = JSON.stringify(rule.description);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
44
66
|
}
|
|
45
67
|
else {
|
|
46
68
|
extractedDescription = (0, xccdf_1.convertEncodedHTMLIntoJson)(rule.description);
|
|
@@ -74,9 +96,19 @@ function processXCCDF(xml, removeNewlines = false, useRuleId, ovalDefinitions) {
|
|
|
74
96
|
default:
|
|
75
97
|
throw new Error('useRuleId must be one of "group", "rule", or "version"');
|
|
76
98
|
}
|
|
77
|
-
control.title = (0, xccdf_1.removeXMLSpecialCharacters)(rule['@_severity'] ? ensureDecodedXMLStringValue(rule.title) : `[[[MISSING SEVERITY FROM
|
|
78
|
-
|
|
79
|
-
|
|
99
|
+
control.title = (0, xccdf_1.removeXMLSpecialCharacters)(rule['@_severity'] ? ensureDecodedXMLStringValue(rule.title) : `[[[MISSING SEVERITY FROM BENCHMARK]]] ${ensureDecodedXMLStringValue(rule.title)}`);
|
|
100
|
+
if (typeof extractedDescription === 'object' && !Array.isArray(extractedDescription)) {
|
|
101
|
+
control.desc = ((_a = extractedDescription.VulnDiscussion) === null || _a === void 0 ? void 0 : _a.split('Satisfies: ')[0]) || '';
|
|
102
|
+
}
|
|
103
|
+
else if (typeof extractedDescription === 'object') {
|
|
104
|
+
control.desc = JSON.stringify(extractedDescription);
|
|
105
|
+
}
|
|
106
|
+
else if (typeof extractedDescription === 'string') {
|
|
107
|
+
control.desc = extractedDescription || '';
|
|
108
|
+
}
|
|
109
|
+
else {
|
|
110
|
+
console.warn(`Invalid value for extracted description: ${extractedDescription}`);
|
|
111
|
+
}
|
|
80
112
|
control.impact = (0, xccdf_1.severityStringToImpact)(rule['@_severity'] || 'medium', rule.group['@_id']);
|
|
81
113
|
if (!control.descs || Array.isArray(control.descs)) {
|
|
82
114
|
control.descs = {};
|
|
@@ -90,6 +122,7 @@ function processXCCDF(xml, removeNewlines = false, useRuleId, ovalDefinitions) {
|
|
|
90
122
|
let referenceID = null;
|
|
91
123
|
for (const checkContent of rule.check) {
|
|
92
124
|
if ('check-content-ref' in checkContent && checkContent['@_system'].includes('oval')) {
|
|
125
|
+
console.log(`Found OVAL reference: ${checkContent['@_system']}`);
|
|
93
126
|
for (const checkContentRef of checkContent['check-content-ref']) {
|
|
94
127
|
if (checkContentRef['@_name']) {
|
|
95
128
|
referenceID = checkContentRef['@_name'];
|
|
@@ -105,6 +138,54 @@ function processXCCDF(xml, removeNewlines = false, useRuleId, ovalDefinitions) {
|
|
|
105
138
|
}
|
|
106
139
|
}
|
|
107
140
|
}
|
|
141
|
+
// Very CIS specific
|
|
142
|
+
else if (rule['complex-check']) {
|
|
143
|
+
let checkTexts = [];
|
|
144
|
+
for (const complexChecks of rule['complex-check']) {
|
|
145
|
+
const allComplexChecks = extractAllComplexChecks(complexChecks);
|
|
146
|
+
if (control.id === '1.1.1.5') {
|
|
147
|
+
console.log(allComplexChecks);
|
|
148
|
+
}
|
|
149
|
+
allComplexChecks.forEach((complexCheck) => {
|
|
150
|
+
if (complexCheck.check) {
|
|
151
|
+
complexCheck.check.forEach((check) => {
|
|
152
|
+
var _a;
|
|
153
|
+
if ((_a = check['@_system']) === null || _a === void 0 ? void 0 : _a.toLowerCase().includes('oval')) {
|
|
154
|
+
const ovalReference = check['check-content-ref'][0]['@_name'];
|
|
155
|
+
if (!ovalDefinitions) {
|
|
156
|
+
console.warn(`Missing OVAL definitions! Unable to process OVAL reference: ${ovalReference}`);
|
|
157
|
+
}
|
|
158
|
+
else if (ovalReference && ovalReference in ovalDefinitions) {
|
|
159
|
+
ovalDefinitions[ovalReference].resolvedValues.forEach((resolvedValue) => {
|
|
160
|
+
const comment = resolvedValue['@_comment'];
|
|
161
|
+
if (comment) {
|
|
162
|
+
checkTexts.push(comment + '\n');
|
|
163
|
+
}
|
|
164
|
+
resolvedValue.resolvedObjects.forEach((resolvedObject) => {
|
|
165
|
+
// Try to find the associated state for a resolved object
|
|
166
|
+
const resolvedId = resolvedObject['@_id'].split(':')[resolvedValue['@_id'].split(':').length - 1];
|
|
167
|
+
if (resolvedId) {
|
|
168
|
+
const relatedResolvedState = resolvedValue.resolvedStates.find((resolvedState) => resolvedState['@_id'].toLowerCase().includes(resolvedId.toLowerCase()));
|
|
169
|
+
if (relatedResolvedState) {
|
|
170
|
+
lodash_1.default.set(resolvedObject, 'expectedState', lodash_1.default.pickBy(relatedResolvedState, (value, key) => !key.startsWith('@_')));
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
checkTexts.push(JSON.stringify(lodash_1.default.pickBy(resolvedObject, (value, key) => !key.startsWith('@_')), null, 2));
|
|
174
|
+
});
|
|
175
|
+
});
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
else {
|
|
179
|
+
console.warn(`Found external reference to unknown system: ${check['@_system']}, only OVAL is supported`);
|
|
180
|
+
}
|
|
181
|
+
});
|
|
182
|
+
}
|
|
183
|
+
});
|
|
184
|
+
}
|
|
185
|
+
if (checkTexts.length >= 1) {
|
|
186
|
+
control.descs.check = checkTexts.join('\n');
|
|
187
|
+
}
|
|
188
|
+
}
|
|
108
189
|
if (lodash_1.default.get(rule.fixtext, '[0]["#text"]')) {
|
|
109
190
|
control.descs.fix = (0, xccdf_1.removeXMLSpecialCharacters)(rule.fixtext[0]['#text']);
|
|
110
191
|
}
|
|
@@ -113,7 +194,17 @@ function processXCCDF(xml, removeNewlines = false, useRuleId, ovalDefinitions) {
|
|
|
113
194
|
}
|
|
114
195
|
else if (typeof rule.fixtext === 'object') {
|
|
115
196
|
if (Array.isArray(rule.fixtext)) {
|
|
116
|
-
control.descs.fix = (0, xccdf_1.removeXMLSpecialCharacters)(
|
|
197
|
+
control.descs.fix = (0, xccdf_1.removeXMLSpecialCharacters)((0, pretty_1.default)((0, xccdf_1.convertJsonIntoXML)(rule.fixtext.map((fixtext) => {
|
|
198
|
+
if (fixtext.div) {
|
|
199
|
+
return fixtext.div;
|
|
200
|
+
}
|
|
201
|
+
else {
|
|
202
|
+
return fixtext;
|
|
203
|
+
}
|
|
204
|
+
}))));
|
|
205
|
+
}
|
|
206
|
+
else {
|
|
207
|
+
control.descs.fix = (0, xccdf_1.removeXMLSpecialCharacters)((0, pretty_1.default)((0, xccdf_1.convertJsonIntoXML)(rule.fixtext)));
|
|
117
208
|
}
|
|
118
209
|
}
|
|
119
210
|
else if (typeof rule.fixtext === 'undefined') {
|
|
@@ -124,7 +215,7 @@ function processXCCDF(xml, removeNewlines = false, useRuleId, ovalDefinitions) {
|
|
|
124
215
|
else {
|
|
125
216
|
control.descs.fix = 'Missing fix text';
|
|
126
217
|
}
|
|
127
|
-
control.tags.severity = (0, xccdf_1.impactNumberToSeverityString)((0, xccdf_1.severityStringToImpact)(rule['@_severity'] || '
|
|
218
|
+
control.tags.severity = (0, xccdf_1.impactNumberToSeverityString)((0, xccdf_1.severityStringToImpact)(rule['@_severity'] || 'medium', control.id || 'Unknown'));
|
|
128
219
|
control.tags.gid = rule.group['@_id'],
|
|
129
220
|
control.tags.rid = rule['@_id'];
|
|
130
221
|
control.tags.stig_id = rule['version'];
|