Skip to content

Commit

Permalink
Implement interactiveSetup plugin server side functionality: `setup…
Browse files Browse the repository at this point in the history
…` layout (elastic#105222)
  • Loading branch information
azasypkin authored and vadimkibana committed Aug 8, 2021
1 parent b3eae15 commit 2ff8327
Show file tree
Hide file tree
Showing 22 changed files with 280 additions and 25 deletions.
1 change: 1 addition & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -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}',
Expand Down
4 changes: 2 additions & 2 deletions .github/CODEOWNERS
Validating CODEOWNERS rules …
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions .i18nrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
8 changes: 4 additions & 4 deletions docs/developer/plugin-list.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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.
Expand Down
2 changes: 1 addition & 1 deletion packages/kbn-optimizer/limits.yml
Original file line number Diff line number Diff line change
Expand Up @@ -117,4 +117,4 @@ pageLoadAssetSize:
expressionImage: 19288
expressionMetric: 22238
expressionShape: 30033
userSetup: 18532
interactiveSetup: 18532
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
# `userSetup` plugin
# `interactiveSetup` plugin

The plugin provides UI and APIs for the interactive setup mode.
Original file line number Diff line number Diff line change
@@ -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',
}
Original file line number Diff line number Diff line change
Expand Up @@ -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 changes: 45 additions & 0 deletions src/plugins/interactive_setup/common/types.ts
Original file line number Diff line number Diff line change
@@ -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;
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,5 @@
module.exports = {
preset: '@kbn/test',
rootDir: '../../..',
roots: ['<rootDir>/src/plugins/user_setup'],
roots: ['<rootDir>/src/plugins/interactive_setup'],
};
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
{
"id": "userSetup",
"id": "interactiveSetup",
"owner": {
"name": "Platform Security",
"githubTeam": "kibana-security"
},
"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
}
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand All @@ -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 changes: 119 additions & 0 deletions src/plugins/interactive_setup/server/plugin.ts
Original file line number Diff line number Diff line change
@@ -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 changes: 31 additions & 0 deletions src/plugins/interactive_setup/server/routes/enroll.ts
Original file line number Diff line number Diff line change
@@ -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 changes: 28 additions & 0 deletions src/plugins/interactive_setup/server/routes/index.ts
Original file line number Diff line number Diff line change
@@ -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);
}
Loading

0 comments on commit 2ff8327

Please sign in to comment.