Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
79 commits
Select commit Hold shift + click to select a range
01ecada
initial grid page
legrego Oct 23, 2019
dcb1e7e
improving role template selection
legrego Nov 25, 2019
cefe417
simplifying add rule button
legrego Nov 25, 2019
f957a12
rule editor improvements
legrego Dec 3, 2019
3f155cc
introducing advanced rule editor
legrego Dec 3, 2019
858a1d3
improving validation feedback
legrego Dec 3, 2019
bf31479
improve except rules
legrego Dec 3, 2019
8b455d5
improve grid page
legrego Dec 3, 2019
e81ca4d
initial form validation
legrego Dec 3, 2019
c8e6992
calculate max rule depth
legrego Dec 4, 2019
502ddc1
introduce visual editor max depth
legrego Dec 4, 2019
24967a7
fixing field rule validation
legrego Dec 4, 2019
4053de6
switching from EuiButtonEmpty to EuiLink
legrego Dec 4, 2019
ea60514
warn when changing rule groups if sub rules are incompatible
legrego Dec 4, 2019
ea0b41d
cleaning up / moving types
legrego Dec 4, 2019
afb491e
fixing title weight
legrego Dec 4, 2019
09cb610
design tweaks
legrego Dec 4, 2019
0c34ec0
working on functional tests
legrego Dec 5, 2019
0cb0def
updates from rebase with master
legrego Dec 6, 2019
fa034ca
cleanup
legrego Dec 6, 2019
af93d3c
additional component and functional testing
legrego Dec 8, 2019
f5d9765
additional testing
legrego Dec 8, 2019
ef13271
rule builder testing
legrego Dec 9, 2019
3e4d7cf
removing test isolation
legrego Dec 9, 2019
d350693
fix lint errors
legrego Dec 9, 2019
38ed631
additional cleanup
legrego Dec 9, 2019
7d10323
additional cleanup
legrego Dec 9, 2019
6981ff9
i18n updates
legrego Dec 10, 2019
434c82b
additional testing and cleanup
legrego Dec 10, 2019
1a027c4
adding basic license functional test
legrego Dec 10, 2019
cab0191
Merge branch 'master' of github.com:elastic/kibana into security/role…
legrego Dec 10, 2019
2ab5980
i18n cleanup
legrego Dec 10, 2019
d4e90d1
license service test
legrego Dec 10, 2019
7424c6d
Revert "license service test"
legrego Dec 10, 2019
cf7688c
Merge branch 'master' of github.com:elastic/kibana into security/role…
legrego Dec 11, 2019
d3776cb
doc and ux improvements
legrego Dec 11, 2019
d98e971
fixing add alternate value button
legrego Dec 11, 2019
80f684e
stubbing docs
legrego Dec 11, 2019
9e4132c
fixing license_service tests (again??)
legrego Dec 11, 2019
ae58e48
supressing ace editor warnings in test output
legrego Dec 11, 2019
fe92b85
adjusting nested rule styling
legrego Dec 11, 2019
2dd3e8f
improve error handling
legrego Dec 11, 2019
377ea21
improving in-line help
legrego Dec 11, 2019
b3018aa
Merge branch 'master' of github.com:elastic/kibana into security/role…
legrego Dec 11, 2019
0845e8d
fix merge from master
legrego Dec 11, 2019
ff6fa41
fix example text to pass i18n parser
legrego Dec 11, 2019
f98bcee
delete alternate value based on index
legrego Dec 11, 2019
ca796b7
migrate role mappings api to use NP http service
legrego Dec 12, 2019
cb08cff
simplifying loading states
legrego Dec 12, 2019
88fa09b
simplify visual editor cutoff logic
legrego Dec 12, 2019
75b7cf0
Merge branch 'master' of github.com:elastic/kibana into security/role…
legrego Dec 12, 2019
1dcd396
consolidate rule builder logic
legrego Dec 12, 2019
c6605ca
more client-side testing
legrego Dec 13, 2019
dbbfd1a
additional server tests and cleanup
legrego Dec 13, 2019
2be2412
remove stray console.log statement
legrego Dec 13, 2019
c202263
adding support for boolean values
legrego Dec 16, 2019
cd360f0
adding EuiErrorBoundary
legrego Dec 16, 2019
3e5afa7
add rule button design edits
legrego Dec 16, 2019
14b2343
design review: auto-create role template when switching
legrego Dec 16, 2019
8e99028
apply design edits
andreadelrio Dec 16, 2019
d7a4ed8
fixing icon alignment
legrego Dec 16, 2019
7b5f376
extracting help link to panel subtext
legrego Dec 16, 2019
1e89e59
additional create/edit tests
legrego Dec 17, 2019
2eaf573
Merge branch 'master' of github.com:elastic/kibana into security/role…
legrego Dec 17, 2019
e70a783
fix eslint error
legrego Dec 17, 2019
7f07322
Merge branch 'master' of github.com:elastic/kibana into security/role…
legrego Dec 17, 2019
b35eb74
fix license test, again
legrego Dec 17, 2019
e6dbd77
Copy review edits: round 1
legrego Dec 17, 2019
b857356
Merge branch 'master' of github.com:elastic/kibana into security/role…
legrego Dec 18, 2019
79a3cf0
remove demo code
legrego Dec 18, 2019
8799eaf
snapshot updates
legrego Dec 18, 2019
fa52853
rule builder improvements
legrego Dec 18, 2019
00dfd45
simplify page state
legrego Dec 18, 2019
30f4cc1
Merge branch 'master' of github.com:elastic/kibana into security/role…
legrego Dec 18, 2019
b9e34c8
update test to reflect JSON editor name change
legrego Dec 18, 2019
d647b0e
design edits
legrego Dec 18, 2019
e80cdc6
Merge branch 'master' of github.com:elastic/kibana into security/role…
legrego Dec 19, 2019
9bcc1d6
improve license tests after merge from master
legrego Dec 19, 2019
3b88e1a
fix merge from master
legrego Dec 19, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/user/security/index.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -37,4 +37,5 @@ cause Kibana's authorization to behave unexpectedly.
include::authorization/index.asciidoc[]
include::authorization/kibana-privileges.asciidoc[]
include::api-keys/index.asciidoc[]
include::role-mappings/index.asciidoc[]
include::rbac_tutorial.asciidoc[]
40 changes: 40 additions & 0 deletions docs/user/security/role-mappings/index.asciidoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
[role="xpack"]
[[role-mappings]]
=== Role Mappings


