mirror of
https://github.com/elastic/kibana.git
synced 2025-04-23 09:19:04 -04:00
[7.x] Role Management - use ES Builtin Privilege API to drive… (#40752)
* use ES builtin privileges API for role management * Exclude 'none' from privilege lists * additional cleanup
This commit is contained in:
parent
d74f56a199
commit
089d92dd46
23 changed files with 231 additions and 217 deletions
|
@ -0,0 +1,10 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
export interface BuiltinESPrivileges {
|
||||
cluster: string[];
|
||||
index: string[];
|
||||
}
|
|
@ -10,3 +10,4 @@ export { RawKibanaPrivileges, RawKibanaFeaturePrivileges } from './raw_kibana_pr
|
|||
export { KibanaPrivileges } from './kibana_privileges';
|
||||
export { User, EditUser, getUserDisplayName } from './user';
|
||||
export { AuthenticatedUser, canUserChangePassword } from './authenticated_user';
|
||||
export { BuiltinESPrivileges } from './builtin_es_privileges';
|
||||
|
|
|
@ -12,6 +12,7 @@ import { initUsersApi } from './server/routes/api/v1/users';
|
|||
import { initExternalRolesApi } from './server/routes/api/external/roles';
|
||||
import { initPrivilegesApi } from './server/routes/api/external/privileges';
|
||||
import { initIndicesApi } from './server/routes/api/v1/indices';
|
||||
import { initGetBuiltinPrivilegesApi } from './server/routes/api/v1/builtin_privileges';
|
||||
import { initOverwrittenSessionView } from './server/routes/views/overwritten_session';
|
||||
import { initLoginView } from './server/routes/views/login';
|
||||
import { initLogoutView } from './server/routes/views/logout';
|
||||
|
@ -230,6 +231,7 @@ export const security = (kibana) => new kibana.Plugin({
|
|||
initExternalRolesApi(server);
|
||||
initIndicesApi(server);
|
||||
initPrivilegesApi(server);
|
||||
initGetBuiltinPrivilegesApi(server);
|
||||
initLoginView(server, xpackMainPlugin);
|
||||
initLogoutView(server);
|
||||
initLoggedOutView(server);
|
||||
|
|
|
@ -1,18 +0,0 @@
|
|||
/*
|
||||
* 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 'angular-resource';
|
||||
import { uiModules } from 'ui/modules';
|
||||
|
||||
const module = uiModules.get('security', ['ngResource']);
|
||||
module.service('ApplicationPrivileges', ($resource, chrome) => {
|
||||
const baseUrl = chrome.addBasePath('/api/security/v1/privileges');
|
||||
return $resource(baseUrl, null, {
|
||||
query: {
|
||||
isArray: false,
|
||||
}
|
||||
});
|
||||
});
|
|
@ -1,57 +0,0 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
const clusterPrivileges = [
|
||||
'all',
|
||||
'monitor',
|
||||
'manage',
|
||||
'manage_security',
|
||||
'manage_index_templates',
|
||||
'manage_pipeline',
|
||||
'manage_ingest_pipelines',
|
||||
'transport_client',
|
||||
'manage_ml',
|
||||
'monitor_ml',
|
||||
'manage_data_frame_transforms',
|
||||
'monitor_data_frame_transforms',
|
||||
'manage_watcher',
|
||||
'monitor_watcher',
|
||||
'read_ccr',
|
||||
'manage_ccr',
|
||||
'manage_ilm',
|
||||
'read_ilm',
|
||||
'monitor_rollup',
|
||||
'manage_rollup',
|
||||
'manage_token',
|
||||
'manage_saml',
|
||||
'create_snapshot',
|
||||
'manage_oidc',
|
||||
];
|
||||
const indexPrivileges = [
|
||||
'all',
|
||||
'manage',
|
||||
'monitor',
|
||||
'read',
|
||||
'index',
|
||||
'create',
|
||||
'delete',
|
||||
'write',
|
||||
'delete_index',
|
||||
'create_index',
|
||||
'view_index_metadata',
|
||||
'read_cross_cluster',
|
||||
'manage_follow_index',
|
||||
'manage_ilm',
|
||||
'manage_leader_index',
|
||||
];
|
||||
|
||||
export function getClusterPrivileges() {
|
||||
return [...clusterPrivileges];
|
||||
}
|
||||
|
||||
export function getIndexPrivileges() {
|
||||
return [...indexPrivileges];
|
||||
}
|
|
@ -65,6 +65,13 @@ const buildRawKibanaPrivileges = () => {
|
|||
return privilegesFactory(actions, xpackMainPlugin as any).get();
|
||||
};
|
||||
|
||||
const buildBuiltinESPrivileges = () => {
|
||||
return {
|
||||
cluster: ['all', 'manage', 'monitor'],
|
||||
index: ['all', 'read', 'write', 'index'],
|
||||
};
|
||||
};
|
||||
|
||||
const buildUICapabilities = (canManageSpaces = true) => {
|
||||
return {
|
||||
catalogue: {},
|
||||
|
@ -132,7 +139,8 @@ describe('<EditRolePage />', () => {
|
|||
const features: Feature[] = buildFeatures();
|
||||
const mockHttpClient = jest.fn();
|
||||
const indexPatterns: string[] = ['foo*', 'bar*'];
|
||||
const privileges: RawKibanaPrivileges = buildRawKibanaPrivileges();
|
||||
const kibanaPrivileges: RawKibanaPrivileges = buildRawKibanaPrivileges();
|
||||
const builtinESPrivileges = buildBuiltinESPrivileges();
|
||||
const spaces: Space[] = buildSpaces();
|
||||
const uiCapabilities: UICapabilities = buildUICapabilities();
|
||||
|
||||
|
@ -146,7 +154,8 @@ describe('<EditRolePage />', () => {
|
|||
features={features}
|
||||
httpClient={mockHttpClient}
|
||||
indexPatterns={indexPatterns}
|
||||
privileges={privileges}
|
||||
kibanaPrivileges={kibanaPrivileges}
|
||||
builtinESPrivileges={builtinESPrivileges}
|
||||
spaces={spaces}
|
||||
spacesEnabled={true}
|
||||
uiCapabilities={uiCapabilities}
|
||||
|
@ -180,7 +189,8 @@ describe('<EditRolePage />', () => {
|
|||
const features: Feature[] = buildFeatures();
|
||||
const mockHttpClient = jest.fn();
|
||||
const indexPatterns: string[] = ['foo*', 'bar*'];
|
||||
const privileges: RawKibanaPrivileges = buildRawKibanaPrivileges();
|
||||
const kibanaPrivileges: RawKibanaPrivileges = buildRawKibanaPrivileges();
|
||||
const builtinESPrivileges = buildBuiltinESPrivileges();
|
||||
const spaces: Space[] = buildSpaces();
|
||||
const uiCapabilities: UICapabilities = buildUICapabilities();
|
||||
|
||||
|
@ -194,7 +204,8 @@ describe('<EditRolePage />', () => {
|
|||
features={features}
|
||||
httpClient={mockHttpClient}
|
||||
indexPatterns={indexPatterns}
|
||||
privileges={privileges}
|
||||
kibanaPrivileges={kibanaPrivileges}
|
||||
builtinESPrivileges={builtinESPrivileges}
|
||||
spaces={spaces}
|
||||
spacesEnabled={true}
|
||||
uiCapabilities={uiCapabilities}
|
||||
|
@ -222,7 +233,8 @@ describe('<EditRolePage />', () => {
|
|||
const features: Feature[] = buildFeatures();
|
||||
const mockHttpClient = jest.fn();
|
||||
const indexPatterns: string[] = ['foo*', 'bar*'];
|
||||
const privileges: RawKibanaPrivileges = buildRawKibanaPrivileges();
|
||||
const kibanaPrivileges: RawKibanaPrivileges = buildRawKibanaPrivileges();
|
||||
const builtinESPrivileges = buildBuiltinESPrivileges();
|
||||
const spaces: Space[] = buildSpaces();
|
||||
const uiCapabilities: UICapabilities = buildUICapabilities();
|
||||
|
||||
|
@ -236,7 +248,8 @@ describe('<EditRolePage />', () => {
|
|||
features={features}
|
||||
httpClient={mockHttpClient}
|
||||
indexPatterns={indexPatterns}
|
||||
privileges={privileges}
|
||||
kibanaPrivileges={kibanaPrivileges}
|
||||
builtinESPrivileges={builtinESPrivileges}
|
||||
spaces={spaces}
|
||||
spacesEnabled={true}
|
||||
uiCapabilities={uiCapabilities}
|
||||
|
@ -280,7 +293,8 @@ describe('<EditRolePage />', () => {
|
|||
const features: Feature[] = buildFeatures();
|
||||
const mockHttpClient = jest.fn();
|
||||
const indexPatterns: string[] = ['foo*', 'bar*'];
|
||||
const privileges: RawKibanaPrivileges = buildRawKibanaPrivileges();
|
||||
const kibanaPrivileges: RawKibanaPrivileges = buildRawKibanaPrivileges();
|
||||
const builtinESPrivileges = buildBuiltinESPrivileges();
|
||||
const spaces: Space[] = buildSpaces();
|
||||
const uiCapabilities: UICapabilities = buildUICapabilities();
|
||||
|
||||
|
@ -294,7 +308,8 @@ describe('<EditRolePage />', () => {
|
|||
features={features}
|
||||
httpClient={mockHttpClient}
|
||||
indexPatterns={indexPatterns}
|
||||
privileges={privileges}
|
||||
kibanaPrivileges={kibanaPrivileges}
|
||||
builtinESPrivileges={builtinESPrivileges}
|
||||
spaces={spaces}
|
||||
spacesEnabled={true}
|
||||
uiCapabilities={uiCapabilities}
|
||||
|
@ -327,7 +342,8 @@ describe('<EditRolePage />', () => {
|
|||
const features: Feature[] = buildFeatures();
|
||||
const mockHttpClient = jest.fn();
|
||||
const indexPatterns: string[] = ['foo*', 'bar*'];
|
||||
const privileges: RawKibanaPrivileges = buildRawKibanaPrivileges();
|
||||
const kibanaPrivileges: RawKibanaPrivileges = buildRawKibanaPrivileges();
|
||||
const builtinESPrivileges = buildBuiltinESPrivileges();
|
||||
const spaces: Space[] = buildSpaces();
|
||||
const uiCapabilities: UICapabilities = buildUICapabilities(false);
|
||||
|
||||
|
@ -341,7 +357,8 @@ describe('<EditRolePage />', () => {
|
|||
features={features}
|
||||
httpClient={mockHttpClient}
|
||||
indexPatterns={indexPatterns}
|
||||
privileges={privileges}
|
||||
kibanaPrivileges={kibanaPrivileges}
|
||||
builtinESPrivileges={builtinESPrivileges}
|
||||
spaces={spaces}
|
||||
spacesEnabled={true}
|
||||
uiCapabilities={uiCapabilities}
|
||||
|
@ -374,7 +391,8 @@ describe('<EditRolePage />', () => {
|
|||
const features: Feature[] = buildFeatures();
|
||||
const mockHttpClient = jest.fn();
|
||||
const indexPatterns: string[] = ['foo*', 'bar*'];
|
||||
const privileges: RawKibanaPrivileges = buildRawKibanaPrivileges();
|
||||
const kibanaPrivileges: RawKibanaPrivileges = buildRawKibanaPrivileges();
|
||||
const builtinESPrivileges = buildBuiltinESPrivileges();
|
||||
const spaces: Space[] = buildSpaces();
|
||||
const uiCapabilities: UICapabilities = buildUICapabilities(false);
|
||||
|
||||
|
@ -388,7 +406,8 @@ describe('<EditRolePage />', () => {
|
|||
features={features}
|
||||
httpClient={mockHttpClient}
|
||||
indexPatterns={indexPatterns}
|
||||
privileges={privileges}
|
||||
kibanaPrivileges={kibanaPrivileges}
|
||||
builtinESPrivileges={builtinESPrivileges}
|
||||
spaces={spaces}
|
||||
spacesEnabled={true}
|
||||
uiCapabilities={uiCapabilities}
|
||||
|
@ -424,7 +443,8 @@ describe('<EditRolePage />', () => {
|
|||
const features: Feature[] = buildFeatures();
|
||||
const mockHttpClient = jest.fn();
|
||||
const indexPatterns: string[] = ['foo*', 'bar*'];
|
||||
const privileges: RawKibanaPrivileges = buildRawKibanaPrivileges();
|
||||
const kibanaPrivileges: RawKibanaPrivileges = buildRawKibanaPrivileges();
|
||||
const builtinESPrivileges = buildBuiltinESPrivileges();
|
||||
const uiCapabilities: UICapabilities = buildUICapabilities();
|
||||
|
||||
const wrapper = mountWithIntl(
|
||||
|
@ -437,7 +457,8 @@ describe('<EditRolePage />', () => {
|
|||
features={features}
|
||||
httpClient={mockHttpClient}
|
||||
indexPatterns={indexPatterns}
|
||||
privileges={privileges}
|
||||
kibanaPrivileges={kibanaPrivileges}
|
||||
builtinESPrivileges={builtinESPrivileges}
|
||||
spaces={[]}
|
||||
spacesEnabled={false}
|
||||
uiCapabilities={uiCapabilities}
|
||||
|
@ -471,7 +492,8 @@ describe('<EditRolePage />', () => {
|
|||
const features: Feature[] = buildFeatures();
|
||||
const mockHttpClient = jest.fn();
|
||||
const indexPatterns: string[] = ['foo*', 'bar*'];
|
||||
const privileges: RawKibanaPrivileges = buildRawKibanaPrivileges();
|
||||
const kibanaPrivileges: RawKibanaPrivileges = buildRawKibanaPrivileges();
|
||||
const builtinESPrivileges = buildBuiltinESPrivileges();
|
||||
const uiCapabilities: UICapabilities = buildUICapabilities();
|
||||
|
||||
const wrapper = mountWithIntl(
|
||||
|
@ -484,7 +506,8 @@ describe('<EditRolePage />', () => {
|
|||
features={features}
|
||||
httpClient={mockHttpClient}
|
||||
indexPatterns={indexPatterns}
|
||||
privileges={privileges}
|
||||
kibanaPrivileges={kibanaPrivileges}
|
||||
builtinESPrivileges={builtinESPrivileges}
|
||||
spaces={[]}
|
||||
spacesEnabled={false}
|
||||
uiCapabilities={uiCapabilities}
|
||||
|
@ -512,7 +535,8 @@ describe('<EditRolePage />', () => {
|
|||
const features: Feature[] = buildFeatures();
|
||||
const mockHttpClient = jest.fn();
|
||||
const indexPatterns: string[] = ['foo*', 'bar*'];
|
||||
const privileges: RawKibanaPrivileges = buildRawKibanaPrivileges();
|
||||
const kibanaPrivileges: RawKibanaPrivileges = buildRawKibanaPrivileges();
|
||||
const builtinESPrivileges = buildBuiltinESPrivileges();
|
||||
const uiCapabilities: UICapabilities = buildUICapabilities();
|
||||
|
||||
const wrapper = mountWithIntl(
|
||||
|
@ -525,7 +549,8 @@ describe('<EditRolePage />', () => {
|
|||
features={features}
|
||||
httpClient={mockHttpClient}
|
||||
indexPatterns={indexPatterns}
|
||||
privileges={privileges}
|
||||
kibanaPrivileges={kibanaPrivileges}
|
||||
builtinESPrivileges={builtinESPrivileges}
|
||||
spaces={[]}
|
||||
spacesEnabled={false}
|
||||
uiCapabilities={uiCapabilities}
|
||||
|
@ -568,7 +593,8 @@ describe('<EditRolePage />', () => {
|
|||
const features: Feature[] = buildFeatures();
|
||||
const mockHttpClient = jest.fn();
|
||||
const indexPatterns: string[] = ['foo*', 'bar*'];
|
||||
const privileges: RawKibanaPrivileges = buildRawKibanaPrivileges();
|
||||
const kibanaPrivileges: RawKibanaPrivileges = buildRawKibanaPrivileges();
|
||||
const builtinESPrivileges = buildBuiltinESPrivileges();
|
||||
const uiCapabilities: UICapabilities = buildUICapabilities();
|
||||
|
||||
const wrapper = mountWithIntl(
|
||||
|
@ -581,7 +607,8 @@ describe('<EditRolePage />', () => {
|
|||
features={features}
|
||||
httpClient={mockHttpClient}
|
||||
indexPatterns={indexPatterns}
|
||||
privileges={privileges}
|
||||
kibanaPrivileges={kibanaPrivileges}
|
||||
builtinESPrivileges={builtinESPrivileges}
|
||||
spaces={[]}
|
||||
spacesEnabled={false}
|
||||
uiCapabilities={uiCapabilities}
|
||||
|
@ -613,7 +640,8 @@ describe('<EditRolePage />', () => {
|
|||
const features: Feature[] = buildFeatures();
|
||||
const mockHttpClient = jest.fn();
|
||||
const indexPatterns: string[] = ['foo*', 'bar*'];
|
||||
const privileges: RawKibanaPrivileges = buildRawKibanaPrivileges();
|
||||
const kibanaPrivileges: RawKibanaPrivileges = buildRawKibanaPrivileges();
|
||||
const builtinESPrivileges = buildBuiltinESPrivileges();
|
||||
const uiCapabilities: UICapabilities = buildUICapabilities(false);
|
||||
|
||||
const wrapper = mountWithIntl(
|
||||
|
@ -626,7 +654,8 @@ describe('<EditRolePage />', () => {
|
|||
features={features}
|
||||
httpClient={mockHttpClient}
|
||||
indexPatterns={indexPatterns}
|
||||
privileges={privileges}
|
||||
kibanaPrivileges={kibanaPrivileges}
|
||||
builtinESPrivileges={builtinESPrivileges}
|
||||
spaces={[]}
|
||||
spacesEnabled={false}
|
||||
uiCapabilities={uiCapabilities}
|
||||
|
@ -659,7 +688,8 @@ describe('<EditRolePage />', () => {
|
|||
const features: Feature[] = buildFeatures();
|
||||
const mockHttpClient = jest.fn();
|
||||
const indexPatterns: string[] = ['foo*', 'bar*'];
|
||||
const privileges: RawKibanaPrivileges = buildRawKibanaPrivileges();
|
||||
const kibanaPrivileges: RawKibanaPrivileges = buildRawKibanaPrivileges();
|
||||
const builtinESPrivileges = buildBuiltinESPrivileges();
|
||||
const uiCapabilities: UICapabilities = buildUICapabilities(false);
|
||||
|
||||
const wrapper = mountWithIntl(
|
||||
|
@ -672,7 +702,8 @@ describe('<EditRolePage />', () => {
|
|||
features={features}
|
||||
httpClient={mockHttpClient}
|
||||
indexPatterns={indexPatterns}
|
||||
privileges={privileges}
|
||||
kibanaPrivileges={kibanaPrivileges}
|
||||
builtinESPrivileges={builtinESPrivileges}
|
||||
spaces={[]}
|
||||
spacesEnabled={false}
|
||||
uiCapabilities={uiCapabilities}
|
||||
|
|
|
@ -24,7 +24,12 @@ import { UICapabilities } from 'ui/capabilities';
|
|||
import { toastNotifications } from 'ui/notify';
|
||||
import { Space } from '../../../../../../spaces/common/model/space';
|
||||
import { Feature } from '../../../../../../xpack_main/types';
|
||||
import { KibanaPrivileges, RawKibanaPrivileges, Role } from '../../../../../common/model';
|
||||
import {
|
||||
KibanaPrivileges,
|
||||
RawKibanaPrivileges,
|
||||
Role,
|
||||
BuiltinESPrivileges,
|
||||
} from '../../../../../common/model';
|
||||
import {
|
||||
isReadOnlyRole,
|
||||
isReservedRole,
|
||||
|
@ -46,7 +51,8 @@ interface Props {
|
|||
httpClient: any;
|
||||
allowDocumentLevelSecurity: boolean;
|
||||
allowFieldLevelSecurity: boolean;
|
||||
privileges: RawKibanaPrivileges;
|
||||
kibanaPrivileges: RawKibanaPrivileges;
|
||||
builtinESPrivileges: BuiltinESPrivileges;
|
||||
spaces?: Space[];
|
||||
spacesEnabled: boolean;
|
||||
intl: InjectedIntl;
|
||||
|
@ -246,6 +252,7 @@ class EditRolePageUI extends Component<Props, State> {
|
|||
runAsUsers={this.props.runAsUsers}
|
||||
validator={this.validator}
|
||||
indexPatterns={this.props.indexPatterns}
|
||||
builtinESPrivileges={this.props.builtinESPrivileges}
|
||||
allowDocumentLevelSecurity={this.props.allowDocumentLevelSecurity}
|
||||
allowFieldLevelSecurity={this.props.allowFieldLevelSecurity}
|
||||
/>
|
||||
|
@ -264,7 +271,7 @@ class EditRolePageUI extends Component<Props, State> {
|
|||
<div>
|
||||
<EuiSpacer />
|
||||
<KibanaPrivilegesRegion
|
||||
kibanaPrivileges={new KibanaPrivileges(this.props.privileges)}
|
||||
kibanaPrivileges={new KibanaPrivileges(this.props.kibanaPrivileges)}
|
||||
spaces={this.props.spaces}
|
||||
spacesEnabled={this.props.spacesEnabled}
|
||||
features={this.props.features}
|
||||
|
|
|
@ -16,74 +16,11 @@ exports[`it renders without crashing 1`] = `
|
|||
Object {
|
||||
"label": "all",
|
||||
},
|
||||
Object {
|
||||
"label": "monitor",
|
||||
},
|
||||
Object {
|
||||
"label": "manage",
|
||||
},
|
||||
Object {
|
||||
"label": "manage_security",
|
||||
},
|
||||
Object {
|
||||
"label": "manage_index_templates",
|
||||
},
|
||||
Object {
|
||||
"label": "manage_pipeline",
|
||||
},
|
||||
Object {
|
||||
"label": "manage_ingest_pipelines",
|
||||
},
|
||||
Object {
|
||||
"label": "transport_client",
|
||||
},
|
||||
Object {
|
||||
"label": "manage_ml",
|
||||
},
|
||||
Object {
|
||||
"label": "monitor_ml",
|
||||
},
|
||||
Object {
|
||||
"label": "manage_data_frame_transforms",
|
||||
},
|
||||
Object {
|
||||
"label": "monitor_data_frame_transforms",
|
||||
},
|
||||
Object {
|
||||
"label": "manage_watcher",
|
||||
},
|
||||
Object {
|
||||
"label": "monitor_watcher",
|
||||
},
|
||||
Object {
|
||||
"label": "read_ccr",
|
||||
},
|
||||
Object {
|
||||
"label": "manage_ccr",
|
||||
},
|
||||
Object {
|
||||
"label": "manage_ilm",
|
||||
},
|
||||
Object {
|
||||
"label": "read_ilm",
|
||||
},
|
||||
Object {
|
||||
"label": "monitor_rollup",
|
||||
},
|
||||
Object {
|
||||
"label": "manage_rollup",
|
||||
},
|
||||
Object {
|
||||
"label": "manage_token",
|
||||
},
|
||||
Object {
|
||||
"label": "manage_saml",
|
||||
},
|
||||
Object {
|
||||
"label": "create_snapshot",
|
||||
},
|
||||
Object {
|
||||
"label": "manage_oidc",
|
||||
"label": "monitor",
|
||||
},
|
||||
]
|
||||
}
|
||||
|
|
|
@ -48,6 +48,13 @@ exports[`it renders without crashing 1`] = `
|
|||
labelType="label"
|
||||
>
|
||||
<ClusterPrivileges
|
||||
availableClusterPrivileges={
|
||||
Array [
|
||||
"all",
|
||||
"manage",
|
||||
"monitor",
|
||||
]
|
||||
}
|
||||
onChange={[Function]}
|
||||
role={
|
||||
Object {
|
||||
|
@ -163,6 +170,14 @@ exports[`it renders without crashing 1`] = `
|
|||
<IndexPrivileges
|
||||
allowDocumentLevelSecurity={true}
|
||||
allowFieldLevelSecurity={true}
|
||||
availableIndexPrivileges={
|
||||
Array [
|
||||
"all",
|
||||
"read",
|
||||
"write",
|
||||
"index",
|
||||
]
|
||||
}
|
||||
httpClient={[MockFunction]}
|
||||
indexPatterns={Array []}
|
||||
onChange={[MockFunction]}
|
||||
|
|
|
@ -63,47 +63,14 @@ exports[`it renders without crashing 1`] = `
|
|||
Object {
|
||||
"label": "all",
|
||||
},
|
||||
Object {
|
||||
"label": "manage",
|
||||
},
|
||||
Object {
|
||||
"label": "monitor",
|
||||
},
|
||||
Object {
|
||||
"label": "read",
|
||||
},
|
||||
Object {
|
||||
"label": "index",
|
||||
},
|
||||
Object {
|
||||
"label": "create",
|
||||
},
|
||||
Object {
|
||||
"label": "delete",
|
||||
},
|
||||
Object {
|
||||
"label": "write",
|
||||
},
|
||||
Object {
|
||||
"label": "delete_index",
|
||||
},
|
||||
Object {
|
||||
"label": "create_index",
|
||||
},
|
||||
Object {
|
||||
"label": "view_index_metadata",
|
||||
},
|
||||
Object {
|
||||
"label": "read_cross_cluster",
|
||||
},
|
||||
Object {
|
||||
"label": "manage_follow_index",
|
||||
},
|
||||
Object {
|
||||
"label": "manage_ilm",
|
||||
},
|
||||
Object {
|
||||
"label": "manage_leader_index",
|
||||
"label": "index",
|
||||
},
|
||||
]
|
||||
}
|
||||
|
|
|
@ -20,6 +20,12 @@ test('it renders without crashing', () => {
|
|||
kibana: [],
|
||||
};
|
||||
|
||||
const wrapper = shallow(<ClusterPrivileges role={role} onChange={jest.fn()} />);
|
||||
const wrapper = shallow(
|
||||
<ClusterPrivileges
|
||||
role={role}
|
||||
onChange={jest.fn()}
|
||||
availableClusterPrivileges={['all', 'manage', 'monitor']}
|
||||
/>
|
||||
);
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
});
|
||||
|
|
|
@ -8,19 +8,16 @@ import { EuiComboBox, EuiFlexGroup, EuiFlexItem } from '@elastic/eui';
|
|||
import React, { Component } from 'react';
|
||||
import { Role } from '../../../../../../../common/model';
|
||||
import { isReadOnlyRole } from '../../../../../../lib/role_utils';
|
||||
// @ts-ignore
|
||||
import { getClusterPrivileges } from '../../../../../../services/role_privileges';
|
||||
|
||||
interface Props {
|
||||
role: Role;
|
||||
availableClusterPrivileges: string[];
|
||||
onChange: (privs: string[]) => void;
|
||||
}
|
||||
|
||||
export class ClusterPrivileges extends Component<Props, {}> {
|
||||
public render() {
|
||||
const clusterPrivileges = getClusterPrivileges();
|
||||
|
||||
return <EuiFlexGroup>{this.buildComboBox(clusterPrivileges)}</EuiFlexGroup>;
|
||||
return <EuiFlexGroup>{this.buildComboBox(this.props.availableClusterPrivileges)}</EuiFlexGroup>;
|
||||
}
|
||||
|
||||
public buildComboBox = (items: string[]) => {
|
||||
|
|
|
@ -30,6 +30,10 @@ test('it renders without crashing', () => {
|
|||
allowDocumentLevelSecurity: true,
|
||||
allowFieldLevelSecurity: true,
|
||||
validator: new RoleValidator(),
|
||||
builtinESPrivileges: {
|
||||
cluster: ['all', 'manage', 'monitor'],
|
||||
index: ['all', 'read', 'write', 'index'],
|
||||
},
|
||||
};
|
||||
const wrapper = shallowWithIntl(<ElasticsearchPrivileges {...props} />);
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
|
@ -54,6 +58,10 @@ test('it renders ClusterPrivileges', () => {
|
|||
allowDocumentLevelSecurity: true,
|
||||
allowFieldLevelSecurity: true,
|
||||
validator: new RoleValidator(),
|
||||
builtinESPrivileges: {
|
||||
cluster: ['all', 'manage', 'monitor'],
|
||||
index: ['all', 'read', 'write', 'index'],
|
||||
},
|
||||
};
|
||||
const wrapper = mountWithIntl(<ElasticsearchPrivileges {...props} />);
|
||||
expect(wrapper.find(ClusterPrivileges)).toHaveLength(1);
|
||||
|
@ -78,6 +86,10 @@ test('it renders IndexPrivileges', () => {
|
|||
allowDocumentLevelSecurity: true,
|
||||
allowFieldLevelSecurity: true,
|
||||
validator: new RoleValidator(),
|
||||
builtinESPrivileges: {
|
||||
cluster: ['all', 'manage', 'monitor'],
|
||||
index: ['all', 'read', 'write', 'index'],
|
||||
},
|
||||
};
|
||||
const wrapper = mountWithIntl(<ElasticsearchPrivileges {...props} />);
|
||||
expect(wrapper.find(IndexPrivileges)).toHaveLength(1);
|
||||
|
|
|
@ -19,7 +19,7 @@ import {
|
|||
import { i18n } from '@kbn/i18n';
|
||||
import { FormattedMessage } from '@kbn/i18n/react';
|
||||
import React, { Component, Fragment } from 'react';
|
||||
import { Role } from '../../../../../../../common/model';
|
||||
import { Role, BuiltinESPrivileges } from '../../../../../../../common/model';
|
||||
// @ts-ignore
|
||||
import { documentationLinks } from '../../../../../../documentation_links';
|
||||
import { RoleValidator } from '../../../lib/validate_role';
|
||||
|
@ -35,6 +35,7 @@ interface Props {
|
|||
onChange: (role: Role) => void;
|
||||
runAsUsers: string[];
|
||||
validator: RoleValidator;
|
||||
builtinESPrivileges: BuiltinESPrivileges;
|
||||
indexPatterns: string[];
|
||||
allowDocumentLevelSecurity: boolean;
|
||||
allowFieldLevelSecurity: boolean;
|
||||
|
@ -59,6 +60,7 @@ export class ElasticsearchPrivileges extends Component<Props, {}> {
|
|||
indexPatterns,
|
||||
allowDocumentLevelSecurity,
|
||||
allowFieldLevelSecurity,
|
||||
builtinESPrivileges,
|
||||
} = this.props;
|
||||
|
||||
const indexProps = {
|
||||
|
@ -69,6 +71,7 @@ export class ElasticsearchPrivileges extends Component<Props, {}> {
|
|||
allowDocumentLevelSecurity,
|
||||
allowFieldLevelSecurity,
|
||||
onChange,
|
||||
availableIndexPrivileges: builtinESPrivileges.index,
|
||||
};
|
||||
|
||||
return (
|
||||
|
@ -93,7 +96,11 @@ export class ElasticsearchPrivileges extends Component<Props, {}> {
|
|||
}
|
||||
>
|
||||
<EuiFormRow fullWidth={true} hasEmptyLabelSpace>
|
||||
<ClusterPrivileges role={this.props.role} onChange={this.onClusterPrivilegesChange} />
|
||||
<ClusterPrivileges
|
||||
role={this.props.role}
|
||||
onChange={this.onClusterPrivilegesChange}
|
||||
availableClusterPrivileges={builtinESPrivileges.cluster}
|
||||
/>
|
||||
</EuiFormRow>
|
||||
</EuiDescribedFormGroup>
|
||||
|
||||
|
|
|
@ -22,6 +22,7 @@ test('it renders without crashing', () => {
|
|||
formIndex: 0,
|
||||
indexPatterns: [],
|
||||
availableFields: [],
|
||||
availableIndexPrivileges: ['all', 'read', 'write', 'index'],
|
||||
isReadOnlyRole: false,
|
||||
allowDocumentLevelSecurity: true,
|
||||
allowFieldLevelSecurity: true,
|
||||
|
@ -48,6 +49,7 @@ describe('delete button', () => {
|
|||
formIndex: 0,
|
||||
indexPatterns: [],
|
||||
availableFields: [],
|
||||
availableIndexPrivileges: ['all', 'read', 'write', 'index'],
|
||||
isReadOnlyRole: false,
|
||||
allowDocumentLevelSecurity: true,
|
||||
allowFieldLevelSecurity: true,
|
||||
|
@ -99,6 +101,7 @@ describe(`document level security`, () => {
|
|||
formIndex: 0,
|
||||
indexPatterns: [],
|
||||
availableFields: [],
|
||||
availableIndexPrivileges: ['all', 'read', 'write', 'index'],
|
||||
isReadOnlyRole: false,
|
||||
allowDocumentLevelSecurity: true,
|
||||
allowFieldLevelSecurity: true,
|
||||
|
@ -157,6 +160,7 @@ describe('field level security', () => {
|
|||
formIndex: 0,
|
||||
indexPatterns: [],
|
||||
availableFields: [],
|
||||
availableIndexPrivileges: ['all', 'read', 'write', 'index'],
|
||||
isReadOnlyRole: false,
|
||||
allowDocumentLevelSecurity: true,
|
||||
allowFieldLevelSecurity: true,
|
||||
|
|
|
@ -20,8 +20,6 @@ import { FormattedMessage } from '@kbn/i18n/react';
|
|||
import _ from 'lodash';
|
||||
import React, { ChangeEvent, Component, Fragment } from 'react';
|
||||
import { RoleIndexPrivilege } from '../../../../../../../common/model';
|
||||
// @ts-ignore
|
||||
import { getIndexPrivileges } from '../../../../../../services/role_privileges';
|
||||
import { RoleValidator } from '../../../lib/validate_role';
|
||||
|
||||
const fromOption = (option: any) => option.label;
|
||||
|
@ -31,6 +29,7 @@ interface Props {
|
|||
formIndex: number;
|
||||
indexPrivilege: RoleIndexPrivilege;
|
||||
indexPatterns: string[];
|
||||
availableIndexPrivileges: string[];
|
||||
availableFields: string[];
|
||||
onChange: (indexPrivilege: RoleIndexPrivilege) => void;
|
||||
onDelete: () => void;
|
||||
|
@ -126,7 +125,7 @@ export class IndexPrivilegeForm extends Component<Props, State> {
|
|||
>
|
||||
<EuiComboBox
|
||||
data-test-subj={`privilegesInput${this.props.formIndex}`}
|
||||
options={getIndexPrivileges().map(toOption)}
|
||||
options={this.props.availableIndexPrivileges.map(toOption)}
|
||||
selectedOptions={this.props.indexPrivilege.privileges.map(toOption)}
|
||||
onChange={this.onPrivilegeChange}
|
||||
isDisabled={this.props.isReadOnlyRole}
|
||||
|
|
|
@ -28,6 +28,7 @@ test('it renders without crashing', () => {
|
|||
allowFieldLevelSecurity: true,
|
||||
editable: true,
|
||||
validator: new RoleValidator(),
|
||||
availableIndexPrivileges: ['all', 'read', 'write', 'index'],
|
||||
};
|
||||
const wrapper = shallowWithIntl(<IndexPrivileges {...props} />);
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
|
@ -60,6 +61,7 @@ test('it renders a IndexPrivilegeForm for each privilege on the role', () => {
|
|||
allowDocumentLevelSecurity: true,
|
||||
allowFieldLevelSecurity: true,
|
||||
validator: new RoleValidator(),
|
||||
availableIndexPrivileges: ['all', 'read', 'write', 'index'],
|
||||
};
|
||||
const wrapper = mountWithIntl(<IndexPrivileges {...props} />);
|
||||
expect(wrapper.find(IndexPrivilegeForm)).toHaveLength(1);
|
||||
|
|
|
@ -14,6 +14,7 @@ import { IndexPrivilegeForm } from './index_privilege_form';
|
|||
interface Props {
|
||||
role: Role;
|
||||
indexPatterns: string[];
|
||||
availableIndexPrivileges: string[];
|
||||
allowDocumentLevelSecurity: boolean;
|
||||
allowFieldLevelSecurity: boolean;
|
||||
httpClient: any;
|
||||
|
@ -42,7 +43,12 @@ export class IndexPrivileges extends Component<Props, State> {
|
|||
public render() {
|
||||
const { indices = [] } = this.props.role.elasticsearch;
|
||||
|
||||
const { indexPatterns, allowDocumentLevelSecurity, allowFieldLevelSecurity } = this.props;
|
||||
const {
|
||||
indexPatterns,
|
||||
allowDocumentLevelSecurity,
|
||||
allowFieldLevelSecurity,
|
||||
availableIndexPrivileges,
|
||||
} = this.props;
|
||||
|
||||
const props = {
|
||||
indexPatterns,
|
||||
|
@ -60,6 +66,7 @@ export class IndexPrivileges extends Component<Props, State> {
|
|||
{...props}
|
||||
formIndex={idx}
|
||||
validator={this.props.validator}
|
||||
availableIndexPrivileges={availableIndexPrivileges}
|
||||
indexPrivilege={indexPrivilege}
|
||||
availableFields={this.state.availableFields[indexPrivilege.names.join(',')]}
|
||||
onChange={this.onIndexPrivilegeChange(idx)}
|
||||
|
|
|
@ -10,8 +10,6 @@ import { capabilities } from 'ui/capabilities';
|
|||
import { kfetch } from 'ui/kfetch';
|
||||
import { fatalError, toastNotifications } from 'ui/notify';
|
||||
import template from 'plugins/security/views/management/edit_role/edit_role.html';
|
||||
import 'ui/angular_ui_select';
|
||||
import 'plugins/security/services/application_privilege';
|
||||
import 'plugins/security/services/shield_user';
|
||||
import 'plugins/security/services/shield_role';
|
||||
import 'plugins/security/services/shield_indices';
|
||||
|
@ -87,9 +85,12 @@ const routeDefinition = (action) => ({
|
|||
}
|
||||
return [];
|
||||
},
|
||||
privileges() {
|
||||
kibanaPrivileges() {
|
||||
return kfetch({ method: 'get', pathname: '/api/security/privileges', query: { includeActions: true } });
|
||||
},
|
||||
builtinESPrivileges() {
|
||||
return kfetch({ method: 'get', pathname: '/api/security/v1/esPrivileges/builtin' });
|
||||
},
|
||||
features() {
|
||||
return kfetch({ method: 'get', pathname: '/api/features/v1' }).catch(e => {
|
||||
// TODO: This check can be removed once all of these `resolve` entries are moved out of Angular and into the React app.
|
||||
|
@ -132,7 +133,8 @@ const routeDefinition = (action) => ({
|
|||
users,
|
||||
indexPatterns,
|
||||
spaces,
|
||||
privileges,
|
||||
kibanaPrivileges,
|
||||
builtinESPrivileges,
|
||||
features,
|
||||
} = $route.current.locals;
|
||||
|
||||
|
@ -153,7 +155,8 @@ const routeDefinition = (action) => ({
|
|||
spacesEnabled={enableSpaceAwarePrivileges}
|
||||
uiCapabilities={capabilities.get()}
|
||||
features={features}
|
||||
privileges={privileges}
|
||||
kibanaPrivileges={kibanaPrivileges}
|
||||
builtinESPrivileges={builtinESPrivileges}
|
||||
/>
|
||||
</I18nContext>, domNode);
|
||||
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
* 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 { Legacy } from 'kibana';
|
||||
import { BuiltinESPrivileges } from '../../../../common/model';
|
||||
import { getClient } from '../../../../../../server/lib/get_client_shield';
|
||||
|
||||
export function initGetBuiltinPrivilegesApi(server: Legacy.Server) {
|
||||
server.route({
|
||||
method: 'GET',
|
||||
path: '/api/security/v1/esPrivileges/builtin',
|
||||
async handler(req: Legacy.Request) {
|
||||
const callWithRequest = getClient(server).callWithRequest;
|
||||
const privileges = await callWithRequest<BuiltinESPrivileges>(
|
||||
req,
|
||||
'shield.getBuiltinPrivileges'
|
||||
);
|
||||
|
||||
// Exclude the `none` privilege, as it doesn't make sense as an option within the Kibana UI
|
||||
privileges.cluster = privileges.cluster.filter(privilege => privilege !== 'none');
|
||||
privileges.index = privileges.index.filter(privilege => privilege !== 'none');
|
||||
|
||||
return privileges;
|
||||
},
|
||||
});
|
||||
}
|
|
@ -488,5 +488,14 @@
|
|||
fmt: '/_security/user/_has_privileges'
|
||||
}
|
||||
});
|
||||
|
||||
shield.getBuiltinPrivileges = ca({
|
||||
params: {},
|
||||
urls: [
|
||||
{
|
||||
fmt: '/_security/privilege/_builtin'
|
||||
}
|
||||
]
|
||||
});
|
||||
};
|
||||
}));
|
||||
|
|
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
* 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 '@kbn/expect/expect.js';
|
||||
import { KibanaFunctionalTestDefaultProviders } from '../../../types/providers';
|
||||
|
||||
// eslint-disable-next-line import/no-default-export
|
||||
export default function({ getService }: KibanaFunctionalTestDefaultProviders) {
|
||||
const supertest = getService('supertest');
|
||||
|
||||
describe('Builtin ES Privileges', () => {
|
||||
describe('GET /api/security/v1/esPrivileges/builtin', () => {
|
||||
it('should return a list of available builtin privileges', async () => {
|
||||
await supertest
|
||||
.get('/api/security/v1/esPrivileges/builtin')
|
||||
.set('kbn-xsrf', 'xxx')
|
||||
.send()
|
||||
.expect(200)
|
||||
.then((response: Record<string, any>) => {
|
||||
const sampleOfExpectedClusterPrivileges = ['all', 'manage', 'monitor'];
|
||||
const sampleOfExpectedIndexPrivileges = ['create', 'index', 'delete'];
|
||||
|
||||
const payload = response.body;
|
||||
expect(Object.keys(payload).sort()).to.eql(['cluster', 'index']);
|
||||
|
||||
sampleOfExpectedClusterPrivileges.forEach(privilege =>
|
||||
expect(payload.cluster).to.contain(privilege)
|
||||
);
|
||||
|
||||
sampleOfExpectedIndexPrivileges.forEach(privilege =>
|
||||
expect(payload.index).to.contain(privilege)
|
||||
);
|
||||
|
||||
expect(payload.cluster).not.to.contain('none');
|
||||
expect(payload.index).not.to.contain('none');
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
|
@ -9,6 +9,7 @@ export default function ({ loadTestFile }) {
|
|||
this.tags('ciGroup6');
|
||||
|
||||
loadTestFile(require.resolve('./basic_login'));
|
||||
loadTestFile(require.resolve('./builtin_es_privileges'));
|
||||
loadTestFile(require.resolve('./index_fields'));
|
||||
loadTestFile(require.resolve('./roles'));
|
||||
loadTestFile(require.resolve('./privileges'));
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue