Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add convert CCI list workflow #6336

Open
wants to merge 54 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
54 commits
Select commit Hold shift + click to select a range
a4eb287
Fix typo
jtquach1 Oct 24, 2024
e11c5c5
Fix crashing on CCIs who had no references to any NIST controls
jtquach1 Oct 28, 2024
a1c6c64
Generate CCI definitions alongside CCI to NIST file
jtquach1 Oct 28, 2024
29844bb
Rename xml2json to cciListXml2json
jtquach1 Oct 28, 2024
a8b7c67
Update CciNistMappingData with converted content from U_CCI_List.xml
jtquach1 Oct 28, 2024
dbd0229
Update frontend component, CciNistMapping used in converters, delete …
jtquach1 Oct 28, 2024
f8f812f
Add comment about GitHub-hosted wiki for cciListXml2json
jtquach1 Oct 28, 2024
9490959
Create GitHub workflow for pulling down U_CCI_List.xml and converting…
jtquach1 Oct 28, 2024
26aaec3
Fix cron syntax
jtquach1 Oct 28, 2024
063426d
Also add Prettier job to format CciNistMappingData.ts
jtquach1 Oct 28, 2024
fe981f7
Update author and email in commit changes step
jtquach1 Oct 29, 2024
067abfc
Update XCCDF mapper OpenSCAP ubuntu1804 expected JSON
jtquach1 Oct 29, 2024
051defa
Remove temporary file after updating CciNistMappingData.ts
jtquach1 Oct 29, 2024
d6abe03
Address review comments
jtquach1 Oct 30, 2024
99dc13e
Check that workflow runs
jtquach1 Oct 30, 2024
1827856
Remove step
jtquach1 Oct 30, 2024
4483383
Update xml-file parameter in publish-date step
jtquach1 Oct 30, 2024
8e56f8b
Add namespaces parameter to publish-date step and add debug commands
jtquach1 Oct 30, 2024
a50be6a
Update xpath
jtquach1 Oct 30, 2024
019f229
Try to fix xpath again
jtquach1 Nov 1, 2024
abf89e7
Try to fix path of input XML
jtquach1 Nov 1, 2024
0a371bb
Try to resolve 'a mapping was not expected' error
jtquach1 Nov 1, 2024
f6f0cd0
Remove env var
jtquach1 Nov 1, 2024
40a643e
Set env var with path to input XML in separate step
jtquach1 Nov 1, 2024
691f50e
Update paths to input and output XML files
jtquach1 Nov 1, 2024
ad21342
Move env attribute
jtquach1 Nov 1, 2024
4287473
Try to print result of previous step
jtquach1 Nov 1, 2024
7da7aff
Try to grab output of publish-date step from object
jtquach1 Nov 1, 2024
b2e9067
Update to proper branch
jtquach1 Nov 1, 2024
be0d023
Explicitly specify parent-most component in U_CCI_List.xml to grab ve…
jtquach1 Nov 1, 2024
6c2dc8f
Move getCCIsForNISTTags function into libs/hdf-converters/src/mapping…
jtquach1 Nov 1, 2024
518361d
Update GitHub Action and cciListXml2json script to create NIST->CCI J…
jtquach1 Nov 1, 2024
36311c3
Update files from cciListXml2json script and new formatting
jtquach1 Nov 1, 2024
1ea35ea
Remove step
jtquach1 Nov 1, 2024
12d0bbd
Fix env var
jtquach1 Nov 1, 2024
8c2d75a
Remove trailing slash
jtquach1 Nov 1, 2024
67ff7ac
Restructure CCI to NIST and NIST to CCI logic across mappers and dele…
jtquach1 Nov 5, 2024
6125752
Export variables representing magic strings to be used in NIST2CCI fu…
jtquach1 Nov 5, 2024
9788090
Update path for output directory and rename steps
jtquach1 Nov 5, 2024
5965480
WIP address latest PR review comments
jtquach1 Nov 6, 2024
d94270a
Revert NIST->CCI trie to Record<string, string[]>
jtquach1 Nov 6, 2024
7943cb2
Fix typo
jtquach1 Nov 6, 2024
cfad3f4
Update XCCDF mapper and expected XML->HDF test outputs to not include…
jtquach1 Nov 8, 2024
6b3f75b
Fix typo in commented generating-expected-output code
jtquach1 Nov 8, 2024
b42ff7d
Regenerate test expected output files
jtquach1 Nov 8, 2024
20341bd
Uncomment GitHub Action code
jtquach1 Nov 8, 2024
afdbc30
Fix lint issue
jtquach1 Nov 8, 2024
6e717aa
Update XCCDF mapper as per NIST to CCI, CCI to NIST, and proper defau…
jtquach1 Nov 15, 2024
e6597bd
Reduce code complexity in CCI List XML to JSON converter
jtquach1 Nov 15, 2024
a9843fa
Produce empty array of CCI tags in JSONIX->CKL mapper if the input JS…
jtquach1 Nov 18, 2024
08b5a21
Add change to convert-cci-yml based on code review comment
jtquach1 Nov 26, 2024
16e69d7
Keep Revision info when mapping from CCI to NIST
jtquach1 Nov 29, 2024
c1101dd
Remove creator key from NistReference
jtquach1 Nov 29, 2024
c7c5f81
Update style.css
jtquach1 Nov 29, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 60 additions & 0 deletions .github/workflows/convert-cci-list.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
name: Convert CCI List XML to JSON

on:
push:
branches: ['master']

# Run this workflow on the 1st day at 00:00 every month
schedule:
- cron: '0 0 1 * *'

env:
# This URL is super brittle with how links constantly get changed.
CCI_LIST_ZIP_URL: https://dl.dod.cyber.mil/wp-content/uploads/stigs/zip/U_CCI_List.zip

jobs:
convert-cci-list:
runs-on: ubuntu-22.04
steps:
- name: Checkout the code
jtquach1 marked this conversation as resolved.
Show resolved Hide resolved
uses: actions/checkout@v4
- run: git fetch --prune --unshallow
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '18'
check-latest: true
cache: 'yarn'

- name: Install project dependencies
run: yarn install --frozen-lockfile

- name: Download CCI List
run: |
curl -o U_CCI_List.zip $CCI_LIST_ZIP_URL && unzip U_CCI_List.zip

- name: Get publish date of CCI List
id: publish-date
uses: mavrosxristoforos/[email protected]
with:
xml-file: 'U_CCI_List.xml'
xpath: '/*[local-name()="cci_list"]/*[local-name()="metadata"]/*[local-name()="publishdate"]'
namespaces: '{"ns": "http://iase.disa.mil/cci"}'

- name: Set directory environment variables for next step
run: |
echo "ROOT_DIRECTORY=$(pwd)" >> $GITHUB_ENV
echo "OUTPUT_DIRECTORY=$(pwd)/libs/hdf-converters/src/mappings" >> $GITHUB_ENV

- name: Convert CCI List XML to CCI->NIST, CCI->Definitions, and NIST->CCI JSON files
run: yarn workspace @mitre/hdf-converters cciListXml2json -i $ROOT_DIRECTORY/U_CCI_List.xml -n $OUTPUT_DIRECTORY/U_CCI_List.nist.json -d $OUTPUT_DIRECTORY/U_CCI_List.defs.json -c $OUTPUT_DIRECTORY/U_CCI_List.cci.json

- name: Commit changes to produced JSON files
run: |
git config --local user.email "[email protected]"
git config --local user.name "MITRE SAF Automation"
git add $OUTPUT_DIRECTORY/U_CCI_List.nist.json $OUTPUT_DIRECTORY/U_CCI_List.defs.json $OUTPUT_DIRECTORY/U_CCI_List.cci.json
git commit -sm "Update CCI List to the current NIST and definition mappings as of $DATETIME"
git push
env:
DATETIME: ${{steps.publish-date.outputs.info}}
2 changes: 1 addition & 1 deletion apps/frontend/public/static/export/style.css

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -142,9 +142,12 @@
<script lang="ts">
import ResponsiveRowSwitch from '@/components/cards/controltable/ResponsiveRowSwitch.vue';
import HtmlSanitizeMixin from '@/mixins/HtmlSanitizeMixin';
import {CCI_DESCRIPTIONS} from '@/utilities/cci_util';
import {getControlRunTime} from '@/utilities/delta_util';
import {nistCanonConfig, NIST_DESCRIPTIONS} from '@/utilities/nist_util';
import {
CCI_TO_DEFINITION,
CCI_TO_NIST
} from '@mitre/hdf-converters/src/mappings/CciNistMappingData';
import {ContextualizedControl, is_control, parse_nist} from 'inspecjs';
import * as _ from 'lodash';
import Component, {mixins} from 'vue-class-component';
Expand Down Expand Up @@ -224,8 +227,11 @@ export default class ControlRowHeader extends mixins(HtmlSanitizeMixin) {
if (found) {
return found;
}
} else if (CCI_DESCRIPTIONS[tag.toUpperCase()]) {
return CCI_DESCRIPTIONS[tag.toUpperCase()].def;
} else if (
CCI_TO_NIST[tag.toUpperCase()] &&
CCI_TO_DEFINITION[tag.toUpperCase()]
) {
return CCI_TO_DEFINITION[tag.toUpperCase()];
}
return 'Unrecognized Tag';
}
Expand Down
14,210 changes: 0 additions & 14,210 deletions apps/frontend/src/utilities/cci_util.ts

This file was deleted.

159 changes: 159 additions & 0 deletions libs/hdf-converters/data/converters/cciListXml2json.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
import fs from 'fs';
import * as _ from 'lodash';
import xml2js from 'xml2js';
jtquach1 marked this conversation as resolved.
Show resolved Hide resolved
import {parseArgs} from 'node:util';
import {is_control, parse_nist} from 'inspecjs/src/nist';

// Documentation is located at https://github.com/mitre/heimdall2/wiki/Control-Correlation-Identifier-(CCI)-Converter.
const parser = new xml2js.Parser();

const options = {
input: {
type: 'string',
short: 'i'
},
cci2nist: {
type: 'string',
short: 'n'
},
cci2definitions: {
type: 'string',
short: 'd'
},
nist2cci: {
type: 'string',
short: 'c'
}
} as const;

// XML Structure after conversion
export interface ICCIList {
cci_list: {
cci_items: {
cci_item: {
$: Record<string, string>;
references?: {
reference: {
$: {
creator: string;
title: string;
version: string;
index: string;
};
}[];
}[];
definition: string[];
}[];
}[];
};
}

export type NistReference = {
title: string;
nist: string;
version: string;
};

// Check that we're not doing `npm test`; it will look for the arguments to the input and output files.
const scriptIsCalled = process.argv[1].includes('cciListXml2json');

if (scriptIsCalled) {
const {values} = parseArgs({options});

const pathToInfile = values.input;
const pathToCci2NistOutfile = values.cci2nist;
const pathToCci2DefinitionsOutfile = values.cci2definitions;
const pathToNist2CciOutfile = values.nist2cci;

if (
!pathToInfile ||
!pathToCci2NistOutfile ||
!pathToCci2DefinitionsOutfile ||
!pathToNist2CciOutfile
) {
console.error(
'You must provide the path to the input and three output files.'
);
} else {
fs.readFile(pathToInfile, function (readFileError, data) {
if (readFileError) {
console.error(`Failed to read ${pathToInfile}: ${readFileError}`);
} else {
// Parse XML to JS Object
parser.parseString(data, (parseFileError: any, cciList: ICCIList) => {
if (parseFileError) {
console.error(`Failed to parse ${pathToInfile}: ${parseFileError}`);
} else {
// These store our CCI->NIST names, CCI->definitions, and NIST->CCI mappings
const {nists, definitions, ccis} = produceConversions(cciList);

fs.writeFileSync(
pathToCci2NistOutfile,
JSON.stringify(nists, null, 2)
);

fs.writeFileSync(
pathToCci2DefinitionsOutfile,
JSON.stringify(definitions, null, 2)
);

fs.writeFileSync(
pathToNist2CciOutfile,
JSON.stringify(ccis, null, 2)
);
}
});
}
});
}
}

function produceConversions(cciList: ICCIList): {
nists: Record<string, NistReference[]>;
definitions: Record<string, string>;
ccis: Record<string, string[]>;
} {
const nists: Record<string, NistReference[]> = {};
const definitions: Record<string, string> = {};
const ccis: Record<string, string[]> = {};

// For all CCI items
for (const cciItem of cciList.cci_list.cci_items[0].cci_item) {
// Get the latest reference
const newestReference = _.maxBy(cciItem.references?.[0].reference, (item) =>
_.get(item, '$.version')
);
const cciId = cciItem.$.id;

if (newestReference) {
/* There's 1 out of the 2000+ CCI controls where this index string is composed of at
least 2 comma-and-space-separated controls found in the latest revision. */
const {version, creator, index, title} = newestReference.$;
if (creator === 'NIST') {
const nistIds = index
.split(/,\s*/)
.map(parse_nist)
.filter(is_control)
.map((n) => n.canonize());

_.set(
nists,
cciId,
nistIds.map((nist) => ({version, title, nist}))
);
_.set(definitions, cciId, cciItem.definition[0]);

for (const nistId of nistIds) {
if (ccis[nistId] === undefined) {
ccis[nistId] = [cciId];
} else {
ccis[nistId].push(cciId);
}
}
}
} else {
console.error(`No NIST Controls found for ${cciId}`);
}
}
return {nists, definitions, ccis};
}
57 changes: 0 additions & 57 deletions libs/hdf-converters/data/converters/xml2json.ts

This file was deleted.

2 changes: 1 addition & 1 deletion libs/hdf-converters/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
"postpack:win32": "move package.json.orig package.json",
"test": "jest",
"csv2json": "tsx data/converters/csv2json.ts",
"xml2json": "tsx data/converters/xml2json.ts"
"cciListXml2json": "tsx data/converters/cciListXml2json.ts"
},
"dependencies": {
"@aws-sdk/client-config-service": "^3.95.0",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
{
"platform": {
"name": "Heimdall Tools",
"release": "2.10.15",
"release": "2.10.20",
"target_id": null
},
"version": "2.10.15",
"version": "2.10.20",
"statistics": {
"duration": null
},
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
{
"platform": {
"name": "Heimdall Tools",
"release": "2.10.15",
"release": "2.10.20",
"target_id": null
},
"version": "2.10.15",
"version": "2.10.20",
"statistics": {
"duration": null
},
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
{
"platform": {
"name": "Heimdall Tools",
"release": "2.10.15",
"release": "2.10.20",
"target_id": null
},
"version": "2.10.15",
"version": "2.10.20",
"statistics": {
"duration": null
},
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
{
"platform": {
"name": "Heimdall Tools",
"release": "2.10.15",
"release": "2.10.20",
"target_id": null
},
"version": "2.10.15",
"version": "2.10.20",
"statistics": {
"duration": null
},
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
{
"platform": {
"name": "Heimdall Tools",
"release": "2.10.15",
"release": "2.10.20",
"target_id": null
},
"version": "2.10.15",
"version": "2.10.20",
"statistics": {
"duration": null
},
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
{
"platform": {
"name": "Heimdall Tools",
"release": "2.10.15",
"release": "2.10.20",
"target_id": null
},
"version": "2.10.15",
"version": "2.10.20",
"statistics": {
"duration": null
},
Expand Down
Loading
Loading