Role mappings allow you to describe which roles to assign to your users
using a set of rules. Role mappings are required when authenticating via
an external identity provider, such as Active Directory, Kerberos, PKI, OIDC,
or SAML.

Role mappings have no effect for users inside the `native` or `file` realms.

To manage your role mappings, use *Management > Security > Role Mappings*.

NOTE: The role mapping UI will only be available if your license supports external
identity providers which can benefit from role mappings.

// [role="screenshot"]
// image:user/security/role-mappings/images/role-mappings-grid.png["Role Mappings UI"]


[float]
[[role-mappings-security-privileges]]
=== Security privileges

You must have the `manage_security` cluster privilege to manage role mappings in {kib}.
You can manage roles in *Management > Security > Roles*, or use the
<<role-management-api, {kib} Role Management API>>.


[float]
[[create-role-mapping]]
=== Create a Role Mapping
You can create a role mapping from *Management > Security > Role Mappings*.

// [role="screenshot"]
// image:user/security/role-mappings/images/create-role-mapping.png["Create Role Mapping UI"]



66 changes: 66 additions & 0 deletions test/common/services/security/role_mappings.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
/*
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch B.V. licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

import axios, { AxiosInstance } from 'axios';
import util from 'util';
import { ToolingLog } from '@kbn/dev-utils';

export class RoleMappings {
private log: ToolingLog;
private axios: AxiosInstance;

constructor(url: string, log: ToolingLog) {
this.log = log;
this.axios = axios.create({
headers: { 'kbn-xsrf': 'x-pack/ftr/services/security/role_mappings' },
baseURL: url,
maxRedirects: 0,
validateStatus: () => true, // we do our own validation below and throw better error messages
});
}

public async create(name: string, roleMapping: Record<string, any>) {
this.log.debug(`creating role mapping ${name}`);
const { data, status, statusText } = await this.axios.post(
`/internal/security/role_mapping/${name}`,
roleMapping
);
if (status !== 200) {
throw new Error(
`Expected status code of 200, received ${status} ${statusText}: ${util.inspect(data)}`
);
}
this.log.debug(`created role mapping ${name}`);
}

public async delete(name: string) {
this.log.debug(`deleting role mapping ${name}`);
const { data, status, statusText } = await this.axios.delete(
`/internal/security/role_mapping/${name}`
);
if (status !== 200 && status !== 404) {
throw new Error(
`Expected status code of 200 or 404, received ${status} ${statusText}: ${util.inspect(
data
)}`
);
}
this.log.debug(`deleted role mapping ${name}`);
}
}
2 changes: 2 additions & 0 deletions test/common/services/security/security.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import { format as formatUrl } from 'url';

import { Role } from './role';
import { User } from './user';
import { RoleMappings } from './role_mappings';
import { FtrProviderContext } from '../../ftr_provider_context';

export function SecurityServiceProvider({ getService }: FtrProviderContext) {
Expand All @@ -30,6 +31,7 @@ export function SecurityServiceProvider({ getService }: FtrProviderContext) {

return new (class SecurityService {
role = new Role(url, log);
roleMappings = new RoleMappings(url, log);
user = new User(url, log);
})();
}
1 change: 1 addition & 0 deletions x-pack/dev-tools/jest/create_jest_config.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ export function createJestConfig({ kibanaDirectory, xPackKibanaDirectory }) {
'\\.(css|less|scss)$': `${kibanaDirectory}/src/dev/jest/mocks/style_mock.js`,
'^test_utils/enzyme_helpers': `${xPackKibanaDirectory}/test_utils/enzyme_helpers.tsx`,
'^test_utils/find_test_subject': `${xPackKibanaDirectory}/test_utils/find_test_subject.ts`,
'^test_utils/stub_web_worker': `${xPackKibanaDirectory}/test_utils/stub_web_worker.ts`,
},
coverageDirectory: '<rootDir>/../target/kibana-coverage/jest',
coverageReporters: ['html'],
Expand Down
2 changes: 2 additions & 0 deletions x-pack/legacy/plugins/security/common/model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,5 @@ export {
canUserChangePassword,
getUserDisplayName,
} from '../../../../plugins/security/common/model';

export * from './role_mapping';
55 changes: 55 additions & 0 deletions x-pack/legacy/plugins/security/common/role_mapping.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/*
* 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.
*/

interface RoleMappingAnyRule {
any: RoleMappingRule[];
}

interface RoleMappingAllRule {
all: RoleMappingRule[];
}

interface RoleMappingFieldRule {
field: Record<string, any>;
}

interface RoleMappingExceptRule {
except: RoleMappingRule;
}

type RoleMappingRule =
| RoleMappingAnyRule
| RoleMappingAllRule
| RoleMappingFieldRule
| RoleMappingExceptRule;

type RoleTemplateFormat = 'string' | 'json';

export interface InlineRoleTemplate {
template: { source: string };
format?: RoleTemplateFormat;
}

export interface StoredRoleTemplate {
template: { id: string };
format?: RoleTemplateFormat;
}

export interface InvalidRoleTemplate {
template: string;
format?: RoleTemplateFormat;
}

export type RoleTemplate = InlineRoleTemplate | StoredRoleTemplate | InvalidRoleTemplate;

export interface RoleMapping {
name: string;
enabled: boolean;
roles?: string[];
role_templates?: RoleTemplate[];
rules: RoleMappingRule | {};
metadata: Record<string, any>;
}
58 changes: 58 additions & 0 deletions x-pack/legacy/plugins/security/public/lib/role_mappings_api.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
/*
* 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 { CoreSetup } from 'src/core/public';
import { RoleMapping } from '../../common/model';

interface CheckPrivilegesResponse {
canManageRoleMappings: boolean;
canUseInlineScripts: boolean;
canUseStoredScripts: boolean;
hasCompatibleRealms: boolean;
}

type DeleteRoleMappingsResponse = Array<{
name: string;
success: boolean;
error?: Error;
}>;

export class RoleMappingsAPI {
constructor(private readonly http: CoreSetup['http']) {}

public async getRoleMappingFeatures(): Promise<CheckPrivilegesResponse> {
return this.http.get(`/internal/security/role_mapping_feature_check`);
}

public async getRoleMappings(): Promise<RoleMapping[]> {
return this.http.get(`/internal/security/role_mapping`);
}

public async getRoleMapping(name: string): Promise<RoleMapping> {
return this.http.get(`/internal/security/role_mapping/${encodeURIComponent(name)}`);
}

public async saveRoleMapping(roleMapping: RoleMapping) {
const payload = { ...roleMapping };
delete payload.name;

return this.http.post(
`/internal/security/role_mapping/${encodeURIComponent(roleMapping.name)}`,
{ body: JSON.stringify(payload) }
);
}

public async deleteRoleMappings(names: string[]): Promise<DeleteRoleMappingsResponse> {
return Promise.all(
names.map(name =>
this.http
.delete(`/internal/security/role_mapping/${encodeURIComponent(name)}`)
.then(() => ({ success: true, name }))
.catch(error => ({ success: false, name, error }))
)
);
}
}
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
@import './change_password_form/index';
@import './edit_role/index';
@import './edit_user/index';
@import './edit_user/index';
@import './role_mappings/edit_role_mapping/index';
Original file line number Diff line number Diff line change
Expand Up @@ -86,3 +86,30 @@ export function getApiKeysBreadcrumbs() {
},
];
}

export function getRoleMappingBreadcrumbs() {
return [
MANAGEMENT_BREADCRUMB,
{
text: i18n.translate('xpack.security.roleMapping.breadcrumb', {
defaultMessage: 'Role Mappings',
}),
href: '#/management/security/role_mappings',
},
];
}

export function getEditRoleMappingBreadcrumbs($route: Record<string, any>) {
const { name } = $route.current.params;
return [
...getRoleMappingBreadcrumbs(),
{
text:
name ||
i18n.translate('xpack.security.roleMappings.createBreadcrumb', {
defaultMessage: 'Create',
}),
href: `#/management/security/role_mappings/edit/${name}`,
},
];
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,12 @@ import 'plugins/security/views/management/roles_grid/roles';
import 'plugins/security/views/management/api_keys_grid/api_keys';
import 'plugins/security/views/management/edit_user/edit_user';
import 'plugins/security/views/management/edit_role/index';
import 'plugins/security/views/management/role_mappings/role_mappings_grid';
import 'plugins/security/views/management/role_mappings/edit_role_mapping';
import routes from 'ui/routes';
import { xpackInfo } from 'plugins/xpack_main/services/xpack_info';
import '../../services/shield_user';
import { ROLES_PATH, USERS_PATH, API_KEYS_PATH } from './management_urls';
import { ROLES_PATH, USERS_PATH, API_KEYS_PATH, ROLE_MAPPINGS_PATH } from './management_urls';

import { management } from 'ui/management';
import { i18n } from '@kbn/i18n';
Expand All @@ -38,11 +40,23 @@ routes
resolve: {
securityManagementSection: function(ShieldUser) {
const showSecurityLinks = xpackInfo.get('features.security.showLinks');
const showRoleMappingsManagementLink = xpackInfo.get(
'features.security.showRoleMappingsManagement'
);

function deregisterSecurity() {
management.deregister('security');
}

function deregisterRoleMappingsManagement() {
if (management.hasItem('security')) {
const security = management.getSection('security');
if (security.hasItem('roleMappings')) {
security.deregister('roleMappings');
}
}
}

function ensureSecurityRegistered() {
const registerSecurity = () =>
management.register('security', {
Expand Down Expand Up @@ -88,11 +102,25 @@ routes
url: `#${API_KEYS_PATH}`,
});
}

if (showRoleMappingsManagementLink && !security.hasItem('roleMappings')) {
security.register('roleMappings', {
name: 'securityRoleMappingLink',
order: 30,
display: i18n.translate('xpack.security.management.roleMappingsTitle', {
defaultMessage: 'Role Mappings',
}),
url: `#${ROLE_MAPPINGS_PATH}`,
});
}
}

if (!showSecurityLinks) {
deregisterSecurity();
} else {
if (!showRoleMappingsManagementLink) {
deregisterRoleMappingsManagement();
}
// getCurrent will reject if there is no authenticated user, so we prevent them from seeing the security
// management screens
//
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,5 @@ export const CLONE_ROLES_PATH = `${ROLES_PATH}/clone`;
export const USERS_PATH = `${SECURITY_PATH}/users`;
export const EDIT_USERS_PATH = `${USERS_PATH}/edit`;
export const API_KEYS_PATH = `${SECURITY_PATH}/api_keys`;
export const ROLE_MAPPINGS_PATH = `${SECURITY_PATH}/role_mappings`;
export const EDIT_ROLE_MAPPING_PATH = `${SECURITY_PATH}/role_mappings/edit`;
Loading