diff --git a/x-pack/plugins/security/server/lib/authorization/check_privileges.js b/x-pack/plugins/security/server/lib/authorization/check_privileges.js index b3d1a02c6e6f7f..1f3179aba49928 100644 --- a/x-pack/plugins/security/server/lib/authorization/check_privileges.js +++ b/x-pack/plugins/security/server/lib/authorization/check_privileges.js @@ -21,6 +21,7 @@ export function checkPrivilegesWithRequestFactory(actions, application, shieldCl const checkPrivilegesAtResources = async (resources, privilegeOrPrivileges) => { const privileges = Array.isArray(privilegeOrPrivileges) ? privilegeOrPrivileges : [privilegeOrPrivileges]; const allApplicationPrivileges = uniq([actions.version, actions.login, ...privileges]); + const hasPrivilegesResponse = await callWithRequest(request, 'shield.hasPrivileges', { body: { applications: [{ diff --git a/x-pack/test/saved_object_api_integration/common/suites/saved_objects/create.js b/x-pack/test/saved_object_api_integration/common/suites/saved_objects/create.js index 4df092e523382f..0f9f02d30db9a3 100644 --- a/x-pack/test/saved_object_api_integration/common/suites/saved_objects/create.js +++ b/x-pack/test/saved_object_api_integration/common/suites/saved_objects/create.js @@ -11,7 +11,7 @@ export function createTestSuiteFactory(es, esArchiver, supertest) { const spaceAwareType = 'visualization'; const notSpaceAwareType = 'chapo'; - const makeCreateTest = describeFn => (description, { + const makeCreateTest = (describeFn) => (description, { auth = { username: undefined, password: undefined diff --git a/x-pack/test/saved_object_api_integration/common/suites/saved_objects/find.js b/x-pack/test/saved_object_api_integration/common/suites/saved_objects/find.js new file mode 100644 index 00000000000000..989b7666fabc1f --- /dev/null +++ b/x-pack/test/saved_object_api_integration/common/suites/saved_objects/find.js @@ -0,0 +1,179 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ +import expect from 'expect.js'; +import { getIdPrefix, getUrlPrefix } from '../../../common/lib/space_test_utils'; +import { DEFAULT_SPACE_ID } from '../../../../../plugins/spaces/common/constants'; + +export function findTestSuiteFactory(esArchiver, supertest) { + const makeFindTest = (describeFn) => (description, { + auth = { + username: undefined, + password: undefined, + }, + spaceId, + tests + }) => { + describeFn(description, () => { + before(() => esArchiver.load('saved_objects/spaces')); + after(() => esArchiver.unload('saved_objects/spaces')); + + it(`should return ${tests.normal.statusCode} with ${tests.normal.description}`, async () => ( + await supertest + .get(`${getUrlPrefix(spaceId)}/api/saved_objects/_find?type=visualization&fields=title`) + .auth(auth.username, auth.password) + .expect(tests.normal.statusCode) + .then(tests.normal.response) + )); + + describe('unknown type', () => { + it(`should return ${tests.unknownType.statusCode} with ${tests.unknownType.description}`, async () => ( + await supertest + .get(`${getUrlPrefix(spaceId)}/api/saved_objects/_find?type=wigwags`) + .auth(auth.username, auth.password) + .expect(tests.unknownType.statusCode) + .then(tests.unknownType.response) + )); + }); + + describe('page beyond total', () => { + it(`should return ${tests.pageBeyondTotal.statusCode} with ${tests.pageBeyondTotal.description}`, async () => ( + await supertest + .get(`${getUrlPrefix(spaceId)}/api/saved_objects/_find?type=visualization&page=100&per_page=100`) + .auth(auth.username, auth.password) + .expect(tests.pageBeyondTotal.statusCode) + .then(tests.pageBeyondTotal.response) + )); + }); + + describe('unknown search field', () => { + it(`should return ${tests.unknownSearchField.statusCode} with ${tests.unknownSearchField.description}`, async () => ( + await supertest + .get(`${getUrlPrefix(spaceId)}/api/saved_objects/_find?type=wigwags&search_fields=a`) + .auth(auth.username, auth.password) + .expect(tests.unknownSearchField.statusCode) + .then(tests.unknownSearchField.response) + )); + }); + + describe('no type', () => { + it(`should return ${tests.noType.statusCode} with ${tests.noType.description}`, async () => ( + await supertest + .get(`${getUrlPrefix(spaceId)}/api/saved_objects/_find`) + .auth(auth.username, auth.password) + .expect(tests.noType.statusCode) + .then(tests.noType.response) + )); + }); + }); + }; + + const findTest = makeFindTest(describe); + findTest.only = makeFindTest(describe.only); + + const createExpectEmpty = (page, perPage, total) => (resp) => { + expect(resp.body).to.eql({ + page: page, + per_page: perPage, + total: total, + saved_objects: [] + }); + }; + + const createExpectRbacForbidden = (type) => resp => { + const message = type ? + `Unable to find ${type}, missing action:saved_objects/${type}/find` : + `Not authorized to find saved_object`; + + expect(resp.body).to.eql({ + statusCode: 403, + error: 'Forbidden', + message + }); + }; + + const createExpectLegacyForbidden = (username) => resp => { + expect(resp.body).to.eql({ + statusCode: 403, + error: 'Forbidden', + // eslint-disable-next-line max-len + message: `action [indices:data/read/search] is unauthorized for user [${username}]: [security_exception] action [indices:data/read/search] is unauthorized for user [${username}]` + }); + }; + + const createExpectResults = (spaceId = DEFAULT_SPACE_ID) => (resp) => { + expect(resp.body).to.eql({ + page: 1, + per_page: 20, + total: 5, + saved_objects: [ + { + id: `${getIdPrefix(spaceId)}91200a00-9efd-11e7-acb3-3dab96693fab`, + type: 'index-pattern', + updated_at: '2017-09-21T18:49:16.270Z', + version: 1, + attributes: resp.body.saved_objects[0].attributes + }, + { + id: '7.0.0-alpha1', + type: 'config', + updated_at: '2017-09-21T18:49:16.302Z', + version: 1, + attributes: resp.body.saved_objects[1].attributes + }, + { + id: `${getIdPrefix(spaceId)}dd7caf20-9efd-11e7-acb3-3dab96693fab`, + type: 'visualization', + updated_at: '2017-09-21T18:51:23.794Z', + version: 1, + attributes: resp.body.saved_objects[2].attributes + }, + { + id: `${getIdPrefix(spaceId)}be3733a0-9efe-11e7-acb3-3dab96693fab`, + type: 'dashboard', + updated_at: '2017-09-21T18:57:40.826Z', + version: 1, + attributes: resp.body.saved_objects[3].attributes + }, + { + id: `8121a00-8efd-21e7-1cb3-34ab96643444`, + type: 'chapo', + updated_at: '2017-09-21T18:59:16.270Z', + version: 1, + attributes: { + 'name': 'El Chapo' + } + } + ] + }); + }; + + const createExpectVisualizationResults = (spaceId = DEFAULT_SPACE_ID) => (resp) => { + expect(resp.body).to.eql({ + page: 1, + per_page: 20, + total: 1, + saved_objects: [ + { + type: 'visualization', + id: `${getIdPrefix(spaceId)}dd7caf20-9efd-11e7-acb3-3dab96693fab`, + version: 1, + attributes: { + 'title': 'Count of requests' + } + }, + ] + }); + }; + + return { + createExpectEmpty, + createExpectRbacForbidden, + createExpectResults, + createExpectLegacyForbidden, + createExpectVisualizationResults, + findTest, + }; +} diff --git a/x-pack/test/saved_object_api_integration/security_and_spaces/apis/saved_objects/find.js b/x-pack/test/saved_object_api_integration/security_and_spaces/apis/saved_objects/find.js new file mode 100644 index 00000000000000..291d6fd8f0974f --- /dev/null +++ b/x-pack/test/saved_object_api_integration/security_and_spaces/apis/saved_objects/find.js @@ -0,0 +1,429 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { AUTHENTICATION } from '../../../common/lib/authentication'; +import { SPACES } from '../../../common/lib/spaces'; +import { findTestSuiteFactory } from '../../../common/suites/saved_objects/find'; + +export default function ({ getService }) { + const supertest = getService('supertestWithoutAuth'); + const esArchiver = getService('esArchiver'); + + describe('find', () => { + const { + createExpectEmpty, + createExpectRbacForbidden, + createExpectResults, + createExpectLegacyForbidden, + createExpectVisualizationResults, + findTest, + } = findTestSuiteFactory(esArchiver, supertest); + + [{ + spaceId: SPACES.DEFAULT.spaceId, + userWithAllAtSpace: AUTHENTICATION.KIBANA_RBAC_DEFAULT_SPACE_ALL_USER, + userWithReadAtSpace: AUTHENTICATION.KIBANA_RBAC_DEFAULT_SPACE_READ_USER, + userWithAllAtOtherSpace: AUTHENTICATION.KIBANA_RBAC_SPACE_1_ALL_USER, + }, { + spaceId: SPACES.SPACE_1.spaceId, + userWithAllAtSpace: AUTHENTICATION.KIBANA_RBAC_SPACE_1_ALL_USER, + userWithReadAtSpace: AUTHENTICATION.KIBANA_RBAC_SPACE_1_READ_USER, + userWithAllAtOtherSpace: AUTHENTICATION.KIBANA_RBAC_DEFAULT_SPACE_ALL_USER, + }].forEach(({ + spaceId, + userWithAllAtSpace, + userWithReadAtSpace, + userWithAllAtOtherSpace + }) => { + describe(`${spaceId} space`, () => { + findTest(AUTHENTICATION.NOT_A_KIBANA_USER.USERNAME, { + auth: { + username: AUTHENTICATION.NOT_A_KIBANA_USER.USERNAME, + password: AUTHENTICATION.NOT_A_KIBANA_USER.PASSWORD, + }, + spaceId, + tests: { + normal: { + description: 'forbidden login and find visualization message', + statusCode: 403, + response: createExpectLegacyForbidden(AUTHENTICATION.NOT_A_KIBANA_USER.USERNAME), + }, + unknownType: { + description: 'forbidden login and find wigwags message', + statusCode: 403, + response: createExpectLegacyForbidden(AUTHENTICATION.NOT_A_KIBANA_USER.USERNAME), + }, + pageBeyondTotal: { + description: 'forbidden login and find visualization message', + statusCode: 403, + response: createExpectLegacyForbidden(AUTHENTICATION.NOT_A_KIBANA_USER.USERNAME), + }, + unknownSearchField: { + description: 'forbidden login and find wigwags message', + statusCode: 403, + response: createExpectLegacyForbidden(AUTHENTICATION.NOT_A_KIBANA_USER.USERNAME), + }, + noType: { + description: `forbidded can't find any types`, + statusCode: 403, + response: createExpectLegacyForbidden(AUTHENTICATION.NOT_A_KIBANA_USER.USERNAME), + } + } + }); + + findTest(AUTHENTICATION.SUPERUSER.USERNAME, { + auth: { + username: AUTHENTICATION.SUPERUSER.USERNAME, + password: AUTHENTICATION.SUPERUSER.PASSWORD, + }, + spaceId, + tests: { + normal: { + description: 'only the visualization', + statusCode: 200, + response: createExpectVisualizationResults(spaceId), + }, + unknownType: { + description: 'empty result', + statusCode: 200, + response: createExpectEmpty(1, 20, 0), + }, + pageBeyondTotal: { + description: 'empty result', + statusCode: 200, + response: createExpectEmpty(100, 100, 1), + }, + unknownSearchField: { + description: 'empty result', + statusCode: 200, + response: createExpectEmpty(1, 20, 0), + }, + noType: { + description: 'all objects', + statusCode: 200, + response: createExpectResults(spaceId), + }, + }, + }); + + findTest(AUTHENTICATION.KIBANA_LEGACY_USER.USERNAME, { + auth: { + username: AUTHENTICATION.KIBANA_LEGACY_USER.USERNAME, + password: AUTHENTICATION.KIBANA_LEGACY_USER.PASSWORD, + }, + spaceId, + tests: { + normal: { + description: 'only the visualization', + statusCode: 200, + response: createExpectVisualizationResults(spaceId), + }, + unknownType: { + description: 'empty result', + statusCode: 200, + response: createExpectEmpty(1, 20, 0), + }, + pageBeyondTotal: { + description: 'empty result', + statusCode: 200, + response: createExpectEmpty(100, 100, 1), + }, + unknownSearchField: { + description: 'empty result', + statusCode: 200, + response: createExpectEmpty(1, 20, 0), + }, + noType: { + description: 'all objects', + statusCode: 200, + response: createExpectResults(spaceId), + }, + }, + }); + + findTest(AUTHENTICATION.KIBANA_LEGACY_DASHBOARD_ONLY_USER.USERNAME, { + auth: { + username: AUTHENTICATION.KIBANA_LEGACY_DASHBOARD_ONLY_USER.USERNAME, + password: AUTHENTICATION.KIBANA_LEGACY_DASHBOARD_ONLY_USER.PASSWORD, + }, + spaceId, + tests: { + normal: { + description: 'only the visualization', + statusCode: 200, + response: createExpectVisualizationResults(spaceId), + }, + unknownType: { + description: 'empty result', + statusCode: 200, + response: createExpectEmpty(1, 20, 0), + }, + pageBeyondTotal: { + description: 'empty result', + statusCode: 200, + response: createExpectEmpty(100, 100, 1), + }, + unknownSearchField: { + description: 'empty result', + statusCode: 200, + response: createExpectEmpty(1, 20, 0), + }, + noType: { + description: 'all objects', + statusCode: 200, + response: createExpectResults(spaceId), + }, + } + }); + + findTest(AUTHENTICATION.KIBANA_DUAL_PRIVILEGES_USER.USERNAME, { + auth: { + username: AUTHENTICATION.KIBANA_DUAL_PRIVILEGES_USER.USERNAME, + password: AUTHENTICATION.KIBANA_DUAL_PRIVILEGES_USER.PASSWORD, + }, + spaceId, + tests: { + normal: { + description: 'only the visualization', + statusCode: 200, + response: createExpectVisualizationResults(spaceId), + }, + unknownType: { + description: 'empty result', + statusCode: 200, + response: createExpectEmpty(1, 20, 0), + }, + pageBeyondTotal: { + description: 'empty result', + statusCode: 200, + response: createExpectEmpty(100, 100, 1), + }, + unknownSearchField: { + description: 'empty result', + statusCode: 200, + response: createExpectEmpty(1, 20, 0), + }, + noType: { + description: 'all objects', + statusCode: 200, + response: createExpectResults(spaceId), + }, + }, + }); + + findTest(AUTHENTICATION.KIBANA_DUAL_PRIVILEGES_DASHBOARD_ONLY_USER.USERNAME, { + auth: { + username: AUTHENTICATION.KIBANA_DUAL_PRIVILEGES_DASHBOARD_ONLY_USER.USERNAME, + password: AUTHENTICATION.KIBANA_DUAL_PRIVILEGES_DASHBOARD_ONLY_USER.PASSWORD, + }, + spaceId, + tests: { + normal: { + description: 'only the visualization', + statusCode: 200, + response: createExpectVisualizationResults(spaceId), + }, + unknownType: { + description: 'forbidden find wigwags message', + statusCode: 403, + response: createExpectRbacForbidden('wigwags'), + }, + pageBeyondTotal: { + description: 'empty result', + statusCode: 200, + response: createExpectEmpty(100, 100, 1), + }, + unknownSearchField: { + description: 'forbidden find wigwags message', + statusCode: 403, + response: createExpectRbacForbidden('wigwags'), + }, + noType: { + description: 'all objects', + statusCode: 200, + response: createExpectResults(spaceId), + }, + } + }); + + findTest(AUTHENTICATION.KIBANA_RBAC_USER.USERNAME, { + auth: { + username: AUTHENTICATION.KIBANA_RBAC_USER.USERNAME, + password: AUTHENTICATION.KIBANA_RBAC_USER.PASSWORD, + }, + spaceId, + tests: { + normal: { + description: 'only the visualization', + statusCode: 200, + response: createExpectVisualizationResults(spaceId), + }, + unknownType: { + description: 'empty result', + statusCode: 200, + response: createExpectEmpty(1, 20, 0), + }, + pageBeyondTotal: { + description: 'empty result', + statusCode: 200, + response: createExpectEmpty(100, 100, 1), + }, + unknownSearchField: { + description: 'empty result', + statusCode: 200, + response: createExpectEmpty(1, 20, 0), + }, + noType: { + description: 'all objects', + statusCode: 200, + response: createExpectResults(spaceId), + }, + }, + }); + + findTest(AUTHENTICATION.KIBANA_RBAC_DASHBOARD_ONLY_USER.USERNAME, { + auth: { + username: AUTHENTICATION.KIBANA_RBAC_DASHBOARD_ONLY_USER.USERNAME, + password: AUTHENTICATION.KIBANA_RBAC_DASHBOARD_ONLY_USER.PASSWORD, + }, + spaceId, + tests: { + normal: { + description: 'only the visualization', + statusCode: 200, + response: createExpectVisualizationResults(spaceId), + }, + unknownType: { + description: 'forbidden find wigwags message', + statusCode: 403, + response: createExpectRbacForbidden('wigwags'), + }, + pageBeyondTotal: { + description: 'empty result', + statusCode: 200, + response: createExpectEmpty(100, 100, 1), + }, + unknownSearchField: { + description: 'forbidden find wigwags message', + statusCode: 403, + response: createExpectRbacForbidden('wigwags'), + }, + noType: { + description: 'all objects', + statusCode: 200, + response: createExpectResults(spaceId), + }, + } + }); + + findTest(userWithAllAtSpace.USERNAME, { + auth: { + username: userWithAllAtSpace.USERNAME, + password: userWithAllAtSpace.PASSWORD, + }, + spaceId, + tests: { + normal: { + description: 'only the visualization', + statusCode: 200, + response: createExpectVisualizationResults(spaceId), + }, + unknownType: { + description: 'forbidden and find wigwags message', + statusCode: 403, + response: createExpectRbacForbidden('wigwags'), + }, + pageBeyondTotal: { + description: 'empty result', + statusCode: 200, + response: createExpectEmpty(100, 100, 1), + }, + unknownSearchField: { + description: 'forbidden and find wigwags message', + statusCode: 403, + response: createExpectRbacForbidden('wigwags'), + }, + noType: { + description: 'all objects', + statusCode: 200, + response: createExpectResults(spaceId), + }, + } + }); + + findTest(userWithReadAtSpace.USERNAME, { + auth: { + username: userWithReadAtSpace.USERNAME, + password: userWithReadAtSpace.PASSWORD, + }, + spaceId, + tests: { + normal: { + description: 'only the visualization', + statusCode: 200, + response: createExpectVisualizationResults(spaceId), + }, + unknownType: { + description: 'forbidden and find wigwags message', + statusCode: 403, + response: createExpectRbacForbidden('wigwags'), + }, + pageBeyondTotal: { + description: 'empty result', + statusCode: 200, + response: createExpectEmpty(100, 100, 1), + }, + unknownSearchField: { + description: 'forbidden and find wigwags message', + statusCode: 403, + response: createExpectRbacForbidden('wigwags'), + }, + noType: { + description: 'all objects', + statusCode: 200, + response: createExpectResults(spaceId), + }, + } + }); + + findTest(userWithAllAtOtherSpace.USERNAME, { + auth: { + username: userWithAllAtOtherSpace.USERNAME, + password: userWithAllAtOtherSpace.PASSWORD, + }, + spaceId, + tests: { + normal: { + description: 'forbidden login and find visualization message', + statusCode: 403, + response: createExpectRbacForbidden('visualization'), + }, + unknownType: { + description: 'forbidden login and find wigwags message', + statusCode: 403, + response: createExpectRbacForbidden('wigwags'), + }, + pageBeyondTotal: { + description: 'forbidden login and find visualization message', + statusCode: 403, + response: createExpectRbacForbidden('visualization'), + }, + unknownSearchField: { + description: 'forbidden login and find wigwags message', + statusCode: 403, + response: createExpectRbacForbidden('wigwags'), + }, + noType: { + description: `forbidded can't find any types`, + statusCode: 403, + response: createExpectRbacForbidden(), + } + } + }); + }); + }); + }); +} diff --git a/x-pack/test/saved_object_api_integration/security_and_spaces/apis/saved_objects/index.js b/x-pack/test/saved_object_api_integration/security_and_spaces/apis/saved_objects/index.js index 351e71bc38278d..14ac105ad147c8 100644 --- a/x-pack/test/saved_object_api_integration/security_and_spaces/apis/saved_objects/index.js +++ b/x-pack/test/saved_object_api_integration/security_and_spaces/apis/saved_objects/index.js @@ -9,5 +9,6 @@ export default function ({ loadTestFile }) { describe('saved_objects', () => { loadTestFile(require.resolve('./create')); + loadTestFile(require.resolve('./find')); }); } diff --git a/x-pack/test/saved_object_api_integration/security_only/apis/saved_objects/find.js b/x-pack/test/saved_object_api_integration/security_only/apis/saved_objects/find.js index 35d51ed49d61c6..06bb747b0b7919 100644 --- a/x-pack/test/saved_object_api_integration/security_only/apis/saved_objects/find.js +++ b/x-pack/test/saved_object_api_integration/security_only/apis/saved_objects/find.js @@ -4,8 +4,8 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; import { AUTHENTICATION } from '../../../common/lib/authentication'; +import { findTestSuiteFactory } from '../../../common/suites/saved_objects/find'; export default function ({ getService }) { const supertest = getService('supertestWithoutAuth'); @@ -13,151 +13,14 @@ export default function ({ getService }) { describe('find', () => { - const expectVisualizationResults = (resp) => { - expect(resp.body).to.eql({ - page: 1, - per_page: 20, - total: 1, - saved_objects: [ - { - type: 'visualization', - id: 'dd7caf20-9efd-11e7-acb3-3dab96693fab', - version: 1, - attributes: { - 'title': 'Count of requests' - } - }, - ] - }); - }; - - const expectResultsWithValidTypes = (resp) => { - expect(resp.body).to.eql({ - page: 1, - per_page: 20, - total: 5, - saved_objects: [ - { - id: '91200a00-9efd-11e7-acb3-3dab96693fab', - type: 'index-pattern', - updated_at: '2017-09-21T18:49:16.270Z', - version: 1, - attributes: resp.body.saved_objects[0].attributes - }, - { - id: '7.0.0-alpha1', - type: 'config', - updated_at: '2017-09-21T18:49:16.302Z', - version: 1, - attributes: resp.body.saved_objects[1].attributes - }, - { - id: 'dd7caf20-9efd-11e7-acb3-3dab96693fab', - type: 'visualization', - updated_at: '2017-09-21T18:51:23.794Z', - version: 1, - attributes: resp.body.saved_objects[2].attributes - }, - { - id: 'be3733a0-9efe-11e7-acb3-3dab96693fab', - type: 'dashboard', - updated_at: '2017-09-21T18:57:40.826Z', - version: 1, - attributes: resp.body.saved_objects[3].attributes - }, - { - id: `8121a00-8efd-21e7-1cb3-34ab96643444`, - type: 'chapo', - updated_at: '2017-09-21T18:59:16.270Z', - version: 1, - attributes: { - 'name': 'El Chapo' - } - } - ] - }); - }; - - const createExpectEmpty = (page, perPage, total) => (resp) => { - expect(resp.body).to.eql({ - page: page, - per_page: perPage, - total: total, - saved_objects: [] - }); - }; - - const createExpectRbacForbidden = (type) => resp => { - expect(resp.body).to.eql({ - statusCode: 403, - error: 'Forbidden', - message: `Unable to find ${type}, missing action:saved_objects/${type}/find` - }); - }; - - const createExpectLegacyForbidden = (username) => resp => { - expect(resp.body).to.eql({ - statusCode: 403, - error: 'Forbidden', - // eslint-disable-next-line max-len - message: `action [indices:data/read/search] is unauthorized for user [${username}]: [security_exception] action [indices:data/read/search] is unauthorized for user [${username}]` - }); - }; - - const findTest = (description, { auth, tests }) => { - describe(description, () => { - before(() => esArchiver.load('saved_objects/spaces')); - after(() => esArchiver.unload('saved_objects/spaces')); - - it(`should return ${tests.normal.statusCode} with ${tests.normal.description}`, async () => ( - await supertest - .get(`/api/saved_objects/_find?type=visualization&fields=title`) - .auth(auth.username, auth.password) - .expect(tests.normal.statusCode) - .then(tests.normal.response) - )); - - describe('unknown type', () => { - it(`should return ${tests.unknownType.statusCode} with ${tests.unknownType.description}`, async () => ( - await supertest - .get(`/api/saved_objects/_find?type=wigwags`) - .auth(auth.username, auth.password) - .expect(tests.unknownType.statusCode) - .then(tests.unknownType.response) - )); - }); - - describe('page beyond total', () => { - it(`should return ${tests.pageBeyondTotal.statusCode} with ${tests.pageBeyondTotal.description}`, async () => ( - await supertest - .get(`/api/saved_objects/_find?type=visualization&page=100&per_page=100`) - .auth(auth.username, auth.password) - .expect(tests.pageBeyondTotal.statusCode) - .then(tests.pageBeyondTotal.response) - )); - }); - - describe('unknown search field', () => { - it(`should return ${tests.unknownSearchField.statusCode} with ${tests.unknownSearchField.description}`, async () => ( - await supertest - .get(`/api/saved_objects/_find?type=wigwags&search_fields=a`) - .auth(auth.username, auth.password) - .expect(tests.unknownSearchField.statusCode) - .then(tests.unknownSearchField.response) - )); - }); - - describe('no type', () => { - it(`should return ${tests.noType.statusCode} with ${tests.noType.description}`, async () => ( - await supertest - .get(`/api/saved_objects/_find`) - .auth(auth.username, auth.password) - .expect(tests.noType.statusCode) - .then(tests.noType.response) - )); - }); - }); - }; + const { + createExpectEmpty, + createExpectRbacForbidden, + createExpectResults, + createExpectLegacyForbidden, + createExpectVisualizationResults, + findTest, + } = findTestSuiteFactory(esArchiver, supertest); findTest(`not a kibana user`, { auth: { @@ -202,7 +65,7 @@ export default function ({ getService }) { normal: { description: 'only the visualization', statusCode: 200, - response: expectVisualizationResults, + response: createExpectVisualizationResults(), }, unknownType: { description: 'empty result', @@ -222,7 +85,7 @@ export default function ({ getService }) { noType: { description: 'all objects', statusCode: 200, - response: expectResultsWithValidTypes, + response: createExpectResults(), }, }, }); @@ -236,7 +99,7 @@ export default function ({ getService }) { normal: { description: 'only the visualization', statusCode: 200, - response: expectVisualizationResults, + response: createExpectVisualizationResults(), }, unknownType: { description: 'empty result', @@ -256,7 +119,7 @@ export default function ({ getService }) { noType: { description: 'all objects', statusCode: 200, - response: expectResultsWithValidTypes, + response: createExpectResults(), }, }, }); @@ -270,7 +133,7 @@ export default function ({ getService }) { normal: { description: 'only the visualization', statusCode: 200, - response: expectVisualizationResults, + response: createExpectVisualizationResults(), }, unknownType: { description: 'empty result', @@ -290,7 +153,7 @@ export default function ({ getService }) { noType: { description: 'all objects', statusCode: 200, - response: expectResultsWithValidTypes, + response: createExpectResults(), }, } }); @@ -304,7 +167,7 @@ export default function ({ getService }) { normal: { description: 'only the visualization', statusCode: 200, - response: expectVisualizationResults, + response: createExpectVisualizationResults(), }, unknownType: { description: 'empty result', @@ -324,7 +187,7 @@ export default function ({ getService }) { noType: { description: 'all objects', statusCode: 200, - response: expectResultsWithValidTypes, + response: createExpectResults(), }, }, }); @@ -338,7 +201,7 @@ export default function ({ getService }) { normal: { description: 'only the visualization', statusCode: 200, - response: expectVisualizationResults, + response: createExpectVisualizationResults(), }, unknownType: { description: 'forbidden find wigwags message', @@ -358,7 +221,7 @@ export default function ({ getService }) { noType: { description: 'all objects', statusCode: 200, - response: expectResultsWithValidTypes, + response: createExpectResults(), }, } }); @@ -372,7 +235,7 @@ export default function ({ getService }) { normal: { description: 'only the visualization', statusCode: 200, - response: expectVisualizationResults, + response: createExpectVisualizationResults(), }, unknownType: { description: 'empty result', @@ -392,7 +255,7 @@ export default function ({ getService }) { noType: { description: 'all objects', statusCode: 200, - response: expectResultsWithValidTypes, + response: createExpectResults(), }, }, }); @@ -406,7 +269,7 @@ export default function ({ getService }) { normal: { description: 'only the visualization', statusCode: 200, - response: expectVisualizationResults, + response: createExpectVisualizationResults(), }, unknownType: { description: 'forbidden find wigwags message', @@ -426,8 +289,144 @@ export default function ({ getService }) { noType: { description: 'all objects', statusCode: 200, - response: expectResultsWithValidTypes, + response: createExpectResults(), + }, + } + }); + + findTest(`kibana rbac default space all user`, { + auth: { + username: AUTHENTICATION.KIBANA_RBAC_DEFAULT_SPACE_ALL_USER.USERNAME, + password: AUTHENTICATION.KIBANA_RBAC_DEFAULT_SPACE_ALL_USER.PASSWORD, + }, + tests: { + normal: { + description: 'only the visualization', + statusCode: 403, + response: createExpectLegacyForbidden(AUTHENTICATION.KIBANA_RBAC_DEFAULT_SPACE_ALL_USER.USERNAME), + }, + unknownType: { + description: 'empty result', + statusCode: 403, + response: createExpectLegacyForbidden(AUTHENTICATION.KIBANA_RBAC_DEFAULT_SPACE_ALL_USER.USERNAME), + }, + pageBeyondTotal: { + description: 'empty result', + statusCode: 403, + response: createExpectLegacyForbidden(AUTHENTICATION.KIBANA_RBAC_DEFAULT_SPACE_ALL_USER.USERNAME), + }, + unknownSearchField: { + description: 'empty result', + statusCode: 403, + response: createExpectLegacyForbidden(AUTHENTICATION.KIBANA_RBAC_DEFAULT_SPACE_ALL_USER.USERNAME), + }, + noType: { + description: 'all objects', + statusCode: 403, + response: createExpectLegacyForbidden(AUTHENTICATION.KIBANA_RBAC_DEFAULT_SPACE_ALL_USER.USERNAME), + }, + } + }); + + findTest(`kibana rbac default space read user`, { + auth: { + username: AUTHENTICATION.KIBANA_RBAC_DEFAULT_SPACE_READ_USER.USERNAME, + password: AUTHENTICATION.KIBANA_RBAC_DEFAULT_SPACE_READ_USER.PASSWORD, + }, + tests: { + normal: { + description: 'only the visualization', + statusCode: 403, + response: createExpectLegacyForbidden(AUTHENTICATION.KIBANA_RBAC_DEFAULT_SPACE_READ_USER.USERNAME), + }, + unknownType: { + description: 'empty result', + statusCode: 403, + response: createExpectLegacyForbidden(AUTHENTICATION.KIBANA_RBAC_DEFAULT_SPACE_READ_USER.USERNAME), + }, + pageBeyondTotal: { + description: 'empty result', + statusCode: 403, + response: createExpectLegacyForbidden(AUTHENTICATION.KIBANA_RBAC_DEFAULT_SPACE_READ_USER.USERNAME), + }, + unknownSearchField: { + description: 'empty result', + statusCode: 403, + response: createExpectLegacyForbidden(AUTHENTICATION.KIBANA_RBAC_DEFAULT_SPACE_READ_USER.USERNAME), + }, + noType: { + description: 'all objects', + statusCode: 403, + response: createExpectLegacyForbidden(AUTHENTICATION.KIBANA_RBAC_DEFAULT_SPACE_READ_USER.USERNAME), + }, + } + }); + + findTest(`kibana rbac space 1 all user`, { + auth: { + username: AUTHENTICATION.KIBANA_RBAC_SPACE_1_ALL_USER.USERNAME, + password: AUTHENTICATION.KIBANA_RBAC_SPACE_1_ALL_USER.PASSWORD, + }, + tests: { + normal: { + description: 'forbidden login and find visualization message', + statusCode: 403, + response: createExpectLegacyForbidden(AUTHENTICATION.KIBANA_RBAC_SPACE_1_ALL_USER.USERNAME), }, + unknownType: { + description: 'forbidden login and find wigwags message', + statusCode: 403, + response: createExpectLegacyForbidden(AUTHENTICATION.KIBANA_RBAC_SPACE_1_ALL_USER.USERNAME), + }, + pageBeyondTotal: { + description: 'forbidden login and find visualization message', + statusCode: 403, + response: createExpectLegacyForbidden(AUTHENTICATION.KIBANA_RBAC_SPACE_1_ALL_USER.USERNAME), + }, + unknownSearchField: { + description: 'forbidden login and find wigwags message', + statusCode: 403, + response: createExpectLegacyForbidden(AUTHENTICATION.KIBANA_RBAC_SPACE_1_ALL_USER.USERNAME), + }, + noType: { + description: `forbidded can't find any types`, + statusCode: 403, + response: createExpectLegacyForbidden(AUTHENTICATION.KIBANA_RBAC_SPACE_1_ALL_USER.USERNAME), + } + } + }); + + findTest(`kibana rbac space 1 readonly user`, { + auth: { + username: AUTHENTICATION.KIBANA_RBAC_SPACE_1_READ_USER.USERNAME, + password: AUTHENTICATION.KIBANA_RBAC_SPACE_1_READ_USER.PASSWORD, + }, + tests: { + normal: { + description: 'forbidden login and find visualization message', + statusCode: 403, + response: createExpectLegacyForbidden(AUTHENTICATION.KIBANA_RBAC_SPACE_1_READ_USER.USERNAME), + }, + unknownType: { + description: 'forbidden login and find wigwags message', + statusCode: 403, + response: createExpectLegacyForbidden(AUTHENTICATION.KIBANA_RBAC_SPACE_1_READ_USER.USERNAME), + }, + pageBeyondTotal: { + description: 'forbidden login and find visualization message', + statusCode: 403, + response: createExpectLegacyForbidden(AUTHENTICATION.KIBANA_RBAC_SPACE_1_READ_USER.USERNAME), + }, + unknownSearchField: { + description: 'forbidden login and find wigwags message', + statusCode: 403, + response: createExpectLegacyForbidden(AUTHENTICATION.KIBANA_RBAC_SPACE_1_READ_USER.USERNAME), + }, + noType: { + description: `forbidded can't find any types`, + statusCode: 403, + response: createExpectLegacyForbidden(AUTHENTICATION.KIBANA_RBAC_SPACE_1_READ_USER.USERNAME), + } } }); }); diff --git a/x-pack/test/saved_object_api_integration/spaces_only/apis/saved_objects/find.js b/x-pack/test/saved_object_api_integration/spaces_only/apis/saved_objects/find.js index c92c85f3c7832c..2602ba8558a748 100644 --- a/x-pack/test/saved_object_api_integration/spaces_only/apis/saved_objects/find.js +++ b/x-pack/test/saved_object_api_integration/spaces_only/apis/saved_objects/find.js @@ -4,137 +4,21 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; import { SPACES } from '../../../common/lib/spaces'; -import { getIdPrefix, getUrlPrefix } from '../../../common/lib/space_test_utils'; +import { findTestSuiteFactory } from '../../../common/suites/saved_objects/find'; export default function ({ getService }) { const supertest = getService('supertest'); const esArchiver = getService('esArchiver'); - describe('find', () => { - - const expectVisualizationResults = (spaceId) => (resp) => { - expect(resp.body).to.eql({ - page: 1, - per_page: 20, - total: 1, - saved_objects: [ - { - type: 'visualization', - id: `${getIdPrefix(spaceId)}dd7caf20-9efd-11e7-acb3-3dab96693fab`, - // no space id on the saved object because the field is not requested as part of a find operation - version: 1, - attributes: { - 'title': 'Count of requests' - } - } - ] - }); - }; - - const expectAllResults = (spaceId) => (resp) => { - // TODO(legrego): update once config is space-aware - - const sortById = ({ id: id1 }, { id: id2 }) => id1 < id2 ? -1 : 1; - - resp.body.saved_objects.sort(sortById); - - const expectedSavedObjects = [{ - id: '7.0.0-alpha1', - type: 'config', - updated_at: '2017-09-21T18:49:16.302Z', - version: 1, - }, - { - id: `${getIdPrefix(spaceId)}91200a00-9efd-11e7-acb3-3dab96693fab`, - type: 'index-pattern', - updated_at: '2017-09-21T18:49:16.270Z', - version: 1, - }, - - { - id: `${getIdPrefix(spaceId)}be3733a0-9efe-11e7-acb3-3dab96693fab`, - type: 'dashboard', - updated_at: '2017-09-21T18:57:40.826Z', - version: 1, - }, - { - id: `${getIdPrefix(spaceId)}dd7caf20-9efd-11e7-acb3-3dab96693fab`, - type: 'visualization', - updated_at: '2017-09-21T18:51:23.794Z', - version: 1, - }, { - id: `8121a00-8efd-21e7-1cb3-34ab96643444`, - type: 'chapo', - updated_at: '2017-09-21T18:59:16.270Z', - version: 1, - }] - .sort(sortById); - - expectedSavedObjects.forEach((object, index) => { - if (resp.body.saved_objects[index]) { - object.attributes = resp.body.saved_objects[index].attributes; - } - }); - - expect(resp.body).to.eql({ - page: 1, - per_page: 20, - total: expectedSavedObjects.length, - saved_objects: expectedSavedObjects, - }); - }; - - const createExpectEmpty = (page, perPage, total) => (resp) => { - expect(resp.body).to.eql({ - page: page, - per_page: perPage, - total: total, - saved_objects: [] - }); - }; - - const findTest = (description, { spaceId, tests }) => { - describe(description, () => { - before(() => esArchiver.load('saved_objects/spaces')); - after(() => esArchiver.unload('saved_objects/spaces')); - - it(`should return ${tests.normal.statusCode} with ${tests.normal.description}`, async () => ( - await supertest - .get(`${getUrlPrefix(spaceId)}/api/saved_objects/_find?type=visualization&fields=title`) - .expect(tests.normal.statusCode) - .then(tests.normal.response) - )); + const { + createExpectEmpty, + createExpectResults, + createExpectVisualizationResults, + findTest, + } = findTestSuiteFactory(esArchiver, supertest); - describe('page beyond total', () => { - it(`should return ${tests.pageBeyondTotal.statusCode} with ${tests.pageBeyondTotal.description}`, async () => ( - await supertest - .get(`${getUrlPrefix(spaceId)}/api/saved_objects/_find?type=visualization&page=100&per_page=100`) - .expect(tests.pageBeyondTotal.statusCode) - .then(tests.pageBeyondTotal.response) - )); - }); - - describe('unknown search field', () => { - it(`should return ${tests.unknownSearchField.statusCode} with ${tests.unknownSearchField.description}`, async () => ( - await supertest - .get(`${getUrlPrefix(spaceId)}/api/saved_objects/_find?type=wigwags&search_fields=a`) - .expect(tests.unknownSearchField.statusCode) - .then(tests.unknownSearchField.response) - )); - }); - - describe('no type', () => { - it(`should return ${tests.noType.statusCode} with ${tests.noType.description}`, async () => ( - await supertest - .get(`${getUrlPrefix(spaceId)}/api/saved_objects/_find`) - .expect(tests.noType.statusCode) - .then(tests.noType.response) - )); - }); - }); - }; + describe('find', () => { findTest(`objects only within the current space (space_1)`, { ...SPACES.SPACE_1, @@ -142,7 +26,12 @@ export default function ({ getService }) { normal: { description: 'only the visualization', statusCode: 200, - response: expectVisualizationResults(SPACES.SPACE_1.spaceId), + response: createExpectVisualizationResults(SPACES.SPACE_1.spaceId), + }, + unknownType: { + description: 'empty result', + statusCode: 200, + response: createExpectEmpty(1, 20, 0), }, pageBeyondTotal: { description: 'empty result', @@ -157,7 +46,7 @@ export default function ({ getService }) { noType: { description: 'all objects', statusCode: 200, - response: expectAllResults(SPACES.SPACE_1.spaceId), + response: createExpectResults(SPACES.SPACE_1.spaceId), }, } }); @@ -168,7 +57,12 @@ export default function ({ getService }) { normal: { description: 'only the visualization', statusCode: 200, - response: expectVisualizationResults(SPACES.DEFAULT.spaceId), + response: createExpectVisualizationResults(SPACES.DEFAULT.spaceId), + }, + unknownType: { + description: 'empty result', + statusCode: 200, + response: createExpectEmpty(1, 20, 0), }, pageBeyondTotal: { description: 'empty result', @@ -183,7 +77,7 @@ export default function ({ getService }) { noType: { description: 'all objects', statusCode: 200, - response: expectAllResults(SPACES.DEFAULT.spaceId), + response: createExpectResults(SPACES.DEFAULT.spaceId), }, } });