Skip to content

Commit

Permalink
Register privileges in Kibana Platform Security plugin and remove leg…
Browse files Browse the repository at this point in the history
…acy `getUser` API. (elastic#65472)

# Conflicts:
#	x-pack/README.md
#	x-pack/plugins/uptime/README.md
#	x-pack/scripts/functional_tests.js
  • Loading branch information
azasypkin committed Jun 5, 2020
1 parent 962db2f commit 83c3907
Show file tree
Hide file tree
Showing 58 changed files with 721 additions and 413 deletions.
2 changes: 1 addition & 1 deletion .sass-lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,14 @@ files:
- 'src/legacy/core_plugins/timelion/**/*.s+(a|c)ss'
- 'src/plugins/vis_type_vislib/**/*.s+(a|c)ss'
- 'src/plugins/vis_type_xy/**/*.s+(a|c)ss'
- 'x-pack/legacy/plugins/security/**/*.s+(a|c)ss'
- 'x-pack/plugins/canvas/**/*.s+(a|c)ss'
- 'x-pack/plugins/triggers_actions_ui/**/*.s+(a|c)ss'
- 'x-pack/plugins/lens/**/*.s+(a|c)ss'
- 'x-pack/plugins/cross_cluster_replication/**/*.s+(a|c)ss'
- 'x-pack/legacy/plugins/maps/**/*.s+(a|c)ss'
- 'x-pack/plugins/maps/**/*.s+(a|c)ss'
- 'x-pack/plugins/spaces/**/*.s+(a|c)ss'
- 'x-pack/plugins/security/**/*.s+(a|c)ss'
ignore:
- 'x-pack/plugins/canvas/shareable_runtime/**/*.s+(a|c)ss'
rules:
Expand Down
2 changes: 1 addition & 1 deletion x-pack/.i18nrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@
"xpack.reporting": ["plugins/reporting"],
"xpack.rollupJobs": ["legacy/plugins/rollup", "plugins/rollup"],
"xpack.searchProfiler": "plugins/searchprofiler",
"xpack.security": ["legacy/plugins/security", "plugins/security"],
"xpack.security": "plugins/security",
"xpack.server": "legacy/server",
"xpack.securitySolution": "plugins/security_solution",
"xpack.snapshotRestore": "plugins/snapshot_restore",
Expand Down
6 changes: 3 additions & 3 deletions x-pack/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ Examples:
- Run the jest test case whose description matches 'filtering should skip values of null':
`cd x-pack && yarn test:jest -t 'filtering should skip values of null' plugins/ml/public/application/explorer/explorer_charts/explorer_charts_container_service.test.js`
- Run the x-pack api integration test case whose description matches the given string:
`node scripts/functional_tests_server --config x-pack/test/api_integration/config.js`
`node scripts/functional_test_runner --config x-pack/test/api_integration/config.js --grep='apis Monitoring Beats list with restarted beat instance should load multiple clusters'`
`node scripts/functional_tests_server --config x-pack/test/api_integration/config.ts`
`node scripts/functional_test_runner --config x-pack/test/api_integration/config.ts --grep='apis Monitoring Beats list with restarted beat instance should load multiple clusters'`

In addition to to providing a regular expression argument, specific tests can also be run by appeding `.only` to an `it` or `describe` function block. E.g. `describe(` to `describe.only(`.

Expand Down Expand Up @@ -61,7 +61,7 @@ yarn test:mocha

#### Running functional tests

The functional UI tests, the API integration tests, and the SAML API integration tests are all run against a live browser, Kibana, and Elasticsearch install. Each set of tests is specified with a unique config that describes how to start the Elasticsearch server, the Kibana server, and what tests to run against them. The sets of tests that exist today are *functional UI tests* ([specified by this config](test/functional/config.js)), *API integration tests* ([specified by this config](test/api_integration/config.js)), and *SAML API integration tests* ([specified by this config](test/saml_api_integration/config.js)).
The functional UI tests, the API integration tests, and the SAML API integration tests are all run against a live browser, Kibana, and Elasticsearch install. Each set of tests is specified with a unique config that describes how to start the Elasticsearch server, the Kibana server, and what tests to run against them. The sets of tests that exist today are *functional UI tests* ([specified by this config](test/functional/config.js)), *API integration tests* ([specified by this config](test/api_integration/config.ts)), and *SAML API integration tests* ([specified by this config](test/saml_api_integration/config.ts)).

The script runs all sets of tests sequentially like so:
* builds Elasticsearch and X-Pack
Expand Down
2 changes: 1 addition & 1 deletion x-pack/legacy/plugins/beats_management/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ In one shell, from **~/kibana/x-pack**:
`node scripts/functional_tests-server.js`

In another shell, from **~kibana/x-pack**:
`node ../scripts/functional_test_runner.js --config test/api_integration/config.js`.
`node ../scripts/functional_test_runner.js --config test/api_integration/config.ts`.

### Manual e2e testing

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

import { Lifecycle, ResponseToolkit } from 'hapi';
import * as t from 'io-ts';
import { SecurityPluginSetup } from '../../../../../../../plugins/security/server';
import { LicenseType } from '../../../../common/constants/security';

export const internalAuthData = Symbol('internalAuthData');
Expand Down Expand Up @@ -39,6 +40,11 @@ export interface BackendFrameworkAdapter {
}

export interface KibanaLegacyServer {
newPlatform: {
setup: {
plugins: { security: SecurityPluginSetup };
};
};
plugins: {
xpack_main: {
status: {
Expand All @@ -53,9 +59,6 @@ export interface KibanaLegacyServer {
};
};
};
security: {
getUser: (request: KibanaServerRequest) => any;
};
elasticsearch: {
status: {
on: (status: 'green' | 'yellow' | 'red', callback: () => void) => void;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { ResponseToolkit } from 'hapi';
import { PathReporter } from 'io-ts/lib/PathReporter';
import { get } from 'lodash';
import { isLeft } from 'fp-ts/lib/Either';
import { KibanaRequest, LegacyRequest } from '../../../../../../../../src/core/server';
// @ts-ignore
import { mirrorPluginStatus } from '../../../../../../server/lib/mirror_plugin_status';
import {
Expand Down Expand Up @@ -128,13 +129,10 @@ export class KibanaBackendFrameworkAdapter implements BackendFrameworkAdapter {
}

private async getUser(request: KibanaServerRequest): Promise<KibanaUser | null> {
let user;
try {
user = await this.server.plugins.security.getUser(request);
} catch (e) {
return null;
}
if (user === null) {
const user = this.server.newPlatform.setup.plugins.security?.authc.getCurrentUser(
KibanaRequest.from((request as unknown) as LegacyRequest)
);
if (!user) {
return null;
}
const assertKibanaUser = RuntimeKibanaUser.decode(user);
Expand Down
59 changes: 6 additions & 53 deletions x-pack/legacy/plugins/security/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,64 +6,17 @@

import { Root } from 'joi';
import { resolve } from 'path';
import { Server } from 'src/legacy/server/kbn_server';
import { KibanaRequest, LegacyRequest } from '../../../../src/core/server';
// @ts-ignore
import { watchStatusAndLicenseToInitialize } from '../../server/lib/watch_status_and_license_to_initialize';
import { AuthenticatedUser, SecurityPluginSetup } from '../../../plugins/security/server';

/**
* Public interface of the security plugin.
*/
export interface SecurityPlugin {
getUser: (request: LegacyRequest) => Promise<AuthenticatedUser>;
}

function getSecurityPluginSetup(server: Server) {
const securityPlugin = server.newPlatform.setup.plugins.security as SecurityPluginSetup;
if (!securityPlugin) {
throw new Error('Kibana Platform Security plugin is not available.');
}

return securityPlugin;
}

export const security = (kibana: Record<string, any>) =>
new kibana.Plugin({
id: 'security',
publicDir: resolve(__dirname, 'public'),
require: ['kibana', 'xpack_main'],
require: ['kibana'],
configPrefix: 'xpack.security',
uiExports: {
hacks: ['plugins/security/hacks/legacy'],
injectDefaultVars: (server: Server) => {
return { enableSpaceAwarePrivileges: server.config().get('xpack.spaces.enabled') };
},
},

config(Joi: Root) {
return Joi.object({
enabled: Joi.boolean().default(true),
})
uiExports: { hacks: ['plugins/security/hacks/legacy'] },
config: (Joi: Root) =>
Joi.object({ enabled: Joi.boolean().default(true) })
.unknown()
.default();
},

async postInit(server: Server) {
watchStatusAndLicenseToInitialize(server.plugins.xpack_main, this, async () => {
const xpackInfo = server.plugins.xpack_main.info;
if (xpackInfo.isAvailable() && xpackInfo.feature('security').isEnabled()) {
await getSecurityPluginSetup(server).__legacyCompat.registerPrivilegesWithCluster();
}
});
},

async init(server: Server) {
const securityPlugin = getSecurityPluginSetup(server);

server.expose({
getUser: async (request: LegacyRequest) =>
securityPlugin.authc.getCurrentUser(KibanaRequest.from(request)),
});
},
.default(),
init() {},
});
4 changes: 2 additions & 2 deletions x-pack/plugins/apm/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -83,13 +83,13 @@ For debugging access Elasticsearch on http://localhost:9220` (elastic/changeme)
**Start server**

```
node scripts/functional_tests_server --config x-pack/test/api_integration/config.js
node scripts/functional_tests_server --config x-pack/test/api_integration/config.ts
```

**Run tests**

```
node scripts/functional_test_runner --config x-pack/test/api_integration/config.js --grep='APM specs'
node scripts/functional_test_runner --config x-pack/test/api_integration/config.ts --grep='APM specs'
```

APM tests are located in `x-pack/test/api_integration/apis/apm`.
Expand Down
4 changes: 2 additions & 2 deletions x-pack/plugins/ingest_manager/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,12 +52,12 @@ This plugin follows the `common`, `server`, `public` structure from the [Archite
1. In one terminal, change to the `x-pack` directory and start the test server with

```
node scripts/functional_tests_server.js --config test/api_integration/config.js
node scripts/functional_tests_server.js --config test/api_integration/config.ts
```

1. in a second terminal, run the tests from the Kibana root directory with
```
node scripts/functional_test_runner.js --config x-pack/test/api_integration/config.js
node scripts/functional_test_runner.js --config x-pack/test/api_integration/config.ts
```

#### EPM
Expand Down
2 changes: 1 addition & 1 deletion x-pack/plugins/lens/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,4 @@ Run all tests from the `x-pack` root directory
- You may want to comment out all imports except for Lens in the config file.
- API Functional tests:
- Run `node scripts/functional_tests_server`
- Run `node ../scripts/functional_test_runner.js --config ./test/api_integration/config.js --grep=Lens`
- Run `node ../scripts/functional_test_runner.js --config ./test/api_integration/config.ts --grep=Lens`
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,12 @@
*/

import { i18n } from '@kbn/i18n';
import { StartServicesAccessor, ApplicationSetup, AppMountParameters } from 'src/core/public';
import {
ApplicationSetup,
AppMountParameters,
AppNavLinkStatus,
StartServicesAccessor,
} from '../../../../../src/core/public';
import { AuthenticationServiceSetup } from '../authentication';

interface CreateDeps {
Expand All @@ -23,8 +28,7 @@ export const accountManagementApp = Object.freeze({
application.register({
id: this.id,
title,
// TODO: switch to proper enum once https://github.com/elastic/kibana/issues/58327 is resolved.
navLinkStatus: 3,
navLinkStatus: AppNavLinkStatus.hidden,
appRoute: '/security/account',
async mount({ element }: AppMountParameters) {
const [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,10 @@
}

&:focus {
@include euiFocusRing;

border-color: transparent;
border-radius: $euiBorderRadius;
@include euiFocusRing;

.secLoginCard__title {
text-decoration: underline;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,15 @@ import { Feature } from '../../../../../features/public';
import { KibanaPrivileges } from '../model';
import { SecurityLicenseFeatures } from '../../..';

// eslint-disable-next-line @kbn/eslint/no-restricted-paths
import { featuresPluginMock } from '../../../../../features/server/mocks';

export const createRawKibanaPrivileges = (
features: Feature[],
{ allowSubFeaturePrivileges = true } = {}
) => {
const featuresService = {
getFeatures: () => features,
};
const featuresService = featuresPluginMock.createSetup();
featuresService.getFeatures.mockReturnValue(features);

const licensingService = {
getFeatures: () => ({ allowSubFeaturePrivileges } as SecurityLicenseFeatures),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,12 @@ function getProps({
const { http, docLinks, notifications } = coreMock.createStart();
http.get.mockImplementation(async (path: any) => {
if (path === '/api/spaces/space') {
return buildSpaces();
if (spacesEnabled) {
return buildSpaces();
}

const notFoundError = { response: { status: 404 } };
throw notFoundError;
}
});

Expand All @@ -181,7 +186,6 @@ function getProps({
notifications,
docLinks: new DocumentationLinksService(docLinks),
fatalErrors,
spacesEnabled,
uiCapabilities: buildUICapabilities(canManageSpaces),
history: (scopedHistoryMock.create() as unknown) as ScopedHistory,
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,6 @@ interface Props {
docLinks: DocumentationLinksService;
http: HttpStart;
license: SecurityLicense;
spacesEnabled: boolean;
uiCapabilities: Capabilities;
notifications: NotificationsStart;
fatalErrors: FatalErrorsSetup;
Expand Down Expand Up @@ -225,14 +224,21 @@ function useRole(
return [role, setRole] as [Role | null, typeof setRole];
}

function useSpaces(http: HttpStart, fatalErrors: FatalErrorsSetup, spacesEnabled: boolean) {
const [spaces, setSpaces] = useState<Space[] | null>(null);
function useSpaces(http: HttpStart, fatalErrors: FatalErrorsSetup) {
const [spaces, setSpaces] = useState<{ enabled: boolean; list: Space[] } | null>(null);
useEffect(() => {
(spacesEnabled ? http.get('/api/spaces/space') : Promise.resolve([])).then(
(fetchedSpaces) => setSpaces(fetchedSpaces),
(err) => fatalErrors.add(err)
http.get('/api/spaces/space').then(
(fetchedSpaces) => setSpaces({ enabled: true, list: fetchedSpaces }),
(err: IHttpFetchError) => {
// Spaces plugin can be disabled and hence this endpoint can be unavailable.
if (err.response?.status === 404) {
setSpaces({ enabled: false, list: [] });
} else {
fatalErrors.add(err);
}
}
);
}, [http, fatalErrors, spacesEnabled]);
}, [http, fatalErrors]);

return spaces;
}
Expand Down Expand Up @@ -278,7 +284,6 @@ export const EditRolePage: FunctionComponent<Props> = ({
roleName,
action,
fatalErrors,
spacesEnabled,
license,
docLinks,
uiCapabilities,
Expand All @@ -295,7 +300,7 @@ export const EditRolePage: FunctionComponent<Props> = ({
const runAsUsers = useRunAsUsers(userAPIClient, fatalErrors);
const indexPatternsTitles = useIndexPatternsTitles(indexPatterns, fatalErrors, notifications);
const privileges = usePrivileges(privilegesAPIClient, fatalErrors);
const spaces = useSpaces(http, fatalErrors, spacesEnabled);
const spaces = useSpaces(http, fatalErrors);
const features = useFeatures(getFeatures, fatalErrors);
const [role, setRole] = useRole(
rolesAPIClient,
Expand Down Expand Up @@ -434,8 +439,8 @@ export const EditRolePage: FunctionComponent<Props> = ({
<EuiSpacer />
<KibanaPrivilegesRegion
kibanaPrivileges={new KibanaPrivileges(kibanaPrivileges, features)}
spaces={spaces}
spacesEnabled={spacesEnabled}
spaces={spaces.list}
spacesEnabled={spaces.enabled}
uiCapabilities={uiCapabilities}
canCustomizeSubFeaturePrivileges={license.getFeatures().allowSubFeaturePrivileges}
editable={!isRoleReadOnly}
Expand Down Expand Up @@ -519,7 +524,7 @@ export const EditRolePage: FunctionComponent<Props> = ({
setFormError(null);

try {
await rolesAPIClient.saveRole({ role, spacesEnabled });
await rolesAPIClient.saveRole({ role, spacesEnabled: spaces.enabled });
} catch (error) {
notifications.toasts.addDanger(get(error, 'data.message'));
return;
Expand Down Expand Up @@ -554,7 +559,7 @@ export const EditRolePage: FunctionComponent<Props> = ({
backToRoleList();
};

const description = spacesEnabled ? (
const description = spaces.enabled ? (
<FormattedMessage
id="xpack.security.management.editRole.setPrivilegesToKibanaSpacesDescription"
defaultMessage="Set privileges on your Elasticsearch data and control access to your Kibana spaces."
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,7 @@ export const rolesManagementApp = Object.freeze({
];

const [
[
{ application, docLinks, http, i18n: i18nStart, injectedMetadata, notifications },
{ data, features },
],
[{ application, docLinks, http, i18n: i18nStart, notifications }, { data, features }],
{ RolesGridPage },
{ EditRolePage },
{ RolesAPIClient },
Expand Down Expand Up @@ -86,9 +83,6 @@ export const rolesManagementApp = Object.freeze({
<EditRolePage
action={action}
roleName={roleName}
spacesEnabled={
injectedMetadata.getInjectedVar('enableSpaceAwarePrivileges') as boolean
}
rolesAPIClient={rolesAPIClient}
userAPIClient={new UserAPIClient(http)}
indicesAPIClient={new IndicesAPIClient(http)}
Expand Down
Loading

0 comments on commit 83c3907

Please sign in to comment.