From 868f52e8cb246eb14b964d9126f4c8bde5aae6b5 Mon Sep 17 00:00:00 2001 From: Larry Gregory Date: Thu, 8 Apr 2021 09:19:57 -0400 Subject: [PATCH] Create privilege action to allow for decrypted telemetry payload --- .../privileges/privileges.test.ts | 885 ++++++++++-------- .../authorization/privileges/privileges.ts | 8 +- 2 files changed, 484 insertions(+), 409 deletions(-) diff --git a/x-pack/plugins/security/server/authorization/privileges/privileges.test.ts b/x-pack/plugins/security/server/authorization/privileges/privileges.test.ts index 4da0020e94b15..ecbbb637f4da0 100644 --- a/x-pack/plugins/security/server/authorization/privileges/privileges.test.ts +++ b/x-pack/plugins/security/server/authorization/privileges/privileges.test.ts @@ -212,438 +212,485 @@ describe('features', () => { expectManageSpaces: true, expectGetFeatures: true, expectEnterpriseSearch: true, + expectDecryptedTelemetry: true, }, { group: 'space', expectManageSpaces: false, expectGetFeatures: false, expectEnterpriseSearch: false, + expectDecryptedTelemetry: false, }, -].forEach(({ group, expectManageSpaces, expectGetFeatures, expectEnterpriseSearch }) => { - describe(`${group}`, () => { - test('actions defined in any feature privilege are included in `all`', () => { - const features: KibanaFeature[] = [ - new KibanaFeature({ - id: 'foo', - name: 'Foo KibanaFeature', - app: [], - category: { id: 'foo', label: 'foo' }, - catalogue: ['ignore-me-1', 'ignore-me-2'], - management: { - foo: ['ignore-me-1', 'ignore-me-2'], - }, - privileges: { - all: { - management: { - 'all-management': ['all-management-1', 'all-management-2'], - }, - catalogue: ['all-catalogue-1', 'all-catalogue-2'], - savedObject: { - all: ['all-savedObject-all-1', 'all-savedObject-all-2'], - read: ['all-savedObject-read-1', 'all-savedObject-read-2'], - }, - ui: ['all-ui-1', 'all-ui-2'], +].forEach( + ({ + group, + expectManageSpaces, + expectGetFeatures, + expectEnterpriseSearch, + expectDecryptedTelemetry, + }) => { + describe(`${group}`, () => { + test('actions defined in any feature privilege are included in `all`', () => { + const features: KibanaFeature[] = [ + new KibanaFeature({ + id: 'foo', + name: 'Foo KibanaFeature', + app: [], + category: { id: 'foo', label: 'foo' }, + catalogue: ['ignore-me-1', 'ignore-me-2'], + management: { + foo: ['ignore-me-1', 'ignore-me-2'], }, - read: { - management: { - 'read-management': ['read-management-1', 'read-management-2'], + privileges: { + all: { + management: { + 'all-management': ['all-management-1', 'all-management-2'], + }, + catalogue: ['all-catalogue-1', 'all-catalogue-2'], + savedObject: { + all: ['all-savedObject-all-1', 'all-savedObject-all-2'], + read: ['all-savedObject-read-1', 'all-savedObject-read-2'], + }, + ui: ['all-ui-1', 'all-ui-2'], }, - catalogue: ['read-catalogue-1', 'read-catalogue-2'], - savedObject: { - all: ['read-savedObject-all-1', 'read-savedObject-all-2'], - read: ['read-savedObject-read-1', 'read-savedObject-read-2'], + read: { + management: { + 'read-management': ['read-management-1', 'read-management-2'], + }, + catalogue: ['read-catalogue-1', 'read-catalogue-2'], + savedObject: { + all: ['read-savedObject-all-1', 'read-savedObject-all-2'], + read: ['read-savedObject-read-1', 'read-savedObject-read-2'], + }, + ui: ['read-ui-1', 'read-ui-2'], }, - ui: ['read-ui-1', 'read-ui-2'], }, - }, - }), - ]; - - const mockFeaturesPlugin = { - getKibanaFeatures: jest.fn().mockReturnValue(features), - }; - const mockLicenseService = { - getFeatures: jest.fn().mockReturnValue({ allowSubFeaturePrivileges: true }), - getType: jest.fn().mockReturnValue('basic'), - }; - const privileges = privilegesFactory(actions, mockFeaturesPlugin as any, mockLicenseService); - - const actual = privileges.get(); - expect(actual).toHaveProperty(`${group}.all`, [ - actions.login, - actions.version, - ...(expectGetFeatures ? [actions.api.get('features')] : []), - ...(expectManageSpaces - ? [ - actions.space.manage, - actions.ui.get('spaces', 'manage'), - actions.ui.get('management', 'kibana', 'spaces'), - actions.ui.get('catalogue', 'spaces'), - ] - : []), - ...(expectEnterpriseSearch ? [actions.ui.get('enterpriseSearch', 'all')] : []), - actions.ui.get('catalogue', 'all-catalogue-1'), - actions.ui.get('catalogue', 'all-catalogue-2'), - actions.ui.get('management', 'all-management', 'all-management-1'), - actions.ui.get('management', 'all-management', 'all-management-2'), - actions.savedObject.get('all-savedObject-all-1', 'bulk_get'), - actions.savedObject.get('all-savedObject-all-1', 'get'), - actions.savedObject.get('all-savedObject-all-1', 'find'), - actions.savedObject.get('all-savedObject-all-1', 'open_point_in_time'), - actions.savedObject.get('all-savedObject-all-1', 'close_point_in_time'), - actions.savedObject.get('all-savedObject-all-1', 'create'), - actions.savedObject.get('all-savedObject-all-1', 'bulk_create'), - actions.savedObject.get('all-savedObject-all-1', 'update'), - actions.savedObject.get('all-savedObject-all-1', 'bulk_update'), - actions.savedObject.get('all-savedObject-all-1', 'delete'), - actions.savedObject.get('all-savedObject-all-1', 'share_to_space'), - actions.savedObject.get('all-savedObject-all-2', 'bulk_get'), - actions.savedObject.get('all-savedObject-all-2', 'get'), - actions.savedObject.get('all-savedObject-all-2', 'find'), - actions.savedObject.get('all-savedObject-all-2', 'open_point_in_time'), - actions.savedObject.get('all-savedObject-all-2', 'close_point_in_time'), - actions.savedObject.get('all-savedObject-all-2', 'create'), - actions.savedObject.get('all-savedObject-all-2', 'bulk_create'), - actions.savedObject.get('all-savedObject-all-2', 'update'), - actions.savedObject.get('all-savedObject-all-2', 'bulk_update'), - actions.savedObject.get('all-savedObject-all-2', 'delete'), - actions.savedObject.get('all-savedObject-all-2', 'share_to_space'), - actions.savedObject.get('all-savedObject-read-1', 'bulk_get'), - actions.savedObject.get('all-savedObject-read-1', 'get'), - actions.savedObject.get('all-savedObject-read-1', 'find'), - actions.savedObject.get('all-savedObject-read-1', 'open_point_in_time'), - actions.savedObject.get('all-savedObject-read-1', 'close_point_in_time'), - actions.savedObject.get('all-savedObject-read-2', 'bulk_get'), - actions.savedObject.get('all-savedObject-read-2', 'get'), - actions.savedObject.get('all-savedObject-read-2', 'find'), - actions.savedObject.get('all-savedObject-read-2', 'open_point_in_time'), - actions.savedObject.get('all-savedObject-read-2', 'close_point_in_time'), - actions.ui.get('foo', 'all-ui-1'), - actions.ui.get('foo', 'all-ui-2'), - actions.ui.get('catalogue', 'read-catalogue-1'), - actions.ui.get('catalogue', 'read-catalogue-2'), - actions.ui.get('management', 'read-management', 'read-management-1'), - actions.ui.get('management', 'read-management', 'read-management-2'), - actions.savedObject.get('read-savedObject-all-1', 'bulk_get'), - actions.savedObject.get('read-savedObject-all-1', 'get'), - actions.savedObject.get('read-savedObject-all-1', 'find'), - actions.savedObject.get('read-savedObject-all-1', 'open_point_in_time'), - actions.savedObject.get('read-savedObject-all-1', 'close_point_in_time'), - actions.savedObject.get('read-savedObject-all-1', 'create'), - actions.savedObject.get('read-savedObject-all-1', 'bulk_create'), - actions.savedObject.get('read-savedObject-all-1', 'update'), - actions.savedObject.get('read-savedObject-all-1', 'bulk_update'), - actions.savedObject.get('read-savedObject-all-1', 'delete'), - actions.savedObject.get('read-savedObject-all-1', 'share_to_space'), - actions.savedObject.get('read-savedObject-all-2', 'bulk_get'), - actions.savedObject.get('read-savedObject-all-2', 'get'), - actions.savedObject.get('read-savedObject-all-2', 'find'), - actions.savedObject.get('read-savedObject-all-2', 'open_point_in_time'), - actions.savedObject.get('read-savedObject-all-2', 'close_point_in_time'), - actions.savedObject.get('read-savedObject-all-2', 'create'), - actions.savedObject.get('read-savedObject-all-2', 'bulk_create'), - actions.savedObject.get('read-savedObject-all-2', 'update'), - actions.savedObject.get('read-savedObject-all-2', 'bulk_update'), - actions.savedObject.get('read-savedObject-all-2', 'delete'), - actions.savedObject.get('read-savedObject-all-2', 'share_to_space'), - actions.savedObject.get('read-savedObject-read-1', 'bulk_get'), - actions.savedObject.get('read-savedObject-read-1', 'get'), - actions.savedObject.get('read-savedObject-read-1', 'find'), - actions.savedObject.get('read-savedObject-read-1', 'open_point_in_time'), - actions.savedObject.get('read-savedObject-read-1', 'close_point_in_time'), - actions.savedObject.get('read-savedObject-read-2', 'bulk_get'), - actions.savedObject.get('read-savedObject-read-2', 'get'), - actions.savedObject.get('read-savedObject-read-2', 'find'), - actions.savedObject.get('read-savedObject-read-2', 'open_point_in_time'), - actions.savedObject.get('read-savedObject-read-2', 'close_point_in_time'), - actions.ui.get('foo', 'read-ui-1'), - actions.ui.get('foo', 'read-ui-2'), - ]); - }); - - test('actions defined in a feature privilege with name `read` are included in `read`', () => { - const features: KibanaFeature[] = [ - new KibanaFeature({ - id: 'foo', - name: 'Foo KibanaFeature', - app: [], - category: { id: 'foo', label: 'foo' }, - catalogue: ['ignore-me-1', 'ignore-me-2'], - management: { - foo: ['ignore-me-1', 'ignore-me-2'], - }, - privileges: { - all: { - management: { - 'ignore-me': ['ignore-me-1', 'ignore-me-2'], - }, - catalogue: ['ignore-me-1', 'ignore-me-2'], - savedObject: { - all: ['ignore-me-1', 'ignore-me-2'], - read: ['ignore-me-1', 'ignore-me-2'], - }, - ui: ['ignore-me-1', 'ignore-me-2'], + }), + ]; + + const mockFeaturesPlugin = { + getKibanaFeatures: jest.fn().mockReturnValue(features), + }; + const mockLicenseService = { + getFeatures: jest.fn().mockReturnValue({ allowSubFeaturePrivileges: true }), + getType: jest.fn().mockReturnValue('basic'), + }; + const privileges = privilegesFactory( + actions, + mockFeaturesPlugin as any, + mockLicenseService + ); + + const actual = privileges.get(); + expect(actual).toHaveProperty(`${group}.all`, [ + actions.login, + actions.version, + ...(expectDecryptedTelemetry ? [actions.api.get('decryptedTelemetry')] : []), + ...(expectGetFeatures ? [actions.api.get('features')] : []), + ...(expectManageSpaces + ? [ + actions.space.manage, + actions.ui.get('spaces', 'manage'), + actions.ui.get('management', 'kibana', 'spaces'), + actions.ui.get('catalogue', 'spaces'), + ] + : []), + ...(expectEnterpriseSearch ? [actions.ui.get('enterpriseSearch', 'all')] : []), + actions.ui.get('catalogue', 'all-catalogue-1'), + actions.ui.get('catalogue', 'all-catalogue-2'), + actions.ui.get('management', 'all-management', 'all-management-1'), + actions.ui.get('management', 'all-management', 'all-management-2'), + actions.savedObject.get('all-savedObject-all-1', 'bulk_get'), + actions.savedObject.get('all-savedObject-all-1', 'get'), + actions.savedObject.get('all-savedObject-all-1', 'find'), + actions.savedObject.get('all-savedObject-all-1', 'open_point_in_time'), + actions.savedObject.get('all-savedObject-all-1', 'close_point_in_time'), + actions.savedObject.get('all-savedObject-all-1', 'create'), + actions.savedObject.get('all-savedObject-all-1', 'bulk_create'), + actions.savedObject.get('all-savedObject-all-1', 'update'), + actions.savedObject.get('all-savedObject-all-1', 'bulk_update'), + actions.savedObject.get('all-savedObject-all-1', 'delete'), + actions.savedObject.get('all-savedObject-all-1', 'share_to_space'), + actions.savedObject.get('all-savedObject-all-2', 'bulk_get'), + actions.savedObject.get('all-savedObject-all-2', 'get'), + actions.savedObject.get('all-savedObject-all-2', 'find'), + actions.savedObject.get('all-savedObject-all-2', 'open_point_in_time'), + actions.savedObject.get('all-savedObject-all-2', 'close_point_in_time'), + actions.savedObject.get('all-savedObject-all-2', 'create'), + actions.savedObject.get('all-savedObject-all-2', 'bulk_create'), + actions.savedObject.get('all-savedObject-all-2', 'update'), + actions.savedObject.get('all-savedObject-all-2', 'bulk_update'), + actions.savedObject.get('all-savedObject-all-2', 'delete'), + actions.savedObject.get('all-savedObject-all-2', 'share_to_space'), + actions.savedObject.get('all-savedObject-read-1', 'bulk_get'), + actions.savedObject.get('all-savedObject-read-1', 'get'), + actions.savedObject.get('all-savedObject-read-1', 'find'), + actions.savedObject.get('all-savedObject-read-1', 'open_point_in_time'), + actions.savedObject.get('all-savedObject-read-1', 'close_point_in_time'), + actions.savedObject.get('all-savedObject-read-2', 'bulk_get'), + actions.savedObject.get('all-savedObject-read-2', 'get'), + actions.savedObject.get('all-savedObject-read-2', 'find'), + actions.savedObject.get('all-savedObject-read-2', 'open_point_in_time'), + actions.savedObject.get('all-savedObject-read-2', 'close_point_in_time'), + actions.ui.get('foo', 'all-ui-1'), + actions.ui.get('foo', 'all-ui-2'), + actions.ui.get('catalogue', 'read-catalogue-1'), + actions.ui.get('catalogue', 'read-catalogue-2'), + actions.ui.get('management', 'read-management', 'read-management-1'), + actions.ui.get('management', 'read-management', 'read-management-2'), + actions.savedObject.get('read-savedObject-all-1', 'bulk_get'), + actions.savedObject.get('read-savedObject-all-1', 'get'), + actions.savedObject.get('read-savedObject-all-1', 'find'), + actions.savedObject.get('read-savedObject-all-1', 'open_point_in_time'), + actions.savedObject.get('read-savedObject-all-1', 'close_point_in_time'), + actions.savedObject.get('read-savedObject-all-1', 'create'), + actions.savedObject.get('read-savedObject-all-1', 'bulk_create'), + actions.savedObject.get('read-savedObject-all-1', 'update'), + actions.savedObject.get('read-savedObject-all-1', 'bulk_update'), + actions.savedObject.get('read-savedObject-all-1', 'delete'), + actions.savedObject.get('read-savedObject-all-1', 'share_to_space'), + actions.savedObject.get('read-savedObject-all-2', 'bulk_get'), + actions.savedObject.get('read-savedObject-all-2', 'get'), + actions.savedObject.get('read-savedObject-all-2', 'find'), + actions.savedObject.get('read-savedObject-all-2', 'open_point_in_time'), + actions.savedObject.get('read-savedObject-all-2', 'close_point_in_time'), + actions.savedObject.get('read-savedObject-all-2', 'create'), + actions.savedObject.get('read-savedObject-all-2', 'bulk_create'), + actions.savedObject.get('read-savedObject-all-2', 'update'), + actions.savedObject.get('read-savedObject-all-2', 'bulk_update'), + actions.savedObject.get('read-savedObject-all-2', 'delete'), + actions.savedObject.get('read-savedObject-all-2', 'share_to_space'), + actions.savedObject.get('read-savedObject-read-1', 'bulk_get'), + actions.savedObject.get('read-savedObject-read-1', 'get'), + actions.savedObject.get('read-savedObject-read-1', 'find'), + actions.savedObject.get('read-savedObject-read-1', 'open_point_in_time'), + actions.savedObject.get('read-savedObject-read-1', 'close_point_in_time'), + actions.savedObject.get('read-savedObject-read-2', 'bulk_get'), + actions.savedObject.get('read-savedObject-read-2', 'get'), + actions.savedObject.get('read-savedObject-read-2', 'find'), + actions.savedObject.get('read-savedObject-read-2', 'open_point_in_time'), + actions.savedObject.get('read-savedObject-read-2', 'close_point_in_time'), + actions.ui.get('foo', 'read-ui-1'), + actions.ui.get('foo', 'read-ui-2'), + ]); + }); + + test('actions defined in a feature privilege with name `read` are included in `read`', () => { + const features: KibanaFeature[] = [ + new KibanaFeature({ + id: 'foo', + name: 'Foo KibanaFeature', + app: [], + category: { id: 'foo', label: 'foo' }, + catalogue: ['ignore-me-1', 'ignore-me-2'], + management: { + foo: ['ignore-me-1', 'ignore-me-2'], }, - read: { - management: { - 'read-management': ['read-management-1', 'read-management-2'], + privileges: { + all: { + management: { + 'ignore-me': ['ignore-me-1', 'ignore-me-2'], + }, + catalogue: ['ignore-me-1', 'ignore-me-2'], + savedObject: { + all: ['ignore-me-1', 'ignore-me-2'], + read: ['ignore-me-1', 'ignore-me-2'], + }, + ui: ['ignore-me-1', 'ignore-me-2'], }, - catalogue: ['read-catalogue-1', 'read-catalogue-2'], - savedObject: { - all: ['read-savedObject-all-1', 'read-savedObject-all-2'], - read: ['read-savedObject-read-1', 'read-savedObject-read-2'], + read: { + management: { + 'read-management': ['read-management-1', 'read-management-2'], + }, + catalogue: ['read-catalogue-1', 'read-catalogue-2'], + savedObject: { + all: ['read-savedObject-all-1', 'read-savedObject-all-2'], + read: ['read-savedObject-read-1', 'read-savedObject-read-2'], + }, + ui: ['read-ui-1', 'read-ui-2'], }, - ui: ['read-ui-1', 'read-ui-2'], }, - }, - }), - ]; - - const mockFeaturesPlugin = { - getKibanaFeatures: jest.fn().mockReturnValue(features), - }; - const mockLicenseService = { - getFeatures: jest.fn().mockReturnValue({ allowSubFeaturePrivileges: true }), - getType: jest.fn().mockReturnValue('basic'), - }; - const privileges = privilegesFactory(actions, mockFeaturesPlugin as any, mockLicenseService); - - const actual = privileges.get(); - expect(actual).toHaveProperty(`${group}.read`, [ - actions.login, - actions.version, - actions.ui.get('catalogue', 'read-catalogue-1'), - actions.ui.get('catalogue', 'read-catalogue-2'), - actions.ui.get('management', 'read-management', 'read-management-1'), - actions.ui.get('management', 'read-management', 'read-management-2'), - actions.savedObject.get('read-savedObject-all-1', 'bulk_get'), - actions.savedObject.get('read-savedObject-all-1', 'get'), - actions.savedObject.get('read-savedObject-all-1', 'find'), - actions.savedObject.get('read-savedObject-all-1', 'open_point_in_time'), - actions.savedObject.get('read-savedObject-all-1', 'close_point_in_time'), - actions.savedObject.get('read-savedObject-all-1', 'create'), - actions.savedObject.get('read-savedObject-all-1', 'bulk_create'), - actions.savedObject.get('read-savedObject-all-1', 'update'), - actions.savedObject.get('read-savedObject-all-1', 'bulk_update'), - actions.savedObject.get('read-savedObject-all-1', 'delete'), - actions.savedObject.get('read-savedObject-all-1', 'share_to_space'), - actions.savedObject.get('read-savedObject-all-2', 'bulk_get'), - actions.savedObject.get('read-savedObject-all-2', 'get'), - actions.savedObject.get('read-savedObject-all-2', 'find'), - actions.savedObject.get('read-savedObject-all-2', 'open_point_in_time'), - actions.savedObject.get('read-savedObject-all-2', 'close_point_in_time'), - actions.savedObject.get('read-savedObject-all-2', 'create'), - actions.savedObject.get('read-savedObject-all-2', 'bulk_create'), - actions.savedObject.get('read-savedObject-all-2', 'update'), - actions.savedObject.get('read-savedObject-all-2', 'bulk_update'), - actions.savedObject.get('read-savedObject-all-2', 'delete'), - actions.savedObject.get('read-savedObject-all-2', 'share_to_space'), - actions.savedObject.get('read-savedObject-read-1', 'bulk_get'), - actions.savedObject.get('read-savedObject-read-1', 'get'), - actions.savedObject.get('read-savedObject-read-1', 'find'), - actions.savedObject.get('read-savedObject-read-1', 'open_point_in_time'), - actions.savedObject.get('read-savedObject-read-1', 'close_point_in_time'), - actions.savedObject.get('read-savedObject-read-2', 'bulk_get'), - actions.savedObject.get('read-savedObject-read-2', 'get'), - actions.savedObject.get('read-savedObject-read-2', 'find'), - actions.savedObject.get('read-savedObject-read-2', 'open_point_in_time'), - actions.savedObject.get('read-savedObject-read-2', 'close_point_in_time'), - actions.ui.get('foo', 'read-ui-1'), - actions.ui.get('foo', 'read-ui-2'), - ]); - }); - - test('actions defined in a reserved privilege are not included in `all` or `read`', () => { - const features: KibanaFeature[] = [ - new KibanaFeature({ - id: 'foo', - name: 'Foo KibanaFeature', - app: [], - category: { id: 'foo', label: 'foo' }, - catalogue: ['ignore-me-1', 'ignore-me-2'], - management: { - foo: ['ignore-me-1', 'ignore-me-2'], - }, - privileges: null, - reserved: { - privileges: [ - { - id: 'reserved', - privilege: { - savedObject: { - all: ['ignore-me-1', 'ignore-me-2'], - read: ['ignore-me-1', 'ignore-me-2'], + }), + ]; + + const mockFeaturesPlugin = { + getKibanaFeatures: jest.fn().mockReturnValue(features), + }; + const mockLicenseService = { + getFeatures: jest.fn().mockReturnValue({ allowSubFeaturePrivileges: true }), + getType: jest.fn().mockReturnValue('basic'), + }; + const privileges = privilegesFactory( + actions, + mockFeaturesPlugin as any, + mockLicenseService + ); + + const actual = privileges.get(); + expect(actual).toHaveProperty(`${group}.read`, [ + actions.login, + actions.version, + ...(expectDecryptedTelemetry ? [actions.api.get('decryptedTelemetry')] : []), + actions.ui.get('catalogue', 'read-catalogue-1'), + actions.ui.get('catalogue', 'read-catalogue-2'), + actions.ui.get('management', 'read-management', 'read-management-1'), + actions.ui.get('management', 'read-management', 'read-management-2'), + actions.savedObject.get('read-savedObject-all-1', 'bulk_get'), + actions.savedObject.get('read-savedObject-all-1', 'get'), + actions.savedObject.get('read-savedObject-all-1', 'find'), + actions.savedObject.get('read-savedObject-all-1', 'open_point_in_time'), + actions.savedObject.get('read-savedObject-all-1', 'close_point_in_time'), + actions.savedObject.get('read-savedObject-all-1', 'create'), + actions.savedObject.get('read-savedObject-all-1', 'bulk_create'), + actions.savedObject.get('read-savedObject-all-1', 'update'), + actions.savedObject.get('read-savedObject-all-1', 'bulk_update'), + actions.savedObject.get('read-savedObject-all-1', 'delete'), + actions.savedObject.get('read-savedObject-all-1', 'share_to_space'), + actions.savedObject.get('read-savedObject-all-2', 'bulk_get'), + actions.savedObject.get('read-savedObject-all-2', 'get'), + actions.savedObject.get('read-savedObject-all-2', 'find'), + actions.savedObject.get('read-savedObject-all-2', 'open_point_in_time'), + actions.savedObject.get('read-savedObject-all-2', 'close_point_in_time'), + actions.savedObject.get('read-savedObject-all-2', 'create'), + actions.savedObject.get('read-savedObject-all-2', 'bulk_create'), + actions.savedObject.get('read-savedObject-all-2', 'update'), + actions.savedObject.get('read-savedObject-all-2', 'bulk_update'), + actions.savedObject.get('read-savedObject-all-2', 'delete'), + actions.savedObject.get('read-savedObject-all-2', 'share_to_space'), + actions.savedObject.get('read-savedObject-read-1', 'bulk_get'), + actions.savedObject.get('read-savedObject-read-1', 'get'), + actions.savedObject.get('read-savedObject-read-1', 'find'), + actions.savedObject.get('read-savedObject-read-1', 'open_point_in_time'), + actions.savedObject.get('read-savedObject-read-1', 'close_point_in_time'), + actions.savedObject.get('read-savedObject-read-2', 'bulk_get'), + actions.savedObject.get('read-savedObject-read-2', 'get'), + actions.savedObject.get('read-savedObject-read-2', 'find'), + actions.savedObject.get('read-savedObject-read-2', 'open_point_in_time'), + actions.savedObject.get('read-savedObject-read-2', 'close_point_in_time'), + actions.ui.get('foo', 'read-ui-1'), + actions.ui.get('foo', 'read-ui-2'), + ]); + }); + + test('actions defined in a reserved privilege are not included in `all` or `read`', () => { + const features: KibanaFeature[] = [ + new KibanaFeature({ + id: 'foo', + name: 'Foo KibanaFeature', + app: [], + category: { id: 'foo', label: 'foo' }, + catalogue: ['ignore-me-1', 'ignore-me-2'], + management: { + foo: ['ignore-me-1', 'ignore-me-2'], + }, + privileges: null, + reserved: { + privileges: [ + { + id: 'reserved', + privilege: { + savedObject: { + all: ['ignore-me-1', 'ignore-me-2'], + read: ['ignore-me-1', 'ignore-me-2'], + }, + ui: ['ignore-me-1'], }, - ui: ['ignore-me-1'], }, - }, - ], - description: '', - }, - }), - ]; - - const mockFeaturesPlugin = { - getKibanaFeatures: jest.fn().mockReturnValue(features), - }; - const mockLicenseService = { - getFeatures: jest.fn().mockReturnValue({ allowSubFeaturePrivileges: true }), - getType: jest.fn().mockReturnValue('basic'), - }; - const privileges = privilegesFactory(actions, mockFeaturesPlugin as any, mockLicenseService); - - const actual = privileges.get(); - expect(actual).toHaveProperty(`${group}.all`, [ - actions.login, - actions.version, - ...(expectGetFeatures ? [actions.api.get('features')] : []), - ...(expectManageSpaces - ? [ - actions.space.manage, - actions.ui.get('spaces', 'manage'), - actions.ui.get('management', 'kibana', 'spaces'), - actions.ui.get('catalogue', 'spaces'), - ] - : []), - ...(expectEnterpriseSearch ? [actions.ui.get('enterpriseSearch', 'all')] : []), - ]); - expect(actual).toHaveProperty(`${group}.read`, [actions.login, actions.version]); - }); - - test('actions defined in a feature with excludeFromBasePrivileges are not included in `all` or `read', () => { - const features: KibanaFeature[] = [ - new KibanaFeature({ - id: 'foo', - name: 'Foo KibanaFeature', - excludeFromBasePrivileges: true, - app: [], - category: { id: 'foo', label: 'foo' }, - catalogue: ['ignore-me-1', 'ignore-me-2'], - management: { - foo: ['ignore-me-1', 'ignore-me-2'], - }, - privileges: { - all: { - management: { - 'all-management': ['all-management-1'], - }, - catalogue: ['all-catalogue-1'], - savedObject: { - all: ['all-savedObject-all-1'], - read: ['all-savedObject-read-1'], - }, - ui: ['all-ui-1'], + ], + description: '', }, - read: { - management: { - 'read-management': ['read-management-1'], - }, - catalogue: ['read-catalogue-1'], - savedObject: { - all: ['read-savedObject-all-1'], - read: ['read-savedObject-read-1'], - }, - ui: ['read-ui-1'], + }), + ]; + + const mockFeaturesPlugin = { + getKibanaFeatures: jest.fn().mockReturnValue(features), + }; + const mockLicenseService = { + getFeatures: jest.fn().mockReturnValue({ allowSubFeaturePrivileges: true }), + getType: jest.fn().mockReturnValue('basic'), + }; + const privileges = privilegesFactory( + actions, + mockFeaturesPlugin as any, + mockLicenseService + ); + + const actual = privileges.get(); + expect(actual).toHaveProperty(`${group}.all`, [ + actions.login, + actions.version, + ...(expectDecryptedTelemetry ? [actions.api.get('decryptedTelemetry')] : []), + ...(expectGetFeatures ? [actions.api.get('features')] : []), + ...(expectManageSpaces + ? [ + actions.space.manage, + actions.ui.get('spaces', 'manage'), + actions.ui.get('management', 'kibana', 'spaces'), + actions.ui.get('catalogue', 'spaces'), + ] + : []), + ...(expectEnterpriseSearch ? [actions.ui.get('enterpriseSearch', 'all')] : []), + ]); + expect(actual).toHaveProperty(`${group}.read`, [ + actions.login, + actions.version, + ...(expectDecryptedTelemetry ? [actions.api.get('decryptedTelemetry')] : []), + ]); + }); + + test('actions defined in a feature with excludeFromBasePrivileges are not included in `all` or `read', () => { + const features: KibanaFeature[] = [ + new KibanaFeature({ + id: 'foo', + name: 'Foo KibanaFeature', + excludeFromBasePrivileges: true, + app: [], + category: { id: 'foo', label: 'foo' }, + catalogue: ['ignore-me-1', 'ignore-me-2'], + management: { + foo: ['ignore-me-1', 'ignore-me-2'], }, - }, - }), - ]; - - const mockFeaturesPlugin = { - getKibanaFeatures: jest.fn().mockReturnValue(features), - }; - const mockLicenseService = { - getFeatures: jest.fn().mockReturnValue({ allowSubFeaturePrivileges: true }), - getType: jest.fn().mockReturnValue('basic'), - }; - const privileges = privilegesFactory(actions, mockFeaturesPlugin as any, mockLicenseService); - - const actual = privileges.get(); - expect(actual).toHaveProperty(`${group}.all`, [ - actions.login, - actions.version, - ...(expectGetFeatures ? [actions.api.get('features')] : []), - ...(expectManageSpaces - ? [ - actions.space.manage, - actions.ui.get('spaces', 'manage'), - actions.ui.get('management', 'kibana', 'spaces'), - actions.ui.get('catalogue', 'spaces'), - ] - : []), - ...(expectEnterpriseSearch ? [actions.ui.get('enterpriseSearch', 'all')] : []), - ]); - expect(actual).toHaveProperty(`${group}.read`, [actions.login, actions.version]); - }); - - test('actions defined in an individual feature privilege with excludeFromBasePrivileges are not included in `all` or `read`', () => { - const features: KibanaFeature[] = [ - new KibanaFeature({ - id: 'foo', - name: 'Foo KibanaFeature', - app: [], - category: { id: 'foo', label: 'foo' }, - catalogue: ['ignore-me-1', 'ignore-me-2'], - management: { - foo: ['ignore-me-1', 'ignore-me-2'], - }, - privileges: { - all: { - excludeFromBasePrivileges: true, - management: { - 'all-management': ['all-management-1'], + privileges: { + all: { + management: { + 'all-management': ['all-management-1'], + }, + catalogue: ['all-catalogue-1'], + savedObject: { + all: ['all-savedObject-all-1'], + read: ['all-savedObject-read-1'], + }, + ui: ['all-ui-1'], }, - catalogue: ['all-catalogue-1'], - savedObject: { - all: ['all-savedObject-all-1'], - read: ['all-savedObject-read-1'], + read: { + management: { + 'read-management': ['read-management-1'], + }, + catalogue: ['read-catalogue-1'], + savedObject: { + all: ['read-savedObject-all-1'], + read: ['read-savedObject-read-1'], + }, + ui: ['read-ui-1'], }, - ui: ['all-ui-1'], }, - read: { - excludeFromBasePrivileges: true, - management: { - 'read-management': ['read-management-1'], + }), + ]; + + const mockFeaturesPlugin = { + getKibanaFeatures: jest.fn().mockReturnValue(features), + }; + const mockLicenseService = { + getFeatures: jest.fn().mockReturnValue({ allowSubFeaturePrivileges: true }), + getType: jest.fn().mockReturnValue('basic'), + }; + const privileges = privilegesFactory( + actions, + mockFeaturesPlugin as any, + mockLicenseService + ); + + const actual = privileges.get(); + expect(actual).toHaveProperty(`${group}.all`, [ + actions.login, + actions.version, + ...(expectDecryptedTelemetry ? [actions.api.get('decryptedTelemetry')] : []), + ...(expectGetFeatures ? [actions.api.get('features')] : []), + ...(expectManageSpaces + ? [ + actions.space.manage, + actions.ui.get('spaces', 'manage'), + actions.ui.get('management', 'kibana', 'spaces'), + actions.ui.get('catalogue', 'spaces'), + ] + : []), + ...(expectEnterpriseSearch ? [actions.ui.get('enterpriseSearch', 'all')] : []), + ]); + expect(actual).toHaveProperty(`${group}.read`, [ + actions.login, + actions.version, + ...(expectDecryptedTelemetry ? [actions.api.get('decryptedTelemetry')] : []), + ]); + }); + + test('actions defined in an individual feature privilege with excludeFromBasePrivileges are not included in `all` or `read`', () => { + const features: KibanaFeature[] = [ + new KibanaFeature({ + id: 'foo', + name: 'Foo KibanaFeature', + app: [], + category: { id: 'foo', label: 'foo' }, + catalogue: ['ignore-me-1', 'ignore-me-2'], + management: { + foo: ['ignore-me-1', 'ignore-me-2'], + }, + privileges: { + all: { + excludeFromBasePrivileges: true, + management: { + 'all-management': ['all-management-1'], + }, + catalogue: ['all-catalogue-1'], + savedObject: { + all: ['all-savedObject-all-1'], + read: ['all-savedObject-read-1'], + }, + ui: ['all-ui-1'], }, - catalogue: ['read-catalogue-1'], - savedObject: { - all: ['read-savedObject-all-1'], - read: ['read-savedObject-read-1'], + read: { + excludeFromBasePrivileges: true, + management: { + 'read-management': ['read-management-1'], + }, + catalogue: ['read-catalogue-1'], + savedObject: { + all: ['read-savedObject-all-1'], + read: ['read-savedObject-read-1'], + }, + ui: ['read-ui-1'], }, - ui: ['read-ui-1'], }, - }, - }), - ]; - - const mockFeaturesPlugin = { - getKibanaFeatures: jest.fn().mockReturnValue(features), - }; - const mockLicenseService = { - getFeatures: jest.fn().mockReturnValue({ allowSubFeaturePrivileges: true }), - getType: jest.fn().mockReturnValue('basic'), - }; - const privileges = privilegesFactory(actions, mockFeaturesPlugin as any, mockLicenseService); - - const actual = privileges.get(); - expect(actual).toHaveProperty(`${group}.all`, [ - actions.login, - actions.version, - ...(expectGetFeatures ? [actions.api.get('features')] : []), - ...(expectManageSpaces - ? [ - actions.space.manage, - actions.ui.get('spaces', 'manage'), - actions.ui.get('management', 'kibana', 'spaces'), - actions.ui.get('catalogue', 'spaces'), - ] - : []), - ...(expectEnterpriseSearch ? [actions.ui.get('enterpriseSearch', 'all')] : []), - ]); - expect(actual).toHaveProperty(`${group}.read`, [actions.login, actions.version]); + }), + ]; + + const mockFeaturesPlugin = { + getKibanaFeatures: jest.fn().mockReturnValue(features), + }; + const mockLicenseService = { + getFeatures: jest.fn().mockReturnValue({ allowSubFeaturePrivileges: true }), + getType: jest.fn().mockReturnValue('basic'), + }; + const privileges = privilegesFactory( + actions, + mockFeaturesPlugin as any, + mockLicenseService + ); + + const actual = privileges.get(); + expect(actual).toHaveProperty(`${group}.all`, [ + actions.login, + actions.version, + ...(expectDecryptedTelemetry ? [actions.api.get('decryptedTelemetry')] : []), + ...(expectGetFeatures ? [actions.api.get('features')] : []), + ...(expectManageSpaces + ? [ + actions.space.manage, + actions.ui.get('spaces', 'manage'), + actions.ui.get('management', 'kibana', 'spaces'), + actions.ui.get('catalogue', 'spaces'), + ] + : []), + ...(expectEnterpriseSearch ? [actions.ui.get('enterpriseSearch', 'all')] : []), + ]); + expect(actual).toHaveProperty(`${group}.read`, [ + actions.login, + actions.version, + ...(expectDecryptedTelemetry ? [actions.api.get('decryptedTelemetry')] : []), + ]); + }); }); - }); -}); + } +); describe('reserved', () => { test('actions defined at the feature do not cascade to the privileges', () => { @@ -911,6 +958,7 @@ describe('subFeatures', () => { expect(actual).toHaveProperty('global.all', [ actions.login, actions.version, + actions.api.get('decryptedTelemetry'), actions.api.get('features'), actions.space.manage, actions.ui.get('spaces', 'manage'), @@ -922,6 +970,7 @@ describe('subFeatures', () => { expect(actual).toHaveProperty('global.read', [ actions.login, actions.version, + actions.api.get('decryptedTelemetry'), actions.ui.get('foo', 'foo'), ]); @@ -1080,6 +1129,7 @@ describe('subFeatures', () => { expect(actual).toHaveProperty('global.all', [ actions.login, actions.version, + actions.api.get('decryptedTelemetry'), actions.api.get('features'), actions.space.manage, actions.ui.get('spaces', 'manage'), @@ -1108,6 +1158,7 @@ describe('subFeatures', () => { expect(actual).toHaveProperty('global.read', [ actions.login, actions.version, + actions.api.get('decryptedTelemetry'), actions.savedObject.get('all-sub-feature-type', 'bulk_get'), actions.savedObject.get('all-sub-feature-type', 'get'), actions.savedObject.get('all-sub-feature-type', 'find'), @@ -1316,6 +1367,7 @@ describe('subFeatures', () => { expect(actual).toHaveProperty('global.all', [ actions.login, actions.version, + actions.api.get('decryptedTelemetry'), actions.api.get('features'), actions.space.manage, actions.ui.get('spaces', 'manage'), @@ -1323,7 +1375,11 @@ describe('subFeatures', () => { actions.ui.get('catalogue', 'spaces'), actions.ui.get('enterpriseSearch', 'all'), ]); - expect(actual).toHaveProperty('global.read', [actions.login, actions.version]); + expect(actual).toHaveProperty('global.read', [ + actions.login, + actions.version, + actions.api.get('decryptedTelemetry'), + ]); expect(actual).toHaveProperty('space.all', [actions.login, actions.version]); expect(actual).toHaveProperty('space.read', [actions.login, actions.version]); @@ -1455,6 +1511,7 @@ describe('subFeatures', () => { expect(actual).toHaveProperty('global.all', [ actions.login, actions.version, + actions.api.get('decryptedTelemetry'), actions.api.get('features'), actions.space.manage, actions.ui.get('spaces', 'manage'), @@ -1483,6 +1540,7 @@ describe('subFeatures', () => { expect(actual).toHaveProperty('global.read', [ actions.login, actions.version, + actions.api.get('decryptedTelemetry'), actions.ui.get('foo', 'foo'), ]); @@ -1640,6 +1698,7 @@ describe('subFeatures', () => { expect(actual).toHaveProperty('global.all', [ actions.login, actions.version, + actions.api.get('decryptedTelemetry'), actions.api.get('features'), actions.space.manage, actions.ui.get('spaces', 'manage'), @@ -1647,7 +1706,11 @@ describe('subFeatures', () => { actions.ui.get('catalogue', 'spaces'), actions.ui.get('enterpriseSearch', 'all'), ]); - expect(actual).toHaveProperty('global.read', [actions.login, actions.version]); + expect(actual).toHaveProperty('global.read', [ + actions.login, + actions.version, + actions.api.get('decryptedTelemetry'), + ]); expect(actual).toHaveProperty('space.all', [actions.login, actions.version]); expect(actual).toHaveProperty('space.read', [actions.login, actions.version]); @@ -1768,6 +1831,7 @@ describe('subFeatures', () => { expect(actual).toHaveProperty('global.all', [ actions.login, actions.version, + actions.api.get('decryptedTelemetry'), actions.api.get('features'), actions.space.manage, actions.ui.get('spaces', 'manage'), @@ -1796,6 +1860,7 @@ describe('subFeatures', () => { expect(actual).toHaveProperty('global.read', [ actions.login, actions.version, + actions.api.get('decryptedTelemetry'), actions.savedObject.get('all-sub-feature-type', 'bulk_get'), actions.savedObject.get('all-sub-feature-type', 'get'), actions.savedObject.get('all-sub-feature-type', 'find'), @@ -2002,6 +2067,7 @@ describe('subFeatures', () => { expect(actual).toHaveProperty('global.all', [ actions.login, actions.version, + actions.api.get('decryptedTelemetry'), actions.api.get('features'), actions.space.manage, actions.ui.get('spaces', 'manage'), @@ -2030,6 +2096,7 @@ describe('subFeatures', () => { expect(actual).toHaveProperty('global.read', [ actions.login, actions.version, + actions.api.get('decryptedTelemetry'), actions.savedObject.get('all-sub-feature-type', 'bulk_get'), actions.savedObject.get('all-sub-feature-type', 'get'), actions.savedObject.get('all-sub-feature-type', 'find'), @@ -2270,6 +2337,7 @@ describe('subFeatures', () => { expect(actual).toHaveProperty('global.all', [ actions.login, actions.version, + actions.api.get('decryptedTelemetry'), actions.api.get('features'), actions.space.manage, actions.ui.get('spaces', 'manage'), @@ -2315,6 +2383,7 @@ describe('subFeatures', () => { expect(actual).toHaveProperty('global.read', [ actions.login, actions.version, + actions.api.get('decryptedTelemetry'), actions.savedObject.get('all-sub-feature-type', 'bulk_get'), actions.savedObject.get('all-sub-feature-type', 'get'), actions.savedObject.get('all-sub-feature-type', 'find'), diff --git a/x-pack/plugins/security/server/authorization/privileges/privileges.ts b/x-pack/plugins/security/server/authorization/privileges/privileges.ts index 28d3ddefc62b5..1826b853ce668 100644 --- a/x-pack/plugins/security/server/authorization/privileges/privileges.ts +++ b/x-pack/plugins/security/server/authorization/privileges/privileges.ts @@ -105,6 +105,7 @@ export function privilegesFactory( all: [ actions.login, actions.version, + actions.api.get('decryptedTelemetry'), actions.api.get('features'), actions.space.manage, actions.ui.get('spaces', 'manage'), @@ -113,7 +114,12 @@ export function privilegesFactory( actions.ui.get('enterpriseSearch', 'all'), ...allActions, ], - read: [actions.login, actions.version, ...readActions], + read: [ + actions.login, + actions.version, + actions.api.get('decryptedTelemetry'), + ...readActions, + ], }, space: { all: [actions.login, actions.version, ...allActions],