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

Resolves #1076 - ADP short name parameter #1087

Merged
merged 7 commits into from
Jun 23, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
24 changes: 24 additions & 0 deletions api-docs/openapi.json
Original file line number Diff line number Diff line change
Expand Up @@ -832,6 +832,12 @@
},
{
"$ref": "#/components/parameters/pageQuery"
},
{
"$ref": "#/components/parameters/cnaModified"
},
{
"$ref": "#/components/parameters/adpShortName"
}
],
"responses": {
Expand Down Expand Up @@ -2644,6 +2650,24 @@
"type": "boolean"
}
},
"cnaModified": {
"in": "query",
"name": "cna_modified",
"description": "Only get CVE records with cnaContainers that have been modified/created within the set time_modified range. Requires at least one time_modified parameter set",
"required": false,
"schema": {
"type": "boolean"
}
},
"adpShortName": {
"in": "query",
"name": "adp_short_name",
"description": "Only get CVE records that have an adpContainer owned by this org and that has been modified/created within the set time_modified range. Requires at least one time_modified parameter set",
"required": false,
"schema": {
"type": "string"
}
},
"cveState": {
"in": "query",
"name": "state",
Expand Down
62 changes: 50 additions & 12 deletions src/controller/cve.controller/cve.controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ async function getFilteredCves (req, res, next) {
let cnaModified = false
let timeModifiedGtDateObject = null
let timeModifiedLtDateObject = null
let adpShortName = null
const timeModified = {
timeStamp: [],
dateOperator: []
Expand Down Expand Up @@ -81,6 +82,8 @@ async function getFilteredCves (req, res, next) {
assigner = req.ctx.query.assigner
} else if (key === 'cna_modified') {
cnaModified = req.ctx.query.cna_modified
} else if (key === 'adp_short_name') {
adpShortName = req.ctx.query.adp_short_name
}
})

Expand Down Expand Up @@ -144,25 +147,60 @@ async function getFilteredCves (req, res, next) {
const pg = await cveRepo.aggregatePaginate(agt, options)
const payload = {
cveRecords: pg.itemsList.map(val => { return val.cve }).filter((val) => {
// If cnaModified is false, return all values.
if (!cnaModified) {
// If cnaModified AND adpShortName are false, return all values, no filtering to be done.
if (!cnaModified && !adpShortName) {
return true
}
// Check that the CNA has a date updated
if ((val.containers.cna.providerMetadata?.dateUpdated)) {
// If the time modified gt flag is set, and the dateUpdated date is less than the flag
if ((timeModifiedGtDateObject && timeModifiedGtDateObject > toDate(val.containers.cna.providerMetadata?.dateUpdated))) {

// cnaModified and adpShortName are treated as an AND if they are both set
if (cnaModified) {
if (val.containers.cna.providerMetadata?.dateUpdated) {
// If the time modified gt flag is set, and the dateUpdated date is less than the flag
if ((timeModifiedGtDateObject && timeModifiedGtDateObject > toDate(val.containers.cna.providerMetadata?.dateUpdated))) {
return false
}
// if the time modified lt flag is set, and the dateUpdated date is greater than the flag
if ((timeModifiedLtDateObject && timeModifiedLtDateObject < toDate(val.containers.cna.providerMetadata?.dateUpdated))) {
return false
}
} else {
// if cnaModified was set, but there is no value
return false
}
// if the time modified lt flag is set, and the dateUpdated date is greater than the flag
if ((timeModifiedLtDateObject && timeModifiedLtDateObject < toDate(val.containers.cna.providerMetadata?.dateUpdated))) {
}
if (adpShortName) {
// Check to make sure we want to filter ADPs and that the CVE has an ADP container
if (val.containers?.adp && val.containers?.adp?.length) {
// Check all adp containers and if ANY of them have what we are searching for, return them
let adpMatchFound = false
for (const element of val.containers.adp) {
// If shortname is defined AND no dates are set, only check for the short name
if (element.providerMetadata.shortName === adpShortName) {
if (!timeModifiedGtDateObject && !timeModifiedLtDateObject) {
adpMatchFound = true
break
} else {
// otherwise we need to check the dates for a match
if ((timeModifiedGtDateObject && timeModifiedGtDateObject < toDate(element.providerMetadata?.dateUpdated))) {
adpMatchFound = true
break
}
if (timeModifiedLtDateObject && timeModifiedLtDateObject > toDate(element.providerMetadata?.dateUpdated)) {
adpMatchFound = true
break
}
}
}
}
if (!adpMatchFound) {
return false
}
} else {
// if adpShortName was set, BUT we didn't find anything
return false
}
// If the code gets to this point, all checks have passed.
return true
}
// Base fall through case
return false
return true
})
}

Expand Down
2 changes: 1 addition & 1 deletion src/controller/cve.controller/cve.middleware.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ function parsePostParams (req, res, next) {
}

function parseGetParams (req, res, next) {
utils.reqCtxMapping(req, 'query', ['page', 'time_modified.lt', 'time_modified.gt', 'state', 'count_only', 'assigner_short_name', 'assigner', 'cna_modified'])
utils.reqCtxMapping(req, 'query', ['page', 'time_modified.lt', 'time_modified.gt', 'state', 'count_only', 'assigner_short_name', 'assigner', 'cna_modified', 'adp_short_name'])
utils.reqCtxMapping(req, 'params', ['id'])
next()
}
Expand Down
7 changes: 5 additions & 2 deletions src/controller/cve.controller/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,9 @@ router.get('/cve',
'#/components/parameters/countOnly',
'#/components/parameters/assignerShortName',
'#/components/parameters/assigner',
'#/components/parameters/pageQuery'
'#/components/parameters/pageQuery',
'#/components/parameters/cnaModified',
'#/components/parameters/adpShortName'
]
#swagger.responses[200] = {
description: 'A filtered list of CVE Records, along with pagination fields if results span multiple pages of data',
Expand Down Expand Up @@ -154,7 +156,7 @@ router.get('/cve',
*/
mw.validateUser,
mw.onlySecretariatOrBulkDownload,
query().custom((query) => { return mw.validateQueryParameterNames(query, ['page', 'time_modified.lt', 'time_modified.gt', 'state', 'count_only', 'assigner_short_name', 'assigner', 'cna_modified']) }),
query().custom((query) => { return mw.validateQueryParameterNames(query, ['page', 'time_modified.lt', 'time_modified.gt', 'state', 'count_only', 'assigner_short_name', 'assigner', 'cna_modified', 'adp_short_name']) }),
query(['page']).optional().isInt({ min: CONSTANTS.PAGINATOR_PAGE }),
query(['time_modified.lt']).optional().isString().trim().escape().customSanitizer(val => { return toDate(val) }).not().isEmpty().withMessage(errorMsgs.TIMESTAMP_FORMAT),
query(['time_modified.gt']).optional().isString().trim().escape().customSanitizer(val => { return toDate(val) }).not().isEmpty().withMessage(errorMsgs.TIMESTAMP_FORMAT),
Expand All @@ -163,6 +165,7 @@ router.get('/cve',
query(['assigner_short_name']).optional().isString().trim().escape().notEmpty().isLength({ min: CONSTANTS.MIN_SHORTNAME_LENGTH, max: CONSTANTS.MAX_SHORTNAME_LENGTH }),
query(['assigner']).optional().isString().trim().escape().notEmpty(),
query(['cna_modified']).optional().isBoolean({ loose: true }).withMessage(errorMsgs.CNA_MODIFIED),
query(['adp_short_name']).optional().isString().trim().escape().notEmpty().isLength({ min: CONSTANTS.MIN_SHORTNAME_LENGTH, max: CONSTANTS.MAX_SHORTNAME_LENGTH }),
parseError,
parseGetParams,
controller.CVE_GET_FILTERED)
Expand Down
18 changes: 18 additions & 0 deletions src/swagger.js
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,24 @@ const doc = {
type: 'boolean'
}
},
cnaModified: {
in: 'query',
name: 'cna_modified',
description: 'Only get CVE records with cnaContainers that have been modified/created within the set time_modified range. Requires at least one time_modified parameter set',
required: false,
schema: {
type: 'boolean'
}
},
adpShortName: {
in: 'query',
name: 'adp_short_name',
description: 'Only get CVE records that have an adpContainer owned by this org and that has been modified/created within the set time_modified range. Requires at least one time_modified parameter set',
required: false,
schema: {
type: 'string'
}
},
cveState: {
in: 'query',
name: 'state',
Expand Down
83 changes: 83 additions & 0 deletions test/integration-tests/cve/getCveAdpShortNameTest.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
/* eslint-disable no-unused-expressions */
const chai = require('chai')
chai.use(require('chai-http'))
const expect = chai.expect

const constants = require('../constants.js')
const app = require('../../../src/index.js')
const helpers = require('../helpers.js')
const _ = require('lodash')

const shortName = 'win_5'

describe('Test cna_modified parameter for get CVE', () => {
let cveId
before(async () => {
cveId = await helpers.cveIdReserveHelper(1, '2023', shortName, 'non-sequential')
await helpers.cveRequestAsCnaHelper(cveId)
await helpers.cveUpdateAsCnaHelperWithAdpContainer(cveId, constants.testAdp)
})
context('Positive Test', () => {
it('CVE should not be returned with adp_short_name set to fake_org as it does not exist', async () => {
await chai.request(app)
.get('/api/cve/?adp_short_name=fake_org')
.set(constants.headers)
.then((res, err) => {
expect(err).to.be.undefined
expect(res).to.have.status(200)
expect(_.some(res.body.cveRecords, { cveMetadata: { cveId: cveId } })).to.be.false
})
})
it(`CVE should be returned with adp_short_name set to ${shortName} as it has been created`, async () => {
await chai.request(app)
.get(`/api/cve/?adp_short_name=${shortName}`)
.set(constants.headers)
.then((res, err) => {
expect(err).to.be.undefined
expect(res).to.have.status(200)
expect(_.some(res.body.cveRecords, { cveMetadata: { cveId: cveId } })).to.be.true
})
})
it(`Get CVE with adp_short_name set to ${shortName} AND date.gt should return when searched with a known earlier than date`, async () => {
await chai.request(app)
.get(`/api/cve/?time_modified.gt=2022-01-01T00:00:00&adp_short_name=${shortName}`)
.set(constants.headers)
.then((res, err) => {
expect(err).to.be.undefined
expect(res).to.have.status(200)
expect(_.some(res.body.cveRecords, { cveMetadata: { cveId: cveId } })).to.be.true
})
})
it(`Get CVE with with adp_short_name set to ${shortName} AND date.gt should return and empty list when searched with a known bad earlier than date`, async () => {
await chai.request(app)
.get(`/api/cve/?time_modified.gt=2100-01-01T00:00:00&adp_short_name=${shortName}`)
.set(constants.headers)
.then((res, err) => {
expect(err).to.be.undefined
expect(res).to.have.status(200)
expect(_.some(res.body.cveRecords, { cveMetadata: { cveId: cveId } })).to.be.false
})
})

it(`Get CVE with adp_short_name set to ${shortName} AND date.lt should return when searched with a known later than date`, async () => {
await chai.request(app)
.get(`/api/cve/?time_modified.lt=2100-01-01T00:00:00&adp_short_name=${shortName}`)
.set(constants.headers)
.then((res, err) => {
expect(err).to.be.undefined
expect(res).to.have.status(200)
expect(_.some(res.body.cveRecords, { cveMetadata: { cveId: cveId } })).to.be.true
})
})
it(`Get CVE with adp_short_name set to ${shortName} AND date.lt should return and empty list when searched with a known bad later than date`, async () => {
await chai.request(app)
.get(`/api/cve/?time_modified.lt=2022-01-01T00:00:00&adp_short_name=${shortName}`)
.set(constants.headers)
.then((res, err) => {
expect(err).to.be.undefined
expect(res).to.have.status(200)
expect(_.some(res.body.cveRecords, { cveMetadata: { cveId: cveId } })).to.be.false
})
})
})
})
12 changes: 11 additions & 1 deletion test/integration-tests/helpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,4 +51,14 @@ async function cveUpdatetAsCnaHelperWithCnaContainer (cveId, cnaContainer) {
})
}

module.exports = { cveIdReserveHelper, cveRequestAsCnaHelper, cveRequestAsCnaHelperWithCnaContainer, cveUpdatetAsCnaHelperWithCnaContainer }
async function cveUpdateAsCnaHelperWithAdpContainer (cveId, adpContainer) {
await chai.request(app)
.put(`/api/cve/${cveId}/adp`)
.set(constants.nonSecretariatUserHeaders)
.send(adpContainer)
.then((res, err) => {
expect(res).to.have.status(200)
})
}

module.exports = { cveIdReserveHelper, cveRequestAsCnaHelper, cveRequestAsCnaHelperWithCnaContainer, cveUpdatetAsCnaHelperWithCnaContainer, cveUpdateAsCnaHelperWithAdpContainer }
Loading