[APM] Remove mentions of apm_user (#132790)

This commit is contained in:
Søren Louv-Jansen 2022-05-25 12:07:00 +02:00 committed by GitHub
parent 06a98d7844
commit c1b77b93b6
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
44 changed files with 149 additions and 418 deletions

View file

@ -125,9 +125,9 @@ Here are two examples:
<titleabbrev>Create an annotation user</titleabbrev>
++++
NOTE: By default, the `apm_user` built-in role provides access to Observability annotations.
You only need to create an annotation user if the default annotation index
defined in <<apm-settings-kb,`xpack.observability.annotations.index`>> has been customized.
NOTE: By default, the `viewer` and `editor` built-in roles provide read access to Observability annotations.
You only need to create an annotation user to write to the annotations index
(<<apm-settings-kb,`xpack.observability.annotations.index`>>).
[[apm-app-annotation-user]]
==== Annotation user

View file

@ -16,22 +16,25 @@ To access an Elasticsearch instance that has live data you have three options:
**Start Elasticsearch & Kibana**
Elasticsearch:
```
yarn es snapshot
```
Kibana:
```
yarn start
```
**Run Synthtrace**
```
node packages/elastic-apm-synthtrace/src/scripts/run packages/elastic-apm-synthtrace/src/scripts/examples/01_simple_trace.ts \
--local
```
The `--local` flag is a shortcut to specifying `--target` and `--kibana`. It autodiscovers the current kibana basepath and installs the appropiate APM package.
The `--local` flag is a shortcut to specifying `--target` and `--kibana`. It autodiscovers the current kibana basepath and installs the appropiate APM package.
**Connect Kibana to ES**
Update `config/kibana.dev.yml` with:
@ -61,7 +64,9 @@ node packages/elastic-apm-synthtrace/src/scripts/run packages/elastic-apm-syntht
## 3. Local ES Cluster
### Start Elasticsearch and APM data generators
_Docker Compose is required_
```
git clone git@github.com:elastic/apm-integration-testing.git
cd apm-integration-testing/
@ -80,16 +85,16 @@ elasticsearch.password: changeme
# Setup default APM users
APM behaves differently depending on which the role and permissions a logged in user has. To create the users run:
APM behaves differently depending on which role and permissions a logged in user has. To create APM users run:
```sh
node x-pack/plugins/apm/scripts/create_apm_users_and_roles.js --username admin --password changeme --kibana-url http://localhost:5601 --role-suffix <github-username-or-something-unique>
node x-pack/plugins/apm/scripts/create_apm_users.js --username admin --password changeme --kibana-url http://localhost:5601
```
This will create:
- **apm_read_user**: Read only user
- **apm_power_user**: Read+write user.
- **viewer_user**: User with `viewer` role (read-only)
- **editor_user**: User with `editor` role (read/write)
# Debugging Elasticsearch queries

View file

@ -18,47 +18,47 @@ open target/coverage/jest/index.html
## API Tests
API tests are separated in two suites:
| Option | Description |
| --------- | ----------------------------------------------- |
| --basic | Run tests with basic license |
| --trial | Run tests with trial license |
| --server | Only start ES and Kibana |
| --runner | Only run tests |
| --grep | Specify the spec files to run |
| --inspect | Add --inspect-brk flag to the ftr for debugging |
| --times | Repeat the test n number of times |
- a basic license test suite [default]
- a trial license test suite (the equivalent of gold+)
The API tests are located in [`x-pack/test/apm_api_integration/`](/x-pack/test/apm_api_integration/).
### Run tests with [--trial] license
### Start server and run test in a single process
```
node scripts/test/api [--trial] [--help]
node scripts/test/api [--trial/--basic] [--help]
```
The above command will initiate an Elasticsearch instance on http://localhost:9220 and a kibana instance on http://localhost:5620 and will run the api test against these environments.
The above command will start an ES instance on http://localhost:9220, a Kibana instance on http://localhost:5620 and run the api tests.
Once the tests finish, the instances will be terminated.
### Start test server
### Start server and run test in separate processes
```sh
# start server
node scripts/test/api --server --basic
# run tests
node scripts/test/api --runner --basic
```
node scripts/test/api --server
```
Start Elasticsearch and Kibana instances.
### Run all tests
```
node scripts/test/api --runner
```
Run all tests. The test server needs to be running, see [Start Test Server](#start-test-server).
### Update snapshots (from Kibana root)
To update snapshots append `--updateSnapshots` to the `functional_test_runner` command
To update snapshots append `--updateSnapshots` to the `--runner` command:
```
node scripts/functional_test_runner --config x-pack/test/apm_api_integration/[basic | trial]/config.ts --quiet --updateSnapshots
node scripts/test/api --runner --basic --updateSnapshots
```
The test server needs to be running, see [Start Test Server](#start-test-server).
The API tests are located in [`x-pack/test/apm_api_integration/`](/x-pack/test/apm_api_integration/).
(The test server needs to be running)
**API Test tips**

View file

@ -30,7 +30,7 @@ describe('Comparison feature flag', () => {
});
beforeEach(() => {
cy.loginAsPowerUser();
cy.loginAsEditorUser();
});
describe('when comparison feature is enabled', () => {

View file

@ -32,7 +32,7 @@ describe('Infrastracture feature flag', () => {
});
beforeEach(() => {
cy.loginAsPowerUser();
cy.loginAsEditorUser();
});
describe('when infrastracture feature is disabled', () => {

View file

@ -56,7 +56,7 @@ describe('when navigating to integration page', () => {
beforeEach(() => {
const integrationsPath = '/app/integrations/browse';
cy.loginAsPowerUser();
cy.loginAsEditorUser();
cy.visit(integrationsPath);
// open integration policy form

View file

@ -10,7 +10,7 @@ const apmIndicesSaveURL = '/internal/apm/settings/apm-indices/save';
describe('No data screen', () => {
describe('bypass no data screen on settings pages', () => {
beforeEach(() => {
cy.loginAsPowerUser();
cy.loginAsEditorUser();
});
before(() => {
@ -29,7 +29,7 @@ describe('No data screen', () => {
headers: {
'kbn-xsrf': true,
},
auth: { user: 'apm_power_user', pass: 'changeme' },
auth: { user: 'editor_user', pass: 'changeme' },
});
});
@ -57,7 +57,7 @@ describe('No data screen', () => {
metric: '',
},
headers: { 'kbn-xsrf': true },
auth: { user: 'apm_power_user', pass: 'changeme' },
auth: { user: 'editor_user', pass: 'changeme' },
});
});
});

View file

@ -37,7 +37,7 @@ describe('Rules', () => {
describe('when created from APM', () => {
describe('when created from Service Inventory', () => {
before(() => {
cy.loginAsPowerUser();
cy.loginAsEditorUser();
deleteAllRules();
});
@ -68,7 +68,7 @@ describe('Rules', () => {
describe('when created from Stack management', () => {
before(() => {
cy.loginAsPowerUser();
cy.loginAsEditorUser();
deleteAllRules();
});

View file

@ -72,7 +72,7 @@ describe('Agent configuration', () => {
});
beforeEach(() => {
cy.loginAsPowerUser();
cy.loginAsEditorUser();
cy.visit(agentConfigHref);
});

View file

@ -9,7 +9,7 @@ const basePath = '/app/apm/settings/custom-links';
describe('Custom links', () => {
beforeEach(() => {
cy.loginAsPowerUser();
cy.loginAsEditorUser();
});
it('shows empty message and create button', () => {

View file

@ -7,7 +7,7 @@
describe('APM deep links', () => {
before(() => {
cy.loginAsReadOnlyUser();
cy.loginAsViewerUser();
});
it('navigates to apm links on search elastic', () => {
cy.visit('/');

View file

@ -31,7 +31,7 @@ describe('Dependencies', () => {
});
beforeEach(() => {
cy.loginAsReadOnlyUser();
cy.loginAsViewerUser();
});
describe('top-level dependencies page', () => {

View file

@ -23,7 +23,7 @@ const errorDetailsPageHref = url.format({
describe('Error details', () => {
beforeEach(() => {
cy.loginAsReadOnlyUser();
cy.loginAsViewerUser();
});
describe('when data is loaded', () => {

View file

@ -25,7 +25,7 @@ const nodeServiceErrorsPageHref = url.format({
describe('Errors page', () => {
beforeEach(() => {
cy.loginAsReadOnlyUser();
cy.loginAsViewerUser();
});
describe('when data is loaded', () => {

View file

@ -38,7 +38,7 @@ describe.skip('Home page', () => {
});
beforeEach(() => {
cy.loginAsReadOnlyUser();
cy.loginAsViewerUser();
});
it('Redirects to service page with comparisonEnabled, environment, rangeFrom, rangeTo and offset added to the URL', () => {

View file

@ -35,7 +35,7 @@ describe('Service inventory - header filters', () => {
});
beforeEach(() => {
cy.loginAsReadOnlyUser();
cy.loginAsViewerUser();
});
describe('Filtering by kuerybar', () => {

View file

@ -44,7 +44,7 @@ const mainAliasNames = mainApiRequestsToIntercept.map(
describe('When navigating to the service inventory', () => {
before(async () => {
cy.loginAsReadOnlyUser();
cy.loginAsViewerUser();
cy.visit(serviceInventoryHref);
const { rangeFrom, rangeTo } = timeRange;
@ -90,7 +90,7 @@ describe('When navigating to the service inventory', () => {
}
);
cy.loginAsReadOnlyUser();
cy.loginAsViewerUser();
cy.visit(serviceInventoryHref);
});

View file

@ -37,7 +37,7 @@ describe('Service overview - aws lambda', () => {
});
beforeEach(() => {
cy.loginAsReadOnlyUser();
cy.loginAsViewerUser();
});
it('displays a cold start rate chart and not a transaction breakdown chart', () => {

View file

@ -32,7 +32,7 @@ describe('Errors table', () => {
});
beforeEach(() => {
cy.loginAsReadOnlyUser();
cy.loginAsViewerUser();
});
it('errors table is populated', () => {

View file

@ -71,7 +71,7 @@ describe('Service overview - header filters', () => {
describe('Filtering by transaction type', () => {
beforeEach(() => {
cy.loginAsReadOnlyUser();
cy.loginAsViewerUser();
});
it('changes url when selecting different value', () => {
cy.visit(serviceOverviewHref);
@ -119,7 +119,7 @@ describe('Service overview - header filters', () => {
describe('Filtering by kuerybar', () => {
beforeEach(() => {
cy.loginAsReadOnlyUser();
cy.loginAsViewerUser();
});
it('filters by transaction.name', () => {
cy.visit(

View file

@ -38,7 +38,7 @@ const apisToIntercept = [
describe('Instances table', () => {
beforeEach(() => {
cy.loginAsReadOnlyUser();
cy.loginAsViewerUser();
});
// describe('when data is not loaded', () => {

View file

@ -101,7 +101,7 @@ describe('Service Overview', () => {
describe('renders', () => {
before(() => {
cy.loginAsReadOnlyUser();
cy.loginAsViewerUser();
cy.visit(baseUrl);
});
@ -121,7 +121,7 @@ describe('Service Overview', () => {
describe('transactions', () => {
beforeEach(() => {
cy.loginAsReadOnlyUser();
cy.loginAsViewerUser();
cy.visit(baseUrl);
});
@ -174,7 +174,7 @@ describe('Service Overview', () => {
describe('when RUM service', () => {
before(() => {
cy.loginAsReadOnlyUser();
cy.loginAsViewerUser();
cy.visit(
url.format({
pathname: '/app/apm/services/opbeans-rum/overview',
@ -203,7 +203,7 @@ describe('Service Overview', () => {
describe('Calls APIs', () => {
beforeEach(() => {
cy.loginAsReadOnlyUser();
cy.loginAsViewerUser();
cy.visit(baseUrl);
apiRequestsToIntercept.map(({ endpoint, aliasName }) => {
cy.intercept('GET', endpoint).as(aliasName);

View file

@ -65,7 +65,7 @@ describe.skip('Service overview: Time Comparison', () => {
});
beforeEach(() => {
cy.loginAsReadOnlyUser();
cy.loginAsViewerUser();
});
it('enables by default the time comparison feature with Last 24 hours selected', () => {

View file

@ -30,7 +30,7 @@ function getServiceInventoryUrl({ serviceName }: { serviceName: string }) {
describe('Span links', () => {
beforeEach(() => {
cy.loginAsReadOnlyUser();
cy.loginAsViewerUser();
});
describe('when data is loaded', () => {

View file

@ -33,7 +33,7 @@ describe('Transactions Overview', () => {
});
beforeEach(() => {
cy.loginAsReadOnlyUser();
cy.loginAsViewerUser();
});
it('has no detectable a11y violations on load', () => {

View file

@ -10,12 +10,12 @@ import 'cypress-axe';
import moment from 'moment';
import { AXE_CONFIG, AXE_OPTIONS } from '@kbn/axe-config';
Cypress.Commands.add('loginAsReadOnlyUser', () => {
cy.loginAs({ username: 'apm_read_user', password: 'changeme' });
Cypress.Commands.add('loginAsViewerUser', () => {
cy.loginAs({ username: 'viewer_user', password: 'changeme' });
});
Cypress.Commands.add('loginAsPowerUser', () => {
cy.loginAs({ username: 'apm_power_user', password: 'changeme' });
Cypress.Commands.add('loginAsEditorUser', () => {
cy.loginAs({ username: 'editor_user', password: 'changeme' });
});
Cypress.Commands.add(

View file

@ -7,8 +7,8 @@
declare namespace Cypress {
interface Chainable {
loginAsReadOnlyUser(): void;
loginAsPowerUser(): void;
loginAsViewerUser(): void;
loginAsEditorUser(): void;
loginAs(params: { username: string; password: string }): void;
changeTimeRange(value: string): void;
selectAbsoluteTimeRange(start: string, end: string): void;

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 { createApmAndObsUsersAndRoles } from '../scripts/create_apm_users_and_roles/create_apm_users_and_roles';
import { createApmUsers } from '../scripts/create_apm_users/create_apm_users';
import { esArchiverLoad, esArchiverUnload } from './cypress/tasks/es_archiver';
export async function cypressStart(
@ -27,14 +27,13 @@ export async function cypressStart(
});
// Creates APM users
await createApmAndObsUsersAndRoles({
await createApmUsers({
elasticsearch: {
username: config.get('servers.elasticsearch.username'),
password: config.get('servers.elasticsearch.password'),
},
kibana: {
hostname: kibanaUrl,
roleSuffix: 'e2e_tests',
},
});

View file

@ -0,0 +1,20 @@
/*
* 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.
*/
/*
* This script will create two users
* - editor_user
* - viewer_user
*
* Usage: node create-apm-users.js
******************************/
// compile typescript on the fly
// eslint-disable-next-line import/no-extraneous-dependencies
require('@kbn/optimizer').registerNodeAutoTranspilation();
require('./create_apm_users/create_apm_users_cli');

View file

@ -6,9 +6,6 @@
*/
import { AbortError, callKibana } from './helpers/call_kibana';
import { createRole } from './helpers/create_role';
import { powerUserRole } from './roles/power_user_role';
import { readOnlyUserRole } from './roles/read_only_user_role';
import { createOrUpdateUser } from './helpers/create_or_update_user';
export interface Elasticsearch {
@ -17,11 +14,10 @@ export interface Elasticsearch {
}
export interface Kibana {
roleSuffix: string;
hostname: string;
}
export async function createApmAndObsUsersAndRoles({
export async function createApmUsers({
kibana,
elasticsearch,
}: {
@ -44,26 +40,10 @@ export async function createApmAndObsUsersAndRoles({
throw new AbortError('Security must be enabled!');
}
const KIBANA_READ_ROLE = `kibana_read_${kibana.roleSuffix}`;
const KIBANA_POWER_ROLE = `kibana_power_${kibana.roleSuffix}`;
// roles definition
const roles = [
{ roleName: KIBANA_READ_ROLE, role: readOnlyUserRole },
{ roleName: KIBANA_POWER_ROLE, role: powerUserRole },
];
// create roles
await Promise.all(
roles.map(async (role) => createRole({ elasticsearch, kibana, ...role }))
);
// user definitions
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] },
{ username: 'viewer_user', roles: ['viewer'] },
{ username: 'editor_user', roles: ['editor'] },
];
// create users

View file

@ -9,14 +9,13 @@
import { argv } from 'yargs';
import { AbortError, isAxiosError } from './helpers/call_kibana';
import { createApmAndObsUsersAndRoles } from './create_apm_users_and_roles';
import { createApmUsers } from './create_apm_users';
import { getKibanaVersion } from './helpers/get_version';
async function init() {
const esUserName = (argv.username as string) || 'elastic';
const esPassword = argv.password as string | undefined;
const kibanaBaseUrl = argv.kibanaUrl as string | undefined;
const kibanaRoleSuffix = argv.roleSuffix as string | undefined;
if (!esPassword) {
console.error(
@ -42,14 +41,7 @@ async function init() {
process.exit();
}
if (!kibanaRoleSuffix) {
console.error(
'Please specify a unique suffix that will be added to your roles with `--role-suffix <suffix>` '
);
process.exit();
}
const kibana = { roleSuffix: kibanaRoleSuffix, hostname: kibanaBaseUrl };
const kibana = { hostname: kibanaBaseUrl };
const elasticsearch = { username: esUserName, password: esPassword };
console.log({ kibana, elasticsearch });
@ -57,7 +49,7 @@ async function init() {
const version = await getKibanaVersion({ elasticsearch, kibana });
console.log(`Connected to Kibana ${version}`);
const users = await createApmAndObsUsersAndRoles({ elasticsearch, kibana });
const users = await createApmUsers({ elasticsearch, kibana });
const credentials = users
.map((u) => ` - ${u.username} / ${esPassword}`)
.join('\n');

View file

@ -6,7 +6,7 @@
*/
import axios, { AxiosRequestConfig, AxiosError } from 'axios';
import { once } from 'lodash';
import { Elasticsearch, Kibana } from '../create_apm_users_and_roles';
import { Elasticsearch, Kibana } from '../create_apm_users';
export async function callKibana<T>({
elasticsearch,

View file

@ -8,7 +8,7 @@
/* eslint-disable no-console */
import { difference, union } from 'lodash';
import { Elasticsearch, Kibana } from '../create_apm_users_and_roles';
import { Elasticsearch, Kibana } from '../create_apm_users';
import { callKibana, isAxiosError } from './call_kibana';
interface User {

View file

@ -5,7 +5,7 @@
* 2.0.
*/
import { Elasticsearch, Kibana } from '../create_apm_users_and_roles';
import { Elasticsearch, Kibana } from '../create_apm_users';
import { AbortError } from './call_kibana';
import { callKibana, isAxiosError } from './call_kibana';

View file

@ -1,23 +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
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
/*
* This script will create two roles
* - a read_only kibana role
* - a read/write kibana role
*
* The two roles will be assigned to the already existing users: `apm_read_user`, `apm_write_user`, `kibana_write_user`
*
* This makes it possible to use the existing cloud users locally
* Usage: node create-apm-users-and-roles.js --role-suffix <YOUR-GITHUB-USERNAME-OR-SOMETHING-UNIQUE>
******************************/
// compile typescript on the fly
// eslint-disable-next-line import/no-extraneous-dependencies
require('@kbn/optimizer').registerNodeAutoTranspilation();
require('./create_apm_users_and_roles/create_apm_users_and_roles_cli');

View file

@ -1,84 +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
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
/* eslint-disable no-console */
import { Role } from '@kbn/security-plugin/common/model';
import { callKibana, isAxiosError } from './call_kibana';
import { Elasticsearch, Kibana } from '../create_apm_users_and_roles';
type Privilege = [] | ['read'] | ['all'];
export interface KibanaPrivileges {
base?: Privilege;
feature?: Record<string, Privilege>;
}
export type RoleType = Omit<Role, 'name' | 'metadata'>;
export async function createRole({
elasticsearch,
kibana,
roleName,
role,
}: {
elasticsearch: Elasticsearch;
kibana: Kibana;
roleName: string;
role: RoleType;
}) {
const roleFound = await getRole({
elasticsearch,
kibana,
roleName,
});
if (roleFound) {
console.log(`Skipping: Role "${roleName}" already exists`);
return Promise.resolve();
}
await callKibana({
elasticsearch,
kibana,
options: {
method: 'PUT',
url: `/api/security/role/${roleName}`,
data: {
metadata: { version: 1 },
...role,
},
},
});
console.log(`Created role "${roleName}"`);
}
async function getRole({
elasticsearch,
kibana,
roleName,
}: {
elasticsearch: Elasticsearch;
kibana: Kibana;
roleName: string;
}): Promise<Role | null> {
try {
return await callKibana({
elasticsearch,
kibana,
options: {
method: 'GET',
url: `/api/security/role/${roleName}`,
},
});
} catch (e) {
// return empty if role doesn't exist
if (isAxiosError(e) && e.response?.status === 404) {
return null;
}
throw e;
}
}

View file

@ -1,76 +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
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import { RoleType } from '../helpers/create_role';
export const powerUserRole: RoleType = {
elasticsearch: {
run_as: [],
cluster: [],
indices: [
// apm
{
names: ['apm-*', 'logs-apm*', 'metrics-apm*', 'traces-apm*'],
privileges: ['read', 'view_index_metadata'],
},
{
names: ['observability-annotations'],
privileges: ['read', 'write', 'view_index_metadata'],
},
// logs
{
names: ['logs-*', 'filebeat-*', 'kibana_sample_data_logs*'],
privileges: ['read', 'view_index_metadata'],
},
// metrics
{
names: ['metrics-*', 'metricbeat-*'],
privileges: ['read', 'view_index_metadata'],
},
// uptime
{
names: ['heartbeat-*', 'synthetics-*'],
privileges: ['read', 'view_index_metadata'],
},
],
},
kibana: [
{
base: [],
feature: {
// core
discover: ['all'],
dashboard: ['all'],
canvas: ['all'],
ml: ['all'],
maps: ['all'],
graph: ['all'],
visualize: ['all'],
// observability
logs: ['all'],
infrastructure: ['all'],
apm: ['all'],
uptime: ['all'],
// security
siem: ['all'],
// management
dev_tools: ['all'],
advancedSettings: ['all'],
indexPatterns: ['all'],
savedObjectsManagement: ['all'],
stackAlerts: ['all'],
fleet: ['all'],
fleetv2: ['all'],
actions: ['all'],
},
spaces: ['*'],
},
],
};

View file

@ -1,77 +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
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import { RoleType } from '../helpers/create_role';
export const readOnlyUserRole: RoleType = {
elasticsearch: {
run_as: [],
cluster: [],
indices: [
// apm
{
names: [
'apm-*',
'logs-apm*',
'metrics-apm*',
'traces-apm*',
'observability-annotations',
],
privileges: ['read', 'view_index_metadata'],
},
// logs
{
names: ['logs-*', 'filebeat-*', 'kibana_sample_data_logs*'],
privileges: ['read', 'view_index_metadata'],
},
// metrics
{
names: ['metrics-*', 'metricbeat-*'],
privileges: ['read', 'view_index_metadata'],
},
// uptime
{
names: ['heartbeat-*', 'synthetics-*'],
privileges: ['read', 'view_index_metadata'],
},
],
},
kibana: [
{
base: [],
feature: {
// core
discover: ['read'],
dashboard: ['read'],
canvas: ['read'],
ml: ['read'],
maps: ['read'],
graph: ['read'],
visualize: ['read'],
// observability
logs: ['read'],
infrastructure: ['read'],
apm: ['read'],
uptime: ['read'],
// security
siem: ['read'],
// management
dev_tools: ['read'],
advancedSettings: ['read'],
indexPatterns: ['read'],
savedObjectsManagement: ['read'],
stackAlerts: ['read'],
fleet: ['read'],
actions: ['read'],
},
spaces: ['*'],
},
],
};

View file

@ -13,7 +13,7 @@ const childProcess = require('child_process');
const { argv } = yargs(process.argv.slice(2))
.option('basic', {
default: true,
default: false,
type: 'boolean',
description: 'Run tests with basic license',
})
@ -25,13 +25,12 @@ const { argv } = yargs(process.argv.slice(2))
.option('server', {
default: false,
type: 'boolean',
description: 'Start Elasticsearch and kibana',
description: 'Only start ES and Kibana',
})
.option('runner', {
default: false,
type: 'boolean',
description:
'Run all tests (an instance of Elasticsearch and kibana are needs to be available)',
description: 'Only run tests',
})
.option('grep', {
alias: 'spec',
@ -48,6 +47,11 @@ const { argv } = yargs(process.argv.slice(2))
type: 'number',
description: 'Repeat the test n number of times',
})
.option('updateSnapshots', {
default: false,
type: 'boolean',
description: 'Update snapshots',
})
.check((argv) => {
const { inspect, runner } = argv;
if (inspect && !runner) {
@ -58,7 +62,11 @@ const { argv } = yargs(process.argv.slice(2))
})
.help();
const { trial, server, runner, grep, inspect } = argv;
const { basic, trial, server, runner, grep, inspect, updateSnapshots } = argv;
if (trial === false && basic === false) {
throw new Error('Please specify either --trial or --basic');
}
const license = trial ? 'trial' : 'basic';
@ -71,11 +79,16 @@ if (server) {
ftrScript = 'functional_test_runner';
}
const inspectArg = inspect ? '--inspect-brk' : '';
const grepArg = grep ? `--grep "${grep}"` : '';
const cmd = `node ${inspectArg} ../../../../scripts/${ftrScript} ${grepArg} --config ../../../../test/apm_api_integration/${license}/config.ts`;
const cmd = [
'node',
...(inspect ? ['--inspect-brk'] : []),
`../../../../scripts/${ftrScript}`,
...(grep ? [`--grep "${grep}"`] : []),
...(updateSnapshots ? [`--updateSnapshots`] : []),
`--config ../../../../test/apm_api_integration/${license}/config.ts`,
].join(' ');
console.log(`Running ${cmd}`);
console.log(`Running: "${cmd}"`);
function runTests() {
childProcess.execSync(cmd, { cwd: path.join(__dirname), stdio: 'inherit' });

View file

@ -6,7 +6,7 @@
*/
import { journey, step, expect, before } from '@elastic/synthetics';
import { callKibana } from '@kbn/apm-plugin/scripts/create_apm_users_and_roles/helpers/call_kibana';
import { callKibana } from '@kbn/apm-plugin/scripts/create_apm_users/helpers/call_kibana';
import { byTestId, waitForLoadingToFinish } from './utils';
import { loginPageProvider } from '../page_objects/login';
@ -17,7 +17,7 @@ journey('DataViewPermissions', async ({ page, params }) => {
try {
await callKibana({
elasticsearch: { username: 'elastic', password: 'changeme' },
kibana: { hostname: params.kibanaUrl, roleSuffix: '' },
kibana: { hostname: params.kibanaUrl },
options: {
method: 'DELETE',
url: '/api/saved_objects/index-pattern/synthetics_static_index_pattern_id_heartbeat_?force=false',

View file

@ -9,7 +9,7 @@
import Url from 'url';
import { run as playwrightRun } from '@elastic/synthetics';
import { createApmAndObsUsersAndRoles } from '@kbn/apm-plugin/scripts/create_apm_users_and_roles/create_apm_users_and_roles';
import { createApmUsers } from '@kbn/apm-plugin/scripts/create_apm_users/create_apm_users';
import { esArchiverLoad, esArchiverUnload } from './tasks/es_archiver';
import './journeys';
@ -43,9 +43,9 @@ async function playwrightStart(getService: any, headless = true, match?: string)
port: config.get('servers.kibana.port'),
});
await createApmAndObsUsersAndRoles({
await createApmUsers({
elasticsearch: { username: 'elastic', password: 'changeme' },
kibana: { roleSuffix: 'e2e', hostname: kibanaUrl },
kibana: { hostname: kibanaUrl },
});
const res = await playwrightRun({

View file

@ -13,27 +13,18 @@ type SecurityService = Awaited<ReturnType<typeof SecurityServiceProvider>>;
export enum ApmUser {
noAccessUser = 'no_access_user',
apmReadUser = 'apm_read_user',
apmWriteUser = 'apm_write_user',
viewerUser = 'viewer_user',
editorUser = 'editor_user',
apmAnnotationsWriteUser = 'apm_annotations_write_user',
apmReadUserWithoutMlAccess = 'apm_read_user_without_ml_access',
apmManageOwnAgentKeys = 'apm_manage_own_agent_keys',
apmManageOwnAndCreateAgentKeys = 'apm_manage_own_and_create_agent_keys',
}
// TODO: Going forward we want to use the built-in roles `viewer` and `editor`. However ML privileges are not included in the built-in roles
// Until https://github.com/elastic/kibana/issues/71422 is closed we have to use the custom roles below
const roles = {
[ApmUser.noAccessUser]: {},
[ApmUser.apmReadUser]: {
kibana: [
{
base: [],
feature: { ml: ['read'] },
spaces: ['*'],
},
],
},
[ApmUser.viewerUser]: {},
[ApmUser.editorUser]: {},
[ApmUser.apmReadUserWithoutMlAccess]: {
elasticsearch: {
cluster: [],
@ -52,15 +43,6 @@ const roles = {
},
],
},
[ApmUser.apmWriteUser]: {
kibana: [
{
base: [],
feature: { ml: ['all'] },
spaces: ['*'],
},
],
},
[ApmUser.apmAnnotationsWriteUser]: {
elasticsearch: {
cluster: [],
@ -99,17 +81,17 @@ const users = {
[ApmUser.noAccessUser]: {
roles: [],
},
[ApmUser.apmReadUser]: {
roles: ['viewer', ApmUser.apmReadUser],
[ApmUser.viewerUser]: {
roles: ['viewer'],
},
[ApmUser.editorUser]: {
roles: ['editor'],
},
[ApmUser.apmReadUserWithoutMlAccess]: {
roles: [ApmUser.apmReadUserWithoutMlAccess],
},
[ApmUser.apmWriteUser]: {
roles: ['editor', ApmUser.apmWriteUser],
},
[ApmUser.apmAnnotationsWriteUser]: {
roles: ['editor', ApmUser.apmWriteUser, ApmUser.apmAnnotationsWriteUser],
roles: ['editor', ApmUser.apmAnnotationsWriteUser],
},
[ApmUser.apmManageOwnAgentKeys]: {
roles: ['editor', ApmUser.apmManageOwnAgentKeys],

View file

@ -89,8 +89,8 @@ export function createTestConfig(config: ApmFtrConfig) {
return {
noAccessUser: await getApmApiClient(servers.kibana, security, ApmUser.noAccessUser, es),
readUser: await getApmApiClient(servers.kibana, security, ApmUser.apmReadUser, es),
writeUser: await getApmApiClient(servers.kibana, security, ApmUser.apmWriteUser, es),
readUser: await getApmApiClient(servers.kibana, security, ApmUser.viewerUser, es),
writeUser: await getApmApiClient(servers.kibana, security, ApmUser.editorUser, es),
annotationWriterUser: await getApmApiClient(
servers.kibana,
security,
@ -120,8 +120,8 @@ export function createTestConfig(config: ApmFtrConfig) {
ml: MachineLearningAPIProvider,
// legacy clients
legacySupertestAsNoAccessUser: getLegacySupertestClient(kibanaServer, ApmUser.noAccessUser),
legacySupertestAsApmReadUser: getLegacySupertestClient(kibanaServer, ApmUser.apmReadUser),
legacySupertestAsApmWriteUser: getLegacySupertestClient(kibanaServer, ApmUser.apmWriteUser),
legacySupertestAsApmReadUser: getLegacySupertestClient(kibanaServer, ApmUser.viewerUser),
legacySupertestAsApmWriteUser: getLegacySupertestClient(kibanaServer, ApmUser.editorUser),
legacySupertestAsApmAnnotationsWriteUser: getLegacySupertestClient(
kibanaServer,
ApmUser.apmAnnotationsWriteUser

View file

@ -10,14 +10,14 @@ import { FtrProviderContext } from '../../../common/ftr_provider_context';
export default function apiTest({ getService }: FtrProviderContext) {
const registry = getService('registry');
const apmReadUser = getService('legacySupertestAsApmReadUser');
const viewerUser = getService('legacySupertestAsApmReadUser');
function getJobs() {
return apmReadUser.get(`/internal/apm/settings/anomaly-detection/jobs`).set('kbn-xsrf', 'foo');
return viewerUser.get(`/internal/apm/settings/anomaly-detection/jobs`).set('kbn-xsrf', 'foo');
}
function createJobs(environments: string[]) {
return apmReadUser
return viewerUser
.post(`/internal/apm/settings/anomaly-detection/jobs`)
.send({ environments })
.set('kbn-xsrf', 'foo');