mirror of
https://github.com/elastic/kibana.git
synced 2025-04-23 17:28:26 -04:00
[APM] Remove mentions of apm_user
(#132790)
This commit is contained in:
parent
06a98d7844
commit
c1b77b93b6
44 changed files with 149 additions and 418 deletions
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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**
|
||||
|
||||
|
|
|
@ -30,7 +30,7 @@ describe('Comparison feature flag', () => {
|
|||
});
|
||||
|
||||
beforeEach(() => {
|
||||
cy.loginAsPowerUser();
|
||||
cy.loginAsEditorUser();
|
||||
});
|
||||
|
||||
describe('when comparison feature is enabled', () => {
|
||||
|
|
|
@ -32,7 +32,7 @@ describe('Infrastracture feature flag', () => {
|
|||
});
|
||||
|
||||
beforeEach(() => {
|
||||
cy.loginAsPowerUser();
|
||||
cy.loginAsEditorUser();
|
||||
});
|
||||
|
||||
describe('when infrastracture feature is disabled', () => {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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' },
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -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();
|
||||
});
|
||||
|
||||
|
|
|
@ -72,7 +72,7 @@ describe('Agent configuration', () => {
|
|||
});
|
||||
|
||||
beforeEach(() => {
|
||||
cy.loginAsPowerUser();
|
||||
cy.loginAsEditorUser();
|
||||
cy.visit(agentConfigHref);
|
||||
});
|
||||
|
||||
|
|
|
@ -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', () => {
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
describe('APM deep links', () => {
|
||||
before(() => {
|
||||
cy.loginAsReadOnlyUser();
|
||||
cy.loginAsViewerUser();
|
||||
});
|
||||
it('navigates to apm links on search elastic', () => {
|
||||
cy.visit('/');
|
||||
|
|
|
@ -31,7 +31,7 @@ describe('Dependencies', () => {
|
|||
});
|
||||
|
||||
beforeEach(() => {
|
||||
cy.loginAsReadOnlyUser();
|
||||
cy.loginAsViewerUser();
|
||||
});
|
||||
|
||||
describe('top-level dependencies page', () => {
|
||||
|
|
|
@ -23,7 +23,7 @@ const errorDetailsPageHref = url.format({
|
|||
|
||||
describe('Error details', () => {
|
||||
beforeEach(() => {
|
||||
cy.loginAsReadOnlyUser();
|
||||
cy.loginAsViewerUser();
|
||||
});
|
||||
|
||||
describe('when data is loaded', () => {
|
||||
|
|
|
@ -25,7 +25,7 @@ const nodeServiceErrorsPageHref = url.format({
|
|||
|
||||
describe('Errors page', () => {
|
||||
beforeEach(() => {
|
||||
cy.loginAsReadOnlyUser();
|
||||
cy.loginAsViewerUser();
|
||||
});
|
||||
|
||||
describe('when data is loaded', () => {
|
||||
|
|
|
@ -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', () => {
|
||||
|
|
|
@ -35,7 +35,7 @@ describe('Service inventory - header filters', () => {
|
|||
});
|
||||
|
||||
beforeEach(() => {
|
||||
cy.loginAsReadOnlyUser();
|
||||
cy.loginAsViewerUser();
|
||||
});
|
||||
|
||||
describe('Filtering by kuerybar', () => {
|
||||
|
|
|
@ -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);
|
||||
});
|
||||
|
||||
|
|
|
@ -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', () => {
|
||||
|
|
|
@ -32,7 +32,7 @@ describe('Errors table', () => {
|
|||
});
|
||||
|
||||
beforeEach(() => {
|
||||
cy.loginAsReadOnlyUser();
|
||||
cy.loginAsViewerUser();
|
||||
});
|
||||
|
||||
it('errors table is populated', () => {
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -38,7 +38,7 @@ const apisToIntercept = [
|
|||
|
||||
describe('Instances table', () => {
|
||||
beforeEach(() => {
|
||||
cy.loginAsReadOnlyUser();
|
||||
cy.loginAsViewerUser();
|
||||
});
|
||||
|
||||
// describe('when data is not loaded', () => {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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', () => {
|
||||
|
|
|
@ -30,7 +30,7 @@ function getServiceInventoryUrl({ serviceName }: { serviceName: string }) {
|
|||
|
||||
describe('Span links', () => {
|
||||
beforeEach(() => {
|
||||
cy.loginAsReadOnlyUser();
|
||||
cy.loginAsViewerUser();
|
||||
});
|
||||
|
||||
describe('when data is loaded', () => {
|
||||
|
|
|
@ -33,7 +33,7 @@ describe('Transactions Overview', () => {
|
|||
});
|
||||
|
||||
beforeEach(() => {
|
||||
cy.loginAsReadOnlyUser();
|
||||
cy.loginAsViewerUser();
|
||||
});
|
||||
|
||||
it('has no detectable a11y violations on load', () => {
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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',
|
||||
},
|
||||
});
|
||||
|
||||
|
|
20
x-pack/plugins/apm/scripts/create_apm_users.js
Normal file
20
x-pack/plugins/apm/scripts/create_apm_users.js
Normal 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');
|
|
@ -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
|
|
@ -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');
|
|
@ -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,
|
|
@ -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 {
|
|
@ -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';
|
||||
|
|
@ -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');
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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: ['*'],
|
||||
},
|
||||
],
|
||||
};
|
|
@ -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: ['*'],
|
||||
},
|
||||
],
|
||||
};
|
|
@ -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' });
|
||||
|
|
|
@ -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',
|
||||
|
|
|
@ -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({
|
||||
|
|
|
@ -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],
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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');
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue