[Exploratory view] Update index pattern permission error (#122680)

This commit is contained in:
Shahzad 2022-01-18 15:52:49 +01:00 committed by GitHub
parent bd57aa55b0
commit 5ad36d2a93
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
13 changed files with 96 additions and 13 deletions

View file

@ -59,7 +59,11 @@ export type { IndexPatternsContract, DataViewsContract } from './data_views';
export { IndexPatternsService, DataViewsService } from './data_views';
export type { IndexPatternListItem, DataViewListItem, TimeBasedDataView } from './data_views';
export { IndexPattern, DataView } from './data_views';
export { DuplicateDataViewError, DataViewSavedObjectConflictError } from './errors';
export {
DuplicateDataViewError,
DataViewSavedObjectConflictError,
DataViewInsufficientAccessError,
} from './errors';
export type {
IndexPatternExpressionType,
IndexPatternLoadStartDependencies,

View file

@ -11,7 +11,7 @@ import { argv } from 'yargs';
import Url from 'url';
import cypress from 'cypress';
import { FtrProviderContext } from './ftr_provider_context';
import { createApmUsersAndRoles } from '../scripts/create_apm_users_and_roles/create_apm_users_and_roles';
import { createApmAndObsUsersAndRoles } from '../scripts/create_apm_users_and_roles/create_apm_users_and_roles';
import { esArchiverLoad, esArchiverUnload } from './cypress/tasks/es_archiver';
export async function cypressStart(
@ -27,7 +27,7 @@ export async function cypressStart(
});
// Creates APM users
await createApmUsersAndRoles({
await createApmAndObsUsersAndRoles({
elasticsearch: {
username: config.get('servers.elasticsearch.username'),
password: config.get('servers.elasticsearch.password'),

View file

@ -21,7 +21,7 @@ export interface Kibana {
hostname: string;
}
export async function createApmUsersAndRoles({
export async function createApmAndObsUsersAndRoles({
kibana,
elasticsearch,
}: {
@ -62,6 +62,8 @@ export async function createApmUsersAndRoles({
const users = [
{ username: 'apm_read_user', roles: [KIBANA_READ_ROLE] },
{ username: 'apm_power_user', roles: [KIBANA_POWER_ROLE] },
{ username: 'obs_read_user', roles: [KIBANA_READ_ROLE] },
{ username: 'obs_admin_user', roles: [KIBANA_POWER_ROLE] },
];
// create users

View file

@ -9,7 +9,7 @@
import { argv } from 'yargs';
import { AbortError, isAxiosError } from './helpers/call_kibana';
import { createApmUsersAndRoles } from './create_apm_users_and_roles';
import { createApmAndObsUsersAndRoles } from './create_apm_users_and_roles';
import { getKibanaVersion } from './helpers/get_version';
async function init() {
@ -57,7 +57,7 @@ async function init() {
const version = await getKibanaVersion({ elasticsearch, kibana });
console.log(`Connected to Kibana ${version}`);
const users = await createApmUsersAndRoles({ elasticsearch, kibana });
const users = await createApmAndObsUsersAndRoles({ elasticsearch, kibana });
const credentials = users
.map((u) => ` - ${u.username} / ${esPassword}`)
.join('\n');

View file

@ -31,5 +31,5 @@
],
"ui": true,
"server": true,
"requiredBundles": ["data", "kibanaReact", "kibanaUtils"]
"requiredBundles": ["data", "dataViews", "kibanaReact", "kibanaUtils"]
}

View file

@ -14,6 +14,7 @@ import { ObservabilityPublicPluginsStart } from '../../../../plugin';
import { ObservabilityIndexPatterns } from '../utils/observability_index_patterns';
import { getDataHandler } from '../../../../data_handler';
import { useExploratoryView } from '../contexts/exploratory_view_config';
import { DataViewInsufficientAccessError } from '../../../../../../../../src/plugins/data_views/common';
export interface IndexPatternContext {
loading: boolean;
@ -89,7 +90,10 @@ export function IndexPatternContextProvider({ children }: ProviderProps) {
}
setLoading((prevState) => ({ ...prevState, [dataType]: false }));
} catch (e) {
if ((e as HttpFetchError).body.error === 'Forbidden') {
if (
e instanceof DataViewInsufficientAccessError ||
(e as HttpFetchError).body === 'Forbidden'
) {
setIndexPatternErrors((prevState) => ({ ...prevState, [dataType]: e }));
}
setLoading((prevState) => ({ ...prevState, [dataType]: false }));

View file

@ -89,7 +89,8 @@ export function ReportMetricOptions({ seriesId, series, seriesConfig }: Props) {
// TODO: Add a link to docs to explain how to add index patterns
return (
<EuiText color="danger" className="eui-textNoWrap">
{indexPatternError.body.error === 'Forbidden'
{indexPatternError.body?.error === 'Forbidden' ||
indexPatternError.name === 'DataViewInsufficientAccessError'
? NO_PERMISSIONS
: indexPatternError.body.message}
</EuiText>

View file

@ -0,0 +1,52 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import { journey, step, expect, before } from '@elastic/synthetics';
import { loginToKibana, waitForLoadingToFinish } from './utils';
import { byTestId } from './uptime.journey';
import { callKibana } from '../../../apm/scripts/create_apm_users_and_roles/helpers/call_kibana';
journey('DataViewPermissions', async ({ page, params }) => {
before(async () => {
await waitForLoadingToFinish({ page });
try {
await callKibana({
elasticsearch: { username: 'elastic', password: 'changeme' },
kibana: { hostname: params.kibanaUrl, roleSuffix: '' },
options: {
method: 'DELETE',
url: '/api/saved_objects/index-pattern/synthetics_static_index_pattern_id_heartbeat_?force=false',
},
});
// eslint-disable-next-line no-empty
} catch (e) {}
});
const queryParams = new URLSearchParams({
dateRangeStart: '2021-11-21T22:06:06.502Z',
dateRangeEnd: '2021-11-21T22:10:08.203Z',
}).toString();
const baseUrl = `${params.kibanaUrl}/app/uptime`;
step('Go to uptime', async () => {
await page.goto(`${baseUrl}?${queryParams}`, {
waitUntil: 'networkidle',
});
await loginToKibana({ page, user: { username: 'obs_read_user', password: 'changeme' } });
});
step('Click explore data button', async () => {
await page.click(byTestId('uptimeExploreDataButton'));
await waitForLoadingToFinish({ page });
await page.waitForSelector(`text=${permissionError}`);
expect(await page.$(`text=${permissionError}`)).toBeTruthy();
});
});
const permissionError =
"Unable to create Data View. You don't have the required permission, please contact your admin.";

View file

@ -5,6 +5,7 @@
* 2.0.
*/
export * from './data_view_permissions';
export * from './uptime.journey';
export * from './step_duration.journey';
export * from './alerts';

View file

@ -14,11 +14,18 @@ export async function waitForLoadingToFinish({ page }: { page: Page }) {
}
}
export async function loginToKibana({ page }: { page: Page }) {
await page.fill('[data-test-subj=loginUsername]', 'elastic', {
export async function loginToKibana({
page,
user,
}: {
page: Page;
user?: { username: string; password: string };
}) {
await page.fill('[data-test-subj=loginUsername]', user?.username ?? 'elastic', {
timeout: 60 * 1000,
});
await page.fill('[data-test-subj=loginPassword]', 'changeme');
await page.fill('[data-test-subj=loginPassword]', user?.password ?? 'changeme');
await page.click('[data-test-subj=loginSubmit]');

View file

@ -12,6 +12,7 @@ import { run as playwrightRun } from '@elastic/synthetics';
import { esArchiverLoad, esArchiverUnload } from './tasks/es_archiver';
import './journeys';
import { createApmAndObsUsersAndRoles } from '../../apm/scripts/create_apm_users_and_roles/create_apm_users_and_roles';
const listOfJourneys = [
'uptime',
@ -49,6 +50,11 @@ async function playwrightStart(getService: any, headless = true, match?: string)
port: config.get('servers.kibana.port'),
});
await createApmAndObsUsersAndRoles({
elasticsearch: { username: 'elastic', password: 'changeme' },
kibana: { roleSuffix: 'e2e', hostname: kibanaUrl },
});
const res = await playwrightRun({
params: { kibanaUrl },
playwrightOptions: { headless, chromiumSandbox: false, timeout: 60 * 1000 },

View file

@ -5,5 +5,10 @@
"compilerOptions": {
"outDir": "target/types",
"types": [ "node"],
}
},
"references": [
{
"path": "../../apm/tsconfig.json",
},
]
}

View file

@ -115,6 +115,7 @@ export function ActionMenuContent({ config }: { config: UptimeConfig }): React.R
href={syntheticExploratoryViewLink}
color="text"
iconType="visBarVerticalStacked"
data-test-subj={'uptimeExploreDataButton'}
>
{ANALYZE_DATA}
</EuiHeaderLink>