diff --git a/packages/kbn-test/src/functional_tests/lib/run_elasticsearch.js b/packages/kbn-test/src/functional_tests/lib/run_elasticsearch.js index d0a3160018fea..f19164fdd6027 100644 --- a/packages/kbn-test/src/functional_tests/lib/run_elasticsearch.js +++ b/packages/kbn-test/src/functional_tests/lib/run_elasticsearch.js @@ -25,22 +25,27 @@ import { setupUsers, DEFAULT_SUPERUSER_PASS } from './auth'; export async function runElasticsearch({ config, options }) { const { log, esFrom } = options; - const isOss = config.get('esTestCluster.license') === 'oss'; + const securityEnabled = config.get('esTestCluster.securityEnabled'); const cluster = createEsTestCluster({ port: config.get('servers.elasticsearch.port'), - password: !isOss ? DEFAULT_SUPERUSER_PASS : config.get('servers.elasticsearch.password'), + password: securityEnabled + ? DEFAULT_SUPERUSER_PASS + : config.get('servers.elasticsearch.password'), license: config.get('esTestCluster.license'), log, basePath: resolve(KIBANA_ROOT, '.es'), esFrom: esFrom || config.get('esTestCluster.from'), }); - const esArgs = config.get('esTestCluster.serverArgs'); + const esArgs = [ + ...config.get('esTestCluster.serverArgs'), + ...(securityEnabled ? ['xpack.security.enabled=true'] : []), + ]; await cluster.start(esArgs); - if (!isOss) { + if (securityEnabled) { await setupUsers(log, config); } diff --git a/src/functional_test_runner/lib/config/schema.js b/src/functional_test_runner/lib/config/schema.js index faf7de7fea940..6c3d07f04fd6a 100644 --- a/src/functional_test_runner/lib/config/schema.js +++ b/src/functional_test_runner/lib/config/schema.js @@ -117,6 +117,7 @@ export const schema = Joi.object().keys({ license: Joi.string().default('oss'), from: Joi.string().default('snapshot'), serverArgs: Joi.array(), + securityEnabled: Joi.boolean().default(false), }).default(), kbnTestServer: Joi.object().keys({ diff --git a/x-pack/test/functional/config.js b/x-pack/test/functional/config.js index 5f4cb60fa81e8..9fe631bf298c1 100644 --- a/x-pack/test/functional/config.js +++ b/x-pack/test/functional/config.js @@ -140,9 +140,9 @@ export default async function ({ readConfigFile }) { esTestCluster: { license: 'trial', from: 'snapshot', + securityEnabled: true, serverArgs: [ 'xpack.license.self_generated.type=trial', - 'xpack.security.enabled=true', ], }, diff --git a/x-pack/test/saved_object_api_integration/common/config.js b/x-pack/test/saved_object_api_integration/common/config.js index ae1e5c13c0c22..eb1b1a9514ccc 100644 --- a/x-pack/test/saved_object_api_integration/common/config.js +++ b/x-pack/test/saved_object_api_integration/common/config.js @@ -9,7 +9,7 @@ import { resolveKibanaPath } from '@kbn/plugin-helpers'; import { EsProvider } from './services/es'; -export function createTestConfig(name, { license = 'trial', disabledPlugins = [] } = {}) { +export function createTestConfig(name, { license = 'trial', disabledPlugins = [], securityEnabled = true } = {}) { return async function ({ readConfigFile }) { @@ -48,10 +48,11 @@ export function createTestConfig(name, { license = 'trial', disabledPlugins = [] }, esTestCluster: { - ...config.xpack.api.get('esTestCluster'), license, + from: 'snapshot', + securityEnabled, serverArgs: [ - ...config.xpack.api.get('esTestCluster.serverArgs'), + ...license === 'trial' ? ['xpack.license.self_generated.type=trial'] : [], ], }, 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 new file mode 100644 index 0000000000000..f6d52f86f9ff1 --- /dev/null +++ b/x-pack/test/saved_object_api_integration/common/suites/saved_objects/create.js @@ -0,0 +1,123 @@ +/* + * 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 { getUrlPrefix } from '../../lib/space_test_utils'; +import { DEFAULT_SPACE_ID } from '../../../../../plugins/spaces/common/constants'; + +export function createTestSuiteFactory(es, esArchiver, supertest) { + const createTest = (description, { + auth = { + username: undefined, + password: undefined + }, + spaceId, + tests, + }) => { + describe(description, () => { + before(() => esArchiver.load('saved_objects/spaces')); + after(() => esArchiver.unload('saved_objects/spaces')); + it(`should return ${tests.spaceAware.statusCode} for a space-aware type`, async () => { + await supertest + .post(`${getUrlPrefix(spaceId)}/api/saved_objects/visualization`) + .auth(auth.username, auth.password) + .send({ + attributes: { + title: 'My favorite vis' + } + }) + .expect(tests.spaceAware.statusCode) + .then(tests.spaceAware.response); + }); + + it(`should return ${tests.notSpaceAware.statusCode} for a non space-aware type`, async () => { + await supertest + .post(`${getUrlPrefix(spaceId)}/api/saved_objects/space`) + .auth(auth.username, auth.password) + .send({ + attributes: { + name: 'My favorite space', + } + }) + .expect(tests.notSpaceAware.statusCode) + .then(tests.notSpaceAware.response); + }); + + }); + }; + + const createExpectSpaceAwareResults = (spaceId = DEFAULT_SPACE_ID) => async (resp) => { + expect(resp.body).to.have.property('id').match(/^[0-9a-f-]{36}$/); + + // loose ISO8601 UTC time with milliseconds validation + expect(resp.body).to.have.property('updated_at').match(/^[\d-]{10}T[\d:\.]{12}Z$/); + + expect(resp.body).to.eql({ + id: resp.body.id, + type: 'visualization', + updated_at: resp.body.updated_at, + version: 1, + attributes: { + title: 'My favorite vis' + } + }); + + const expectedSpacePrefix = spaceId === DEFAULT_SPACE_ID ? '' : `${spaceId}:`; + + // query ES directory to ensure namespace was or wasn't specified + const { _source } = await es.get({ + id: `${expectedSpacePrefix}visualization:${resp.body.id}`, + type: 'doc', + index: '.kibana' + }); + + const { + namespace: actualNamespace + } = _source; + + if (spaceId === DEFAULT_SPACE_ID) { + expect(actualNamespace).to.eql(undefined); + } else { + expect(actualNamespace).to.eql(spaceId); + } + }; + + const expectNotSpaceAwareResults = () => async (resp) => { + expect(resp.body).to.have.property('id').match(/^[0-9a-f-]{36}$/); + + // loose ISO8601 UTC time with milliseconds validation + expect(resp.body).to.have.property('updated_at').match(/^[\d-]{10}T[\d:\.]{12}Z$/); + + expect(resp.body).to.eql({ + id: resp.body.id, + type: 'space', + updated_at: resp.body.updated_at, + version: 1, + attributes: { + name: 'My favorite space', + } + }); + + // query ES directory to ensure namespace wasn't specified + const { _source } = await es.get({ + id: `space:${resp.body.id}`, + type: 'doc', + index: '.kibana' + }); + + const { + namespace: actualNamespace + } = _source; + + expect(actualNamespace).to.eql(undefined); + }; + + + return { + createTest, + createExpectSpaceAwareResults, + expectNotSpaceAwareResults, + }; +} diff --git a/x-pack/test/saved_object_api_integration/security_only/apis/saved_objects/create.js b/x-pack/test/saved_object_api_integration/security_only/apis/saved_objects/create.js index 9a7a12557aa80..a1eadfbea96ec 100644 --- a/x-pack/test/saved_object_api_integration/security_only/apis/saved_objects/create.js +++ b/x-pack/test/saved_object_api_integration/security_only/apis/saved_objects/create.js @@ -6,34 +6,26 @@ import expect from 'expect.js'; import { AUTHENTICATION } from '../../../common/lib/authentication'; +import { createTestSuiteFactory } from '../../../common/suites/saved_objects/create'; export default function ({ getService }) { - const supertest = getService('supertestWithoutAuth'); + const supertestWithoutAuth = getService('supertestWithoutAuth'); + const es = getService('es'); const esArchiver = getService('esArchiver'); - describe('create', () => { - const expectResults = (resp) => { - expect(resp.body).to.have.property('id').match(/^[0-9a-f-]{36}$/); - - // loose ISO8601 UTC time with milliseconds validation - expect(resp.body).to.have.property('updated_at').match(/^[\d-]{10}T[\d:\.]{12}Z$/); + const { + createTest, + createExpectSpaceAwareResults, + expectNotSpaceAwareResults + } = createTestSuiteFactory(es, esArchiver, supertestWithoutAuth); - expect(resp.body).to.eql({ - id: resp.body.id, - type: 'visualization', - updated_at: resp.body.updated_at, - version: 1, - attributes: { - title: 'My favorite vis' - } - }); - }; + describe('create', () => { - const expectRbacForbidden = resp => { + const createExpectRbacForbidden = type => resp => { expect(resp.body).to.eql({ statusCode: 403, error: 'Forbidden', - message: `Unable to create visualization, missing action:saved_objects/visualization/create` + message: `Unable to create ${type}, missing action:saved_objects/${type}/create` }); }; @@ -46,32 +38,17 @@ export default function ({ getService }) { }); }; - const createTest = (description, { auth, tests }) => { - describe(description, () => { - before(() => esArchiver.load('saved_objects/spaces')); - after(() => esArchiver.unload('saved_objects/spaces')); - it(`should return ${tests.default.statusCode}`, async () => { - await supertest - .post(`/api/saved_objects/visualization`) - .auth(auth.username, auth.password) - .send({ - attributes: { - title: 'My favorite vis' - } - }) - .expect(tests.default.statusCode) - .then(tests.default.response); - }); - }); - }; - createTest(`not a kibana user`, { auth: { username: AUTHENTICATION.NOT_A_KIBANA_USER.USERNAME, password: AUTHENTICATION.NOT_A_KIBANA_USER.PASSWORD, }, tests: { - default: { + spaceAware: { + statusCode: 403, + response: createExpectLegacyForbidden(AUTHENTICATION.NOT_A_KIBANA_USER.USERNAME), + }, + notSpaceAware: { statusCode: 403, response: createExpectLegacyForbidden(AUTHENTICATION.NOT_A_KIBANA_USER.USERNAME), }, @@ -84,9 +61,13 @@ export default function ({ getService }) { password: AUTHENTICATION.SUPERUSER.PASSWORD, }, tests: { - default: { + spaceAware: { + statusCode: 200, + response: createExpectSpaceAwareResults(), + }, + notSpaceAware: { statusCode: 200, - response: expectResults, + response: expectNotSpaceAwareResults(), }, } }); @@ -97,9 +78,13 @@ export default function ({ getService }) { password: AUTHENTICATION.KIBANA_LEGACY_USER.PASSWORD, }, tests: { - default: { + spaceAware: { statusCode: 200, - response: expectResults, + response: createExpectSpaceAwareResults(), + }, + notSpaceAware: { + statusCode: 200, + response: expectNotSpaceAwareResults, }, } }); @@ -110,7 +95,11 @@ export default function ({ getService }) { password: AUTHENTICATION.KIBANA_LEGACY_DASHBOARD_ONLY_USER.PASSWORD, }, tests: { - default: { + spaceAware: { + statusCode: 403, + response: createExpectLegacyForbidden(AUTHENTICATION.KIBANA_LEGACY_DASHBOARD_ONLY_USER.USERNAME), + }, + notSpaceAware: { statusCode: 403, response: createExpectLegacyForbidden(AUTHENTICATION.KIBANA_LEGACY_DASHBOARD_ONLY_USER.USERNAME), }, @@ -123,9 +112,13 @@ export default function ({ getService }) { password: AUTHENTICATION.KIBANA_DUAL_PRIVILEGES_USER.PASSWORD, }, tests: { - default: { + spaceAware: { + statusCode: 200, + response: createExpectSpaceAwareResults(), + }, + notSpaceAware: { statusCode: 200, - response: expectResults, + response: expectNotSpaceAwareResults, }, } }); @@ -136,9 +129,13 @@ export default function ({ getService }) { password: AUTHENTICATION.KIBANA_DUAL_PRIVILEGES_DASHBOARD_ONLY_USER.PASSWORD, }, tests: { - default: { + spaceAware: { statusCode: 403, - response: expectRbacForbidden, + response: createExpectRbacForbidden('visualization'), + }, + notSpaceAware: { + statusCode: 403, + response: createExpectRbacForbidden('space'), }, } }); @@ -149,9 +146,13 @@ export default function ({ getService }) { password: AUTHENTICATION.KIBANA_RBAC_USER.PASSWORD, }, tests: { - default: { + spaceAware: { + statusCode: 200, + response: createExpectSpaceAwareResults(), + }, + notSpaceAware: { statusCode: 200, - response: expectResults, + response: expectNotSpaceAwareResults, }, } }); @@ -162,9 +163,13 @@ export default function ({ getService }) { password: AUTHENTICATION.KIBANA_RBAC_DASHBOARD_ONLY_USER.PASSWORD, }, tests: { - default: { + spaceAware: { + statusCode: 403, + response: createExpectRbacForbidden('visualization'), + }, + notSpaceAware: { statusCode: 403, - response: expectRbacForbidden, + response: createExpectRbacForbidden('space'), }, } }); diff --git a/x-pack/test/saved_object_api_integration/spaces_only/apis/saved_objects/create.js b/x-pack/test/saved_object_api_integration/spaces_only/apis/saved_objects/create.js index 86cdd70bc4379..b8f20dca1531a 100644 --- a/x-pack/test/saved_object_api_integration/spaces_only/apis/saved_objects/create.js +++ b/x-pack/test/saved_object_api_integration/spaces_only/apis/saved_objects/create.js @@ -4,120 +4,28 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from 'expect.js'; -import { getUrlPrefix } from '../../../common/lib/space_test_utils'; import { SPACES } from '../../../common/lib/spaces'; -import { DEFAULT_SPACE_ID } from '../../../../../plugins/spaces/common/constants'; +import { createTestSuiteFactory } from '../../../common/suites/saved_objects/create'; export default function ({ getService }) { - const supertest = getService('supertest'); + const supertestWithoutAuth = getService('supertestWithoutAuth'); const es = getService('es'); const esArchiver = getService('esArchiver'); - describe('create', () => { - const expectSpaceAwareResults = (spaceId) => async (resp) => { - expect(resp.body).to.have.property('id').match(/^[0-9a-f-]{36}$/); - - // loose ISO8601 UTC time with milliseconds validation - expect(resp.body).to.have.property('updated_at').match(/^[\d-]{10}T[\d:\.]{12}Z$/); - - expect(resp.body).to.eql({ - id: resp.body.id, - type: 'visualization', - updated_at: resp.body.updated_at, - version: 1, - attributes: { - title: 'My favorite vis' - } - }); - - const expectedSpacePrefix = spaceId === DEFAULT_SPACE_ID ? '' : `${spaceId}:`; - - // query ES directory to assert on space id - const { _source } = await es.get({ - id: `${expectedSpacePrefix}visualization:${resp.body.id}`, - type: 'doc', - index: '.kibana' - }); - - const { - namespace: actualSpaceId = '**not defined**' - } = _source; - - if (spaceId === DEFAULT_SPACE_ID) { - expect(actualSpaceId).to.eql('**not defined**'); - } else { - expect(actualSpaceId).to.eql(spaceId); - } - }; - - const expectNotSpaceAwareResults = () => async (resp) => { - expect(resp.body).to.have.property('id').match(/^[0-9a-f-]{36}$/); + const { + createTest, + createExpectSpaceAwareResults, + expectNotSpaceAwareResults + } = createTestSuiteFactory(es, esArchiver, supertestWithoutAuth); - // loose ISO8601 UTC time with milliseconds validation - expect(resp.body).to.have.property('updated_at').match(/^[\d-]{10}T[\d:\.]{12}Z$/); - - expect(resp.body).to.eql({ - id: resp.body.id, - type: 'space', - updated_at: resp.body.updated_at, - version: 1, - attributes: { - name: 'My favorite space', - } - }); - - // query ES directory to assert on space id - const { _source } = await es.get({ - id: `space:${resp.body.id}`, - type: 'doc', - index: '.kibana' - }); - - const { - namespace: actualSpaceId = '**not defined**' - } = _source; - - expect(actualSpaceId).to.eql('**not defined**'); - }; - - const createTest = (description, { spaceId, tests }) => { - describe(description, () => { - before(() => esArchiver.load('saved_objects/spaces')); - after(() => esArchiver.unload('saved_objects/spaces')); - it(`should return ${tests.spaceAware.statusCode} for a space-aware type`, async () => { - await supertest - .post(`${getUrlPrefix(spaceId)}/api/saved_objects/visualization`) - .send({ - attributes: { - title: 'My favorite vis' - } - }) - .expect(tests.spaceAware.statusCode) - .then(tests.spaceAware.response); - }); - - it(`should return ${tests.notSpaceAware.statusCode} for a non space-aware type`, async () => { - await supertest - .post(`${getUrlPrefix(spaceId)}/api/saved_objects/space`) - .send({ - attributes: { - name: 'My favorite space', - } - }) - .expect(tests.notSpaceAware.statusCode) - .then(tests.notSpaceAware.response); - }); - - }); - }; + describe('create', () => { createTest('in the current space (space_1)', { ...SPACES.SPACE_1, tests: { spaceAware: { statusCode: 200, - response: expectSpaceAwareResults(SPACES.SPACE_1.spaceId), + response: createExpectSpaceAwareResults(SPACES.SPACE_1.spaceId), }, notSpaceAware: { statusCode: 200, @@ -131,7 +39,7 @@ export default function ({ getService }) { tests: { spaceAware: { statusCode: 200, - response: expectSpaceAwareResults(SPACES.DEFAULT.spaceId), + response: createExpectSpaceAwareResults(SPACES.DEFAULT.spaceId), }, notSpaceAware: { statusCode: 200, diff --git a/x-pack/test/saved_object_api_integration/spaces_only/config.js b/x-pack/test/saved_object_api_integration/spaces_only/config.js index 9390ef12f51d0..bff1dcbe7face 100644 --- a/x-pack/test/saved_object_api_integration/spaces_only/config.js +++ b/x-pack/test/saved_object_api_integration/spaces_only/config.js @@ -6,4 +6,4 @@ import { createTestConfig } from '../common/config'; -export default createTestConfig('spaces_only', { license: 'basic' }); +export default createTestConfig('spaces_only', { license: 'basic', securityEnabled: false });