From e7983a523edc418d00bf0621d1814609cfbfa126 Mon Sep 17 00:00:00 2001 From: david-rocca Date: Tue, 26 Nov 2024 10:51:58 -0500 Subject: [PATCH 1/3] UTC is now enforced on the cve/id endpointss even for secretariat --- src/constants/index.js | 4 +- .../cve.controller/cve.controller.js | 6 +- src/utils/utils.js | 61 ++++++++++++++++++- 3 files changed, 67 insertions(+), 4 deletions(-) diff --git a/src/constants/index.js b/src/constants/index.js index 2b424b94b..b733add14 100644 --- a/src/constants/index.js +++ b/src/constants/index.js @@ -100,7 +100,9 @@ function getConstants () { CVE_ID_PATTERN: cveSchemaV5.definitions.cveId.pattern, // Ajv's pattern validation uses the "u" (unicode) flag: // https://ajv.js.org/json-schema.html#pattern - CVE_ID_REGEX: new RegExp(cveSchemaV5.definitions.cveId.pattern, 'u') + CVE_ID_REGEX: new RegExp(cveSchemaV5.definitions.cveId.pattern, 'u'), + DATE_FIELDS: ['cveMetadata.datePublished', 'cveMetadata.dateUpdated', 'cveMetadata.dateReserved', 'providerMetadata.dateUpdated', 'datePublic', 'dateAssigned' + ] } return defaults diff --git a/src/controller/cve.controller/cve.controller.js b/src/controller/cve.controller/cve.controller.js index d8e62db7a..94df0e6b7 100644 --- a/src/controller/cve.controller/cve.controller.js +++ b/src/controller/cve.controller/cve.controller.js @@ -4,6 +4,7 @@ const errors = require('./error') const getConstants = require('../../constants').getConstants const error = new errors.CveControllerError() const booleanIsTrue = require('../../utils/utils').booleanIsTrue +const convertDatesToISO = require('../../utils/utils').convertDatesToISO const url = process.env.NODE_ENV === 'staging' ? 'https://test.cve.org/' : 'https://cve.org/' // Helper function to create providerMetadata object @@ -331,7 +332,7 @@ async function submitCve (req, res, next) { const CONSTANTS = getConstants() try { - const newCve = new Cve({ cve: req.ctx.body }) + const newCve = new Cve({ cve: convertDatesToISO(req.ctx.body, CONSTANTS.DATE_FIELDS) }) const id = req.ctx.params.id const cveId = newCve.cve.cveMetadata.cveId const state = newCve.cve.cveMetadata.state @@ -391,7 +392,8 @@ async function updateCve (req, res, next) { const CONSTANTS = getConstants() try { - const newCve = new Cve({ cve: req.ctx.body }) + // All CVE fields are stored in UTC format, we need to check and convert dates to ISO before storing in the database. + const newCve = new Cve({ cve: convertDatesToISO(req.ctx.body, CONSTANTS.DATE_FIELDS) }) const cveId = req.ctx.params.id const cveRepo = req.ctx.repositories.getCveRepository() const cveIdRepo = req.ctx.repositories.getCveIdRepository() diff --git a/src/utils/utils.js b/src/utils/utils.js index f6ec5d2a1..5f5ddd758 100644 --- a/src/utils/utils.js +++ b/src/utils/utils.js @@ -1,6 +1,7 @@ const Org = require('../model/org') const User = require('../model/user') const getConstants = require('../constants').getConstants +const _ = require('lodash') const { DateTime } = require('luxon') async function getOrgUUID (shortName) { @@ -153,6 +154,62 @@ function toDate (val) { return result } +// Covert Dates to ISO format +function convertDatesToISO (obj, dateKeys) { + // Helper function to check if a value is a valid date + function isValidDate (value) { + return value instanceof Date && !isNaN(value) + } + + // Helper function to check if a string is a valid date + function isStringDate (value) { + const date = new Date(value) + return !isNaN(date.getTime()) + } + + function updateDateValue (objectToUpdate, key, value) { + if (isValidDate(value)) { + _.set(objectToUpdate, key, value.toISOString()) + } else if (typeof value === 'string' && isStringDate(value)) { + _.set(objectToUpdate, key, new Date(value).toISOString()) + } + } + + // For the top layer object + for (const key of dateKeys) { + if (_.has(obj, key)) { + const value = _.get(obj, key) + updateDateValue(obj, key, value) + } + } + + // For the ADP(s) + if (_.has(obj, 'containers.adp')) { + // Use lodash for each to loop over array and check for date keys + _.each(obj.containers.adp, (adp) => { + for (const key of dateKeys) { + if (_.has(adp, key)) { + const value = _.get(adp, key) + updateDateValue(adp, key, value) + } + } + }) + } + // For the CNAs + + if (_.has(obj, 'containers.cna')) { + // Use lodash to check the containers.cna object for date keys + for (const key of dateKeys) { + if (_.has(obj.containers.cna, key)) { + const value = _.get(obj.containers.cna, key) + updateDateValue(obj.containers.cna, key, value) + } + } + } + + return obj +} + module.exports = { isSecretariat, isBulkDownload, @@ -163,5 +220,7 @@ module.exports = { getUserUUID, reqCtxMapping, booleanIsTrue, - toDate + toDate, + convertDatesToISO + } From c8ebc8acac10873521f1178591a3e299d75aa247 Mon Sep 17 00:00:00 2001 From: david-rocca Date: Tue, 26 Nov 2024 11:12:25 -0500 Subject: [PATCH 2/3] Add converting call to other needed endpoints --- src/controller/cve.controller/cve.controller.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/controller/cve.controller/cve.controller.js b/src/controller/cve.controller/cve.controller.js index 94df0e6b7..7b90c9950 100644 --- a/src/controller/cve.controller/cve.controller.js +++ b/src/controller/cve.controller/cve.controller.js @@ -482,7 +482,7 @@ async function submitCna (req, res, next) { // create full cve record here const owningCna = await orgRepo.findOneByUUID(cveId.owning_cna) const assignerShortName = owningCna.short_name - const cnaContainer = req.ctx.body.cnaContainer + const cnaContainer = convertDatesToISO(req.ctx.body.cnaContainer, CONSTANTS.DATE_FIELDS) const dateUpdated = (new Date()).toISOString() const additionalCveMetadataFields = { assignerShortName: assignerShortName, @@ -564,7 +564,7 @@ async function updateCna (req, res, next) { // update cve record here const cveRecord = result.cve - const cnaContainer = req.ctx.body.cnaContainer + const cnaContainer = convertDatesToISO(req.ctx.body.cnaContainer, CONSTANTS.DATE_FIELDS) const dateUpdated = (new Date()).toISOString() cveRecord.cveMetadata.dateUpdated = dateUpdated @@ -659,7 +659,7 @@ async function rejectCVE (req, res, next) { const providerMetadata = createProviderMetadata(providerOrgObj.UUID, req.ctx.org, (new Date()).toISOString()) const rejectedCve = Cve.newRejectedCve(cveIdObj, req.ctx.body, owningCnaShortName, providerMetadata) - const newCveObj = new Cve({ cve: rejectedCve }) + const newCveObj = new Cve({ cve: convertDatesToISO(rejectedCve, CONSTANTS.DATE_FIELDS) }) result = Cve.validateCveRecord(newCveObj.cve) if (!result.isValid) { @@ -732,7 +732,7 @@ async function rejectExistingCve (req, res, next) { // update CVE record to rejected const updatedRecord = Cve.updateCveToRejected(id, providerMetadata, result.cve, req.ctx.body) - const updatedCve = new Cve({ cve: updatedRecord }) + const updatedCve = new Cve({ cve: convertDatesToISO(updatedRecord, CONSTANTS.DATE_FIELDS) }) result = Cve.validateCveRecord(updatedCve.cve) if (!result.isValid) { @@ -842,7 +842,7 @@ async function insertAdp (req, res, next) { cveRecord.containers.adp.push(adpContainer) } - const cveModel = new Cve({ cve: cveRecord }) + const cveModel = new Cve({ cve: convertDatesToISO(cveRecord, CONSTANTS.DATE_FIELDS) }) result = Cve.validateCveRecord(cveModel.cve) if (!result.isValid) { logger.error(JSON.stringify({ uuid: req.ctx.uuid, message: 'CVE JSON schema validation FAILED.' })) From 6901b17d72942befc6429885e9445d3262f7a9b9 Mon Sep 17 00:00:00 2001 From: david-rocca Date: Fri, 20 Dec 2024 11:28:25 -0500 Subject: [PATCH 3/3] Fix the actual conflict --- src/controller/cve.controller/cve.controller.js | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/controller/cve.controller/cve.controller.js b/src/controller/cve.controller/cve.controller.js index 3a374d534..dd280e346 100644 --- a/src/controller/cve.controller/cve.controller.js +++ b/src/controller/cve.controller/cve.controller.js @@ -488,7 +488,7 @@ async function submitCna (req, res, next) { return res.status(403).json(error.cveRecordExists()) } - const cnaContainer = req.ctx.body.cnaContainer + const cnaContainer = convertDatesToISO(req.ctx.body.cnaContainer, CONSTANTS.DATE_FIELDS) if (erlCheck && !isEnrichedContainer(cnaContainer)) { // Process the ERL check here return res.status(403).json(error.erlCheckFailed()) @@ -497,7 +497,6 @@ async function submitCna (req, res, next) { // create full cve record here const owningCna = await orgRepo.findOneByUUID(cveId.owning_cna) const assignerShortName = owningCna.short_name - const cnaContainer = convertDatesToISO(req.ctx.body.cnaContainer, CONSTANTS.DATE_FIELDS) const dateUpdated = (new Date()).toISOString() const additionalCveMetadataFields = { assignerShortName: assignerShortName, @@ -585,7 +584,7 @@ async function updateCna (req, res, next) { return res.status(403).json(error.cveRecordDne()) } - const cnaContainer = req.ctx.body.cnaContainer + const cnaContainer = convertDatesToISO(req.ctx.body.cnaContainer, CONSTANTS.DATE_FIELDS) if (erlCheck && !isEnrichedContainer(cnaContainer)) { // Process the ERL check here return res.status(403).json(error.erlCheckFailed()) @@ -593,7 +592,6 @@ async function updateCna (req, res, next) { // update cve record here const cveRecord = result.cve - const cnaContainer = convertDatesToISO(req.ctx.body.cnaContainer, CONSTANTS.DATE_FIELDS) const dateUpdated = (new Date()).toISOString() cveRecord.cveMetadata.dateUpdated = dateUpdated