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

Updating Prod-Staging with v2.2.1 #1188

Merged
merged 9 commits into from
Feb 21, 2024
2 changes: 1 addition & 1 deletion api-docs/openapi.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"openapi": "3.0.2",
"info": {
"version": "2.2.0",
"version": "2.2.1",
"title": "CVE Services API",
"description": "The CVE Services API supports automation tooling for the CVE Program. Credentials are required for most service endpoints. Representatives of <a href='https://www.cve.org/ProgramOrganization/CNAs'>CVE Numbering Authorities (CNAs)</a> should use one of the methods below to obtain credentials: <ul><li>If your organization already has an Organizational Administrator (OA) account for the CVE Services, ask your admin for credentials</li> <li>Contact your Root (<a href='https://www.cve.org/PartnerInformation/ListofPartners/partner/Google'>Google</a>, <a href='https://www.cve.org/PartnerInformation/ListofPartners/partner/INCIBE'>INCIBE</a>, <a href='https://www.cve.org/PartnerInformation/ListofPartners/partner/jpcert'>JPCERT/CC</a>, or <a href='https://www.cve.org/PartnerInformation/ListofPartners/partner/redhat'>Red Hat</a>) or Top-Level Root (<a href='https://www.cve.org/PartnerInformation/ListofPartners/partner/icscert'>CISA ICS</a> or <a href='https://www.cve.org/PartnerInformation/ListofPartners/partner/mitre'>MITRE</a>) to request credentials </ul> <p>CVE data is to be in the JSON 5.0 CVE Record format. Details of the JSON 5.0 schema are located <a href='https://github.com/CVEProject/cve-schema/tree/master/schema/v5.0' target='_blank'>here</a>.</p> <a href='https://cveform.mitre.org/' class='link' target='_blank'>Contact the CVE Services team</a>",
"contact": {
Expand Down
6 changes: 3 additions & 3 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "cve-services",
"author": "Automation Working Group",
"version": "2.2.0",
"version": "2.2.1",
"license": "(CC0)",
"devDependencies": {
"@faker-js/faker": "^7.6.0",
Expand Down Expand Up @@ -100,4 +100,4 @@
"test:coverage-html": "NODE_ENV=test nyc --reporter=html mocha src/* --recursive --exit || true",
"test:scripts": "NODE_ENV=development node-dev src/scripts/templateScript.js"
}
}
}
29 changes: 28 additions & 1 deletion src/controller/cve-id.controller/cve-id.controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,11 +42,14 @@ async function getFilteredCveId (req, res, next) {
const users = await userRepo.getAllUsers()

const orgMap = {}
const userMap = {}

orgs.forEach(org => {
orgMap[org.UUID] = { shortname: org.short_name, users: {} }
})

users.forEach(user => {
userMap[user.UUID] = user.username
if (!orgMap[user.org_UUID]) {
orgMap[user.org_UUID] = { shortname: `MISSING ORG ${user.org_UUID}`, users: {} }
}
Expand Down Expand Up @@ -122,7 +125,31 @@ async function getFilteredCveId (req, res, next) {
cve_ids: pg.itemsList.map((i) => {
const cnaid = i.requested_by.cna
i.requested_by.cna = orgMap[cnaid].shortname
i.requested_by.user = orgMap[cnaid].users[i.requested_by.user]

// User value is redacted in certain cases
// Checks if requested_by.user is in requested_by.cna org
if (!orgMap[cnaid].users[i.requested_by.user]) {
// Never redact for secretariat users
if (isSecretariat) {
i.requested_by.user = userMap[i.requested_by.user]
} else {
// Redact because requested_by.user is not in requested_by.cna org
i.requested_by.user = 'REDACTED'
}
// Check is current owning_cna is also requested_by.cna (if a CVE-ID changes orgs)
} else if (cnaid !== i.owning_cna) {
// Never redact for secretariat
if (isSecretariat) {
i.requested_by.user = userMap[i.requested_by.user]
} else {
// Redact because current owner is not requested_by.cna and shouldn't see requested_by.user
i.requested_by.user = 'REDACTED'
}
} else {
// No redaction, original requested_by.user is in requested_by.cna and owning_cna
i.requested_by.user = orgMap[cnaid].users[i.requested_by.user]
}

i.owning_cna = orgMap[i.owning_cna].shortname
return i
})
Expand Down
2 changes: 1 addition & 1 deletion src/swagger.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ const rejectedCreateCVERecord = require('../schemas/cve/rejected-create-cve-exam
/* eslint-disable no-multi-str */
const doc = {
info: {
version: '2.2.0',
version: '2.2.1',
title: 'CVE Services API',
description: "The CVE Services API supports automation tooling for the CVE Program. Credentials are \
required for most service endpoints. Representatives of \
Expand Down
14 changes: 14 additions & 0 deletions test/integration-tests/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,18 @@ const nonSecretariatUserHeaders = {
'CVE-API-USER': 'jasminesmith@win_5.com'
}

const nonSecretariatUserHeaders2 = {
'CVE-API-ORG': 'win_5',
'CVE-API-Key': 'TCF25YM-39C4H6D-KA32EGF-V5XSHN3',
'CVE-API-USER': 'win_5_admin@win_5.com'
}

const nonSecretariatUserHeaders3 = {
'CVE-API-ORG': 'evidence_15',
'CVE-API-Key': 'TCF25YM-39C4H6D-KA32EGF-V5XSHN3',
'CVE-API-USER': 'timothymyers@evidence_15.com'
}

const nonSecretariatUserHeadersWithAdp2 = {
'CVE-API-ORG': 'range_4',
'CVE-API-Key': 'TCF25YM-39C4H6D-KA32EGF-V5XSHN3',
Expand Down Expand Up @@ -272,6 +284,8 @@ const existingOrg = {
module.exports = {
headers,
nonSecretariatUserHeaders,
nonSecretariatUserHeaders2,
nonSecretariatUserHeaders3,
badNonSecretariatUserHeaders,
nonSecretariatUserHeadersWithAdp2,
testCve,
Expand Down
79 changes: 79 additions & 0 deletions test/integration-tests/cve-id/getCveIdTest.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ const _ = require('lodash')
const expect = chai.expect

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

describe('Testing Get CVE-ID endpoint', () => {
Expand Down Expand Up @@ -109,6 +110,84 @@ describe('Testing Get CVE-ID endpoint', () => {
expect(res).to.have.status(200)
})
})
it('For non Secretariat users, should redact requested_by.user values not in requested_by.cna org', async () => {
const cveId = await helpers.cveIdReserveHelper(1, '2023', constants.nonSecretariatUserHeaders['CVE-API-ORG'], 'non-sequential')

// change users org for testing
await helpers.userOrgUpdateAsSecHelper(constants.nonSecretariatUserHeaders['CVE-API-USER'], constants.nonSecretariatUserHeaders['CVE-API-ORG'], 'mitre')

await chai.request(app)
.get('/api/cve-id?state=RESERVED')
.set(constants.nonSecretariatUserHeaders2)
.then(async (res, err) => {
const cveIdObject = _.find(res.body.cve_ids, obj => {
return obj.cve_id === cveId
})
expect(err).to.be.undefined
expect(res).to.have.status(200)
expect(cveIdObject.requested_by.user).to.equal('REDACTED')

// Reset user to original org
await helpers.userOrgUpdateAsSecHelper(constants.nonSecretariatUserHeaders['CVE-API-USER'], 'mitre', 'win_5')
})
})
it('For non Secretariat users, should redact requested_by.user values when requested_by.cna is not owning_cna', async () => {
const cveId = await helpers.cveIdReserveHelper(1, '2023', constants.nonSecretariatUserHeaders['CVE-API-ORG'], 'non-sequential')

// change cve-id's owning_org for testing
await helpers.updateOwningOrgAsSecHelper(cveId, constants.nonSecretariatUserHeaders3['CVE-API-ORG'])

await chai.request(app)
.get('/api/cve-id?state=RESERVED')
.set(constants.nonSecretariatUserHeaders3)
.then(async (res, err) => {
const cveIdObject = _.find(res.body.cve_ids, obj => {
return obj.cve_id === cveId
})
expect(err).to.be.undefined
expect(res).to.have.status(200)
expect(cveIdObject.requested_by.user).to.equal('REDACTED')
})
})
it('For Secretariat users, should redact requested_by.user values not in requested_by.cna org', async () => {
const cveId = await helpers.cveIdReserveHelper(1, '2023', constants.nonSecretariatUserHeaders['CVE-API-ORG'], 'non-sequential')

// change users org for testing
await helpers.userOrgUpdateAsSecHelper(constants.nonSecretariatUserHeaders['CVE-API-USER'], constants.nonSecretariatUserHeaders['CVE-API-ORG'], 'mitre')

await chai.request(app)
.get('/api/cve-id?state=RESERVED')
.set(constants.headers)
.then(async (res, err) => {
const cveIdObject = _.find(res.body.cve_ids, obj => {
return obj.cve_id === cveId
})
expect(err).to.be.undefined
expect(res).to.have.status(200)
expect(cveIdObject.requested_by.user).to.equal(constants.nonSecretariatUserHeaders['CVE-API-USER'])

// Reset user to original org
await helpers.userOrgUpdateAsSecHelper(constants.nonSecretariatUserHeaders['CVE-API-USER'], 'mitre', 'win_5')
})
})
it('For Secretariat users, should redact requested_by.user values when requested_by.cna is not owning_cna', async () => {
const cveId = await helpers.cveIdReserveHelper(1, '2023', constants.nonSecretariatUserHeaders['CVE-API-ORG'], 'non-sequential')

// change cve-id's owning_org for testing
await helpers.updateOwningOrgAsSecHelper(cveId, constants.nonSecretariatUserHeaders3['CVE-API-ORG'])

await chai.request(app)
.get('/api/cve-id?state=RESERVED')
.set(constants.headers)
.then(async (res, err) => {
const cveIdObject = _.find(res.body.cve_ids, obj => {
return obj.cve_id === cveId
})
expect(err).to.be.undefined
expect(res).to.have.status(200)
expect(cveIdObject.requested_by.user).to.equal(constants.nonSecretariatUserHeaders['CVE-API-USER'])
})
})
})
context('negative tests', () => {
it('Feb 29 2100 should not be valid', async () => {
Expand Down
24 changes: 23 additions & 1 deletion test/integration-tests/helpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,26 @@ async function cveUpdateAsCnaHelperWithAdpContainer (cveId, adpContainer) {
})
}

async function userOrgUpdateAsSecHelper (userName, orgShortName, newOrgShortName) {
await chai.request(app)
.put(`/api/org/${orgShortName}/user/${userName}?org_short_name=${newOrgShortName}`)
.set(constants.headers)
.then((res, err) => {
// Safety Expect
expect(res).to.have.status(200)
})
}

async function updateOwningOrgAsSecHelper (cveId, newOrgShortName) {
await chai.request(app)
.put(`/api/cve-id/${cveId}?org=${newOrgShortName}`)
.set(constants.headers)
.then((res, err) => {
// Safety Expect
expect(res).to.have.status(200)
})
}

module.exports = {
cveIdReserveHelper,
cveIdBulkReserveHelper,
Expand All @@ -104,5 +124,7 @@ module.exports = {
cveRequestAsSecHelper,
cveUpdatetAsCnaHelperWithCnaContainer,
cveUpdateAsSecHelper,
cveUpdateAsCnaHelperWithAdpContainer
cveUpdateAsCnaHelperWithAdpContainer,
userOrgUpdateAsSecHelper,
updateOwningOrgAsSecHelper
}
Loading