mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 01:38:56 -04:00
Grant access to machine learning features when base privileges are used (#115444)
This commit is contained in:
parent
1827cf2479
commit
852a728229
8 changed files with 129 additions and 33 deletions
|
@ -96,7 +96,7 @@ export function getPluginPrivileges() {
|
|||
];
|
||||
const privilege = {
|
||||
app: [PLUGIN_ID, 'kibana'],
|
||||
excludeFromBasePrivileges: true,
|
||||
excludeFromBasePrivileges: false,
|
||||
management: {
|
||||
insightsAndAlerting: ['jobsListLink'],
|
||||
},
|
||||
|
|
|
@ -64,7 +64,7 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) {
|
|||
expect(sections).to.have.length(2);
|
||||
expect(sections[0]).to.eql({
|
||||
sectionId: 'insightsAndAlerting',
|
||||
sectionLinks: ['triggersActions'],
|
||||
sectionLinks: ['triggersActions', 'jobsListLink'],
|
||||
});
|
||||
expect(sections[1]).to.eql({
|
||||
sectionId: 'kibana',
|
||||
|
|
|
@ -77,9 +77,9 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) {
|
|||
await security.user.delete('global_all');
|
||||
});
|
||||
|
||||
it(`doesn't show ml navlink`, async () => {
|
||||
it(`shows ml navlink`, async () => {
|
||||
const navLinks = (await appsMenu.readLinks()).map((link) => link.text);
|
||||
expect(navLinks).not.to.contain('Machine Learning');
|
||||
expect(navLinks).to.contain('Machine Learning');
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -103,5 +103,75 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) {
|
|||
expect(navLinks).to.contain('Machine Learning');
|
||||
});
|
||||
});
|
||||
|
||||
describe('ml read', () => {
|
||||
before(async () => {
|
||||
await security.role.create('ml_role_read', {
|
||||
elasticsearch: {
|
||||
indices: [{ names: ['logstash-*'], privileges: ['read', 'view_index_metadata'] }],
|
||||
},
|
||||
kibana: [
|
||||
{
|
||||
base: [],
|
||||
feature: { ml: ['read'], savedObjectsManagement: ['read'] },
|
||||
spaces: ['*'],
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
await security.user.create('ml_read_user', {
|
||||
password: 'ml_read-password',
|
||||
roles: ['ml_role_read'],
|
||||
full_name: 'ml read',
|
||||
});
|
||||
|
||||
await PageObjects.security.login('ml_read_user', 'ml_read-password');
|
||||
});
|
||||
|
||||
after(async () => {
|
||||
await security.role.delete('ml_role_read');
|
||||
await security.user.delete('ml_read_user');
|
||||
});
|
||||
|
||||
it('shows ML navlink', async () => {
|
||||
const navLinks = (await appsMenu.readLinks()).map((link) => link.text);
|
||||
expect(navLinks).to.contain('Machine Learning');
|
||||
});
|
||||
});
|
||||
|
||||
describe('ml none', () => {
|
||||
before(async () => {
|
||||
await security.role.create('ml_role_none', {
|
||||
elasticsearch: {
|
||||
indices: [{ names: ['logstash-*'], privileges: ['read', 'view_index_metadata'] }],
|
||||
},
|
||||
kibana: [
|
||||
{
|
||||
base: [],
|
||||
feature: { discover: ['read'] },
|
||||
spaces: ['*'],
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
await security.user.create('ml_none_user', {
|
||||
password: 'ml_none-password',
|
||||
roles: ['ml_role_none'],
|
||||
full_name: 'ml none',
|
||||
});
|
||||
|
||||
await PageObjects.security.login('ml_none_user', 'ml_none-password');
|
||||
});
|
||||
|
||||
after(async () => {
|
||||
await security.role.delete('ml_role_none');
|
||||
await security.user.delete('ml_none_user');
|
||||
});
|
||||
|
||||
it('does NOT show ML navlink', async () => {
|
||||
const navLinks = (await appsMenu.readLinks()).map((link) => link.text);
|
||||
expect(navLinks).to.not.contain('Machine Learning');
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
|
@ -13,10 +13,7 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) {
|
|||
const PageObjects = getPageObjects(['common', 'error']);
|
||||
const ml = getService('ml');
|
||||
|
||||
const testUsers = [
|
||||
{ user: USER.ML_UNAUTHORIZED, discoverAvailable: true },
|
||||
{ user: USER.ML_UNAUTHORIZED_SPACES, discoverAvailable: true },
|
||||
];
|
||||
const testUsers = [{ user: USER.ML_UNAUTHORIZED, discoverAvailable: true }];
|
||||
|
||||
describe('for user with no ML access', function () {
|
||||
this.tags(['skipFirefox', 'mlqa']);
|
||||
|
|
|
@ -21,7 +21,6 @@ export enum USER {
|
|||
ML_VIEWER_SPACE1 = 'ft_ml_viewer_space1',
|
||||
ML_VIEWER_ALL_SPACES = 'ft_ml_viewer_all_spaces',
|
||||
ML_UNAUTHORIZED = 'ft_ml_unauthorized',
|
||||
ML_UNAUTHORIZED_SPACES = 'ft_ml_unauthorized_spaces',
|
||||
}
|
||||
|
||||
export function MachineLearningSecurityCommonProvider({ getService }: FtrProviderContext) {
|
||||
|
@ -90,8 +89,7 @@ export function MachineLearningSecurityCommonProvider({ getService }: FtrProvide
|
|||
elasticsearch: { cluster: [], indices: [], run_as: [] },
|
||||
kibana: [
|
||||
{
|
||||
base: [],
|
||||
feature: { ml: ['all'], savedObjectsManagement: ['all'] },
|
||||
base: ['all'],
|
||||
spaces: ['*'],
|
||||
},
|
||||
],
|
||||
|
@ -123,8 +121,7 @@ export function MachineLearningSecurityCommonProvider({ getService }: FtrProvide
|
|||
elasticsearch: { cluster: [], indices: [], run_as: [] },
|
||||
kibana: [
|
||||
{
|
||||
base: [],
|
||||
feature: { ml: ['read'], savedObjectsManagement: ['read'] },
|
||||
base: ['read'],
|
||||
spaces: ['*'],
|
||||
},
|
||||
],
|
||||
|
@ -134,6 +131,31 @@ export function MachineLearningSecurityCommonProvider({ getService }: FtrProvide
|
|||
elasticsearch: { cluster: [], indices: [], run_as: [] },
|
||||
kibana: [{ base: [], feature: { discover: ['read'] }, spaces: ['default'] }],
|
||||
},
|
||||
{
|
||||
name: 'ft_all_space_ml_none',
|
||||
elasticsearch: { cluster: [], indices: [], run_as: [] },
|
||||
kibana: [
|
||||
{
|
||||
base: [],
|
||||
// This role is intended to be used by the "ft_ml_poweruser" and "ft_ml_viewer" users; they should have access to ML by virtue of
|
||||
// the "machine_learning_admin" and "machine_learning_user" roles. However, a user needs _at least_ one Kibana privilege to log
|
||||
// into Kibana. This role allows these users to log in, but explicitly omits ML from the feature privileges.
|
||||
// In addition: several functional tests that use these users also rely on UI elements that are enabled by other Kibana features,
|
||||
// such as "View in Lens", "Add to Dashboard", and creating anomaly detection rules. These feature privileges are the minimal ones
|
||||
// necessary to satisfy all of those functional tests.
|
||||
feature: {
|
||||
discover: ['read'],
|
||||
visualize: ['read'],
|
||||
dashboard: ['all'],
|
||||
actions: ['all'],
|
||||
savedObjectsManagement: ['all'],
|
||||
advancedSettings: ['all'],
|
||||
indexPatterns: ['all'],
|
||||
},
|
||||
spaces: ['*'],
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
const users = [
|
||||
|
@ -142,7 +164,7 @@ export function MachineLearningSecurityCommonProvider({ getService }: FtrProvide
|
|||
full_name: 'ML Poweruser',
|
||||
password: 'mlp001',
|
||||
roles: [
|
||||
'kibana_admin',
|
||||
'ft_all_space_ml_none',
|
||||
'machine_learning_admin',
|
||||
'ft_ml_source',
|
||||
'ft_ml_dest',
|
||||
|
@ -172,7 +194,7 @@ export function MachineLearningSecurityCommonProvider({ getService }: FtrProvide
|
|||
full_name: 'ML Viewer',
|
||||
password: 'mlv001',
|
||||
roles: [
|
||||
'kibana_admin',
|
||||
'ft_all_space_ml_none',
|
||||
'machine_learning_user',
|
||||
'ft_ml_source_readonly',
|
||||
'ft_ml_dest_readonly',
|
||||
|
@ -200,12 +222,6 @@ export function MachineLearningSecurityCommonProvider({ getService }: FtrProvide
|
|||
name: 'ft_ml_unauthorized',
|
||||
full_name: 'ML Unauthorized',
|
||||
password: 'mlu001',
|
||||
roles: ['kibana_admin', 'ft_ml_source_readonly'],
|
||||
},
|
||||
{
|
||||
name: 'ft_ml_unauthorized_spaces',
|
||||
full_name: 'ML Unauthorized',
|
||||
password: 'mlus001',
|
||||
roles: ['ft_default_space_ml_none', 'ft_ml_source_readonly'],
|
||||
},
|
||||
];
|
||||
|
|
|
@ -13,10 +13,7 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) {
|
|||
const PageObjects = getPageObjects(['common', 'error']);
|
||||
const ml = getService('ml');
|
||||
|
||||
const testUsers = [
|
||||
{ user: USER.ML_UNAUTHORIZED, discoverAvailable: true },
|
||||
{ user: USER.ML_UNAUTHORIZED_SPACES, discoverAvailable: true },
|
||||
];
|
||||
const testUsers = [{ user: USER.ML_UNAUTHORIZED, discoverAvailable: true }];
|
||||
|
||||
describe('for user with no ML access', function () {
|
||||
for (const testUser of testUsers) {
|
||||
|
|
|
@ -46,12 +46,10 @@ export default function catalogueTests({ getService }: FtrProviderContext) {
|
|||
case 'dual_privileges_all at everything_space': {
|
||||
expect(uiCapabilities.success).to.be(true);
|
||||
expect(uiCapabilities.value).to.have.property('catalogue');
|
||||
// everything except ml, monitoring, and ES features are enabled
|
||||
// everything except monitoring, and ES features are enabled
|
||||
const expected = mapValues(
|
||||
uiCapabilities.value!.catalogue,
|
||||
(enabled, catalogueId) =>
|
||||
catalogueId !== 'ml' &&
|
||||
catalogueId !== 'ml_file_data_visualizer' &&
|
||||
catalogueId !== 'monitoring' &&
|
||||
catalogueId !== 'osquery' &&
|
||||
!esFeatureExceptions.includes(catalogueId)
|
||||
|
@ -59,16 +57,35 @@ export default function catalogueTests({ getService }: FtrProviderContext) {
|
|||
expect(uiCapabilities.value!.catalogue).to.eql(expected);
|
||||
break;
|
||||
}
|
||||
case 'everything_space_all at everything_space':
|
||||
case 'everything_space_all at everything_space': {
|
||||
expect(uiCapabilities.success).to.be(true);
|
||||
expect(uiCapabilities.value).to.have.property('catalogue');
|
||||
// everything except spaces, monitoring, the enterprise search suite, and ES features are enabled
|
||||
// (easier to say: all "proper" Kibana features are enabled)
|
||||
const exceptions = [
|
||||
'monitoring',
|
||||
'enterpriseSearch',
|
||||
'appSearch',
|
||||
'workplaceSearch',
|
||||
'spaces',
|
||||
'osquery',
|
||||
...esFeatureExceptions,
|
||||
];
|
||||
const expected = mapValues(
|
||||
uiCapabilities.value!.catalogue,
|
||||
(enabled, catalogueId) => !exceptions.includes(catalogueId)
|
||||
);
|
||||
expect(uiCapabilities.value!.catalogue).to.eql(expected);
|
||||
break;
|
||||
}
|
||||
case 'global_read at everything_space':
|
||||
case 'dual_privileges_read at everything_space':
|
||||
case 'everything_space_read at everything_space': {
|
||||
expect(uiCapabilities.success).to.be(true);
|
||||
expect(uiCapabilities.value).to.have.property('catalogue');
|
||||
// everything except spaces, ml, monitoring, the enterprise search suite, and ES features are enabled
|
||||
// everything except spaces, ml_file_data_visualizer, monitoring, the enterprise search suite, and ES features are enabled
|
||||
// (easier to say: all "proper" Kibana features are enabled)
|
||||
const exceptions = [
|
||||
'ml',
|
||||
'ml_file_data_visualizer',
|
||||
'monitoring',
|
||||
'enterpriseSearch',
|
||||
|
|
|
@ -42,7 +42,7 @@ export default function navLinksTests({ getService }: FtrProviderContext) {
|
|||
expect(uiCapabilities.success).to.be(true);
|
||||
expect(uiCapabilities.value).to.have.property('navLinks');
|
||||
expect(uiCapabilities.value!.navLinks).to.eql(
|
||||
navLinksBuilder.except('ml', 'monitoring', 'osquery')
|
||||
navLinksBuilder.except('monitoring', 'osquery')
|
||||
);
|
||||
break;
|
||||
case 'everything_space_all at everything_space':
|
||||
|
@ -53,7 +53,6 @@ export default function navLinksTests({ getService }: FtrProviderContext) {
|
|||
expect(uiCapabilities.value).to.have.property('navLinks');
|
||||
expect(uiCapabilities.value!.navLinks).to.eql(
|
||||
navLinksBuilder.except(
|
||||
'ml',
|
||||
'monitoring',
|
||||
'enterpriseSearch',
|
||||
'appSearch',
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue