From fd57ce416d369aa070a2e27b278a0316a1526778 Mon Sep 17 00:00:00 2001 From: Marley Stipich <87209745+marleystipich2@users.noreply.github.com> Date: Tue, 5 Nov 2024 10:58:09 -0500 Subject: [PATCH] RHINENG-4902: Migrate Request to Axios --- src/connectors/Connector.js | 11 +- src/connectors/Connector.unit.js | 11 +- src/connectors/advisor/impl.js | 22 +- src/connectors/advisor/impl.unit.js | 23 +- src/connectors/advisor/mock.js | 8 +- src/connectors/bop/impl.js | 23 +- src/connectors/bop/impl.unit.js | 56 +- src/connectors/bop/mock.js | 4 +- src/connectors/compliance/impl.js | 13 +- src/connectors/compliance/impl.unit.js | 23 +- src/connectors/compliance/mock.js | 6 +- src/connectors/configManager/impl.js | 10 +- src/connectors/configManager/impl.unit.js | 15 +- src/connectors/contentServer/impl.js | 10 +- src/connectors/contentServer/impl.unit.js | 19 +- src/connectors/contentServer/mock.js | 6 +- src/connectors/dispatcher/impl.js | 55 +- src/connectors/dispatcher/impl.unit.js | 61 +- src/connectors/dispatcher/mock.js | 8 +- src/connectors/dispatcher/noop.js | 6 +- src/connectors/http.js | 10 +- src/connectors/http.unit.js | 27 +- src/connectors/inventory/impl.js | 52 +- src/connectors/inventory/impl.unit.js | 55 +- src/connectors/inventory/mock.js | 4 +- src/connectors/inventory/xjoin.js | 36 +- src/connectors/inventory/xjoin.queries.js | 4 +- src/connectors/inventory/xjoin.unit.js | 38 +- src/connectors/patchman/impl.js | 10 +- src/connectors/patchman/impl.unit.js | 15 +- src/connectors/patchman/mock.js | 6 +- src/connectors/rbac/impl.js | 12 +- src/connectors/rbac/impl.unit.js | 21 +- src/connectors/receptor/impl.js | 16 +- src/connectors/receptor/impl.unit.js | 27 +- src/connectors/sources/impl.js | 33 +- src/connectors/sources/impl.unit.js | 23 +- src/connectors/sources/mock.js | 8 +- src/connectors/ssg/compliance.js | 16 +- src/connectors/ssg/compliance.unit.js | 15 +- src/connectors/ssg/impl.js | 11 +- src/connectors/ssg/impl.unit.js | 11 +- src/connectors/ssg/mock.js | 4 +- src/connectors/testUtils.js | 35 +- src/connectors/users/impl.js | 14 +- src/connectors/users/impl.unit.js | 25 +- src/connectors/users/mock.js | 2 +- src/connectors/vmaas/mock.js | 4 +- src/connectors/vmaas/vmaas.integration.js | 11 +- src/connectors/vmaas/vmaas.js | 23 +- src/connectors/vmaas/vmaas.unit.js | 17 +- src/connectors/vulnerabilities/impl.js | 11 +- src/connectors/vulnerabilities/impl.unit.js | 17 +- src/connectors/vulnerabilities/mock.js | 2 +- src/diagnosis/diagnosis.controller.js | 4 +- src/errors.js | 72 +- src/generator/factories/AdvisorFactory.js | 10 +- src/generator/factories/CSAWFactory.js | 10 +- src/generator/factories/CVEFactory.js | 12 +- src/generator/factories/ComplianceFactory.js | 11 +- src/generator/factories/Factory.js | 4 +- src/generator/factories/TestFactory.js | 8 +- src/generator/generator.controller.js | 18 +- src/issues/AdvisorHandler.js | 12 +- src/issues/CSAWHandler.js | 20 +- src/issues/CVEHandler.js | 16 +- src/issues/ErratumHandler.js | 4 +- src/issues/PackageHandler.js | 4 +- src/issues/PatchmanHandler.js | 4 +- src/issues/SSGHandler.js | 10 +- src/issues/TestHandler.js | 8 +- src/issues/index.js | 18 +- src/middleware/identity/impl.js | 6 +- src/middleware/identity/userIdentity.js | 6 +- .../openapi/RequestSpecValidationError.js | 2 +- src/middleware/rbac.js | 3 +- .../__snapshots__/fifi.integration.js.snap | 622 +++++++++--------- src/remediations/controller.fifi.js | 22 +- src/remediations/controller.fifi_2.js | 13 +- src/remediations/controller.read.js | 56 +- src/remediations/controller.status.js | 10 +- src/remediations/controller.write.js | 28 +- src/remediations/fifi.integration.js | 57 +- src/remediations/fifi.js | 47 +- src/remediations/fifi_2.js | 16 +- src/remediations/write.integration.js | 4 +- src/resolutions/disambiguator.js | 6 +- src/resolutions/resolutions.controller.js | 12 +- src/resolutions/resolvers/CSAWResolver.js | 8 +- src/resolutions/resolvers/CVEResolver.js | 8 +- .../resolvers/ContentServerResolver.js | 5 +- src/resolutions/resolvers/ErratumResolver.js | 4 +- src/resolutions/resolvers/PackageResolver.js | 3 +- src/resolutions/resolvers/PatchmanResolver.js | 4 +- src/resolutions/resolvers/Resolver.js | 6 +- src/resolutions/resolvers/SSGResolver.js | 10 +- src/resolutions/resolvers/SSGResolver.unit.js | 35 +- src/resolutions/resolvers/TestResolver.js | 2 +- src/routes.js | 2 +- src/status/status.controller.js | 6 +- src/util/cls.js | 6 +- src/util/identifiers.js | 22 +- src/util/identifiers.unit.js | 25 +- src/util/log.js | 10 +- src/util/request.unit.js | 9 + src/util/trace.js | 16 +- 106 files changed, 1295 insertions(+), 1046 deletions(-) diff --git a/src/connectors/Connector.js b/src/connectors/Connector.js index 97b876ac..ea6ba7cb 100644 --- a/src/connectors/Connector.js +++ b/src/connectors/Connector.js @@ -36,20 +36,19 @@ module.exports = class Connector { return uri; } - async doHttp (options, caching, metrics = false, responseTransformer) { + async doHttp (req, options, caching, metrics = false, responseTransformer) { try { - const result = await http.request(options, caching, metrics, responseTransformer); + const result = await http.request(req, options, caching, metrics, responseTransformer); return result; } catch (e) { log.trace(e, 'dependency error'); metrics && metrics.error.inc(); - throw errors.internal.dependencyError(e, this); + throw errors.internal.dependencyError(req, e, this); } } - getForwardedHeaders (identity = true) { - const req = cls.getReq(); - assert(req, 'request not available in CLS'); + getForwardedHeaders (req, identity = true) { + // const req1 = cls.getReq(); const toPick = [REQ_ID_HEADER]; if (identity) { toPick.push(IDENTITY_HEADER); diff --git a/src/connectors/Connector.unit.js b/src/connectors/Connector.unit.js index 7c617271..afd635b9 100644 --- a/src/connectors/Connector.unit.js +++ b/src/connectors/Connector.unit.js @@ -7,11 +7,20 @@ const StatusCodeError = require('./StatusCodeError'); const errors = require('../errors'); const { mockRequest } = require('./testUtils'); +const REQ = { + headers: { + 'x-rh-identity': 'identity', + 'x-rh-insights-request-id': 'request-id' + }, + identity: { type: 'test' }, + user: { username: 'test', account_number: 'test' } +}; + describe('Connector', function () { test('wraps errors', async function () { mockRequest(); base.getSandbox().stub(http, 'request').rejects(new StatusCodeError(500)); - await expect(vmaas.getCve('id')).rejects.toThrow(errors.DependencyError); + await expect(vmaas.getCve(REQ, 'id')).rejects.toThrow(errors.DependencyError); }); }); diff --git a/src/connectors/advisor/impl.js b/src/connectors/advisor/impl.js index a52170c6..03528742 100644 --- a/src/connectors/advisor/impl.js +++ b/src/connectors/advisor/impl.js @@ -25,18 +25,18 @@ module.exports = new class extends Connector { return this.buildUri(host, 'advisor', 'v1'); } - getRule (id, refresh = false) { + getRule (req, id, refresh = false) { const uri = this.buildBaseUri(host, 'advisor', 'v1'); uri.segment('rule'); uri.segment(id); - return this.doHttp({ + return this.doHttp(req, { uri: uri.toString(), method: 'GET', json: true, rejectUnauthorized: !insecure, headers: { - ...this.getForwardedHeaders() + ...this.getForwardedHeaders(req) } }, { refresh, @@ -45,7 +45,7 @@ module.exports = new class extends Connector { this.ruleMetrics); } - async getDiagnosis (system, branchId = null) { + async getDiagnosis (req, system, branchId = null) { const uri = this.buildBaseUri(); uri.segment('system'); uri.segment(system); @@ -56,13 +56,13 @@ module.exports = new class extends Connector { uri.query({branch_id: branchId}); } - const data = await this.doHttp({ + const data = await this.doHttp(req, { uri: uri.toString(), method: 'GET', json: true, rejectUnauthorized: !insecure, headers: { - ...this.getForwardedHeaders() + ...this.getForwardedHeaders(req) } }, false, this.diagnosisMetrics); @@ -87,18 +87,18 @@ module.exports = new class extends Connector { .value(); } - async getSystems (id) { + async getSystems (id, req) { const uri = this.buildBaseUri(host, 'advisor', 'v1'); uri.segment('rule'); uri.segment(id); uri.segment('systems'); - const data = await this.doHttp({ + const data = await this.doHttp(req, { uri: uri.toString(), method: 'GET', json: true, rejectUnauthorized: !insecure, - headers: this.getForwardedHeaders() + headers: this.getForwardedHeaders(req) }, false, this.systemsMetrics); @@ -110,8 +110,8 @@ module.exports = new class extends Connector { return data.host_ids; } - async ping () { - const result = await this.getRule('network_bond_opts_config_issue|NETWORK_BONDING_OPTS_DOUBLE_QUOTES_ISSUE', true); + async ping (req) { + const result = await this.getRule(req, 'network_bond_opts_config_issue|NETWORK_BONDING_OPTS_DOUBLE_QUOTES_ISSUE', true); assert(result !== null); } }(); diff --git a/src/connectors/advisor/impl.unit.js b/src/connectors/advisor/impl.unit.js index f7e4f554..e188d45f 100644 --- a/src/connectors/advisor/impl.unit.js +++ b/src/connectors/advisor/impl.unit.js @@ -8,6 +8,15 @@ const { mockRequest, mockCache } = require('../testUtils'); const request = require('../../util/request'); const errors = require('../../errors'); +const REQ = { + headers: { + 'x-rh-identity': 'identity', + 'x-rh-insights-request-id': 'request-id' + }, + identity: { type: 'test' }, + user: { username: 'test', account_number: 'test' } +}; + /* eslint-disable max-len */ describe('advisor impl', function () { @@ -68,7 +77,7 @@ describe('advisor impl', function () { headers: {} }); - const result = await impl.getRule('network_bond_opts_config_issue|NETWORK_BONDING_OPTS_DOUBLE_QUOTES_ISSUE'); + const result = await impl.getRule(REQ, 'network_bond_opts_config_issue|NETWORK_BONDING_OPTS_DOUBLE_QUOTES_ISSUE'); result.should.have.property('summary', 'Bonding will not fail over to the backup link when bonding options are partially read.\n'); http.callCount.should.equal(1); @@ -79,7 +88,7 @@ describe('advisor impl', function () { cache.get.callCount.should.equal(1); cache.setex.callCount.should.equal(1); - await impl.getRule('network_bond_opts_config_issue|NETWORK_BONDING_OPTS_DOUBLE_QUOTES_ISSUE'); + await impl.getRule(REQ, 'network_bond_opts_config_issue|NETWORK_BONDING_OPTS_DOUBLE_QUOTES_ISSUE'); cache.get.callCount.should.equal(2); cache.setex.callCount.should.equal(1); }); @@ -95,7 +104,7 @@ describe('advisor impl', function () { headers: {} }); - await expect(impl.getRule('unknown-rule')).resolves.toBeNull(); + await expect(impl.getRule(REQ, 'unknown-rule')).resolves.toBeNull(); http.callCount.should.equal(1); cache.get.callCount.should.equal(1); @@ -104,7 +113,7 @@ describe('advisor impl', function () { test('status code handling', async function () { base.mockRequestStatusCode(); - await expect(impl.getRule('network_bond_opts_config_issue|NETWORK_BONDING_OPTS_DOUBLE_QUOTES_ISSUE')).rejects.toThrow(errors.DependencyError); + await expect(impl.getRule(REQ, 'network_bond_opts_config_issue|NETWORK_BONDING_OPTS_DOUBLE_QUOTES_ISSUE')).rejects.toThrow(errors.DependencyError); }); }); @@ -112,7 +121,7 @@ describe('advisor impl', function () { test('parses diagnosis reports', async function () { const spy = base.getSandbox().stub(Connector.prototype, 'doHttp').resolves(data.diagnosis1); - const diagnosis = await impl.getDiagnosis('id', 'branchId'); + const diagnosis = await impl.getDiagnosis(REQ, 'id', 'branchId'); spy.callCount.should.equal(1); diagnosis.should.eql({ @@ -155,7 +164,7 @@ describe('advisor impl', function () { headers: {} }); - await expect(impl.getSystems('rule')).resolves.toEqual([ + await expect(impl.getSystems('rule', REQ)).resolves.toEqual([ '7de3c608-8553-4625-90c7-d27f1d29327f', '0d962e11-ff3c-4db1-b06c-c4674d90069b' ]); @@ -173,7 +182,7 @@ describe('advisor impl', function () { headers: {} }); - await expect(impl.getSystems('unknown-rule')).resolves.toEqual([]); + await expect(impl.getSystems('unknown-rule', REQ)).resolves.toEqual([]); http.callCount.should.equal(1); cache.get.callCount.should.equal(0); diff --git a/src/connectors/advisor/mock.js b/src/connectors/advisor/mock.js index ef861a95..f38d24d1 100644 --- a/src/connectors/advisor/mock.js +++ b/src/connectors/advisor/mock.js @@ -58,7 +58,7 @@ module.exports = new class extends Connector { super(module); } - async getRule (id) { + async getRule (req, id) { if (_.has(DATA, id)) { // eslint-disable-next-line security/detect-object-injection return DATA[id]; @@ -67,7 +67,7 @@ module.exports = new class extends Connector { return null; } - async getDiagnosis (system, branchId) { + async getDiagnosis (req, system, branchId) { if (system === 'none') { return {}; } @@ -86,7 +86,7 @@ module.exports = new class extends Connector { ]; } - ping () { - return this.getRule('network_bond_opts_config_issue|NETWORK_BONDING_OPTS_DOUBLE_QUOTES_ISSUE'); + ping (req) { + return this.getRule(req, 'network_bond_opts_config_issue|NETWORK_BONDING_OPTS_DOUBLE_QUOTES_ISSUE'); } }(); diff --git a/src/connectors/bop/impl.js b/src/connectors/bop/impl.js index 0bca3540..ff762077 100644 --- a/src/connectors/bop/impl.js +++ b/src/connectors/bop/impl.js @@ -19,7 +19,8 @@ module.exports = new class extends Connector { // Given an array of account numbers, fetch corresponding tenant org_ids from // backoffice proxy - async getTenantOrgIds (accounts) { + // Might have to look at migrations.. this function is used there without request being passed + async getTenantOrgIds (req, accounts) { log.info(`Fetching tenant_org_ids for accounts: ${accounts}`); const EBS_accounts = [].concat(accounts).map(String); @@ -43,13 +44,14 @@ module.exports = new class extends Connector { // TODO: I'm not even sure we need to bother forwarding headers for this internal service... // if this function was called outside the context of a user request (e.g. from a db migration) // then skip the forwarded headers. - if (cls.getReq()) { - options.headers = this.getForwardedHeaders(false); + // if (cls.getReq()) { + if (req) { + options.headers = this.getForwardedHeaders(req, false); } try { log.debug(`Request options: ${JSON.stringify(options)}`); - const result = await this.doHttp (options, false, this.orgIdMetrics); + const result = await this.doHttp (req, options, false, this.orgIdMetrics); log.debug(`POST response: ${JSON.stringify(result)}`); if (_.isEmpty(result)) { @@ -65,7 +67,7 @@ module.exports = new class extends Connector { // Given an array of tenant org_ids, fetch corresponding EBS account numbers // from backoffice proxy - async getEBSAccounts (org_ids) { + async getEBSAccounts (req, org_ids) { log.info(`Fetching EBS Accounts for: ${org_ids}`); const tenant_org_ids = [].concat(org_ids).map(String); @@ -83,13 +85,13 @@ module.exports = new class extends Connector { method: 'POST', json: true, rejectUnauthorized: !insecure, - headers: this.getForwardedHeaders(false), + headers: this.getForwardedHeaders(req, false), body: tenant_org_ids }; try { log.debug(`Request options: ${JSON.stringify(options)}`); - const result = await this.doHttp (options, false, this.EBSAccountMetrics); + const result = await this.doHttp (req, options, false, this.EBSAccountMetrics); log.debug(`POST response: ${JSON.stringify(result)}`); if (_.isEmpty(result)) { @@ -104,9 +106,10 @@ module.exports = new class extends Connector { } // Verify connection to backoffice proxy tenant org_id / EBS account number translation service - async ping () { - const req = cls.getReq(); - const result = await this.getEBSAccounts([`${req.identity.internal.org_id}`]); + // Pass req to ping here too + async ping (req) { + // const req = cls.getReq(); + const result = await this.getEBSAccounts(req, [`${req.identity.internal.org_id}`]); assert(result !== null); } }(); diff --git a/src/connectors/bop/impl.unit.js b/src/connectors/bop/impl.unit.js index 227af71a..e5a7fad5 100644 --- a/src/connectors/bop/impl.unit.js +++ b/src/connectors/bop/impl.unit.js @@ -10,6 +10,14 @@ const { mockRequest, mockCache } = require('../testUtils'); const request = require('../../util/request'); const RequestError = require('request-promise-core/errors').RequestError; +const REQ = { + headers: { + 'x-rh-identity': 'identity', + 'x-rh-insights-request-id': 'request-id' + }, + identity: { type: 'test' }, + user: { username: 'test', account_number: 'test' } +}; describe('inventory impl', () => { beforeEach(mockRequest); @@ -20,20 +28,20 @@ describe('inventory impl', () => { const stub = base.getSandbox().stub(http, 'request'); stub.returns({"1979710": "540155"}); - const result = await impl.getEBSAccounts(1979710); + const result = await impl.getEBSAccounts(REQ, 1979710); - stub.getCall(0).args[0].body.should.be.array; - stub.getCall(0).args[0].body[0].should.be.String; + stub.getCall(0).args[1].body.should.be.array; + stub.getCall(0).args[1].body[0].should.be.String; }); test('Array of org_ids', async () => { const stub = base.getSandbox().stub(http, 'request'); stub.returns({"1979710": "540155", "38393949": "3098430"}); - const result = await impl.getEBSAccounts([1979710, 38393949]); + const result = await impl.getEBSAccounts(REQ, [1979710, 38393949]); - stub.getCall(0).args[0].body.should.be.array; - for (const account of stub.getCall(0).args[0].body) { + stub.getCall(0).args[1].body.should.be.array; + for (const account of stub.getCall(0).args[1].body) { account.should.be.String; } }); @@ -46,10 +54,10 @@ describe('inventory impl', () => { "38393949": "3098430" }); - const result = await impl.getEBSAccounts([1979710, "38393949", 29393933]); + const result = await impl.getEBSAccounts(REQ, [1979710, "38393949", 29393933]); - stub.getCall(0).args[0].body.should.be.array; - for (const account of stub.getCall(0).args[0].body) { + stub.getCall(0).args[1].body.should.be.array; + for (const account of stub.getCall(0).args[1].body) { account.should.be.String; } }); @@ -58,15 +66,15 @@ describe('inventory impl', () => { const stub = base.getSandbox().stub(http, 'request'); stub.returns({}); - const result = await impl.getEBSAccounts(1979710); + const result = await impl.getEBSAccounts(REQ, 1979710); - stub.getCall(0).args[0].body.should.be.array; - stub.getCall(0).args[0].body[0].should.be.String; + stub.getCall(0).args[1].body.should.be.array; + stub.getCall(0).args[1].body[0].should.be.String; }); test('does not make a call for empty list', async () => { const spy = base.getSandbox().spy(http, 'request'); - const result = await impl.getEBSAccounts([]); + const result = await impl.getEBSAccounts(REQ, []); result.should.be.empty(); spy.called.should.be.false(); @@ -79,20 +87,20 @@ describe('inventory impl', () => { const stub = base.getSandbox().stub(http, 'request'); stub.returns({"540155": "1979710"}); - const result = await impl.getTenantOrgIds(540155); + const result = await impl.getTenantOrgIds(REQ, 540155); - stub.getCall(0).args[0].body.should.be.array; - stub.getCall(0).args[0].body[0].should.be.String; + stub.getCall(0).args[1].body.should.be.array; + stub.getCall(0).args[1].body[0].should.be.String; }); test('Array of EBS account numbers', async () => { const stub = base.getSandbox().stub(http, 'request'); stub.returns({"540155": "1979710", "3098430": "38393949"}); - const result = await impl.getTenantOrgIds([540155, 3098430]); + const result = await impl.getTenantOrgIds(REQ, [540155, 3098430]); - stub.getCall(0).args[0].body.should.be.array; - for (const account of stub.getCall(0).args[0].body) { + stub.getCall(0).args[1].body.should.be.array; + for (const account of stub.getCall(0).args[1].body) { account.should.be.String; } }); @@ -105,20 +113,20 @@ describe('inventory impl', () => { "3098430": "38393949" }); - const result = await impl.getTenantOrgIds([540155, "3098430", 2828282]); + const result = await impl.getTenantOrgIds(REQ, [540155, "3098430", 2828282]); - stub.getCall(0).args[0].body.should.be.array; - for (const account of stub.getCall(0).args[0].body) { + stub.getCall(0).args[1].body.should.be.array; + for (const account of stub.getCall(0).args[1].body) { account.should.be.String; } }); test('does not make a call for empty list', async () => { const spy = base.getSandbox().spy(http, 'request'); - const result = await impl.getTenantOrgIds([]); + const result = await impl.getTenantOrgIds(REQ, []); result.should.be.empty(); spy.called.should.be.false(); }); }); -}); \ No newline at end of file +}); diff --git a/src/connectors/bop/mock.js b/src/connectors/bop/mock.js index 1c92fd99..6a3212b2 100644 --- a/src/connectors/bop/mock.js +++ b/src/connectors/bop/mock.js @@ -32,11 +32,11 @@ module.exports = new class extends Connector { return ORG_IDS_2; } - async getEBSAccounts() { + async getEBSAccounts(req) { return EBS_ACCOUNTS; } async ping () { await this.getTenantOrgIds(); } -}(); \ No newline at end of file +}(); diff --git a/src/connectors/compliance/impl.js b/src/connectors/compliance/impl.js index ad18361c..14e88b7c 100644 --- a/src/connectors/compliance/impl.js +++ b/src/connectors/compliance/impl.js @@ -14,19 +14,19 @@ module.exports = new class extends Connector { this.metrics = metrics.createConnectorMetric(this.getName()); } - async getRule (id, refresh = false, retries = 2) { + async getRule (req, id, refresh = false, retries = 2) { id = id.replace(/\./g, '-'); // compliance API limitation const uri = this.buildUri(host, 'compliance', 'rules', id); try { - const result = await this.doHttp({ + const result = await this.doHttp(req, { uri: uri.toString(), method: 'GET', json: true, rejectUnauthorized: !insecure, headers: { - ...this.getForwardedHeaders() + ...this.getForwardedHeaders(req) } }, { @@ -40,15 +40,16 @@ module.exports = new class extends Connector { } catch (e) { if (retries > 0) { log.warn({ error: e, id, retries }, 'Compliance fetch failed. Retrying'); - return this.getRule(id, true, retries - 1); + return this.getRule(req, id, true, retries - 1); } throw e; } } - async ping () { - const result = await this.getRule('xccdf_org.ssgproject.content_rule_sshd_disable_root_login', true); +// Pass req to ping here too + async ping (req) { + const result = await this.getRule(req, 'xccdf_org.ssgproject.content_rule_sshd_disable_root_login', true); assert(result !== null); } }(); diff --git a/src/connectors/compliance/impl.unit.js b/src/connectors/compliance/impl.unit.js index 10d2300e..eb4a9d64 100644 --- a/src/connectors/compliance/impl.unit.js +++ b/src/connectors/compliance/impl.unit.js @@ -7,6 +7,15 @@ const request = require('../../util/request'); const errors = require('../../errors'); const RequestError = require('request-promise-core/errors').RequestError; +const REQ = { + headers: { + 'x-rh-identity': 'identity', + 'x-rh-insights-request-id': 'request-id' + }, + identity: { type: 'test' }, + user: { username: 'test', account_number: 'test' } +}; + /* eslint-disable max-len */ describe('compliance impl', function () { @@ -37,7 +46,7 @@ describe('compliance impl', function () { headers: {} }); - const result = await impl.getRule('xccdf_org.ssgproject.content_rule_sshd_disable_root_login'); + const result = await impl.getRule(REQ, 'xccdf_org.ssgproject.content_rule_sshd_disable_root_login'); result.should.property('ref_id', 'xccdf_org.ssgproject.content_rule_sshd_disable_root_login'); result.should.property('title', 'Disable SSH Root Login'); @@ -49,7 +58,7 @@ describe('compliance impl', function () { cache.get.callCount.should.equal(1); cache.setex.callCount.should.equal(1); - await impl.getRule('xccdf_org.ssgproject.content_rule_sshd_disable_root_login'); + await impl.getRule(REQ, 'xccdf_org.ssgproject.content_rule_sshd_disable_root_login'); cache.get.callCount.should.equal(2); cache.setex.callCount.should.equal(1); }); @@ -82,7 +91,7 @@ describe('compliance impl', function () { headers: {} }); - const result = await impl.getRule('xccdf_org.ssgproject.content_rule_sshd_disable_root_login'); + const result = await impl.getRule(REQ, 'xccdf_org.ssgproject.content_rule_sshd_disable_root_login'); result.should.property('ref_id', 'xccdf_org.ssgproject.content_rule_sshd_disable_root_login'); result.should.property('title', 'Disable SSH Root Login'); @@ -94,7 +103,7 @@ describe('compliance impl', function () { cache.get.callCount.should.equal(3); cache.setex.callCount.should.equal(1); - await impl.getRule('xccdf_org.ssgproject.content_rule_sshd_disable_root_login'); + await impl.getRule(REQ, 'xccdf_org.ssgproject.content_rule_sshd_disable_root_login'); cache.get.callCount.should.equal(4); cache.setex.callCount.should.equal(1); }); @@ -108,7 +117,7 @@ describe('compliance impl', function () { headers: {} }); - await expect(impl.getRule('unknown-rule')).resolves.toBeNull(); + await expect(impl.getRule(REQ, 'unknown-rule')).resolves.toBeNull(); http.callCount.should.equal(1); cache.get.callCount.should.equal(1); @@ -117,11 +126,11 @@ describe('compliance impl', function () { test('status code handling', async function () { base.mockRequestStatusCode(); - await expect(impl.getRule('unknown-rule')).rejects.toThrow(errors.DependencyError); + await expect(impl.getRule(REQ, 'unknown-rule')).rejects.toThrow(errors.DependencyError); }); test('403 response handling', async function () { base.mockRequestStatusCode(403); - await expect(impl.getRule('xccdf_org.ssgproject.content_rule_sshd_disable_root_login')).resolves.toBeNull(); + await expect(impl.getRule(REQ, 'xccdf_org.ssgproject.content_rule_sshd_disable_root_login')).resolves.toBeNull(); }); }); diff --git a/src/connectors/compliance/mock.js b/src/connectors/compliance/mock.js index e7c8286a..efd40fb6 100644 --- a/src/connectors/compliance/mock.js +++ b/src/connectors/compliance/mock.js @@ -178,11 +178,11 @@ module.exports = new class extends Connector { super(module); } - getRule (id) { + getRule (req, id) { return P.resolve(DATA[id]); // eslint-disable-line security/detect-object-injection } - ping () { - return this.getRule('xccdf_org.ssgproject.content_rule_sshd_disable_root_login'); + ping (req) { + return this.getRule(req, 'xccdf_org.ssgproject.content_rule_sshd_disable_root_login'); } }(); diff --git a/src/connectors/configManager/impl.js b/src/connectors/configManager/impl.js index 17d178ce..d5d653b3 100644 --- a/src/connectors/configManager/impl.js +++ b/src/connectors/configManager/impl.js @@ -14,7 +14,7 @@ module.exports = new class extends Connector { this.currentProfile = metrics.createConnectorMetric(this.getName(), 'getCurrentProfile'); } - async getCurrentProfile () { + async getCurrentProfile (req) { const uri = this.buildUri(host, 'config-manager', 'v2'); uri.segment('profiles'); uri.segment('current'); @@ -23,10 +23,10 @@ module.exports = new class extends Connector { uri: uri.toString(), method: 'GET', json: true, - headers: this.getForwardedHeaders() + headers: this.getForwardedHeaders(req) }; - const result = await this.doHttp (options, false, this.currentProfile); + const result = await this.doHttp (req, options, false, this.currentProfile); if (!result) { return null; @@ -35,8 +35,8 @@ module.exports = new class extends Connector { return result; } - async ping () { - const results = await this.getCurrentProfile(); + async ping (req) { + const results = await this.getCurrentProfile(req); assert(_.isObject(results)); } }(); diff --git a/src/connectors/configManager/impl.unit.js b/src/connectors/configManager/impl.unit.js index dc23baa4..e1e6cc36 100644 --- a/src/connectors/configManager/impl.unit.js +++ b/src/connectors/configManager/impl.unit.js @@ -6,6 +6,15 @@ const { mockRequest } = require('../testUtils'); const request = require('../../util/request'); const errors = require('../../errors'); +const REQ = { + headers: { + 'x-rh-identity': 'identity', + 'x-rh-insights-request-id': 'request-id' + }, + identity: { type: 'test' }, + user: { username: 'test', account_number: 'test' } +}; + describe('config manager impl', function () { beforeEach(mockRequest); @@ -29,7 +38,7 @@ describe('config manager impl', function () { headers: {} }); - const result = await impl.getCurrentProfile(); + const result = await impl.getCurrentProfile(REQ); result.should.have.property('id', 'c5639a03-4640-4ae3-93ce-9966cae18df7'); result.should.have.property('account_id', '654321'); @@ -52,12 +61,12 @@ describe('config manager impl', function () { test('connection error handling', async function () { base.mockRequestError(); - await expect(impl.getCurrentProfile()).rejects.toThrow(errors.DependencyError); + await expect(impl.getCurrentProfile(REQ)).rejects.toThrow(errors.DependencyError); }); test('status code handling', async function () { base.mockRequestStatusCode(); - await expect(impl.getCurrentProfile()).rejects.toThrow(errors.DependencyError); + await expect(impl.getCurrentProfile(REQ)).rejects.toThrow(errors.DependencyError); }); }); }); diff --git a/src/connectors/contentServer/impl.js b/src/connectors/contentServer/impl.js index b427899c..e6ccc7e2 100644 --- a/src/connectors/contentServer/impl.js +++ b/src/connectors/contentServer/impl.js @@ -14,7 +14,7 @@ module.exports = new class extends Connector { this.metrics = metrics.createConnectorMetric(this.getName()); } - async getResolutions (id, refresh = false) { + async getResolutions (req, id, refresh = false) { const uri = new URI(host); uri.segment('private'); uri.segment('playbooks'); @@ -25,7 +25,7 @@ module.exports = new class extends Connector { method: 'GET', json: true, rejectUnauthorized: !insecure, - headers: this.getForwardedHeaders(false) + headers: this.getForwardedHeaders(req, false) }; if (auth) { @@ -34,7 +34,7 @@ module.exports = new class extends Connector { }; } - const resolutions = await this.doHttp(options, { + const resolutions = await this.doHttp(req, options, { refresh, revalidationInterval, cacheable: body => body.length > 0 // only cache responses with resolutions @@ -54,8 +54,8 @@ module.exports = new class extends Connector { ).value(); } - async ping () { - const result = await this.getResolutions('network_bond_opts_config_issue|NETWORK_BONDING_OPTS_DOUBLE_QUOTES_ISSUE', true); + async ping (req) { + const result = await this.getResolutions(req, 'network_bond_opts_config_issue|NETWORK_BONDING_OPTS_DOUBLE_QUOTES_ISSUE', true); assert(result.length > 0); } }(); diff --git a/src/connectors/contentServer/impl.unit.js b/src/connectors/contentServer/impl.unit.js index 71857ded..351d7db0 100644 --- a/src/connectors/contentServer/impl.unit.js +++ b/src/connectors/contentServer/impl.unit.js @@ -6,6 +6,15 @@ const { mockRequest, mockCache } = require('../testUtils'); const request = require('../../util/request'); const errors = require('../../errors'); +const REQ = { + headers: { + 'x-rh-identity': 'identity', + 'x-rh-insights-request-id': 'request-id' + }, + identity: { type: 'test' }, + user: { username: 'test', account_number: 'test' } +}; + /* eslint-disable max-len */ describe('content server impl', function () { @@ -26,7 +35,7 @@ describe('content server impl', function () { headers: {} }); - const result = await impl.getResolutions('network_bond_opts_config_issue|NETWORK_BONDING_OPTS_DOUBLE_QUOTES_ISSUE'); + const result = await impl.getResolutions(REQ, 'network_bond_opts_config_issue|NETWORK_BONDING_OPTS_DOUBLE_QUOTES_ISSUE'); result.should.have.length(1); const resolution = result[0]; resolution.should.have.size(5); @@ -43,7 +52,7 @@ describe('content server impl', function () { cache.get.callCount.should.equal(1); cache.setex.callCount.should.equal(1); - await impl.getResolutions('network_bond_opts_config_issue|NETWORK_BONDING_OPTS_DOUBLE_QUOTES_ISSUE'); + await impl.getResolutions(REQ, 'network_bond_opts_config_issue|NETWORK_BONDING_OPTS_DOUBLE_QUOTES_ISSUE'); cache.get.callCount.should.equal(2); cache.setex.callCount.should.equal(1); }); @@ -57,7 +66,7 @@ describe('content server impl', function () { headers: {} }); - await expect(impl.getResolutions('unknown-resolution')).resolves.toEqual([]); + await expect(impl.getResolutions(REQ, 'unknown-resolution')).resolves.toEqual([]); http.callCount.should.equal(1); cache.get.callCount.should.equal(1); @@ -66,7 +75,7 @@ describe('content server impl', function () { test('status code handling', async function () { base.mockRequestStatusCode(); - await expect(impl.getResolutions('network_bond_opts_config_issue|NETWORK_BONDING_OPTS_DOUBLE_QUOTES_ISSUE')).rejects.toThrow(errors.DependencyError); + await expect(impl.getResolutions(REQ, 'network_bond_opts_config_issue|NETWORK_BONDING_OPTS_DOUBLE_QUOTES_ISSUE')).rejects.toThrow(errors.DependencyError); }); test('deals with null play field', async function () { @@ -88,7 +97,7 @@ describe('content server impl', function () { headers: {} }); - const result = await impl.getResolutions('network_bond_opts_config_issue|NETWORK_BONDING_OPTS_DOUBLE_QUOTES_ISSUE'); + const result = await impl.getResolutions(REQ, 'network_bond_opts_config_issue|NETWORK_BONDING_OPTS_DOUBLE_QUOTES_ISSUE'); result.should.have.length(1); const resolution = result[0]; resolution.should.have.property('resolution_type', 'fix'); diff --git a/src/connectors/contentServer/mock.js b/src/connectors/contentServer/mock.js index 9bcf0305..0e3c6bdd 100644 --- a/src/connectors/contentServer/mock.js +++ b/src/connectors/contentServer/mock.js @@ -53,7 +53,7 @@ module.exports = new class extends Connector { super(module); } - getResolutions (id) { + getResolutions (req, id) { if (_.has(DATA, id)) { return DATA[id]; // eslint-disable-line security/detect-object-injection } @@ -61,8 +61,8 @@ module.exports = new class extends Connector { return []; } - ping () { - return this.getResolutions('network_bond_opts_config_issue|NETWORK_BONDING_OPTS_DOUBLE_QUOTES_ISSUE'); + ping (req) { + return this.getResolutions(req, 'network_bond_opts_config_issue|NETWORK_BONDING_OPTS_DOUBLE_QUOTES_ISSUE'); } }(); diff --git a/src/connectors/dispatcher/impl.js b/src/connectors/dispatcher/impl.js index a15ef734..3531545a 100644 --- a/src/connectors/dispatcher/impl.js +++ b/src/connectors/dispatcher/impl.js @@ -31,11 +31,12 @@ module.exports = new class extends Connector { this.getRunRecipientStatus = metrics.createConnectorMetric(this.getName(), 'getPlaybookRunRecipientStatus'); } - async postPlaybookRunRequests (dispatcherWorkRequest) { + // Maybe change these parameters because dispatcherWorkRequest is part of the req + async postPlaybookRunRequests (req, dispatcherWorkRequest) { // chunk this request if necessary... if (dispatcherWorkRequest.length > pageSize) { const chunks = _.chunk(dispatcherWorkRequest, pageSize); - const results = await P.map(chunks, chunk => this.postPlaybookRunRequests(chunk)); + const results = await P.map(chunks, chunk => this.postPlaybookRunRequests(req, chunk)); return results.flat(); } @@ -48,7 +49,7 @@ module.exports = new class extends Connector { method: 'POST', json: true, rejectUnauthorized: !insecure, - headers: this.getForwardedHeaders(), + headers: this.getForwardedHeaders(req), body: dispatcherWorkRequest }; @@ -57,7 +58,7 @@ module.exports = new class extends Connector { options.headers.Authorization = `PSK ${auth}`; } - const result = await this.doHttp (options, false, this.postRunRequests); + const result = await this.doHttp (req, options, false, this.postRunRequests); if (_.isEmpty(result)) { return null; @@ -107,7 +108,8 @@ module.exports = new class extends Connector { // - one object per satellite_organization (recipient_type == satellite) // - one object for each direct-connect hosts // - one object for hosts with recipient_type == none (e.g. old receptor hosts, no_rhc) - async getConnectionStatus (dispatcherConnectionStatusRequest) { + // Maybe change these parameters because dispatcherWorkRequest is part of the request + async getConnectionStatus (request, dispatcherConnectionStatusRequest) { // chunk this request if necessary... if (dispatcherConnectionStatusRequest.hosts.length > pageSize) { const chunks = _.chunk(dispatcherConnectionStatusRequest.hosts, pageSize); @@ -118,7 +120,7 @@ module.exports = new class extends Connector { hosts: chunk }; - return this.getConnectionStatus(req); + return this.getConnectionStatus(request, req); }); // merge items with same recipient id & status @@ -147,7 +149,7 @@ module.exports = new class extends Connector { method: 'POST', json: true, rejectUnauthorized: !insecure, - headers: this.getForwardedHeaders(), + headers: this.getForwardedHeaders(request), body: dispatcherConnectionStatusRequest }; @@ -156,7 +158,7 @@ module.exports = new class extends Connector { options.headers.Authorization = `PSK ${auth}`; } - const result = await this.doHttp (options, false, this.postV2ConnectionStatus); + const result = await this.doHttp (request, options, false, this.postV2ConnectionStatus); if (_.isEmpty(result)) { return []; @@ -165,11 +167,11 @@ module.exports = new class extends Connector { return result; } - async postV2PlaybookRunRequests (dispatcherV2WorkRequests) { + async postV2PlaybookRunRequests (req, dispatcherV2WorkRequests) { // chunk this request if necessary... if (dispatcherV2WorkRequests.length > pageSize) { const chunks = _.chunk(dispatcherV2WorkRequests, pageSize); - const results = await P.map(chunks, chunk => this.postV2PlaybookRunRequests(chunk)); + const results = await P.map(chunks, chunk => this.postV2PlaybookRunRequests(req, chunk)); return results.flat(); } @@ -183,7 +185,7 @@ module.exports = new class extends Connector { method: 'POST', json: true, rejectUnauthorized: !insecure, - headers: this.getForwardedHeaders(), + headers: this.getForwardedHeaders(req), body: dispatcherV2WorkRequests }; @@ -192,7 +194,7 @@ module.exports = new class extends Connector { options.headers.Authorization = `PSK ${auth}`; } - const result = await this.doHttp (options, false, this.postV2RunRequests); + const result = await this.doHttp (req, options, false, this.postV2RunRequests); if (_.isEmpty(result)) { return null; @@ -201,7 +203,7 @@ module.exports = new class extends Connector { return result; } - async fetchPlaybookRuns (filter, fields, sort_by = null) { + async fetchPlaybookRuns (req, filter, fields, sort_by = null) { const _uri = this.buildUri(host, 'playbook-dispatcher', 'v1', 'runs'); _uri.search(generateQueries(filter, fields)); @@ -218,16 +220,14 @@ module.exports = new class extends Connector { const options = { method: 'GET', json: true, - headers: this.getForwardedHeaders() + headers: this.getForwardedHeaders(req) }; // get playbook runs... do { // grab a page options.uri = uri; - const batch = await this.doHttp (options, - false, - this.fetchRuns); + const batch = await this.doHttp (req, options, false, this.fetchRuns); // bail if we got nothing if (!batch?.data) { @@ -254,7 +254,7 @@ module.exports = new class extends Connector { return results; } - async fetchPlaybookRunHosts (filter, fields) { + async fetchPlaybookRunHosts (req, filter, fields) { const _uri = this.buildUri(host, 'playbook-dispatcher', 'v1', 'run_hosts'); _uri.search(generateQueries(filter, fields)); @@ -267,13 +267,13 @@ module.exports = new class extends Connector { const options = { method: 'GET', json: true, - headers: this.getForwardedHeaders() + headers: this.getForwardedHeaders(req) }; do { // grab a page options.uri = uri; - const batch = await this.doHttp (options, + const batch = await this.doHttp (req, options, false, this.fetchRunHosts); @@ -303,7 +303,7 @@ module.exports = new class extends Connector { return results; } - async postPlaybookCancelRequest (cancelPlaybookRunsRequest) { + async postPlaybookCancelRequest (req, cancelPlaybookRunsRequest) { const uri = new URI(host); uri.segment('internal'); uri.segment('v2'); @@ -314,7 +314,7 @@ module.exports = new class extends Connector { method: 'POST', json: true, rejectUnauthorized: !insecure, - headers: this.getForwardedHeaders(), + headers: this.getForwardedHeaders(req), body: cancelPlaybookRunsRequest }; @@ -323,7 +323,7 @@ module.exports = new class extends Connector { options.headers.Authorization = `PSK ${auth}`; } - const result = await this.doHttp (options, false, this.postPlaybookCancelRequests); + const result = await this.doHttp (req, options, false, this.postPlaybookCancelRequests); if (_.isEmpty(result.data)) { return null; @@ -332,12 +332,13 @@ module.exports = new class extends Connector { return result; } - async getPlaybookRunRecipientStatus (dispatcherStatusRequest) { +// Is this necessary? + async getPlaybookRunRecipientStatus (req, dispatcherStatusRequest) { // chunk this request if necessary... if (dispatcherStatusRequest.length > pageSize) { const chunks = _.chunk(dispatcherStatusRequest, pageSize); - const results = await P.map(chunks, chunk => this.getPlaybookRunRecipientStatus(chunk)); + const results = await P.map(chunks, chunk => this.getPlaybookRunRecipientStatus(req, chunk)); return results.flat(); } @@ -352,7 +353,7 @@ module.exports = new class extends Connector { method: 'POST', json: true, rejectUnauthorized: !insecure, - headers: this.getForwardedHeaders(), + headers: this.getForwardedHeaders(req), body: dispatcherStatusRequest }; @@ -362,7 +363,7 @@ module.exports = new class extends Connector { } log.info({request: dispatcherStatusRequest}, 'PRE RunRecipientStatus'); - const result = await this.doHttp (options, false, this.getRunRecipientStatus); + const result = await this.doHttp (req, options, false, this.getRunRecipientStatus); // TODO: ehh, we probably shouldn't be logging this... log.info({result: result}, 'POST RunRecipientStatus'); diff --git a/src/connectors/dispatcher/impl.unit.js b/src/connectors/dispatcher/impl.unit.js index bdc0c8d7..f94141cd 100644 --- a/src/connectors/dispatcher/impl.unit.js +++ b/src/connectors/dispatcher/impl.unit.js @@ -75,6 +75,15 @@ const LARGE_SAT_STATUS_REQ = { const MOCKFILTER = {filter: {service: 'remediations'}}; const MOCKFIELDS = {fields: {data: ['id']}}; +const REQ = { + headers: { + 'x-rh-identity': 'identity', + 'x-rh-insights-request-id': 'request-id' + }, + identity: { type: 'test' }, + user: { username: 'test', account_number: 'test' } +}; + /* eslint-disable max-len */ describe('dispatcher impl', function () { @@ -96,7 +105,7 @@ describe('dispatcher impl', function () { headers: {} }); - const results = await impl.postPlaybookRunRequests(DISPATCHERWORKREQUEST); + const results = await impl.postPlaybookRunRequests(REQ, DISPATCHERWORKREQUEST); results.should.have.size(2); const result1 = results[0]; @@ -116,17 +125,17 @@ describe('dispatcher impl', function () { test('returns null dispatcherWorkRequest is incorrect', async function () { base.getSandbox().stub(Connector.prototype, 'doHttp').resolves([]); - await expect(impl.postPlaybookRunRequests(DISPATCHERWORKREQUEST)).resolves.toBeNull(); + await expect(impl.postPlaybookRunRequests(REQ, DISPATCHERWORKREQUEST)).resolves.toBeNull(); }); test('connection error handling dispatcherWorkRequest', async function () { base.mockRequestError(); - await expect(impl.postPlaybookRunRequests(DISPATCHERWORKREQUEST)).rejects.toThrow(errors.DependencyError); + await expect(impl.postPlaybookRunRequests(REQ, DISPATCHERWORKREQUEST)).rejects.toThrow(errors.DependencyError); }); test('status code handling dispatcherWorkRequest', async function () { base.mockRequestStatusCode(); - await expect(impl.postPlaybookRunRequests(DISPATCHERWORKREQUEST)).rejects.toThrow(errors.DependencyError); + await expect(impl.postPlaybookRunRequests(REQ, DISPATCHERWORKREQUEST)).rejects.toThrow(errors.DependencyError); }); test('handles many requests', async function () { @@ -166,7 +175,7 @@ describe('dispatcher impl', function () { }); // submit work request - const result = await impl.postPlaybookRunRequests(workRequest); + const result = await impl.postPlaybookRunRequests(REQ, workRequest); // validate results result.should.have.size(250); @@ -215,7 +224,7 @@ describe('dispatcher impl', function () { headers: {} }); - const results = await impl.fetchPlaybookRuns(MOCKFILTER, MOCKFIELDS); + const results = await impl.fetchPlaybookRuns(REQ, MOCKFILTER, MOCKFIELDS); results.data.should.have.size(2); const result1 = results.data[0]; @@ -264,17 +273,17 @@ describe('dispatcher impl', function () { headers: {} }); - await expect(impl.fetchPlaybookRuns(MOCKFILTER, MOCKFIELDS)).resolves.toBeNull(); + await expect(impl.fetchPlaybookRuns(REQ, MOCKFILTER, MOCKFIELDS)).resolves.toBeNull(); }); test('connection error handling dispatcherWorkRequest', async function () { base.mockRequestError(); - await expect(impl.fetchPlaybookRuns(MOCKFILTER, MOCKFIELDS)).rejects.toThrow(errors.DependencyError); + await expect(impl.fetchPlaybookRuns(REQ, MOCKFILTER, MOCKFIELDS)).rejects.toThrow(errors.DependencyError); }); test('status code handling dispatcherWorkRequest', async function () { base.mockRequestStatusCode(); - await expect(impl.fetchPlaybookRuns(MOCKFILTER, MOCKFIELDS)).rejects.toThrow(errors.DependencyError); + await expect(impl.fetchPlaybookRuns(REQ, MOCKFILTER, MOCKFIELDS)).rejects.toThrow(errors.DependencyError); }); }); @@ -327,7 +336,7 @@ describe('dispatcher impl', function () { headers: {} }); - const results = await impl.fetchPlaybookRunHosts(MOCKFILTER, MOCKFIELDS); + const results = await impl.fetchPlaybookRunHosts(REQ, MOCKFILTER, MOCKFIELDS); results.data.should.have.size(2); const result1 = results.data[0]; @@ -354,17 +363,17 @@ describe('dispatcher impl', function () { test('returns null dispatcherWorkRequest is incorrect', async function () { base.getSandbox().stub(Connector.prototype, 'doHttp').resolves([]); - await expect(impl.fetchPlaybookRunHosts(MOCKFILTER, MOCKFIELDS)).resolves.toBeNull(); + await expect(impl.fetchPlaybookRunHosts(REQ, MOCKFILTER, MOCKFIELDS)).resolves.toBeNull(); }); test('connection error handling dispatcherWorkRequest', async function () { base.mockRequestError(); - await expect(impl.fetchPlaybookRunHosts(MOCKFILTER, MOCKFIELDS)).rejects.toThrow(errors.DependencyError); + await expect(impl.fetchPlaybookRunHosts(REQ, MOCKFILTER, MOCKFIELDS)).rejects.toThrow(errors.DependencyError); }); test('status code handling dispatcherWorkRequest', async function () { base.mockRequestStatusCode(); - await expect(impl.fetchPlaybookRunHosts(MOCKFILTER, MOCKFIELDS)).rejects.toThrow(errors.DependencyError); + await expect(impl.fetchPlaybookRunHosts(REQ, MOCKFILTER, MOCKFIELDS)).rejects.toThrow(errors.DependencyError); }); }); @@ -386,7 +395,7 @@ describe('dispatcher impl', function () { headers: {} }); - const results = await impl.postPlaybookCancelRequest(MOCKCANCELREQUEST); + const results = await impl.postPlaybookCancelRequest(REQ, MOCKCANCELREQUEST); results.data.should.have.size(1); const result1 = results.data[0]; @@ -402,17 +411,17 @@ describe('dispatcher impl', function () { test('returns null playbookCancelRequest is incorrect', async function () { base.getSandbox().stub(Connector.prototype, 'doHttp').resolves([]); - await expect(impl.postPlaybookCancelRequest(MOCKCANCELREQUEST)).resolves.toBeNull(); + await expect(impl.postPlaybookCancelRequest(REQ, MOCKCANCELREQUEST)).resolves.toBeNull(); }); test('connection error handling playbookCancelRequest', async function () { base.mockRequestError(); - await expect(impl.postPlaybookCancelRequest(MOCKCANCELREQUEST)).rejects.toThrow(errors.DependencyError); + await expect(impl.postPlaybookCancelRequest(REQ, MOCKCANCELREQUEST)).rejects.toThrow(errors.DependencyError); }); test('status code handling playbookCancelRequest', async function () { base.mockRequestStatusCode(); - await expect(impl.postPlaybookCancelRequest(MOCKCANCELREQUEST)).rejects.toThrow(errors.DependencyError); + await expect(impl.postPlaybookCancelRequest(REQ, MOCKCANCELREQUEST)).rejects.toThrow(errors.DependencyError); }); }); @@ -440,7 +449,7 @@ describe('dispatcher impl', function () { headers: {} }); - const results = await impl.getPlaybookRunRecipientStatus(DISPATCHSTATUSREQUEST); + const results = await impl.getPlaybookRunRecipientStatus(REQ, DISPATCHSTATUSREQUEST); const result1 = results['d415fc2d-9700-4e30-9621-6a410ccc92d8']; result1.should.have.property('recipient', 'd415fc2d-9700-4e30-9621-6a410ccc92d8'); @@ -466,17 +475,17 @@ describe('dispatcher impl', function () { test('returns null dispatcherStatusRequest is incorrect', async function () { base.getSandbox().stub(Connector.prototype, 'doHttp').resolves(null); - await expect(impl.getPlaybookRunRecipientStatus(DISPATCHSTATUSREQUEST)).resolves.toBeNull(); + await expect(impl.getPlaybookRunRecipientStatus(REQ, DISPATCHSTATUSREQUEST)).resolves.toBeNull(); }); test('connection error handling dispatcherStatusRequest', async function () { base.mockRequestError(); - await expect(impl.getPlaybookRunRecipientStatus(DISPATCHSTATUSREQUEST)).rejects.toThrow(errors.DependencyError); + await expect(impl.getPlaybookRunRecipientStatus(REQ, DISPATCHSTATUSREQUEST)).rejects.toThrow(errors.DependencyError); }); test('status code handling dispatcherStatusRequest', async function () { base.mockRequestStatusCode(); - await expect(impl.getPlaybookRunRecipientStatus(DISPATCHSTATUSREQUEST)).rejects.toThrow(errors.DependencyError); + await expect(impl.getPlaybookRunRecipientStatus(REQ, DISPATCHSTATUSREQUEST)).rejects.toThrow(errors.DependencyError); }); }); @@ -503,7 +512,7 @@ describe('dispatcher impl', function () { headers: {} }); - const results = await impl.getConnectionStatus(DISPATCHV2STATUSREUEST); + const results = await impl.getConnectionStatus(REQ, DISPATCHV2STATUSREUEST); results.should.have.length(1); results[0].systems.should.have.length(4); @@ -512,24 +521,24 @@ describe('dispatcher impl', function () { test('chunks large request', async () => { // verify correct collation (sat_a: 51+, sat_b: 2+, direct_a: 1, direct_b: 1) base.getSandbox().stub(request, 'run').callsFake(dispatcher); - const results = await impl.getConnectionStatus(LARGE_SAT_STATUS_REQ); + const results = await impl.getConnectionStatus(REQ, LARGE_SAT_STATUS_REQ); expect(results.body).toMatchSnapshot(); }); test('returns empty array if no results', async () => { base.getSandbox().stub(Connector.prototype, 'doHttp').resolves(null); - await expect(impl.getConnectionStatus(DISPATCHV2STATUSREUEST)).resolves.toEqual([]); + await expect(impl.getConnectionStatus(REQ, DISPATCHV2STATUSREUEST)).resolves.toEqual([]); }); test('connection error handling dispatcherV2StatusRequest', async () => { base.mockRequestStatusCode(); - await expect(impl.getConnectionStatus(DISPATCHV2STATUSREUEST)).rejects.toThrow(errors.DependencyError); + await expect(impl.getConnectionStatus(REQ, DISPATCHV2STATUSREUEST)).rejects.toThrow(errors.DependencyError); }); test('status code handling dispatcherV2StatusRequest', async () => { base.mockRequestStatusCode(); - await expect(impl.getConnectionStatus(DISPATCHV2STATUSREUEST)).rejects.toThrow(errors.DependencyError); + await expect(impl.getConnectionStatus(REQ, DISPATCHV2STATUSREUEST)).rejects.toThrow(errors.DependencyError); }); }); }); diff --git a/src/connectors/dispatcher/mock.js b/src/connectors/dispatcher/mock.js index 5f94a581..b492069a 100644 --- a/src/connectors/dispatcher/mock.js +++ b/src/connectors/dispatcher/mock.js @@ -323,7 +323,7 @@ module.exports = new class extends Connector { return MOCKDISPATCHRESPONSE; } - fetchPlaybookRuns (filter = null) { + fetchPlaybookRuns (req, filter = null) { if (filter) { if (!_.isUndefined(filter.filter.labels)) { const run = RUNS[filter.filter.labels['playbook-run']]; @@ -349,7 +349,7 @@ module.exports = new class extends Connector { }; } - fetchPlaybookRunHosts (filter = null) { + fetchPlaybookRunHosts (req, filter = null) { if (filter) { if (!_.isUndefined(filter.filter.inventory_id)) { return { @@ -378,7 +378,7 @@ module.exports = new class extends Connector { }; } - postPlaybookCancelRequest (request) { + postPlaybookCancelRequest (req, request) { if (request[0].run_id !== '88d0ba73-0015-4e7d-a6d6-4b530cbfb7bc') { return { meta: { @@ -405,7 +405,7 @@ module.exports = new class extends Connector { return RUNSTATUSES; } - getConnectionStatus (dispatcherConnectionStatusRequest) { + getConnectionStatus (req, dispatcherConnectionStatusRequest) { const hosts = dispatcherConnectionStatusRequest.hosts; // get system data diff --git a/src/connectors/dispatcher/noop.js b/src/connectors/dispatcher/noop.js index 7a21ece1..278d1037 100644 --- a/src/connectors/dispatcher/noop.js +++ b/src/connectors/dispatcher/noop.js @@ -38,9 +38,9 @@ module.exports = new class extends Connector { ]; } - getPlaybookRunRecipientStatus () { - return null; - } + // getPlaybookRunRecipientStatus () { + // return null; + // } ping () {} }(); diff --git a/src/connectors/http.js b/src/connectors/http.js index d52b595e..d753e8ba 100644 --- a/src/connectors/http.js +++ b/src/connectors/http.js @@ -11,7 +11,7 @@ const StatusCodeError = require('./StatusCodeError'); const CACHE_TTL = config.cache.ttl; const REVALIDATION_INTERVAL = config.cache.revalidationInterval; -function doHttp (options, cached, metrics) { +function doHttp (req, options, cached, metrics) { const opts = { resolveWithFullResponse: true, simple: false, @@ -64,18 +64,18 @@ function saveCachedEntry (redis, key, etag, body) { })); } -async function run (options, useCache = false, metrics = false, responseTransformer = res => res === null ? null : res.body) { +async function run (req, options, useCache = false, metrics = false, responseTransformer = res => res === null ? null : res.body) { if (!useCache || !config.redis.enabled || cache.get().status !== 'ready') { metrics && metrics.miss.inc(); - return doHttp(options, false, metrics).then(responseTransformer); + return doHttp(req, options, false, metrics).then(responseTransformer); } const uri = notNil(options.uri); const key = useCache.key || cacheKey(uri); const revalidationInterval = useCache.revalidationInterval || REVALIDATION_INTERVAL; // seconds - const cached = await loadCachedEntry(cache.get(), key, revalidationInterval); + if (useCache.refresh) { log.trace({key}, 'forced refresh'); } else if (cached && !cached.expired) { @@ -89,7 +89,7 @@ async function run (options, useCache = false, metrics = false, responseTransfor } metrics && metrics.miss.inc(); - const res = await doHttp(options, cached, metrics); + const res = await doHttp(req, options, cached, metrics); if (!res) { // 404 if (cached) { diff --git a/src/connectors/http.unit.js b/src/connectors/http.unit.js index 5f1d9843..3fd14a5b 100644 --- a/src/connectors/http.unit.js +++ b/src/connectors/http.unit.js @@ -15,6 +15,15 @@ const MOCK_CACHE = { del () {} }; +const REQ = { + headers: { + 'x-rh-identity': 'identity', + 'x-rh-insights-request-id': 'request-id' + }, + identity: { type: 'test' }, + user: { username: 'test', account_number: 'test' } +}; + describe('connector caching', function () { beforeEach(() => { base.sandbox.stub(config.redis, 'enabled').value(true); @@ -34,7 +43,7 @@ describe('connector caching', function () { base.sandbox.spy(MOCK_CACHE, 'setex'); base.sandbox.spy(request, 'run'); - const result = await http.request({ + const result = await http.request(REQ, { uri: 'https://example.com' }, true); @@ -58,7 +67,7 @@ describe('connector caching', function () { }); base.sandbox.spy(MOCK_CACHE, 'setex'); - const result = await http.request({ + const result = await http.request(REQ, { uri: 'https://example.com' }, true); @@ -88,7 +97,7 @@ describe('connector caching', function () { }); base.sandbox.spy(MOCK_CACHE, 'setex'); - const result = await http.request({ + const result = await http.request(REQ, { uri: 'https://example.com' }, true); @@ -115,7 +124,7 @@ describe('connector caching', function () { base.sandbox.spy(MOCK_CACHE, 'setex'); base.sandbox.spy(MOCK_CACHE, 'del'); - const result = await http.request({ + const result = await http.request(REQ, { uri: 'https://example.com' }, true); @@ -139,7 +148,7 @@ describe('connector caching', function () { }); base.sandbox.spy(MOCK_CACHE, 'setex'); - const result = await http.request({ + const result = await http.request(REQ, { uri: 'https://example.com' }, true); @@ -157,7 +166,7 @@ describe('connector caching', function () { }); base.sandbox.spy(MOCK_CACHE, 'setex'); - const result = await http.request({ + const result = await http.request(REQ, { uri: 'https://example.com' }, true); @@ -174,7 +183,7 @@ describe('connector caching', function () { }); base.sandbox.stub(MOCK_CACHE, 'setex').resolves(null); - await expect(http.request({ + await expect(http.request(REQ, { uri: 'https://example.com' }, true)).rejects.toThrow(StatusCodeError); @@ -188,7 +197,7 @@ describe('connector caching', function () { base.sandbox.stub(request, 'run').rejects(new Error('socket timeout')); base.sandbox.stub(MOCK_CACHE, 'setex').resolves(null); - await expect(http.request({ + await expect(http.request(REQ, { uri: 'https://example.com' }, true)).rejects.toThrow('socket timeout'); @@ -204,7 +213,7 @@ describe('connector caching', function () { }); base.sandbox.stub(MOCK_CACHE, 'setex').resolves(null); - await http.request({ + await http.request(REQ, { uri: 'https://example.com' }); diff --git a/src/connectors/inventory/impl.js b/src/connectors/inventory/impl.js index ebd96f60..dd6300f3 100644 --- a/src/connectors/inventory/impl.js +++ b/src/connectors/inventory/impl.js @@ -42,14 +42,15 @@ module.exports = new class extends Connector { return this.buildUri(host, 'inventory', 'api', 'v1', 'hosts'); } - async getSystemInfoBatch (ids = [], refresh = false, retries = 2) { +// Is this being used? + async getSystemInfoBatch (req, ids = [], refresh = false, retries = 2) { if (ids.length === 0) { return {}; } if (ids.length > pageSize) { const chunks = _.chunk(ids, pageSize); - const results = await P.map(chunks, chunk => this.getSystemInfoBatch(chunk, refresh)); + const results = await P.map(chunks, chunk => this.getSystemInfoBatch(req, chunk, refresh)); return _.assign({}, ...results); } @@ -61,12 +62,12 @@ module.exports = new class extends Connector { let response = null; try { - response = await this.doHttp({ + response = await this.doHttp(req, { uri: uri.toString(), method: 'GET', json: true, rejectUnauthorized: !insecure, - headers: this.getForwardedHeaders() + headers: this.getForwardedHeaders(req) }, { key: `remediations|http-cache|inventory|${ids.join()}`, @@ -78,7 +79,7 @@ module.exports = new class extends Connector { } catch (e) { if (retries > 0) { log.warn({ error: e, ids, retries }, 'Inventory fetch failed. Retrying'); - return this.getSystemInfoBatch(ids, true, retries - 1); + return this.getSystemInfoBatch(req, ids, true, retries - 1); } throw e; @@ -113,7 +114,7 @@ module.exports = new class extends Connector { return result; } - async getSystemDetailsBatch (ids = [], refresh = false, retries = 2) { + async getSystemDetailsBatch (req, ids = [], refresh = false, retries = 2) { if (ids.length === 0) { return {}; } @@ -122,7 +123,7 @@ module.exports = new class extends Connector { if (ids.length > pageSize) { const chunks = _.chunk(ids, pageSize); - const results = await P.map(chunks, chunk => this.getSystemDetailsBatch(chunk, refresh)); + const results = await P.map(chunks, chunk => this.getSystemDetailsBatch(req, chunk, refresh)); return _.assign({}, ...results); } @@ -133,12 +134,12 @@ module.exports = new class extends Connector { let response = null; try { - response = await this.doHttp({ + response = await this.doHttp(req, { uri: uri.toString(), method: 'GET', json: true, rejectUnauthorized: !insecure, - headers: this.getForwardedHeaders() + headers: this.getForwardedHeaders(req) }, { key: `remediations|http-cache|inventory|${ids.join()}`, @@ -150,7 +151,7 @@ module.exports = new class extends Connector { } catch (e) { if (retries > 0) { log.warn({ error: e, ids, retries }, 'Inventory fetch failed. Retrying'); - return this.getSystemDetailsBatch(ids, true, retries - 1); + return this.getSystemDetailsBatch(req, ids, true, retries - 1); } throw e; @@ -165,7 +166,7 @@ module.exports = new class extends Connector { return validate(transformed); } - async getSystemProfileBatch (ids = [], refresh = false, retries = 2) { + async getSystemProfileBatch (req, ids = [], refresh = false, retries = 2) { if (ids.length === 0) { return {}; } @@ -174,7 +175,7 @@ module.exports = new class extends Connector { if (ids.length > pageSize) { const chunks = _.chunk(ids, pageSize); - const results = await P.map(chunks, chunk => this.getSystemProfileBatch(chunk, refresh)); + const results = await P.map(chunks, chunk => this.getSystemProfileBatch(req, chunk, refresh)); return _.assign({}, ...results); } @@ -187,12 +188,12 @@ module.exports = new class extends Connector { let response = null; try { - response = await this.doHttp({ + response = await this.doHttp(req, { uri: uri.toString(), method: 'GET', json: true, rejectUnauthorized: !insecure, - headers: this.getForwardedHeaders() + headers: this.getForwardedHeaders(req) }, { key: `remediations|http-cache|inventory|system_profile|${ids.join()}`, @@ -204,7 +205,7 @@ module.exports = new class extends Connector { } catch (e) { if (retries > 0) { log.warn({ error: e, ids, retries }, 'Inventory fetch failed. Retrying'); - return this.getSystemProfileBatch(ids, true, retries - 1); + return this.getSystemProfileBatch(req, ids, true, retries - 1); } throw e; @@ -219,17 +220,17 @@ module.exports = new class extends Connector { return transformed; } - async getSystemsByInsightsId (id) { + async getSystemsByInsightsId (id, req) { const uri = this.buildHostsUri(); uri.addQuery('per_page', String(pageSize)); uri.addQuery('insights_id', id); - const response = await this.doHttp({ + const response = await this.doHttp(req, { uri: uri.toString(), method: 'GET', json: true, rejectUnauthorized: !insecure, - headers: this.getForwardedHeaders() + headers: this.getForwardedHeaders(req) }, false); assert(response.total <= pageSize, `results exceed page (${response.total})`); @@ -243,7 +244,8 @@ module.exports = new class extends Connector { return transformed; } - async getSystemsByOwnerId (owner_id, refresh = false, retries = 2) { +// Maybe remove? not being used + async getSystemsByOwnerId (req, owner_id, refresh = false, retries = 2) { const uri = this.buildHostsUri(); uri.addQuery('per_page', String(pageSize)); uri.addQuery('filter[system_profile][owner_id]', owner_id); @@ -251,12 +253,12 @@ module.exports = new class extends Connector { let response = null; try { - response = await this.doHttp({ + response = await this.doHttp(req, { uri: uri.toString(), method: 'GET', json: true, rejectUnauthorized: !insecure, - headers: this.getForwardedHeaders() + headers: this.getForwardedHeaders(req) }, { key: `remediations|http-cache|inventory|owner-id|${owner_id}`, @@ -268,7 +270,7 @@ module.exports = new class extends Connector { } catch (e) { if (retries > 0) { log.warn({ error: e, retries }, 'Inventory fetch failed. Retrying'); - return this.getSystemsByOwnerId(owner_id, false, retries - 1); + return this.getSystemsByOwnerId(req, owner_id, false, retries - 1); } throw e; @@ -283,16 +285,16 @@ module.exports = new class extends Connector { return transformed; } - async ping () { + async ping (req) { const uri = this.buildHostsUri(); uri.addQuery('per_page', String(1)); - const response = await this.doHttp({ + const response = await this.doHttp(req, { uri: uri.toString(), method: 'GET', json: true, rejectUnauthorized: !insecure, - headers: this.getForwardedHeaders() + headers: this.getForwardedHeaders(req) }); assert(Array.isArray(response.results)); diff --git a/src/connectors/inventory/impl.unit.js b/src/connectors/inventory/impl.unit.js index 078939ca..d9644d0d 100644 --- a/src/connectors/inventory/impl.unit.js +++ b/src/connectors/inventory/impl.unit.js @@ -11,6 +11,15 @@ const request = require('../../util/request'); const RequestError = require('request-promise-core/errors').RequestError; const inventory_GET = require('./inventory_GET.json'); +const REQ = { + headers: { + 'x-rh-identity': 'identity', + 'x-rh-insights-request-id': 'request-id' + }, + identity: { type: 'test' }, + user: { username: 'test', account_number: 'test' } +}; + function inventoryResponse (results, total = results.length) { return { results, @@ -28,7 +37,7 @@ describe('inventory impl', function () { const spy = base.getSandbox().stub(Connector.prototype, 'doHttp').resolves(inventory_GET); - const result = await impl.getSystemInfoBatch([ + const result = await impl.getSystemInfoBatch(REQ, [ "9cc31c02-96f9-4d33-8d14-ea8467393b51", "2c9284a9-a489-43d4-a7bb-1ef43cf890b8" ]); @@ -43,7 +52,7 @@ describe('inventory impl', function () { describe('getSystemDetailsBatch', function () { test('does not make a call for empty list', async function () { const spy = base.getSandbox().spy(http, 'request'); - const result = await impl.getSystemDetailsBatch([]); + const result = await impl.getSystemDetailsBatch(REQ, []); result.should.be.empty(); spy.called.should.be.false(); @@ -52,7 +61,7 @@ describe('inventory impl', function () { test('forwards request headers', async function () { const spy = base.getSandbox().stub(Connector.prototype, 'doHttp').resolves(inventoryResponse([])); - await impl.getSystemDetailsBatch(['id']); + await impl.getSystemDetailsBatch(REQ, ['id']); const headers = spy.args[0][0].headers; headers.should.have.size(2); headers.should.have.property('x-rh-identity', 'identity'); @@ -103,7 +112,7 @@ describe('inventory impl', function () { headers: {} }); - const results = await impl.getSystemDetailsBatch(['id']); + const results = await impl.getSystemDetailsBatch(REQ, ['id']); results.should.have.size(1); results.should.have.property('9615dda7-5868-4957-88ba-c3064c86d332'); const result = results['9615dda7-5868-4957-88ba-c3064c86d332']; @@ -120,7 +129,7 @@ describe('inventory impl', function () { cache.get.callCount.should.equal(1); cache.setex.callCount.should.equal(1); - await impl.getSystemDetailsBatch(['id']); + await impl.getSystemDetailsBatch(REQ, ['id']); cache.get.callCount.should.equal(2); cache.setex.callCount.should.equal(1); }); @@ -165,7 +174,7 @@ describe('inventory impl', function () { headers: {} }); - const results = await impl.getSystemDetailsBatch(['id']); + const results = await impl.getSystemDetailsBatch(REQ, ['id']); results.should.have.size(1); results.should.have.property('9615dda7-5868-4957-88ba-c3064c86d332'); const result = results['9615dda7-5868-4957-88ba-c3064c86d332']; @@ -181,7 +190,7 @@ describe('inventory impl', function () { cache.get.callCount.should.equal(3); cache.setex.callCount.should.equal(1); - await impl.getSystemDetailsBatch(['id']); + await impl.getSystemDetailsBatch(REQ, ['id']); cache.get.callCount.should.equal(4); cache.setex.callCount.should.equal(1); }); @@ -201,7 +210,7 @@ describe('inventory impl', function () { headers: {} }); - await expect(impl.getSystemDetailsBatch(['id'])).resolves.toEqual({}); + await expect(impl.getSystemDetailsBatch(REQ, ['id'])).resolves.toEqual({}); http.callCount.should.equal(1); cache.get.callCount.should.equal(1); @@ -240,7 +249,7 @@ describe('inventory impl', function () { const ids = Array(250).fill(0).map((value, key) => `84762eb3-0bbb-4bd8-ab11-f420c50e9${String(key).padStart(3, '0')}`); - const result = await impl.getSystemDetailsBatch(ids); + const result = await impl.getSystemDetailsBatch(REQ, ids); result.should.have.size(250); ids.forEach(id => _.has(result, id).should.be.true()); }); @@ -249,7 +258,7 @@ describe('inventory impl', function () { describe('getSystemsProfileBatch', function () { test('does not make a call for empty list', async function () { const spy = base.getSandbox().spy(http, 'request'); - const result = await impl.getSystemProfileBatch([]); + const result = await impl.getSystemProfileBatch(REQ, []); result.should.be.empty(); spy.called.should.be.false(); @@ -258,7 +267,7 @@ describe('inventory impl', function () { test('forwards request headers', async function () { const spy = base.getSandbox().stub(Connector.prototype, 'doHttp').resolves(inventoryResponse([])); - await impl.getSystemProfileBatch(['id']); + await impl.getSystemProfileBatch(REQ, ['id']); const headers = spy.args[0][0].headers; headers.should.have.size(2); headers.should.have.property('x-rh-identity', 'identity'); @@ -285,7 +294,7 @@ describe('inventory impl', function () { headers: {} }); - const results = await impl.getSystemProfileBatch(['id']); + const results = await impl.getSystemProfileBatch(REQ, ['id']); results.should.have.size(1); results.should.have.property('9dae9304-86a8-4f66-baa3-a1b27dfdd479'); const result = results['9dae9304-86a8-4f66-baa3-a1b27dfdd479']; @@ -302,7 +311,7 @@ describe('inventory impl', function () { cache.get.callCount.should.equal(1); cache.setex.callCount.should.equal(1); - await impl.getSystemProfileBatch(['id']); + await impl.getSystemProfileBatch(REQ, ['id']); cache.get.callCount.should.equal(2); cache.setex.callCount.should.equal(1); }); @@ -331,7 +340,7 @@ describe('inventory impl', function () { headers: {} }); - const results = await impl.getSystemProfileBatch(['id']); + const results = await impl.getSystemProfileBatch(REQ, ['id']); results.should.have.size(1); results.should.have.property('9dae9304-86a8-4f66-baa3-a1b27dfdd479'); const result = results['9dae9304-86a8-4f66-baa3-a1b27dfdd479']; @@ -348,7 +357,7 @@ describe('inventory impl', function () { cache.get.callCount.should.equal(3); cache.setex.callCount.should.equal(1); - await impl.getSystemProfileBatch(['id']); + await impl.getSystemProfileBatch(REQ, ['id']); cache.get.callCount.should.equal(4); cache.setex.callCount.should.equal(1); }); @@ -368,7 +377,7 @@ describe('inventory impl', function () { headers: {} }); - await expect(impl.getSystemProfileBatch(['id'])).resolves.toEqual({}); + await expect(impl.getSystemProfileBatch(REQ, ['id'])).resolves.toEqual({}); http.callCount.should.equal(1); cache.get.callCount.should.equal(1); @@ -380,7 +389,7 @@ describe('inventory impl', function () { test('forwards request headers', async function () { const spy = base.getSandbox().stub(Connector.prototype, 'doHttp').resolves(inventoryResponse([])); - await impl.getSystemsByOwnerId('id'); + await impl.getSystemsByOwnerId(REQ, 'id'); const headers = spy.args[0][0].headers; headers.should.have.size(2); headers.should.have.property('x-rh-identity', 'identity'); @@ -431,7 +440,7 @@ describe('inventory impl', function () { headers: {} }); - const results = await impl.getSystemsByOwnerId('id'); + const results = await impl.getSystemsByOwnerId(REQ, 'id'); results.should.have.size(1); const result = results[0]; result.should.have.property('id', '9615dda7-5868-4957-88ba-c3064c86d332'); @@ -446,7 +455,7 @@ describe('inventory impl', function () { cache.get.callCount.should.equal(1); cache.setex.callCount.should.equal(1); - await impl.getSystemsByOwnerId('id'); + await impl.getSystemsByOwnerId(REQ, 'id'); cache.get.callCount.should.equal(2); cache.setex.callCount.should.equal(1); }); @@ -491,7 +500,7 @@ describe('inventory impl', function () { headers: {} }); - const results = await impl.getSystemsByOwnerId('id'); + const results = await impl.getSystemsByOwnerId(REQ, 'id'); results.should.have.size(1); const result = results[0]; result.should.have.property('id', '9615dda7-5868-4957-88ba-c3064c86d332'); @@ -506,7 +515,7 @@ describe('inventory impl', function () { cache.get.callCount.should.equal(3); cache.setex.callCount.should.equal(1); - await impl.getSystemsByOwnerId('id'); + await impl.getSystemsByOwnerId(REQ, 'id'); cache.get.callCount.should.equal(4); cache.setex.callCount.should.equal(1); }); @@ -526,7 +535,7 @@ describe('inventory impl', function () { headers: {} }); - await expect(impl.getSystemsByOwnerId('id')).resolves.toEqual([]); + await expect(impl.getSystemsByOwnerId(REQ, 'id')).resolves.toEqual([]); http.callCount.should.equal(1); cache.get.callCount.should.equal(1); @@ -555,7 +564,7 @@ describe('inventory impl', function () { total: 1 }); - const result = await impl.getSystemsByInsightsId('3ecd82fb-abdd-471c-9ca2-249c055644b8'); + const result = await impl.getSystemsByInsightsId('3ecd82fb-abdd-471c-9ca2-249c055644b8', REQ); result.should.has.size(2); result[0].should.have.property('insights_id', '3ecd82fb-abdd-471c-9ca2-249c055644b8'); result[1].should.have.property('insights_id', '3ecd82fb-abdd-471c-9ca2-249c055644b8'); diff --git a/src/connectors/inventory/mock.js b/src/connectors/inventory/mock.js index 7ceda72e..928e9efa 100644 --- a/src/connectors/inventory/mock.js +++ b/src/connectors/inventory/mock.js @@ -9,7 +9,7 @@ module.exports = new class extends Connector { super(module); } - getSystemDetailsBatch (systems) { + getSystemDetailsBatch (req, systems) { return Promise.resolve(_(systems) .keyBy() .mapValues(generator.generateSystem) @@ -25,7 +25,7 @@ module.exports = new class extends Connector { .value()); } - getSystemProfileBatch (systems) { + getSystemProfileBatch (req, systems) { return Promise.resolve(_(systems) .keyBy() .mapValues(generator.generateSystemProfile) diff --git a/src/connectors/inventory/xjoin.js b/src/connectors/inventory/xjoin.js index 8e7c398b..53522174 100644 --- a/src/connectors/inventory/xjoin.js +++ b/src/connectors/inventory/xjoin.js @@ -32,14 +32,14 @@ module.exports = new class extends Connector { this.xjoinOwnerIdMetrics = metrics.createConnectorMetric(this.getName(), 'getSystemsByOwnerId'); } - async getSystemDetailsBatch (ids = [], refresh = false, retries = 2) { + async getSystemDetailsBatch (req, ids = [], refresh = false, retries = 2) { if (ids.length === 0) { return {}; } if (ids.length > pageSize) { const chunks = _.chunk(ids, pageSize); - const results = await P.map(chunks, chunk => this.getSystemDetailsBatch(chunk, refresh)); + const results = await P.map(chunks, chunk => this.getSystemDetailsBatch(req, chunk, refresh)); return _.assign({}, ...results); } @@ -47,17 +47,17 @@ module.exports = new class extends Connector { const queryIds = ids.map(identifier => ({id: {eq: identifier}})); try { - response = await queries.runQuery(BATCH_DETAILS_QUERY, { + response = await queries.runQuery(req, BATCH_DETAILS_QUERY, { filter: {OR: queryIds}, order_by: 'display_name', order_how: 'ASC', limit: pageSize, offset: 0 - }, this.getForwardedHeaders(), this.xjoinDetailsMetrics); + }, this.getForwardedHeaders(req), this.xjoinDetailsMetrics); } catch (e) { if (retries > 0) { log.warn({ error: e, ids, retries }, 'Xjoin fetch failed. Retrying'); - return this.getSystemDetailsBatch(ids, true, retries - 1); + return this.getSystemDetailsBatch(req, ids, true, retries - 1); } throw e; @@ -72,14 +72,14 @@ module.exports = new class extends Connector { return validate(transformed); } - async getSystemProfileBatch(ids = [], refresh = false, retries = 2) { + async getSystemProfileBatch(req, ids = [], refresh = false, retries = 2) { if (ids.length === 0) { return {}; } if (ids.length > pageSize) { const chunks = _.chunk(ids, pageSize); - const results = await P.map(chunks, chunk => this.getSystemProfileBatch(chunk, refresh)); + const results = await P.map(chunks, chunk => this.getSystemProfileBatch(req, chunk, refresh)); return _.assign({}, ...results); } @@ -87,17 +87,17 @@ module.exports = new class extends Connector { const queryIds = ids.map(identifier => ({id: {eq: identifier}})); try { - response = await queries.runQuery(BATCH_PROFILE_QUERY, { + response = await queries.runQuery(req, BATCH_PROFILE_QUERY, { filter: {OR: queryIds}, order_by: 'display_name', order_how: 'ASC', limit: pageSize, offset: 0 - }, this.getForwardedHeaders(), this.xjoinSystemProfileMetrics); + }, this.getForwardedHeaders(req), this.xjoinSystemProfileMetrics); } catch (e) { if (retries > 0) { log.warn({ error: e, ids, retries }, 'Xjoin fetch failed. Retrying'); - return this.getSystemProfileBatch(ids, true, retries - 1); + return this.getSystemProfileBatch(req, ids, true, retries - 1); } throw e; @@ -112,10 +112,10 @@ module.exports = new class extends Connector { return transformed; } - async getSystemsByInsightsId (id) { - const response = await queries.runQuery(INSIGHTS_ID_QUERY, { + async getSystemsByInsightsId (id, req) { + const response = await queries.runQuery(req, INSIGHTS_ID_QUERY, { insights_id: id - }, this.getForwardedHeaders(), this.xjoinInsightsIdMetrics); + }, this.getForwardedHeaders(req), this.xjoinInsightsIdMetrics); const transformed = _(response.data.hosts.data) .map(({id, display_name, canonical_facts, account, updated, ansible_host}) => @@ -126,10 +126,10 @@ module.exports = new class extends Connector { return transformed; } - async getSystemsByOwnerId (owner_id) { - const response = await queries.runQuery(OWNER_ID_QUERY, { + async getSystemsByOwnerId (owner_id, req) { + const response = await queries.runQuery(req, OWNER_ID_QUERY, { owner_id - }, this.getForwardedHeaders(), this.xjoinOwnerIdMetrics); + }, this.getForwardedHeaders(req), this.xjoinOwnerIdMetrics); const transformed = _(response.data.hosts.data) .map(({id, display_name, canonical_facts, account, updated, ansible_host}) => @@ -140,8 +140,8 @@ module.exports = new class extends Connector { return transformed; } - async ping () { - const response = queries.runQuery(BATCH_DETAILS_QUERY, {limit: 1}, this.getForwardedHeaders()); + async ping (req) { + const response = queries.runQuery(req, BATCH_DETAILS_QUERY, {limit: 1}, this.getForwardedHeaders(req)); assert(Array.isArray(response.data.hosts.data)); } }(); diff --git a/src/connectors/inventory/xjoin.queries.js b/src/connectors/inventory/xjoin.queries.js index d91552d7..86d9d218 100644 --- a/src/connectors/inventory/xjoin.queries.js +++ b/src/connectors/inventory/xjoin.queries.js @@ -87,7 +87,7 @@ exports.OWNER_ID_QUERY = ` } `; -exports.runQuery = async function (query, variables, headers = {[IDENTITY_HEADER]: createIdentityHeader()}, metrics = false) { +exports.runQuery = async function (req, query, variables, headers = {[IDENTITY_HEADER]: createIdentityHeader()}, metrics = false) { try { const client = new GraphQLClient(xjoinHost, { headers }); const before = new Date(); @@ -101,6 +101,6 @@ exports.runQuery = async function (query, variables, headers = {[IDENTITY_HEADER } catch (e) { log.trace(e, 'dependency error'); metrics && metrics.error.inc(); - throw errors.internal.dependencyError(e, this); + throw errors.internal.dependencyError(req, e, this); } }; diff --git a/src/connectors/inventory/xjoin.unit.js b/src/connectors/inventory/xjoin.unit.js index a8f3c585..c621eccc 100644 --- a/src/connectors/inventory/xjoin.unit.js +++ b/src/connectors/inventory/xjoin.unit.js @@ -6,13 +6,21 @@ const base = require('../../test'); const queries = require('./xjoin.queries'); const { mockRequest } = require('../testUtils'); const RequestError = require('request-promise-core/errors').RequestError; +const REQ = { + headers: { + 'x-rh-identity': 'identity', + 'x-rh-insights-request-id': 'request-id' + }, + identity: { type: 'test' }, + user: { username: 'test', account_number: 'test' } + }; describe('inventory xjoin', function () { beforeEach(mockRequest); test('does not make a call for empty list', async function () { const spy = base.getSandbox().spy(queries, 'runQuery'); - const result = await xjoin.getSystemDetailsBatch([]); + const result = await xjoin.getSystemDetailsBatch(REQ, []); result.should.be.empty(); spy.called.should.be.false(); @@ -39,8 +47,8 @@ describe('inventory xjoin', function () { } }); - await xjoin.getSystemDetailsBatch(['22cd8e39-13bb-4d02-8316-84b850dc5136']); - const headers = spy.args[0][2]; + await xjoin.getSystemDetailsBatch(REQ, ['22cd8e39-13bb-4d02-8316-84b850dc5136']); + const headers = spy.args[0][3]; headers.should.have.size(2); headers.should.have.property('x-rh-identity', 'identity'); headers.should.have.property('x-rh-insights-request-id', 'request-id'); @@ -67,7 +75,7 @@ describe('inventory xjoin', function () { } }); - const results = await xjoin.getSystemDetailsBatch(['22cd8e39-13bb-4d02-8316-84b850dc5136']); + const results = await xjoin.getSystemDetailsBatch(REQ, ['22cd8e39-13bb-4d02-8316-84b850dc5136']); results.should.have.size(1); results.should.have.property('22cd8e39-13bb-4d02-8316-84b850dc5136'); const result = results['22cd8e39-13bb-4d02-8316-84b850dc5136']; @@ -104,7 +112,7 @@ describe('inventory xjoin', function () { } }); - const results = await xjoin.getSystemDetailsBatch(['22cd8e39-13bb-4d02-8316-84b850dc5136']); + const results = await xjoin.getSystemDetailsBatch(REQ, ['22cd8e39-13bb-4d02-8316-84b850dc5136']); results.should.have.size(1); results.should.have.property('22cd8e39-13bb-4d02-8316-84b850dc5136'); const result = results['22cd8e39-13bb-4d02-8316-84b850dc5136']; @@ -127,7 +135,7 @@ describe('inventory xjoin', function () { } }); - await expect(xjoin.getSystemDetailsBatch(['22cd8e39-13bb-4d02-8316-84b850dc5136'])).resolves.toEqual({}); + await expect(xjoin.getSystemDetailsBatch(REQ, ['22cd8e39-13bb-4d02-8316-84b850dc5136'])).resolves.toEqual({}); http.callCount.should.equal(1); }); @@ -154,7 +162,7 @@ describe('inventory xjoin', function () { const ids = Array(250).fill(0).map((value, key) => `84762eb3-0bbb-4bd8-ab11-f420c50e9${String(key).padStart(3, '0')}`); - const result = await xjoin.getSystemDetailsBatch(ids); + const result = await xjoin.getSystemDetailsBatch(REQ, ids); result.should.have.size(250); ids.forEach(id => _.has(result, id).should.be.true()); }); @@ -162,7 +170,7 @@ describe('inventory xjoin', function () { describe('getSystemProfileBatch', function () { test('does not make a call for empty list', async function () { const spy = base.getSandbox().spy(queries, 'runQuery'); - const result = await xjoin.getSystemProfileBatch([]); + const result = await xjoin.getSystemProfileBatch(REQ, []); result.should.be.empty(); spy.called.should.be.false(); @@ -188,8 +196,8 @@ describe('inventory xjoin', function () { } }); - await xjoin.getSystemProfileBatch(['9dae9304-86a8-4f66-baa3-a1b27dfdd479']); - const headers = spy.args[0][2]; + await xjoin.getSystemProfileBatch(REQ, ['9dae9304-86a8-4f66-baa3-a1b27dfdd479']); + const headers = spy.args[0][3]; headers.should.have.size(2); headers.should.have.property('x-rh-identity', 'identity'); headers.should.have.property('x-rh-insights-request-id', 'request-id'); @@ -215,7 +223,7 @@ describe('inventory xjoin', function () { } }); - const results = await xjoin.getSystemProfileBatch(['9dae9304-86a8-4f66-baa3-a1b27dfdd479']); + const results = await xjoin.getSystemProfileBatch(REQ, ['9dae9304-86a8-4f66-baa3-a1b27dfdd479']); results.should.have.size(1); results.should.have.property('9dae9304-86a8-4f66-baa3-a1b27dfdd479'); const result = results['9dae9304-86a8-4f66-baa3-a1b27dfdd479']; @@ -251,7 +259,7 @@ describe('inventory xjoin', function () { } }); - const results = await xjoin.getSystemProfileBatch(['9dae9304-86a8-4f66-baa3-a1b27dfdd479']); + const results = await xjoin.getSystemProfileBatch(REQ, ['9dae9304-86a8-4f66-baa3-a1b27dfdd479']); results.should.have.size(1); results.should.have.property('9dae9304-86a8-4f66-baa3-a1b27dfdd479'); const result = results['9dae9304-86a8-4f66-baa3-a1b27dfdd479']; @@ -274,7 +282,7 @@ describe('inventory xjoin', function () { } }); - await expect(xjoin.getSystemProfileBatch(['9dae9304-86a8-4f66-baa3-a1b27dfdd479'])).resolves.toEqual({}); + await expect(xjoin.getSystemProfileBatch(REQ, ['9dae9304-86a8-4f66-baa3-a1b27dfdd479'])).resolves.toEqual({}); http.callCount.should.equal(1); }); }); @@ -310,7 +318,7 @@ describe('inventory xjoin', function () { } }); - const result = await xjoin.getSystemsByInsightsId('d46c20e5-8f10-43ed-94e4-6c467a581ec7'); + const result = await xjoin.getSystemsByInsightsId('d46c20e5-8f10-43ed-94e4-6c467a581ec7', REQ); result.should.has.size(2); result[0].should.have.property('id', '22cd8e39-13bb-4d02-8316-84b850dc5136'); result[0].should.have.property('account', 'test'); @@ -357,7 +365,7 @@ describe('inventory xjoin', function () { } }); - const result = await xjoin.getSystemsByOwnerId('d46c20e5-8f10-43ed-94e4-6c467a581ec7'); + const result = await xjoin.getSystemsByOwnerId('d46c20e5-8f10-43ed-94e4-6c467a581ec7', REQ); result.should.has.size(2); result[0].should.have.property('id', '22cd8e39-13bb-4d02-8316-84b850dc5136'); result[0].should.have.property('account', 'test'); diff --git a/src/connectors/patchman/impl.js b/src/connectors/patchman/impl.js index 062baf5e..4e008eff 100644 --- a/src/connectors/patchman/impl.js +++ b/src/connectors/patchman/impl.js @@ -13,16 +13,16 @@ module.exports = new class extends Connector { this.metrics = metrics.createConnectorMetric(this.getName()); } - getErratum (id, refresh = false) { + getErratum (req, id, refresh = false) { const uri = new URI(host); uri.path('/api/patch/v3/advisories'); uri.segment(id); - return this.doHttp({ + return this.doHttp(req, { uri: uri.toString(), method: 'GET', json: true, - headers: this.getForwardedHeaders() + headers: this.getForwardedHeaders(req) }, { refresh, @@ -32,8 +32,8 @@ module.exports = new class extends Connector { ).then(res => _.get(res, ['data'], null)); } - async ping () { - const result = await this.getErratum('RHBA-2019:0689', true); + async ping (req) { + const result = await this.getErratum(req, 'RHBA-2019:0689', true); assert(result.id === 'RHBA-2019:0689'); } }(); diff --git a/src/connectors/patchman/impl.unit.js b/src/connectors/patchman/impl.unit.js index 730bb009..d6849691 100644 --- a/src/connectors/patchman/impl.unit.js +++ b/src/connectors/patchman/impl.unit.js @@ -7,6 +7,15 @@ const base = require('../../test'); const { mockRequest, mockCache } = require('../testUtils'); const request = require('../../util/request'); +const REQ = { + headers: { + 'x-rh-identity': 'identity', + 'x-rh-insights-request-id': 'request-id' + }, + identity: { type: 'test' }, + user: { username: 'test', account_number: 'test' } +}; + describe('patchman impl', function () { beforeEach(mockRequest); @@ -37,7 +46,7 @@ describe('patchman impl', function () { headers: {} }); - const result = await impl.getErratum('RHBA-2019:2871'); + const result = await impl.getErratum(REQ, 'RHBA-2019:2871'); result.should.have.property('id', 'RHBA-2019:2871'); result.should.have.property('attributes'); result.attributes.should.have.property('description', 'The tzdata packages contain data files with rules for various time zones.\n\nThe tzdata packages have been updated to version 2019c, which addresses recent\ntime zone changes. Notably:\n\n* Fiji will observe the daylight saving time (DST) from November 10, 2019 to January 12, 2020. \n\n* Norfolk Island will start to observe Australian-style DST on November 06, 2019.\n(BZ#1751551, BZ#1751737, BZ#1751402, BZ#1751404)\n\nUsers of tzdata are advised to upgrade to these updated packages, which add\nthese enhancements.'); @@ -51,7 +60,7 @@ describe('patchman impl', function () { cache.get.callCount.should.equal(1); cache.setex.callCount.should.equal(1); - await impl.getErratum('RHBA-2019:2871'); + await impl.getErratum(REQ, 'RHBA-2019:2871'); cache.get.callCount.should.equal(2); cache.setex.callCount.should.equal(1); }); @@ -67,7 +76,7 @@ describe('patchman impl', function () { headers: {} }); - await expect(impl.getErratum('RHBA-2019:2872')).resolves.toBeNull(); + await expect(impl.getErratum(REQ, 'RHBA-2019:2872')).resolves.toBeNull(); http.callCount.should.equal(1); cache.get.callCount.should.equal(1); diff --git a/src/connectors/patchman/mock.js b/src/connectors/patchman/mock.js index c04a13ac..2e6d79f3 100644 --- a/src/connectors/patchman/mock.js +++ b/src/connectors/patchman/mock.js @@ -67,11 +67,11 @@ module.exports = new class extends Connector { super(module); } - getErratum (id) { + getErratum (req, id) { return P.resolve(ERRATA[id]); } - ping () { - return this.getErratum('RHBA-2019:4105'); + ping (req) { + return this.getErratum(req, 'RHBA-2019:4105'); } }(); diff --git a/src/connectors/rbac/impl.js b/src/connectors/rbac/impl.js index 5c96198d..a30e9722 100644 --- a/src/connectors/rbac/impl.js +++ b/src/connectors/rbac/impl.js @@ -15,18 +15,18 @@ module.exports = new class extends Connector { this.accessMetrics = metrics.createConnectorMetric(this.getName(), 'getRemediationsAccess'); } - async getRemediationsAccess (retries = 2) { + async getRemediationsAccess (req, retries = 2) { const uri = new URI(host); uri.path('/api/rbac/v1/access/'); uri.query({application: 'remediations'}); try { - const result = await this.doHttp ({ + const result = await this.doHttp (req, { uri: uri.toString(), method: 'GET', json: true, rejectUnauthorized: !insecure, - headers: this.getForwardedHeaders() + headers: this.getForwardedHeaders(req) }, false, this.accessMetrics); if (_.isEmpty(result)) { @@ -37,15 +37,15 @@ module.exports = new class extends Connector { } catch (e) { if (retries > 0) { log.warn({ error: e, retries }, 'RBAC access fetch failed. Retrying'); - return this.getRemediationsAccess(retries - 1); + return this.getRemediationsAccess(req, retries - 1); } throw e; } } - async ping () { - const result = await this.getRemediationsAccess(); + async ping (req) { + const result = await this.getRemediationsAccess(req); assert(result !== null); } }(); diff --git a/src/connectors/rbac/impl.unit.js b/src/connectors/rbac/impl.unit.js index 791951f9..fab33aeb 100644 --- a/src/connectors/rbac/impl.unit.js +++ b/src/connectors/rbac/impl.unit.js @@ -8,6 +8,15 @@ const request = require('../../util/request'); const errors = require('../../errors'); const RequestError = require('request-promise-core/errors').RequestError; +const REQ = { + headers: { + 'x-rh-identity': 'identity', + 'x-rh-insights-request-id': 'request-id' + }, + identity: { type: 'test' }, + user: { username: 'test', account_number: 'test' } +}; + describe('rbac impl', function () { beforeEach(mockRequest); @@ -37,7 +46,7 @@ describe('rbac impl', function () { headers: {} }); - const result = await impl.getRemediationsAccess(); + const result = await impl.getRemediationsAccess(REQ); result.meta.should.have.property('count', 1); result.meta.should.have.property('limit', 10); result.meta.should.have.property('offset', 0); @@ -94,7 +103,7 @@ describe('rbac impl', function () { headers: {} }); - const result = await impl.getRemediationsAccess(); + const result = await impl.getRemediationsAccess(REQ); result.meta.should.have.property('count', 1); result.meta.should.have.property('limit', 10); result.meta.should.have.property('offset', 0); @@ -124,7 +133,7 @@ describe('rbac impl', function () { test('returns null when operation failed', async function () { base.getSandbox().stub(Connector.prototype, 'doHttp').resolves([]); - await expect(impl.getRemediationsAccess()).resolves.toBeNull(); + await expect(impl.getRemediationsAccess(REQ)).resolves.toBeNull(); }); test('ping', async function () { @@ -150,16 +159,16 @@ describe('rbac impl', function () { } ); - await impl.ping(); + await impl.ping(REQ); }); test('access error handling', async function () { base.mockRequestError(); - await expect(impl.getRemediationsAccess()).rejects.toThrow(errors.DependencyError); + await expect(impl.getRemediationsAccess(REQ)).rejects.toThrow(errors.DependencyError); }); test('status code handling', async function () { base.mockRequestStatusCode(); - await expect(impl.getRemediationsAccess()).rejects.toThrow(errors.DependencyError); + await expect(impl.getRemediationsAccess(REQ)).rejects.toThrow(errors.DependencyError); }); }); diff --git a/src/connectors/receptor/impl.js b/src/connectors/receptor/impl.js index 01cd688b..4736ff58 100644 --- a/src/connectors/receptor/impl.js +++ b/src/connectors/receptor/impl.js @@ -15,16 +15,16 @@ module.exports = new class extends Connector { this.statusMetrics = metrics.createConnectorMetric(this.getName(), 'postInitialRequest'); } - async getConnectionStatus (account_num, node) { + async getConnectionStatus (req, account_num, node) { const uri = new URI(host); uri.path('/connection/status'); - const result = await this.doHttp ({ + const result = await this.doHttp (req, { uri: uri.toString(), method: 'POST', json: true, rejectUnauthorized: !insecure, - headers: this.getForwardedHeaders(), + headers: this.getForwardedHeaders(req), body: { account: account_num, node_id: node @@ -38,16 +38,16 @@ module.exports = new class extends Connector { return result; } - async postInitialRequest (receptorWorkRequest) { + async postInitialRequest (req, receptorWorkRequest) { const uri = new URI(host); uri.path('/job'); - const result = await this.doHttp ({ + const result = await this.doHttp (req, { uri: uri.toString(), method: 'POST', json: true, rejectUnauthorized: !insecure, - headers: this.getForwardedHeaders(), + headers: this.getForwardedHeaders(req), body: receptorWorkRequest }, false, this.statusMetrics); @@ -58,7 +58,7 @@ module.exports = new class extends Connector { return result; } - async ping () { - await this.getConnectionStatus('540155', 'node-a'); + async ping (req) { + await this.getConnectionStatus(req, '540155', 'node-a'); } }(); diff --git a/src/connectors/receptor/impl.unit.js b/src/connectors/receptor/impl.unit.js index db1417f5..0865c22b 100644 --- a/src/connectors/receptor/impl.unit.js +++ b/src/connectors/receptor/impl.unit.js @@ -14,6 +14,15 @@ const RECEPTORWORKREQUEST = { directive: 'receptor_satellite:execute' }; +const REQ = { + headers: { + 'x-rh-identity': 'identity', + 'x-rh-insights-request-id': 'request-id' + }, + identity: { type: 'test' }, + user: { username: 'test', account_number: 'test' } +}; + describe('receptor impl', function () { beforeEach(mockRequest); @@ -25,7 +34,7 @@ describe('receptor impl', function () { headers: {} }); - const result = await impl.getConnectionStatus('540155', 'node-a'); + const result = await impl.getConnectionStatus(REQ, '540155', 'node-a'); result.should.have.property('status', 'connected'); const options = http.args[0][0]; @@ -42,22 +51,22 @@ describe('receptor impl', function () { test('returns null when account or node is incorrect', async function () { base.getSandbox().stub(Connector.prototype, 'doHttp').resolves([]); - await expect(impl.getConnectionStatus('540155', 'node-a')).resolves.toBeNull(); + await expect(impl.getConnectionStatus(REQ, '540155', 'node-a')).resolves.toBeNull(); }); test('ping', async function () { base.getSandbox().stub(Connector.prototype, 'doHttp').resolves({status: 'connected'}); - await impl.ping(); + await impl.ping(REQ); }); test('connection error handling', async function () { base.mockRequestError(); - await expect(impl.getConnectionStatus('540155', 'node-a')).rejects.toThrow(errors.DependencyError); + await expect(impl.getConnectionStatus(REQ, '540155', 'node-a')).rejects.toThrow(errors.DependencyError); }); test('status code handling', async function () { base.mockRequestStatusCode(); - await expect(impl.getConnectionStatus('540155', 'node-a')).rejects.toThrow(errors.DependencyError); + await expect(impl.getConnectionStatus(REQ, '540155', 'node-a')).rejects.toThrow(errors.DependencyError); }); }); @@ -69,7 +78,7 @@ describe('receptor impl', function () { headers: {} }); - const result = await impl.postInitialRequest(RECEPTORWORKREQUEST); + const result = await impl.postInitialRequest(REQ, RECEPTORWORKREQUEST); result.should.have.property('id', '355986a3-5f37-40f7-8f36-c3ac928ce190'); const options = http.args[0][0]; @@ -87,17 +96,17 @@ describe('receptor impl', function () { test('returns null receptorWorkRequest is incorrect', async function () { base.getSandbox().stub(Connector.prototype, 'doHttp').resolves([]); - await expect(impl.postInitialRequest(RECEPTORWORKREQUEST)).resolves.toBeNull(); + await expect(impl.postInitialRequest(REQ, RECEPTORWORKREQUEST)).resolves.toBeNull(); }); test('connection error handling receptorWorkRequest', async function () { base.mockRequestError(); - await expect(impl.postInitialRequest(RECEPTORWORKREQUEST)).rejects.toThrow(errors.DependencyError); + await expect(impl.postInitialRequest(REQ, RECEPTORWORKREQUEST)).rejects.toThrow(errors.DependencyError); }); test('status code handling receptorWorkRequest', async function () { base.mockRequestStatusCode(); - await expect(impl.postInitialRequest(RECEPTORWORKREQUEST)).rejects.toThrow(errors.DependencyError); + await expect(impl.postInitialRequest(REQ, RECEPTORWORKREQUEST)).rejects.toThrow(errors.DependencyError); }); }); }); diff --git a/src/connectors/sources/impl.js b/src/connectors/sources/impl.js index cfc68dcb..e9087b2f 100644 --- a/src/connectors/sources/impl.js +++ b/src/connectors/sources/impl.js @@ -17,8 +17,8 @@ module.exports = new class extends Connector { this.endpointMetrics = metrics.createConnectorMetric(this.getName(), 'getEndpoints'); this.rhcConnectionsMetrics = metrics.createConnectorMetric(this.getName(), 'getRHCConnections'); } - - async findSources (ids) { +// Do we need this? + async findSources (req, ids) { // TODO: Chunk this is list of ids is long if (ids.length === 0) { @@ -32,12 +32,12 @@ module.exports = new class extends Connector { 'filter[source_ref][eq][]': ids }); - const result = await this.doHttp({ + const result = await this.doHttp(req, { uri: uri.toString(), method: 'GET', json: true, rejectUnauthorized: !insecure, - headers: this.getForwardedHeaders() + headers: this.getForwardedHeaders(req) }, false, this.sourcesMetrics); assert(result.meta.count <= result.meta.limit); @@ -49,15 +49,16 @@ module.exports = new class extends Connector { .value(); } - async getEndpoints (id) { +// Do we need this? + async getEndpoints (id, req) { const uri = this.buildUri(host, 'sources', 'v2.0', 'sources', String(id), 'endpoints'); - const result = await this.doHttp({ + const result = await this.doHttp(req, { uri: uri.toString(), method: 'GET', json: true, rejectUnauthorized: !insecure, - headers: this.getForwardedHeaders() + headers: this.getForwardedHeaders(req) }, false, this.endpointMetrics); if (!result) { @@ -68,30 +69,32 @@ module.exports = new class extends Connector { return result.data; } - async getSourceInfo (ids) { - const sources = await this.findSources(ids); +// Not being used??? + async getSourceInfo (ids, req) { + const sources = await this.findSources(req, ids); await P.map(_.values(sources), async source => { if (source === null) { return source; } - source.endpoints = await this.getEndpoints(source.id); + source.endpoints = await this.getEndpoints(source.id, req); return source; }); return sources; } - async getRHCConnections (id) { + + async getRHCConnections (id, req) { const uri = this.buildUri(host, 'sources', 'v3.1', 'sources', String(id), 'rhc_connections'); - const result = await this.doHttp({ + const result = await this.doHttp(req, { uri: uri.toString(), method: 'GET', json: true, rejectUnauthorized: !insecure, - headers: this.getForwardedHeaders() + headers: this.getForwardedHeaders(req) }, false, this.rhcConnectionsMetrics); if (!result) { @@ -102,7 +105,7 @@ module.exports = new class extends Connector { return result.data; } - async ping () { - await this.findSources('test'); + async ping (req) { + await this.findSources(req, 'test'); } }(); diff --git a/src/connectors/sources/impl.unit.js b/src/connectors/sources/impl.unit.js index d1a878d6..cb3a957e 100644 --- a/src/connectors/sources/impl.unit.js +++ b/src/connectors/sources/impl.unit.js @@ -5,6 +5,15 @@ const base = require('../../test'); const { mockRequest } = require('../testUtils'); const request = require('../../util/request'); +const REQ = { + headers: { + 'x-rh-identity': 'identity', + 'x-rh-insights-request-id': 'request-id' + }, + identity: { type: 'test' }, + user: { username: 'test', account_number: 'test' } +}; + describe('sources impl', function () { beforeEach(mockRequest); @@ -39,7 +48,7 @@ describe('sources impl', function () { headers: {} }); - const results = await impl.findSources([ + const results = await impl.findSources(REQ, [ '72e67490-010a-4c69-a445-97017ef2a696', 'de91d755-e1da-4ae2-b173-7d56f5df7c86' ]); results.should.have.size(2); @@ -80,7 +89,7 @@ describe('sources impl', function () { headers: {} }); - const results = await impl.getEndpoints(['1231']); + const results = await impl.getEndpoints(['1231'], REQ); results.should.have.size(1); results[0].should.have.property('receptor_node', 'dsasd'); @@ -97,7 +106,7 @@ describe('sources impl', function () { headers: {} }); - const results = await impl.getEndpoints(['1231']); + const results = await impl.getEndpoints(['1231'], REQ); (results === null).should.be.true(); }); }); @@ -165,7 +174,7 @@ describe('sources impl', function () { const results = await impl.getSourceInfo([ '72e67490-010a-4c69-a445-97017ef2a696', 'de91d755-e1da-4ae2-b173-7d56f5df7c86' - ]); + ], REQ); results.should.have.size(2); results.should.have.property('72e67490-010a-4c69-a445-97017ef2a696'); const first = results['72e67490-010a-4c69-a445-97017ef2a696']; @@ -182,7 +191,7 @@ describe('sources impl', function () { test('does not call anything on an empty list', async function () { const spy = base.getSandbox().spy(request, 'run'); - const results = await impl.getSourceInfo([]); + const results = await impl.getSourceInfo([], REQ); results.should.be.empty(); spy.callCount.should.equal(0); }); @@ -211,7 +220,7 @@ describe('sources impl', function () { headers: {} }); - const results = await impl.getRHCConnections('5'); + const results = await impl.getRHCConnections('5', REQ); results.should.have.size(1); const result = results[0]; @@ -232,7 +241,7 @@ describe('sources impl', function () { headers: {} }); - const results = await impl.getRHCConnections('1231'); + const results = await impl.getRHCConnections('1231', REQ); (results === null).should.be.true(); }); }); diff --git a/src/connectors/sources/mock.js b/src/connectors/sources/mock.js index cb8f18fb..1c7cae73 100644 --- a/src/connectors/sources/mock.js +++ b/src/connectors/sources/mock.js @@ -106,18 +106,18 @@ module.exports = new class extends Connector { throw new Error('unsupported'); } - async getSourceInfo (ids) { + async getSourceInfo (ids, req) { return _(ids) .keyBy() .mapValues(id => _.get(SOURCES, id, null)) .value(); } - async getRHCConnections (id) { + async getRHCConnections (id, req) { return [_.get(RHC_CONNECTIONS, id, null)]; } - async ping () { - await this.findSources('test'); + async ping (req) { + await this.findSources(req, 'test'); } }(); diff --git a/src/connectors/ssg/compliance.js b/src/connectors/ssg/compliance.js index d177827a..3ccf2722 100644 --- a/src/connectors/ssg/compliance.js +++ b/src/connectors/ssg/compliance.js @@ -19,7 +19,7 @@ module.exports = new class extends Connector { this.metrics = metrics.createConnectorMetric(this.getName()); } - async getTemplate (id, refresh = false) { + async getTemplate (req, id, refresh = false) { const p = new Promise(function(resolve, reject) { PROMISES.push({resolve, reject}); }); @@ -27,7 +27,7 @@ module.exports = new class extends Connector { if (_.isEmpty(REQUESTS)) { REQUESTS.push(id); - setTimeout(() => {this.flush(refresh);}, 200); + setTimeout(() => {this.flush(req, refresh);}, 200); } else { REQUESTS.push(id); } @@ -35,25 +35,25 @@ module.exports = new class extends Connector { return p; } - async flush(refresh = false) { + async flush(req, refresh = false) { const copyIds = REQUESTS; const copyPromises = PROMISES; REQUESTS = []; PROMISES = []; - const req = cls.getReq(); + // const req = cls.getReq(); const uri = this.buildUri(host, 'compliance', 'rules'); uri.segment(copyIds.join()); try { - const results = await this.doHttp({ + const results = await this.doHttp(req, { uri: uri.toString(), method: 'POST', json: true, body: { copyIds }, rejectUnauthorized: !insecure, headers: { - ...this.getForwardedHeaders() + ...this.getForwardedHeaders(req) } }, { @@ -72,8 +72,8 @@ module.exports = new class extends Connector { } } - async ping () { - const result = await this.getRule('xccdf_org.ssgproject.content_rule_sshd_disable_root_login', true); + async ping (req) { + const result = await this.getRule(req, 'xccdf_org.ssgproject.content_rule_sshd_disable_root_login', true); assert(result !== null); } }; diff --git a/src/connectors/ssg/compliance.unit.js b/src/connectors/ssg/compliance.unit.js index f8090105..d66e6786 100644 --- a/src/connectors/ssg/compliance.unit.js +++ b/src/connectors/ssg/compliance.unit.js @@ -10,6 +10,15 @@ const base = require('../../test'); const { mockRequest } = require('../testUtils'); const request = require('../../util/request'); +const REQ = { + headers: { + 'x-rh-identity': 'identity', + 'x-rh-insights-request-id': 'request-id' + }, + identity: { type: 'test' }, + user: { username: 'test', account_number: 'test' } +}; + describe('compliance impl', function () { beforeEach(mockRequest); @@ -25,7 +34,7 @@ describe('compliance impl', function () { } }); - const { template, version } = await compliance.getTemplate('rhel7|standard|xccdf_org.ssgproject.content_rule_service_autofs_disabled'); + const { template, version } = await compliance.getTemplate(REQ, 'rhel7|standard|xccdf_org.ssgproject.content_rule_service_autofs_disabled'); version.should.equal('unit'); expect(template).toMatchSnapshot(); @@ -48,8 +57,8 @@ describe('compliance impl', function () { }); const pending = [ - compliance.getTemplate('rhel7|standard|xccdf_org.ssgproject.content_rule_service_autofs_disabled'), - compliance.getTemplate('rhel7|standard|xccdf_org.ssgproject.content_rule_service_rsylog_enabled.yml') + compliance.getTemplate(REQ, 'rhel7|standard|xccdf_org.ssgproject.content_rule_service_autofs_disabled'), + compliance.getTemplate(REQ, 'rhel7|standard|xccdf_org.ssgproject.content_rule_service_rsylog_enabled.yml') ]; const results = await P.all(pending); diff --git a/src/connectors/ssg/impl.js b/src/connectors/ssg/impl.js index 404d7789..219e8d13 100644 --- a/src/connectors/ssg/impl.js +++ b/src/connectors/ssg/impl.js @@ -15,7 +15,7 @@ module.exports = new class extends Connector { this.metrics = metrics.createConnectorMetric(this.getName()); } - getTemplate (platform, profile, rule) { + getTemplate (req, platform, profile, rule) { trace.enter('ssg_impl.getTemplate'); const uri = new URI(host); uri.segment('/playbooks'); @@ -26,8 +26,9 @@ module.exports = new class extends Connector { trace.event(`Fetching: ${platform}|${profile}|${rule}`); - const result = this.doHttp( - { uri: uri.toString() }, + const result = this.doHttp(req, { + uri: uri.toString() + }, { key: `remediations|http-cache|ssg|${uri.path()}`, revalidationInterval @@ -42,8 +43,8 @@ module.exports = new class extends Connector { return result; } - async ping () { - const result = await this.getTemplate('rhel7', 'pci-dss', 'file_owner_etc_passwd'); + async ping (req) { + const result = await this.getTemplate(req, 'rhel7', 'pci-dss', 'file_owner_etc_passwd'); assert(result !== null); } }(); diff --git a/src/connectors/ssg/impl.unit.js b/src/connectors/ssg/impl.unit.js index a65ba026..10388c3e 100644 --- a/src/connectors/ssg/impl.unit.js +++ b/src/connectors/ssg/impl.unit.js @@ -7,6 +7,15 @@ const base = require('../../test'); const { mockRequest } = require('../testUtils'); const request = require('../../util/request'); +const REQ = { + headers: { + 'x-rh-identity': 'identity', + 'x-rh-insights-request-id': 'request-id' + }, + identity: { type: 'test' }, + user: { username: 'test', account_number: 'test' } +}; + describe('ssg impl', function () { beforeEach(mockRequest); @@ -22,7 +31,7 @@ describe('ssg impl', function () { } }); - const { template, version } = await impl.getTemplate('rhel7', 'standard', 'sshd_disable_root_login'); + const { template, version } = await impl.getTemplate(REQ, 'rhel7', 'standard', 'sshd_disable_root_login'); version.should.equal('unit'); expect(template).toMatchSnapshot(); http.callCount.should.equal(1); diff --git a/src/connectors/ssg/mock.js b/src/connectors/ssg/mock.js index af25ed30..0fa6f654 100644 --- a/src/connectors/ssg/mock.js +++ b/src/connectors/ssg/mock.js @@ -17,7 +17,7 @@ module.exports = new class extends Connector { super(module); } - async getTemplate (platform, profile, rule) { + async getTemplate (req, platform, profile, rule) { switch (`${platform}|${profile}|${rule}`) { case 'rhel7|pci-dss|disable_prelink': return read('pci-dss', 'disable_prelink'); @@ -41,7 +41,7 @@ module.exports = new class extends Connector { } } - ping () { + ping (req) { return true; } }(); diff --git a/src/connectors/testUtils.js b/src/connectors/testUtils.js index 7a5c2453..21f43bc1 100644 --- a/src/connectors/testUtils.js +++ b/src/connectors/testUtils.js @@ -7,19 +7,30 @@ const cls = require('../util/cls'); const cache = require('../cache'); const config = require('../config'); -exports.mockRequest = function (headers = { - 'x-rh-identity': 'identity', - 'x-rh-insights-request-id': 'request-id' -}, user = { - username: 'test', - account_number: 'test' -}, identity = {type: 'test'}) { - base.getSandbox().stub(cls, 'getReq').returns({ - headers, - identity, - user - }); +exports.mockRequest = function () { + const request = { + headers: { + 'x-rh-identity': 'identity', + 'x-rh-insights-request-id': 'request-id' + }, + identity: { type: 'test' }, + user: { username: 'test', account_number: 'test' } + } + return request }; +// headers = { +// 'x-rh-identity': 'identity', +// 'x-rh-insights-request-id': 'request-id' +// }, user = { +// username: 'test', +// account_number: 'test' +// }, identity = {type: 'test'}) { +// base.getSandbox().stub(cls, 'getReq').returns({ +// headers, +// identity, +// user +// }); +// }; exports.mockCache = function () { const data = {}; diff --git a/src/connectors/users/impl.js b/src/connectors/users/impl.js index 75c6a83a..fee3fcc4 100644 --- a/src/connectors/users/impl.js +++ b/src/connectors/users/impl.js @@ -21,11 +21,11 @@ module.exports = new class extends Connector { this.metrics = metrics.createConnectorMetric(this.getName()); } - async getUser (id, refresh = false) { + async getUser (req, id, refresh = false) { const uri = new URI(host); uri.path('/v1/users'); - const result = await this.doHttp({ + const result = await this.doHttp(req, { uri: uri.toString(), method: 'POST', json: true, @@ -36,7 +36,7 @@ module.exports = new class extends Connector { 'x-rh-apitoken': auth, 'x-rh-insights-env': env, 'x-rh-clientid': clientId, - ...this.getForwardedHeaders(false) + ...this.getForwardedHeaders(req, false) }, body: { users: [id] @@ -55,16 +55,16 @@ module.exports = new class extends Connector { return result[0]; } - async ping () { - const req = cls.getReq(); + async ping (req) { + // const req = cls.getReq(); if (req.identity.type === 'User') { - const result = await this.getUser(req.identity.user.username, true); + const result = await this.getUser(req, req.identity.user.username, true); assert(result.username === req.identity.user.username); } else { - const result = await this.getUser(testAccount, true); + const result = await this.getUser(req, testAccount, true); assert(result.username === testAccount); } } diff --git a/src/connectors/users/impl.unit.js b/src/connectors/users/impl.unit.js index 0fef6a4b..aa177550 100644 --- a/src/connectors/users/impl.unit.js +++ b/src/connectors/users/impl.unit.js @@ -23,6 +23,15 @@ const MOCK_USER = { is_internal: true }; +const REQ = { + headers: { + 'x-rh-identity': 'identity', + 'x-rh-insights-request-id': 'request-id' + }, + identity: { type: 'test' }, + user: { username: 'test', account_number: 'test' } +}; + describe('users impl', function () { beforeEach(mockRequest); @@ -34,7 +43,7 @@ describe('users impl', function () { headers: {} }); - const result = await impl.getUser('someUsername'); + const result = await impl.getUser(REQ, 'someUsername'); result.should.have.property('username', 'someUsername'); result.should.have.property('first_name', 'Jozef'); result.should.have.property('last_name', 'Hartinger'); @@ -50,12 +59,12 @@ describe('users impl', function () { test('returns null when user does not exist', async function () { base.getSandbox().stub(Connector.prototype, 'doHttp').resolves([]); - await expect(impl.getUser('someUsername')).resolves.toBeNull(); + await expect(impl.getUser(REQ, 'someUsername')).resolves.toBeNull(); }); test('ping', async function () { base.getSandbox().stub(Connector.prototype, 'doHttp').resolves([MOCK_USER]); - await impl.ping(); + await impl.ping(REQ); }); test('caches retrieved info', async function () { @@ -67,13 +76,13 @@ describe('users impl', function () { const cache = mockCache(); - await impl.getUser('someUsername'); + await impl.getUser(REQ, 'someUsername'); http.callCount.should.equal(1); cache.get.callCount.should.equal(1); cache.get.args[0][0].should.equal('remediations|http-cache|users|someUsername'); cache.setex.callCount.should.equal(1); - await impl.getUser('someUsername'); + await impl.getUser(REQ, 'someUsername'); http.callCount.should.equal(1); cache.get.callCount.should.equal(2); cache.get.args[1][0].should.equal('remediations|http-cache|users|someUsername'); @@ -89,7 +98,7 @@ describe('users impl', function () { const cache = mockCache(); - await impl.getUser('non-existent-user'); + await impl.getUser(REQ, 'non-existent-user'); http.callCount.should.equal(1); cache.get.callCount.should.equal(1); cache.get.args[0][0].should.equal('remediations|http-cache|users|non-existent-user'); @@ -98,11 +107,11 @@ describe('users impl', function () { test('connection error handling', async function () { base.mockRequestError(); - await expect(impl.getUser('someUsername')).rejects.toThrow(errors.DependencyError); + await expect(impl.getUser(REQ, 'someUsername')).rejects.toThrow(errors.DependencyError); }); test('status code handling', async function () { base.mockRequestStatusCode(); - await expect(impl.getUser('someUsername')).rejects.toThrow(errors.DependencyError); + await expect(impl.getUser(REQ, 'someUsername')).rejects.toThrow(errors.DependencyError); }); }); diff --git a/src/connectors/users/mock.js b/src/connectors/users/mock.js index f019df95..68aa6f95 100644 --- a/src/connectors/users/mock.js +++ b/src/connectors/users/mock.js @@ -72,7 +72,7 @@ module.exports = new class extends Connector { super(module); } - async getUser (id) { + async getUser (req, id) { return MOCK_USERS[id]; } diff --git a/src/connectors/vmaas/mock.js b/src/connectors/vmaas/mock.js index 927085d6..e14c3d68 100644 --- a/src/connectors/vmaas/mock.js +++ b/src/connectors/vmaas/mock.js @@ -52,11 +52,11 @@ module.exports = new class extends Connector { super(module); } - getErratum (id) { + getErratum (req, id) { return P.resolve(ERRATA[id]); } - getCve (id) { + getCve (req, id) { return P.resolve(CVES[id]); } diff --git a/src/connectors/vmaas/vmaas.integration.js b/src/connectors/vmaas/vmaas.integration.js index 23169c31..f6cc3738 100644 --- a/src/connectors/vmaas/vmaas.integration.js +++ b/src/connectors/vmaas/vmaas.integration.js @@ -4,9 +4,18 @@ require('../../test'); const vmaas = require('../vmaas'); const { mockRequest } = require('../testUtils'); +const REQ = { + headers: { + 'x-rh-identity': 'identity', + 'x-rh-insights-request-id': 'request-id' + }, + identity: { type: 'test' }, + user: { username: 'test', account_number: 'test' } +}; + test('obtains erratum metadata', async () => { mockRequest(); - const result = await vmaas.getCve('CVE-2017-17712'); + const result = await vmaas.getCve(REQ, 'CVE-2017-17712'); result.should.have.property('synopsis', 'CVE-2017-17712'); result.should.have.property('impact', 'Important'); }); diff --git a/src/connectors/vmaas/vmaas.js b/src/connectors/vmaas/vmaas.js index ae018a81..421e3b8a 100644 --- a/src/connectors/vmaas/vmaas.js +++ b/src/connectors/vmaas/vmaas.js @@ -14,21 +14,21 @@ module.exports = new class extends Connector { this.metrics = metrics.createConnectorMetric(this.getName()); } - getErratum (id) { + getErratum (req, id) { const uri = new URI(host); uri.path('/api/v1/errata'); uri.segment(id); - return this.doHttp({ + return this.doHttp(req, { uri: uri.toString(), method: 'GET', json: true, - headers: this.getForwardedHeaders(false) + headers: this.getForwardedHeaders(req, false) }, false) .then(res => _.get(res, ['errata_list', id], null)); } - getCve (id, refresh = false) { + getCve (req, id, refresh = false) { trace.enter('connectors/vmaas/vmaas.getCve'); const uri = new URI(host); @@ -39,7 +39,7 @@ module.exports = new class extends Connector { uri: uri.toString(), method: 'GET', json: true, - headers: this.getForwardedHeaders(false) + headers: this.getForwardedHeaders(req, false) }; const caching = { @@ -51,7 +51,7 @@ module.exports = new class extends Connector { trace.event(`GET options: ${options}`); trace.event(`GET caching: ${caching}`); - const promise = this.doHttp(options, caching, this.metrics) + const promise = this.doHttp(req, options, caching, this.metrics) .then(res => { trace.event(`Got data back!`); return _.get(res, ['cve_list', id], null); @@ -61,16 +61,17 @@ module.exports = new class extends Connector { return promise; } - getPackage (id, refresh = false) { + // Not being used?? + getPackage (req, id, refresh = false) { const uri = new URI(host); uri.path('/api/v1/packages'); uri.segment(id); - return this.doHttp({ + return this.doHttp(req, { uri: uri.toString(), method: 'GET', json: true, - headers: this.getForwardedHeaders(false) + headers: this.getForwardedHeaders(req, false) }, { refresh, @@ -81,8 +82,8 @@ module.exports = new class extends Connector { ).then(res => _.get(res, ['package_list', id], null)); } - async ping () { - const result = await this.getCve('CVE-2017-17712', true); + async ping (req) { + const result = await this.getCve(req, 'CVE-2017-17712', true); assert(result.synopsis === 'CVE-2017-17712'); } }(); diff --git a/src/connectors/vmaas/vmaas.unit.js b/src/connectors/vmaas/vmaas.unit.js index d4cafd92..662c51e1 100644 --- a/src/connectors/vmaas/vmaas.unit.js +++ b/src/connectors/vmaas/vmaas.unit.js @@ -5,9 +5,16 @@ const base = require('../../test'); const { mockRequest, mockCache } = require('../testUtils'); const request = require('../../util/request'); -describe('vmaas impl', function () { +const REQ = { + headers: { + 'x-rh-identity': 'identity', + 'x-rh-insights-request-id': 'request-id' + }, + identity: { type: 'test' }, + user: { username: 'test', account_number: 'test' } +}; - beforeEach(mockRequest); +describe('vmaas impl', function () { test('obtains CVE info', async function () { const cache = mockCache(); @@ -42,7 +49,7 @@ describe('vmaas impl', function () { headers: {} }); - const result = await impl.getCve('CVE-2017-5715'); + const result = await impl.getCve(REQ, 'CVE-2017-5715'); result.should.have.property('description', 'An industry-wide issue was found in the way many modern microprocessor.'); result.should.have.property('synopsis', 'CVE-2017-5715'); @@ -53,7 +60,7 @@ describe('vmaas impl', function () { cache.get.callCount.should.equal(1); cache.setex.callCount.should.equal(1); - await impl.getCve('CVE-2017-5715'); + await impl.getCve(REQ, 'CVE-2017-5715'); cache.get.callCount.should.equal(2); cache.setex.callCount.should.equal(1); }); @@ -72,7 +79,7 @@ describe('vmaas impl', function () { headers: {} }); - await expect(impl.getCve('CVE-2017-57155')).resolves.toBeNull(); + await expect(impl.getCve(REQ, 'CVE-2017-57155')).resolves.toBeNull(); http.callCount.should.equal(1); cache.get.callCount.should.equal(1); diff --git a/src/connectors/vulnerabilities/impl.js b/src/connectors/vulnerabilities/impl.js index 9c576eae..45832eb5 100644 --- a/src/connectors/vulnerabilities/impl.js +++ b/src/connectors/vulnerabilities/impl.js @@ -19,7 +19,7 @@ module.exports = new class extends Connector { throw new Error('not implemented'); } - async getSystems (id) { + async getSystems (id, req) { trace.enter('vulnerabilities_impl.getSystems'); const _uri = this.buildUri(host, 'vulnerability', 'v1', 'cves', id, 'affected_systems', 'ids'); _uri.query({limit: String(pageSize)}); @@ -33,12 +33,12 @@ module.exports = new class extends Connector { do { // grab a page trace.event(`Fetch ${uri}`); - const batch = await this.doHttp({ + const batch = await this.doHttp(req, { uri: uri, method: 'GET', json: true, rejectUnauthorized: !insecure, - headers: this.getForwardedHeaders() + headers: this.getForwardedHeaders(req) }, false, this.systemsMetrics); @@ -64,7 +64,7 @@ module.exports = new class extends Connector { return inventory_ids; } - async getResolutions (issue) { + async getResolutions (req, issue) { trace.enter('connectors/vulnerabilities/impl.getResolutions'); const uri = this.buildUri(host, 'vulnerability', 'v1', 'playbooks', 'templates', issue); @@ -74,12 +74,13 @@ module.exports = new class extends Connector { method: 'GET', json: true, rejectUnauthorized: !insecure, - headers: this.getForwardedHeaders() + headers: this.getForwardedHeaders(req) }; trace.event(`GET options: ${JSON.stringify(options)}`); const resolutions = await this.doHttp( + req, options, false, this.systemsMetrics); diff --git a/src/connectors/vulnerabilities/impl.unit.js b/src/connectors/vulnerabilities/impl.unit.js index f692c909..fadf4dab 100644 --- a/src/connectors/vulnerabilities/impl.unit.js +++ b/src/connectors/vulnerabilities/impl.unit.js @@ -5,6 +5,15 @@ const base = require('../../test'); const { mockRequest, mockCache } = require('../testUtils'); const request = require('../../util/request'); +const REQ = { + headers: { + 'x-rh-identity': 'identity', + 'x-rh-insights-request-id': 'request-id' + }, + identity: { type: 'test' }, + user: { username: 'test', account_number: 'test' } +}; + /* eslint-disable max-len */ describe('vulnerabilities impl', function () { @@ -49,7 +58,7 @@ describe('vulnerabilities impl', function () { headers: {} }); - await expect(impl.getSystems('rule')).resolves.toEqual([ + await expect(impl.getSystems('rule', REQ)).resolves.toEqual([ '802cab91-410f-473b-b4c6-b1524c45ba8c', '6ac1bb84-333d-48e5-bf02-7a9b0263d220' ]); @@ -78,7 +87,7 @@ describe('vulnerabilities impl', function () { headers: {} }); - await expect(impl.getSystems('unknown-rule')).resolves.toEqual([]); + await expect(impl.getSystems('unknown-rule', REQ)).resolves.toEqual([]); http.callCount.should.equal(1); cache.get.callCount.should.equal(0); @@ -112,7 +121,7 @@ describe('vulnerabilities impl', function () { headers: {} }); - const results = await impl.getResolutions('rule'); + const results = await impl.getResolutions(REQ, 'rule'); http.callCount.should.equal(1); const resolution = results[0]; @@ -142,7 +151,7 @@ describe('vulnerabilities impl', function () { headers: {} }); - await expect(impl.getResolutions('unknown-rule')).resolves.toEqual([]); + await expect(impl.getResolutions(REQ, 'unknown-rule')).resolves.toEqual([]); http.callCount.should.equal(1); cache.get.callCount.should.equal(0); diff --git a/src/connectors/vulnerabilities/mock.js b/src/connectors/vulnerabilities/mock.js index eae52d46..10363508 100644 --- a/src/connectors/vulnerabilities/mock.js +++ b/src/connectors/vulnerabilities/mock.js @@ -56,7 +56,7 @@ module.exports = new class extends Connector { ]; } - getResolutions (id) { + getResolutions (req, id) { if (_.has(RESOLUTION_DATA, id)) { // eslint-disable-next-line security/detect-object-injection return RESOLUTION_DATA[id]; diff --git a/src/diagnosis/diagnosis.controller.js b/src/diagnosis/diagnosis.controller.js index 6805fcc4..e6ae34e2 100644 --- a/src/diagnosis/diagnosis.controller.js +++ b/src/diagnosis/diagnosis.controller.js @@ -20,7 +20,7 @@ exports.getDiagnosis = errors.async(async function (req, res) { // 3) get report details from advisor, vulnerabilities // 4) optimize based on req.swagger.params.remediation.value - const systems = await inventory.getSystemsByInsightsId(insightsId); + const systems = await inventory.getSystemsByInsightsId(insightsId, req); const sorted = _.orderBy(systems, ['updated'], ['desc']); if (!sorted.length) { @@ -31,7 +31,7 @@ exports.getDiagnosis = errors.async(async function (req, res) { assert(system.tenant_org_id === req.identity.org_id); assert(system.insights_id === insightsId, system.insights_id); - const advisorDiagnosis = await advisor.getDiagnosis(system.id, branchId); + const advisorDiagnosis = await advisor.getDiagnosis(req, system.id, branchId); res.json({ id: system.id, insights_id: system.insights_id, diff --git a/src/errors.js b/src/errors.js index 454856df..a4b5f6b1 100644 --- a/src/errors.js +++ b/src/errors.js @@ -6,9 +6,9 @@ const cls = require('./util/cls'); const RequestSpecValidationError = require('./middleware/openapi/RequestSpecValidationError'); class HttpError extends Error { - constructor (status, code, title, details) { + constructor (req, status, code, title, details) { super(title); - const req = cls.getReq(); + // const req = cls.getReq(); this.name = this.constructor.name; this.error = { id: req ? req.id : 'unknown', @@ -58,32 +58,33 @@ class CompositeError extends Error { exports.CompositeError = CompositeError; exports.BadRequest = class BadRequest extends HttpError { - constructor (code, title, details) { - super(400, code, title, details); + constructor (req, code, title, details) { + super(req, 400, code, title, details); } }; exports.Unauthorized = class Unauthorized extends HttpError { - constructor () { - super(401, 'UNAUTHORIZED', 'Authorization headers missing'); + constructor (req) { + super(req, 401, 'UNAUTHORIZED', 'Authorization headers missing'); } }; exports.Forbidden = class Forbidden extends HttpError { - constructor (message) { - super(403, 'FORBIDDEN', 'Access forbidden', {message}); + constructor (req, message) { + super(req, 403, 'FORBIDDEN', 'Access forbidden', {message}); } }; exports.Unprocessable = class BadRequest extends HttpError { - constructor (code, title, details) { - super(422, code, title, details); + constructor (req, code, title, details) { + super(req, 422, code, title, details); } }; exports.DependencyError = class DependencyError extends HttpError { - constructor (e, connector) { + constructor (req, e, connector) { super( + req, 503, 'DEPENDENCY_UNAVAILABLE', // eslint-disable-next-line max-len @@ -139,16 +140,16 @@ exports.handler = (error, req, res, next) => { } if (error instanceof exports.DependencyError) { - log.error(error, 'rejecting request due to DependencyError'); + log.error(req, error, 'rejecting request due to DependencyError'); return error.writeResponse(res); } else if (error instanceof HttpError) { - log.debug(error, 'rejecting request due to HttpError'); + log.debug(req, error, 'rejecting request due to HttpError'); return error.writeResponse(res); } if (error instanceof RequestSpecValidationError) { log.debug(error.errors, 'rejecting request due to RequestSpecValidationError'); - return error.writeResponse(req, res); + return error.writeResponse(res); } if (error.name === 'SequelizeUniqueConstraintError') { @@ -175,34 +176,35 @@ exports.async = fn => (req, res, next) => { return result; }; -exports.unknownIssue = id => - new exports.BadRequest('UNKNOWN_ISSUE', `Unknown issue identifier "${id.full}"`); +exports.unknownIssue = (req, id) => + new exports.BadRequest(req, 'UNKNOWN_ISSUE', `Unknown issue identifier "${id.full}"`); -exports.unknownSystem = id => - new exports.BadRequest('UNKNOWN_SYSTEM', `Unknown system identifier "${id}"`); +exports.unknownSystem = (req, id) => + new exports.BadRequest(req, 'UNKNOWN_SYSTEM', `Unknown system identifier "${id}"`); -exports.unsupportedIssue = id => - new exports.BadRequest('UNSUPPORTED_ISSUE', `Issue "${id.full}" does not have Ansible support`); +exports.unsupportedIssue = (req, id) => + new exports.BadRequest(req, 'UNSUPPORTED_ISSUE', `Issue "${id.full}" does not have Ansible support`); -exports.unknownResolution = (id, resolution) => - new exports.BadRequest('UNKNOWN_RESOLUTION', `Issue "${id.full}" does not have Ansible resolution "${resolution}"`); +exports.unknownResolution = (req, id, resolution) => + new exports.BadRequest(req, 'UNKNOWN_RESOLUTION', `Issue "${id.full}" does not have Ansible resolution "${resolution}"`); -exports.invalidIssueId = (id) => new exports.BadRequest('INVALID_ISSUE_IDENTIFIER', `"${id}" is not a valid issue identifier.`); +exports.invalidIssueId = (req, id) => + new exports.BadRequest(req, 'INVALID_ISSUE_IDENTIFIER', `"${id}" is not a valid issue identifier.`); -exports.invalidOffset = (offset, max) => - new exports.BadRequest('INVALID_OFFSET', `Requested starting offset ${offset} out of range: [0, ${max}]`); +exports.invalidOffset = (req, offset, max) => + new exports.BadRequest(req, 'INVALID_OFFSET', `Requested starting offset ${offset} out of range: [0, ${max}]`); -exports.noExecutors = remediation => - new exports.Unprocessable('NO_EXECUTORS', `No executors available for Playbook "${remediation.name}" (${remediation.id})`); +exports.noExecutors = (req, remediation) => + new exports.Unprocessable(req, 'NO_EXECUTORS', `No executors available for Playbook "${remediation.name}" (${remediation.id})`); -exports.noSystems = remediation => - new exports.Unprocessable('NO_SYSTEMS', `Remediation ${remediation.id} contains no systems`); +exports.noSystems = (req, remediation) => + new exports.Unprocessable(req, 'NO_SYSTEMS', `Remediation ${remediation.id} contains no systems`); -exports.unknownExclude = excluded => - new exports.BadRequest('UNKNOWN_EXCLUDE', `Excluded Executor [${excluded}] not found in list of identified executors`); +exports.unknownExclude = (req, excluded) => + new exports.BadRequest(req, 'UNKNOWN_EXCLUDE', `Excluded Executor [${excluded}] not found in list of identified executors`); -exports.unauthorizedGeneration = cn => - new exports.Forbidden(`Host certificate ${cn} is unauthorized to access this playbook`); +exports.unauthorizedGeneration = (req, cn) => + new exports.Forbidden(req, `Host certificate ${cn} is unauthorized to access this playbook`); exports.internal = { invalidTemplate (msg) { @@ -221,8 +223,8 @@ exports.internal = { return new InternalError('PLAYBOOK_RENDERING_FAILED', `Playbook rendering failed for template ${template}`, {cause: e}); }, - dependencyError (e, connector) { - return new exports.DependencyError(e, connector); + dependencyError (req, e, connector) { + return new exports.DependencyError(req, e, connector); }, preconditionFailed (msg) { diff --git a/src/generator/factories/AdvisorFactory.js b/src/generator/factories/AdvisorFactory.js index 80897a03..bc4adef0 100644 --- a/src/generator/factories/AdvisorFactory.js +++ b/src/generator/factories/AdvisorFactory.js @@ -8,15 +8,15 @@ const Factory = require('./Factory'); module.exports = class AdvisorFactory extends Factory { - async createPlay ({id, resolution, hosts}, strict = true) { - const handler = issues.getHandler(id); + async createPlay ({id, resolution, hosts}, req, strict = true) { + const handler = issues.getHandler(id, req); const [resolutions, rule] = await P.all([ - handler.getResolutionResolver().resolveResolutions(id), - handler.getIssueDetails(id) + handler.getResolutionResolver().resolveResolutions(req, id), + handler.getIssueDetails(id, req) ]); - const disambiguatedResolution = this.disambiguate(resolutions, resolution, id, strict); + const disambiguatedResolution = this.disambiguate(req, resolutions, resolution, id, strict); return new ResolutionPlay(id, hosts, disambiguatedResolution, rule.description); } }; diff --git a/src/generator/factories/CSAWFactory.js b/src/generator/factories/CSAWFactory.js index 79b18f83..72bb7a4b 100644 --- a/src/generator/factories/CSAWFactory.js +++ b/src/generator/factories/CSAWFactory.js @@ -10,22 +10,22 @@ const trace = require('../../util/trace'); module.exports = class CVEFactory extends Factory { - async createPlay (issue, strict = true) { + async createPlay (issue, req, strict = true) { trace.enter('CSAWFactory.createPlay'); trace.event(`Resolve resolutions for id: ${issue.id}`); const {id, hosts, resolution} = issue; - const resolver = issues.getHandler(id).getResolutionResolver(); - const resolutions = await resolver.resolveResolutions(id, strict); + const resolver = issues.getHandler(id, req).getResolutionResolver(); + const resolutions = await resolver.resolveResolutions(req, id, strict); trace.event(`Resolutions: ${JSON.stringify(resolutions)}`); if (!resolutions.length) { trace.leave('Unknown issue!'); - throw errors.unknownIssue(id); + throw errors.unknownIssue(req, id); } trace.event('Disambiguate resolutions...'); - const disambiguatedResolution = this.disambiguate(resolutions, resolution, id, strict); + const disambiguatedResolution = this.disambiguate(req, resolutions, resolution, id, strict); trace.event(`Disambiguated resolution: ${JSON.stringify(disambiguatedResolution)}`); if (ErratumResolution.isErratumResolution(disambiguatedResolution)) { diff --git a/src/generator/factories/CVEFactory.js b/src/generator/factories/CVEFactory.js index 067678f3..27ab0e5d 100644 --- a/src/generator/factories/CVEFactory.js +++ b/src/generator/factories/CVEFactory.js @@ -8,20 +8,20 @@ const Factory = require('./Factory'); module.exports = class CVEFactory extends Factory { - async createPlay ({id, hosts, resolution}, strict = true) { + async createPlay ({id, hosts, resolution}, req, strict = true) { trace.enter('CVEFactory.createPlay'); trace.event(`Resolve resolutions for issue: ${id}`); - const resolver = issues.getHandler(id).getResolutionResolver(); - const resolutions = await resolver.resolveResolutions(id); + const resolver = issues.getHandler(id, req).getResolutionResolver(); + const resolutions = await resolver.resolveResolutions(req, id); if (!resolutions.length) { trace.event('Issue/resolution not found!'); - throw errors.unknownIssue(id); + throw errors.unknownIssue(req, id); } - + trace.event(`Disambiguate resolution...`); - const disambiguatedResolution = this.disambiguate(resolutions, resolution, id, strict); + const disambiguatedResolution = this.disambiguate(req, resolutions, resolution, id, strict); trace.event(`Disambiguated resolution.`); trace.event('Create erratum play...'); diff --git a/src/generator/factories/ComplianceFactory.js b/src/generator/factories/ComplianceFactory.js index 86538a9a..aedc2bd1 100644 --- a/src/generator/factories/ComplianceFactory.js +++ b/src/generator/factories/ComplianceFactory.js @@ -7,15 +7,14 @@ const Factory = require('./Factory'); module.exports = class ComplianceFactory extends Factory { - async createPlay ({id, hosts, resolution}, strict = true) { - const handler = issues.getHandler(id); + async createPlay ({id, hosts, resolution}, req, strict = true) { + const handler = issues.getHandler(id, req); const [resolutions, rule] = await P.all([ - handler.getResolutionResolver().resolveResolutions(id), - handler.getIssueDetails(id) + handler.getResolutionResolver().resolveResolutions(req, id), + handler.getIssueDetails(id, req) ]); - - const disambiguatedResolution = this.disambiguate(resolutions, resolution, id, strict); + const disambiguatedResolution = this.disambiguate(req, resolutions, resolution, id, strict); return new ResolutionPlay(id, hosts, disambiguatedResolution, rule.description); } }; diff --git a/src/generator/factories/Factory.js b/src/generator/factories/Factory.js index f0837759..614412e9 100644 --- a/src/generator/factories/Factory.js +++ b/src/generator/factories/Factory.js @@ -8,7 +8,7 @@ module.exports = class Factory { throw new Error('not implemented'); } - disambiguate (resolutions, resolution, id, strict) { - return disambiguator.disambiguate(resolutions, resolution, id, strict); + disambiguate (req, resolutions, resolution, id, strict) { + return disambiguator.disambiguate(req, resolutions, resolution, id, strict); } }; diff --git a/src/generator/factories/TestFactory.js b/src/generator/factories/TestFactory.js index 00412bed..3e2845f1 100644 --- a/src/generator/factories/TestFactory.js +++ b/src/generator/factories/TestFactory.js @@ -7,14 +7,14 @@ const Factory = require('./Factory'); module.exports = class TestFactory extends Factory { - async createPlay ({id, resolution, hosts}) { - const resolutions = await testResolver.resolveResolutions(id); + async createPlay ({id, resolution, hosts}, req) { + const resolutions = await testResolver.resolveResolutions(req, id); - const disambiguatedResolution = this.disambiguate(resolutions, resolution, id, true); + const disambiguatedResolution = this.disambiguate(req, resolutions, resolution, id, true); if (disambiguatedResolution) { return new ResolutionPlay(id, hosts, disambiguatedResolution); } - throw errors.unsupportedIssue(id); + throw errors.unsupportedIssue(req, id); } }; diff --git a/src/generator/generator.controller.js b/src/generator/generator.controller.js index 0eb1540c..3fc60fde 100644 --- a/src/generator/generator.controller.js +++ b/src/generator/generator.controller.js @@ -27,20 +27,20 @@ exports.normalizeIssues = function (issues) { return issues; }; -exports.playbookPipeline = async function ({issues, auto_reboot = true}, remediation = false, strict = true, localhost = false) { +exports.playbookPipeline = async function ({issues, auto_reboot = true}, req, remediation = false, strict = true, localhost = false) { trace.enter('generator.controller.playbookPipeline'); trace.event('Fetch systems...'); - await exports.resolveSystems(issues, strict); + await exports.resolveSystems(issues, req, strict); trace.event('Parse issue identifiers...'); _.forEach(issues, issue => { - issue.id = identifiers.parse(issue.id); + issue.id = identifiers.parse(req, issue.id); trace.event(`issue.id = ${issue.id}`); }); trace.event('Get play snippets for each issue...'); - issues = await P.map(issues, issue => issueManager.getPlayFactory(issue.id).createPlay(issue, strict).catch((e) => { + issues = await P.map(issues, issue => issueManager.getPlayFactory(issue.id, req).createPlay(issue, req, strict).catch((e) => { trace.event(`Caught error getting snippet for: ${JSON.stringify(issue.id)}`); trace.event(`(error: ${JSON.stringify(e)})`) @@ -79,7 +79,7 @@ exports.playbookPipeline = async function ({issues, auto_reboot = true}, remedia trace.event('Aggregate erratum plays...'); issues = erratumPlayAggregator.process(issues); - // Add play that generates a new Compliance report when there are Compliance(ssg) issues + // Add play that generates a new Compliance report when there are Compliance(ssg) issues const complianceIssue = _.some(issues, issue => issue.id.app === 'ssg'); if (complianceIssue) { trace.event('Generate new Compliance report...'); @@ -113,7 +113,7 @@ exports.generate = errors.async(async function (req, res) { const input = { ...req.body }; trace.event(`generate playbook for: ${JSON.stringify(input)}`); - const playbook = await exports.playbookPipeline(input); + const playbook = await exports.playbookPipeline(input, req); trace.leave(); return exports.send(req, res, playbook); @@ -123,7 +123,7 @@ exports.systemToHost = function (system) { return system.ansible_host || system.hostname || system.id; }; -exports.resolveSystems = async function (issues, strict = true) { +exports.resolveSystems = async function (issues, req, strict = true) { trace.enter('generator.controller.resolveSystems'); const systemIds = _(issues).flatMap('systems').uniq().value(); @@ -133,7 +133,7 @@ exports.resolveSystems = async function (issues, strict = true) { // bypass cache as ansible_host may change so we want to grab the latest one trace.event('Get system details...'); - const systems = await inventory.getSystemDetailsBatch(systemIds, true); + const systems = await inventory.getSystemDetailsBatch(req, systemIds, true); if (!strict) { trace.event('Remove systems for which we have no inventory entry...'); @@ -148,7 +148,7 @@ exports.resolveSystems = async function (issues, strict = true) { if (!systems.hasOwnProperty(id)) { trace.event(`Found no data for system: ${id}`); probes.failedGeneration(issue.id); - throw errors.unknownSystem(id); + throw errors.unknownSystem(req, id); } // validated by openapi middleware and also above diff --git a/src/issues/AdvisorHandler.js b/src/issues/AdvisorHandler.js index 23cf8453..62b76d28 100644 --- a/src/issues/AdvisorHandler.js +++ b/src/issues/AdvisorHandler.js @@ -9,11 +9,11 @@ const contentServerResolver = new(require('../resolutions/resolvers/ContentServe module.exports = class AdvisorHandler extends Handler { - async getIssueDetails (id) { - const raw = await advisor.getRule(id.issue); + async getIssueDetails (id, req) { + const raw = await advisor.getRule(req, id.issue); if (!raw) { - throw errors.unknownIssue(id); + throw errors.unknownIssue(req, id); } return { @@ -26,11 +26,11 @@ module.exports = class AdvisorHandler extends Handler { return contentServerResolver; } - getPlayFactory () { + getPlayFactory (id, req) { return advisorFactory; } - getSystems (id) { - return advisor.getSystems(id.issue); + getSystems (id, req) { + return advisor.getSystems(id.issue, req); } }; diff --git a/src/issues/CSAWHandler.js b/src/issues/CSAWHandler.js index 72c03497..bc497956 100644 --- a/src/issues/CSAWHandler.js +++ b/src/issues/CSAWHandler.js @@ -10,27 +10,27 @@ const csawFactory = new(require('../generator/factories/CSAWFactory'))(); module.exports = class CVEHandler extends Handler { - getCSAWIssueDetailsInternal (id) { - return vulnerabilities.getResolutions(id.issue); + getCSAWIssueDetailsInternal (id, req) { + return vulnerabilities.getResolutions(req, id.issue); } - getCVEIssueDetailsInternal (id) { - return vmaas.getCve(id.issue); + getCVEIssueDetailsInternal (req, id) { + return vmaas.getCve(req, id.issue); } - async getIssueDetails (id) { - const parsed = identifiers.parseCSAW(id); + async getIssueDetails (id, req) { + const parsed = identifiers.parseCSAW(req, id); id.issue = parsed.csaw; - let raw = await this.getCSAWIssueDetailsInternal(id); + let raw = await this.getCSAWIssueDetailsInternal(id, req); if (!raw && parsed.cve) { id.issue = parsed.cve; - raw = await this.getCVEIssueDetailsInternal(id); + raw = await this.getCVEIssueDetailsInternal(req, id); } if (!raw) { - throw errors.unknownIssue(id); + throw errors.unknownIssue(req, id); } return { @@ -43,7 +43,7 @@ module.exports = class CVEHandler extends Handler { return csawResolver; } - getPlayFactory () { + getPlayFactory (id, req) { return csawFactory; } }; diff --git a/src/issues/CVEHandler.js b/src/issues/CVEHandler.js index 240f8289..c668829d 100644 --- a/src/issues/CVEHandler.js +++ b/src/issues/CVEHandler.js @@ -10,15 +10,15 @@ const cveFactory = new(require('../generator/factories/CVEFactory'))(); module.exports = class CVEHandler extends Handler { - getIssueDetailsInternal (id) { - return vmaas.getCve(id.issue); + getIssueDetailsInternal (req, id) { + return vmaas.getCve(req, id.issue); } - async getIssueDetails (id) { - const raw = await this.getIssueDetailsInternal(id); + async getIssueDetails (id, req) { + const raw = await this.getIssueDetailsInternal(req, id); if (!raw) { - throw errors.unknownIssue(id); + throw errors.unknownIssue(req, id); } return { @@ -31,12 +31,12 @@ module.exports = class CVEHandler extends Handler { return cveResolver; } - getPlayFactory () { + getPlayFactory (id, req) { return cveFactory; } - getSystems (id) { - return vulnerabilities.getSystems(id.issue); + getSystems (id, req) { + return vulnerabilities.getSystems(id.issue, req); } }; diff --git a/src/issues/ErratumHandler.js b/src/issues/ErratumHandler.js index 6963cff2..6aada787 100644 --- a/src/issues/ErratumHandler.js +++ b/src/issues/ErratumHandler.js @@ -7,8 +7,8 @@ const erratumResolver = new(require('../resolutions/resolvers/ErratumResolver')) module.exports = class ErratumHandler extends CVEHandler { - getIssueDetailsInternal (id) { - return vmaas.getErratum(id.issue); + getIssueDetailsInternal (req, id) { + return vmaas.getErratum(req, id.issue); } getResolutionResolver () { diff --git a/src/issues/PackageHandler.js b/src/issues/PackageHandler.js index dd2d6675..94f27e0f 100644 --- a/src/issues/PackageHandler.js +++ b/src/issues/PackageHandler.js @@ -6,7 +6,7 @@ const cveFactory = new(require('../generator/factories/CVEFactory'))(); module.exports = class PackageHandler extends Handler { - async getIssueDetails (id) { + async getIssueDetails (id, req) { return { description: id.issue }; @@ -16,7 +16,7 @@ module.exports = class PackageHandler extends Handler { return packageResolver; } - getPlayFactory () { + getPlayFactory (id, req) { return cveFactory; } }; diff --git a/src/issues/PatchmanHandler.js b/src/issues/PatchmanHandler.js index 17d37be2..15c1fe29 100644 --- a/src/issues/PatchmanHandler.js +++ b/src/issues/PatchmanHandler.js @@ -6,7 +6,7 @@ const patchFactory = new(require('../generator/factories/PatchmanFactory'))(); module.exports = class PatchmanHandler extends Handler { - async getIssueDetails (id) { + async getIssueDetails (id, req) { return { description: id.issue }; @@ -16,7 +16,7 @@ module.exports = class PatchmanHandler extends Handler { return patchResolver; } - getPlayFactory () { + getPlayFactory (id, req) { return patchFactory; } }; diff --git a/src/issues/SSGHandler.js b/src/issues/SSGHandler.js index f9ed4c8f..3329a63a 100644 --- a/src/issues/SSGHandler.js +++ b/src/issues/SSGHandler.js @@ -9,12 +9,12 @@ const resolver = new(require('../resolutions/resolvers/SSGResolver'))(); const identifiers = require('../util/identifiers'); module.exports = class ComplianceHandler extends Handler { - async getIssueDetails (id) { - const ssgId = identifiers.parseSSG(id); - const raw = await compliance.getRule(ssgId.ruleRef); + async getIssueDetails (id, req) { + const ssgId = identifiers.parseSSG(req, id); + const raw = await compliance.getRule(req, ssgId.ruleRef); if (!raw) { - throw errors.unknownIssue(id); + throw errors.unknownIssue(req, id); } return { @@ -27,7 +27,7 @@ module.exports = class ComplianceHandler extends Handler { return resolver; } - getPlayFactory () { + getPlayFactory (id, req) { return complianceFactory; } }; diff --git a/src/issues/TestHandler.js b/src/issues/TestHandler.js index 87d58f72..9a993238 100644 --- a/src/issues/TestHandler.js +++ b/src/issues/TestHandler.js @@ -8,10 +8,10 @@ const testFactory = new(require('../generator/factories/TestFactory'))(); module.exports = class TestHandler extends Handler { - async getIssueDetails (id) { - const [resolution] = await testResolver.resolveResolutions(id); + async getIssueDetails (id, req) { + const [resolution] = await testResolver.resolveResolutions(req, id); if (!resolution) { - throw errors.unknownIssue(id); + throw errors.unknownIssue(req, id); } return { @@ -19,7 +19,7 @@ module.exports = class TestHandler extends Handler { }; } - getPlayFactory () { + getPlayFactory (id, req) { return testFactory; } diff --git a/src/issues/index.js b/src/issues/index.js index e7b3cdd4..2ee5773e 100644 --- a/src/issues/index.js +++ b/src/issues/index.js @@ -22,7 +22,7 @@ const packageHandler = new(require('./PackageHandler'))(); const csawHandler = new(require('./CSAWHandler'))(); /* eslint no-fallthrough: off */ -function getHandler (id) { +function getHandler (id, req) { switch (id.app) { case 'advisor': return advisorHandler; case 'ssg': return ssgHandler; @@ -39,7 +39,7 @@ function getHandler (id) { return erratumHandler; } - throw errors.unknownIssue(id); + throw errors.unknownIssue(req, id); case 'test': return testHandler; case 'patch-advisory': @@ -47,24 +47,24 @@ function getHandler (id) { return patchmanHandler; } - throw errors.unknownIssue(id); + throw errors.unknownIssue(req, id); case 'patch-package': if (NEVRA_PATTERN.test(id.issue)) { return packageHandler; } - throw errors.unknownIssue(id); + throw errors.unknownIssue(req, id); default: - throw errors.unknownIssue(id); + throw errors.unknownIssue(req, id); } } exports.getHandler = getHandler; -exports.getIssueDetails = function (id) { - return getHandler(id).getIssueDetails(id); +exports.getIssueDetails = function (id, req) { + return getHandler(id, req).getIssueDetails(id, req); }; -exports.getPlayFactory = function (id) { - return getHandler(id).getPlayFactory(id); +exports.getPlayFactory = function (id, req) { + return getHandler(id, req).getPlayFactory(id, req); }; diff --git a/src/middleware/identity/impl.js b/src/middleware/identity/impl.js index 1dd1e12a..4a3658a7 100644 --- a/src/middleware/identity/impl.js +++ b/src/middleware/identity/impl.js @@ -11,7 +11,7 @@ module.exports = function (req, res, next) { if (raw === undefined) { log.info({headers: req.headers, reqId}, 'rejecting request due to missing identity header'); - return next(new errors.Unauthorized()); + return next(new errors.Unauthorized(req)); } try { @@ -25,7 +25,7 @@ module.exports = function (req, res, next) { // allow for anemic tenants (org_id present but no account_number) if (!(req.identity.account_number || req.identity.org_id)) { - return next(new errors.Unauthorized()); + return next(new errors.Unauthorized(req)); } if (req.identity.type === 'User') { @@ -49,6 +49,6 @@ module.exports = function (req, res, next) { next(); } catch (e) { log.debug({header: raw, error: e.message, reqId}, 'Error decoding identity header'); - next(new errors.BadRequest('IDENTITY_HEADER', 'Invalid identity header')); + next(new errors.BadRequest(req, 'IDENTITY_HEADER', 'Invalid identity header')); } }; diff --git a/src/middleware/identity/userIdentity.js b/src/middleware/identity/userIdentity.js index 4735bdeb..3aa0028f 100644 --- a/src/middleware/identity/userIdentity.js +++ b/src/middleware/identity/userIdentity.js @@ -6,18 +6,18 @@ module.exports = function (req, res, next) { switch(req.identity.type) { case 'User': if (!req.identity?.user?.username || req.identity?.user?.is_internal === undefined) { - return next(new errors.Forbidden('Supplied identity invalid')); + return next(new errors.Forbidden(req, 'Supplied identity invalid')); } break; case 'ServiceAccount': if (!req.identity?.service_account?.username) { - return next(new errors.Forbidden('Supplied service account identity invalid')); + return next(new errors.Forbidden(req, 'Supplied service account identity invalid')); } break; default: - return next(new errors.Forbidden('Supplied identity not valid for requested operation')); + return next(new errors.Forbidden(req, 'Supplied identity not valid for requested operation')); } return next(); diff --git a/src/middleware/openapi/RequestSpecValidationError.js b/src/middleware/openapi/RequestSpecValidationError.js index af007b0c..8cf4d86c 100644 --- a/src/middleware/openapi/RequestSpecValidationError.js +++ b/src/middleware/openapi/RequestSpecValidationError.js @@ -6,7 +6,7 @@ module.exports = class RequestSpecValidationError { this.errors = errors; } - writeResponse (req, res) { + writeResponse (res) { res.status(this.status).json({ errors: this.errors }).end(); diff --git a/src/middleware/rbac.js b/src/middleware/rbac.js index a3d5f4c2..c473fbc0 100644 --- a/src/middleware/rbac.js +++ b/src/middleware/rbac.js @@ -17,7 +17,7 @@ module.exports = function (permission) { // Should cert-auth be used on the '/playbooks' endpoint skip the RBAC middleware check if (req.identity.type !== 'System') { try { - const access = await rbacConnector.getRemediationsAccess(); + const access = await rbacConnector.getRemediationsAccess(req); const accessPermissions = _.map(access.data, 'permission'); if (_.includes(accessPermissions, `remediations:*:*`) || @@ -30,6 +30,7 @@ module.exports = function (permission) { probes.rbacErrorCount(permission, accessPermissions); return next(new errors.Forbidden( + req, `Permission remediations:${srcPermission.resource}:${srcPermission.resourceType} is required for this operation` )); } diff --git a/src/remediations/__snapshots__/fifi.integration.js.snap b/src/remediations/__snapshots__/fifi.integration.js.snap index 2d5918fb..78c93158 100644 --- a/src/remediations/__snapshots__/fifi.integration.js.snap +++ b/src/remediations/__snapshots__/fifi.integration.js.snap @@ -672,356 +672,348 @@ Array [ exports[`FiFi playbook run POST exclude RHC is case-insensitive 1`] = ` [ - [ - [ + { + "hosts": [ { - "hosts": [ - { - "inventory_id": "2a708189-4b48-4642-9443-64bda5f38e5f", - }, - { - "inventory_id": "36828b63-38f3-4b9a-ad08-0b7812e5df57", - }, - { - "inventory_id": "6f6a889d-6bac-4d53-9bc1-ef75bc1a55ff", - }, - { - "inventory_id": "938c5ce7-481f-4b82-815c-2973ca76a0ef", - }, - ], - "labels": { - "playbook-run": "b995e750-c1d3-4c5b-a3ec-eee897ee9065", - }, - "name": "FiFI playbook 5", - "org_id": "6666666", - "principal": "fifi", - "recipient": "beefface-c7a6-4cc3-89bc-9066ffda695e", - "recipient_config": { - "sat_id": "893f2788-c7a6-4cc3-89bc-9066ffda695e", - "sat_org_id": "6", - }, - "url": "https://hostname/api/remediations/v1/remediations/63d92aeb-9351-4216-8d7c-044d171337bc/playbook?hosts=2a708189-4b48-4642-9443-64bda5f38e5f&hosts=36828b63-38f3-4b9a-ad08-0b7812e5df57&hosts=6f6a889d-6bac-4d53-9bc1-ef75bc1a55ff&hosts=938c5ce7-481f-4b82-815c-2973ca76a0ef", - "web_console_url": "https://console.redhat.com/insights/remediations", + "inventory_id": "2a708189-4b48-4642-9443-64bda5f38e5f", }, { - "hosts": [ - { - "inventory_id": "34360dba-a2e7-4788-b9a2-44246a865c7e", - }, - { - "inventory_id": "64ee45db-6f2b-4862-bc9a-40aea8f5ecbe", - }, - ], - "labels": { - "playbook-run": "b995e750-c1d3-4c5b-a3ec-eee897ee9065", - }, - "name": "FiFI playbook 5", - "org_id": "6666666", - "principal": "fifi", - "recipient": "beefface-c7a6-4cc3-89bc-9066ffda695e", - "recipient_config": { - "sat_id": "893f2788-c7a6-4cc3-89bc-9066ffda695e", - "sat_org_id": "2", - }, - "url": "https://hostname/api/remediations/v1/remediations/63d92aeb-9351-4216-8d7c-044d171337bc/playbook?hosts=34360dba-a2e7-4788-b9a2-44246a865c7e&hosts=64ee45db-6f2b-4862-bc9a-40aea8f5ecbe", - "web_console_url": "https://console.redhat.com/insights/remediations", + "inventory_id": "36828b63-38f3-4b9a-ad08-0b7812e5df57", }, { - "hosts": [ - { - "inventory_id": "355986a3-5f37-40f7-8f36-c3ac928ce190", - }, - { - "inventory_id": "881256d7-8f99-4073-be6d-67ee42ba9af8", - }, - { - "inventory_id": "b84f4322-a0b8-4fb9-a8dc-8abb9ee16bc0", - }, - ], - "labels": { - "playbook-run": "b995e750-c1d3-4c5b-a3ec-eee897ee9065", - }, - "name": "FiFI playbook 5", - "org_id": "6666666", - "principal": "fifi", - "recipient": "beefface-f4b5-4b1f-9c2f-23fc7b0ba390", - "recipient_config": { - "sat_id": "722ec903-f4b5-4b1f-9c2f-23fc7b0ba390", - "sat_org_id": "2", - }, - "url": "https://hostname/api/remediations/v1/remediations/63d92aeb-9351-4216-8d7c-044d171337bc/playbook?hosts=355986a3-5f37-40f7-8f36-c3ac928ce190&hosts=881256d7-8f99-4073-be6d-67ee42ba9af8&hosts=b84f4322-a0b8-4fb9-a8dc-8abb9ee16bc0", - "web_console_url": "https://console.redhat.com/insights/remediations", + "inventory_id": "6f6a889d-6bac-4d53-9bc1-ef75bc1a55ff", }, { - "hosts": [ - { - "inventory_id": "35e9b452-e405-499c-9c6e-120010b7b465", - }, - { - "inventory_id": "8728dbf3-6500-44bb-a55c-4909a48673ed", - }, - { - "inventory_id": "88d0ba73-0015-4e7d-a6d6-4b530cbfb4ad", - }, - { - "inventory_id": "baaad5ad-1b8e-457e-ad43-39d1aea40d4d", - }, - { - "inventory_id": "e4a0a6ff-0f01-4659-ad9d-44150ade51dd", - }, - ], - "labels": { - "playbook-run": "b995e750-c1d3-4c5b-a3ec-eee897ee9065", - }, - "name": "FiFI playbook 5", - "org_id": "6666666", - "principal": "fifi", - "recipient": "beefface-46a5-498b-9614-01f2f66fd40b", - "recipient_config": { - "sat_id": "63142926-46a5-498b-9614-01f2f66fd40b", - "sat_org_id": "2", - }, - "url": "https://hostname/api/remediations/v1/remediations/63d92aeb-9351-4216-8d7c-044d171337bc/playbook?hosts=35e9b452-e405-499c-9c6e-120010b7b465&hosts=8728dbf3-6500-44bb-a55c-4909a48673ed&hosts=88d0ba73-0015-4e7d-a6d6-4b530cbfb4ad&hosts=baaad5ad-1b8e-457e-ad43-39d1aea40d4d&hosts=e4a0a6ff-0f01-4659-ad9d-44150ade51dd", - "web_console_url": "https://console.redhat.com/insights/remediations", + "inventory_id": "938c5ce7-481f-4b82-815c-2973ca76a0ef", + }, + ], + "labels": { + "playbook-run": "b995e750-c1d3-4c5b-a3ec-eee897ee9065", + }, + "name": "FiFI playbook 5", + "org_id": "6666666", + "principal": "fifi", + "recipient": "beefface-c7a6-4cc3-89bc-9066ffda695e", + "recipient_config": { + "sat_id": "893f2788-c7a6-4cc3-89bc-9066ffda695e", + "sat_org_id": "6", + }, + "url": "https://hostname/api/remediations/v1/remediations/63d92aeb-9351-4216-8d7c-044d171337bc/playbook?hosts=2a708189-4b48-4642-9443-64bda5f38e5f&hosts=36828b63-38f3-4b9a-ad08-0b7812e5df57&hosts=6f6a889d-6bac-4d53-9bc1-ef75bc1a55ff&hosts=938c5ce7-481f-4b82-815c-2973ca76a0ef", + "web_console_url": "https://console.redhat.com/insights/remediations", + }, + { + "hosts": [ + { + "inventory_id": "34360dba-a2e7-4788-b9a2-44246a865c7e", }, { - "hosts": [ - { - "inventory_id": "3fec343b-ecc0-4049-9e30-e4dc2bae9f62", - }, - { - "inventory_id": "9574cba7-b9ce-4725-b392-e959afd3e69a", - }, - { - "inventory_id": "bd91d212-91ae-4813-a406-d2af96fbeb52", - }, - ], - "labels": { - "playbook-run": "b995e750-c1d3-4c5b-a3ec-eee897ee9065", - }, - "name": "FiFI playbook 5", - "org_id": "6666666", - "principal": "fifi", - "recipient": "beefface-64a7-4ee7-a94e-3beed9393972", - "recipient_config": { - "sat_id": "72f44b25-64a7-4ee7-a94e-3beed9393972", - "sat_org_id": "2", - }, - "url": "https://hostname/api/remediations/v1/remediations/63d92aeb-9351-4216-8d7c-044d171337bc/playbook?hosts=3fec343b-ecc0-4049-9e30-e4dc2bae9f62&hosts=9574cba7-b9ce-4725-b392-e959afd3e69a&hosts=bd91d212-91ae-4813-a406-d2af96fbeb52", - "web_console_url": "https://console.redhat.com/insights/remediations", + "inventory_id": "64ee45db-6f2b-4862-bc9a-40aea8f5ecbe", }, + ], + "labels": { + "playbook-run": "b995e750-c1d3-4c5b-a3ec-eee897ee9065", + }, + "name": "FiFI playbook 5", + "org_id": "6666666", + "principal": "fifi", + "recipient": "beefface-c7a6-4cc3-89bc-9066ffda695e", + "recipient_config": { + "sat_id": "893f2788-c7a6-4cc3-89bc-9066ffda695e", + "sat_org_id": "2", + }, + "url": "https://hostname/api/remediations/v1/remediations/63d92aeb-9351-4216-8d7c-044d171337bc/playbook?hosts=34360dba-a2e7-4788-b9a2-44246a865c7e&hosts=64ee45db-6f2b-4862-bc9a-40aea8f5ecbe", + "web_console_url": "https://console.redhat.com/insights/remediations", + }, + { + "hosts": [ { - "hosts": [ - { - "inventory_id": "95c5ee0d-9599-475f-a8ef-c838545b9a73", - }, - ], - "labels": { - "playbook-run": "b995e750-c1d3-4c5b-a3ec-eee897ee9065", - }, - "name": "FiFI playbook 5", - "org_id": "6666666", - "principal": "fifi", - "recipient": "beefface-6092-485c-ba04-c656d77f988a", - "recipient_config": { - "sat_id": "01bf542e-6092-485c-ba04-c656d77f988a", - "sat_org_id": "2", - }, - "url": "https://hostname/api/remediations/v1/remediations/63d92aeb-9351-4216-8d7c-044d171337bc/playbook?hosts=95c5ee0d-9599-475f-a8ef-c838545b9a73", - "web_console_url": "https://console.redhat.com/insights/remediations", + "inventory_id": "355986a3-5f37-40f7-8f36-c3ac928ce190", + }, + { + "inventory_id": "881256d7-8f99-4073-be6d-67ee42ba9af8", + }, + { + "inventory_id": "b84f4322-a0b8-4fb9-a8dc-8abb9ee16bc0", }, ], - ], + "labels": { + "playbook-run": "b995e750-c1d3-4c5b-a3ec-eee897ee9065", + }, + "name": "FiFI playbook 5", + "org_id": "6666666", + "principal": "fifi", + "recipient": "beefface-f4b5-4b1f-9c2f-23fc7b0ba390", + "recipient_config": { + "sat_id": "722ec903-f4b5-4b1f-9c2f-23fc7b0ba390", + "sat_org_id": "2", + }, + "url": "https://hostname/api/remediations/v1/remediations/63d92aeb-9351-4216-8d7c-044d171337bc/playbook?hosts=355986a3-5f37-40f7-8f36-c3ac928ce190&hosts=881256d7-8f99-4073-be6d-67ee42ba9af8&hosts=b84f4322-a0b8-4fb9-a8dc-8abb9ee16bc0", + "web_console_url": "https://console.redhat.com/insights/remediations", + }, + { + "hosts": [ + { + "inventory_id": "35e9b452-e405-499c-9c6e-120010b7b465", + }, + { + "inventory_id": "8728dbf3-6500-44bb-a55c-4909a48673ed", + }, + { + "inventory_id": "88d0ba73-0015-4e7d-a6d6-4b530cbfb4ad", + }, + { + "inventory_id": "baaad5ad-1b8e-457e-ad43-39d1aea40d4d", + }, + { + "inventory_id": "e4a0a6ff-0f01-4659-ad9d-44150ade51dd", + }, + ], + "labels": { + "playbook-run": "b995e750-c1d3-4c5b-a3ec-eee897ee9065", + }, + "name": "FiFI playbook 5", + "org_id": "6666666", + "principal": "fifi", + "recipient": "beefface-46a5-498b-9614-01f2f66fd40b", + "recipient_config": { + "sat_id": "63142926-46a5-498b-9614-01f2f66fd40b", + "sat_org_id": "2", + }, + "url": "https://hostname/api/remediations/v1/remediations/63d92aeb-9351-4216-8d7c-044d171337bc/playbook?hosts=35e9b452-e405-499c-9c6e-120010b7b465&hosts=8728dbf3-6500-44bb-a55c-4909a48673ed&hosts=88d0ba73-0015-4e7d-a6d6-4b530cbfb4ad&hosts=baaad5ad-1b8e-457e-ad43-39d1aea40d4d&hosts=e4a0a6ff-0f01-4659-ad9d-44150ade51dd", + "web_console_url": "https://console.redhat.com/insights/remediations", + }, + { + "hosts": [ + { + "inventory_id": "3fec343b-ecc0-4049-9e30-e4dc2bae9f62", + }, + { + "inventory_id": "9574cba7-b9ce-4725-b392-e959afd3e69a", + }, + { + "inventory_id": "bd91d212-91ae-4813-a406-d2af96fbeb52", + }, + ], + "labels": { + "playbook-run": "b995e750-c1d3-4c5b-a3ec-eee897ee9065", + }, + "name": "FiFI playbook 5", + "org_id": "6666666", + "principal": "fifi", + "recipient": "beefface-64a7-4ee7-a94e-3beed9393972", + "recipient_config": { + "sat_id": "72f44b25-64a7-4ee7-a94e-3beed9393972", + "sat_org_id": "2", + }, + "url": "https://hostname/api/remediations/v1/remediations/63d92aeb-9351-4216-8d7c-044d171337bc/playbook?hosts=3fec343b-ecc0-4049-9e30-e4dc2bae9f62&hosts=9574cba7-b9ce-4725-b392-e959afd3e69a&hosts=bd91d212-91ae-4813-a406-d2af96fbeb52", + "web_console_url": "https://console.redhat.com/insights/remediations", + }, + { + "hosts": [ + { + "inventory_id": "95c5ee0d-9599-475f-a8ef-c838545b9a73", + }, + ], + "labels": { + "playbook-run": "b995e750-c1d3-4c5b-a3ec-eee897ee9065", + }, + "name": "FiFI playbook 5", + "org_id": "6666666", + "principal": "fifi", + "recipient": "beefface-6092-485c-ba04-c656d77f988a", + "recipient_config": { + "sat_id": "01bf542e-6092-485c-ba04-c656d77f988a", + "sat_org_id": "2", + }, + "url": "https://hostname/api/remediations/v1/remediations/63d92aeb-9351-4216-8d7c-044d171337bc/playbook?hosts=95c5ee0d-9599-475f-a8ef-c838545b9a73", + "web_console_url": "https://console.redhat.com/insights/remediations", + }, ] `; exports[`FiFi playbook run POST exclude one of the connected executors 1`] = ` [ - [ - [ + { + "hosts": [ { - "hosts": [ - { - "inventory_id": "2a708189-4b48-4642-9443-64bda5f38e5f", - }, - { - "inventory_id": "36828b63-38f3-4b9a-ad08-0b7812e5df57", - }, - { - "inventory_id": "6f6a889d-6bac-4d53-9bc1-ef75bc1a55ff", - }, - { - "inventory_id": "938c5ce7-481f-4b82-815c-2973ca76a0ef", - }, - ], - "labels": { - "playbook-run": "b995e750-c1d3-4c5b-a3ec-eee897ee9065", - }, - "name": "FiFI playbook 5", - "org_id": "6666666", - "principal": "fifi", - "recipient": "beefface-c7a6-4cc3-89bc-9066ffda695e", - "recipient_config": { - "sat_id": "893f2788-c7a6-4cc3-89bc-9066ffda695e", - "sat_org_id": "6", - }, - "url": "https://hostname/api/remediations/v1/remediations/63d92aeb-9351-4216-8d7c-044d171337bc/playbook?hosts=2a708189-4b48-4642-9443-64bda5f38e5f&hosts=36828b63-38f3-4b9a-ad08-0b7812e5df57&hosts=6f6a889d-6bac-4d53-9bc1-ef75bc1a55ff&hosts=938c5ce7-481f-4b82-815c-2973ca76a0ef", - "web_console_url": "https://console.redhat.com/insights/remediations", + "inventory_id": "2a708189-4b48-4642-9443-64bda5f38e5f", }, { - "hosts": [ - { - "inventory_id": "34360dba-a2e7-4788-b9a2-44246a865c7e", - }, - { - "inventory_id": "64ee45db-6f2b-4862-bc9a-40aea8f5ecbe", - }, - ], - "labels": { - "playbook-run": "b995e750-c1d3-4c5b-a3ec-eee897ee9065", - }, - "name": "FiFI playbook 5", - "org_id": "6666666", - "principal": "fifi", - "recipient": "beefface-c7a6-4cc3-89bc-9066ffda695e", - "recipient_config": { - "sat_id": "893f2788-c7a6-4cc3-89bc-9066ffda695e", - "sat_org_id": "2", - }, - "url": "https://hostname/api/remediations/v1/remediations/63d92aeb-9351-4216-8d7c-044d171337bc/playbook?hosts=34360dba-a2e7-4788-b9a2-44246a865c7e&hosts=64ee45db-6f2b-4862-bc9a-40aea8f5ecbe", - "web_console_url": "https://console.redhat.com/insights/remediations", + "inventory_id": "36828b63-38f3-4b9a-ad08-0b7812e5df57", }, { - "hosts": [ - { - "inventory_id": "35e9b452-e405-499c-9c6e-120010b7b465", - }, - { - "inventory_id": "8728dbf3-6500-44bb-a55c-4909a48673ed", - }, - { - "inventory_id": "88d0ba73-0015-4e7d-a6d6-4b530cbfb4ad", - }, - { - "inventory_id": "baaad5ad-1b8e-457e-ad43-39d1aea40d4d", - }, - { - "inventory_id": "e4a0a6ff-0f01-4659-ad9d-44150ade51dd", - }, - ], - "labels": { - "playbook-run": "b995e750-c1d3-4c5b-a3ec-eee897ee9065", - }, - "name": "FiFI playbook 5", - "org_id": "6666666", - "principal": "fifi", - "recipient": "beefface-46a5-498b-9614-01f2f66fd40b", - "recipient_config": { - "sat_id": "63142926-46a5-498b-9614-01f2f66fd40b", - "sat_org_id": "2", - }, - "url": "https://hostname/api/remediations/v1/remediations/63d92aeb-9351-4216-8d7c-044d171337bc/playbook?hosts=35e9b452-e405-499c-9c6e-120010b7b465&hosts=8728dbf3-6500-44bb-a55c-4909a48673ed&hosts=88d0ba73-0015-4e7d-a6d6-4b530cbfb4ad&hosts=baaad5ad-1b8e-457e-ad43-39d1aea40d4d&hosts=e4a0a6ff-0f01-4659-ad9d-44150ade51dd", - "web_console_url": "https://console.redhat.com/insights/remediations", + "inventory_id": "6f6a889d-6bac-4d53-9bc1-ef75bc1a55ff", }, { - "hosts": [ - { - "inventory_id": "3fec343b-ecc0-4049-9e30-e4dc2bae9f62", - }, - { - "inventory_id": "9574cba7-b9ce-4725-b392-e959afd3e69a", - }, - { - "inventory_id": "bd91d212-91ae-4813-a406-d2af96fbeb52", - }, - ], - "labels": { - "playbook-run": "b995e750-c1d3-4c5b-a3ec-eee897ee9065", - }, - "name": "FiFI playbook 5", - "org_id": "6666666", - "principal": "fifi", - "recipient": "beefface-64a7-4ee7-a94e-3beed9393972", - "recipient_config": { - "sat_id": "72f44b25-64a7-4ee7-a94e-3beed9393972", - "sat_org_id": "2", - }, - "url": "https://hostname/api/remediations/v1/remediations/63d92aeb-9351-4216-8d7c-044d171337bc/playbook?hosts=3fec343b-ecc0-4049-9e30-e4dc2bae9f62&hosts=9574cba7-b9ce-4725-b392-e959afd3e69a&hosts=bd91d212-91ae-4813-a406-d2af96fbeb52", - "web_console_url": "https://console.redhat.com/insights/remediations", + "inventory_id": "938c5ce7-481f-4b82-815c-2973ca76a0ef", }, + ], + "labels": { + "playbook-run": "b995e750-c1d3-4c5b-a3ec-eee897ee9065", + }, + "name": "FiFI playbook 5", + "org_id": "6666666", + "principal": "fifi", + "recipient": "beefface-c7a6-4cc3-89bc-9066ffda695e", + "recipient_config": { + "sat_id": "893f2788-c7a6-4cc3-89bc-9066ffda695e", + "sat_org_id": "6", + }, + "url": "https://hostname/api/remediations/v1/remediations/63d92aeb-9351-4216-8d7c-044d171337bc/playbook?hosts=2a708189-4b48-4642-9443-64bda5f38e5f&hosts=36828b63-38f3-4b9a-ad08-0b7812e5df57&hosts=6f6a889d-6bac-4d53-9bc1-ef75bc1a55ff&hosts=938c5ce7-481f-4b82-815c-2973ca76a0ef", + "web_console_url": "https://console.redhat.com/insights/remediations", + }, + { + "hosts": [ { - "hosts": [ - { - "inventory_id": "95c5ee0d-9599-475f-a8ef-c838545b9a73", - }, - ], - "labels": { - "playbook-run": "b995e750-c1d3-4c5b-a3ec-eee897ee9065", - }, - "name": "FiFI playbook 5", - "org_id": "6666666", - "principal": "fifi", - "recipient": "beefface-6092-485c-ba04-c656d77f988a", - "recipient_config": { - "sat_id": "01bf542e-6092-485c-ba04-c656d77f988a", - "sat_org_id": "2", - }, - "url": "https://hostname/api/remediations/v1/remediations/63d92aeb-9351-4216-8d7c-044d171337bc/playbook?hosts=95c5ee0d-9599-475f-a8ef-c838545b9a73", - "web_console_url": "https://console.redhat.com/insights/remediations", + "inventory_id": "34360dba-a2e7-4788-b9a2-44246a865c7e", }, { - "hosts": [ - { - "ansible_host": "localhost", - "inventory_id": "0341e468-fbae-416c-b16f-5abb64d99834", - }, - ], - "labels": { - "playbook-run": "b995e750-c1d3-4c5b-a3ec-eee897ee9065", - }, - "name": "FiFI playbook 5", - "org_id": "6666666", - "principal": "fifi", - "recipient": "0341e468-fbae-416c-b16f-5abb64d99834", - "url": "https://hostname/api/remediations/v1/remediations/63d92aeb-9351-4216-8d7c-044d171337bc/playbook?hosts=0341e468-fbae-416c-b16f-5abb64d99834&localhost", - "web_console_url": "https://console.redhat.com/insights/remediations", + "inventory_id": "64ee45db-6f2b-4862-bc9a-40aea8f5ecbe", + }, + ], + "labels": { + "playbook-run": "b995e750-c1d3-4c5b-a3ec-eee897ee9065", + }, + "name": "FiFI playbook 5", + "org_id": "6666666", + "principal": "fifi", + "recipient": "beefface-c7a6-4cc3-89bc-9066ffda695e", + "recipient_config": { + "sat_id": "893f2788-c7a6-4cc3-89bc-9066ffda695e", + "sat_org_id": "2", + }, + "url": "https://hostname/api/remediations/v1/remediations/63d92aeb-9351-4216-8d7c-044d171337bc/playbook?hosts=34360dba-a2e7-4788-b9a2-44246a865c7e&hosts=64ee45db-6f2b-4862-bc9a-40aea8f5ecbe", + "web_console_url": "https://console.redhat.com/insights/remediations", + }, + { + "hosts": [ + { + "inventory_id": "35e9b452-e405-499c-9c6e-120010b7b465", }, { - "hosts": [ - { - "ansible_host": "localhost", - "inventory_id": "750c60ee-b67e-4ccd-8d7f-cb8aed2bdbf4", - }, - ], - "labels": { - "playbook-run": "b995e750-c1d3-4c5b-a3ec-eee897ee9065", - }, - "name": "FiFI playbook 5", - "org_id": "6666666", - "principal": "fifi", - "recipient": "750c60ee-b67e-4ccd-8d7f-cb8aed2bdbf4", - "url": "https://hostname/api/remediations/v1/remediations/63d92aeb-9351-4216-8d7c-044d171337bc/playbook?hosts=750c60ee-b67e-4ccd-8d7f-cb8aed2bdbf4&localhost", - "web_console_url": "https://console.redhat.com/insights/remediations", + "inventory_id": "8728dbf3-6500-44bb-a55c-4909a48673ed", }, { - "hosts": [ - { - "ansible_host": "localhost", - "inventory_id": "d5174274-4307-4fac-84fd-da2c3497657c", - }, - ], - "labels": { - "playbook-run": "b995e750-c1d3-4c5b-a3ec-eee897ee9065", - }, - "name": "FiFI playbook 5", - "org_id": "6666666", - "principal": "fifi", - "recipient": "d5174274-4307-4fac-84fd-da2c3497657c", - "url": "https://hostname/api/remediations/v1/remediations/63d92aeb-9351-4216-8d7c-044d171337bc/playbook?hosts=d5174274-4307-4fac-84fd-da2c3497657c&localhost", - "web_console_url": "https://console.redhat.com/insights/remediations", + "inventory_id": "88d0ba73-0015-4e7d-a6d6-4b530cbfb4ad", + }, + { + "inventory_id": "baaad5ad-1b8e-457e-ad43-39d1aea40d4d", + }, + { + "inventory_id": "e4a0a6ff-0f01-4659-ad9d-44150ade51dd", }, ], - ], + "labels": { + "playbook-run": "b995e750-c1d3-4c5b-a3ec-eee897ee9065", + }, + "name": "FiFI playbook 5", + "org_id": "6666666", + "principal": "fifi", + "recipient": "beefface-46a5-498b-9614-01f2f66fd40b", + "recipient_config": { + "sat_id": "63142926-46a5-498b-9614-01f2f66fd40b", + "sat_org_id": "2", + }, + "url": "https://hostname/api/remediations/v1/remediations/63d92aeb-9351-4216-8d7c-044d171337bc/playbook?hosts=35e9b452-e405-499c-9c6e-120010b7b465&hosts=8728dbf3-6500-44bb-a55c-4909a48673ed&hosts=88d0ba73-0015-4e7d-a6d6-4b530cbfb4ad&hosts=baaad5ad-1b8e-457e-ad43-39d1aea40d4d&hosts=e4a0a6ff-0f01-4659-ad9d-44150ade51dd", + "web_console_url": "https://console.redhat.com/insights/remediations", + }, + { + "hosts": [ + { + "inventory_id": "3fec343b-ecc0-4049-9e30-e4dc2bae9f62", + }, + { + "inventory_id": "9574cba7-b9ce-4725-b392-e959afd3e69a", + }, + { + "inventory_id": "bd91d212-91ae-4813-a406-d2af96fbeb52", + }, + ], + "labels": { + "playbook-run": "b995e750-c1d3-4c5b-a3ec-eee897ee9065", + }, + "name": "FiFI playbook 5", + "org_id": "6666666", + "principal": "fifi", + "recipient": "beefface-64a7-4ee7-a94e-3beed9393972", + "recipient_config": { + "sat_id": "72f44b25-64a7-4ee7-a94e-3beed9393972", + "sat_org_id": "2", + }, + "url": "https://hostname/api/remediations/v1/remediations/63d92aeb-9351-4216-8d7c-044d171337bc/playbook?hosts=3fec343b-ecc0-4049-9e30-e4dc2bae9f62&hosts=9574cba7-b9ce-4725-b392-e959afd3e69a&hosts=bd91d212-91ae-4813-a406-d2af96fbeb52", + "web_console_url": "https://console.redhat.com/insights/remediations", + }, + { + "hosts": [ + { + "inventory_id": "95c5ee0d-9599-475f-a8ef-c838545b9a73", + }, + ], + "labels": { + "playbook-run": "b995e750-c1d3-4c5b-a3ec-eee897ee9065", + }, + "name": "FiFI playbook 5", + "org_id": "6666666", + "principal": "fifi", + "recipient": "beefface-6092-485c-ba04-c656d77f988a", + "recipient_config": { + "sat_id": "01bf542e-6092-485c-ba04-c656d77f988a", + "sat_org_id": "2", + }, + "url": "https://hostname/api/remediations/v1/remediations/63d92aeb-9351-4216-8d7c-044d171337bc/playbook?hosts=95c5ee0d-9599-475f-a8ef-c838545b9a73", + "web_console_url": "https://console.redhat.com/insights/remediations", + }, + { + "hosts": [ + { + "ansible_host": "localhost", + "inventory_id": "0341e468-fbae-416c-b16f-5abb64d99834", + }, + ], + "labels": { + "playbook-run": "b995e750-c1d3-4c5b-a3ec-eee897ee9065", + }, + "name": "FiFI playbook 5", + "org_id": "6666666", + "principal": "fifi", + "recipient": "0341e468-fbae-416c-b16f-5abb64d99834", + "url": "https://hostname/api/remediations/v1/remediations/63d92aeb-9351-4216-8d7c-044d171337bc/playbook?hosts=0341e468-fbae-416c-b16f-5abb64d99834&localhost", + "web_console_url": "https://console.redhat.com/insights/remediations", + }, + { + "hosts": [ + { + "ansible_host": "localhost", + "inventory_id": "750c60ee-b67e-4ccd-8d7f-cb8aed2bdbf4", + }, + ], + "labels": { + "playbook-run": "b995e750-c1d3-4c5b-a3ec-eee897ee9065", + }, + "name": "FiFI playbook 5", + "org_id": "6666666", + "principal": "fifi", + "recipient": "750c60ee-b67e-4ccd-8d7f-cb8aed2bdbf4", + "url": "https://hostname/api/remediations/v1/remediations/63d92aeb-9351-4216-8d7c-044d171337bc/playbook?hosts=750c60ee-b67e-4ccd-8d7f-cb8aed2bdbf4&localhost", + "web_console_url": "https://console.redhat.com/insights/remediations", + }, + { + "hosts": [ + { + "ansible_host": "localhost", + "inventory_id": "d5174274-4307-4fac-84fd-da2c3497657c", + }, + ], + "labels": { + "playbook-run": "b995e750-c1d3-4c5b-a3ec-eee897ee9065", + }, + "name": "FiFI playbook 5", + "org_id": "6666666", + "principal": "fifi", + "recipient": "d5174274-4307-4fac-84fd-da2c3497657c", + "url": "https://hostname/api/remediations/v1/remediations/63d92aeb-9351-4216-8d7c-044d171337bc/playbook?hosts=d5174274-4307-4fac-84fd-da2c3497657c&localhost", + "web_console_url": "https://console.redhat.com/insights/remediations", + }, ] `; diff --git a/src/remediations/controller.fifi.js b/src/remediations/controller.fifi.js index 48c99e6c..18bcd7a9 100644 --- a/src/remediations/controller.fifi.js +++ b/src/remediations/controller.fifi.js @@ -17,15 +17,14 @@ const notFound = res => res.sendStatus(404); exports.checkExecutable = errors.async(async function (req, res) { const remediation = await queries.get(req.params.id, req.user.tenant_org_id, req.user.username); - if (!remediation) { return notFound(res); } - const executable = await fifi.checkSmartManagement(remediation, req.entitlements.smart_management); + const executable = await fifi.checkSmartManagement(req, remediation, req.entitlements.smart_management); if (!executable) { - throw new errors.Forbidden(); + throw new errors.Forbidden(req); } res.sendStatus(200); @@ -44,6 +43,7 @@ exports.cancelPlaybookRuns = errors.async(async function (req, res) { } await fifi.cancelPlaybookRun( + req, req.user.account_number, req.identity.org_id, req.params.playbook_run_id, @@ -65,14 +65,14 @@ exports.listPlaybookRuns = errors.async(async function (req, res) { remediation = remediation.toJSON(); // Join rhcRuns and playbookRuns - remediation.playbook_runs = await fifi.combineRuns(remediation); + remediation.playbook_runs = await fifi.combineRuns(req, remediation); const total = fifi.getListSize(remediation.playbook_runs); remediation.playbook_runs = await fifi.pagination(remediation.playbook_runs, total, limit, offset); if (_.isNull(remediation)) { - throw errors.invalidOffset(offset, total); + throw errors.invalidOffset(req, offset, total); } remediation = await fifi.resolveUsers(req, remediation); @@ -101,7 +101,7 @@ exports.getRunDetails = errors.async(async function (req, res) { remediation = remediation.toJSON(); // Join rhcRuns and playbookRuns - remediation.playbook_runs = await fifi.combineRuns(remediation); + remediation.playbook_runs = await fifi.combineRuns(req, remediation); remediation = await fifi.resolveUsers(req, remediation); @@ -130,7 +130,7 @@ exports.getSystems = errors.async(async function (req, res) { req.user.tenant_org_id, req.user.username ), - fifi.getRHCRuns(req.params.playbook_run_id) + fifi.getRHCRuns(req, req.params.playbook_run_id) ]); // Ugh... so here are the possibilities: @@ -155,10 +155,12 @@ exports.getSystems = errors.async(async function (req, res) { if (!_.isEmpty(rhcRuns)) { trace.event('Combine rhc and receptor systems...') await fifi.combineHosts( + req, rhcRuns, systems, req.params.playbook_run_id, - req.query.ansible_host); + req.query.ansible_host + ); } } @@ -186,7 +188,7 @@ exports.getSystems = errors.async(async function (req, res) { trace.event('paginate...'); const total = fifi.getListSize(systems); if (offset >= Math.max(total, 1)) { - throw errors.invalidOffset(offset, total); + throw errors.invalidOffset(req, offset, total); } systems = fifi.pagination(systems, total, limit, offset); @@ -219,7 +221,7 @@ exports.getSystemDetails = errors.async(async function (req, res) { if (!system) { // rhc-direct or rhc-satellite system trace.event('get RHC system/satellite details from playbook-dispatcher'); - system = await fifi.getRunHostDetails(req.params.playbook_run_id, req.params.system); + system = await fifi.getRunHostDetails(req.params.playbook_run_id, req.params.system, req); if (!system) { trace.leave('RHC system/satellite not found!'); diff --git a/src/remediations/controller.fifi_2.js b/src/remediations/controller.fifi_2.js index dc4e8a13..38aea954 100644 --- a/src/remediations/controller.fifi_2.js +++ b/src/remediations/controller.fifi_2.js @@ -38,7 +38,7 @@ exports.connection_status = errors.async(async function (req, res) { if (!rhcEnabled) { // 403 if remediations not enabled - throw new errors.Forbidden(); + throw new errors.Forbidden(req); } //-------------------------------------------------------------- @@ -61,7 +61,7 @@ exports.connection_status = errors.async(async function (req, res) { hosts: systemIds }; - const recipients = await dispatcher.getConnectionStatus(connectionStatusRequest); + const recipients = await dispatcher.getConnectionStatus(req, connectionStatusRequest); //----------------- // process e-tag @@ -111,7 +111,7 @@ exports.executePlaybookRuns = errors.async(async function (req, res) { if (!rhcEnabled) { // 403 if remediations not enabled - throw new errors.Forbidden(); + throw new errors.Forbidden(req); } //-------------------------------------------------------------- @@ -128,7 +128,7 @@ exports.executePlaybookRuns = errors.async(async function (req, res) { if (systemIds.length === 0) { // no systems - throw errors.noSystems(remediation); + throw errors.noSystems(req, remediation); } //----------------------------------------------- @@ -139,7 +139,7 @@ exports.executePlaybookRuns = errors.async(async function (req, res) { hosts: systemIds }; - const recipients = await dispatcher.getConnectionStatus(connectionStatusRequest); + const recipients = await dispatcher.getConnectionStatus(req, connectionStatusRequest); log.error(`Requested status for ${connectionStatusRequest.hosts.length} hosts, received: ${JSON.stringify(recipients)}`); //----------------- @@ -158,6 +158,7 @@ exports.executePlaybookRuns = errors.async(async function (req, res) { // createPlaybookRun //-------------------------------------------------- const result = await fifi.createPlaybookRun( + req, recipients, exclude, remediation, @@ -165,7 +166,7 @@ exports.executePlaybookRuns = errors.async(async function (req, res) { ); if (_.isNull(result)) { - throw errors.noExecutors(remediation); + throw errors.noExecutors(req, remediation); } res.status(201).send({id: result}); diff --git a/src/remediations/controller.read.js b/src/remediations/controller.read.js index d5a8d9ff..7fbb7210 100644 --- a/src/remediations/controller.read.js +++ b/src/remediations/controller.read.js @@ -31,11 +31,11 @@ const catchErrorCode = (code, fn) => e => { throw e; }; -function resolveResolutions (...remediations) { +function resolveResolutions (req, ...remediations) { return P.all(_(remediations).flatMap('issues').map(async issue => { - const id = identifiers.parse(issue.issue_id); - const resolutions = await issues.getHandler(id).getResolutionResolver().resolveResolutions(id); - const resolution = disambiguator.disambiguate(resolutions, issue.resolution, id, false, false); + const id = identifiers.parse(req, issue.issue_id); + const resolutions = await issues.getHandler(id, req).getResolutionResolver().resolveResolutions(req, id); + const resolution = disambiguator.disambiguate(req, resolutions, issue.resolution, id, false, false); if (resolution) { issue.resolution = resolution; @@ -46,10 +46,10 @@ function resolveResolutions (...remediations) { }).value()); } -function resolveResolutionsNeedReboot (...remediations) { +function resolveResolutionsNeedReboot (req, ...remediations) { return P.all(_(remediations).flatMap('issues').map(async issue => { - const id = identifiers.parse(issue.issue_id); - const needsReboot = await issues.getHandler(id).getResolutionResolver().isRebootNeeded(id, issue.resolution); + const id = identifiers.parse(req, issue.issue_id); + const needsReboot = await issues.getHandler(id, req).getResolutionResolver().isRebootNeeded(req, id, issue.resolution); if (needsReboot !== null) { issue.resolution = { needsReboot }; @@ -68,7 +68,7 @@ exports.getUsers = async function (req, usernames) { }; } - const resolvedUsers = await P.map(usernames, username => users.getUser(username)); + const resolvedUsers = await P.map(usernames, username => users.getUser(req, username)); return _.keyBy(resolvedUsers, 'username'); }; @@ -104,7 +104,7 @@ exports.list = errors.async(async function (req, res) { trace.enter('controller.read.list'); if (_.get(req, 'query.fields.data', []).includes('name') && Array.isArray(_.get(req, 'query.fields.data', []))) { - throw new errors.BadRequest('INVALID_REQUEST', `'name' cannot be combined with other fields.`); + throw new errors.BadRequest(req, 'INVALID_REQUEST', `'name' cannot be combined with other fields.`); } trace.event('Get sort and query parms from url'); @@ -147,7 +147,7 @@ exports.list = errors.async(async function (req, res) { trace.event('Validate offset query parm'); if (offset >= Math.max(count.length, 1)) { - throw errors.invalidOffset(offset, count.length - 1); + throw errors.invalidOffset(req, offset, count.length - 1); } trace.event('Fetch remediation details from DB'); @@ -162,13 +162,13 @@ exports.list = errors.async(async function (req, res) { trace.event('Resolve user names and reboot flag'); await P.all([ - resolveResolutionsNeedReboot(...remediations), + resolveResolutionsNeedReboot(req, ...remediations), resolveUsers(req, ...remediations) ]); // Add 'details' if they exist to each issue in remediation.issues trace.event('Fetch issue details'); - await P.map(remediations, remediation => resolveIssues(remediation)); + await P.map(remediations, remediation => resolveIssues(remediation, req)); trace.event('Remove empty issues'); remediations.forEach(remediation => { @@ -209,7 +209,7 @@ exports.list = errors.async(async function (req, res) { // Join rhcRuns and playbookRuns trace.event(`[${local_iteration}] Combine runs`); playbook_runs.iteration = local_iteration; - playbook_runs.playbook_runs = await fifi.combineRuns(playbook_runs); + playbook_runs.playbook_runs = await fifi.combineRuns(req, playbook_runs); trace.event(`[${local_iteration}] Resolve users`); playbook_runs = await fifi.resolveUsers(req, playbook_runs); @@ -233,11 +233,11 @@ exports.list = errors.async(async function (req, res) { return res.json(resp); }); -async function resolveSystems (remediation) { +async function resolveSystems (remediation, req) { const systems = _.flatMap(remediation.issues, 'systems'); const ids = _(systems).map('system_id').uniq().value(); - const resolvedSystems = await inventory.getSystemDetailsBatch(ids); + const resolvedSystems = await inventory.getSystemDetailsBatch(req, ids); remediation.issues.forEach(issue => issue.systems = issue.systems .filter(({system_id}) => _.has(resolvedSystems, system_id)) // filter out systems not found in inventory @@ -249,10 +249,10 @@ async function resolveSystems (remediation) { })); } -function resolveIssues (remediation) { +function resolveIssues (remediation, req) { return P.map(remediation.issues, async issue => { - const id = identifiers.parse(issue.issue_id); - return issues.getIssueDetails(id) + const id = identifiers.parse(req, issue.issue_id); + return issues.getIssueDetails(id, req) .then(result => issue.details = result) .catch(catchErrorCode('UNKNOWN_ISSUE', () => issue.details = false)); }); @@ -270,9 +270,9 @@ exports.get = errors.async(async function (req, res) { } await P.all([ - resolveSystems(remediation), - resolveResolutions(remediation), - resolveIssues(remediation), + resolveSystems(remediation, req), + resolveResolutions(req, remediation), + resolveIssues(remediation, req), resolveUsers(req, remediation) ]); @@ -343,7 +343,7 @@ exports.playbook = errors.async(async function (req, res) { // remove any systems not in specified satellite organization if (sat_org_id) { - const batchDetailInfo = await inventory.getSystemDetailsBatch(all_systems); + const batchDetailInfo = await inventory.getSystemDetailsBatch(req, all_systems); _.forEach(normalizedIssues, issue => { issue.systems = _.filter(issue.systems, system => { // eslint-disable-next-line security/detect-object-injection @@ -359,7 +359,7 @@ exports.playbook = errors.async(async function (req, res) { // validate system ownership if using certificate authentication if (cert_auth) { - const batchProfileInfo = await inventory.getSystemProfileBatch(all_systems); + const batchProfileInfo = await inventory.getSystemProfileBatch(req, all_systems); if (_.isEmpty(batchProfileInfo)) { return notFound(res); // Eh, this is really more of an internal error... @@ -373,7 +373,7 @@ exports.playbook = errors.async(async function (req, res) { // eslint-disable-next-line security/detect-object-injection const ownerId = batchProfileInfo[system].system_profile.owner_id; if (!_.isEqual(req.identity.system.cn, ownerId)) { - throw errors.unauthorizedGeneration(req.identity.system.cn); + throw errors.unauthorizedGeneration(req, req.identity.system.cn); } }); } @@ -391,7 +391,7 @@ exports.playbook = errors.async(async function (req, res) { const playbook = await generator.playbookPipeline({ issues: normalizedIssues, auto_reboot: remediation.auto_reboot - }, remediation, false, localhost); + }, req, remediation, false, localhost); if (!playbook) { return noContent(res); @@ -431,7 +431,7 @@ exports.downloadPlaybooks = errors.async(async function (req, res) { const playbook = await generator.playbookPipeline({ issues: normalizedIssues, auto_reboot: remediation.auto_reboot - }, remediation, false); + }, req, remediation, false); if (!playbook) { generateZip = false; @@ -467,7 +467,7 @@ exports.getIssueSystems = errors.async(async function (req, res) { return notFound(res); } - await resolveSystems(remediation); + await resolveSystems(remediation, req); // filter out issues with 0 systems remediation.issues = remediation.issues.filter(issue => issue.systems.length); @@ -483,7 +483,7 @@ exports.getIssueSystems = errors.async(async function (req, res) { remediation.issues[0].systems = await fifi.pagination(remediation.issues[0].systems, total, limit, offset); if (_.isNull(remediation.issues[0].systems)) { - throw errors.invalidOffset(offset, total); + throw errors.invalidOffset(req, offset, total); } res.json(format.issueSystems(remediation.issues[0], total)); diff --git a/src/remediations/controller.status.js b/src/remediations/controller.status.js index bf2a1dec..758d653f 100644 --- a/src/remediations/controller.status.js +++ b/src/remediations/controller.status.js @@ -10,15 +10,15 @@ const AdvisorHandler = require('../issues/AdvisorHandler'); const CVEHandler = require('../issues/CVEHandler'); const trace = require("../util/trace"); -async function resolveStatus (issue) { +async function resolveStatus (issue, req) { trace.enter('status.resolveStatus'); trace.event(`Get handler for issue: ${issue.id}`); - const handler = issues.getHandler(issue.id); + const handler = issues.getHandler(issue.id, req); if (handler instanceof AdvisorHandler || handler instanceof CVEHandler) { trace.event('Get systems for Advisor or CVE issues'); - const affectedSystems = await handler.getSystems(issue.id); + const affectedSystems = await handler.getSystems(issue.id, req); // TODO: this is quite inefficient trace.event(`Filter issue systems: ${issue.systems}`); issue.systems = _.mapValues(issue.systems, (value, key) => !affectedSystems.includes(key)); @@ -42,12 +42,12 @@ exports.status = errors.async(async function (req, res) { trace.event(`Collect array of issues with parsed identifier and system_ids: ${remediation.issues}`); const issues = _.map(remediation.issues, issue => ({ ...issue, - id: identifiers.parse(issue.issue_id), + id: identifiers.parse(req, issue.issue_id), systems: _(issue.systems).keyBy('system_id').mapValues(() => null).value() })); trace.event(`Resolve status of all issues: ${issues}`); - await P.map(issues, resolveStatus); + await P.map(issues, issue => resolveStatus(issue, req)); const result = { summary: { diff --git a/src/remediations/controller.write.js b/src/remediations/controller.write.js index f0fc50a3..964a9ee3 100644 --- a/src/remediations/controller.write.js +++ b/src/remediations/controller.write.js @@ -15,13 +15,13 @@ const disambiguator = require('../resolutions/disambiguator'); const notFound = res => res.status(404).json(); -async function validateResolution (id, resolutionId) { - const identifier = identifiers.parse(id); - const resolutions = await issues.getHandler(identifier).getResolutionResolver().resolveResolutions(identifier); - disambiguator.disambiguate(resolutions, resolutionId, identifier); +async function validateResolution (id, resolutionId, req) { + const identifier = identifiers.parse(req, id); + const resolutions = await issues.getHandler(identifier, req).getResolutionResolver().resolveResolutions(req, identifier); + disambiguator.disambiguate(req, resolutions, resolutionId, identifier); } -async function validateNewActions(add) { +async function validateNewActions(add, req) { // normalize and validate add.issues.forEach(issue => { if (!issue.systems && add.systems) { @@ -29,13 +29,13 @@ async function validateNewActions(add) { } if (!issue.systems || !issue.systems.length) { - throw new errors.BadRequest('NO_SYSTEMS', `Systems not specified for "${issue.id}"`); + throw new errors.BadRequest(req, 'NO_SYSTEMS', `Systems not specified for "${issue.id}"`); } }); const duplicateIssues = _(add.issues).groupBy('id').pickBy(value => value.length > 1).value(); if (_.size(duplicateIssues)) { - throw new errors.BadRequest('DUPLICATE_ISSUE', + throw new errors.BadRequest(req, 'DUPLICATE_ISSUE', `Issue "${Object.keys(duplicateIssues)[0]}" specified more than once in the issue list`); } @@ -43,14 +43,14 @@ async function validateNewActions(add) { // TODO: might be better to call these before the transaction const [systemsById] = await P.all([ - inventory.getSystemDetailsBatch(systems), - P.all(add.issues.map(issue => validateResolution(issue.id, issue.resolution))) + inventory.getSystemDetailsBatch(req, systems), + P.all(add.issues.map(issue => validateResolution(issue.id, issue.resolution, req))) ]); // verify systems identifiers are valid systems.forEach(system => { if (!systemsById.hasOwnProperty(system)) { - throw errors.unknownSystem(system); + throw errors.unknownSystem(req, system); } }); } @@ -107,7 +107,7 @@ exports.create = errors.async(async function (req, res) { const {add, name, auto_reboot} = req.body; if (add) { - await validateNewActions(add); + await validateNewActions(add, req); } const id = uuid.v4(); @@ -142,11 +142,11 @@ exports.patch = errors.async(async function (req, res) { if (_.isUndefined(add) && _.isUndefined(name) && _.isUndefined(auto_reboot) && _.isUndefined(archived)) { // eslint-disable-next-line max-len - throw new errors.BadRequest('EMPTY_REQUEST', 'At least one of "add", "name", "auto_reboot", "archived" needs to be specified'); + throw new errors.BadRequest(req, 'EMPTY_REQUEST', 'At least one of "add", "name", "auto_reboot", "archived" needs to be specified'); } if (add) { - await validateNewActions(add); + await validateNewActions(add, req); } const result = await db.s.transaction(async transaction => { @@ -195,7 +195,7 @@ exports.patchIssue = errors.async(async function (req, res) { const { resolution: rid } = req.body; // validate that the given resolution exists - await validateResolution(iid, rid); + await validateResolution(iid, rid, req); const result = await db.s.transaction(async transaction => { const issue = await db.issue.findOne(findIssueQuery(req), {transaction}); diff --git a/src/remediations/fifi.integration.js b/src/remediations/fifi.integration.js index 37c045e1..83cbd065 100644 --- a/src/remediations/fifi.integration.js +++ b/src/remediations/fifi.integration.js @@ -23,22 +23,31 @@ const config = require('../config'); const db = require('../db'); const { systems } = require('../connectors/inventory/impl.unit.data'); +const REQ = { + headers: { + 'x-rh-identity': 'identity', + 'x-rh-insights-request-id': 'request-id' + }, + identity: { type: 'test' }, + user: { username: 'test', account_number: 'test' } +}; + // Helper functions -function fake_doHttp(req) { - const uri = new URI(req.uri); +function fake_doHttp(req, options) { + const uri = new URI(options.uri); const path = uri.path(); if (path === '/api/playbook-dispatcher/v1/runs') - return fake_dispatcher_runs(req); + return fake_dispatcher_runs(req, options); if (path === '/api/playbook-dispatcher/v1/run_hosts') - return fake_dispatcher_run_hosts(req); + return fake_dispatcher_run_hosts(req, options); return Promise.resolve({}); } -function fake_dispatcher_runs(req) { - const uri = new URI(req.uri); +function fake_dispatcher_runs(req, options) { + const uri = new URI(options.uri); const params = queryString.parse(uri.query()); const offset = parseInt(params.offset) || 0; @@ -80,8 +89,8 @@ function fake_dispatcher_runs(req) { } // For now, this just fakes a single run host for direct targets -function fake_dispatcher_run_hosts(req) { - const uri = new URI(req.uri); +function fake_dispatcher_run_hosts(req, options) { + const uri = new URI(options.uri); const params = queryString.parse(uri.query()); // construct response @@ -1076,7 +1085,7 @@ describe('FiFi', function () { // c061da50-e9eb-43be-9cea-751a8d64d8d9 // b76f065b-2ec6-4022-8bde-91dc1df6b344 - const result = dispatcher_mock.getConnectionStatus(TEST_DATA); + const result = dispatcher_mock.getConnectionStatus(REQ, TEST_DATA); // await request // .post('/v1/remediations/0ecb5db7-2f1a-441b-8220-e5ce45066f50/playbook_runs') @@ -1219,11 +1228,11 @@ describe('FiFi', function () { spy.callCount.should.equal(1); - const payload = spy.firstCall.args[0]; + const payload = spy.firstCall.args[1]; payload.should.have.length(8); - expect(spy.args).toMatchSnapshot(); + expect(spy.args[0][1]).toMatchSnapshot(); }); test('exclude all connected connectors and return 400 NO_EXECUTORS', async function () { @@ -1260,7 +1269,7 @@ describe('FiFi', function () { .set(auth.fifi) .expect(201); - expect(spy.args).toMatchSnapshot(); + expect(spy.args[0][1]).toMatchSnapshot(); }); test('post playbook_runs with wrong exclude statement', async function () { @@ -1554,7 +1563,7 @@ describe('FiFi', function () { test.skip('if 1st executor result from receptor connector is request error', async function () { base.getSandbox().stub(receptor, 'postInitialRequest') - .rejects(errors.internal.dependencyError(new Error('receptor down'), receptor)); + .rejects(errors.internal.dependencyError(REQ, new Error('receptor down'), receptor)); const {body} = await request .post('/v1/remediations/63d92aeb-9351-4216-8d7c-044d171337bc/playbook_runs') @@ -1569,7 +1578,7 @@ describe('FiFi', function () { test('if 2nd executor result from receptor is request error', async function () { const stub = base.getSandbox().stub(receptor, 'postInitialRequest'); stub.callThrough(); - stub.onSecondCall().rejects(errors.internal.dependencyError(new Error('receptor down'), receptor)); + stub.onSecondCall().rejects(errors.internal.dependencyError(REQ, new Error('receptor down'), receptor)); const {body} = await request .post('/v1/remediations/63d92aeb-9351-4216-8d7c-044d171337bc/playbook_runs') @@ -1587,14 +1596,14 @@ describe('FiFi', function () { .expect(202); spy.callCount.should.equal(2); - spy.firstCall.args[0].should.eql({ + spy.firstCall.args[1].should.eql({ account: 'fifi', recipient: 'Job-1', payload: '{"type":"playbook_run_cancel","playbook_run_id":"88d0ba73-0015-4e7d-a6d6-4b530cbfb5bc"}', directive: 'receptor_satellite:cancel' }); - spy.secondCall.args[0].should.eql({ + spy.secondCall.args[1].should.eql({ account: 'fifi', recipient: 'Job-2', payload: '{"type":"playbook_run_cancel","playbook_run_id":"88d0ba73-0015-4e7d-a6d6-4b530cbfb5bc"}', @@ -1611,7 +1620,7 @@ describe('FiFi', function () { spy.callCount.should.equal(1); - spy.firstCall.args[0].should.eql([{ + spy.firstCall.args[1].should.eql([{ run_id: '88d0ba73-0015-4e7d-a6d6-4b530cbfb7bc', org_id: '6666666', principal: 'fifi' @@ -1677,8 +1686,18 @@ describe('FiFi', function () { }); test('if RBAC connector fails a dependency error is returned', async function () { + const ID_REQ = { + headers: { + 'x-rh-identity': 'identity', + 'x-rh-insights-request-id': 'request-id' + }, + id: '77d92aeb-9351-4216-8d7c-044d171437bc', + identity: { type: 'test' }, + user: { username: 'test', account_number: 'test' } + }; + base.getSandbox().stub(rbac, 'getRemediationsAccess') - .rejects(errors.internal.dependencyError(new Error('rbac down'), rbac)); + .rejects(errors.internal.dependencyError(ID_REQ, new Error('rbac down'), rbac)); const {body} = await request .post('/v1/remediations/63d92aeb-9351-4216-8d7c-044d171337bc/playbook_runs') @@ -1789,7 +1808,7 @@ describe('FiFi', function () { test('create playbook run (with 2nd executor failing)', async () => { const stub = base.getSandbox().stub(receptor, 'postInitialRequest'); stub.callThrough(); - stub.onSecondCall().rejects(errors.internal.dependencyError(new Error('receptor down'), receptor)); + stub.onSecondCall().rejects(errors.internal.dependencyError(REQ, new Error('receptor down'), receptor)); const {body: post} = await request .post('/v1/remediations/d12efef0-9580-4c82-b604-9888e2269c5a/playbook_runs') diff --git a/src/remediations/fifi.js b/src/remediations/fifi.js index 3dd15f18..06bd57af 100644 --- a/src/remediations/fifi.js +++ b/src/remediations/fifi.js @@ -45,7 +45,8 @@ const SUCCESS = 'success'; const CANCELED = 'canceled'; const SERVICE = 'remediations'; -exports.checkSmartManagement = async function (remediation, smart_management) { +// Aren't we removing this? +exports.checkSmartManagement = async function (req, remediation, smart_management) { // if customer has smart_management entitlement fastlane them if (smart_management) { return true; @@ -57,7 +58,7 @@ exports.checkSmartManagement = async function (remediation, smart_management) { } const systemsIds = _(remediation.issues).flatMap('systems').map('system_id').uniq().sort().value(); - const systemsProfiles = await inventory.getSystemProfileBatch(systemsIds); + const systemsProfiles = await inventory.getSystemProfileBatch(req, systemsIds); return _.some(systemsProfiles, system => system.system_profile.is_marketplace === true); }; @@ -133,7 +134,7 @@ function findRunStatus (run) { // Create array of maps: one representing all RCH-direct hosts, and one for each RHC-satellite // Compute aggregate system_count, status counts and overall status for each -async function formatRHCRuns (rhcRuns, playbook_run_id) { +async function formatRHCRuns (req, rhcRuns, playbook_run_id) { trace.enter('fifi.js[formatRHCRuns]'); // rhcRuns contains all the dispatcher runs for this playbook_run_id @@ -161,7 +162,7 @@ async function formatRHCRuns (rhcRuns, playbook_run_id) { for (const run of rhcRuns.data) { // get dispatcher run hosts const runHostsFilter = createDispatcherRunHostsFilter(run.labels['playbook-run'], run.id); - const rhcRunHosts = await dispatcher.fetchPlaybookRunHosts(runHostsFilter, RHCRUNFIELDS); + const rhcRunHosts = await dispatcher.fetchPlaybookRunHosts(req, runHostsFilter, RHCRUNFIELDS); // If host === 'localhost' then add to RHCDirect if (_.get(rhcRunHosts, 'data[0][host]') === 'localhost') { rhcDirect.playbook = run.url; @@ -217,14 +218,14 @@ async function formatRHCRuns (rhcRuns, playbook_run_id) { } -exports.formatRunHosts = async function (rhcRuns, playbook_run_id) { +exports.formatRunHosts = async function (rhcRuns, playbook_run_id, req) { let hosts = []; if (rhcRuns?.data) { for (const run of rhcRuns.data) { // get dispatcher run hosts... const runHostsFilter = createDispatcherRunHostsFilter(playbook_run_id, run.id); - const rhcRunHosts = await dispatcher.fetchPlaybookRunHosts(runHostsFilter, RHCRUNFIELDS); + const rhcRunHosts = await dispatcher.fetchPlaybookRunHosts(req, runHostsFilter, RHCRUNFIELDS); hosts.push(..._.map(rhcRunHosts.data, host => ({ system_id: host.inventory_id, @@ -269,14 +270,14 @@ function pushRHCExecutor (rhcRuns, satRun) { } } -exports.getRHCRuns = async function (playbook_run_id = null) { +exports.getRHCRuns = async function (req, playbook_run_id = null) { const filter = createDispatcherRunsFilter(playbook_run_id); - const rhcRuns = await dispatcher.fetchPlaybookRuns(filter, RUNSFIELDS); + const rhcRuns = await dispatcher.fetchPlaybookRuns(req, filter, RUNSFIELDS); return rhcRuns; }; -exports.getRunHostDetails = async function (playbook_run_id, system_id) { +exports.getRunHostDetails = async function (playbook_run_id, system_id, req) { trace.enter('fifi.getRunHostDetails'); // So... given the remediations playbook_run_id and a system_id find the matching // dispatcher run_hosts entry. /dispatcher/runs?playbook_run_id will return an @@ -286,7 +287,7 @@ exports.getRunHostDetails = async function (playbook_run_id, system_id) { const runsFilter = createDispatcherRunsFilter(playbook_run_id); trace.event(`fetch playbook-dispatcher/v1/runs with filter: ${JSON.stringify(runsFilter)}`); - const rhcRuns = await dispatcher.fetchPlaybookRuns(runsFilter, RUNSFIELDS); + const rhcRuns = await dispatcher.fetchPlaybookRuns(req, runsFilter, RUNSFIELDS); trace.event(`playbook-dispatcher returned: ${JSON.stringify(rhcRuns)}`); if (!rhcRuns || !rhcRuns.data) { @@ -305,7 +306,7 @@ exports.getRunHostDetails = async function (playbook_run_id, system_id) { for (const run of rhcRuns.data) { const runHostsFilter = createDispatcherRunHostsFilter(playbook_run_id, run.id, system_id); trace.event(`fetch playbook-dispatcher/v1/run_hosts with filter: ${JSON.stringify(runHostsFilter)}`); - const rhcRunHosts = await dispatcher.fetchPlaybookRunHosts(runHostsFilter, RUNHOSTFIELDS) + const rhcRunHosts = await dispatcher.fetchPlaybookRunHosts(req, runHostsFilter, RUNHOSTFIELDS) trace.event(`playbook-dispatcher/v1/run_hosts returned: ${JSON.stringify(rhcRunHosts)}`); if (!rhcRunHosts || !rhcRunHosts.data) { @@ -326,8 +327,8 @@ exports.getRunHostDetails = async function (playbook_run_id, system_id) { return null; // didn't find any systems... }; -exports.combineHosts = async function (rhcRunHosts, systems, playbook_run_id, filter_hostname = null) { - rhcRunHosts = await exports.formatRunHosts(rhcRunHosts, playbook_run_id); +exports.combineHosts = async function (req, rhcRunHosts, systems, playbook_run_id, filter_hostname = null) { + rhcRunHosts = await exports.formatRunHosts(rhcRunHosts, playbook_run_id, req); _.forEach(rhcRunHosts, host => { if (!filter_hostname || host.system_name.indexOf(filter_hostname) >= 0) { @@ -337,7 +338,7 @@ exports.combineHosts = async function (rhcRunHosts, systems, playbook_run_id, fi }; // add rhc playbook run data to remediation -exports.combineRuns = async function (remediation) { +exports.combineRuns = async function (req, remediation) { const iteration = remediation.iteration; // this was added to make the logging prettier trace.enter(`[${iteration}] fifi.combineRuns`); @@ -347,11 +348,11 @@ exports.combineRuns = async function (remediation) { // query playbook-dispatcher to see if there are any RHC direct or // RHC satellite hosts for this playbook run... trace.event(`[${iteration}] Fetch run details for run: ${run.id}`); - const rhcRuns = await exports.getRHCRuns(run.id); // run.id is playbook_run_id + const rhcRuns = await exports.getRHCRuns(req, run.id); // run.id is playbook_run_id if (rhcRuns) { trace.event(`[${iteration}] Format run details and add it to the remediation`) - const executors = await formatRHCRuns(rhcRuns, run.id); + const executors = await formatRHCRuns(req, rhcRuns, run.id); pushRHCExecutor(executors, run); } } @@ -411,10 +412,10 @@ function prepareRHCCancelRequest (org_id, playbook_run_id, username) { return { run_id: playbook_run_id, org_id, principal: username}; } -function dispatchReceptorCancelRequests (requests, playbook_run_id) { +function dispatchReceptorCancelRequests (req, requests, playbook_run_id) { return P.mapSeries(requests, async ({ executor, receptorCancelRequest }) => { try { - const response = await receptorConnector.postInitialRequest(receptorCancelRequest); + const response = await receptorConnector.postInitialRequest(req, receptorCancelRequest); probes.receptorCancelDispatched(receptorCancelRequest, executor, response, playbook_run_id); return response; } catch (e) { @@ -423,9 +424,9 @@ function dispatchReceptorCancelRequests (requests, playbook_run_id) { }); } -async function dispatchRHCCancelRequests (dispatcherCancelRequest, playbook_run_id) { +async function dispatchRHCCancelRequests (req, dispatcherCancelRequest, playbook_run_id) { try { - const response = await dispatcher.postPlaybookCancelRequest(dispatcherCancelRequest); + const response = await dispatcher.postPlaybookCancelRequest(req, dispatcherCancelRequest); probes.dispatcherCancelDispatched(dispatcherCancelRequest); return response; } catch (e) { @@ -433,12 +434,12 @@ async function dispatchRHCCancelRequests (dispatcherCancelRequest, playbook_run_ } } -exports.cancelPlaybookRun = async function (account_number, org_id, playbook_run_id, username, executors) { +exports.cancelPlaybookRun = async function (req, account_number, org_id, playbook_run_id, username, executors) { if (_.isEmpty(executors)) { const request = [prepareRHCCancelRequest(org_id, playbook_run_id, username)]; - await dispatchRHCCancelRequests(request); + await dispatchRHCCancelRequests(req, request); } else { const requests = executors.map(executor => prepareReceptorCancelRequest(account_number, executor, playbook_run_id)); - await dispatchReceptorCancelRequests(requests, playbook_run_id); + await dispatchReceptorCancelRequests(req, requests, playbook_run_id); } }; diff --git a/src/remediations/fifi_2.js b/src/remediations/fifi_2.js index 25374c97..feb408a0 100644 --- a/src/remediations/fifi_2.js +++ b/src/remediations/fifi_2.js @@ -74,23 +74,23 @@ exports.uuidv4 = function () { // remediation - the id of the associated remediation // username - the username of the entity initiating the playbook run //-------------------------------------------- -exports.createPlaybookRun = async function (recipients, exclude, remediation, username) { +exports.createPlaybookRun = async function (req, recipients, exclude, remediation, username) { // create UUID for this run const playbook_run_id = exports.uuidv4(); // check if excludes contains anything NOT in targets - validateExcludes(exclude, recipients); + validateExcludes(req, exclude, recipients); // create work requests const workRequests = createWorkRequests(playbook_run_id, recipients, exclude, remediation, username); // return 422 if no work remains if (_.isEmpty(workRequests)) { - throw errors.noExecutors(remediation); + throw errors.noExecutors(req, remediation); } // dispatch requests - const response = await dispatchWorkRequests(workRequests, playbook_run_id); + const response = await dispatchWorkRequests(req, workRequests, playbook_run_id); if (response === null) { return null; @@ -108,7 +108,7 @@ exports.createPlaybookRun = async function (recipients, exclude, remediation, us //---------------------------------------------------------------------------------- // Verify that the exclude list does not contain sat_ids not in list of recipients //---------------------------------------------------------------------------------- -function validateExcludes (excludes, recipients) { +function validateExcludes (req, excludes, recipients) { // throw error if any exclude not in recipients const unknownExcludes = _.difference(excludes, _.filter(excludes, exclude_id => { if (exclude_id === 'RHC') { @@ -119,7 +119,7 @@ function validateExcludes (excludes, recipients) { })); if (!_.isEmpty(unknownExcludes)) { - throw errors.unknownExclude(unknownExcludes); + throw errors.unknownExclude(req, unknownExcludes); } return true; @@ -170,10 +170,10 @@ function createWorkRequests (playbook_run_id, recipients, exclude, remediation, //---------------------------------------------- // Submit work requests to playbook-dispatcher //---------------------------------------------- -async function dispatchWorkRequests (workRequests, playbook_run_id) { +async function dispatchWorkRequests (req, workRequests, playbook_run_id) { try { probes.workRequest(workRequests, playbook_run_id); - const response = await dispatcher.postV2PlaybookRunRequests(workRequests); + const response = await dispatcher.postV2PlaybookRunRequests(req, workRequests); probes.JobDispatched(response, playbook_run_id); // handle aggregate responses diff --git a/src/remediations/write.integration.js b/src/remediations/write.integration.js index c4c5df05..03e456b4 100644 --- a/src/remediations/write.integration.js +++ b/src/remediations/write.integration.js @@ -198,7 +198,7 @@ describe('remediations', function () { }); test('400s on post with invalid json body format', async () => { - const {header} = reqId(); + const {id, header} = reqId(); const {body} = await request .post('/v1/remediations') @@ -209,7 +209,7 @@ describe('remediations', function () { .expect(400); body.errors.should.eql([{ - id: 'unknown', + id, status: 400, code: 'INVALID_CONTENT_TYPE', title: 'The request body must be in JSON format.' diff --git a/src/resolutions/disambiguator.js b/src/resolutions/disambiguator.js index efbc6c6a..87eb93ef 100644 --- a/src/resolutions/disambiguator.js +++ b/src/resolutions/disambiguator.js @@ -3,10 +3,10 @@ const _ = require('lodash'); const errors = require('../errors'); -exports.disambiguate = function (templates, resolution, id, strict = true, strictOnEmpty = true) { +exports.disambiguate = function (req, templates, resolution, id, strict = true, strictOnEmpty = true) { if (!templates.length) { if (strictOnEmpty) { - throw errors.unsupportedIssue(id); + throw errors.unsupportedIssue(req, id); } return; @@ -24,7 +24,7 @@ exports.disambiguate = function (templates, resolution, id, strict = true, stric } if (strict) { - throw errors.unknownResolution(id, resolution); + throw errors.unknownResolution(req, id, resolution); } } diff --git a/src/resolutions/resolutions.controller.js b/src/resolutions/resolutions.controller.js index e98690aa..9a751d83 100644 --- a/src/resolutions/resolutions.controller.js +++ b/src/resolutions/resolutions.controller.js @@ -8,7 +8,7 @@ const identifiers = require('../util/identifiers'); const disambiguator = require('./disambiguator'); exports.getResolutions = errors.async(async function (req, res) { - const result = await getResolutions(req.params.issue); + const result = await getResolutions(req, req.params.issue); if (!result) { return res.status(404).end(); @@ -20,17 +20,17 @@ exports.getResolutions = errors.async(async function (req, res) { exports.resolutionsBatch = errors.async(async function (req, res) { const { issues } = req.body; - let result = _(issues).keyBy().mapValues(getResolutions).value(); + let result = _(issues).keyBy().mapValues(issue => getResolutions(req, issue)).value(); result = await P.props(result); result = _.mapValues(result, value => value || false); res.json(result); }); -async function getResolutions (identifier) { - const id = identifiers.parse(identifier); - const resolver = issues.getHandler(id).getResolutionResolver(); - const resolutions = await resolver.resolveResolutions(id); +async function getResolutions (req, identifier) { + const id = identifiers.parse(req, identifier); + const resolver = issues.getHandler(id, req).getResolutionResolver(); + const resolutions = await resolver.resolveResolutions(req, id); if (!resolutions.length) { return null; diff --git a/src/resolutions/resolvers/CSAWResolver.js b/src/resolutions/resolvers/CSAWResolver.js index 076303fa..1305ed16 100644 --- a/src/resolutions/resolvers/CSAWResolver.js +++ b/src/resolutions/resolvers/CSAWResolver.js @@ -10,20 +10,20 @@ const trace = require('../../util/trace'); module.exports = class CVEResolver extends Resolver { - async resolveResolutions (id) { + async resolveResolutions (req, id) { trace.enter('CSAWResolver.resolveResolutions'); - const parsed = identifier.parseCSAW(id); + const parsed = identifier.parseCSAW(req, id); trace.event(`Fetch vulnerabilities resolutions for id: ${parsed.csaw}`); id.issue = parsed.csaw; - const resolutions = await vulnerabilities.getResolutions(id.issue); + const resolutions = await vulnerabilities.getResolutions(req, id.issue); trace.event(`Resolutions: ${JSON.stringify(resolutions)}`); if (_.isEmpty(resolutions)) { if (!_.isUndefined(parsed.cve)) { id.issue = parsed.cve; trace.event(`Fetch CVE resolution for id: ${parsed.cve}`); - const result = await cveResolver.resolveResolutions(id); + const result = await cveResolver.resolveResolutions(req, id); trace.leave(`Returning CVE resolution: ${JSON.stringify(result)}`); return result; } diff --git a/src/resolutions/resolvers/CVEResolver.js b/src/resolutions/resolvers/CVEResolver.js index 6f895c39..d432be95 100644 --- a/src/resolutions/resolvers/CVEResolver.js +++ b/src/resolutions/resolvers/CVEResolver.js @@ -7,19 +7,19 @@ const Resolver = require('./Resolver'); module.exports = class CVEResolver extends Resolver { - fetch (id) { - return vmaas.getCve(id.issue); + fetch (req, id) { + return vmaas.getCve(req, id.issue); } build(id, entity) { return ErratumResolution.forCve(id, entity); } - async resolveResolutions (id) { + async resolveResolutions (req, id) { trace.enter('CVEResolver.resolveResolutions'); trace.event(`Fetch resolutions for: ${id}`); - const entity = await this.fetch(id); + const entity = await this.fetch(req, id); trace.event(`Resolutions: ${JSON.stringify(entity)}`); if (!entity) { diff --git a/src/resolutions/resolvers/ContentServerResolver.js b/src/resolutions/resolvers/ContentServerResolver.js index 4ff7c38e..110cc946 100644 --- a/src/resolutions/resolvers/ContentServerResolver.js +++ b/src/resolutions/resolvers/ContentServerResolver.js @@ -6,8 +6,9 @@ const shared = require('./SharedFunctions'); module.exports = class ContentServerResolver extends Resolver { - async resolveResolutions (id) { - const templates = await contentServer.getResolutions(id.issue); + async resolveResolutions (req, id) { + const templates = await contentServer.getResolutions(req, id.issue); + return templates.map(template => shared.parseResolution(template, id)); } }; diff --git a/src/resolutions/resolvers/ErratumResolver.js b/src/resolutions/resolvers/ErratumResolver.js index 5b8020cf..9b9a6a26 100644 --- a/src/resolutions/resolvers/ErratumResolver.js +++ b/src/resolutions/resolvers/ErratumResolver.js @@ -6,8 +6,8 @@ const CVEResolver = require('./CVEResolver'); module.exports = class ErratumResolver extends CVEResolver { - fetch (id) { - return vmaas.getErratum(id.issue); + fetch (req, id) { + return vmaas.getErratum(req, id.issue); } build(id, entity) { diff --git a/src/resolutions/resolvers/PackageResolver.js b/src/resolutions/resolvers/PackageResolver.js index 69f9641d..3201c681 100644 --- a/src/resolutions/resolvers/PackageResolver.js +++ b/src/resolutions/resolvers/PackageResolver.js @@ -9,7 +9,8 @@ module.exports = class PackageResolver extends CVEResolver { return ErratumResolution.forPackage(id, ''); } - async resolveResolutions (id) { + // probably dont need to pass req here + async resolveResolutions (req, id) { return [this.build(id)]; } }; diff --git a/src/resolutions/resolvers/PatchmanResolver.js b/src/resolutions/resolvers/PatchmanResolver.js index b93b2cbf..f729b3ad 100644 --- a/src/resolutions/resolvers/PatchmanResolver.js +++ b/src/resolutions/resolvers/PatchmanResolver.js @@ -5,7 +5,7 @@ const ErratumResolver = require('./ErratumResolver'); module.exports = class PatchmanResolver extends ErratumResolver { - fetch (id) { - return patchman.getErratum(id.issue); + fetch (req, id) { + return patchman.getErratum(req, id.issue); } }; diff --git a/src/resolutions/resolvers/Resolver.js b/src/resolutions/resolvers/Resolver.js index c17b40f4..d0b0c0ef 100644 --- a/src/resolutions/resolvers/Resolver.js +++ b/src/resolutions/resolvers/Resolver.js @@ -11,9 +11,9 @@ module.exports = class Resolver { throw new Error('not implemented'); } - async isRebootNeeded (id, resolutionId) { - const resolutions = await this.resolveResolutions(id); - const resolution = disambiguator.disambiguate(resolutions, resolutionId, id, false, false); + async isRebootNeeded (req, id, resolutionId) { + const resolutions = await this.resolveResolutions(req, id); + const resolution = disambiguator.disambiguate(req, resolutions, resolutionId, id, false, false); if (resolution) { return resolution.needsReboot; diff --git a/src/resolutions/resolvers/SSGResolver.js b/src/resolutions/resolvers/SSGResolver.js index c741ead0..3abe430c 100644 --- a/src/resolutions/resolvers/SSGResolver.js +++ b/src/resolutions/resolvers/SSGResolver.js @@ -23,19 +23,19 @@ function testPlaceholders (raw) { } module.exports = class SSGResolver extends Resolver { - async resolveResolutions (id) { - const {platform, profile, rule} = identifiers.parseSSG(id); + async resolveResolutions (req, id) { + const {platform, profile, rule} = identifiers.parseSSG(req, id); let raw = {}; // RHCLOUD-4280: disable rule "rsyslog_remote_loghost" if (id.issue.includes('rsyslog_remote_loghost')) {return [];} if (config.ssg.impl === 'compliance') { - raw = await ssg.getTemplate(id.issue); + raw = await ssg.getTemplate(req, id.issue); } else { const [primary, fallback] = await P.all([ - ssg.getTemplate(platform, profile, rule), - ssg.getTemplate(platform, FALLBACK_PROFILE, rule) + ssg.getTemplate(req, platform, profile, rule), + ssg.getTemplate(req, platform, FALLBACK_PROFILE, rule) ]); raw = primary || fallback; diff --git a/src/resolutions/resolvers/SSGResolver.unit.js b/src/resolutions/resolvers/SSGResolver.unit.js index a58587c2..275c257e 100644 --- a/src/resolutions/resolvers/SSGResolver.unit.js +++ b/src/resolutions/resolvers/SSGResolver.unit.js @@ -5,47 +5,56 @@ const resolver = new(require('./SSGResolver'))(); const identifiers = require('../../util/identifiers'); const ssg = require('../../connectors/ssg/mock'); +const REQ = { + headers: { + 'x-rh-identity': 'identity', + 'x-rh-insights-request-id': 'request-id' + }, + identity: { type: 'test' }, + user: { username: 'test', account_number: 'test' } +}; + describe('SSGResolved', function () { describe('impl', function () { test('detects unresolved interpolation placeholder', async () => { - const id = identifiers.parse('ssg:rhel7|pci-dss|xccdf_org.ssgproject.content_rule_disable_prelink-unresolved'); - const resolutions = (await resolver.resolveResolutions(id)); + const id = identifiers.parse(REQ, 'ssg:rhel7|pci-dss|xccdf_org.ssgproject.content_rule_disable_prelink-unresolved'); + const resolutions = (await resolver.resolveResolutions(REQ, id)); resolutions.should.be.empty(); - const template = await ssg.getTemplate('rhel7', 'pci-dss', 'disable_prelink-unresolved'); + const template = await ssg.getTemplate(REQ, 'rhel7', 'pci-dss', 'disable_prelink-unresolved'); expect(() => resolver.parseResolution(template)).toThrow('Unresolved interpolation placeholder @RULE_TITLE@'); }); test('resolves the name for simple plays', async () => { - const id = identifiers.parse('ssg:rhel7|standard|xccdf_org.ssgproject.content_rule_service_rsyslog_enabled'); - const resolutions = (await resolver.resolveResolutions(id)); + const id = identifiers.parse(REQ, 'ssg:rhel7|standard|xccdf_org.ssgproject.content_rule_service_rsyslog_enabled'); + const resolutions = (await resolver.resolveResolutions(REQ, id)); resolutions.should.have.size(1); resolutions[0].description.should.equal('Enable rsyslog Service'); }); test('falls back to default name for more complex plays', async () => { - const id = identifiers.parse('ssg:rhel7|standard|xccdf_org.ssgproject.content_rule_service_autofs_disabled'); - const resolutions = (await resolver.resolveResolutions(id)); + const id = identifiers.parse(REQ, 'ssg:rhel7|standard|xccdf_org.ssgproject.content_rule_service_autofs_disabled'); + const resolutions = (await resolver.resolveResolutions(REQ, id)); resolutions.should.have.size(1); resolutions[0].description.should.equal('Disable the Automounter'); }); test('falls back to all profile if the rule does not belong to the spefified profile', async () => { - const id = identifiers.parse('ssg:rhel7|standard|xccdf_org.ssgproject.content_rule_disable_prelink'); - const resolutions = (await resolver.resolveResolutions(id)); + const id = identifiers.parse(REQ, 'ssg:rhel7|standard|xccdf_org.ssgproject.content_rule_disable_prelink'); + const resolutions = (await resolver.resolveResolutions(REQ, id)); resolutions.should.have.size(1); resolutions[0].description.should.equal('Disable Prelinking'); }); test('returns 0 if the rule does not exist at all', async () => { - const id = identifiers.parse('ssg:rhel7|standard|xccdf_org.ssgproject.content_rule_this_is_nonsense'); - const resolutions = (await resolver.resolveResolutions(id)); + const id = identifiers.parse(REQ, 'ssg:rhel7|standard|xccdf_org.ssgproject.content_rule_this_is_nonsense'); + const resolutions = (await resolver.resolveResolutions(REQ, id)); resolutions.should.have.size(0); }); test('returns 0 if the rule id is rsyslog_remote_loghost', async () => { - const id = identifiers.parse('ssg:rhel7|standard|xccdf_org.ssgproject.content_rule_rsyslog_remote_loghost'); - const resolutions = (await resolver.resolveResolutions(id)); + const id = identifiers.parse(REQ, 'ssg:rhel7|standard|xccdf_org.ssgproject.content_rule_rsyslog_remote_loghost'); + const resolutions = (await resolver.resolveResolutions(REQ, id)); resolutions.should.have.size(0); }); }); diff --git a/src/resolutions/resolvers/TestResolver.js b/src/resolutions/resolvers/TestResolver.js index 80a6ddd7..943a94ce 100644 --- a/src/resolutions/resolvers/TestResolver.js +++ b/src/resolutions/resolvers/TestResolver.js @@ -53,7 +53,7 @@ const RESOLUTIONS = Object.freeze({ }); module.exports = class TestResolver extends Resolver { - async resolveResolutions (id) { + async resolveResolutions (req, id) { if (RESOLUTIONS[id.issue]) { return RESOLUTIONS[id.issue]; } diff --git a/src/routes.js b/src/routes.js index 51875a1b..8e5c17f2 100644 --- a/src/routes.js +++ b/src/routes.js @@ -56,7 +56,7 @@ module.exports = async function (app) { /*eslint-disable no-unused-vars*/ app.use((err, req, res, next) => { if (err.type === 'entity.parse.failed') { - throw new errors.BadRequest('INVALID_CONTENT_TYPE', 'The request body must be in JSON format.'); + throw new errors.BadRequest(req, 'INVALID_CONTENT_TYPE', 'The request body must be in JSON format.'); } else { throw err; } diff --git a/src/status/status.controller.js b/src/status/status.controller.js index 9a71f39d..a87a99c0 100644 --- a/src/status/status.controller.js +++ b/src/status/status.controller.js @@ -27,9 +27,9 @@ const CONNECTORS = _([ 'bop' ]).keyBy().mapValues(id => require(`../connectors/${id}`)).value(); // eslint-disable-line security/detect-non-literal-require -async function getConnectorStatus (connector) { +async function getConnectorStatus (connector, req) { try { - await connector.ping(); + await connector.ping(req); return OK; } catch (e) { log.warn(e, 'ping failed'); @@ -65,7 +65,7 @@ async function getDb () { exports.status = errors.async(async function (req, res) { const [connectors, db] = await P.all([ P.props(_.mapValues(CONNECTORS, async connector => { - const status = await getConnectorStatus(connector); + const status = await getConnectorStatus(connector, req); return { status, diff --git a/src/util/cls.js b/src/util/cls.js index 9a362e07..3d7ff2ef 100644 --- a/src/util/cls.js +++ b/src/util/cls.js @@ -13,9 +13,9 @@ exports.middleware = function (req, res, next) { next(); }; -exports.getReq = function () { - return httpContext.get('req'); -}; +// exports.getReq = function () { +// return httpContext.get('req'); +// }; exports.patchMiddleware = function (fn) { return function (req, res, next) { diff --git a/src/util/identifiers.js b/src/util/identifiers.js index bf69952a..3b1119d2 100644 --- a/src/util/identifiers.js +++ b/src/util/identifiers.js @@ -6,10 +6,10 @@ const SSG_PATTERN = /^([\w-]+)\|([\w-]+)\|xccdf_org\.ssgproject\.content_rule_([ const CSAW_PATTERN = /^(CVE-20[\d]{2}-[\d]{4,}):(\w+\|[A-Z\d_]+)$/; const CSAW_RULE_PATTERN = /^(\w+\|[A-Z\d_]+)$/; -function match (id) { +function match (req, id) { const match = PATTERN.exec(id); if (!match) { - throw errors.invalidIssueId(id); + throw errors.invalidIssueId(req, id); } return match; @@ -29,15 +29,15 @@ exports.Identifier = class Identifier { } }; -exports.parse = function (id) { - const result = match(id); +exports.parse = function (req, id) { + const result = match(req, id); return new exports.Identifier(result[1], result[2], id); }; -exports.parseCSAW = function (id) { +exports.parseCSAW = function (req, id) { if (!(id instanceof exports.Identifier)) { - id = exports.parse(id); + id = exports.parse(req, id); } const csawResult = CSAW_PATTERN.exec(id.issue); @@ -54,18 +54,18 @@ exports.parseCSAW = function (id) { }; } - throw errors.invalidIssueId(id); + throw errors.invalidIssueId(req, id); }; -exports.parseSSG = function (id) { +exports.parseSSG = function (req, id) { if (!(id instanceof exports.Identifier)) { - id = exports.parse(id); + id = exports.parse(req, id); } const result = SSG_PATTERN.exec(id.issue); if (!result || result.length !== 4) { - throw errors.invalidIssueId(id); + throw errors.invalidIssueId(req, id); } return { @@ -76,4 +76,4 @@ exports.parseSSG = function (id) { }; }; -exports.toExternal = id => match(id)[2]; +exports.toExternal = (req, id) => match(req, id)[2]; diff --git a/src/util/identifiers.unit.js b/src/util/identifiers.unit.js index 031ae70f..1f6025cd 100644 --- a/src/util/identifiers.unit.js +++ b/src/util/identifiers.unit.js @@ -4,57 +4,66 @@ require('../test'); const identifiers = require('./identifiers'); +const REQ = { + headers: { + 'x-rh-identity': 'identity', + 'x-rh-insights-request-id': 'request-id' + }, + identity: { type: 'test' }, + user: { username: 'test', account_number: 'test' } +}; + test('parses a test id', () => { - const parsed = identifiers.parse('test:reboot'); + const parsed = identifiers.parse(REQ, 'test:reboot'); parsed.should.have.property('app', 'test'); parsed.should.have.property('issue', 'reboot'); parsed.should.have.property('full', 'test:reboot'); }); test('parses an advisor id', () => { - const parsed = identifiers.parse('advisor:network_bond_opts_config_issue|NETWORK_BONDING_OPTS_DOUBLE_QUOTES_ISSUE'); + const parsed = identifiers.parse(REQ, 'advisor:network_bond_opts_config_issue|NETWORK_BONDING_OPTS_DOUBLE_QUOTES_ISSUE'); parsed.should.have.property('app', 'advisor'); parsed.should.have.property('issue', 'network_bond_opts_config_issue|NETWORK_BONDING_OPTS_DOUBLE_QUOTES_ISSUE'); parsed.should.have.property('full', 'advisor:network_bond_opts_config_issue|NETWORK_BONDING_OPTS_DOUBLE_QUOTES_ISSUE'); }); test('parses a vulnerabilities id', () => { - const parsed = identifiers.parse('vulnerabilities:CVE-2017-5715'); + const parsed = identifiers.parse(REQ, 'vulnerabilities:CVE-2017-5715'); parsed.should.have.property('app', 'vulnerabilities'); parsed.should.have.property('issue', 'CVE-2017-5715'); parsed.should.have.property('full', 'vulnerabilities:CVE-2017-5715'); }); test('parses a vulnerabilities (erratum) id', () => { - const parsed = identifiers.parse('vulnerabilities:RHBA-2007:0331'); + const parsed = identifiers.parse(REQ, 'vulnerabilities:RHBA-2007:0331'); parsed.should.have.property('app', 'vulnerabilities'); parsed.should.have.property('issue', 'RHBA-2007:0331'); parsed.should.have.property('full', 'vulnerabilities:RHBA-2007:0331'); }); test('parses patch (erratum) id', () => { - const parsed = identifiers.parse('patch-advisory:RHBA-2021:0439'); + const parsed = identifiers.parse(REQ, 'patch-advisory:RHBA-2021:0439'); parsed.should.have.property('app', 'patch-advisory'); parsed.should.have.property('issue', 'RHBA-2021:0439'); parsed.should.have.property('full', 'patch-advisory:RHBA-2021:0439'); }); test('parses patch (package) id', () => { - const parsed = identifiers.parse('patch-package:libstdc++-8.3.1-5.1.el8.x86_64'); + const parsed = identifiers.parse(REQ, 'patch-package:libstdc++-8.3.1-5.1.el8.x86_64'); parsed.should.have.property('app', 'patch-package'); parsed.should.have.property('issue', 'libstdc++-8.3.1-5.1.el8.x86_64'); parsed.should.have.property('full', 'patch-package:libstdc++-8.3.1-5.1.el8.x86_64'); }); test('parses a vulnerabilities (csaw) id', () => { - const parsed = identifiers.parse('vulnerabilities:CVE-2017-5715:network_bond_opts_config_issue|NETWORK_BONDING_OPTS_DOUBLE_QUOTES_ISSUE'); + const parsed = identifiers.parse(REQ, 'vulnerabilities:CVE-2017-5715:network_bond_opts_config_issue|NETWORK_BONDING_OPTS_DOUBLE_QUOTES_ISSUE'); parsed.should.have.property('app', 'vulnerabilities'); parsed.should.have.property('issue', 'CVE-2017-5715:network_bond_opts_config_issue|NETWORK_BONDING_OPTS_DOUBLE_QUOTES_ISSUE'); parsed.should.have.property('full', 'vulnerabilities:CVE-2017-5715:network_bond_opts_config_issue|NETWORK_BONDING_OPTS_DOUBLE_QUOTES_ISSUE'); }); test('parses a ssg id', () => { - const parsed = identifiers.parse('ssg:rhel7|pci-dss|xccdf_org.ssgproject.content_rule_sshd_disable_root_login'); + const parsed = identifiers.parse(REQ, 'ssg:rhel7|pci-dss|xccdf_org.ssgproject.content_rule_sshd_disable_root_login'); parsed.should.have.property('app', 'ssg'); parsed.should.have.property('issue', 'rhel7|pci-dss|xccdf_org.ssgproject.content_rule_sshd_disable_root_login'); parsed.should.have.property('full', 'ssg:rhel7|pci-dss|xccdf_org.ssgproject.content_rule_sshd_disable_root_login'); diff --git a/src/util/log.js b/src/util/log.js index 9c28ef86..15982b34 100644 --- a/src/util/log.js +++ b/src/util/log.js @@ -122,8 +122,8 @@ if (config.logging.cloudwatch.enabled) { logger.info({group: config.logging.cloudwatch.options.group}, 'CloudWatch enabled'); } -function getLogger () { - const req = cls.getReq(); +function getLogger (req) { + // const req = cls.getReq(); if (!req) { return logger; // outside of request, fallback to default logger @@ -140,9 +140,11 @@ function getLogger () { // child logger that has an additional reqID correlation parameter) if we're // called in the context of a request. Otherwise, pass the call onto the default // logger. + +// How do we get the reqest here module.exports = new Proxy (logger, { - get (target, key, receiver) { - const logger = getLogger(); + get (target, key, receiver, req) { + const logger = getLogger(req); const result = Reflect.get(logger, key, receiver); if (typeof result === 'function') { diff --git a/src/util/request.unit.js b/src/util/request.unit.js index c6307aef..0087e399 100644 --- a/src/util/request.unit.js +++ b/src/util/request.unit.js @@ -6,6 +6,15 @@ const request = require('./request'); const version = require('../version/version.controller'); const config = require('../config'); +const REQ = { + headers: { + 'x-rh-identity': 'identity', + 'x-rh-insights-request-id': 'request-id' + }, + identity: { type: 'test' }, + user: { username: 'test', account_number: 'test' } +}; + // stub getVersions for the request to take at least 50ms beforeEach(() => base.sandbox.stub(version, 'get').callsFake((req, res) => P.delay(50).then(() => res.end()))); diff --git a/src/util/trace.js b/src/util/trace.js index 65173eac..0b8ef9b9 100644 --- a/src/util/trace.js +++ b/src/util/trace.js @@ -125,9 +125,11 @@ const dummy = new Trace(); // Returns a Proxy object that directs calls to either the trace object attached // to the current request or a dummy trace object that does nothing. This is // useful for functions that might be called outside the context of a request. + +// How do we get the request here module.exports = new Proxy(dummy, { - apply (target, thisArg, args) { - const trace = cls.getReq()?.trace; + apply (target, thisArg, args, req) { + const trace = req?.trace; if (trace) { return Reflect.apply(trace, thisArg, args); @@ -135,8 +137,8 @@ module.exports = new Proxy(dummy, { // do nothing if there was no req.trace }, - get (target, key, receiver) { - const trace = cls.getReq()?.trace; + get (target, key, receiver, req) { + const trace = req?.trace; if (trace) { return Reflect.get(trace, key, receiver); @@ -146,15 +148,15 @@ module.exports = new Proxy(dummy, { return Reflect.get(target, key, receiver); }, - set (obj, prop, value) { - const trace = cls.getReq()?.trace; + set (obj, prop, value, req) { + const trace = req?.trace; if (trace) { return Reflect.set(trace, prop, value); } // return dummy object attr if no req.trace - this[prop] = Object.assign({}, ); + this[prop] = Object.assign({}); return Reflect.set(obj, prop, value); } });