diff --git a/.ci/Jenkinsfile_flaky b/.ci/Jenkinsfile_flaky
index 669395564db447..f702405aad69e3 100644
--- a/.ci/Jenkinsfile_flaky
+++ b/.ci/Jenkinsfile_flaky
@@ -99,7 +99,7 @@ def getWorkerMap(agentNumber, numberOfExecutions, worker, workerFailures, maxWor
def numberOfWorkers = Math.min(numberOfExecutions, maxWorkerProcesses)
for(def i = 1; i <= numberOfWorkers; i++) {
- def workerExecutions = numberOfExecutions/numberOfWorkers + (i <= numberOfExecutions%numberOfWorkers ? 1 : 0)
+ def workerExecutions = floor(numberOfExecutions/numberOfWorkers + (i <= numberOfExecutions%numberOfWorkers ? 1 : 0))
workerMap["agent-${agentNumber}-worker-${i}"] = { workerNumber ->
for(def j = 0; j < workerExecutions; j++) {
diff --git a/.eslintrc.js b/.eslintrc.js
index c43366abf0c3d8..a7bb204da47751 100644
--- a/.eslintrc.js
+++ b/.eslintrc.js
@@ -82,31 +82,6 @@ module.exports = {
'react-hooks/exhaustive-deps': 'off',
},
},
- {
- files: ['src/legacy/core_plugins/kibana/**/*.{js,ts,tsx}'],
- rules: {
- 'react-hooks/rules-of-hooks': 'off',
- 'react-hooks/exhaustive-deps': 'off',
- },
- },
- {
- files: ['src/legacy/core_plugins/tile_map/**/*.{js,ts,tsx}'],
- rules: {
- 'react-hooks/exhaustive-deps': 'off',
- },
- },
- {
- files: ['src/legacy/core_plugins/vis_type_markdown/**/*.{js,ts,tsx}'],
- rules: {
- 'react-hooks/exhaustive-deps': 'off',
- },
- },
- {
- files: ['src/legacy/core_plugins/vis_type_metric/**/*.{js,ts,tsx}'],
- rules: {
- 'jsx-a11y/click-events-have-key-events': 'off',
- },
- },
{
files: ['src/legacy/core_plugins/vis_type_table/**/*.{js,ts,tsx}'],
rules: {
@@ -366,9 +341,8 @@ module.exports = {
'src/fixtures/**/*.js', // TODO: this directory needs to be more obviously "public" (or go away)
],
settings: {
- // instructs import/no-extraneous-dependencies to treat modules
- // in plugins/ or ui/ namespace as "core modules" so they don't
- // trigger failures for not being listed in package.json
+ // instructs import/no-extraneous-dependencies to treat certain modules
+ // as core modules, even if they aren't listed in package.json
'import/core-modules': [
'plugins',
'legacy/ui',
diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS
index a0a22446ba31d1..9a4f2b71da1ffb 100644
--- a/.github/CODEOWNERS
+++ b/.github/CODEOWNERS
@@ -86,6 +86,7 @@
/packages/kbn-es/ @elastic/kibana-operations
/packages/kbn-pm/ @elastic/kibana-operations
/packages/kbn-test/ @elastic/kibana-operations
+/packages/kbn-ui-shared-deps/ @elastic/kibana-operations
/src/legacy/server/keystore/ @elastic/kibana-operations
/src/legacy/server/pid/ @elastic/kibana-operations
/src/legacy/server/sass/ @elastic/kibana-operations
diff --git a/docs/development/core/public/kibana-plugin-public.appbase.chromeless.md b/docs/development/core/public/kibana-plugin-public.appbase.chromeless.md
new file mode 100644
index 00000000000000..ddbf9aafbd28a5
--- /dev/null
+++ b/docs/development/core/public/kibana-plugin-public.appbase.chromeless.md
@@ -0,0 +1,13 @@
+
+
+[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [AppBase](./kibana-plugin-public.appbase.md) > [chromeless](./kibana-plugin-public.appbase.chromeless.md)
+
+## AppBase.chromeless property
+
+Hide the UI chrome when the application is mounted. Defaults to `false`. Takes precedence over chrome service visibility settings.
+
+Signature:
+
+```typescript
+chromeless?: boolean;
+```
diff --git a/docs/development/core/public/kibana-plugin-public.appbase.id.md b/docs/development/core/public/kibana-plugin-public.appbase.id.md
index 57daa0c94bdf6b..89dd32d296104c 100644
--- a/docs/development/core/public/kibana-plugin-public.appbase.id.md
+++ b/docs/development/core/public/kibana-plugin-public.appbase.id.md
@@ -4,6 +4,8 @@
## AppBase.id property
+The unique identifier of the application
+
Signature:
```typescript
diff --git a/docs/development/core/public/kibana-plugin-public.appbase.md b/docs/development/core/public/kibana-plugin-public.appbase.md
index a93a195c559b1b..eb6d91cb924888 100644
--- a/docs/development/core/public/kibana-plugin-public.appbase.md
+++ b/docs/development/core/public/kibana-plugin-public.appbase.md
@@ -16,10 +16,14 @@ export interface AppBase
| Property | Type | Description |
| --- | --- | --- |
| [capabilities](./kibana-plugin-public.appbase.capabilities.md) | Partial<Capabilities> | Custom capabilities defined by the app. |
+| [chromeless](./kibana-plugin-public.appbase.chromeless.md) | boolean | Hide the UI chrome when the application is mounted. Defaults to false. Takes precedence over chrome service visibility settings. |
| [euiIconType](./kibana-plugin-public.appbase.euiicontype.md) | string | A EUI iconType that will be used for the app's icon. This icon takes precendence over the icon property. |
| [icon](./kibana-plugin-public.appbase.icon.md) | string | A URL to an image file used as an icon. Used as a fallback if euiIconType is not provided. |
-| [id](./kibana-plugin-public.appbase.id.md) | string | |
+| [id](./kibana-plugin-public.appbase.id.md) | string | The unique identifier of the application |
+| [navLinkStatus](./kibana-plugin-public.appbase.navlinkstatus.md) | AppNavLinkStatus | The initial status of the application's navLink. Defaulting to visible if status is accessible and hidden if status is inaccessible See [AppNavLinkStatus](./kibana-plugin-public.appnavlinkstatus.md) |
| [order](./kibana-plugin-public.appbase.order.md) | number | An ordinal used to sort nav links relative to one another for display. |
+| [status](./kibana-plugin-public.appbase.status.md) | AppStatus | The initial status of the application. Defaulting to accessible |
| [title](./kibana-plugin-public.appbase.title.md) | string | The title of the application. |
-| [tooltip$](./kibana-plugin-public.appbase.tooltip_.md) | Observable<string> | An observable for a tooltip shown when hovering over app link. |
+| [tooltip](./kibana-plugin-public.appbase.tooltip.md) | string | A tooltip shown when hovering over app link. |
+| [updater$](./kibana-plugin-public.appbase.updater_.md) | Observable<AppUpdater> | An [AppUpdater](./kibana-plugin-public.appupdater.md) observable that can be used to update the application [AppUpdatableFields](./kibana-plugin-public.appupdatablefields.md) at runtime. |
diff --git a/docs/development/core/public/kibana-plugin-public.appbase.navlinkstatus.md b/docs/development/core/public/kibana-plugin-public.appbase.navlinkstatus.md
new file mode 100644
index 00000000000000..d6744c3e757568
--- /dev/null
+++ b/docs/development/core/public/kibana-plugin-public.appbase.navlinkstatus.md
@@ -0,0 +1,13 @@
+
+
+[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [AppBase](./kibana-plugin-public.appbase.md) > [navLinkStatus](./kibana-plugin-public.appbase.navlinkstatus.md)
+
+## AppBase.navLinkStatus property
+
+The initial status of the application's navLink. Defaulting to `visible` if `status` is `accessible` and `hidden` if status is `inaccessible` See [AppNavLinkStatus](./kibana-plugin-public.appnavlinkstatus.md)
+
+Signature:
+
+```typescript
+navLinkStatus?: AppNavLinkStatus;
+```
diff --git a/docs/development/core/public/kibana-plugin-public.appbase.tooltip_.md b/docs/development/core/public/kibana-plugin-public.appbase.status.md
similarity index 56%
rename from docs/development/core/public/kibana-plugin-public.appbase.tooltip_.md
rename to docs/development/core/public/kibana-plugin-public.appbase.status.md
index 0767ead5f1455b..a5fbadbeea1ffc 100644
--- a/docs/development/core/public/kibana-plugin-public.appbase.tooltip_.md
+++ b/docs/development/core/public/kibana-plugin-public.appbase.status.md
@@ -1,13 +1,13 @@
-[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [AppBase](./kibana-plugin-public.appbase.md) > [tooltip$](./kibana-plugin-public.appbase.tooltip_.md)
+[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [AppBase](./kibana-plugin-public.appbase.md) > [status](./kibana-plugin-public.appbase.status.md)
-## AppBase.tooltip$ property
+## AppBase.status property
-An observable for a tooltip shown when hovering over app link.
+The initial status of the application. Defaulting to `accessible`
Signature:
```typescript
-tooltip$?: Observable;
+status?: AppStatus;
```
diff --git a/docs/development/core/public/kibana-plugin-public.appbase.tooltip.md b/docs/development/core/public/kibana-plugin-public.appbase.tooltip.md
new file mode 100644
index 00000000000000..85921a5a321dd2
--- /dev/null
+++ b/docs/development/core/public/kibana-plugin-public.appbase.tooltip.md
@@ -0,0 +1,13 @@
+
+
+[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [AppBase](./kibana-plugin-public.appbase.md) > [tooltip](./kibana-plugin-public.appbase.tooltip.md)
+
+## AppBase.tooltip property
+
+A tooltip shown when hovering over app link.
+
+Signature:
+
+```typescript
+tooltip?: string;
+```
diff --git a/docs/development/core/public/kibana-plugin-public.appbase.updater_.md b/docs/development/core/public/kibana-plugin-public.appbase.updater_.md
new file mode 100644
index 00000000000000..3edd3573834491
--- /dev/null
+++ b/docs/development/core/public/kibana-plugin-public.appbase.updater_.md
@@ -0,0 +1,44 @@
+
+
+[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [AppBase](./kibana-plugin-public.appbase.md) > [updater$](./kibana-plugin-public.appbase.updater_.md)
+
+## AppBase.updater$ property
+
+An [AppUpdater](./kibana-plugin-public.appupdater.md) observable that can be used to update the application [AppUpdatableFields](./kibana-plugin-public.appupdatablefields.md) at runtime.
+
+Signature:
+
+```typescript
+updater$?: Observable;
+```
+
+## Example
+
+How to update an application navLink at runtime
+
+```ts
+// inside your plugin's setup function
+export class MyPlugin implements Plugin {
+ private appUpdater = new BehaviorSubject(() => ({}));
+
+ setup({ application }) {
+ application.register({
+ id: 'my-app',
+ title: 'My App',
+ updater$: this.appUpdater,
+ async mount(params) {
+ const { renderApp } = await import('./application');
+ return renderApp(params);
+ },
+ });
+ }
+
+ start() {
+ // later, when the navlink needs to be updated
+ appUpdater.next(() => {
+ navLinkStatus: AppNavLinkStatus.disabled,
+ })
+ }
+
+```
+
diff --git a/docs/development/core/public/kibana-plugin-public.appleaveaction.md b/docs/development/core/public/kibana-plugin-public.appleaveaction.md
new file mode 100644
index 00000000000000..ae56205f5e45ca
--- /dev/null
+++ b/docs/development/core/public/kibana-plugin-public.appleaveaction.md
@@ -0,0 +1,15 @@
+
+
+[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [AppLeaveAction](./kibana-plugin-public.appleaveaction.md)
+
+## AppLeaveAction type
+
+Possible actions to return from a [AppLeaveHandler](./kibana-plugin-public.appleavehandler.md)
+
+See [AppLeaveConfirmAction](./kibana-plugin-public.appleaveconfirmaction.md) and [AppLeaveDefaultAction](./kibana-plugin-public.appleavedefaultaction.md)
+
+Signature:
+
+```typescript
+export declare type AppLeaveAction = AppLeaveDefaultAction | AppLeaveConfirmAction;
+```
diff --git a/docs/development/core/public/kibana-plugin-public.appleaveactiontype.md b/docs/development/core/public/kibana-plugin-public.appleaveactiontype.md
new file mode 100644
index 00000000000000..482b2e489b33e4
--- /dev/null
+++ b/docs/development/core/public/kibana-plugin-public.appleaveactiontype.md
@@ -0,0 +1,21 @@
+
+
+[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [AppLeaveActionType](./kibana-plugin-public.appleaveactiontype.md)
+
+## AppLeaveActionType enum
+
+Possible type of actions on application leave.
+
+Signature:
+
+```typescript
+export declare enum AppLeaveActionType
+```
+
+## Enumeration Members
+
+| Member | Value | Description |
+| --- | --- | --- |
+| confirm | "confirm" | |
+| default | "default" | |
+
diff --git a/docs/development/core/public/kibana-plugin-public.appleaveconfirmaction.md b/docs/development/core/public/kibana-plugin-public.appleaveconfirmaction.md
new file mode 100644
index 00000000000000..4cd99dd2a3fb3f
--- /dev/null
+++ b/docs/development/core/public/kibana-plugin-public.appleaveconfirmaction.md
@@ -0,0 +1,24 @@
+
+
+[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [AppLeaveConfirmAction](./kibana-plugin-public.appleaveconfirmaction.md)
+
+## AppLeaveConfirmAction interface
+
+Action to return from a [AppLeaveHandler](./kibana-plugin-public.appleavehandler.md) to show a confirmation message when trying to leave an application.
+
+See
+
+Signature:
+
+```typescript
+export interface AppLeaveConfirmAction
+```
+
+## Properties
+
+| Property | Type | Description |
+| --- | --- | --- |
+| [text](./kibana-plugin-public.appleaveconfirmaction.text.md) | string | |
+| [title](./kibana-plugin-public.appleaveconfirmaction.title.md) | string | |
+| [type](./kibana-plugin-public.appleaveconfirmaction.type.md) | AppLeaveActionType.confirm | |
+
diff --git a/docs/development/core/public/kibana-plugin-public.appleaveconfirmaction.text.md b/docs/development/core/public/kibana-plugin-public.appleaveconfirmaction.text.md
new file mode 100644
index 00000000000000..dbbd11c6f71f88
--- /dev/null
+++ b/docs/development/core/public/kibana-plugin-public.appleaveconfirmaction.text.md
@@ -0,0 +1,11 @@
+
+
+[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [AppLeaveConfirmAction](./kibana-plugin-public.appleaveconfirmaction.md) > [text](./kibana-plugin-public.appleaveconfirmaction.text.md)
+
+## AppLeaveConfirmAction.text property
+
+Signature:
+
+```typescript
+text: string;
+```
diff --git a/docs/development/core/public/kibana-plugin-public.appleaveconfirmaction.title.md b/docs/development/core/public/kibana-plugin-public.appleaveconfirmaction.title.md
new file mode 100644
index 00000000000000..684ef384a37c35
--- /dev/null
+++ b/docs/development/core/public/kibana-plugin-public.appleaveconfirmaction.title.md
@@ -0,0 +1,11 @@
+
+
+[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [AppLeaveConfirmAction](./kibana-plugin-public.appleaveconfirmaction.md) > [title](./kibana-plugin-public.appleaveconfirmaction.title.md)
+
+## AppLeaveConfirmAction.title property
+
+Signature:
+
+```typescript
+title?: string;
+```
diff --git a/docs/development/core/public/kibana-plugin-public.appleaveconfirmaction.type.md b/docs/development/core/public/kibana-plugin-public.appleaveconfirmaction.type.md
new file mode 100644
index 00000000000000..926cecf893cc85
--- /dev/null
+++ b/docs/development/core/public/kibana-plugin-public.appleaveconfirmaction.type.md
@@ -0,0 +1,11 @@
+
+
+[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [AppLeaveConfirmAction](./kibana-plugin-public.appleaveconfirmaction.md) > [type](./kibana-plugin-public.appleaveconfirmaction.type.md)
+
+## AppLeaveConfirmAction.type property
+
+Signature:
+
+```typescript
+type: AppLeaveActionType.confirm;
+```
diff --git a/docs/development/core/public/kibana-plugin-public.appleavedefaultaction.md b/docs/development/core/public/kibana-plugin-public.appleavedefaultaction.md
new file mode 100644
index 00000000000000..ed2f729a0c6482
--- /dev/null
+++ b/docs/development/core/public/kibana-plugin-public.appleavedefaultaction.md
@@ -0,0 +1,22 @@
+
+
+[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [AppLeaveDefaultAction](./kibana-plugin-public.appleavedefaultaction.md)
+
+## AppLeaveDefaultAction interface
+
+Action to return from a [AppLeaveHandler](./kibana-plugin-public.appleavehandler.md) to execute the default behaviour when leaving the application.
+
+See
+
+Signature:
+
+```typescript
+export interface AppLeaveDefaultAction
+```
+
+## Properties
+
+| Property | Type | Description |
+| --- | --- | --- |
+| [type](./kibana-plugin-public.appleavedefaultaction.type.md) | AppLeaveActionType.default | |
+
diff --git a/docs/development/core/public/kibana-plugin-public.appleavedefaultaction.type.md b/docs/development/core/public/kibana-plugin-public.appleavedefaultaction.type.md
new file mode 100644
index 00000000000000..ee12393121a5a4
--- /dev/null
+++ b/docs/development/core/public/kibana-plugin-public.appleavedefaultaction.type.md
@@ -0,0 +1,11 @@
+
+
+[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [AppLeaveDefaultAction](./kibana-plugin-public.appleavedefaultaction.md) > [type](./kibana-plugin-public.appleavedefaultaction.type.md)
+
+## AppLeaveDefaultAction.type property
+
+Signature:
+
+```typescript
+type: AppLeaveActionType.default;
+```
diff --git a/docs/development/core/public/kibana-plugin-public.appleavehandler.md b/docs/development/core/public/kibana-plugin-public.appleavehandler.md
new file mode 100644
index 00000000000000..e879227961bc6f
--- /dev/null
+++ b/docs/development/core/public/kibana-plugin-public.appleavehandler.md
@@ -0,0 +1,15 @@
+
+
+[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [AppLeaveHandler](./kibana-plugin-public.appleavehandler.md)
+
+## AppLeaveHandler type
+
+A handler that will be executed before leaving the application, either when going to another application or when closing the browser tab or manually changing the url. Should return `confirm` to to prompt a message to the user before leaving the page, or `default` to keep the default behavior (doing nothing).
+
+See [AppMountParameters](./kibana-plugin-public.appmountparameters.md) for detailed usage examples.
+
+Signature:
+
+```typescript
+export declare type AppLeaveHandler = (factory: AppLeaveActionFactory) => AppLeaveAction;
+```
diff --git a/docs/development/core/public/kibana-plugin-public.applicationsetup.md b/docs/development/core/public/kibana-plugin-public.applicationsetup.md
index a63de399c2ecb4..cf9bc5189af409 100644
--- a/docs/development/core/public/kibana-plugin-public.applicationsetup.md
+++ b/docs/development/core/public/kibana-plugin-public.applicationsetup.md
@@ -16,5 +16,6 @@ export interface ApplicationSetup
| Method | Description |
| --- | --- |
| [register(app)](./kibana-plugin-public.applicationsetup.register.md) | Register an mountable application to the system. |
+| [registerAppUpdater(appUpdater$)](./kibana-plugin-public.applicationsetup.registerappupdater.md) | Register an application updater that can be used to change the [AppUpdatableFields](./kibana-plugin-public.appupdatablefields.md) fields of all applications at runtime.This is meant to be used by plugins that needs to updates the whole list of applications. To only updates a specific application, use the updater$ property of the registered application instead. |
| [registerMountContext(contextName, provider)](./kibana-plugin-public.applicationsetup.registermountcontext.md) | Register a context provider for application mounting. Will only be available to applications that depend on the plugin that registered this context. Deprecated, use [CoreSetup.getStartServices()](./kibana-plugin-public.coresetup.getstartservices.md). |
diff --git a/docs/development/core/public/kibana-plugin-public.applicationsetup.registerappupdater.md b/docs/development/core/public/kibana-plugin-public.applicationsetup.registerappupdater.md
new file mode 100644
index 00000000000000..39b4f878a3f795
--- /dev/null
+++ b/docs/development/core/public/kibana-plugin-public.applicationsetup.registerappupdater.md
@@ -0,0 +1,47 @@
+
+
+[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ApplicationSetup](./kibana-plugin-public.applicationsetup.md) > [registerAppUpdater](./kibana-plugin-public.applicationsetup.registerappupdater.md)
+
+## ApplicationSetup.registerAppUpdater() method
+
+Register an application updater that can be used to change the [AppUpdatableFields](./kibana-plugin-public.appupdatablefields.md) fields of all applications at runtime.
+
+This is meant to be used by plugins that needs to updates the whole list of applications. To only updates a specific application, use the `updater$` property of the registered application instead.
+
+Signature:
+
+```typescript
+registerAppUpdater(appUpdater$: Observable): void;
+```
+
+## Parameters
+
+| Parameter | Type | Description |
+| --- | --- | --- |
+| appUpdater$ | Observable<AppUpdater> | |
+
+Returns:
+
+`void`
+
+## Example
+
+How to register an application updater that disables some applications:
+
+```ts
+// inside your plugin's setup function
+export class MyPlugin implements Plugin {
+ setup({ application }) {
+ application.registerAppUpdater(
+ new BehaviorSubject(app => {
+ if (myPluginApi.shouldDisable(app))
+ return {
+ status: AppStatus.inaccessible,
+ };
+ })
+ );
+ }
+}
+
+```
+
diff --git a/docs/development/core/public/kibana-plugin-public.applicationstart.md b/docs/development/core/public/kibana-plugin-public.applicationstart.md
index 4baa4565ff7b06..e36ef3f14f87e8 100644
--- a/docs/development/core/public/kibana-plugin-public.applicationstart.md
+++ b/docs/development/core/public/kibana-plugin-public.applicationstart.md
@@ -22,6 +22,6 @@ export interface ApplicationStart
| Method | Description |
| --- | --- |
| [getUrlForApp(appId, options)](./kibana-plugin-public.applicationstart.geturlforapp.md) | Returns a relative URL to a given app, including the global base path. |
-| [navigateToApp(appId, options)](./kibana-plugin-public.applicationstart.navigatetoapp.md) | Navigiate to a given app |
+| [navigateToApp(appId, options)](./kibana-plugin-public.applicationstart.navigatetoapp.md) | Navigate to a given app |
| [registerMountContext(contextName, provider)](./kibana-plugin-public.applicationstart.registermountcontext.md) | Register a context provider for application mounting. Will only be available to applications that depend on the plugin that registered this context. Deprecated, use [CoreSetup.getStartServices()](./kibana-plugin-public.coresetup.getstartservices.md). |
diff --git a/docs/development/core/public/kibana-plugin-public.applicationstart.navigatetoapp.md b/docs/development/core/public/kibana-plugin-public.applicationstart.navigatetoapp.md
index eef31fe661f54f..3e29d09ea4cd56 100644
--- a/docs/development/core/public/kibana-plugin-public.applicationstart.navigatetoapp.md
+++ b/docs/development/core/public/kibana-plugin-public.applicationstart.navigatetoapp.md
@@ -4,7 +4,7 @@
## ApplicationStart.navigateToApp() method
-Navigiate to a given app
+Navigate to a given app
Signature:
@@ -12,7 +12,7 @@ Navigiate to a given app
navigateToApp(appId: string, options?: {
path?: string;
state?: any;
- }): void;
+ }): Promise;
```
## Parameters
@@ -24,5 +24,5 @@ navigateToApp(appId: string, options?: {
Returns:
-`void`
+`Promise`
diff --git a/docs/development/core/public/kibana-plugin-public.appmountparameters.md b/docs/development/core/public/kibana-plugin-public.appmountparameters.md
index aa5ca93ed8ff03..9586eba96a697b 100644
--- a/docs/development/core/public/kibana-plugin-public.appmountparameters.md
+++ b/docs/development/core/public/kibana-plugin-public.appmountparameters.md
@@ -17,4 +17,5 @@ export interface AppMountParameters
| --- | --- | --- |
| [appBasePath](./kibana-plugin-public.appmountparameters.appbasepath.md) | string | The route path for configuring navigation to the application. This string should not include the base path from HTTP. |
| [element](./kibana-plugin-public.appmountparameters.element.md) | HTMLElement | The container element to render the application into. |
+| [onAppLeave](./kibana-plugin-public.appmountparameters.onappleave.md) | (handler: AppLeaveHandler) => void | A function that can be used to register a handler that will be called when the user is leaving the current application, allowing to prompt a confirmation message before actually changing the page.This will be called either when the user goes to another application, or when trying to close the tab or manually changing the url. |
diff --git a/docs/development/core/public/kibana-plugin-public.appmountparameters.onappleave.md b/docs/development/core/public/kibana-plugin-public.appmountparameters.onappleave.md
new file mode 100644
index 00000000000000..55eb840ce1cf68
--- /dev/null
+++ b/docs/development/core/public/kibana-plugin-public.appmountparameters.onappleave.md
@@ -0,0 +1,41 @@
+
+
+[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [AppMountParameters](./kibana-plugin-public.appmountparameters.md) > [onAppLeave](./kibana-plugin-public.appmountparameters.onappleave.md)
+
+## AppMountParameters.onAppLeave property
+
+A function that can be used to register a handler that will be called when the user is leaving the current application, allowing to prompt a confirmation message before actually changing the page.
+
+This will be called either when the user goes to another application, or when trying to close the tab or manually changing the url.
+
+Signature:
+
+```typescript
+onAppLeave: (handler: AppLeaveHandler) => void;
+```
+
+## Example
+
+
+```ts
+// application.tsx
+import React from 'react';
+import ReactDOM from 'react-dom';
+import { BrowserRouter, Route } from 'react-router-dom';
+
+import { CoreStart, AppMountParams } from 'src/core/public';
+import { MyPluginDepsStart } from './plugin';
+
+export renderApp = ({ appBasePath, element, onAppLeave }: AppMountParams) => {
+ const { renderApp, hasUnsavedChanges } = await import('./application');
+ onAppLeave(actions => {
+ if(hasUnsavedChanges()) {
+ return actions.confirm('Some changes were not saved. Are you sure you want to leave?');
+ }
+ return actions.default();
+ });
+ return renderApp(params);
+}
+
+```
+
diff --git a/docs/development/core/public/kibana-plugin-public.appnavlinkstatus.md b/docs/development/core/public/kibana-plugin-public.appnavlinkstatus.md
new file mode 100644
index 00000000000000..d6b22ac2b92178
--- /dev/null
+++ b/docs/development/core/public/kibana-plugin-public.appnavlinkstatus.md
@@ -0,0 +1,23 @@
+
+
+[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [AppNavLinkStatus](./kibana-plugin-public.appnavlinkstatus.md)
+
+## AppNavLinkStatus enum
+
+Status of the application's navLink.
+
+Signature:
+
+```typescript
+export declare enum AppNavLinkStatus
+```
+
+## Enumeration Members
+
+| Member | Value | Description |
+| --- | --- | --- |
+| default | 0 | The application navLink will be visible if the application's [AppStatus](./kibana-plugin-public.appstatus.md) is set to accessible and hidden if the application status is set to inaccessible. |
+| disabled | 2 | The application navLink is visible but inactive and not clickable in the navigation bar. |
+| hidden | 3 | The application navLink does not appear in the navigation bar. |
+| visible | 1 | The application navLink is visible and clickable in the navigation bar. |
+
diff --git a/docs/development/core/public/kibana-plugin-public.appstatus.md b/docs/development/core/public/kibana-plugin-public.appstatus.md
new file mode 100644
index 00000000000000..23fb7186569dad
--- /dev/null
+++ b/docs/development/core/public/kibana-plugin-public.appstatus.md
@@ -0,0 +1,21 @@
+
+
+[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [AppStatus](./kibana-plugin-public.appstatus.md)
+
+## AppStatus enum
+
+Accessibility status of an application.
+
+Signature:
+
+```typescript
+export declare enum AppStatus
+```
+
+## Enumeration Members
+
+| Member | Value | Description |
+| --- | --- | --- |
+| accessible | 0 | Application is accessible. |
+| inaccessible | 1 | Application is not accessible. |
+
diff --git a/docs/development/core/public/kibana-plugin-public.appupdatablefields.md b/docs/development/core/public/kibana-plugin-public.appupdatablefields.md
new file mode 100644
index 00000000000000..b9260c79cd972b
--- /dev/null
+++ b/docs/development/core/public/kibana-plugin-public.appupdatablefields.md
@@ -0,0 +1,13 @@
+
+
+[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [AppUpdatableFields](./kibana-plugin-public.appupdatablefields.md)
+
+## AppUpdatableFields type
+
+Defines the list of fields that can be updated via an [AppUpdater](./kibana-plugin-public.appupdater.md).
+
+Signature:
+
+```typescript
+export declare type AppUpdatableFields = Pick;
+```
diff --git a/docs/development/core/public/kibana-plugin-public.appupdater.md b/docs/development/core/public/kibana-plugin-public.appupdater.md
new file mode 100644
index 00000000000000..f1b965cc2fc22f
--- /dev/null
+++ b/docs/development/core/public/kibana-plugin-public.appupdater.md
@@ -0,0 +1,13 @@
+
+
+[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [AppUpdater](./kibana-plugin-public.appupdater.md)
+
+## AppUpdater type
+
+Updater for applications. see [ApplicationSetup](./kibana-plugin-public.applicationsetup.md)
+
+Signature:
+
+```typescript
+export declare type AppUpdater = (app: AppBase) => Partial | undefined;
+```
diff --git a/docs/development/core/public/kibana-plugin-public.chromenavlink.md b/docs/development/core/public/kibana-plugin-public.chromenavlink.md
index 93ebbe3653ac40..4cb9080222ac54 100644
--- a/docs/development/core/public/kibana-plugin-public.chromenavlink.md
+++ b/docs/development/core/public/kibana-plugin-public.chromenavlink.md
@@ -24,7 +24,7 @@ export interface ChromeNavLink
| [id](./kibana-plugin-public.chromenavlink.id.md) | string | A unique identifier for looking up links. |
| [linkToLastSubUrl](./kibana-plugin-public.chromenavlink.linktolastsuburl.md) | boolean | Whether or not the subUrl feature should be enabled. |
| [order](./kibana-plugin-public.chromenavlink.order.md) | number | An ordinal used to sort nav links relative to one another for display. |
-| [subUrlBase](./kibana-plugin-public.chromenavlink.suburlbase.md) | string | A url base that legacy apps can set to match deep URLs to an applcation. |
+| [subUrlBase](./kibana-plugin-public.chromenavlink.suburlbase.md) | string | A url base that legacy apps can set to match deep URLs to an application. |
| [title](./kibana-plugin-public.chromenavlink.title.md) | string | The title of the application. |
| [tooltip](./kibana-plugin-public.chromenavlink.tooltip.md) | string | A tooltip shown when hovering over an app link. |
| [url](./kibana-plugin-public.chromenavlink.url.md) | string | A url that legacy apps can set to deep link into their applications. |
diff --git a/docs/development/core/public/kibana-plugin-public.chromenavlink.suburlbase.md b/docs/development/core/public/kibana-plugin-public.chromenavlink.suburlbase.md
index b9d12432a01df9..1b8fb0574cf8be 100644
--- a/docs/development/core/public/kibana-plugin-public.chromenavlink.suburlbase.md
+++ b/docs/development/core/public/kibana-plugin-public.chromenavlink.suburlbase.md
@@ -8,7 +8,7 @@
>
>
-A url base that legacy apps can set to match deep URLs to an applcation.
+A url base that legacy apps can set to match deep URLs to an application.
Signature:
diff --git a/docs/development/core/public/kibana-plugin-public.md b/docs/development/core/public/kibana-plugin-public.md
index e2c2866b57b6b0..64cbdd880fed1a 100644
--- a/docs/development/core/public/kibana-plugin-public.md
+++ b/docs/development/core/public/kibana-plugin-public.md
@@ -1,137 +1,151 @@
-
-
-[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md)
-
-## kibana-plugin-public package
-
-The Kibana Core APIs for client-side plugins.
-
-A plugin's `public/index` file must contain a named import, `plugin`, that implements [PluginInitializer](./kibana-plugin-public.plugininitializer.md) which returns an object that implements [Plugin](./kibana-plugin-public.plugin.md).
-
-The plugin integrates with the core system via lifecycle events: `setup`, `start`, and `stop`. In each lifecycle method, the plugin will receive the corresponding core services available (either [CoreSetup](./kibana-plugin-public.coresetup.md) or [CoreStart](./kibana-plugin-public.corestart.md)) and any interfaces returned by dependency plugins' lifecycle method. Anything returned by the plugin's lifecycle method will be exposed to downstream dependencies when their corresponding lifecycle methods are invoked.
-
-## Classes
-
-| Class | Description |
-| --- | --- |
-| [SavedObjectsClient](./kibana-plugin-public.savedobjectsclient.md) | Saved Objects is Kibana's data persisentence mechanism allowing plugins to use Elasticsearch for storing plugin state. The client-side SavedObjectsClient is a thin convenience library around the SavedObjects HTTP API for interacting with Saved Objects. |
-| [SimpleSavedObject](./kibana-plugin-public.simplesavedobject.md) | This class is a very simple wrapper for SavedObjects loaded from the server with the [SavedObjectsClient](./kibana-plugin-public.savedobjectsclient.md).It provides basic functionality for creating/saving/deleting saved objects, but doesn't include any type-specific implementations. |
-| [ToastsApi](./kibana-plugin-public.toastsapi.md) | Methods for adding and removing global toast messages. |
-
-## Interfaces
-
-| Interface | Description |
-| --- | --- |
-| [App](./kibana-plugin-public.app.md) | Extension of [common app properties](./kibana-plugin-public.appbase.md) with the mount function. |
-| [AppBase](./kibana-plugin-public.appbase.md) | |
-| [ApplicationSetup](./kibana-plugin-public.applicationsetup.md) | |
-| [ApplicationStart](./kibana-plugin-public.applicationstart.md) | |
-| [AppMountContext](./kibana-plugin-public.appmountcontext.md) | The context object received when applications are mounted to the DOM. Deprecated, use [CoreSetup.getStartServices()](./kibana-plugin-public.coresetup.getstartservices.md). |
-| [AppMountParameters](./kibana-plugin-public.appmountparameters.md) | |
-| [Capabilities](./kibana-plugin-public.capabilities.md) | The read-only set of capabilities available for the current UI session. Capabilities are simple key-value pairs of (string, boolean), where the string denotes the capability ID, and the boolean is a flag indicating if the capability is enabled or disabled. |
-| [ChromeBadge](./kibana-plugin-public.chromebadge.md) | |
-| [ChromeBrand](./kibana-plugin-public.chromebrand.md) | |
-| [ChromeDocTitle](./kibana-plugin-public.chromedoctitle.md) | APIs for accessing and updating the document title. |
-| [ChromeHelpExtension](./kibana-plugin-public.chromehelpextension.md) | |
-| [ChromeNavControl](./kibana-plugin-public.chromenavcontrol.md) | |
-| [ChromeNavControls](./kibana-plugin-public.chromenavcontrols.md) | [APIs](./kibana-plugin-public.chromenavcontrols.md) for registering new controls to be displayed in the navigation bar. |
-| [ChromeNavLink](./kibana-plugin-public.chromenavlink.md) | |
-| [ChromeNavLinks](./kibana-plugin-public.chromenavlinks.md) | [APIs](./kibana-plugin-public.chromenavlinks.md) for manipulating nav links. |
-| [ChromeRecentlyAccessed](./kibana-plugin-public.chromerecentlyaccessed.md) | [APIs](./kibana-plugin-public.chromerecentlyaccessed.md) for recently accessed history. |
-| [ChromeRecentlyAccessedHistoryItem](./kibana-plugin-public.chromerecentlyaccessedhistoryitem.md) | |
-| [ChromeStart](./kibana-plugin-public.chromestart.md) | ChromeStart allows plugins to customize the global chrome header UI and enrich the UX with additional information about the current location of the browser. |
-| [ContextSetup](./kibana-plugin-public.contextsetup.md) | An object that handles registration of context providers and configuring handlers with context. |
-| [CoreSetup](./kibana-plugin-public.coresetup.md) | Core services exposed to the Plugin setup lifecycle |
-| [CoreStart](./kibana-plugin-public.corestart.md) | Core services exposed to the Plugin start lifecycle |
-| [DocLinksStart](./kibana-plugin-public.doclinksstart.md) | |
-| [EnvironmentMode](./kibana-plugin-public.environmentmode.md) | |
-| [ErrorToastOptions](./kibana-plugin-public.errortoastoptions.md) | Options available for [IToasts](./kibana-plugin-public.itoasts.md) APIs. |
-| [FatalErrorInfo](./kibana-plugin-public.fatalerrorinfo.md) | Represents the message and stack of a fatal Error |
-| [FatalErrorsSetup](./kibana-plugin-public.fatalerrorssetup.md) | FatalErrors stop the Kibana Public Core and displays a fatal error screen with details about the Kibana build and the error. |
-| [HttpErrorRequest](./kibana-plugin-public.httperrorrequest.md) | |
-| [HttpErrorResponse](./kibana-plugin-public.httperrorresponse.md) | |
-| [HttpFetchOptions](./kibana-plugin-public.httpfetchoptions.md) | All options that may be used with a [HttpHandler](./kibana-plugin-public.httphandler.md). |
-| [HttpFetchQuery](./kibana-plugin-public.httpfetchquery.md) | |
-| [HttpHandler](./kibana-plugin-public.httphandler.md) | A function for making an HTTP requests to Kibana's backend. See [HttpFetchOptions](./kibana-plugin-public.httpfetchoptions.md) for options and [IHttpResponse](./kibana-plugin-public.ihttpresponse.md) for the response. |
-| [HttpHeadersInit](./kibana-plugin-public.httpheadersinit.md) | |
-| [HttpInterceptor](./kibana-plugin-public.httpinterceptor.md) | An object that may define global interceptor functions for different parts of the request and response lifecycle. See [IHttpInterceptController](./kibana-plugin-public.ihttpinterceptcontroller.md). |
-| [HttpRequestInit](./kibana-plugin-public.httprequestinit.md) | Fetch API options available to [HttpHandler](./kibana-plugin-public.httphandler.md)s. |
-| [HttpSetup](./kibana-plugin-public.httpsetup.md) | |
-| [I18nStart](./kibana-plugin-public.i18nstart.md) | I18nStart.Context is required by any localizable React component from @kbn/i18n and @elastic/eui packages and is supposed to be used as the topmost component for any i18n-compatible React tree. |
-| [IAnonymousPaths](./kibana-plugin-public.ianonymouspaths.md) | APIs for denoting paths as not requiring authentication |
-| [IBasePath](./kibana-plugin-public.ibasepath.md) | APIs for manipulating the basePath on URL segments. |
-| [IContextContainer](./kibana-plugin-public.icontextcontainer.md) | An object that handles registration of context providers and configuring handlers with context. |
-| [IHttpFetchError](./kibana-plugin-public.ihttpfetcherror.md) | |
-| [IHttpInterceptController](./kibana-plugin-public.ihttpinterceptcontroller.md) | Used to halt a request Promise chain in a [HttpInterceptor](./kibana-plugin-public.httpinterceptor.md). |
-| [IHttpResponse](./kibana-plugin-public.ihttpresponse.md) | |
-| [IHttpResponseInterceptorOverrides](./kibana-plugin-public.ihttpresponseinterceptoroverrides.md) | Properties that can be returned by HttpInterceptor.request to override the response. |
-| [IUiSettingsClient](./kibana-plugin-public.iuisettingsclient.md) | Client-side client that provides access to the advanced settings stored in elasticsearch. The settings provide control over the behavior of the Kibana application. For example, a user can specify how to display numeric or date fields. Users can adjust the settings via Management UI. [IUiSettingsClient](./kibana-plugin-public.iuisettingsclient.md) |
-| [LegacyCoreSetup](./kibana-plugin-public.legacycoresetup.md) | Setup interface exposed to the legacy platform via the ui/new_platform module. |
-| [LegacyCoreStart](./kibana-plugin-public.legacycorestart.md) | Start interface exposed to the legacy platform via the ui/new_platform module. |
-| [LegacyNavLink](./kibana-plugin-public.legacynavlink.md) | |
-| [NotificationsSetup](./kibana-plugin-public.notificationssetup.md) | |
-| [NotificationsStart](./kibana-plugin-public.notificationsstart.md) | |
-| [OverlayBannersStart](./kibana-plugin-public.overlaybannersstart.md) | |
-| [OverlayRef](./kibana-plugin-public.overlayref.md) | Returned by [OverlayStart](./kibana-plugin-public.overlaystart.md) methods for closing a mounted overlay. |
-| [OverlayStart](./kibana-plugin-public.overlaystart.md) | |
-| [PackageInfo](./kibana-plugin-public.packageinfo.md) | |
-| [Plugin](./kibana-plugin-public.plugin.md) | The interface that should be returned by a PluginInitializer. |
-| [PluginInitializerContext](./kibana-plugin-public.plugininitializercontext.md) | The available core services passed to a PluginInitializer |
-| [SavedObject](./kibana-plugin-public.savedobject.md) | |
-| [SavedObjectAttributes](./kibana-plugin-public.savedobjectattributes.md) | The data for a Saved Object is stored as an object in the attributes property. |
-| [SavedObjectReference](./kibana-plugin-public.savedobjectreference.md) | A reference to another saved object. |
-| [SavedObjectsBaseOptions](./kibana-plugin-public.savedobjectsbaseoptions.md) | |
-| [SavedObjectsBatchResponse](./kibana-plugin-public.savedobjectsbatchresponse.md) | |
-| [SavedObjectsBulkCreateObject](./kibana-plugin-public.savedobjectsbulkcreateobject.md) | |
-| [SavedObjectsBulkCreateOptions](./kibana-plugin-public.savedobjectsbulkcreateoptions.md) | |
-| [SavedObjectsBulkUpdateObject](./kibana-plugin-public.savedobjectsbulkupdateobject.md) | |
-| [SavedObjectsBulkUpdateOptions](./kibana-plugin-public.savedobjectsbulkupdateoptions.md) | |
-| [SavedObjectsCreateOptions](./kibana-plugin-public.savedobjectscreateoptions.md) | |
-| [SavedObjectsFindOptions](./kibana-plugin-public.savedobjectsfindoptions.md) | |
-| [SavedObjectsFindResponsePublic](./kibana-plugin-public.savedobjectsfindresponsepublic.md) | Return type of the Saved Objects find() method.\*Note\*: this type is different between the Public and Server Saved Objects clients. |
-| [SavedObjectsImportConflictError](./kibana-plugin-public.savedobjectsimportconflicterror.md) | Represents a failure to import due to a conflict. |
-| [SavedObjectsImportError](./kibana-plugin-public.savedobjectsimporterror.md) | Represents a failure to import. |
-| [SavedObjectsImportMissingReferencesError](./kibana-plugin-public.savedobjectsimportmissingreferenceserror.md) | Represents a failure to import due to missing references. |
-| [SavedObjectsImportResponse](./kibana-plugin-public.savedobjectsimportresponse.md) | The response describing the result of an import. |
-| [SavedObjectsImportRetry](./kibana-plugin-public.savedobjectsimportretry.md) | Describes a retry operation for importing a saved object. |
-| [SavedObjectsImportUnknownError](./kibana-plugin-public.savedobjectsimportunknownerror.md) | Represents a failure to import due to an unknown reason. |
-| [SavedObjectsImportUnsupportedTypeError](./kibana-plugin-public.savedobjectsimportunsupportedtypeerror.md) | Represents a failure to import due to having an unsupported saved object type. |
-| [SavedObjectsMigrationVersion](./kibana-plugin-public.savedobjectsmigrationversion.md) | Information about the migrations that have been applied to this SavedObject. When Kibana starts up, KibanaMigrator detects outdated documents and migrates them based on this value. For each migration that has been applied, the plugin's name is used as a key and the latest migration version as the value. |
-| [SavedObjectsStart](./kibana-plugin-public.savedobjectsstart.md) | |
-| [SavedObjectsUpdateOptions](./kibana-plugin-public.savedobjectsupdateoptions.md) | |
-| [UiSettingsState](./kibana-plugin-public.uisettingsstate.md) | |
-
-## Type Aliases
-
-| Type Alias | Description |
-| --- | --- |
-| [AppMount](./kibana-plugin-public.appmount.md) | A mount function called when the user navigates to this app's route. |
-| [AppMountDeprecated](./kibana-plugin-public.appmountdeprecated.md) | A mount function called when the user navigates to this app's route. |
-| [AppUnmount](./kibana-plugin-public.appunmount.md) | A function called when an application should be unmounted from the page. This function should be synchronous. |
-| [ChromeBreadcrumb](./kibana-plugin-public.chromebreadcrumb.md) | |
-| [ChromeHelpExtensionMenuCustomLink](./kibana-plugin-public.chromehelpextensionmenucustomlink.md) | |
-| [ChromeHelpExtensionMenuDiscussLink](./kibana-plugin-public.chromehelpextensionmenudiscusslink.md) | |
-| [ChromeHelpExtensionMenuDocumentationLink](./kibana-plugin-public.chromehelpextensionmenudocumentationlink.md) | |
-| [ChromeHelpExtensionMenuGitHubLink](./kibana-plugin-public.chromehelpextensionmenugithublink.md) | |
-| [ChromeHelpExtensionMenuLink](./kibana-plugin-public.chromehelpextensionmenulink.md) | |
-| [ChromeNavLinkUpdateableFields](./kibana-plugin-public.chromenavlinkupdateablefields.md) | |
-| [HandlerContextType](./kibana-plugin-public.handlercontexttype.md) | Extracts the type of the first argument of a [HandlerFunction](./kibana-plugin-public.handlerfunction.md) to represent the type of the context. |
-| [HandlerFunction](./kibana-plugin-public.handlerfunction.md) | A function that accepts a context object and an optional number of additional arguments. Used for the generic types in [IContextContainer](./kibana-plugin-public.icontextcontainer.md) |
-| [HandlerParameters](./kibana-plugin-public.handlerparameters.md) | Extracts the types of the additional arguments of a [HandlerFunction](./kibana-plugin-public.handlerfunction.md), excluding the [HandlerContextType](./kibana-plugin-public.handlercontexttype.md). |
-| [HttpStart](./kibana-plugin-public.httpstart.md) | See [HttpSetup](./kibana-plugin-public.httpsetup.md) |
-| [IContextProvider](./kibana-plugin-public.icontextprovider.md) | A function that returns a context value for a specific key of given context type. |
-| [IToasts](./kibana-plugin-public.itoasts.md) | Methods for adding and removing global toast messages. See [ToastsApi](./kibana-plugin-public.toastsapi.md). |
-| [MountPoint](./kibana-plugin-public.mountpoint.md) | A function that should mount DOM content inside the provided container element and return a handler to unmount it. |
-| [PluginInitializer](./kibana-plugin-public.plugininitializer.md) | The plugin export at the root of a plugin's public directory should conform to this interface. |
-| [PluginOpaqueId](./kibana-plugin-public.pluginopaqueid.md) | |
-| [RecursiveReadonly](./kibana-plugin-public.recursivereadonly.md) | |
-| [SavedObjectAttribute](./kibana-plugin-public.savedobjectattribute.md) | Type definition for a Saved Object attribute value |
-| [SavedObjectAttributeSingle](./kibana-plugin-public.savedobjectattributesingle.md) | Don't use this type, it's simply a helper type for [SavedObjectAttribute](./kibana-plugin-public.savedobjectattribute.md) |
-| [SavedObjectsClientContract](./kibana-plugin-public.savedobjectsclientcontract.md) | SavedObjectsClientContract as implemented by the [SavedObjectsClient](./kibana-plugin-public.savedobjectsclient.md) |
-| [Toast](./kibana-plugin-public.toast.md) | |
-| [ToastInput](./kibana-plugin-public.toastinput.md) | Inputs for [IToasts](./kibana-plugin-public.itoasts.md) APIs. |
-| [ToastInputFields](./kibana-plugin-public.toastinputfields.md) | Allowed fields for [ToastInput](./kibana-plugin-public.toastinput.md). |
-| [ToastsSetup](./kibana-plugin-public.toastssetup.md) | [IToasts](./kibana-plugin-public.itoasts.md) |
-| [ToastsStart](./kibana-plugin-public.toastsstart.md) | [IToasts](./kibana-plugin-public.itoasts.md) |
-| [UnmountCallback](./kibana-plugin-public.unmountcallback.md) | A function that will unmount the element previously mounted by the associated [MountPoint](./kibana-plugin-public.mountpoint.md) |
-
+
+
+[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md)
+
+## kibana-plugin-public package
+
+The Kibana Core APIs for client-side plugins.
+
+A plugin's `public/index` file must contain a named import, `plugin`, that implements [PluginInitializer](./kibana-plugin-public.plugininitializer.md) which returns an object that implements [Plugin](./kibana-plugin-public.plugin.md).
+
+The plugin integrates with the core system via lifecycle events: `setup`, `start`, and `stop`. In each lifecycle method, the plugin will receive the corresponding core services available (either [CoreSetup](./kibana-plugin-public.coresetup.md) or [CoreStart](./kibana-plugin-public.corestart.md)) and any interfaces returned by dependency plugins' lifecycle method. Anything returned by the plugin's lifecycle method will be exposed to downstream dependencies when their corresponding lifecycle methods are invoked.
+
+## Classes
+
+| Class | Description |
+| --- | --- |
+| [SavedObjectsClient](./kibana-plugin-public.savedobjectsclient.md) | Saved Objects is Kibana's data persisentence mechanism allowing plugins to use Elasticsearch for storing plugin state. The client-side SavedObjectsClient is a thin convenience library around the SavedObjects HTTP API for interacting with Saved Objects. |
+| [SimpleSavedObject](./kibana-plugin-public.simplesavedobject.md) | This class is a very simple wrapper for SavedObjects loaded from the server with the [SavedObjectsClient](./kibana-plugin-public.savedobjectsclient.md).It provides basic functionality for creating/saving/deleting saved objects, but doesn't include any type-specific implementations. |
+| [ToastsApi](./kibana-plugin-public.toastsapi.md) | Methods for adding and removing global toast messages. |
+
+## Enumerations
+
+| Enumeration | Description |
+| --- | --- |
+| [AppLeaveActionType](./kibana-plugin-public.appleaveactiontype.md) | Possible type of actions on application leave. |
+| [AppNavLinkStatus](./kibana-plugin-public.appnavlinkstatus.md) | Status of the application's navLink. |
+| [AppStatus](./kibana-plugin-public.appstatus.md) | Accessibility status of an application. |
+
+## Interfaces
+
+| Interface | Description |
+| --- | --- |
+| [App](./kibana-plugin-public.app.md) | Extension of [common app properties](./kibana-plugin-public.appbase.md) with the mount function. |
+| [AppBase](./kibana-plugin-public.appbase.md) | |
+| [AppLeaveConfirmAction](./kibana-plugin-public.appleaveconfirmaction.md) | Action to return from a [AppLeaveHandler](./kibana-plugin-public.appleavehandler.md) to show a confirmation message when trying to leave an application.See |
+| [AppLeaveDefaultAction](./kibana-plugin-public.appleavedefaultaction.md) | Action to return from a [AppLeaveHandler](./kibana-plugin-public.appleavehandler.md) to execute the default behaviour when leaving the application.See |
+| [ApplicationSetup](./kibana-plugin-public.applicationsetup.md) | |
+| [ApplicationStart](./kibana-plugin-public.applicationstart.md) | |
+| [AppMountContext](./kibana-plugin-public.appmountcontext.md) | The context object received when applications are mounted to the DOM. Deprecated, use [CoreSetup.getStartServices()](./kibana-plugin-public.coresetup.getstartservices.md). |
+| [AppMountParameters](./kibana-plugin-public.appmountparameters.md) | |
+| [Capabilities](./kibana-plugin-public.capabilities.md) | The read-only set of capabilities available for the current UI session. Capabilities are simple key-value pairs of (string, boolean), where the string denotes the capability ID, and the boolean is a flag indicating if the capability is enabled or disabled. |
+| [ChromeBadge](./kibana-plugin-public.chromebadge.md) | |
+| [ChromeBrand](./kibana-plugin-public.chromebrand.md) | |
+| [ChromeDocTitle](./kibana-plugin-public.chromedoctitle.md) | APIs for accessing and updating the document title. |
+| [ChromeHelpExtension](./kibana-plugin-public.chromehelpextension.md) | |
+| [ChromeNavControl](./kibana-plugin-public.chromenavcontrol.md) | |
+| [ChromeNavControls](./kibana-plugin-public.chromenavcontrols.md) | [APIs](./kibana-plugin-public.chromenavcontrols.md) for registering new controls to be displayed in the navigation bar. |
+| [ChromeNavLink](./kibana-plugin-public.chromenavlink.md) | |
+| [ChromeNavLinks](./kibana-plugin-public.chromenavlinks.md) | [APIs](./kibana-plugin-public.chromenavlinks.md) for manipulating nav links. |
+| [ChromeRecentlyAccessed](./kibana-plugin-public.chromerecentlyaccessed.md) | [APIs](./kibana-plugin-public.chromerecentlyaccessed.md) for recently accessed history. |
+| [ChromeRecentlyAccessedHistoryItem](./kibana-plugin-public.chromerecentlyaccessedhistoryitem.md) | |
+| [ChromeStart](./kibana-plugin-public.chromestart.md) | ChromeStart allows plugins to customize the global chrome header UI and enrich the UX with additional information about the current location of the browser. |
+| [ContextSetup](./kibana-plugin-public.contextsetup.md) | An object that handles registration of context providers and configuring handlers with context. |
+| [CoreSetup](./kibana-plugin-public.coresetup.md) | Core services exposed to the Plugin setup lifecycle |
+| [CoreStart](./kibana-plugin-public.corestart.md) | Core services exposed to the Plugin start lifecycle |
+| [DocLinksStart](./kibana-plugin-public.doclinksstart.md) | |
+| [EnvironmentMode](./kibana-plugin-public.environmentmode.md) | |
+| [ErrorToastOptions](./kibana-plugin-public.errortoastoptions.md) | Options available for [IToasts](./kibana-plugin-public.itoasts.md) APIs. |
+| [FatalErrorInfo](./kibana-plugin-public.fatalerrorinfo.md) | Represents the message and stack of a fatal Error |
+| [FatalErrorsSetup](./kibana-plugin-public.fatalerrorssetup.md) | FatalErrors stop the Kibana Public Core and displays a fatal error screen with details about the Kibana build and the error. |
+| [HttpErrorRequest](./kibana-plugin-public.httperrorrequest.md) | |
+| [HttpErrorResponse](./kibana-plugin-public.httperrorresponse.md) | |
+| [HttpFetchOptions](./kibana-plugin-public.httpfetchoptions.md) | All options that may be used with a [HttpHandler](./kibana-plugin-public.httphandler.md). |
+| [HttpFetchQuery](./kibana-plugin-public.httpfetchquery.md) | |
+| [HttpHandler](./kibana-plugin-public.httphandler.md) | A function for making an HTTP requests to Kibana's backend. See [HttpFetchOptions](./kibana-plugin-public.httpfetchoptions.md) for options and [IHttpResponse](./kibana-plugin-public.ihttpresponse.md) for the response. |
+| [HttpHeadersInit](./kibana-plugin-public.httpheadersinit.md) | |
+| [HttpInterceptor](./kibana-plugin-public.httpinterceptor.md) | An object that may define global interceptor functions for different parts of the request and response lifecycle. See [IHttpInterceptController](./kibana-plugin-public.ihttpinterceptcontroller.md). |
+| [HttpRequestInit](./kibana-plugin-public.httprequestinit.md) | Fetch API options available to [HttpHandler](./kibana-plugin-public.httphandler.md)s. |
+| [HttpSetup](./kibana-plugin-public.httpsetup.md) | |
+| [I18nStart](./kibana-plugin-public.i18nstart.md) | I18nStart.Context is required by any localizable React component from @kbn/i18n and @elastic/eui packages and is supposed to be used as the topmost component for any i18n-compatible React tree. |
+| [IAnonymousPaths](./kibana-plugin-public.ianonymouspaths.md) | APIs for denoting paths as not requiring authentication |
+| [IBasePath](./kibana-plugin-public.ibasepath.md) | APIs for manipulating the basePath on URL segments. |
+| [IContextContainer](./kibana-plugin-public.icontextcontainer.md) | An object that handles registration of context providers and configuring handlers with context. |
+| [IHttpFetchError](./kibana-plugin-public.ihttpfetcherror.md) | |
+| [IHttpInterceptController](./kibana-plugin-public.ihttpinterceptcontroller.md) | Used to halt a request Promise chain in a [HttpInterceptor](./kibana-plugin-public.httpinterceptor.md). |
+| [IHttpResponse](./kibana-plugin-public.ihttpresponse.md) | |
+| [IHttpResponseInterceptorOverrides](./kibana-plugin-public.ihttpresponseinterceptoroverrides.md) | Properties that can be returned by HttpInterceptor.request to override the response. |
+| [IUiSettingsClient](./kibana-plugin-public.iuisettingsclient.md) | Client-side client that provides access to the advanced settings stored in elasticsearch. The settings provide control over the behavior of the Kibana application. For example, a user can specify how to display numeric or date fields. Users can adjust the settings via Management UI. [IUiSettingsClient](./kibana-plugin-public.iuisettingsclient.md) |
+| [LegacyCoreSetup](./kibana-plugin-public.legacycoresetup.md) | Setup interface exposed to the legacy platform via the ui/new_platform module. |
+| [LegacyCoreStart](./kibana-plugin-public.legacycorestart.md) | Start interface exposed to the legacy platform via the ui/new_platform module. |
+| [LegacyNavLink](./kibana-plugin-public.legacynavlink.md) | |
+| [NotificationsSetup](./kibana-plugin-public.notificationssetup.md) | |
+| [NotificationsStart](./kibana-plugin-public.notificationsstart.md) | |
+| [OverlayBannersStart](./kibana-plugin-public.overlaybannersstart.md) | |
+| [OverlayRef](./kibana-plugin-public.overlayref.md) | Returned by [OverlayStart](./kibana-plugin-public.overlaystart.md) methods for closing a mounted overlay. |
+| [OverlayStart](./kibana-plugin-public.overlaystart.md) | |
+| [PackageInfo](./kibana-plugin-public.packageinfo.md) | |
+| [Plugin](./kibana-plugin-public.plugin.md) | The interface that should be returned by a PluginInitializer. |
+| [PluginInitializerContext](./kibana-plugin-public.plugininitializercontext.md) | The available core services passed to a PluginInitializer |
+| [SavedObject](./kibana-plugin-public.savedobject.md) | |
+| [SavedObjectAttributes](./kibana-plugin-public.savedobjectattributes.md) | The data for a Saved Object is stored as an object in the attributes property. |
+| [SavedObjectReference](./kibana-plugin-public.savedobjectreference.md) | A reference to another saved object. |
+| [SavedObjectsBaseOptions](./kibana-plugin-public.savedobjectsbaseoptions.md) | |
+| [SavedObjectsBatchResponse](./kibana-plugin-public.savedobjectsbatchresponse.md) | |
+| [SavedObjectsBulkCreateObject](./kibana-plugin-public.savedobjectsbulkcreateobject.md) | |
+| [SavedObjectsBulkCreateOptions](./kibana-plugin-public.savedobjectsbulkcreateoptions.md) | |
+| [SavedObjectsBulkUpdateObject](./kibana-plugin-public.savedobjectsbulkupdateobject.md) | |
+| [SavedObjectsBulkUpdateOptions](./kibana-plugin-public.savedobjectsbulkupdateoptions.md) | |
+| [SavedObjectsCreateOptions](./kibana-plugin-public.savedobjectscreateoptions.md) | |
+| [SavedObjectsFindOptions](./kibana-plugin-public.savedobjectsfindoptions.md) | |
+| [SavedObjectsFindResponsePublic](./kibana-plugin-public.savedobjectsfindresponsepublic.md) | Return type of the Saved Objects find() method.\*Note\*: this type is different between the Public and Server Saved Objects clients. |
+| [SavedObjectsImportConflictError](./kibana-plugin-public.savedobjectsimportconflicterror.md) | Represents a failure to import due to a conflict. |
+| [SavedObjectsImportError](./kibana-plugin-public.savedobjectsimporterror.md) | Represents a failure to import. |
+| [SavedObjectsImportMissingReferencesError](./kibana-plugin-public.savedobjectsimportmissingreferenceserror.md) | Represents a failure to import due to missing references. |
+| [SavedObjectsImportResponse](./kibana-plugin-public.savedobjectsimportresponse.md) | The response describing the result of an import. |
+| [SavedObjectsImportRetry](./kibana-plugin-public.savedobjectsimportretry.md) | Describes a retry operation for importing a saved object. |
+| [SavedObjectsImportUnknownError](./kibana-plugin-public.savedobjectsimportunknownerror.md) | Represents a failure to import due to an unknown reason. |
+| [SavedObjectsImportUnsupportedTypeError](./kibana-plugin-public.savedobjectsimportunsupportedtypeerror.md) | Represents a failure to import due to having an unsupported saved object type. |
+| [SavedObjectsMigrationVersion](./kibana-plugin-public.savedobjectsmigrationversion.md) | Information about the migrations that have been applied to this SavedObject. When Kibana starts up, KibanaMigrator detects outdated documents and migrates them based on this value. For each migration that has been applied, the plugin's name is used as a key and the latest migration version as the value. |
+| [SavedObjectsStart](./kibana-plugin-public.savedobjectsstart.md) | |
+| [SavedObjectsUpdateOptions](./kibana-plugin-public.savedobjectsupdateoptions.md) | |
+| [UiSettingsState](./kibana-plugin-public.uisettingsstate.md) | |
+
+## Type Aliases
+
+| Type Alias | Description |
+| --- | --- |
+| [AppLeaveAction](./kibana-plugin-public.appleaveaction.md) | Possible actions to return from a [AppLeaveHandler](./kibana-plugin-public.appleavehandler.md)See [AppLeaveConfirmAction](./kibana-plugin-public.appleaveconfirmaction.md) and [AppLeaveDefaultAction](./kibana-plugin-public.appleavedefaultaction.md) |
+| [AppLeaveHandler](./kibana-plugin-public.appleavehandler.md) | A handler that will be executed before leaving the application, either when going to another application or when closing the browser tab or manually changing the url. Should return confirm to to prompt a message to the user before leaving the page, or default to keep the default behavior (doing nothing).See [AppMountParameters](./kibana-plugin-public.appmountparameters.md) for detailed usage examples. |
+| [AppMount](./kibana-plugin-public.appmount.md) | A mount function called when the user navigates to this app's route. |
+| [AppMountDeprecated](./kibana-plugin-public.appmountdeprecated.md) | A mount function called when the user navigates to this app's route. |
+| [AppUnmount](./kibana-plugin-public.appunmount.md) | A function called when an application should be unmounted from the page. This function should be synchronous. |
+| [AppUpdatableFields](./kibana-plugin-public.appupdatablefields.md) | Defines the list of fields that can be updated via an [AppUpdater](./kibana-plugin-public.appupdater.md). |
+| [AppUpdater](./kibana-plugin-public.appupdater.md) | Updater for applications. see [ApplicationSetup](./kibana-plugin-public.applicationsetup.md) |
+| [ChromeBreadcrumb](./kibana-plugin-public.chromebreadcrumb.md) | |
+| [ChromeHelpExtensionMenuCustomLink](./kibana-plugin-public.chromehelpextensionmenucustomlink.md) | |
+| [ChromeHelpExtensionMenuDiscussLink](./kibana-plugin-public.chromehelpextensionmenudiscusslink.md) | |
+| [ChromeHelpExtensionMenuDocumentationLink](./kibana-plugin-public.chromehelpextensionmenudocumentationlink.md) | |
+| [ChromeHelpExtensionMenuGitHubLink](./kibana-plugin-public.chromehelpextensionmenugithublink.md) | |
+| [ChromeHelpExtensionMenuLink](./kibana-plugin-public.chromehelpextensionmenulink.md) | |
+| [ChromeNavLinkUpdateableFields](./kibana-plugin-public.chromenavlinkupdateablefields.md) | |
+| [HandlerContextType](./kibana-plugin-public.handlercontexttype.md) | Extracts the type of the first argument of a [HandlerFunction](./kibana-plugin-public.handlerfunction.md) to represent the type of the context. |
+| [HandlerFunction](./kibana-plugin-public.handlerfunction.md) | A function that accepts a context object and an optional number of additional arguments. Used for the generic types in [IContextContainer](./kibana-plugin-public.icontextcontainer.md) |
+| [HandlerParameters](./kibana-plugin-public.handlerparameters.md) | Extracts the types of the additional arguments of a [HandlerFunction](./kibana-plugin-public.handlerfunction.md), excluding the [HandlerContextType](./kibana-plugin-public.handlercontexttype.md). |
+| [HttpStart](./kibana-plugin-public.httpstart.md) | See [HttpSetup](./kibana-plugin-public.httpsetup.md) |
+| [IContextProvider](./kibana-plugin-public.icontextprovider.md) | A function that returns a context value for a specific key of given context type. |
+| [IToasts](./kibana-plugin-public.itoasts.md) | Methods for adding and removing global toast messages. See [ToastsApi](./kibana-plugin-public.toastsapi.md). |
+| [MountPoint](./kibana-plugin-public.mountpoint.md) | A function that should mount DOM content inside the provided container element and return a handler to unmount it. |
+| [PluginInitializer](./kibana-plugin-public.plugininitializer.md) | The plugin export at the root of a plugin's public directory should conform to this interface. |
+| [PluginOpaqueId](./kibana-plugin-public.pluginopaqueid.md) | |
+| [RecursiveReadonly](./kibana-plugin-public.recursivereadonly.md) | |
+| [SavedObjectAttribute](./kibana-plugin-public.savedobjectattribute.md) | Type definition for a Saved Object attribute value |
+| [SavedObjectAttributeSingle](./kibana-plugin-public.savedobjectattributesingle.md) | Don't use this type, it's simply a helper type for [SavedObjectAttribute](./kibana-plugin-public.savedobjectattribute.md) |
+| [SavedObjectsClientContract](./kibana-plugin-public.savedobjectsclientcontract.md) | SavedObjectsClientContract as implemented by the [SavedObjectsClient](./kibana-plugin-public.savedobjectsclient.md) |
+| [Toast](./kibana-plugin-public.toast.md) | |
+| [ToastInput](./kibana-plugin-public.toastinput.md) | Inputs for [IToasts](./kibana-plugin-public.itoasts.md) APIs. |
+| [ToastInputFields](./kibana-plugin-public.toastinputfields.md) | Allowed fields for [ToastInput](./kibana-plugin-public.toastinput.md). |
+| [ToastsSetup](./kibana-plugin-public.toastssetup.md) | [IToasts](./kibana-plugin-public.itoasts.md) |
+| [ToastsStart](./kibana-plugin-public.toastsstart.md) | [IToasts](./kibana-plugin-public.itoasts.md) |
+| [UnmountCallback](./kibana-plugin-public.unmountcallback.md) | A function that will unmount the element previously mounted by the associated [MountPoint](./kibana-plugin-public.mountpoint.md) |
+
diff --git a/docs/development/core/public/kibana-plugin-public.overlaystart.md b/docs/development/core/public/kibana-plugin-public.overlaystart.md
index 8b6f11bd819f83..a83044763344ba 100644
--- a/docs/development/core/public/kibana-plugin-public.overlaystart.md
+++ b/docs/development/core/public/kibana-plugin-public.overlaystart.md
@@ -16,6 +16,7 @@ export interface OverlayStart
| Property | Type | Description |
| --- | --- | --- |
| [banners](./kibana-plugin-public.overlaystart.banners.md) | OverlayBannersStart | [OverlayBannersStart](./kibana-plugin-public.overlaybannersstart.md) |
+| [openConfirm](./kibana-plugin-public.overlaystart.openconfirm.md) | OverlayModalStart['openConfirm'] | |
| [openFlyout](./kibana-plugin-public.overlaystart.openflyout.md) | OverlayFlyoutStart['open'] | |
| [openModal](./kibana-plugin-public.overlaystart.openmodal.md) | OverlayModalStart['open'] | |
diff --git a/docs/development/core/public/kibana-plugin-public.overlaystart.openconfirm.md b/docs/development/core/public/kibana-plugin-public.overlaystart.openconfirm.md
new file mode 100644
index 00000000000000..543a69e0b33184
--- /dev/null
+++ b/docs/development/core/public/kibana-plugin-public.overlaystart.openconfirm.md
@@ -0,0 +1,12 @@
+
+
+[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [OverlayStart](./kibana-plugin-public.overlaystart.md) > [openConfirm](./kibana-plugin-public.overlaystart.openconfirm.md)
+
+## OverlayStart.openConfirm property
+
+
+Signature:
+
+```typescript
+openConfirm: OverlayModalStart['openConfirm'];
+```
diff --git a/docs/development/core/server/kibana-plugin-server.icustomclusterclient.md b/docs/development/core/server/kibana-plugin-server.icustomclusterclient.md
index bc9ea71bc23893..d7511a119fc0ff 100644
--- a/docs/development/core/server/kibana-plugin-server.icustomclusterclient.md
+++ b/docs/development/core/server/kibana-plugin-server.icustomclusterclient.md
@@ -4,7 +4,7 @@
## ICustomClusterClient type
-Represents an Elasticsearch cluster API client created by a plugin.. It allows to call API on behalf of the internal Kibana user and the actual user that is derived from the request headers (via `asScoped(...)`).
+Represents an Elasticsearch cluster API client created by a plugin. It allows to call API on behalf of the internal Kibana user and the actual user that is derived from the request headers (via `asScoped(...)`).
See [ClusterClient](./kibana-plugin-server.clusterclient.md).
diff --git a/docs/development/core/server/kibana-plugin-server.kibanaresponsefactory.md b/docs/development/core/server/kibana-plugin-server.kibanaresponsefactory.md
index 85874f5ec16bae..2e496aa0c46fc7 100644
--- a/docs/development/core/server/kibana-plugin-server.kibanaresponsefactory.md
+++ b/docs/development/core/server/kibana-plugin-server.kibanaresponsefactory.md
@@ -10,7 +10,7 @@ Set of helpers used to create `KibanaResponse` to form HTTP response on an incom
```typescript
kibanaResponseFactory: {
- custom: | Buffer | Stream | {
+ custom: | {
message: string | Error;
attributes?: Record | undefined;
} | undefined>(options: CustomHttpResponseOptions) => KibanaResponse;
@@ -21,9 +21,9 @@ kibanaResponseFactory: {
conflict: (options?: ErrorHttpResponseOptions) => KibanaResponse;
internalError: (options?: ErrorHttpResponseOptions) => KibanaResponse;
customError: (options: CustomHttpResponseOptions) => KibanaResponse;
- redirected: (options: RedirectResponseOptions) => KibanaResponse | Buffer | Stream>;
- ok: (options?: HttpResponseOptions) => KibanaResponse | Buffer | Stream>;
- accepted: (options?: HttpResponseOptions) => KibanaResponse | Buffer | Stream>;
+ redirected: (options: RedirectResponseOptions) => KibanaResponse>;
+ ok: (options?: HttpResponseOptions) => KibanaResponse>;
+ accepted: (options?: HttpResponseOptions) => KibanaResponse>;
noContent: (options?: HttpResponseOptions) => KibanaResponse;
}
```
diff --git a/docs/development/core/server/kibana-plugin-server.md b/docs/development/core/server/kibana-plugin-server.md
index 3f01048846fe1a..5e28643843af30 100644
--- a/docs/development/core/server/kibana-plugin-server.md
+++ b/docs/development/core/server/kibana-plugin-server.md
@@ -177,7 +177,7 @@ The plugin integrates with the core system via lifecycle events: `setup`
| [IBasePath](./kibana-plugin-server.ibasepath.md) | Access or manipulate the Kibana base path[BasePath](./kibana-plugin-server.basepath.md) |
| [IClusterClient](./kibana-plugin-server.iclusterclient.md) | Represents an Elasticsearch cluster API client created by the platform. It allows to call API on behalf of the internal Kibana user and the actual user that is derived from the request headers (via asScoped(...)).See [ClusterClient](./kibana-plugin-server.clusterclient.md). |
| [IContextProvider](./kibana-plugin-server.icontextprovider.md) | A function that returns a context value for a specific key of given context type. |
-| [ICustomClusterClient](./kibana-plugin-server.icustomclusterclient.md) | Represents an Elasticsearch cluster API client created by a plugin.. It allows to call API on behalf of the internal Kibana user and the actual user that is derived from the request headers (via asScoped(...)).See [ClusterClient](./kibana-plugin-server.clusterclient.md). |
+| [ICustomClusterClient](./kibana-plugin-server.icustomclusterclient.md) | Represents an Elasticsearch cluster API client created by a plugin. It allows to call API on behalf of the internal Kibana user and the actual user that is derived from the request headers (via asScoped(...)).See [ClusterClient](./kibana-plugin-server.clusterclient.md). |
| [IsAuthenticated](./kibana-plugin-server.isauthenticated.md) | Return authentication status for a request. |
| [ISavedObjectsRepository](./kibana-plugin-server.isavedobjectsrepository.md) | See [SavedObjectsRepository](./kibana-plugin-server.savedobjectsrepository.md) |
| [IScopedClusterClient](./kibana-plugin-server.iscopedclusterclient.md) | Serves the same purpose as "normal" ClusterClient but exposes additional callAsCurrentUser method that doesn't use credentials of the Kibana internal user (as callAsInternalUser does) to request Elasticsearch API, but rather passes HTTP headers extracted from the current user request to the API.See [ScopedClusterClient](./kibana-plugin-server.scopedclusterclient.md). |
diff --git a/docs/management/managing-licenses.asciidoc b/docs/management/managing-licenses.asciidoc
index bbe4b3b68e03b0..0ad27e68f7fe94 100644
--- a/docs/management/managing-licenses.asciidoc
+++ b/docs/management/managing-licenses.asciidoc
@@ -1,28 +1,185 @@
[[managing-licenses]]
-== License Management
+== License management
-When you install {kib}, it generates a Basic license
-with no expiration date. Go to *Management > License Management* to view the
-status of your license, start a 30-day trial, or install a new license.
+When you install the default distribution of {kib}, you receive a basic license
+with no expiration date. For the full list of free features that are included in
+the basic license, see https://www.elastic.co/subscriptions[the subscription page].
-To learn more about the available license levels,
-see https://www.elastic.co/subscriptions[the subscription page].
+If you want to try out the full set of platinum features, you can activate a
+30-day trial license. Go to *Management > License Management* to view the
+status of your license, start a trial, or install a new license.
-You can activate a 30-day trial license to try out the full set of
-https://www.elastic.co/subscriptions[Platinum features], including machine learning,
-advanced security, alerting, graph capabilities, and more.
+NOTE: You can start a trial only if your cluster has not already activated a
+trial license for the current major product version. For example, if you have
+already activated a trial for v6.0, you cannot start a new trial until
+v7.0. You can, however, contact `info@elastic.co` to request an extended trial
+license.
-When you activate a new license level, new features will appear in the left sidebar
+When you activate a new license level, new features appear in the left sidebar
of the *Management* page.
[role="screenshot"]
image::images/management-license.png[]
-At the end of the trial period, the Platinum features operate in a
-{stack-ov}/license-expiration.html[degraded mode]. You can revert to a Basic
-license, extend the trial, or purchase a subscription.
+At the end of the trial period, the platinum features operate in a
+<>. You can revert to a basic license,
+extend the trial, or purchase a subscription.
+TIP: If {security-features} are enabled, before you revert to a basic license or
+install a gold or platinum license, you must configure Transport Layer Security
+(TLS) in {es}. See {ref}/encrypting-communications.html[Encrypting communications].
+{kib} and the {ref}/start-basic.html[start basic API] provide a list of all of
+the features that will no longer be supported if you revert to a basic license.
-TIP: If {security-features} are enabled, before you revert to a Basic license or install
-a Gold or Platinum license, you must configure Transport Layer Security (TLS) in {es}.
-See {ref}/encrypting-communications.html[Encrypting communications].
\ No newline at end of file
+[discrete]
+[[update-license]]
+=== Update your license
+
+You can update your license at runtime without shutting down your {es} nodes.
+License updates take effect immediately. The license is provided as a _JSON_
+file that you install in {kib} or by using the
+{ref}/update-license.html[update license API].
+
+TIP: If you are using a basic or trial license, {security-features} are disabled
+by default. In all other licenses, {security-features} are enabled by default;
+you must secure the {stack} or disable the {security-features}.
+
+[discrete]
+[[license-expiration]]
+=== License expiration
+
+Your license is time based and expires at a future date. If you're using
+{monitor-features} and your license will expire within 30 days, a license
+expiration warning is displayed prominently. Warnings are also displayed on
+startup and written to the {es} log starting 30 days from the expiration date.
+These error messages tell you when the license expires and what features will be
+disabled if you do not update the license.
+
+IMPORTANT: You should update your license as soon as possible. You are
+essentially flying blind when running with an expired license. Access to the
+cluster health and stats APIs is critical for monitoring and managing an {es}
+cluster.
+
+[discrete]
+[[expiration-beats]]
+==== Beats
+
+* Beats will continue to poll centrally-managed configuration.
+
+[discrete]
+[[expiration-elasticsearch]]
+==== {es}
+
+// Upgrade API is disabled
+* The deprecation API is disabled.
+* SQL support is disabled.
+* Aggregations provided by the analytics plugin are no longer usable.
+
+[discrete]
+[[expiration-watcher]]
+==== {stack} {alert-features}
+
+* The PUT and GET watch APIs are disabled. The DELETE watch API continues to work.
+* Watches execute and write to the history.
+* The actions of the watches do not execute.
+
+[discrete]
+[[expiration-graph]]
+==== {stack} {graph-features}
+
+* Graph explore APIs are disabled.
+
+[discrete]
+[[expiration-ml]]
+==== {stack} {ml-features}
+
+* APIs to create {anomaly-jobs}, open jobs, send data to jobs, create {dfeeds},
+and start {dfeeds} are disabled.
+* All started {dfeeds} are stopped.
+* All open {anomaly-jobs} are closed.
+* APIs to create and start {dfanalytics-jobs} are disabled.
+* Existing {anomaly-job} and {dfanalytics-job} results continue to be available
+by using {kib} or APIs.
+
+[discrete]
+[[expiration-monitoring]]
+==== {stack} {monitor-features}
+
+* The agent stops collecting cluster and indices metrics.
+* The agent stops automatically cleaning indices older than
+`xpack.monitoring.history.duration`.
+
+[discrete]
+[[expiration-security]]
+==== {stack} {security-features}
+
+* Cluster health, cluster stats, and indices stats operations are blocked.
+* All data operations (read and write) continue to work.
+
+Once the license expires, calls to the cluster health, cluster stats, and index
+stats APIs fail with a `security_exception` and return a 403 HTTP status code.
+
+[source,sh]
+-----------------------------------------------------
+{
+ "error": {
+ "root_cause": [
+ {
+ "type": "security_exception",
+ "reason": "current license is non-compliant for [security]",
+ "license.expired.feature": "security"
+ }
+ ],
+ "type": "security_exception",
+ "reason": "current license is non-compliant for [security]",
+ "license.expired.feature": "security"
+ },
+ "status": 403
+}
+-----------------------------------------------------
+
+This message enables automatic monitoring systems to easily detect the license
+failure without immediately impacting other users.
+
+[discrete]
+[[expiration-logstash]]
+==== {ls} pipeline management
+
+* Cannot create new pipelines or edit or delete existing pipelines from the UI.
+* Cannot list or view existing pipelines from the UI.
+* Cannot run Logstash instances which are registered to listen to existing pipelines.
+//TBD: * Logstash will continue to poll centrally-managed pipelines
+
+[discrete]
+[[expiration-kibana]]
+==== {kib}
+
+* Users can still log into {kib}.
+* {kib} works for data exploration and visualization, but some features
+are disabled.
+* The license management UI is available to easily upgrade your license. See
+<> and <>.
+
+[discrete]
+[[expiration-reporting]]
+==== {kib} {report-features}
+
+* Reporting is no longer available in {kib}.
+* Report generation URLs stop working.
+* Existing reports are no longer accessible.
+
+[discrete]
+[[expiration-rollups]]
+==== {rollups-cap}
+
+* {rollup-jobs-cap} cannot be created or started.
+* Existing {rollup-jobs} can be stopped and deleted.
+* The get rollup caps and rollup search APIs continue to function.
+
+[discrete]
+[[expiration-transforms]]
+==== {transforms-cap}
+
+* {transforms-cap} cannot be created, previewed, started, or updated.
+* Existing {transforms} can be stopped and deleted.
+* Existing {transform} results continue to be available.
diff --git a/docs/management/snapshot-restore/index.asciidoc b/docs/management/snapshot-restore/index.asciidoc
index f19aaa122675e7..dc722c24af76ca 100644
--- a/docs/management/snapshot-restore/index.asciidoc
+++ b/docs/management/snapshot-restore/index.asciidoc
@@ -21,7 +21,7 @@ With this UI, you can:
image:management/snapshot-restore/images/snapshot_list.png["Snapshot list"]
Before using this feature, you should be familiar with how snapshots work.
-{ref}/modules-snapshots.html[Snapshot and Restore] is a good source for
+{ref}/snapshot-restore.html[Snapshot and Restore] is a good source for
more detailed information.
[float]
@@ -35,9 +35,9 @@ registering one.
{kib} supports three repository types
out of the box: shared file system, read-only URL, and source-only.
For more information on these repositories and their settings,
-see {ref}/modules-snapshots.html#snapshots-repositories[Repositories].
+see {ref}/snapshots-register-repository.html[Repositories].
To use other repositories, such as S3, see
-{ref}/modules-snapshots.html#_repository_plugins[Repository plugins].
+{ref}/snapshots-register-repository.html#snapshots-repository-plugins[Repository plugins].
Once you create a repository, it is listed in the *Repositories*
@@ -61,7 +61,7 @@ into each snapshot for further investigation.
image:management/snapshot-restore/images/snapshot_details.png["Snapshot details"]
If you don’t have any snapshots, you can create them from the {kib} <>. The
-{ref}//modules-snapshots.html#snapshots-take-snapshot[snapshot API]
+{ref}/snapshots-take-snapshot.html[snapshot API]
takes the current state and data in your index or cluster, and then saves it to a
shared repository.
@@ -162,7 +162,7 @@ Ready to try *Snapshot and Restore*? In this tutorial, you'll learn to:
This example shows you how to register a shared file system repository
and store snapshots.
Before you begin, you must register the location of the repository in the
-{ref}/modules-snapshots.html#_shared_file_system_repository[path.repo] setting on
+{ref}/snapshots-register-repository.html#snapshots-filesystem-repository[path.repo] setting on
your master and data nodes. You can do this in one of two ways:
* Edit your `elasticsearch.yml` to include the `path.repo` setting.
@@ -197,7 +197,7 @@ The repository currently doesn’t have any snapshots.
[float]
==== Add a snapshot to the repository
-Use the {ref}//modules-snapshots.html#snapshots-take-snapshot[snapshot API] to create a snapshot.
+Use the {ref}/snapshots-take-snapshot.html[snapshot API] to create a snapshot.
. Go to *Dev Tools > Console*.
. Create the snapshot:
@@ -206,7 +206,7 @@ Use the {ref}//modules-snapshots.html#snapshots-take-snapshot[snapshot API] to c
PUT /_snapshot/my_backup/2019-04-25_snapshot?wait_for_completion=true
+
In this example, the snapshot name is `2019-04-25_snapshot`. You can also
-use {ref}//date-math-index-names.html[date math expression] for the snapshot name.
+use {ref}/date-math-index-names.html[date math expression] for the snapshot name.
+
[role="screenshot"]
image:management/snapshot-restore/images/create_snapshot.png["Create snapshot"]
diff --git a/docs/settings/reporting-settings.asciidoc b/docs/settings/reporting-settings.asciidoc
index a754f91e9f22a1..a9fa2bd18d3154 100644
--- a/docs/settings/reporting-settings.asciidoc
+++ b/docs/settings/reporting-settings.asciidoc
@@ -54,6 +54,14 @@ The protocol for accessing Kibana, typically `http` or `https`.
`xpack.reporting.kibanaServer.hostname`::
The hostname for accessing {kib}, if different from the `server.host` value.
+[NOTE]
+============
+Reporting authenticates requests on the Kibana page only when the hostname matches the
+`xpack.reporting.kibanaServer.hostname` setting. Therefore Reporting would fail if the
+set value redirects to another server. For that reason, `"0"` is an invalid setting
+because, in the Reporting browser, it becomes an automatic redirect to `"0.0.0.0"`.
+============
+
[float]
[[reporting-job-queue-settings]]
diff --git a/docs/settings/security-settings.asciidoc b/docs/settings/security-settings.asciidoc
index d6dd4378da1b7c..16d68a7759f776 100644
--- a/docs/settings/security-settings.asciidoc
+++ b/docs/settings/security-settings.asciidoc
@@ -45,7 +45,7 @@ if this setting isn't the same for all instances of {kib}.
`xpack.security.secureCookies`::
Sets the `secure` flag of the session cookie. The default value is `false`. It
-is set to `true` if `server.ssl.certificate` and `server.ssl.key` are set. Set
+is automatically set to `true` if `server.ssl.enabled` is set to `true`. Set
this to `true` if SSL is configured outside of {kib} (for example, you are
routing requests through a load balancer or proxy).
diff --git a/docs/setup/settings.asciidoc b/docs/setup/settings.asciidoc
index c98df6ca78356b..535ad169782170 100644
--- a/docs/setup/settings.asciidoc
+++ b/docs/setup/settings.asciidoc
@@ -82,31 +82,52 @@ Elasticsearch nodes on startup.
`elasticsearch.sniffOnConnectionFault:`:: *Default: false* Update the list of
Elasticsearch nodes immediately following a connection fault.
-`elasticsearch.ssl.alwaysPresentCertificate:`:: *Default: false* Controls
-whether to always present the certificate specified by
-`elasticsearch.ssl.certificate` when requested. This applies to all requests to
-Elasticsearch, including requests that are proxied for end-users. Setting this
-to `true` when Elasticsearch is using certificates to authenticate users can
-lead to proxied requests for end-users being executed as the identity tied to
-the configured certificate.
-
-`elasticsearch.ssl.certificate:` and `elasticsearch.ssl.key:`:: Optional
-settings that provide the paths to the PEM-format SSL certificate and key files.
-These files are used to verify the identity of Kibana to Elasticsearch and are
-required when `xpack.security.http.ssl.client_authentication` in Elasticsearch is
-set to `required`.
-
-`elasticsearch.ssl.certificateAuthorities:`:: Optional setting that enables you
-to specify a list of paths to the PEM file for the certificate authority for
-your Elasticsearch instance.
-
-`elasticsearch.ssl.keyPassphrase:`:: The passphrase that will be used to decrypt
-the private key. This value is optional as the key may not be encrypted.
-
-`elasticsearch.ssl.verificationMode:`:: *Default: full* Controls the
-verification of certificates presented by Elasticsearch. Valid values are `none`,
-`certificate`, and `full`. `full` performs hostname verification, and
-`certificate` does not.
+`elasticsearch.ssl.alwaysPresentCertificate:`:: *Default: false* Controls whether to always present the certificate specified by
+`elasticsearch.ssl.certificate` or `elasticsearch.ssl.keystore.path` when requested. This setting applies to all requests to Elasticsearch,
+including requests that are proxied for end users. Setting this to `true` when Elasticsearch is using certificates to authenticate users can
+lead to proxied requests for end users being executed as the identity tied to the configured certificate.
+
+`elasticsearch.ssl.certificate:` and `elasticsearch.ssl.key:`:: Paths to a PEM-encoded X.509 certificate and its private key, respectively.
+When `xpack.security.http.ssl.client_authentication` in Elasticsearch is set to `required` or `optional`, the certificate and key are used
+to prove Kibana's identity when it makes an outbound request to your Elasticsearch cluster.
++
+--
+NOTE: These settings cannot be used in conjunction with `elasticsearch.ssl.keystore.path`.
+--
+
+`elasticsearch.ssl.certificateAuthorities:`:: Paths to one or more PEM-encoded X.509 certificates. These certificates may consist of a root
+certificate authority (CA), and one or more intermediate CAs, which make up a trusted certificate chain for Kibana. This chain is used to
+establish trust when Kibana creates an SSL connection with your Elasticsearch cluster. In addition to this setting, trusted certificates may
+be specified via `elasticsearch.ssl.keystore.path` and/or `elasticsearch.ssl.truststore.path`.
+
+`elasticsearch.ssl.keyPassphrase:`:: The passphrase that will be used to decrypt the private key that is specified via
+`elasticsearch.ssl.key`. This value is optional, as the key may not be encrypted.
+
+`elasticsearch.ssl.keystore.path:`:: Path to a PKCS #12 file that contains an X.509 certificate with its private key. When
+`xpack.security.http.ssl.client_authentication` in Elasticsearch is set to `required` or `optional`, the certificate and key are used to
+prove Kibana's identity when it makes an outbound request to your Elasticsearch cluster. If the file contains any additional certificates,
+those will be used as a trusted certificate chain for your Elasticsearch cluster. This chain is used to establish trust when Kibana creates
+an SSL connection with your Elasticsearch cluster. In addition to this setting, trusted certificates may be specified via
+`elasticsearch.ssl.certificateAuthorities` and/or `elasticsearch.ssl.truststore.path`.
++
+--
+NOTE: This setting cannot be used in conjunction with `elasticsearch.ssl.certificate` or `elasticsearch.ssl.key`.
+--
+
+`elasticsearch.ssl.keystore.password:`:: The password that will be used to decrypt the key store and its private key. If your key store has
+no password, leave this unset. If your key store has an empty password, set this to `""`.
+
+`elasticsearch.ssl.truststore.path:`:: Path to a PKCS #12 trust store that contains one or more X.509 certificates. This may consist of a
+root certificate authority (CA) and one or more intermediate CAs, which make up a trusted certificate chain for your Elasticsearch cluster.
+This chain is used to establish trust when Kibana creates an SSL connection with your Elasticsearch cluster. In addition to this setting,
+trusted certificates may be specified via `elasticsearch.ssl.certificateAuthorities` and/or `elasticsearch.ssl.keystore.path`.
+
+`elasticsearch.ssl.truststore.password:`:: The password that will be used to decrypt the trust store. If your trust store has no password,
+leave this unset. If your trust store has an empty password, set this to `""`.
+
+`elasticsearch.ssl.verificationMode:`:: *Default: full* Controls the verification of certificates presented by Elasticsearch. Valid values
+are `none`, `certificate`, and `full`. `full` performs hostname verification and `certificate` does not. This setting is used only when
+traffic to Elasticsearch is encrypted, which is specified by using the HTTPS protocol in `elasticsearch.hosts`.
`elasticsearch.startupTimeout:`:: *Default: 5000* Time in milliseconds to wait
for Elasticsearch at Kibana startup before retrying.
@@ -325,11 +346,19 @@ default is `true`.
`server.socketTimeout:`:: *Default: "120000"* The number of milliseconds to wait before closing an
inactive socket.
-`server.ssl.certificate:` and `server.ssl.key:`:: Paths to the PEM-format SSL
-certificate and SSL key files, respectively.
+`server.ssl.certificate:` and `server.ssl.key:`:: Paths to a PEM-encoded X.509 certificate and its private key, respectively. These are used
+when enabling SSL for inbound requests from web browsers to the Kibana server.
++
+--
+NOTE: These settings cannot be used in conjunction with `server.ssl.keystore.path`.
+--
-`server.ssl.certificateAuthorities:`:: List of paths to PEM encoded certificate
-files that should be trusted.
+`server.ssl.certificateAuthorities:`:: Paths to one or more PEM-encoded X.509 certificates. These certificates may consist of a root
+certificate authority (CA) and one or more intermediate CAs, which make up a trusted certificate chain for Kibana. This chain is used when a
+web browser creates an SSL connection with the Kibana server; the certificate chain is sent to the browser along with the end-entity
+certificate to establish trust. This chain is also used to determine whether client certificates should be trusted when PKI authentication
+is enabled. In addition to this setting, trusted certificates may be specified via `server.ssl.keystore.path` and/or
+`server.ssl.truststore.path`.
`server.ssl.cipherSuites:`:: *Default: ECDHE-RSA-AES128-GCM-SHA256, ECDHE-ECDSA-AES128-GCM-SHA256, ECDHE-RSA-AES256-GCM-SHA384, ECDHE-ECDSA-AES256-GCM-SHA384, DHE-RSA-AES128-GCM-SHA256, ECDHE-RSA-AES128-SHA256, DHE-RSA-AES128-SHA256, ECDHE-RSA-AES256-SHA384, DHE-RSA-AES256-SHA384, ECDHE-RSA-AES256-SHA256, DHE-RSA-AES256-SHA256, HIGH,!aNULL, !eNULL, !EXPORT, !DES, !RC4, !MD5, !PSK, !SRP, !CAMELLIA*.
Details on the format, and the valid options, are available via the
@@ -339,12 +368,36 @@ https://www.openssl.org/docs/man1.0.2/apps/ciphers.html#CIPHER-LIST-FORMAT[OpenS
connections. Valid values are `required`, `optional`, and `none`. `required` forces a client to present a certificate, while `optional`
requests a client certificate but the client is not required to present one.
-`server.ssl.enabled:`:: *Default: "false"* Enables SSL for outgoing requests
-from the Kibana server to the browser. When set to `true`,
-`server.ssl.certificate` and `server.ssl.key` are required.
+`server.ssl.enabled:`:: *Default: "false"* Enables SSL for inbound requests from the browser to the Kibana server. When set to `true`, a
+certificate and private key must be provided. These can be specified via `server.ssl.keystore.path` or the combination of
+`server.ssl.certificate` and `server.ssl.key`.
+
+`server.ssl.keyPassphrase:`:: The passphrase that will be used to decrypt the private key that is specified via `server.ssl.key`. This value
+is optional, as the key may not be encrypted.
+
+`server.ssl.keystore.path:`:: Path to a PKCS #12 file that contains an X.509 certificate with its private key. These are used when enabling
+SSL for inbound requests from web browsers to the Kibana server. If the file contains any additional certificates, those will be used as a
+trusted certificate chain for Kibana. This chain is used when a web browser creates an SSL connection with the Kibana server; the
+certificate chain is sent to the browser along with the end-entity certificate to establish trust. This chain is also used to determine
+whether client certificates should be trusted when PKI authentication is enabled. In addition to this setting, trusted certificates may be
+specified via `server.ssl.certificateAuthorities` and/or `server.ssl.truststore.path`.
++
+--
+NOTE: This setting cannot be used in conjunction with `server.ssl.certificate` or `server.ssl.key`.
+--
+
+`server.ssl.keystore.password:`:: The password that will be used to decrypt the key store and its private key. If your key store has no
+password, leave this unset. If your key store has an empty password, set this to `""`.
+
+`server.ssl.truststore.path:`:: Path to a PKCS #12 trust store that contains one or more X.509 certificates. These certificates may consist
+of a root certificate authority (CA) and one or more intermediate CAs, which make up a trusted certificate chain for Kibana. This chain is
+used when a web browser creates an SSL connection with the Kibana server; the certificate chain is sent to the browser along with the
+end-entity certificate to establish trust. This chain is also used to determine whether client certificates should be trusted when PKI
+authentication is enabled. In addition to this setting, trusted certificates may be specified via `server.ssl.certificateAuthorities` and/or
+`server.ssl.keystore.path`.
-`server.ssl.keyPassphrase:`:: The passphrase that will be used to decrypt the
-private key. This value is optional as the key may not be encrypted.
+`server.ssl.truststore.password:`:: The password that will be used to decrypt the trust store. If your trust store has no password, leave
+this unset. If your trust store has an empty password, set this to `""`.
`server.ssl.redirectHttpFromPort:`:: Kibana will bind to this port and redirect
all http requests to https over the port configured as `server.port`.
diff --git a/docs/user/monitoring/monitoring-kibana.asciidoc b/docs/user/monitoring/monitoring-kibana.asciidoc
index d7af0d5c420a14..b5d263aed8346a 100644
--- a/docs/user/monitoring/monitoring-kibana.asciidoc
+++ b/docs/user/monitoring/monitoring-kibana.asciidoc
@@ -96,7 +96,8 @@ used when {kib} sends monitoring data to the production cluster.
.. Configure {kib} to encrypt communications between the {kib} server and the
production cluster. This set up involves generating a server certificate and
setting `server.ssl.*` and `elasticsearch.ssl.certificateAuthorities` settings
-in the `kibana.yml` file on the {kib} server. For example:
+in the `kibana.yml` file on the {kib} server. For example, using a PEM-formatted
+certificate and private key:
+
--
[source,yaml]
@@ -105,14 +106,19 @@ server.ssl.key: /path/to/your/server.key
server.ssl.certificate: /path/to/your/server.crt
--------------------------------------------------------------------------------
-If you are using your own certificate authority to sign certificates, specify
-the location of the PEM file in the `kibana.yml` file:
+If you are using your own certificate authority (CA) to sign certificates,
+specify the location of the PEM file in the `kibana.yml` file:
[source,yaml]
--------------------------------------------------------------------------------
elasticsearch.ssl.certificateAuthorities: /path/to/your/cacert.pem
--------------------------------------------------------------------------------
+NOTE: Alternatively, the PKCS #12 format can be used for the Kibana certificate
+and key, along with any included CA certificates, by setting
+`server.ssl.keystore.path`. If your CA certificate chain is in a separate trust
+store, you can also use `server.ssl.truststore.path`.
+
For more information, see <>.
--
diff --git a/docs/user/security/authentication/index.asciidoc b/docs/user/security/authentication/index.asciidoc
index 2e2aaf688e8b68..05aabfc343be94 100644
--- a/docs/user/security/authentication/index.asciidoc
+++ b/docs/user/security/authentication/index.asciidoc
@@ -67,6 +67,9 @@ server.ssl.clientAuthentication: required
xpack.security.authc.providers: [pki]
--------------------------------------------------------------------------------
+NOTE: Trusted CAs can also be specified in a PKCS #12 keystore bundled with your Kibana server certificate/key using
+`server.ssl.keystore.path` or in a separate trust store using `server.ssl.truststore.path`.
+
PKI support in {kib} is designed to be the primary (or sole) authentication method for users of that {kib} instance. However, you can configure both PKI and Basic authentication for the same {kib} instance:
[source,yaml]
diff --git a/docs/user/security/index.asciidoc b/docs/user/security/index.asciidoc
index eab3833b3f5ae3..e3d6e0d97c73a4 100644
--- a/docs/user/security/index.asciidoc
+++ b/docs/user/security/index.asciidoc
@@ -37,4 +37,5 @@ cause Kibana's authorization to behave unexpectedly.
include::authorization/index.asciidoc[]
include::authorization/kibana-privileges.asciidoc[]
include::api-keys/index.asciidoc[]
+include::role-mappings/index.asciidoc[]
include::rbac_tutorial.asciidoc[]
diff --git a/docs/user/security/role-mappings/images/role-mappings-create-step-1.png b/docs/user/security/role-mappings/images/role-mappings-create-step-1.png
new file mode 100644
index 00000000000000..2b4ad16459529c
Binary files /dev/null and b/docs/user/security/role-mappings/images/role-mappings-create-step-1.png differ
diff --git a/docs/user/security/role-mappings/images/role-mappings-create-step-2.gif b/docs/user/security/role-mappings/images/role-mappings-create-step-2.gif
new file mode 100644
index 00000000000000..0a10126ea3cce3
Binary files /dev/null and b/docs/user/security/role-mappings/images/role-mappings-create-step-2.gif differ
diff --git a/docs/user/security/role-mappings/images/role-mappings-grid.png b/docs/user/security/role-mappings/images/role-mappings-grid.png
new file mode 100644
index 00000000000000..96c9ee8e4cd95e
Binary files /dev/null and b/docs/user/security/role-mappings/images/role-mappings-grid.png differ
diff --git a/docs/user/security/role-mappings/index.asciidoc b/docs/user/security/role-mappings/index.asciidoc
new file mode 100644
index 00000000000000..01028ab4d59e08
--- /dev/null
+++ b/docs/user/security/role-mappings/index.asciidoc
@@ -0,0 +1,51 @@
+[role="xpack"]
+[[role-mappings]]
+=== Role mappings
+
+Role mappings allow you to describe which roles to assign to your users
+using a set of rules. Role mappings are required when authenticating via
+an external identity provider, such as Active Directory, Kerberos, PKI, OIDC,
+or SAML.
+
+Role mappings have no effect for users inside the `native` or `file` realms.
+
+To manage your role mappings, use *Management > Security > Role Mappings*.
+
+With *Role mappings*, you can:
+
+* View your configured role mappings
+* Create/Edit/Delete role mappings
+
+[role="screenshot"]
+image:user/security/role-mappings/images/role-mappings-grid.png["Role mappings"]
+
+
+[float]
+=== Create a role mapping
+
+To create a role mapping, navigate to *Management > Security > Role Mappings*, and click **Create role mapping**.
+Give your role mapping a unique name, and choose which roles you wish to assign to your users.
+If you need more flexibility, you can use {ref}/security-api-put-role-mapping.html#_role_templates[role templates] instead.
+
+Next, define the rules describing which users should receive the roles you defined. Rules can optionally grouped and nested, allowing for sophisticated logic to suite complex requirements.
+View the {ref}/role-mapping-resources.html[role mapping resources for an overview of the allowed rule types].
+
+
+[float]
+=== Example
+
+Let's create a `sales-users` role mapping, which assigns a `sales` role to users whose username
+starts with `sls_`, *or* belongs to the `executive` group.
+
+First, we give the role mapping a name, and assign the `sales` role:
+
+[role="screenshot"]
+image:user/security/role-mappings/images/role-mappings-create-step-1.png["Create role mapping, step 1"]
+
+Next, we define the two rules, making sure to set the group to *Any are true*:
+
+[role="screenshot"]
+image:user/security/role-mappings/images/role-mappings-create-step-2.gif["Create role mapping, step 2"]
+
+Click *Save role mapping* once you're finished.
+
diff --git a/docs/user/security/securing-communications/index.asciidoc b/docs/user/security/securing-communications/index.asciidoc
index 6917a48909c7b0..b370c35905bce4 100644
--- a/docs/user/security/securing-communications/index.asciidoc
+++ b/docs/user/security/securing-communications/index.asciidoc
@@ -4,121 +4,115 @@
Encrypting communications
++++
-{kib} supports Transport Layer Security (TLS/SSL) encryption for client
-requests.
-//TBD: It is unclear what "client requests" are in this context. Is it just
-// communication between the browser and the Kibana server or are we talking
-// about other types of clients connecting to the Kibana server?
-
-If you are using {security} or a proxy that provides an HTTPS endpoint for {es},
-you can configure {kib} to access {es} via HTTPS. Thus, communications between
-{kib} and {es} are also encrypted.
-
-. Configure {kib} to encrypt communications between the browser and the {kib}
-server:
+{kib} supports Transport Layer Security (TLS/SSL) encryption for all forms of data-in-transit. Browsers send traffic to {kib} and {kib}
+sends traffic to {es}. These communications are configured separately.
+
+[[configuring-tls-browser-kib]]
+==== Encrypting traffic between the browser and {kib}
+
+NOTE: You do not need to enable {security-features} for this type of encryption.
+
+. Obtain a server certificate and private key for {kib}.
+
--
-NOTE: You do not need to enable {security} for this type of encryption.
+{kib} supports certificates/keys in both PKCS #12 key stores and PEM format.
+
+When you obtain a certificate, you must do at least one of the following:
+
+.. Set the certificate's `subjectAltName` to the hostname, fully-qualified domain name (FQDN), or IP address of the {kib} server.
+
+.. Set the certificate's Common Name (CN) to the {kib} server's hostname or FQDN. Using the server's IP address as the CN does not work.
+
+You may choose to generate a certificate and private key using {ref}/certutil.html[the {es} certutil tool]. If you already used certutil to
+generate a certificate authority (CA), you would generate a certificate/key for Kibana like so (using the `--dns` param to set the
+`subjectAltName`):
+
+[source,sh]
+--------------------------------------------------------------------------------
+bin/elasticsearch-certutil cert --ca elastic-stack-ca.p12 --name kibana --dns localhost
+--------------------------------------------------------------------------------
+
+This will generate a certificate and private key in a PKCS #12 keystore named `kibana.p12`.
--
-.. Generate a server certificate for {kib}.
+. Enable TLS/SSL in `kibana.yml`:
+
--
-//TBD: Can we provide more information about how they generate the certificate?
-//Would they be able to use something like the elasticsearch-certutil command?
-You must either set the certificate's
-`subjectAltName` to the hostname, fully-qualified domain name (FQDN), or IP
-address of the {kib} server, or set the CN to the {kib} server's hostname
-or FQDN. Using the server's IP address as the CN does not work.
+[source,yaml]
+--------------------------------------------------------------------------------
+server.ssl.enabled: true
+--------------------------------------------------------------------------------
--
-.. Set the `server.ssl.enabled`, `server.ssl.key`, and `server.ssl.certificate`
-properties in `kibana.yml`:
+. Specify your server certificate and private key in `kibana.yml`:
+
--
+If your certificate and private key are in a PKCS #12 keystore, specify it like so:
+
[source,yaml]
--------------------------------------------------------------------------------
-server.ssl.enabled: true
-server.ssl.key: /path/to/your/server.key
-server.ssl.certificate: /path/to/your/server.crt
+server.ssl.keystore.path: "/path/to/your/keystore.p12"
+server.ssl.keystore.password: "optional decryption password"
+--------------------------------------------------------------------------------
+
+Otherwise, if your certificate/key are in PEM format, specify them like so:
+
+[source,yaml]
+--------------------------------------------------------------------------------
+server.ssl.certificate: "/path/to/your/server.crt"
+server.ssl.key: "/path/to/your/server.key"
+server.ssl.keyPassphrase: "optional decryption password"
--------------------------------------------------------------------------------
After making these changes, you must always access {kib} via HTTPS. For example,
https://localhost:5601.
-// TBD: The reference information for server.ssl.enabled says it "enables SSL for
-// outgoing requests from the Kibana server to the browser". Do we need to
-// reiterate here that only one side of the communications is encrypted?
-
For more information, see <>.
--
-. Configure {kib} to connect to {es} via HTTPS:
-+
---
+[[configuring-tls-kib-es]]
+==== Encrypting traffic between {kib} and {es}
+
NOTE: To perform this step, you must
{ref}/configuring-security.html[enable the {es} {security-features}] or you
must have a proxy that provides an HTTPS endpoint for {es}.
---
-
-.. Specify the HTTPS protocol in the `elasticsearch.hosts` setting in the {kib}
-configuration file, `kibana.yml`:
+. Specify the HTTPS URL in the `elasticsearch.hosts` setting in the {kib} configuration file, `kibana.yml`:
+
--
[source,yaml]
--------------------------------------------------------------------------------
elasticsearch.hosts: ["https://.com:9200"]
--------------------------------------------------------------------------------
---
-
-.. If you are using your own CA to sign certificates for {es}, set the
-`elasticsearch.ssl.certificateAuthorities` setting in `kibana.yml` to specify
-the location of the PEM file.
-+
---
-[source,yaml]
---------------------------------------------------------------------------------
-elasticsearch.ssl.certificateAuthorities: /path/to/your/cacert.pem
---------------------------------------------------------------------------------
-Setting the `certificateAuthorities` property lets you use the default
-`verificationMode` option of `full`.
-//TBD: Is this still true? It isn't mentioned in https://www.elastic.co/guide/en/kibana/master/settings.html
+Using the HTTPS protocol results in a default `elasticsearch.ssl.verificationMode` option of `full`, which utilizes hostname verification.
For more information, see <>.
--
-. (Optional) If the Elastic {monitor-features} are enabled, configure {kib} to
-connect to the {es} monitoring cluster via HTTPS:
+. Specify the {es} cluster's CA certificate chain in `kibana.yml`:
+
--
-NOTE: To perform this step, you must
-{ref}/configuring-security.html[enable the {es} {security-features}] or you
-must have a proxy that provides an HTTPS endpoint for {es}.
---
+If you are using your own CA to sign certificates for {es}, then you need to specify the CA certificate chain in {kib} to properly establish
+trust in TLS connections. If your CA certificate chain is contained in a PKCS #12 trust store, specify it like so:
-.. Specify the HTTPS URL in the `xpack.monitoring.elasticsearch.hosts` setting in
-the {kib} configuration file, `kibana.yml`
-+
---
[source,yaml]
--------------------------------------------------------------------------------
-xpack.monitoring.elasticsearch.hosts: ["https://:9200"]
+elasticsearch.ssl.truststore.path: "/path/to/your/truststore.p12"
+elasticsearch.ssl.truststore.password: "optional decryption password"
--------------------------------------------------------------------------------
---
-.. Specify the `xpack.monitoring.elasticsearch.ssl.*` settings in the
-`kibana.yml` file.
-+
---
-For example, if you are using your own certificate authority to sign
-certificates, specify the location of the PEM file in the `kibana.yml` file:
+Otherwise, if your CA certificate chain is in PEM format, specify each certificate like so:
[source,yaml]
--------------------------------------------------------------------------------
-xpack.monitoring.elasticsearch.ssl.certificateAuthorities: /path/to/your/cacert.pem
+elasticsearch.ssl.certificateAuthorities: ["/path/to/your/cacert1.pem", "/path/to/your/cacert2.pem"]
--------------------------------------------------------------------------------
+
--
+
+. (Optional) If the Elastic {monitor-features} are enabled, configure {kib} to connect to the {es} monitoring cluster via HTTPS. The steps
+are the same as above, but each setting is prefixed by `xpack.monitoring.`. For example, `xpack.monitoring.elasticsearch.hosts`,
+`xpack.monitoring.elasticsearch.ssl.truststore.path`, etc.
diff --git a/docs/visualize/visualize_rollup_data.asciidoc b/docs/visualize/visualize_rollup_data.asciidoc
index 110533589cab9c..481cbc6e394182 100644
--- a/docs/visualize/visualize_rollup_data.asciidoc
+++ b/docs/visualize/visualize_rollup_data.asciidoc
@@ -6,7 +6,7 @@ beta[]
You can visualize your rolled up data in a variety of charts, tables, maps, and
more. Most visualizations support rolled up data, with the exception of
-Timelion, TSVB, and Vega visualizations.
+Timelion and Vega visualizations.
To get started, go to *Management > Kibana > Index patterns.*
If a rollup index is detected in the cluster, *Create index pattern*
diff --git a/examples/state_containers_examples/kibana.json b/examples/state_containers_examples/kibana.json
new file mode 100644
index 00000000000000..9114a414a4da39
--- /dev/null
+++ b/examples/state_containers_examples/kibana.json
@@ -0,0 +1,10 @@
+{
+ "id": "stateContainersExamples",
+ "version": "0.0.1",
+ "kibanaVersion": "kibana",
+ "configPath": ["state_containers_examples"],
+ "server": false,
+ "ui": true,
+ "requiredPlugins": [],
+ "optionalPlugins": []
+}
diff --git a/examples/state_containers_examples/package.json b/examples/state_containers_examples/package.json
new file mode 100644
index 00000000000000..b309494a366628
--- /dev/null
+++ b/examples/state_containers_examples/package.json
@@ -0,0 +1,17 @@
+{
+ "name": "state_containers_examples",
+ "version": "1.0.0",
+ "main": "target/examples/state_containers_examples",
+ "kibana": {
+ "version": "kibana",
+ "templateVersion": "1.0.0"
+ },
+ "license": "Apache-2.0",
+ "scripts": {
+ "kbn": "node ../../scripts/kbn.js",
+ "build": "rm -rf './target' && tsc"
+ },
+ "devDependencies": {
+ "typescript": "3.7.2"
+ }
+}
diff --git a/examples/state_containers_examples/public/app.tsx b/examples/state_containers_examples/public/app.tsx
new file mode 100644
index 00000000000000..319680d07f9bc8
--- /dev/null
+++ b/examples/state_containers_examples/public/app.tsx
@@ -0,0 +1,69 @@
+/*
+ * Licensed to Elasticsearch B.V. under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch B.V. licenses this file to you under
+ * the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import { AppMountParameters } from 'kibana/public';
+import ReactDOM from 'react-dom';
+import React from 'react';
+import { createHashHistory, createBrowserHistory } from 'history';
+import { TodoAppPage } from './todo';
+
+export interface AppOptions {
+ appInstanceId: string;
+ appTitle: string;
+ historyType: History;
+}
+
+export enum History {
+ Browser,
+ Hash,
+}
+
+export const renderApp = (
+ { appBasePath, element }: AppMountParameters,
+ { appInstanceId, appTitle, historyType }: AppOptions
+) => {
+ const history =
+ historyType === History.Browser
+ ? createBrowserHistory({ basename: appBasePath })
+ : createHashHistory();
+ ReactDOM.render(
+ {
+ const stripTrailingSlash = (path: string) =>
+ path.charAt(path.length - 1) === '/' ? path.substr(0, path.length - 1) : path;
+ const currentAppUrl = stripTrailingSlash(history.createHref(history.location));
+ if (historyType === History.Browser) {
+ // browser history
+ const basePath = stripTrailingSlash(appBasePath);
+ return currentAppUrl === basePath && !history.location.search && !history.location.hash;
+ } else {
+ // hashed history
+ return currentAppUrl === '#' && !history.location.search;
+ }
+ }}
+ />,
+ element
+ );
+
+ return () => ReactDOM.unmountComponentAtNode(element);
+};
diff --git a/webpackShims/angular.js b/examples/state_containers_examples/public/index.ts
similarity index 86%
rename from webpackShims/angular.js
rename to examples/state_containers_examples/public/index.ts
index 4857f0f8975bca..bc7ad78574ddb8 100644
--- a/webpackShims/angular.js
+++ b/examples/state_containers_examples/public/index.ts
@@ -17,6 +17,6 @@
* under the License.
*/
-require('jquery');
-require('../node_modules/angular/angular');
-module.exports = window.angular;
+import { StateContainersExamplesPlugin } from './plugin';
+
+export const plugin = () => new StateContainersExamplesPlugin();
diff --git a/examples/state_containers_examples/public/plugin.ts b/examples/state_containers_examples/public/plugin.ts
new file mode 100644
index 00000000000000..beb7b93dbc5b66
--- /dev/null
+++ b/examples/state_containers_examples/public/plugin.ts
@@ -0,0 +1,52 @@
+/*
+ * Licensed to Elasticsearch B.V. under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch B.V. licenses this file to you under
+ * the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import { AppMountParameters, CoreSetup, Plugin } from 'kibana/public';
+
+export class StateContainersExamplesPlugin implements Plugin {
+ public setup(core: CoreSetup) {
+ core.application.register({
+ id: 'state-containers-example-browser-history',
+ title: 'State containers example - browser history routing',
+ async mount(params: AppMountParameters) {
+ const { renderApp, History } = await import('./app');
+ return renderApp(params, {
+ appInstanceId: '1',
+ appTitle: 'Routing with browser history',
+ historyType: History.Browser,
+ });
+ },
+ });
+ core.application.register({
+ id: 'state-containers-example-hash-history',
+ title: 'State containers example - hash history routing',
+ async mount(params: AppMountParameters) {
+ const { renderApp, History } = await import('./app');
+ return renderApp(params, {
+ appInstanceId: '2',
+ appTitle: 'Routing with hash history',
+ historyType: History.Hash,
+ });
+ },
+ });
+ }
+
+ public start() {}
+ public stop() {}
+}
diff --git a/examples/state_containers_examples/public/todo.tsx b/examples/state_containers_examples/public/todo.tsx
new file mode 100644
index 00000000000000..84defb4a91e3f1
--- /dev/null
+++ b/examples/state_containers_examples/public/todo.tsx
@@ -0,0 +1,327 @@
+/*
+ * Licensed to Elasticsearch B.V. under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch B.V. licenses this file to you under
+ * the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import React, { useEffect } from 'react';
+import { Link, Route, Router, Switch, useLocation } from 'react-router-dom';
+import { History } from 'history';
+import {
+ EuiButton,
+ EuiCheckbox,
+ EuiFieldText,
+ EuiPageBody,
+ EuiPageContent,
+ EuiPageContentBody,
+ EuiPageHeader,
+ EuiPageHeaderSection,
+ EuiTitle,
+} from '@elastic/eui';
+import {
+ BaseStateContainer,
+ INullableBaseStateContainer,
+ createKbnUrlStateStorage,
+ createSessionStorageStateStorage,
+ createStateContainer,
+ createStateContainerReactHelpers,
+ PureTransition,
+ syncStates,
+ getStateFromKbnUrl,
+} from '../../../src/plugins/kibana_utils/public';
+import { useUrlTracker } from '../../../src/plugins/kibana_react/public';
+import {
+ defaultState,
+ pureTransitions,
+ TodoActions,
+ TodoState,
+} from '../../../src/plugins/kibana_utils/demos/state_containers/todomvc';
+
+interface GlobalState {
+ text: string;
+}
+interface GlobalStateAction {
+ setText: PureTransition;
+}
+const defaultGlobalState: GlobalState = { text: '' };
+const globalStateContainer = createStateContainer(
+ defaultGlobalState,
+ {
+ setText: state => text => ({ ...state, text }),
+ }
+);
+
+const GlobalStateHelpers = createStateContainerReactHelpers();
+
+const container = createStateContainer(defaultState, pureTransitions);
+const { Provider, connect, useTransitions, useState } = createStateContainerReactHelpers<
+ typeof container
+>();
+
+interface TodoAppProps {
+ filter: 'completed' | 'not-completed' | null;
+}
+
+const TodoApp: React.FC = ({ filter }) => {
+ const { setText } = GlobalStateHelpers.useTransitions();
+ const { text } = GlobalStateHelpers.useState();
+ const { edit: editTodo, delete: deleteTodo, add: addTodo } = useTransitions();
+ const todos = useState();
+ const filteredTodos = todos.filter(todo => {
+ if (!filter) return true;
+ if (filter === 'completed') return todo.completed;
+ if (filter === 'not-completed') return !todo.completed;
+ return true;
+ });
+ const location = useLocation();
+ return (
+ <>
+
+
+
+ All
+
+
+
+
+ Completed
+
+
+
+
+ Not Completed
+
+
+
+ >
+ );
+};
+
+const TodoAppConnected = GlobalStateHelpers.connect(() => ({}))(
+ connect(() => ({}))(TodoApp)
+);
+
+export const TodoAppPage: React.FC<{
+ history: History;
+ appInstanceId: string;
+ appTitle: string;
+ appBasePath: string;
+ isInitialRoute: () => boolean;
+}> = props => {
+ const initialAppUrl = React.useRef(window.location.href);
+ const [useHashedUrl, setUseHashedUrl] = React.useState(false);
+
+ /**
+ * Replicates what src/legacy/ui/public/chrome/api/nav.ts did
+ * Persists the url in sessionStorage and tries to restore it on "componentDidMount"
+ */
+ useUrlTracker(`lastUrlTracker:${props.appInstanceId}`, props.history, urlToRestore => {
+ // shouldRestoreUrl:
+ // App decides if it should restore url or not
+ // In this specific case, restore only if navigated to initial route
+ if (props.isInitialRoute()) {
+ // navigated to the base path, so should restore the url
+ return true;
+ } else {
+ // navigated to specific route, so should not restore the url
+ return false;
+ }
+ });
+
+ useEffect(() => {
+ // have to sync with history passed to react-router
+ // history v5 will be singleton and this will not be needed
+ const kbnUrlStateStorage = createKbnUrlStateStorage({
+ useHash: useHashedUrl,
+ history: props.history,
+ });
+
+ const sessionStorageStateStorage = createSessionStorageStateStorage();
+
+ /**
+ * Restoring global state:
+ * State restoration similar to what GlobalState in legacy world did
+ * It restores state both from url and from session storage
+ */
+ const globalStateKey = `_g`;
+ const globalStateFromInitialUrl = getStateFromKbnUrl(
+ globalStateKey,
+ initialAppUrl.current
+ );
+ const globalStateFromCurrentUrl = kbnUrlStateStorage.get(globalStateKey);
+ const globalStateFromSessionStorage = sessionStorageStateStorage.get(
+ globalStateKey
+ );
+
+ const initialGlobalState: GlobalState = {
+ ...defaultGlobalState,
+ ...globalStateFromCurrentUrl,
+ ...globalStateFromSessionStorage,
+ ...globalStateFromInitialUrl,
+ };
+ globalStateContainer.set(initialGlobalState);
+ kbnUrlStateStorage.set(globalStateKey, initialGlobalState, { replace: true });
+ sessionStorageStateStorage.set(globalStateKey, initialGlobalState);
+
+ /**
+ * Restoring app local state:
+ * State restoration similar to what AppState in legacy world did
+ * It restores state both from url
+ */
+ const appStateKey = `_todo-${props.appInstanceId}`;
+ const initialAppState: TodoState =
+ getStateFromKbnUrl(appStateKey, initialAppUrl.current) ||
+ kbnUrlStateStorage.get(appStateKey) ||
+ defaultState;
+ container.set(initialAppState);
+ kbnUrlStateStorage.set(appStateKey, initialAppState, { replace: true });
+
+ // start syncing only when made sure, that state in synced
+ const { stop, start } = syncStates([
+ {
+ stateContainer: withDefaultState(container, defaultState),
+ storageKey: appStateKey,
+ stateStorage: kbnUrlStateStorage,
+ },
+ {
+ stateContainer: withDefaultState(globalStateContainer, defaultGlobalState),
+ storageKey: globalStateKey,
+ stateStorage: kbnUrlStateStorage,
+ },
+ {
+ stateContainer: withDefaultState(globalStateContainer, defaultGlobalState),
+ storageKey: globalStateKey,
+ stateStorage: sessionStorageStateStorage,
+ },
+ ]);
+
+ start();
+
+ return () => {
+ stop();
+
+ // reset state containers
+ container.set(defaultState);
+ globalStateContainer.set(defaultGlobalState);
+ };
+ }, [props.appInstanceId, props.history, useHashedUrl]);
+
+ return (
+
+
+
+
+
+
+
+
+ State sync example. Instance: ${props.appInstanceId}. {props.appTitle}
+
+
+ setUseHashedUrl(!useHashedUrl)}>
+ {useHashedUrl ? 'Use Expanded State' : 'Use Hashed State'}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+};
+
+function withDefaultState(
+ stateContainer: BaseStateContainer,
+ // eslint-disable-next-line no-shadow
+ defaultState: State
+): INullableBaseStateContainer {
+ return {
+ ...stateContainer,
+ set: (state: State | null) => {
+ if (Array.isArray(defaultState)) {
+ stateContainer.set(state || defaultState);
+ } else {
+ stateContainer.set({
+ ...defaultState,
+ ...state,
+ });
+ }
+ },
+ };
+}
diff --git a/examples/state_containers_examples/tsconfig.json b/examples/state_containers_examples/tsconfig.json
new file mode 100644
index 00000000000000..091130487791bd
--- /dev/null
+++ b/examples/state_containers_examples/tsconfig.json
@@ -0,0 +1,15 @@
+{
+ "extends": "../../tsconfig.json",
+ "compilerOptions": {
+ "outDir": "./target",
+ "skipLibCheck": true
+ },
+ "include": [
+ "index.ts",
+ "public/**/*.ts",
+ "public/**/*.tsx",
+ "server/**/*.ts",
+ "../../typings/**/*"
+ ],
+ "exclude": []
+}
diff --git a/package.json b/package.json
index 0dbed9e432e991..0ed74dd65d1ab9 100644
--- a/package.json
+++ b/package.json
@@ -97,6 +97,7 @@
"packages": [
"packages/*",
"x-pack",
+ "x-pack/plugins/*",
"x-pack/legacy/plugins/*",
"examples/*",
"test/plugin_functional/plugins/*",
@@ -114,7 +115,7 @@
"@babel/core": "^7.5.5",
"@babel/register": "^7.7.0",
"@elastic/apm-rum": "^4.6.0",
- "@elastic/charts": "^16.0.2",
+ "@elastic/charts": "^16.1.0",
"@elastic/datemath": "5.0.2",
"@elastic/ems-client": "1.0.5",
"@elastic/eui": "17.3.1",
@@ -133,8 +134,10 @@
"@kbn/pm": "1.0.0",
"@kbn/test-subj-selector": "0.2.1",
"@kbn/ui-framework": "1.0.0",
+ "@kbn/ui-shared-deps": "1.0.0",
"@types/json-stable-stringify": "^1.0.32",
"@types/lodash.clonedeep": "^4.5.4",
+ "@types/node-forge": "^0.9.0",
"@types/react-grid-layout": "^0.16.7",
"@types/recompose": "^0.30.5",
"JSONStream": "1.3.5",
@@ -168,7 +171,6 @@
"elastic-apm-node": "^3.2.0",
"elasticsearch": "^16.5.0",
"elasticsearch-browser": "^16.5.0",
- "encode-uri-query": "1.0.1",
"execa": "^3.2.0",
"expiry-js": "0.1.7",
"fast-deep-equal": "^3.1.1",
@@ -217,6 +219,7 @@
"mustache": "2.3.2",
"ngreact": "0.5.1",
"node-fetch": "1.7.3",
+ "node-forge": "^0.9.1",
"opn": "^5.5.0",
"oppsy": "^2.0.0",
"pegjs": "0.10.0",
diff --git a/packages/kbn-dev-utils/certs/README.md b/packages/kbn-dev-utils/certs/README.md
new file mode 100644
index 00000000000000..fdf78927894044
--- /dev/null
+++ b/packages/kbn-dev-utils/certs/README.md
@@ -0,0 +1,62 @@
+# Development certificates
+
+Kibana includes several development certificates to enable easy setup of TLS-encrypted communications with Elasticsearch.
+
+_Note: these certificates should **never** be used in production._
+
+## Certificate information
+
+Certificates and keys are provided in multiple formats. These can be used by other packages to set up a new Elastic Stack with Kibana and Elasticsearch. The Certificate Authority (CA) private key is intentionally omitted from this package.
+
+### PEM
+
+* `ca.crt` -- A [PEM-formatted](https://tools.ietf.org/html/rfc1421) [X.509](https://tools.ietf.org/html/rfc5280) certificate that is used as a CA.
+* `elasticsearch.crt` -- A PEM-formatted X.509 certificate and public key for Elasticsearch.
+* `elasticsearch.key` -- A PEM-formatted [PKCS #1](https://tools.ietf.org/html/rfc8017) private key for Elasticsearch.
+* `kibana.crt` -- A PEM-formatted X.509 certificate and public key for Kibana.
+* `kibana.key` -- A PEM-formatted PKCS #1 private key for Kibana.
+
+### PKCS #12
+
+* `elasticsearch.p12` -- A [PKCS #12](https://tools.ietf.org/html/rfc7292) encrypted key store / trust store that contains `ca.crt`, `elasticsearch.crt`, and a [PKCS #8](https://tools.ietf.org/html/rfc5208) encrypted version of `elasticsearch.key`.
+* `kibana.p12` -- A PKCS #12 encrypted key store / trust store that contains `ca.crt`, `kibana.crt`, and a PKCS #8 encrypted version of `kibana.key`.
+
+The password used for both of these is "storepass". Other copies are also provided for testing purposes:
+
+* `elasticsearch_emptypassword.p12` -- The same PKCS #12 key store, encrypted with an empty password.
+* `elasticsearch_nopassword.p12` -- The same PKCS #12 key store, not encrypted with a password.
+
+## Certificate generation
+
+[Elasticsearch cert-util](https://www.elastic.co/guide/en/elasticsearch/reference/current/certutil.html) and [OpenSSL](https://www.openssl.org/) were used to generate these certificates. The following commands were used from the root directory of Elasticsearch:
+
+```
+# Generate the PKCS #12 keystore for a CA, valid for 50 years
+bin/elasticsearch-certutil ca -days 18250 --pass castorepass
+
+# Generate the PKCS #12 keystore for Elasticsearch and sign it with the CA
+bin/elasticsearch-certutil cert -days 18250 --ca elastic-stack-ca.p12 --ca-pass castorepass --name elasticsearch --dns localhost --pass storepass
+
+# Generate the PKCS #12 keystore for Kibana and sign it with the CA
+bin/elasticsearch-certutil cert -days 18250 --ca elastic-stack-ca.p12 --ca-pass castorepass --name kibana --dns localhost --pass storepass
+
+# Copy the PKCS #12 keystore for Elasticsearch with an empty password
+openssl pkcs12 -in elasticsearch.p12 -nodes -passin pass:"storepass" -passout pass:"" | openssl pkcs12 -export -out elasticsearch_emptypassword.p12 -passout pass:""
+
+# Manually create "elasticsearch_nopassword.p12" -- this can be done on macOS by importing the P12 key store into the Keychain and exporting it again
+
+# Extract the PEM-formatted X.509 certificate for the CA
+openssl pkcs12 -in elasticsearch.p12 -out ca.crt -cacerts -passin pass:"storepass" -passout pass:
+
+# Extract the PEM-formatted PKCS #1 private key for Elasticsearch
+openssl pkcs12 -in elasticsearch.p12 -nocerts -passin pass:"storepass" -passout pass:"keypass" | openssl rsa -passin pass:keypass -out elasticsearch.key
+
+# Extract the PEM-formatted X.509 certificate for Elasticsearch
+openssl pkcs12 -in elasticsearch.p12 -out elasticsearch.crt -clcerts -passin pass:"storepass" -passout pass:
+
+# Extract the PEM-formatted PKCS #1 private key for Kibana
+openssl pkcs12 -in kibana.p12 -nocerts -passin pass:"storepass" -passout pass:"keypass" | openssl rsa -passin pass:keypass -out kibana.key
+
+# Extract the PEM-formatted X.509 certificate for Kibana
+openssl pkcs12 -in kibana.p12 -out kibana.crt -clcerts -passin pass:"storepass" -passout pass:
+```
diff --git a/packages/kbn-dev-utils/certs/ca.crt b/packages/kbn-dev-utils/certs/ca.crt
old mode 100755
new mode 100644
index 3e964823c5086b..217935b8d83f63
--- a/packages/kbn-dev-utils/certs/ca.crt
+++ b/packages/kbn-dev-utils/certs/ca.crt
@@ -1,20 +1,29 @@
+Bag Attributes
+ friendlyName: elasticsearch
+ localKeyID: 54 69 6D 65 20 31 35 37 37 34 36 36 31 39 38 30 33 37
+Key Attributes:
+Bag Attributes
+ friendlyName: ca
+ 2.16.840.1.113894.746875.1.1:
+subject=/CN=Elastic Certificate Tool Autogenerated CA
+issuer=/CN=Elastic Certificate Tool Autogenerated CA
-----BEGIN CERTIFICATE-----
-MIIDSjCCAjKgAwIBAgIVAOgxLlE1RMGl2fYgTKDznvDL2vboMA0GCSqGSIb3DQEB
-CwUAMDQxMjAwBgNVBAMTKUVsYXN0aWMgQ2VydGlmaWNhdGUgVG9vbCBBdXRvZ2Vu
-ZXJhdGVkIENBMB4XDTE5MDcxMTE3MzQ0OFoXDTIyMDcxMDE3MzQ0OFowNDEyMDAG
-A1UEAxMpRWxhc3RpYyBDZXJ0aWZpY2F0ZSBUb29sIEF1dG9nZW5lcmF0ZWQgQ0Ew
-ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCNImKp/A9l++Ac7U5lvHOA
-+fYRb8p7AgdfKBMB0v3bo+bpHjkbkf3vYHjo1xJSg5ls6EPK+Do4owkAgKJdrznI
-5/efJOjgA+ylH4rgAfrRIQmiFEWZnAv86vJ+Iq83mfkPELb4dvXCi7AFQkzoM/rY
-Lbi97xha5bA2SEmpYp7VhBTM9zWy+q9Tm5odPO8u2n75GpIM2RwipaXlL0ink+06
-/oweQJoivaDgpDOmUXCFPmpV3VCdhUGxDQPyG0upQkF+NbQoei4RmluPEmVz4S7I
-TFLWjX7LeZVP63bJkcCgiq6Hm97kDtr9EYlPKhHm7UMWzhNzHbfvySMDzqAJC0KX
-AgMBAAGjUzBRMB0GA1UdDgQWBBRKqaaQ/+jT+ipPLJe7qekp1N/zizAfBgNVHSME
-GDAWgBRKqaaQ/+jT+ipPLJe7qekp1N/zizAPBgNVHRMBAf8EBTADAQH/MA0GCSqG
-SIb3DQEBCwUAA4IBAQA7Gcq8h8yDXvepfKUAcTTMCBZkI+g3qE1gfRwjW7587CIj
-xnrzEqANU+Q1lv7IeQ158HiduDUMZfnvpuNwkf0HkqnRWb57RwfVdCAlAeZmzipq
-5ZJWlIW4dbmk57nGLg4fCszedi0uSGytZ2/BUdpWyC0fAM97h7Agtr4xGGKMEL67
-uB55ijt61V62HZ5wWXWNO9m+wfmdnt+YQViQJHtpYz1oOmWhY3dpitZLfWs1sLLD
-w3CZOhmWX7+P7+HlCkSBF4swzHOCI3THyX61NbLxju8VkTAjwbZPq4EOnVKnO6kr
-RdwQVnzKnqG5fxfSGknNahy0pOhJHZlGLwECRlgF
+MIIDSzCCAjOgAwIBAgIUW0brhEtYK3tUBYlXnUa+AMmAX6kwDQYJKoZIhvcNAQEL
+BQAwNDEyMDAGA1UEAxMpRWxhc3RpYyBDZXJ0aWZpY2F0ZSBUb29sIEF1dG9nZW5l
+cmF0ZWQgQ0EwIBcNMTkxMjI3MTcwMjMyWhgPMjA2OTEyMTQxNzAyMzJaMDQxMjAw
+BgNVBAMTKUVsYXN0aWMgQ2VydGlmaWNhdGUgVG9vbCBBdXRvZ2VuZXJhdGVkIENB
+MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAplO5m5Xy8xERyA0/G5SM
+Nu2QXkfS+m7ZTFjSmtwqX7BI1I6ISI4Yw8QxzcIgSbEGlSqb7baeT+A/1JQj0gZN
+KOnKbazl+ujVRJpsfpt5iUsnQyVPheGekcHkB+9WkZPgZ1oGRENr/4Eb1VImQf+Y
+yo/FUj8X939tYW0fficAqYKv8/4NWpBUbeop8wsBtkz738QKlmPkMwC4FbuF2/bN
+vNuzQuRbGMVmPeyivZJRfDAMKExoXjCCLmbShdg4dUHsUjVeWQZ6s4vbims+8qF9
+b4bseayScQNNU3hc5mkfhEhSM0KB0lDpSvoCxuXvXzb6bOk7xIdYo+O4vHUhvSkQ
+mwIDAQABo1MwUTAdBgNVHQ4EFgQUGu0mDnvDRnBdNBG8DxwPdWArB0kwHwYDVR0j
+BBgwFoAUGu0mDnvDRnBdNBG8DxwPdWArB0kwDwYDVR0TAQH/BAUwAwEB/zANBgkq
+hkiG9w0BAQsFAAOCAQEASv/FYOwWGnQreH8ulcVupGeZj25dIjZiuKfJmslH8QN/
+pVCIzAxNZjGjCpKxbJoCu5U9USaBylbhigeBJEq4wmYTs/WPu4uYMgDj0MILuHin
+RQqgEVG0uADGEgH2nnk8DeY8gQvGpJRQGlXNK8pb+pCsy6F8k/svGOeBND9osHfU
+CVEo5nXjfq6JCFt6hPx7kl4h3/j3C4wNy/Dv/QINdpPsl6CnF17Q9R9d60WFv42/
+pkl7W1hszCG9foNJOJabuWfVoPkvKQjoCvPitZt/hCaFZAW49PmAVhK+DAohQ91l
+TZhDmYqHoXNiRDQiUT68OS7RlfKgNpr/vMTZXDxpmw==
-----END CERTIFICATE-----
diff --git a/packages/kbn-dev-utils/certs/elasticsearch.crt b/packages/kbn-dev-utils/certs/elasticsearch.crt
old mode 100755
new mode 100644
index b30e11e9bbce14..87ba02019903f1
--- a/packages/kbn-dev-utils/certs/elasticsearch.crt
+++ b/packages/kbn-dev-utils/certs/elasticsearch.crt
@@ -1,20 +1,29 @@
+Bag Attributes
+ friendlyName: elasticsearch
+ localKeyID: 54 69 6D 65 20 31 35 37 37 34 36 36 31 39 38 30 33 37
+Key Attributes:
+Bag Attributes
+ friendlyName: elasticsearch
+ localKeyID: 54 69 6D 65 20 31 35 37 37 34 36 36 31 39 38 30 33 37
+subject=/CN=elasticsearch
+issuer=/CN=Elastic Certificate Tool Autogenerated CA
-----BEGIN CERTIFICATE-----
-MIIDRDCCAiygAwIBAgIVAI8V1fwvXKykKtp5k0cLpTOtY+DVMA0GCSqGSIb3DQEB
+MIIDQDCCAiigAwIBAgIVAI93OQE6tZffPyzenSg3ljE3JJBzMA0GCSqGSIb3DQEB
CwUAMDQxMjAwBgNVBAMTKUVsYXN0aWMgQ2VydGlmaWNhdGUgVG9vbCBBdXRvZ2Vu
-ZXJhdGVkIENBMB4XDTE5MDcxMTE3MzUxOFoXDTIyMDcxMDE3MzUxOFowGDEWMBQG
-A1UEAxMNZWxhc3RpY3NlYXJjaDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
-ggEBALW+8gV6m6wYmTZmrXzNWKElE+ePkkikCviNfuWonWqxgAoWpAwAx2FvdhP3
-UDFbe38ydJX4oDgXeC25vdIR6z2uqzx+GXSNSybO7luuOUYQOP4Xf5Cj3zzXXMyu
-nY1nZTVsChI9jAMz4cZZdUd04f4r4TBNxrFCcVR0uec5RGRXuP8rSQd9AbYFUVYf
-jJeLb24asghb2Ku+c2JGvMqPEXFWFGOXFhUoIbRjCJNTDcr1ZXPof3+fO1l6HmhT
-QBSqC4IZL8XqANltDT4tCQDD8L9+ckWJD8MP3wPkPUGZId2gLu++hrb9YfiP2upq
-N/f3P7l5Fcisw1iwQC4+DGMTyfcCAwEAAaNpMGcwHQYDVR0OBBYEFGuiGk8HLpG2
-MyA24/J+GwxT32ikMB8GA1UdIwQYMBaAFEqpppD/6NP6Kk8sl7up6SnU3/OLMBoG
-A1UdEQQTMBGCCWxvY2FsaG9zdIcEfwAAATAJBgNVHRMEAjAAMA0GCSqGSIb3DQEB
-CwUAA4IBAQB8yfY0edAgq2KnJNWyl8NpHNfqtM27+/LR2V8OxVwxV1hc4ZilczLu
-CXeqP9uqBVjcck6fvLrjy4LhSG0V05j51UMJ1FjFVTBuhlrDcd3j8848yWrmyz8z
-vPYYY2vIN9d1NsBgufULwliBT4UJchsYE8xT5ayAzGHKCTlzHGHMTPzYjwac8nbT
-nd2u+6h0OQOJn6K4v+RfXtN4EA8ZUrYxUkqHNS3cFB5sxH7JQGi25XJc5MfxyCwY
-YOukxbN85ew861N6oVd+W+nGJu8WOLU88/uvCv+dLhnAlnnIOLqvmrD5m7gFsFO9
-Z7Xz/U1SbNipWy9OLOhqq2Ja59j8p9e5
+ZXJhdGVkIENBMCAXDTE5MTIyNzE3MDMxN1oYDzIwNjkxMjE0MTcwMzE3WjAYMRYw
+FAYDVQQDEw1lbGFzdGljc2VhcmNoMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
+CgKCAQEA2EkPfvE3ZNMjHCAQZhpImoXBCIN6KavvJSbVHRtLzAXB4wxige+vFQWb
+4umqPeEeVH7FvrsRqn24tUgGIkag9p9AOwYxfcT3vwNqcK/EztIlYFs72pmYg7Ez
+s6+qLc/YSLOT3aMoHKDHE93z1jYIDGccyjGbv9NsdgCbLHD0TQuqm+7pKy1MZoJm
+0qn4KYw4kXakVNWlxm5GIwr8uqU/w4phrikcOOWqRzsxByoQajypLOA4eD/uWnI2
+zGyPQy7Bkxojiy1ss0CVlrl8fJgcjC4PONpm1ibUSX3SoZ8PopPThR6gvvwoQolR
+rYu4+D+rsX7q/ldA6vBOiHBD8r4QoQIDAQABo2MwYTAdBgNVHQ4EFgQUSlIMCYYd
+e72A0rUqaCkjVPkGPIwwHwYDVR0jBBgwFoAUGu0mDnvDRnBdNBG8DxwPdWArB0kw
+FAYDVR0RBA0wC4IJbG9jYWxob3N0MAkGA1UdEwQCMAAwDQYJKoZIhvcNAQELBQAD
+ggEBAImbzBVAEjiLRsNDLP7QAl0k7lVmfQRFz5G95ZTAUSUgbqqymDvry47yInFF
+3o12TuI1GxK5zHzi+qzpJLyrnGwGK5JBR+VGxIBBKFVcFh1WNGKV6kSO/zBzO7PO
+4Jw4G7By/ImWvS0RBhBUQ9XbQZN3WcVkVVV8UQw5Y7JoKtM+fzyEKXKRCTsvgH+h
+3+fUBgqwal2Mz4KPH57Jrtk209dtn7tnQxHTNLo0niHyEcfrpuG3YFqTwekr+5FF
+FniIcYHPGjag1WzLIdyhe88FFpuav19mlCaxBACc7t97v+euSVUWnsKpy4dLydpv
+NxJiI9eWbJZ7f5VM7o64pm7U1cU=
-----END CERTIFICATE-----
diff --git a/packages/kbn-dev-utils/certs/elasticsearch.key b/packages/kbn-dev-utils/certs/elasticsearch.key
old mode 100755
new mode 100644
index 1013ce39712461..9ae4e314630d1e
--- a/packages/kbn-dev-utils/certs/elasticsearch.key
+++ b/packages/kbn-dev-utils/certs/elasticsearch.key
@@ -1,27 +1,27 @@
-----BEGIN RSA PRIVATE KEY-----
-MIIEpAIBAAKCAQEAtb7yBXqbrBiZNmatfM1YoSUT54+SSKQK+I1+5aidarGAChak
-DADHYW92E/dQMVt7fzJ0lfigOBd4Lbm90hHrPa6rPH4ZdI1LJs7uW645RhA4/hd/
-kKPfPNdczK6djWdlNWwKEj2MAzPhxll1R3Th/ivhME3GsUJxVHS55zlEZFe4/ytJ
-B30BtgVRVh+Ml4tvbhqyCFvYq75zYka8yo8RcVYUY5cWFSghtGMIk1MNyvVlc+h/
-f587WXoeaFNAFKoLghkvxeoA2W0NPi0JAMPwv35yRYkPww/fA+Q9QZkh3aAu776G
-tv1h+I/a6mo39/c/uXkVyKzDWLBALj4MYxPJ9wIDAQABAoIBAQCb1ggrjn/gxo7I
-yK3FL0XplqNEkCR8SLxndtvyC+w+Schh3hv3dst+zlXOtOZ8C9cOr7KrzS2EKwuP
-GY6bi2XL0/NbwTwOZgCkXBahYfgWDV7w8DEfUoPd5UPa9XZ+gsOTVPolvcRKErhq
-nNYk2SHWEMXb5zSRVUlbg2LL0pzD88bIuKJX+FwPvWcQc2P4OdVTq77iedcl82zZ
-6PqTNqKMep7/odLQeBfX7OapOAviVnPYHe0TA114COOimR/pK8IA1OJymX5rgU7O
-Wh+uNBSxdHsTTYTkAvw8Bt5Q8n1WCpQwZoYU3xWuSlu7eJ7kcgdFOu9r9GjSXysT
-UYCd8s0BAoGBAPXPpCDRxjqF3/ToZ5x5dorKxxJyrmldzMJaUjqOv7y6kezbdBql
-n7p3AJ5UfYUW/N6pgQXaWF4MPSyj7ItHhwHjL+v0Manmi5gq8oA30fplhjUlPre7
-Lx4v7SEmH739EHrkZ2ClIQwY3wKuN8mZKgw6RseFgphczDmhHCqEbjW3AoGBAL1H
-fkl0RNdZ3nZg0u7MUVk8ytnqBsp7bNFhEs0zUl7ghu3NLaPt8qhirG638oMSCxqH
-FPeM3/DryokQAym+UHYNMwiBziEUB2CKMMj7S5YFFWIldCxFeImCO2EP+y3hmbTZ
-yjsznNrDzQtErZGP+JTRZcy9xF0oAfVt0G/O1Q3BAoGAa8bqINW5g6l1Q82uuEXt
-evdkB6uu21YcVE8D5Nb4LMjk+KRUKObbvQc2hzVmf7dPklVh0+4jdsEJBYyuR3dK
-M8KoHV3JdMQ4CrUx9JQFBjQDf0PgVvDEvQiogTNVEZlm42tIBHECp2o0RdmbblIw
-xIG8zPi2BRYTGWWRkvbT18sCgYA+c/B/XBW62LRGavwuPsw4nY5xCH7lIIRvMZB6
-lIyBMaRToneEt2ZxmN08SwWBqdpwDlIkvB7H54UUZGwmwdzaltBX5jyVPX6RpAck
-yYXPIi5EDAeg8+sptAbTp+pA4UdOHO5VSlpe9GwbY7XBabejotPsElFQS3sZ9/nm
-amByAQKBgQCJWghllys1qk76/6PmeVjwjaK9n8o+94LWhqODXlACmDRyse5dwpYb
-BIsMMZrNu1YsqDXlWpU7xNa6A8j4oa+EPnm/01PjdueAvMB/oE1woawM5tSsd8NQ
-zeQPDhxjDxzaO5l4oJLZg6FT7iQAprhYZjgb8m1vz0D2Xid0A3Kgpw==
+MIIEogIBAAKCAQEA2EkPfvE3ZNMjHCAQZhpImoXBCIN6KavvJSbVHRtLzAXB4wxi
+ge+vFQWb4umqPeEeVH7FvrsRqn24tUgGIkag9p9AOwYxfcT3vwNqcK/EztIlYFs7
+2pmYg7Ezs6+qLc/YSLOT3aMoHKDHE93z1jYIDGccyjGbv9NsdgCbLHD0TQuqm+7p
+Ky1MZoJm0qn4KYw4kXakVNWlxm5GIwr8uqU/w4phrikcOOWqRzsxByoQajypLOA4
+eD/uWnI2zGyPQy7Bkxojiy1ss0CVlrl8fJgcjC4PONpm1ibUSX3SoZ8PopPThR6g
+vvwoQolRrYu4+D+rsX7q/ldA6vBOiHBD8r4QoQIDAQABAoIBAB+s44YV0aUEfvnZ
+gE1TwBpRSGn0x2le8tEgFMoEe19P4Itd/vdEoQGVJrVevz38wDJjtpYuU3ICo5B5
+EdznNx+nRwLd71WaCSaCW45RT6Nyh2LLOcLUB9ARnZ7NNUEsVWKgWiF1iaRXr5Ar
+S1Ct7RPT7hV2mnbHgfTuNcuWZ1D5BUcqNczNoHsV6guFChiwTr7ZObnKj4qJLwdu
+ioYYWno4ZLgsk4SfW6DXUCvfKROfYdDd2rGu0NQ4QxT3Q98AsXlrlUITBQbpQEgy
+5GSTEh/4sRYj4NQZqncDpPgXm22kYdU7voBjt/zu66oq1W6kKQ4JwPmyc2SI0haa
+/pyCMtkCgYEA/y3vs59RvrM6xpT77lf7WigSBbIBQxeKs9RGNoN0Nn/eR0MlQAUG
+SmCkkEOcUGuVMnoo5Kc73IP/Q1+O4UGg7f1Gs8KeFPFQMm/wcSL7obvRWray1Bw6
+ohITJPqZYZrw3hmkOMxkLpvUydivN1Unm7BezjOa+T/+OaV3PyAYufsCgYEA2Psb
+S8OQhFiVbOKlMYOebvG+AnhAzJiSVus9R9NcViv20E61PRj2rfA398pYpZ8nxaQp
+cWGy+POZbkxRCprZ1GHkwWjaQysgeOCbJv8nQ2oh5C0ZCaGw6lfmi2mN097+Prmx
+QE8j8OKj3wVI6bniCF7vzwfG3c5cU73elLTAWRMCgYBoA/eDRlvx2ekJbU1MGDzy
+wQann6l4Ca6WIt8D9Y13caPPdIVIlUO9KauqyoR7G39TdgwZODnkZ0Gz2s3I8BGD
+MQyS1a/OZZcFGC/wTgw4HvD1gydd4qvbyHZZSnUfHiM0xUr1hAsKHKceJ980NNfS
+VJAwiUSQeQ9NvC7hYlnx5QKBgDxESsmZcRuBa0eKEC4Xi7rvBEK1WfI58nOX9TZs
++3mnzm7/XZGxzFp1nWYC2uptsWNQ/H3UkBxbtOMQ6XWTmytFYX9i+zSq1uMcJ5wG
+RMaRxQYWjJzDP1tnvM4+LDmL93w+oX/mO2pd2PxKAH2CtshybhNH6rGS7swHsboG
+FmLnAoGAYTnTcWD1qiwjbJR5ZdukAjIq39cGcf0YOVJCiaFS+5vTirbw04ARvNyM
+rxU8EpVN1sKC411pgNvlm6KZJHwihRRQoY+UI2fn78bHBH991QhlrTPO6TBZx7Aw
++hzyxqAiSBX65dQo0e4C15wZysQO/bdT5Def0+UTDR8j8ZgMAQg=
-----END RSA PRIVATE KEY-----
diff --git a/packages/kbn-dev-utils/certs/elasticsearch.p12 b/packages/kbn-dev-utils/certs/elasticsearch.p12
new file mode 100644
index 00000000000000..02a9183cd8a50e
Binary files /dev/null and b/packages/kbn-dev-utils/certs/elasticsearch.p12 differ
diff --git a/packages/kbn-dev-utils/certs/elasticsearch_emptypassword.p12 b/packages/kbn-dev-utils/certs/elasticsearch_emptypassword.p12
new file mode 100644
index 00000000000000..3162982ac635ad
Binary files /dev/null and b/packages/kbn-dev-utils/certs/elasticsearch_emptypassword.p12 differ
diff --git a/packages/kbn-dev-utils/certs/elasticsearch_nopassword.p12 b/packages/kbn-dev-utils/certs/elasticsearch_nopassword.p12
new file mode 100644
index 00000000000000..3a22a58d207dfb
Binary files /dev/null and b/packages/kbn-dev-utils/certs/elasticsearch_nopassword.p12 differ
diff --git a/packages/kbn-dev-utils/certs/kibana.crt b/packages/kbn-dev-utils/certs/kibana.crt
new file mode 100644
index 00000000000000..1c83be587bff9b
--- /dev/null
+++ b/packages/kbn-dev-utils/certs/kibana.crt
@@ -0,0 +1,29 @@
+Bag Attributes
+ friendlyName: kibana
+ localKeyID: 54 69 6D 65 20 31 35 37 37 34 36 36 32 32 33 30 33 39
+Key Attributes:
+Bag Attributes
+ friendlyName: kibana
+ localKeyID: 54 69 6D 65 20 31 35 37 37 34 36 36 32 32 33 30 33 39
+subject=/CN=kibana
+issuer=/CN=Elastic Certificate Tool Autogenerated CA
+-----BEGIN CERTIFICATE-----
+MIIDOTCCAiGgAwIBAgIVANNWkg9lzNiLqNkMFhFKHcXyaZmqMA0GCSqGSIb3DQEB
+CwUAMDQxMjAwBgNVBAMTKUVsYXN0aWMgQ2VydGlmaWNhdGUgVG9vbCBBdXRvZ2Vu
+ZXJhdGVkIENBMCAXDTE5MTIyNzE3MDM0MloYDzIwNjkxMjE0MTcwMzQyWjARMQ8w
+DQYDVQQDEwZraWJhbmEwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCQ
+wYYbQtbRBKJ4uNZc2+IgRU+7NNL21ZebQlEIMgK7jAqOMrsW2b5DATz41Fd+GQFU
+FUYYjwo+PQj6sJHshOJo/gNb32HrydvMI7YPvevkszkuEGCfXxQ3Dw2RTACLgD0Q
+OCkwHvn3TMf0loloV/ePGWaZDYZaXi3a5DdWi/HFFoJysgF0JV2f6XyKhJkGaEfJ
+s9pWX269zH/XQvGNx4BEimJpYB8h4JnDYPFIiQdqj+sl2b+kS1hH9kL5gBAMXjFU
+vcNnX+PmyTjyJrGo75k0ku+spBf1bMwuQt3uSmM+TQIXkvFDmS0DOVESrpA5EC1T
+BUGRz6o/I88Xx4Mud771AgMBAAGjYzBhMB0GA1UdDgQWBBQLB1Eo23M3Ss8MsFaz
+V+Twcb3PmDAfBgNVHSMEGDAWgBQa7SYOe8NGcF00EbwPHA91YCsHSTAUBgNVHREE
+DTALgglsb2NhbGhvc3QwCQYDVR0TBAIwADANBgkqhkiG9w0BAQsFAAOCAQEAnEl/
+z5IElIjvkK4AgMPrNcRlvIGDt2orEik7b6Jsq6/RiJQ7cSsYTZf7xbqyxNsUOTxv
++frj47MEN448H2nRvUxH29YR3XygV5aEwADSAhwaQWn0QfWTCZbJTmSoNEDtDOzX
+TGDlAoCD9s9Xz9S1JpxY4H+WWRZrBSDM6SC1c6CzuEeZRuScNAjYD5mh2v6fOlSy
+b8xJWSg0AFlJPCa3ZsA2SKbNqI0uNfJTnkXRm88Z2NHcgtlADbOLKauWfCrpgsCk
+cZgo6yAYkOM148h/8wGla1eX+iE1R72NUABGydu8MSQKvc0emWJkGsC1/KqPlf/O
+eOUsdwn1yDKHRxDHyA==
+-----END CERTIFICATE-----
diff --git a/packages/kbn-dev-utils/certs/kibana.key b/packages/kbn-dev-utils/certs/kibana.key
new file mode 100644
index 00000000000000..4a4e6b4cb8c360
--- /dev/null
+++ b/packages/kbn-dev-utils/certs/kibana.key
@@ -0,0 +1,27 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIEowIBAAKCAQEAkMGGG0LW0QSieLjWXNviIEVPuzTS9tWXm0JRCDICu4wKjjK7
+Ftm+QwE8+NRXfhkBVBVGGI8KPj0I+rCR7ITiaP4DW99h68nbzCO2D73r5LM5LhBg
+n18UNw8NkUwAi4A9EDgpMB7590zH9JaJaFf3jxlmmQ2GWl4t2uQ3VovxxRaCcrIB
+dCVdn+l8ioSZBmhHybPaVl9uvcx/10LxjceARIpiaWAfIeCZw2DxSIkHao/rJdm/
+pEtYR/ZC+YAQDF4xVL3DZ1/j5sk48iaxqO+ZNJLvrKQX9WzMLkLd7kpjPk0CF5Lx
+Q5ktAzlREq6QORAtUwVBkc+qPyPPF8eDLne+9QIDAQABAoIBAHl9suxWYKz00te3
+alJtSZAEHDLm1tjL034/XnseXiTCGGnYMiWvgnwCIgZFUVlH61GCuV4LT3GFEHA2
+mYKE1PGBn5gQF8MpnAvtPPRhVgaQVUFQBYg86F59h8mWnC545sciG4+DsA/apUem
+wJSOn/u+Odni/AwEV0ALolZFBhl+0rccSr+6paJnzJ7QNiIn6EWbgb0n9WXqkhap
+TqoPclBHm0ObeBI6lNyfvBZ8HB3hyjWZInNCaAs9DnkNPh4evuttUn/KlOPOVn9r
+xz2UYsmVW6E+yPXUpSYkFQN9aaPF6alOz8PIfF8Wit7pmZMmInluGcwi/us9+ZTN
+8gNvpoECgYEA0KC7XEoXRsBTN4kPznkGftvj1dtgB35W/HxXNouArQQjCbLhqcsA
+jqaK0f+stYzSWZXGsKl9yQU9KA7u/wCHmLep70l7WsYYUKdkhWouK0HU5MeeLwB0
+N4ekQOQuQGqelqMo7IG2hQhTYD9PB4F3G0Sz1FgdObfuGPKfvNFVjckCgYEAsaAA
+IY/TpRBWeWZfyXrnkp3atOPzkdpjb6cfT8Kib9bIECXr7ULUxA5QANX05ofodhsW
+3+7iW5wicyZ1VNVEsPRL0aw7YUbNpBvob8faBUZ2KEdKQr42IfVOo7TQnvVXtumR
+UE+dNvWUL2PbL0wMxD1XbMSmOze/wF8X2CeyDc0CgYBQnLqol2xVBz1gaRJ1emgb
+HoXzfVemrZeY6cadKdwnfkC3n6n4fJsTg6CCMiOe5vHkca4bVvJmeSK/Vr3cRG0g
+gl8kOaVzVrXQfE2oC3YZes9zMvqZOLivODcsZ77DXy82D4dhk2FeF/B3cR7tTIYk
+QDCoLP/l7H8QnrdAMza2mQKBgDODwuX475ncviehUEB/26+DBo4V2ms/mj0kjAk2
+2qNy+DzuspjyHADsYbmMU+WUHxA51Q2HG7ET/E3HJpo+7BgiEecye1pADZ391hCt
+Nob3I4eU/W2T+uEoYvFJnIOthg3veYyAOolY+ewwmr4B4WX8oGFUOx3Lklo5ehHf
+mV01AoGBAI/c6OoHdcqQsZxKlxDNLyB2bTbowAcccoZIOjkC5fkkbsmMDLfScBfW
+Q4YYJsmJBdrWNvo7jCl17Mcc4Is3RlmHDrItRkaZj+ehqAN3ejrnPLdgYeW/5XDK
+e7yBj7oJd4oKZc59jVytdHvo5R8K0QohAv9gQEZ/tdypX+xWe+5E
+-----END RSA PRIVATE KEY-----
diff --git a/packages/kbn-dev-utils/certs/kibana.p12 b/packages/kbn-dev-utils/certs/kibana.p12
new file mode 100644
index 00000000000000..06bbd23881290b
Binary files /dev/null and b/packages/kbn-dev-utils/certs/kibana.p12 differ
diff --git a/packages/kbn-dev-utils/src/certs.ts b/packages/kbn-dev-utils/src/certs.ts
index 0d340e4e8c906f..f72e3ee547b5cb 100644
--- a/packages/kbn-dev-utils/src/certs.ts
+++ b/packages/kbn-dev-utils/src/certs.ts
@@ -22,3 +22,14 @@ import { resolve } from 'path';
export const CA_CERT_PATH = resolve(__dirname, '../certs/ca.crt');
export const ES_KEY_PATH = resolve(__dirname, '../certs/elasticsearch.key');
export const ES_CERT_PATH = resolve(__dirname, '../certs/elasticsearch.crt');
+export const ES_P12_PATH = resolve(__dirname, '../certs/elasticsearch.p12');
+export const ES_P12_PASSWORD = 'storepass';
+export const ES_EMPTYPASSWORD_P12_PATH = resolve(
+ __dirname,
+ '../certs/elasticsearch_emptypassword.p12'
+);
+export const ES_NOPASSWORD_P12_PATH = resolve(__dirname, '../certs/elasticsearch_nopassword.p12');
+export const KBN_KEY_PATH = resolve(__dirname, '../certs/kibana.key');
+export const KBN_CERT_PATH = resolve(__dirname, '../certs/kibana.crt');
+export const KBN_P12_PATH = resolve(__dirname, '../certs/kibana.p12');
+export const KBN_P12_PASSWORD = 'storepass';
diff --git a/packages/kbn-dev-utils/src/index.ts b/packages/kbn-dev-utils/src/index.ts
index dc12613cf2a9e9..2fc29b71b262ec 100644
--- a/packages/kbn-dev-utils/src/index.ts
+++ b/packages/kbn-dev-utils/src/index.ts
@@ -25,7 +25,19 @@ export {
ToolingLogCollectingWriter,
} from './tooling_log';
export { createAbsolutePathSerializer } from './serializers';
-export { CA_CERT_PATH, ES_KEY_PATH, ES_CERT_PATH } from './certs';
+export {
+ CA_CERT_PATH,
+ ES_KEY_PATH,
+ ES_CERT_PATH,
+ ES_P12_PATH,
+ ES_P12_PASSWORD,
+ ES_EMPTYPASSWORD_P12_PATH,
+ ES_NOPASSWORD_P12_PATH,
+ KBN_KEY_PATH,
+ KBN_CERT_PATH,
+ KBN_P12_PATH,
+ KBN_P12_PASSWORD,
+} from './certs';
export { run, createFailError, createFlagError, combineErrors, isFailError, Flags } from './run';
export { REPO_ROOT } from './repo_root';
export { KbnClient } from './kbn_client';
diff --git a/packages/kbn-es/src/cluster.js b/packages/kbn-es/src/cluster.js
index 665f80e3802e35..ceb4a5b6aece14 100644
--- a/packages/kbn-es/src/cluster.js
+++ b/packages/kbn-es/src/cluster.js
@@ -35,7 +35,7 @@ const { createCliError } = require('./errors');
const { promisify } = require('util');
const treeKillAsync = promisify(require('tree-kill'));
const { parseSettings, SettingsFilter } = require('./settings');
-const { CA_CERT_PATH, ES_KEY_PATH, ES_CERT_PATH } = require('@kbn/dev-utils');
+const { CA_CERT_PATH, ES_P12_PATH, ES_P12_PASSWORD } = require('@kbn/dev-utils');
const readFile = util.promisify(fs.readFile);
// listen to data on stream until map returns anything but undefined
@@ -261,9 +261,9 @@ exports.Cluster = class Cluster {
const esArgs = [].concat(options.esArgs || []);
if (this._ssl) {
esArgs.push('xpack.security.http.ssl.enabled=true');
- esArgs.push(`xpack.security.http.ssl.key=${ES_KEY_PATH}`);
- esArgs.push(`xpack.security.http.ssl.certificate=${ES_CERT_PATH}`);
- esArgs.push(`xpack.security.http.ssl.certificate_authorities=${CA_CERT_PATH}`);
+ esArgs.push(`xpack.security.http.ssl.keystore.path=${ES_P12_PATH}`);
+ esArgs.push(`xpack.security.http.ssl.keystore.type=PKCS12`);
+ esArgs.push(`xpack.security.http.ssl.keystore.password=${ES_P12_PASSWORD}`);
}
const args = parseSettings(extractConfigFiles(esArgs, installPath, { log: this._log }), {
diff --git a/packages/kbn-es/src/integration_tests/__fixtures__/es_bin.js b/packages/kbn-es/src/integration_tests/__fixtures__/es_bin.js
index d3181a748ffbbe..d374abe5db0683 100644
--- a/packages/kbn-es/src/integration_tests/__fixtures__/es_bin.js
+++ b/packages/kbn-es/src/integration_tests/__fixtures__/es_bin.js
@@ -34,6 +34,8 @@ if (!start) {
let serverUrl;
const server = createServer(
{
+ // Note: the integration uses the ES_P12_PATH, but that keystore contains
+ // the same key/cert as ES_KEY_PATH and ES_CERT_PATH
key: ssl ? fs.readFileSync(ES_KEY_PATH) : undefined,
cert: ssl ? fs.readFileSync(ES_CERT_PATH) : undefined,
},
diff --git a/packages/kbn-es/src/integration_tests/cluster.test.js b/packages/kbn-es/src/integration_tests/cluster.test.js
index dd570e27e32826..dfbc04477bd409 100644
--- a/packages/kbn-es/src/integration_tests/cluster.test.js
+++ b/packages/kbn-es/src/integration_tests/cluster.test.js
@@ -17,7 +17,7 @@
* under the License.
*/
-const { ToolingLog, CA_CERT_PATH, ES_KEY_PATH, ES_CERT_PATH } = require('@kbn/dev-utils');
+const { ToolingLog, ES_P12_PATH, ES_P12_PASSWORD } = require('@kbn/dev-utils');
const execa = require('execa');
const { Cluster } = require('../cluster');
const { installSource, installSnapshot, installArchive } = require('../install');
@@ -252,9 +252,9 @@ describe('#start(installPath)', () => {
const config = extractConfigFiles.mock.calls[0][0];
expect(config).toContain('xpack.security.http.ssl.enabled=true');
- expect(config).toContain(`xpack.security.http.ssl.key=${ES_KEY_PATH}`);
- expect(config).toContain(`xpack.security.http.ssl.certificate=${ES_CERT_PATH}`);
- expect(config).toContain(`xpack.security.http.ssl.certificate_authorities=${CA_CERT_PATH}`);
+ expect(config).toContain(`xpack.security.http.ssl.keystore.path=${ES_P12_PATH}`);
+ expect(config).toContain(`xpack.security.http.ssl.keystore.type=PKCS12`);
+ expect(config).toContain(`xpack.security.http.ssl.keystore.password=${ES_P12_PASSWORD}`);
});
it(`doesn't setup SSL when disabled`, async () => {
@@ -319,9 +319,9 @@ describe('#run()', () => {
const config = extractConfigFiles.mock.calls[0][0];
expect(config).toContain('xpack.security.http.ssl.enabled=true');
- expect(config).toContain(`xpack.security.http.ssl.key=${ES_KEY_PATH}`);
- expect(config).toContain(`xpack.security.http.ssl.certificate=${ES_CERT_PATH}`);
- expect(config).toContain(`xpack.security.http.ssl.certificate_authorities=${CA_CERT_PATH}`);
+ expect(config).toContain(`xpack.security.http.ssl.keystore.path=${ES_P12_PATH}`);
+ expect(config).toContain(`xpack.security.http.ssl.keystore.type=PKCS12`);
+ expect(config).toContain(`xpack.security.http.ssl.keystore.password=${ES_P12_PASSWORD}`);
});
it(`doesn't setup SSL when disabled`, async () => {
diff --git a/packages/kbn-eslint-import-resolver-kibana/lib/get_webpack_config.js b/packages/kbn-eslint-import-resolver-kibana/lib/get_webpack_config.js
index c51168ae2d91c3..e02c38494991a9 100755
--- a/packages/kbn-eslint-import-resolver-kibana/lib/get_webpack_config.js
+++ b/packages/kbn-eslint-import-resolver-kibana/lib/get_webpack_config.js
@@ -30,8 +30,6 @@ exports.getWebpackConfig = function(kibanaPath, projectRoot, config) {
ui: fromKibana('src/legacy/ui/public'),
test_harness: fromKibana('src/test_harness/public'),
querystring: 'querystring-browser',
- moment$: fromKibana('webpackShims/moment'),
- 'moment-timezone$': fromKibana('webpackShims/moment-timezone'),
// Dev defaults for test bundle https://github.com/elastic/kibana/blob/6998f074542e8c7b32955db159d15661aca253d7/src/core_plugins/tests_bundle/index.js#L73-L78
ng_mock$: fromKibana('src/test_utils/public/ng_mock'),
diff --git a/packages/kbn-pm/dist/index.js b/packages/kbn-pm/dist/index.js
index c3f3f2f477fdd0..a3debf78fb8c86 100644
--- a/packages/kbn-pm/dist/index.js
+++ b/packages/kbn-pm/dist/index.js
@@ -4500,6 +4500,14 @@ var certs_1 = __webpack_require__(422);
exports.CA_CERT_PATH = certs_1.CA_CERT_PATH;
exports.ES_KEY_PATH = certs_1.ES_KEY_PATH;
exports.ES_CERT_PATH = certs_1.ES_CERT_PATH;
+exports.ES_P12_PATH = certs_1.ES_P12_PATH;
+exports.ES_P12_PASSWORD = certs_1.ES_P12_PASSWORD;
+exports.ES_EMPTYPASSWORD_P12_PATH = certs_1.ES_EMPTYPASSWORD_P12_PATH;
+exports.ES_NOPASSWORD_P12_PATH = certs_1.ES_NOPASSWORD_P12_PATH;
+exports.KBN_KEY_PATH = certs_1.KBN_KEY_PATH;
+exports.KBN_CERT_PATH = certs_1.KBN_CERT_PATH;
+exports.KBN_P12_PATH = certs_1.KBN_P12_PATH;
+exports.KBN_P12_PASSWORD = certs_1.KBN_P12_PASSWORD;
var run_1 = __webpack_require__(423);
exports.run = run_1.run;
exports.createFailError = run_1.createFailError;
@@ -36986,6 +36994,14 @@ const path_1 = __webpack_require__(16);
exports.CA_CERT_PATH = path_1.resolve(__dirname, '../certs/ca.crt');
exports.ES_KEY_PATH = path_1.resolve(__dirname, '../certs/elasticsearch.key');
exports.ES_CERT_PATH = path_1.resolve(__dirname, '../certs/elasticsearch.crt');
+exports.ES_P12_PATH = path_1.resolve(__dirname, '../certs/elasticsearch.p12');
+exports.ES_P12_PASSWORD = 'storepass';
+exports.ES_EMPTYPASSWORD_P12_PATH = path_1.resolve(__dirname, '../certs/elasticsearch_emptypassword.p12');
+exports.ES_NOPASSWORD_P12_PATH = path_1.resolve(__dirname, '../certs/elasticsearch_nopassword.p12');
+exports.KBN_KEY_PATH = path_1.resolve(__dirname, '../certs/kibana.key');
+exports.KBN_CERT_PATH = path_1.resolve(__dirname, '../certs/kibana.crt');
+exports.KBN_P12_PATH = path_1.resolve(__dirname, '../certs/kibana.p12');
+exports.KBN_P12_PASSWORD = 'storepass';
/***/ }),
@@ -58252,6 +58268,7 @@ function getProjectPaths({
if (!ossOnly) {
projectPaths.push(Object(path__WEBPACK_IMPORTED_MODULE_0__["resolve"])(rootPath, 'x-pack'));
+ projectPaths.push(Object(path__WEBPACK_IMPORTED_MODULE_0__["resolve"])(rootPath, 'x-pack/plugins/*'));
projectPaths.push(Object(path__WEBPACK_IMPORTED_MODULE_0__["resolve"])(rootPath, 'x-pack/legacy/plugins/*'));
}
diff --git a/packages/kbn-pm/src/config.ts b/packages/kbn-pm/src/config.ts
index 6d5e67dca7d139..6ba8d58a26f88f 100644
--- a/packages/kbn-pm/src/config.ts
+++ b/packages/kbn-pm/src/config.ts
@@ -46,6 +46,7 @@ export function getProjectPaths({ rootPath, ossOnly, skipKibanaPlugins }: Option
if (!ossOnly) {
projectPaths.push(resolve(rootPath, 'x-pack'));
+ projectPaths.push(resolve(rootPath, 'x-pack/plugins/*'));
projectPaths.push(resolve(rootPath, 'x-pack/legacy/plugins/*'));
}
diff --git a/packages/kbn-ui-shared-deps/README.md b/packages/kbn-ui-shared-deps/README.md
new file mode 100644
index 00000000000000..3d3ee37ca5a755
--- /dev/null
+++ b/packages/kbn-ui-shared-deps/README.md
@@ -0,0 +1,3 @@
+# `@kbn/ui-shared-deps`
+
+Shared dependencies that must only have a single instance are installed and re-exported from here. To consume them, import the package and merge the `externals` export into your webpack config so that all references to the supported modules will be remapped to use the global versions.
\ No newline at end of file
diff --git a/packages/kbn-ui-shared-deps/entry.js b/packages/kbn-ui-shared-deps/entry.js
new file mode 100644
index 00000000000000..250abd162f91d7
--- /dev/null
+++ b/packages/kbn-ui-shared-deps/entry.js
@@ -0,0 +1,39 @@
+/*
+ * Licensed to Elasticsearch B.V. under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch B.V. licenses this file to you under
+ * the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+// must load before angular
+export const Jquery = require('jquery');
+window.$ = window.jQuery = Jquery;
+
+export const Angular = require('angular');
+export const ElasticCharts = require('@elastic/charts');
+export const ElasticEui = require('@elastic/eui');
+export const ElasticEuiLibServices = require('@elastic/eui/lib/services');
+export const ElasticEuiLightTheme = require('@elastic/eui/dist/eui_theme_light.json');
+export const ElasticEuiDarkTheme = require('@elastic/eui/dist/eui_theme_dark.json');
+export const Moment = require('moment');
+export const MomentTimezone = require('moment-timezone/moment-timezone');
+export const React = require('react');
+export const ReactDom = require('react-dom');
+export const ReactIntl = require('react-intl');
+export const ReactRouter = require('react-router'); // eslint-disable-line
+export const ReactRouterDom = require('react-router-dom');
+
+// load timezone data into moment-timezone
+Moment.tz.load(require('moment-timezone/data/packed/latest.json'));
diff --git a/packages/kbn-ui-shared-deps/index.d.ts b/packages/kbn-ui-shared-deps/index.d.ts
new file mode 100644
index 00000000000000..132445bbde7451
--- /dev/null
+++ b/packages/kbn-ui-shared-deps/index.d.ts
@@ -0,0 +1,45 @@
+/*
+ * Licensed to Elasticsearch B.V. under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch B.V. licenses this file to you under
+ * the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+/**
+ * Absolute path to the distributable directory
+ */
+export const distDir: string;
+
+/**
+ * Filename of the main bundle file in the distributable directory
+ */
+export const distFilename: string;
+
+/**
+ * Filename of the dark-theme css file in the distributable directory
+ */
+export const darkCssDistFilename: string;
+
+/**
+ * Filename of the light-theme css file in the distributable directory
+ */
+export const lightCssDistFilename: string;
+
+/**
+ * Externals mapping inteded to be used in a webpack config
+ */
+export const externals: {
+ [key: string]: string;
+};
diff --git a/packages/kbn-ui-shared-deps/index.js b/packages/kbn-ui-shared-deps/index.js
new file mode 100644
index 00000000000000..cef25295b35d74
--- /dev/null
+++ b/packages/kbn-ui-shared-deps/index.js
@@ -0,0 +1,41 @@
+/*
+ * Licensed to Elasticsearch B.V. under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch B.V. licenses this file to you under
+ * the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+const Path = require('path');
+
+exports.distDir = Path.resolve(__dirname, 'target');
+exports.distFilename = 'kbn-ui-shared-deps.js';
+exports.lightCssDistFilename = 'kbn-ui-shared-deps.light.css';
+exports.darkCssDistFilename = 'kbn-ui-shared-deps.dark.css';
+exports.externals = {
+ angular: '__kbnSharedDeps__.Angular',
+ '@elastic/charts': '__kbnSharedDeps__.ElasticCharts',
+ '@elastic/eui': '__kbnSharedDeps__.ElasticEui',
+ '@elastic/eui/lib/services': '__kbnSharedDeps__.ElasticEuiLibServices',
+ '@elastic/eui/dist/eui_theme_light.json': '__kbnSharedDeps__.ElasticEuiLightTheme',
+ '@elastic/eui/dist/eui_theme_dark.json': '__kbnSharedDeps__.ElasticEuiDarkTheme',
+ jquery: '__kbnSharedDeps__.Jquery',
+ moment: '__kbnSharedDeps__.Moment',
+ 'moment-timezone': '__kbnSharedDeps__.MomentTimezone',
+ react: '__kbnSharedDeps__.React',
+ 'react-dom': '__kbnSharedDeps__.ReactDom',
+ 'react-intl': '__kbnSharedDeps__.ReactIntl',
+ 'react-router': '__kbnSharedDeps__.ReactRouter',
+ 'react-router-dom': '__kbnSharedDeps__.ReactRouterDom',
+};
diff --git a/packages/kbn-ui-shared-deps/package.json b/packages/kbn-ui-shared-deps/package.json
new file mode 100644
index 00000000000000..014467d204d96c
--- /dev/null
+++ b/packages/kbn-ui-shared-deps/package.json
@@ -0,0 +1,29 @@
+{
+ "name": "@kbn/ui-shared-deps",
+ "version": "1.0.0",
+ "license": "Apache-2.0",
+ "private": true,
+ "scripts": {
+ "build": "node scripts/build",
+ "kbn:bootstrap": "node scripts/build --dev",
+ "kbn:watch": "node scripts/build --watch"
+ },
+ "devDependencies": {
+ "@elastic/eui": "17.3.1",
+ "@elastic/charts": "^16.1.0",
+ "@kbn/dev-utils": "1.0.0",
+ "@yarnpkg/lockfile": "^1.1.0",
+ "angular": "^1.7.9",
+ "css-loader": "^2.1.1",
+ "del": "^5.1.0",
+ "jquery": "^3.4.1",
+ "mini-css-extract-plugin": "0.8.0",
+ "moment": "^2.24.0",
+ "moment-timezone": "^0.5.27",
+ "react-dom": "^16.12.0",
+ "react-intl": "^2.8.0",
+ "react": "^16.12.0",
+ "read-pkg": "^5.2.0",
+ "webpack": "4.41.0"
+ }
+}
\ No newline at end of file
diff --git a/packages/kbn-ui-shared-deps/scripts/build.js b/packages/kbn-ui-shared-deps/scripts/build.js
new file mode 100644
index 00000000000000..8b7c22dac24ff3
--- /dev/null
+++ b/packages/kbn-ui-shared-deps/scripts/build.js
@@ -0,0 +1,105 @@
+/*
+ * Licensed to Elasticsearch B.V. under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch B.V. licenses this file to you under
+ * the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+const Path = require('path');
+
+const { run, createFailError } = require('@kbn/dev-utils');
+const webpack = require('webpack');
+const Stats = require('webpack/lib/Stats');
+const del = require('del');
+
+const { getWebpackConfig } = require('../webpack.config');
+
+run(
+ async ({ log, flags }) => {
+ log.info('cleaning previous build output');
+ await del(Path.resolve(__dirname, '../target'));
+
+ const compiler = webpack(
+ getWebpackConfig({
+ dev: flags.dev,
+ })
+ );
+
+ /** @param {webpack.Stats} stats */
+ const onCompilationComplete = stats => {
+ const took = Math.round((stats.endTime - stats.startTime) / 1000);
+
+ if (!stats.hasErrors() && !stats.hasWarnings()) {
+ log.success(`webpack completed in about ${took} seconds`);
+ return;
+ }
+
+ throw createFailError(
+ `webpack failure in about ${took} seconds\n${stats.toString({
+ colors: true,
+ ...Stats.presetToOptions('minimal'),
+ })}`
+ );
+ };
+
+ if (flags.watch) {
+ compiler.hooks.done.tap('report on stats', stats => {
+ try {
+ onCompilationComplete(stats);
+ } catch (error) {
+ log.error(error.message);
+ }
+ });
+
+ compiler.hooks.watchRun.tap('report on start', () => {
+ process.stdout.cursorTo(0, 0);
+ process.stdout.clearScreenDown();
+ log.info('Running webpack compilation...');
+ });
+
+ compiler.watch({}, error => {
+ if (error) {
+ log.error('Fatal webpack error');
+ log.error(error);
+ process.exit(1);
+ }
+ });
+
+ return;
+ }
+
+ onCompilationComplete(
+ await new Promise((resolve, reject) => {
+ compiler.run((error, stats) => {
+ if (error) {
+ reject(error);
+ } else {
+ resolve(stats);
+ }
+ });
+ })
+ );
+ },
+ {
+ description: 'build @kbn/ui-shared-deps',
+ flags: {
+ boolean: ['watch', 'dev'],
+ help: `
+ --watch Run in watch mode
+ --dev Build development friendly version
+ `,
+ },
+ }
+);
diff --git a/packages/kbn-ui-shared-deps/tsconfig.json b/packages/kbn-ui-shared-deps/tsconfig.json
new file mode 100644
index 00000000000000..c5c3cba147fcfb
--- /dev/null
+++ b/packages/kbn-ui-shared-deps/tsconfig.json
@@ -0,0 +1,6 @@
+{
+ "extends": "../../tsconfig.json",
+ "include": [
+ "index.d.ts"
+ ]
+}
diff --git a/packages/kbn-ui-shared-deps/webpack.config.js b/packages/kbn-ui-shared-deps/webpack.config.js
new file mode 100644
index 00000000000000..87cca2cc897f84
--- /dev/null
+++ b/packages/kbn-ui-shared-deps/webpack.config.js
@@ -0,0 +1,90 @@
+/*
+ * Licensed to Elasticsearch B.V. under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch B.V. licenses this file to you under
+ * the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+const Path = require('path');
+
+const MiniCssExtractPlugin = require('mini-css-extract-plugin');
+const { REPO_ROOT } = require('@kbn/dev-utils');
+const webpack = require('webpack');
+
+const SharedDeps = require('./index');
+
+const MOMENT_SRC = require.resolve('moment/min/moment-with-locales.js');
+
+exports.getWebpackConfig = ({ dev = false } = {}) => ({
+ mode: dev ? 'development' : 'production',
+ entry: {
+ [SharedDeps.distFilename.replace(/\.js$/, '')]: './entry.js',
+ [SharedDeps.darkCssDistFilename.replace(/\.css$/, '')]: [
+ '@elastic/eui/dist/eui_theme_dark.css',
+ '@elastic/charts/dist/theme_only_dark.css',
+ ],
+ [SharedDeps.lightCssDistFilename.replace(/\.css$/, '')]: [
+ '@elastic/eui/dist/eui_theme_light.css',
+ '@elastic/charts/dist/theme_only_light.css',
+ ],
+ },
+ context: __dirname,
+ devtool: dev ? '#cheap-source-map' : false,
+ output: {
+ path: SharedDeps.distDir,
+ filename: '[name].js',
+ sourceMapFilename: '[file].map',
+ publicPath: '__REPLACE_WITH_PUBLIC_PATH__',
+ devtoolModuleFilenameTemplate: info =>
+ `kbn-ui-shared-deps/${Path.relative(REPO_ROOT, info.absoluteResourcePath)}`,
+ library: '__kbnSharedDeps__',
+ },
+
+ module: {
+ noParse: [MOMENT_SRC],
+ rules: [
+ {
+ test: /\.css$/,
+ use: [MiniCssExtractPlugin.loader, 'css-loader'],
+ },
+ ],
+ },
+
+ resolve: {
+ alias: {
+ moment: MOMENT_SRC,
+ },
+ },
+
+ optimization: {
+ noEmitOnErrors: true,
+ },
+
+ performance: {
+ // NOTE: we are disabling this as those hints
+ // are more tailored for the final bundles result
+ // and not for the webpack compilations performance itself
+ hints: false,
+ },
+
+ plugins: [
+ new MiniCssExtractPlugin({
+ filename: '[name].css',
+ }),
+ new webpack.DefinePlugin({
+ 'process.env.NODE_ENV': dev ? '"development"' : '"production"',
+ }),
+ ],
+});
diff --git a/renovate.json5 b/renovate.json5
index a5983283a9e856..560403046b0a51 100644
--- a/renovate.json5
+++ b/renovate.json5
@@ -625,6 +625,14 @@
'@types/node-fetch',
],
},
+ {
+ groupSlug: 'node-forge',
+ groupName: 'node-forge related packages',
+ packageNames: [
+ 'node-forge',
+ '@types/node-forge',
+ ],
+ },
{
groupSlug: 'nodemailer',
groupName: 'nodemailer related packages',
diff --git a/src/cli/serve/serve.js b/src/cli/serve/serve.js
index 6b13d0dc32d3f0..9cf5691b88399e 100644
--- a/src/cli/serve/serve.js
+++ b/src/cli/serve/serve.js
@@ -102,6 +102,8 @@ function applyConfigOverrides(rawConfig, opts, extraCliOptions) {
}
ensureNotDefined('server.ssl.certificate');
ensureNotDefined('server.ssl.key');
+ ensureNotDefined('server.ssl.keystore.path');
+ ensureNotDefined('server.ssl.truststore.path');
ensureNotDefined('elasticsearch.ssl.certificateAuthorities');
const elasticsearchHosts = (
@@ -119,6 +121,8 @@ function applyConfigOverrides(rawConfig, opts, extraCliOptions) {
});
set('server.ssl.enabled', true);
+ // TODO: change this cert/key to KBN_CERT_PATH and KBN_KEY_PATH from '@kbn/dev-utils'; will require some work to avoid breaking
+ // functional tests. Once that is done, the existing test cert/key at DEV_SSL_CERT_PATH and DEV_SSL_KEY_PATH can be deleted.
set('server.ssl.certificate', DEV_SSL_CERT_PATH);
set('server.ssl.key', DEV_SSL_KEY_PATH);
set('elasticsearch.hosts', elasticsearchHosts);
diff --git a/src/core/MIGRATION.md b/src/core/MIGRATION.md
index b70ac610f24a79..173d73ffab664c 100644
--- a/src/core/MIGRATION.md
+++ b/src/core/MIGRATION.md
@@ -55,6 +55,7 @@
- [Provide Legacy Platform API to the New platform plugin](#provide-legacy-platform-api-to-the-new-platform-plugin)
- [On the server side](#on-the-server-side)
- [On the client side](#on-the-client-side)
+ - [Updates an application navlink at runtime](#updates-an-app-navlink-at-runtime)
Make no mistake, it is going to take a lot of work to move certain plugins to the new platform. Our target is to migrate the entire repo over to the new platform throughout 7.x and to remove the legacy plugin system no later than 8.0, and this is only possible if teams start on the effort now.
@@ -1624,3 +1625,31 @@ class MyPlugin {
It's not currently possible to use a similar pattern on the client-side.
Because Legacy platform plugins heavily rely on global angular modules, which aren't available on the new platform.
So you can utilize the same approach for only *stateless Angular components*, as long as they are not consumed by a New Platform application. When New Platform applications are on the page, no legacy code is executed, so the `registerLegacyAPI` function would not be called.
+
+### Updates an application navlink at runtime
+
+The application API now provides a way to updates some of a registered application's properties after registration.
+
+```typescript
+// inside your plugin's setup function
+export class MyPlugin implements Plugin {
+ private appUpdater = new BehaviorSubject(() => ({}));
+ setup({ application }) {
+ application.register({
+ id: 'my-app',
+ title: 'My App',
+ updater$: this.appUpdater,
+ async mount(params) {
+ const { renderApp } = await import('./application');
+ return renderApp(params);
+ },
+ });
+ }
+ start() {
+ // later, when the navlink needs to be updated
+ appUpdater.next(() => {
+ navLinkStatus: AppNavLinkStatus.disabled,
+ tooltip: 'Application disabled',
+ })
+ }
+```
\ No newline at end of file
diff --git a/src/core/README.md b/src/core/README.md
index 8863658e0040c3..f4539191d448bd 100644
--- a/src/core/README.md
+++ b/src/core/README.md
@@ -7,6 +7,7 @@ Core Plugin API Documentation:
- [Core Public API](/docs/development/core/public/kibana-plugin-public.md)
- [Core Server API](/docs/development/core/server/kibana-plugin-server.md)
- [Conventions for Plugins](./CONVENTIONS.md)
+ - [Testing Kibana Plugins](./TESTING.md)
- [Migration guide for porting existing plugins](./MIGRATION.md)
Internal Documentation:
diff --git a/src/core/TESTING.md b/src/core/TESTING.md
new file mode 100644
index 00000000000000..6139820d02a14a
--- /dev/null
+++ b/src/core/TESTING.md
@@ -0,0 +1,254 @@
+# Testing Kibana Plugins
+
+This document outlines best practices and patterns for testing Kibana Plugins.
+
+- [Strategy](#strategy)
+- [Core Integrations](#core-integrations)
+ - [Core Mocks](#core-mocks)
+ - [Strategies for specific Core APIs](#strategies-for-specific-core-apis)
+ - [HTTP Routes](#http-routes)
+ - [SavedObjects](#savedobjects)
+ - [Elasticsearch](#elasticsearch)
+- [Plugin Integrations](#plugin-integrations)
+- [Plugin Contracts](#plugin-contracts)
+
+## Strategy
+
+In general, we recommend three tiers of tests:
+- Unit tests: small, fast, exhaustive, make heavy use of mocks for external dependencies
+- Integration tests: higher-level tests that verify interactions between systems (eg. HTTP APIs, Elasticsearch API calls, calling other plugin contracts).
+- End-to-end tests (e2e): tests that verify user-facing behavior through the browser
+
+These tiers should roughly follow the traditional ["testing pyramid"](https://martinfowler.com/articles/practical-test-pyramid.html), where there are more exhaustive testing at the unit level, fewer at the integration level, and very few at the functional level.
+
+## New concerns in the Kibana Platform
+
+The Kibana Platform introduces new concepts that legacy plugins did not have concern themselves with. Namely:
+- **Lifecycles**: plugins now have explicit lifecycle methods that must interop with Core APIs and other plugins.
+- **Shared runtime**: plugins now all run in the same process at the same time. On the frontend, this is different behavior than the legacy plugins. Developers should take care not to break other plugins when interacting with their enviornment (Node.js or Browser).
+- **Single page application**: Kibana's frontend is now a single-page application where all plugins are running, but only one application is mounted at a time. Plugins need to handle mounting and unmounting, cleanup, and avoid overriding global browser behaviors in this shared space.
+- **Dependency management**: plugins must now explicitly declare their dependencies on other plugins, both required and optional. Plugins should ensure to test conditions where a optional dependency is missing.
+
+Simply porting over existing tests when migrating your plugin to the Kibana Platform will leave blind spots in test coverage. It is highly recommended that plugins add new tests that cover these new concerns.
+
+## Core Integrations
+
+### Core Mocks
+
+When testing a plugin's integration points with Core APIs, it is heavily recommended to utilize the mocks provided in `src/core/server/mocks` and `src/core/public/mocks`. The majority of these mocks are dumb `jest` mocks that mimic the interface of their respective Core APIs, however they do not return realistic return values.
+
+If the unit under test expects a particular response from a Core API, the test will need to set this return value explicitly. The return values are type checked to match the Core API where possible to ensure that mocks are updated when Core APIs changed.
+
+#### Example
+
+```ts
+import { elasticsearchServiceMock } from 'src/core/server/mocks';
+
+test('my test', async () => {
+ // Setup mock and faked response
+ const esClient = elasticsearchServiceMock.createScopedClusterClient();
+ esClient.callAsCurrentUser.mockResolvedValue(/** insert ES response here */);
+
+ // Call unit under test with mocked client
+ const result = await myFunction(esClient);
+
+ // Assert that client was called with expected arguments
+ expect(esClient.callAsCurrentUser).toHaveBeenCalledWith(/** expected args */);
+ // Expect that unit under test returns expected value based on client's response
+ expect(result).toEqual(/** expected return value */)
+});
+```
+
+### Strategies for specific Core APIs
+
+#### HTTP Routes
+
+_How to test route handlers_
+
+### Applications
+
+Kibana Platform applications have less control over the page than legacy applications did. It is important that your app is built to handle it's co-habitance with other plugins in the browser. Applications are mounted and unmounted from the DOM as the user navigates between them, without full-page refreshes, as a single-page application (SPA).
+
+These long-lived sessions make cleanup more important than before. It's entirely possible a user has a single browsing session open for weeks at a time, without ever doing a full-page refresh. Common things that need to be cleaned up (and tested!) when your application is unmounted:
+- Subscriptions and polling (eg. `uiSettings.get$()`)
+- Any Core API calls that set state (eg. `core.chrome.setIsVisible`).
+- Open connections (eg. a Websocket)
+
+While applications do get an opportunity to unmount and run cleanup logic, it is also important that you do not _depend_ on this logic to run. The browser tab may get closed without running cleanup logic, so it is not guaranteed to be run. For instance, you should not depend on unmounting logic to run in order to save state to `localStorage` or to the backend.
+
+#### Example
+
+By following the [renderApp](./CONVENTIONS.md#applications) convention, you can greatly reduce the amount of logic in your application's mount function. This makes testing your application's actual rendering logic easier.
+
+```tsx
+/** public/plugin.ts */
+class Plugin {
+ setup(core) {
+ core.application.register({
+ // id, title, etc.
+ async mount(params) {
+ const [{ renderApp }, [coreStart, startDeps]] = await Promise.all([
+ import('./application'),
+ core.getStartServices()
+ ]);
+
+ return renderApp(params, coreStart, startDeps);
+ }
+ })
+ }
+}
+```
+
+We _could_ still write tests for this logic, but you may find that you're just asserting the same things that would be covered by type-checks.
+
+
+See example
+
+```ts
+/** public/plugin.test.ts */
+jest.mock('./application', () => ({ renderApp: jest.fn() }));
+import { coreMock } from 'src/core/public/mocks';
+import { renderApp: renderAppMock } from './application';
+import { Plugin } from './plugin';
+
+describe('Plugin', () => {
+ it('registers an app', () => {
+ const coreSetup = coreMock.createSetup();
+ new Plugin(coreMock.createPluginInitializerContext()).setup(coreSetup);
+ expect(coreSetup.application.register).toHaveBeenCalledWith({
+ id: 'myApp',
+ mount: expect.any(Function)
+ });
+ });
+
+ // Test the glue code from Plugin -> renderApp
+ it('application.mount wires up dependencies to renderApp', async () => {
+ const coreSetup = coreMock.createSetup();
+ const [coreStartMock, startDepsMock] = await coreSetup.getStartServices();
+ const unmountMock = jest.fn();
+ renderAppMock.mockReturnValue(unmountMock);
+ const params = { element: document.createElement('div'), appBasePath: '/fake/base/path' };
+
+ new Plugin(coreMock.createPluginInitializerContext()).setup(coreSetup);
+ // Grab registered mount function
+ const mount = coreSetup.application.register.mock.calls[0][0].mount;
+
+ const unmount = await mount(params);
+ expect(renderAppMock).toHaveBeenCalledWith(params, coreStartMock, startDepsMock);
+ expect(unmount).toBe(unmountMock);
+ });
+});
+```
+
+
+
+The more interesting logic is in `renderApp`:
+
+```ts
+/** public/application.ts */
+import React from 'react';
+import ReactDOM from 'react-dom';
+
+import { AppMountParams, CoreStart } from 'src/core/public';
+import { AppRoot } from './components/app_root';
+
+export const renderApp = ({ element, appBasePath }: AppMountParams, core: CoreStart, plugins: MyPluginDepsStart) => {
+ // Hide the chrome while this app is mounted for a full screen experience
+ core.chrome.setIsVisible(false);
+
+ // uiSettings subscription
+ const uiSettingsClient = core.uiSettings.client;
+ const pollingSubscription = uiSettingClient.get$('mysetting1').subscribe(async mySetting1 => {
+ const value = core.http.fetch(/** use `mySetting1` in request **/);
+ // ...
+ });
+
+ // Render app
+ ReactDOM.render(
+ ,
+ element
+ );
+
+ return () => {
+ // Unmount UI
+ ReactDOM.unmountComponentAtNode(element);
+ // Close any subscriptions
+ pollingSubscription.unsubscribe();
+ // Make chrome visible again
+ core.chrome.setIsVisible(true);
+ };
+};
+```
+
+In testing `renderApp` you should be verifying that:
+1) Your application mounts and unmounts correctly
+2) Cleanup logic is completed as expected
+
+```ts
+/** public/application.test.ts */
+import { coreMock } from 'src/core/public/mocks';
+import { renderApp } from './application';
+
+describe('renderApp', () => {
+ it('mounts and unmounts UI', () => {
+ const params = { element: document.createElement('div'), appBasePath: '/fake/base/path' };
+ const core = coreMock.createStart();
+
+ // Verify some expected DOM element is rendered into the element
+ const unmount = renderApp(params, core, {});
+ expect(params.element.querySelector('.some-app-class')).not.toBeUndefined();
+ // Verify the element is empty after unmounting
+ unmount();
+ expect(params.element.innerHTML).toEqual('');
+ });
+
+ it('unsubscribes from uiSettings', () => {
+ const params = { element: document.createElement('div'), appBasePath: '/fake/base/path' };
+ const core = coreMock.createStart();
+ // Create a fake Subject you can use to monitor observers
+ const settings$ = new Subject();
+ core.uiSettings.get$.mockReturnValue(settings$);
+
+ // Verify mounting adds an observer
+ const unmount = renderApp(params, core, {});
+ expect(settings$.observers.length).toBe(1);
+ // Verify no observers remaining after unmount is called
+ unmount();
+ expect(settings$.observers.length).toBe(0);
+ });
+
+ it('resets chrome visibility', () => {
+ const params = { element: document.createElement('div'), appBasePath: '/fake/base/path' };
+ const core = coreMock.createStart();
+
+ // Verify stateful Core API was called on mount
+ const unmount = renderApp(params, core, {});
+ expect(core.chrome.setIsVisible).toHaveBeenCalledWith(false);
+ core.chrome.setIsVisible.mockClear(); // reset mock
+ // Verify stateful Core API was called on unmount
+ unmount();
+ expect(core.chrome.setIsVisible).toHaveBeenCalledWith(true);
+ })
+});
+```
+
+#### SavedObjects
+
+_How to test SO operations_
+
+#### Elasticsearch
+
+_How to test ES clients_
+
+## Plugin Integrations
+
+_How to test against specific plugin APIs (eg. data plugin)_
+
+## Plugin Contracts
+
+_How to test your plugin's exposed API_
+
+Guidelines:
+- Plugins should never interact with other plugins' REST API directly
+- Plugins should interact with other plugins via JavaScript contracts
+- Exposed contracts need to be well tested to ensure breaking changes are detected easily
diff --git a/src/core/public/application/application_leave.test.ts b/src/core/public/application/application_leave.test.ts
new file mode 100644
index 00000000000000..e06183d8bb8d96
--- /dev/null
+++ b/src/core/public/application/application_leave.test.ts
@@ -0,0 +1,49 @@
+/*
+ * Licensed to Elasticsearch B.V. under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch B.V. licenses this file to you under
+ * the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import { isConfirmAction, getLeaveAction } from './application_leave';
+import { AppLeaveActionType } from './types';
+
+describe('isConfirmAction', () => {
+ it('returns true if action is confirm', () => {
+ expect(isConfirmAction({ type: AppLeaveActionType.confirm, text: 'message' })).toEqual(true);
+ });
+ it('returns false if action is default', () => {
+ expect(isConfirmAction({ type: AppLeaveActionType.default })).toEqual(false);
+ });
+});
+
+describe('getLeaveAction', () => {
+ it('returns the default action provided by the handler', () => {
+ expect(getLeaveAction(actions => actions.default())).toEqual({
+ type: AppLeaveActionType.default,
+ });
+ });
+ it('returns the confirm action provided by the handler', () => {
+ expect(getLeaveAction(actions => actions.confirm('some message'))).toEqual({
+ type: AppLeaveActionType.confirm,
+ text: 'some message',
+ });
+ expect(getLeaveAction(actions => actions.confirm('another message', 'a title'))).toEqual({
+ type: AppLeaveActionType.confirm,
+ text: 'another message',
+ title: 'a title',
+ });
+ });
+});
diff --git a/src/core/public/application/application_leave.tsx b/src/core/public/application/application_leave.tsx
new file mode 100644
index 00000000000000..7b69d70d3f6f6e
--- /dev/null
+++ b/src/core/public/application/application_leave.tsx
@@ -0,0 +1,46 @@
+/*
+ * Licensed to Elasticsearch B.V. under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch B.V. licenses this file to you under
+ * the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import {
+ AppLeaveActionFactory,
+ AppLeaveActionType,
+ AppLeaveAction,
+ AppLeaveConfirmAction,
+ AppLeaveHandler,
+} from './types';
+
+const appLeaveActionFactory: AppLeaveActionFactory = {
+ confirm(text: string, title?: string) {
+ return { type: AppLeaveActionType.confirm, text, title };
+ },
+ default() {
+ return { type: AppLeaveActionType.default };
+ },
+};
+
+export function isConfirmAction(action: AppLeaveAction): action is AppLeaveConfirmAction {
+ return action.type === AppLeaveActionType.confirm;
+}
+
+export function getLeaveAction(handler?: AppLeaveHandler): AppLeaveAction {
+ if (!handler) {
+ return appLeaveActionFactory.default();
+ }
+ return handler(appLeaveActionFactory);
+}
diff --git a/src/core/public/application/application_service.mock.ts b/src/core/public/application/application_service.mock.ts
index b2e2161c92cc8e..dee47315fc3222 100644
--- a/src/core/public/application/application_service.mock.ts
+++ b/src/core/public/application/application_service.mock.ts
@@ -17,7 +17,7 @@
* under the License.
*/
-import { Subject } from 'rxjs';
+import { BehaviorSubject, Subject } from 'rxjs';
import { capabilitiesServiceMock } from './capabilities/capabilities_service.mock';
import {
@@ -25,17 +25,21 @@ import {
InternalApplicationStart,
ApplicationStart,
InternalApplicationSetup,
+ App,
+ LegacyApp,
} from './types';
import { ApplicationServiceContract } from './test_types';
const createSetupContractMock = (): jest.Mocked => ({
register: jest.fn(),
+ registerAppUpdater: jest.fn(),
registerMountContext: jest.fn(),
});
const createInternalSetupContractMock = (): jest.Mocked => ({
register: jest.fn(),
registerLegacyApp: jest.fn(),
+ registerAppUpdater: jest.fn(),
registerMountContext: jest.fn(),
});
@@ -50,8 +54,7 @@ const createInternalStartContractMock = (): jest.Mocked();
return {
- availableApps: new Map(),
- availableLegacyApps: new Map(),
+ applications$: new BehaviorSubject