Skip to content

Commit

Permalink
Merge branch 'add-convert-cci-list-workflow' into checklistView
Browse files Browse the repository at this point in the history
  • Loading branch information
jtquach1 committed Nov 29, 2024
2 parents dbdac31 + 814bc66 commit 6fd7e5e
Show file tree
Hide file tree
Showing 178 changed files with 316,787 additions and 94,399 deletions.
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
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}}
Original file line number Diff line number Diff line change
Expand Up @@ -146,9 +146,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 @@ -228,8 +231,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';
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

0 comments on commit 6fd7e5e

Please sign in to comment.