Skip to content

Commit

Permalink
feat: USMC MCCAST formatted POAM export (#1345)
Browse files Browse the repository at this point in the history
Co-authored-by: David Whalen <david.whalen@usmc.mil>
Co-authored-by: cd-rite <61710958+cd-rite@users.noreply.github.com>
Co-authored-by: csmig <carlsmigielski@gmail.com>
  • Loading branch information
4 people authored Aug 28, 2024
1 parent c845ced commit 2c56ce1
Show file tree
Hide file tree
Showing 9 changed files with 466 additions and 137 deletions.
1 change: 1 addition & 0 deletions CONTRIBUTORS.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
- Copyright 2021 Russell Johnson, russell.d.johnson@saic.com
- Copyright 2023-2024 Mathew Ferreira, mferreira@rite-solutions.com
- Copyright 2024 Rajesh Shrestha, rshrestha@rite-solutions.com
- Copyright 2024 David Whalen, david.whalen@usmc.mil
- _Add the copyright date, your name, and email address here. (PLEASE KEEP THIS LINE)_

## Note for U.S. Federal Employees
Expand Down
40 changes: 26 additions & 14 deletions api/source/controllers/Collection.js
Original file line number Diff line number Diff line change
Expand Up @@ -151,36 +151,48 @@ module.exports.getFindingsByCollection = async function getFindingsByCollection

module.exports.getPoamByCollection = async function getFindingsByCollection (req, res, next) {
try {
const aggregator = req.query.aggregator
const benchmarkId = req.query.benchmarkId
const assetId = req.query.assetId
const acceptedOnly = req.query.acceptedOnly
const {
aggregator,
benchmarkId,
assetId,
acceptedOnly,
date,
office,
status,
mccastPackageId,
mccastAuthName,
format
} = req.query
const defaults = {
date: req.query.date,
office: req.query.office,
status: req.query.status
date,
office,
status,
mccastPackageId,
mccastAuthName
}
const { collectionId, collectionGrant } = getCollectionInfoAndCheckPermission(req, Security.ACCESS_LEVEL.Restricted)
const response = await CollectionService.getFindingsByCollection( collectionId, aggregator, benchmarkId, assetId, acceptedOnly,
const findings = await CollectionService.getFindingsByCollection( collectionId, aggregator, benchmarkId, assetId, acceptedOnly,
[
'rulesWithDiscussion',
'groups',
'assets',
'stigs',
'ccis'
], req.userObject )

const po = Serialize.poamObjectFromFindings(response, defaults)
const xlsx = await Serialize.xlsxFromPoamObject(po)
let collectionName = collectionGrant.collection.name
writer.writeInlineFile( res, xlsx, `POAM-${collectionName}_${escape.filenameComponentFromDate()}.xlsx`, 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet')

const poFns = {
EMASS: Serialize.poamObjectFromFindings,
MCCAST: Serialize.mccastPoamObjectFromFindings
}
const xlsx = await Serialize.xlsxFromPoamObject(poFns[format](findings, defaults), format)
writer.writeInlineFile( res, xlsx, `POAM-${format}-${collectionGrant.collection.name}_${escape.filenameComponentFromDate()}.xlsx`, 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet')

}
catch (err) {
next(err)
}
}


module.exports.getStigAssetsByCollectionUser = async function getStigAssetsByCollectionUser (req, res, next) {
try {
const userId = req.params.userId
Expand Down
29 changes: 29 additions & 0 deletions api/source/specification/stig-manager.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2418,17 +2418,36 @@ paths:
in: query
schema:
type: string
pattern: '^(0[1-9]|1[0-2])/(0[1-9]|[12][0-9]|3[01])/\d{4}$'
- name: office
description: Value for column Office/Org
in: query
schema:
type: string
maxLength: 255
allowReserved: true
- name: status
description: Value for column Status
in: query
schema:
type: string
maxLength: 255
allowReserved: true
- $ref: '#/components/parameters/PoamFormatQuery'
- name: mccastPackageId
description: Value for POAM MCCAST PackageId
in: query
schema:
type: string
maxLength: 255
allowReserved: true
- name: mccastAuthName
description: Value for POAM MCCAST Authorization Name
in: query
schema:
type: string
maxLength: 255
allowReserved: true
responses:
'200':
description: CollectionFinding response
Expand Down Expand Up @@ -7558,6 +7577,16 @@ components:
enum:
- ruleId
- groupId
PoamFormatQuery:
name: format
in: query
description: Value for POAM format (ie. EMASS, MCCAST)
schema:
type: string
enum:
- EMASS
- MCCAST
default: EMASS
RetentionDateQuery:
name: retentionDate
in: query
Expand Down
Binary file added api/source/utils/poam-template-mccast.xlsx
Binary file not shown.
46 changes: 39 additions & 7 deletions api/source/utils/serializers.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,36 @@ const {promises: fs} = require('fs')
const path = require('path')
const XlsxTemplate = require('xlsx-template')

module.exports.poamObjectFromFindings = function ( findings, defaults = {} ) {
module.exports.mccastPoamObjectFromFindings = function (findings, defaults = {}) {
const vuln = findings.map( finding => ({
authPackage: defaults.mccastAuthName,
name: finding.rules[0].title,
dateId: finding.stigs[0].ruleCount === 0 ? finding.stigs[0].benchmarkDate : '',
stigInfo: 'STIG Finding',
status: defaults.status,
packageId: defaults.mccastPackageId,
date: defaults.date,
startDate: '',
endDate: '',
securityChecks: finding.rules[0].ruleId || finding.groupId,
control: finding.ccis.map( cci => `DoD RMF-${defaults.mccastPackageId}-${cci.apAcronym?.replace(/\./g,' ')}-CNSSI 1253`).join('\n'),
resultingRisk: finding.severity === 'medium' ? 'Moderate' : `${finding.severity.charAt(0).toUpperCase()}${finding.severity.slice(1)}`,
weakness: finding.rules[0].vulnDiscussion,
mitigations: '',
comments: finding.stigs[0].ruleCount === 0 ? '' : finding.ccis.map( cci => `CCI-${cci.cci}`).join('\n'),
assets: finding.assets.map( asset => asset.name ).join('\n'),
mav: '',
mac: '',
mpr: '',
mui: '',
ms: '',
mi: '',
ma: ''
}))
return {vuln}
}

module.exports.poamObjectFromFindings = function (findings, defaults = {}) {
const vuln = findings.map( finding => ({
desc: `Title:\n${finding.rules[0].title}\n\nDescription:\n${finding.rules[0].vulnDiscussion}`,
control: finding.ccis.map( cci => cci.apAcronym).join('\n'),
Expand Down Expand Up @@ -30,15 +59,18 @@ module.exports.poamObjectFromFindings = function ( findings, defaults = {} ) {
recommendations: '',
resultingRisk: finding.severity === 'medium' ? 'Moderate' : `${finding.severity.charAt(0).toUpperCase()}${finding.severity.slice(1)}`,
}))
return {
vuln: vuln
}
return {vuln}
}

module.exports.xlsxFromPoamObject = async function ( po ) {
const templateData = await fs.readFile(path.join(__dirname,'poam-template.xlsx'))

module.exports.xlsxFromPoamObject = async function (substitutions, format) {
const templateFiles = {
EMASS: 'poam-template.xlsx',
MCCAST: 'poam-template-mccast.xlsx'
}
const templateData = await fs.readFile(path.join(__dirname, templateFiles[format]))
const template = new XlsxTemplate()
await template.loadTemplate(templateData)
await template.substitute( 1, po )
await template.substitute(1, substitutions)
return await template.generate({type: 'nodebuffer'})
}
Loading

0 comments on commit 2c56ce1

Please sign in to comment.