mirror of
https://github.com/elastic/kibana.git
synced 2025-04-23 17:28:26 -04:00
Implement interactiveSetup
plugin server side functionality: setup
layout (#105222)
This commit is contained in:
parent
ff2a5a8566
commit
ed28155165
22 changed files with 280 additions and 25 deletions
|
@ -1573,6 +1573,7 @@ module.exports = {
|
|||
files: [
|
||||
'src/plugins/security_oss/**/*.{js,mjs,ts,tsx}',
|
||||
'src/plugins/spaces_oss/**/*.{js,mjs,ts,tsx}',
|
||||
'src/plugins/interactive_setup/**/*.{js,mjs,ts,tsx}',
|
||||
'x-pack/plugins/encrypted_saved_objects/**/*.{js,mjs,ts,tsx}',
|
||||
'x-pack/plugins/security/**/*.{js,mjs,ts,tsx}',
|
||||
'x-pack/plugins/spaces/**/*.{js,mjs,ts,tsx}',
|
||||
|
|
4
.github/CODEOWNERS
vendored
4
.github/CODEOWNERS
vendored
|
@ -252,7 +252,7 @@
|
|||
/src/core/server/csp/ @elastic/kibana-security @elastic/kibana-core
|
||||
/src/plugins/security_oss/ @elastic/kibana-security
|
||||
/src/plugins/spaces_oss/ @elastic/kibana-security
|
||||
/src/plugins/user_setup/ @elastic/kibana-security
|
||||
/src/plugins/interactive_setup/ @elastic/kibana-security
|
||||
/test/security_functional/ @elastic/kibana-security
|
||||
/x-pack/plugins/spaces/ @elastic/kibana-security
|
||||
/x-pack/plugins/encrypted_saved_objects/ @elastic/kibana-security
|
||||
|
@ -351,7 +351,7 @@
|
|||
/x-pack/test/case_api_integration @elastic/security-threat-hunting
|
||||
/x-pack/plugins/lists @elastic/security-detections-response
|
||||
|
||||
## Security Solution sub teams - security-onboarding-and-lifecycle-mgt
|
||||
## Security Solution sub teams - security-onboarding-and-lifecycle-mgt
|
||||
/x-pack/plugins/security_solution/public/management/ @elastic/security-onboarding-and-lifecycle-mgt
|
||||
/x-pack/plugins/security_solution/public/common/lib/endpoint*/ @elastic/security-onboarding-and-lifecycle-mgt
|
||||
/x-pack/plugins/security_solution/public/common/components/endpoint/ @elastic/security-onboarding-and-lifecycle-mgt
|
||||
|
|
|
@ -37,6 +37,7 @@
|
|||
"presentationUtil": "src/plugins/presentation_util",
|
||||
"indexPatternFieldEditor": "src/plugins/index_pattern_field_editor",
|
||||
"indexPatternManagement": "src/plugins/index_pattern_management",
|
||||
"interactiveSetup": "src/plugins/interactive_setup",
|
||||
"advancedSettings": "src/plugins/advanced_settings",
|
||||
"kibana_legacy": "src/plugins/kibana_legacy",
|
||||
"kibanaOverview": "src/plugins/kibana_overview",
|
||||
|
|
|
@ -136,6 +136,10 @@ for use in their own application.
|
|||
in Kibana, e.g. visualizations. It has the form of a flyout panel.
|
||||
|
||||
|
||||
|{kib-repo}blob/{branch}/src/plugins/interactive_setup/README.md[interactiveSetup]
|
||||
|The plugin provides UI and APIs for the interactive setup mode.
|
||||
|
||||
|
||||
|{kib-repo}blob/{branch}/src/plugins/kibana_legacy/README.md[kibanaLegacy]
|
||||
|This plugin contains several helpers and services to integrate pieces of the legacy Kibana app with the new Kibana platform.
|
||||
|
||||
|
@ -276,10 +280,6 @@ In general this plugin provides:
|
|||
|The Usage Collection Service defines a set of APIs for other plugins to report the usage of their features. At the same time, it provides necessary the APIs for other services (i.e.: telemetry, monitoring, ...) to consume that usage data.
|
||||
|
||||
|
||||
|{kib-repo}blob/{branch}/src/plugins/user_setup/README.md[userSetup]
|
||||
|The plugin provides UI and APIs for the interactive setup mode.
|
||||
|
||||
|
||||
|{kib-repo}blob/{branch}/src/plugins/vis_default_editor/README.md[visDefaultEditor]
|
||||
|The default editor is used in most primary visualizations, e.x. Area, Data table, Pie, etc.
|
||||
It acts as a container for a particular visualization and options tabs. Contains the default "Data" tab in public/components/sidebar/data_tab.tsx.
|
||||
|
|
|
@ -117,4 +117,4 @@ pageLoadAssetSize:
|
|||
expressionImage: 19288
|
||||
expressionMetric: 22238
|
||||
expressionShape: 30033
|
||||
userSetup: 18532
|
||||
interactiveSetup: 18532
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
# `userSetup` plugin
|
||||
# `interactiveSetup` plugin
|
||||
|
||||
The plugin provides UI and APIs for the interactive setup mode.
|
|
@ -0,0 +1,27 @@
|
|||
/*
|
||||
* 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 and the Server Side Public License, v 1; you may not use this file except
|
||||
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
||||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Describes current status of the Elasticsearch connection.
|
||||
*/
|
||||
export enum ElasticsearchConnectionStatus {
|
||||
/**
|
||||
* Indicates that Kibana hasn't figured out yet if existing Elasticsearch connection configuration is valid.
|
||||
*/
|
||||
Unknown = 'unknown',
|
||||
|
||||
/**
|
||||
* Indicates that current Elasticsearch connection configuration valid and sufficient.
|
||||
*/
|
||||
Configured = 'configured',
|
||||
|
||||
/**
|
||||
* Indicates that current Elasticsearch connection configuration isn't valid or not sufficient.
|
||||
*/
|
||||
NotConfigured = 'not-configured',
|
||||
}
|
|
@ -6,12 +6,5 @@
|
|||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import type { CoreSetup, CoreStart, Plugin } from 'src/core/server';
|
||||
|
||||
export class UserSetupPlugin implements Plugin {
|
||||
public setup(core: CoreSetup) {}
|
||||
|
||||
public start(core: CoreStart) {}
|
||||
|
||||
public stop() {}
|
||||
}
|
||||
export type { InteractiveSetupViewState, EnrollmentToken } from './types';
|
||||
export { ElasticsearchConnectionStatus } from './elasticsearch_connection_status';
|
45
src/plugins/interactive_setup/common/types.ts
Normal file
45
src/plugins/interactive_setup/common/types.ts
Normal file
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
* 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 and the Server Side Public License, v 1; you may not use this file except
|
||||
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
||||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import type { ElasticsearchConnectionStatus } from './elasticsearch_connection_status';
|
||||
|
||||
/**
|
||||
* A set of state details that interactive setup view retrieves from the Kibana server.
|
||||
*/
|
||||
export interface InteractiveSetupViewState {
|
||||
/**
|
||||
* Current status of the Elasticsearch connection.
|
||||
*/
|
||||
elasticsearchConnectionStatus: ElasticsearchConnectionStatus;
|
||||
}
|
||||
|
||||
/**
|
||||
* The token that allows one to configure Kibana instance to communicate with an existing Elasticsearch cluster that
|
||||
* has security features enabled.
|
||||
*/
|
||||
export interface EnrollmentToken {
|
||||
/**
|
||||
* The version of the Elasticsearch node that generated this enrollment token.
|
||||
*/
|
||||
ver: string;
|
||||
|
||||
/**
|
||||
* An array of addresses in the form of `<hostname>:<port>` or `<ip_address>:<port>` where the Elasticsearch node is listening for HTTP connections.
|
||||
*/
|
||||
adr: readonly string[];
|
||||
|
||||
/**
|
||||
* The SHA-256 fingerprint of the CA certificate that is used to sign the certificate that the Elasticsearch node presents for HTTP over TLS connections.
|
||||
*/
|
||||
fgr: string;
|
||||
|
||||
/**
|
||||
* An Elasticsearch API key (not encoded) that can be used as credentials authorized to call the enrollment related APIs in Elasticsearch.
|
||||
*/
|
||||
key: string;
|
||||
}
|
|
@ -9,5 +9,5 @@
|
|||
module.exports = {
|
||||
preset: '@kbn/test',
|
||||
rootDir: '../../..',
|
||||
roots: ['<rootDir>/src/plugins/user_setup'],
|
||||
roots: ['<rootDir>/src/plugins/interactive_setup'],
|
||||
};
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"id": "userSetup",
|
||||
"id": "interactiveSetup",
|
||||
"owner": {
|
||||
"name": "Platform Security",
|
||||
"githubTeam": "kibana-security"
|
||||
|
@ -7,7 +7,8 @@
|
|||
"description": "This plugin provides UI and APIs for the interactive setup mode.",
|
||||
"version": "8.0.0",
|
||||
"kibanaVersion": "kibana",
|
||||
"configPath": ["userSetup"],
|
||||
"type": "preboot",
|
||||
"configPath": ["interactiveSetup"],
|
||||
"server": true,
|
||||
"ui": true
|
||||
}
|
|
@ -10,13 +10,14 @@ import React from 'react';
|
|||
import ReactDOM from 'react-dom';
|
||||
|
||||
import type { CoreSetup, CoreStart, Plugin } from 'src/core/public';
|
||||
|
||||
import { App } from './app';
|
||||
|
||||
export class UserSetupPlugin implements Plugin {
|
||||
public setup(core: CoreSetup) {
|
||||
core.application.register({
|
||||
id: 'userSetup',
|
||||
title: 'User Setup',
|
||||
id: 'interactiveSetup',
|
||||
title: 'Interactive Setup',
|
||||
chromeless: true,
|
||||
mount: (params) => {
|
||||
ReactDOM.render(<App />, params.element);
|
|
@ -7,7 +7,11 @@
|
|||
*/
|
||||
|
||||
import type { TypeOf } from '@kbn/config-schema';
|
||||
import type { PluginConfigDescriptor } from 'src/core/server';
|
||||
import type {
|
||||
PluginConfigDescriptor,
|
||||
PluginInitializer,
|
||||
PluginInitializerContext,
|
||||
} from 'src/core/server';
|
||||
|
||||
import { ConfigSchema } from './config';
|
||||
import { UserSetupPlugin } from './plugin';
|
||||
|
@ -16,4 +20,6 @@ export const config: PluginConfigDescriptor<TypeOf<typeof ConfigSchema>> = {
|
|||
schema: ConfigSchema,
|
||||
};
|
||||
|
||||
export const plugin = () => new UserSetupPlugin();
|
||||
export const plugin: PluginInitializer<void, never> = (
|
||||
initializerContext: PluginInitializerContext
|
||||
) => new UserSetupPlugin(initializerContext);
|
119
src/plugins/interactive_setup/server/plugin.ts
Normal file
119
src/plugins/interactive_setup/server/plugin.ts
Normal file
|
@ -0,0 +1,119 @@
|
|||
/*
|
||||
* 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 and the Server Side Public License, v 1; you may not use this file except
|
||||
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
||||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import type { Subscription } from 'rxjs';
|
||||
|
||||
import type { TypeOf } from '@kbn/config-schema';
|
||||
import type { CorePreboot, Logger, PluginInitializerContext, PrebootPlugin } from 'src/core/server';
|
||||
|
||||
import { ElasticsearchConnectionStatus } from '../common';
|
||||
import type { ConfigSchema, ConfigType } from './config';
|
||||
import { defineRoutes } from './routes';
|
||||
|
||||
export class UserSetupPlugin implements PrebootPlugin {
|
||||
readonly #logger: Logger;
|
||||
|
||||
#configSubscription?: Subscription;
|
||||
#config?: ConfigType;
|
||||
readonly #getConfig = () => {
|
||||
if (!this.#config) {
|
||||
throw new Error('Config is not available.');
|
||||
}
|
||||
return this.#config;
|
||||
};
|
||||
|
||||
#elasticsearchConnectionStatus = ElasticsearchConnectionStatus.Unknown;
|
||||
readonly #getElasticsearchConnectionStatus = () => {
|
||||
return this.#elasticsearchConnectionStatus;
|
||||
};
|
||||
|
||||
constructor(private readonly initializerContext: PluginInitializerContext) {
|
||||
this.#logger = this.initializerContext.logger.get();
|
||||
}
|
||||
|
||||
public setup(core: CorePreboot) {
|
||||
this.#configSubscription = this.initializerContext.config
|
||||
.create<TypeOf<typeof ConfigSchema>>()
|
||||
.subscribe((config) => {
|
||||
this.#config = config;
|
||||
});
|
||||
|
||||
// We shouldn't activate interactive setup mode if we detect that user has already configured
|
||||
// Elasticsearch connection manually: either if Kibana system user credentials are specified or
|
||||
// user specified non-default host for the Elasticsearch.
|
||||
const shouldActiveSetupMode =
|
||||
!core.elasticsearch.config.credentialsSpecified &&
|
||||
core.elasticsearch.config.hosts.length === 1 &&
|
||||
core.elasticsearch.config.hosts[0] === 'http://localhost:9200';
|
||||
if (!shouldActiveSetupMode) {
|
||||
this.#logger.debug(
|
||||
'Interactive setup mode will not be activated since Elasticsearch connection is already configured.'
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
let completeSetup: (result: { shouldReloadConfig: boolean }) => void;
|
||||
core.preboot.holdSetupUntilResolved(
|
||||
'Validating Elasticsearch connection configuration…',
|
||||
new Promise((resolve) => {
|
||||
completeSetup = resolve;
|
||||
})
|
||||
);
|
||||
|
||||
// If preliminary check above indicates that user didn't alter default Elasticsearch connection
|
||||
// details, it doesn't mean Elasticsearch connection isn't configured. There is a chance that they
|
||||
// already disabled security features in Elasticsearch and everything should work by default.
|
||||
// We should check if we can connect to Elasticsearch with default configuration to know if we
|
||||
// need to activate interactive setup. This check can take some time, so we should register our
|
||||
// routes to let interactive setup UI to handle user requests until the check is complete.
|
||||
core.elasticsearch
|
||||
.createClient('ping')
|
||||
.asInternalUser.ping()
|
||||
.then(
|
||||
(pingResponse) => {
|
||||
if (pingResponse.body) {
|
||||
this.#logger.debug(
|
||||
'Kibana is already properly configured to connect to Elasticsearch. Interactive setup mode will not be activated.'
|
||||
);
|
||||
this.#elasticsearchConnectionStatus = ElasticsearchConnectionStatus.Configured;
|
||||
completeSetup({ shouldReloadConfig: false });
|
||||
} else {
|
||||
this.#logger.debug(
|
||||
'Kibana is not properly configured to connect to Elasticsearch. Interactive setup mode will be activated.'
|
||||
);
|
||||
this.#elasticsearchConnectionStatus = ElasticsearchConnectionStatus.NotConfigured;
|
||||
}
|
||||
},
|
||||
() => {
|
||||
// TODO: we should probably react differently to different errors. 401 - credentials aren't correct, etc.
|
||||
// Do we want to constantly ping ES if interactive mode UI isn't active? Just in case user runs Kibana and then
|
||||
// configure Elasticsearch so that it can eventually connect to it without any configuration changes?
|
||||
this.#elasticsearchConnectionStatus = ElasticsearchConnectionStatus.NotConfigured;
|
||||
}
|
||||
);
|
||||
|
||||
core.http.registerRoutes('', (router) => {
|
||||
defineRoutes({
|
||||
router,
|
||||
basePath: core.http.basePath,
|
||||
logger: this.#logger.get('routes'),
|
||||
getConfig: this.#getConfig.bind(this),
|
||||
getElasticsearchConnectionStatus: this.#getElasticsearchConnectionStatus.bind(this),
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
public stop() {
|
||||
this.#logger.debug('Stopping plugin');
|
||||
|
||||
if (this.#configSubscription) {
|
||||
this.#configSubscription.unsubscribe();
|
||||
this.#configSubscription = undefined;
|
||||
}
|
||||
}
|
||||
}
|
31
src/plugins/interactive_setup/server/routes/enroll.ts
Normal file
31
src/plugins/interactive_setup/server/routes/enroll.ts
Normal file
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
* 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 and the Server Side Public License, v 1; you may not use this file except
|
||||
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
||||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import { schema } from '@kbn/config-schema';
|
||||
|
||||
import type { RouteDefinitionParams } from './';
|
||||
|
||||
/**
|
||||
* Defines routes to deal with Elasticsearch `enroll_kibana` APIs.
|
||||
*/
|
||||
export function defineEnrollRoutes({ router }: RouteDefinitionParams) {
|
||||
router.post(
|
||||
{
|
||||
path: '/internal/interactive_setup/enroll',
|
||||
validate: {
|
||||
body: schema.object({ token: schema.string() }),
|
||||
},
|
||||
options: { authRequired: false },
|
||||
},
|
||||
async (context, request, response) => {
|
||||
return response.forbidden({
|
||||
body: { message: `API is not implemented yet.` },
|
||||
});
|
||||
}
|
||||
);
|
||||
}
|
28
src/plugins/interactive_setup/server/routes/index.ts
Normal file
28
src/plugins/interactive_setup/server/routes/index.ts
Normal file
|
@ -0,0 +1,28 @@
|
|||
/*
|
||||
* 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 and the Server Side Public License, v 1; you may not use this file except
|
||||
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
||||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import type { IBasePath, IRouter, Logger } from 'src/core/server';
|
||||
|
||||
import type { ElasticsearchConnectionStatus } from '../../common';
|
||||
import type { ConfigType } from '../config';
|
||||
import { defineEnrollRoutes } from './enroll';
|
||||
|
||||
/**
|
||||
* Describes parameters used to define HTTP routes.
|
||||
*/
|
||||
export interface RouteDefinitionParams {
|
||||
readonly router: IRouter;
|
||||
readonly basePath: IBasePath;
|
||||
readonly logger: Logger;
|
||||
readonly getConfig: () => ConfigType;
|
||||
readonly getElasticsearchConnectionStatus: () => ElasticsearchConnectionStatus;
|
||||
}
|
||||
|
||||
export function defineRoutes(params: RouteDefinitionParams) {
|
||||
defineEnrollRoutes(params);
|
||||
}
|
|
@ -7,6 +7,6 @@
|
|||
"declaration": true,
|
||||
"declarationMap": true
|
||||
},
|
||||
"include": ["public/**/*", "server/**/*"],
|
||||
"include": ["common/**/*", "public/**/*", "server/**/*"],
|
||||
"references": [{ "path": "../../core/tsconfig.json" }]
|
||||
}
|
|
@ -31,6 +31,7 @@
|
|||
{ "path": "./src/plugins/expressions/tsconfig.json" },
|
||||
{ "path": "./src/plugins/home/tsconfig.json" },
|
||||
{ "path": "./src/plugins/inspector/tsconfig.json" },
|
||||
{ "path": "./src/plugins/interactive_setup/tsconfig.json" },
|
||||
{ "path": "./src/plugins/kibana_legacy/tsconfig.json" },
|
||||
{ "path": "./src/plugins/kibana_overview/tsconfig.json" },
|
||||
{ "path": "./src/plugins/kibana_react/tsconfig.json" },
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
{ "path": "./src/plugins/expressions/tsconfig.json" },
|
||||
{ "path": "./src/plugins/home/tsconfig.json" },
|
||||
{ "path": "./src/plugins/inspector/tsconfig.json" },
|
||||
{ "path": "./src/plugins/interactive_setup/tsconfig.json" },
|
||||
{ "path": "./src/plugins/kibana_legacy/tsconfig.json" },
|
||||
{ "path": "./src/plugins/kibana_overview/tsconfig.json" },
|
||||
{ "path": "./src/plugins/kibana_react/tsconfig.json" },
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue