diff --git a/config/kibana.yml b/config/kibana.yml
index eefb6bb8bacda..dea9849f17b28 100644
--- a/config/kibana.yml
+++ b/config/kibana.yml
@@ -42,6 +42,10 @@
#elasticsearch.username: "kibana_system"
#elasticsearch.password: "pass"
+# Kibana can also authenticate to Elasticsearch via "service account tokens".
+# If may use this token instead of a username/password.
+# elasticsearch.serviceAccountToken: "my_token"
+
# Enables SSL and paths to the PEM-format SSL certificate and SSL key files, respectively.
# These settings enable SSL for outgoing requests from the Kibana server to the browser.
#server.ssl.enabled: false
diff --git a/docs/development/core/server/kibana-plugin-core-server.elasticsearchclientconfig.md b/docs/development/core/server/kibana-plugin-core-server.elasticsearchclientconfig.md
index a854e5ddad19a..208e0e0175d71 100644
--- a/docs/development/core/server/kibana-plugin-core-server.elasticsearchclientconfig.md
+++ b/docs/development/core/server/kibana-plugin-core-server.elasticsearchclientconfig.md
@@ -9,7 +9,7 @@ Configuration options to be used to create a [cluster client](./kibana-plugin-co
Signature:
```typescript
-export declare type ElasticsearchClientConfig = Pick & {
+export declare type ElasticsearchClientConfig = Pick & {
pingTimeout?: ElasticsearchConfig['pingTimeout'] | ClientOptions['pingTimeout'];
requestTimeout?: ElasticsearchConfig['requestTimeout'] | ClientOptions['requestTimeout'];
ssl?: Partial;
diff --git a/docs/development/core/server/kibana-plugin-core-server.elasticsearchconfig.md b/docs/development/core/server/kibana-plugin-core-server.elasticsearchconfig.md
index d87ea63d59b8d..a9ed614ba7552 100644
--- a/docs/development/core/server/kibana-plugin-core-server.elasticsearchconfig.md
+++ b/docs/development/core/server/kibana-plugin-core-server.elasticsearchconfig.md
@@ -31,10 +31,11 @@ export declare class ElasticsearchConfig
| [pingTimeout](./kibana-plugin-core-server.elasticsearchconfig.pingtimeout.md) | | Duration
| Timeout after which PING HTTP request will be aborted and retried. |
| [requestHeadersWhitelist](./kibana-plugin-core-server.elasticsearchconfig.requestheaderswhitelist.md) | | string[]
| List of Kibana client-side headers to send to Elasticsearch when request scoped cluster client is used. If this is an empty array then \*no\* client-side will be sent. |
| [requestTimeout](./kibana-plugin-core-server.elasticsearchconfig.requesttimeout.md) | | Duration
| Timeout after which HTTP request will be aborted and retried. |
+| [serviceAccountToken](./kibana-plugin-core-server.elasticsearchconfig.serviceaccounttoken.md) | | string
| If Elasticsearch security features are enabled, this setting provides the service account token that the Kibana server users to perform its administrative functions.This is an alternative to specifying a username and password. |
| [shardTimeout](./kibana-plugin-core-server.elasticsearchconfig.shardtimeout.md) | | Duration
| Timeout for Elasticsearch to wait for responses from shards. Set to 0 to disable. |
| [sniffInterval](./kibana-plugin-core-server.elasticsearchconfig.sniffinterval.md) | | false | Duration
| Interval to perform a sniff operation and make sure the list of nodes is complete. If false
then sniffing is disabled. |
| [sniffOnConnectionFault](./kibana-plugin-core-server.elasticsearchconfig.sniffonconnectionfault.md) | | boolean
| Specifies whether the client should immediately sniff for a more current list of nodes when a connection dies. |
| [sniffOnStart](./kibana-plugin-core-server.elasticsearchconfig.sniffonstart.md) | | boolean
| Specifies whether the client should attempt to detect the rest of the cluster when it is first instantiated. |
| [ssl](./kibana-plugin-core-server.elasticsearchconfig.ssl.md) | | Pick<SslConfigSchema, Exclude<keyof SslConfigSchema, 'certificateAuthorities' | 'keystore' | 'truststore'>> & {
certificateAuthorities?: string[];
}
| Set of settings configure SSL connection between Kibana and Elasticsearch that are required when xpack.ssl.verification_mode
in Elasticsearch is set to either certificate
or full
. |
-| [username](./kibana-plugin-core-server.elasticsearchconfig.username.md) | | string
| If Elasticsearch is protected with basic authentication, this setting provides the username that the Kibana server uses to perform its administrative functions. |
+| [username](./kibana-plugin-core-server.elasticsearchconfig.username.md) | | string
| If Elasticsearch is protected with basic authentication, this setting provides the username that the Kibana server uses to perform its administrative functions. Cannot be used in conjunction with serviceAccountToken. |
diff --git a/docs/development/core/server/kibana-plugin-core-server.elasticsearchconfig.serviceaccounttoken.md b/docs/development/core/server/kibana-plugin-core-server.elasticsearchconfig.serviceaccounttoken.md
new file mode 100644
index 0000000000000..5934e83de17a4
--- /dev/null
+++ b/docs/development/core/server/kibana-plugin-core-server.elasticsearchconfig.serviceaccounttoken.md
@@ -0,0 +1,15 @@
+
+
+[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [ElasticsearchConfig](./kibana-plugin-core-server.elasticsearchconfig.md) > [serviceAccountToken](./kibana-plugin-core-server.elasticsearchconfig.serviceaccounttoken.md)
+
+## ElasticsearchConfig.serviceAccountToken property
+
+If Elasticsearch security features are enabled, this setting provides the service account token that the Kibana server users to perform its administrative functions.
+
+This is an alternative to specifying a username and password.
+
+Signature:
+
+```typescript
+readonly serviceAccountToken?: string;
+```
diff --git a/docs/development/core/server/kibana-plugin-core-server.elasticsearchconfig.username.md b/docs/development/core/server/kibana-plugin-core-server.elasticsearchconfig.username.md
index 14db9f2e36ccf..959870ff43a0f 100644
--- a/docs/development/core/server/kibana-plugin-core-server.elasticsearchconfig.username.md
+++ b/docs/development/core/server/kibana-plugin-core-server.elasticsearchconfig.username.md
@@ -4,7 +4,7 @@
## ElasticsearchConfig.username property
-If Elasticsearch is protected with basic authentication, this setting provides the username that the Kibana server uses to perform its administrative functions.
+If Elasticsearch is protected with basic authentication, this setting provides the username that the Kibana server uses to perform its administrative functions. Cannot be used in conjunction with serviceAccountToken.
Signature:
diff --git a/docs/development/core/server/kibana-plugin-core-server.legacyelasticsearchclientconfig.md b/docs/development/core/server/kibana-plugin-core-server.legacyelasticsearchclientconfig.md
index b028a09bee453..a80ebe2fee493 100644
--- a/docs/development/core/server/kibana-plugin-core-server.legacyelasticsearchclientconfig.md
+++ b/docs/development/core/server/kibana-plugin-core-server.legacyelasticsearchclientconfig.md
@@ -11,7 +11,7 @@
Signature:
```typescript
-export declare type LegacyElasticsearchClientConfig = Pick & Pick & {
+export declare type LegacyElasticsearchClientConfig = Pick & Pick & {
pingTimeout?: ElasticsearchConfig['pingTimeout'] | ConfigOptions['pingTimeout'];
requestTimeout?: ElasticsearchConfig['requestTimeout'] | ConfigOptions['requestTimeout'];
sniffInterval?: ElasticsearchConfig['sniffInterval'] | ConfigOptions['sniffInterval'];
diff --git a/docs/setup/settings.asciidoc b/docs/setup/settings.asciidoc
index ba333deeb1609..15abd0fa4ad96 100644
--- a/docs/setup/settings.asciidoc
+++ b/docs/setup/settings.asciidoc
@@ -284,6 +284,11 @@ the username and password that the {kib} server uses to perform maintenance
on the {kib} index at startup. {kib} users still need to authenticate with
{es}, which is proxied through the {kib} server.
+|[[elasticsearch-service-account-token]] `elasticsearch.serviceAccountToken:`
+ | beta[]. If your {es} is protected with basic authentication, this token provides the credentials
+that the {kib} server uses to perform maintenance on the {kib} index at startup. This setting
+is an alternative to `elasticsearch.username` and `elasticsearch.password`.
+
| `enterpriseSearch.host`
| The URL of your Enterprise Search instance
diff --git a/src/cli/serve/serve.js b/src/cli/serve/serve.js
index ad83965efde33..be949350f7229 100644
--- a/src/cli/serve/serve.js
+++ b/src/cli/serve/serve.js
@@ -68,12 +68,14 @@ function applyConfigOverrides(rawConfig, opts, extraCliOptions) {
delete extraCliOptions.env;
if (opts.dev) {
- if (!has('elasticsearch.username')) {
- set('elasticsearch.username', 'kibana_system');
- }
+ if (!has('elasticsearch.serviceAccountToken')) {
+ if (!has('elasticsearch.username')) {
+ set('elasticsearch.username', 'kibana_system');
+ }
- if (!has('elasticsearch.password')) {
- set('elasticsearch.password', 'changeme');
+ if (!has('elasticsearch.password')) {
+ set('elasticsearch.password', 'changeme');
+ }
}
if (opts.ssl) {
diff --git a/src/core/server/elasticsearch/client/client_config.test.ts b/src/core/server/elasticsearch/client/client_config.test.ts
index faca79b3aa6fa..7e16339b40235 100644
--- a/src/core/server/elasticsearch/client/client_config.test.ts
+++ b/src/core/server/elasticsearch/client/client_config.test.ts
@@ -204,11 +204,27 @@ describe('parseClientOptions', () => {
);
});
+ it('adds an authorization header if `serviceAccountToken` is set', () => {
+ expect(
+ parseClientOptions(
+ createConfig({
+ serviceAccountToken: 'ABC123',
+ }),
+ false
+ )
+ ).toEqual(
+ expect.objectContaining({
+ headers: expect.objectContaining({
+ authorization: `Bearer ABC123`,
+ }),
+ })
+ );
+ });
+
it('does not add auth to the nodes', () => {
const options = parseClientOptions(
createConfig({
- username: 'user',
- password: 'pass',
+ serviceAccountToken: 'ABC123',
hosts: ['http://node-A:9200'],
}),
true
@@ -252,6 +268,34 @@ describe('parseClientOptions', () => {
]
`);
});
+
+ it('does not add the authorization header even if `serviceAccountToken` is set', () => {
+ expect(
+ parseClientOptions(
+ createConfig({
+ serviceAccountToken: 'ABC123',
+ }),
+ true
+ ).headers
+ ).not.toHaveProperty('authorization');
+ });
+
+ it('does not add auth to the nodes even if `serviceAccountToken` is set', () => {
+ const options = parseClientOptions(
+ createConfig({
+ serviceAccountToken: 'ABC123',
+ hosts: ['http://node-A:9200'],
+ }),
+ true
+ );
+ expect(options.nodes).toMatchInlineSnapshot(`
+ Array [
+ Object {
+ "url": "http://node-a:9200/",
+ },
+ ]
+ `);
+ });
});
});
diff --git a/src/core/server/elasticsearch/client/client_config.ts b/src/core/server/elasticsearch/client/client_config.ts
index 3044b277db902..bbbb1ac247b3b 100644
--- a/src/core/server/elasticsearch/client/client_config.ts
+++ b/src/core/server/elasticsearch/client/client_config.ts
@@ -29,6 +29,7 @@ export type ElasticsearchClientConfig = Pick<
| 'hosts'
| 'username'
| 'password'
+ | 'serviceAccountToken'
> & {
pingTimeout?: ElasticsearchConfig['pingTimeout'] | ClientOptions['pingTimeout'];
requestTimeout?: ElasticsearchConfig['requestTimeout'] | ClientOptions['requestTimeout'];
@@ -74,11 +75,16 @@ export function parseClientOptions(
};
}
- if (config.username && config.password && !scoped) {
- clientOptions.auth = {
- username: config.username,
- password: config.password,
- };
+ if (!scoped) {
+ if (config.username && config.password) {
+ clientOptions.auth = {
+ username: config.username,
+ password: config.password,
+ };
+ } else if (config.serviceAccountToken) {
+ // TODO: change once ES client has native support for service account tokens: https://github.com/elastic/elasticsearch-js/issues/1477
+ clientOptions.headers!.authorization = `Bearer ${config.serviceAccountToken}`;
+ }
}
clientOptions.nodes = config.hosts.map((host) => convertHost(host));
diff --git a/src/core/server/elasticsearch/elasticsearch_config.test.ts b/src/core/server/elasticsearch/elasticsearch_config.test.ts
index f8ef1a7a20a83..6e05baac88e34 100644
--- a/src/core/server/elasticsearch/elasticsearch_config.test.ts
+++ b/src/core/server/elasticsearch/elasticsearch_config.test.ts
@@ -41,6 +41,7 @@ test('set correct defaults', () => {
"authorization",
],
"requestTimeout": "PT30S",
+ "serviceAccountToken": undefined,
"shardTimeout": "PT30S",
"sniffInterval": false,
"sniffOnConnectionFault": false,
@@ -377,3 +378,22 @@ test('#username throws if equal to "elastic", only while running from source', (
);
expect(() => config.schema.validate(obj, { dist: true })).not.toThrow();
});
+
+test('serviceAccountToken throws if username is also set', () => {
+ const obj = {
+ username: 'elastic',
+ serviceAccountToken: 'abc123',
+ };
+
+ expect(() => config.schema.validate(obj)).toThrowErrorMatchingInlineSnapshot(
+ `"[serviceAccountToken]: serviceAccountToken cannot be specified when \\"username\\" is also set."`
+ );
+});
+
+test('serviceAccountToken does not throw if username is not set', () => {
+ const obj = {
+ serviceAccountToken: 'abc123',
+ };
+
+ expect(() => config.schema.validate(obj)).not.toThrow();
+});
diff --git a/src/core/server/elasticsearch/elasticsearch_config.ts b/src/core/server/elasticsearch/elasticsearch_config.ts
index b2b25cda3ac2a..e756d9da867b3 100644
--- a/src/core/server/elasticsearch/elasticsearch_config.ts
+++ b/src/core/server/elasticsearch/elasticsearch_config.ts
@@ -53,6 +53,18 @@ export const configSchema = schema.object({
)
),
password: schema.maybe(schema.string()),
+ serviceAccountToken: schema.maybe(
+ schema.conditional(
+ schema.siblingRef('username'),
+ schema.never(),
+ schema.string(),
+ schema.string({
+ validate: () => {
+ return `serviceAccountToken cannot be specified when "username" is also set.`;
+ },
+ })
+ )
+ ),
requestHeadersWhitelist: schema.oneOf(
[
schema.string({
@@ -272,6 +284,7 @@ export class ElasticsearchConfig {
/**
* If Elasticsearch is protected with basic authentication, this setting provides
* the username that the Kibana server uses to perform its administrative functions.
+ * Cannot be used in conjunction with serviceAccountToken.
*/
public readonly username?: string;
@@ -281,6 +294,14 @@ export class ElasticsearchConfig {
*/
public readonly password?: string;
+ /**
+ * If Elasticsearch security features are enabled, this setting provides the service account
+ * token that the Kibana server users to perform its administrative functions.
+ *
+ * This is an alternative to specifying a username and password.
+ */
+ public readonly serviceAccountToken?: string;
+
/**
* Set of settings configure SSL connection between Kibana and Elasticsearch that
* are required when `xpack.ssl.verification_mode` in Elasticsearch is set to
@@ -314,6 +335,7 @@ export class ElasticsearchConfig {
this.healthCheckDelay = rawConfig.healthCheck.delay;
this.username = rawConfig.username;
this.password = rawConfig.password;
+ this.serviceAccountToken = rawConfig.serviceAccountToken;
this.customHeaders = rawConfig.customHeaders;
const { alwaysPresentCertificate, verificationMode } = rawConfig.ssl;
diff --git a/src/core/server/elasticsearch/legacy/cluster_client.test.ts b/src/core/server/elasticsearch/legacy/cluster_client.test.ts
index 2ce19570677c5..52bc4bd45660e 100644
--- a/src/core/server/elasticsearch/legacy/cluster_client.test.ts
+++ b/src/core/server/elasticsearch/legacy/cluster_client.test.ts
@@ -101,6 +101,30 @@ describe('#callAsInternalUser', () => {
expect(mockEsClientInstance.ping).toHaveBeenLastCalledWith(mockParams);
});
+ test('sets the authorization header when a service account token is configured', async () => {
+ clusterClient = new LegacyClusterClient(
+ { apiVersion: 'es-version', serviceAccountToken: 'ABC123' } as any,
+ logger.get(),
+ 'custom-type'
+ );
+
+ const mockResponse = { data: 'ping' };
+ const mockParams = { param: 'ping' };
+ mockEsClientInstance.ping.mockImplementation(function mockCall(this: any) {
+ return Promise.resolve({
+ context: this,
+ response: mockResponse,
+ });
+ });
+
+ await clusterClient.callAsInternalUser('ping', mockParams);
+
+ expect(mockEsClientInstance.ping).toHaveBeenCalledWith({
+ headers: { authorization: 'Bearer ABC123' },
+ param: 'ping',
+ });
+ });
+
test('correctly deals with nested endpoint', async () => {
const mockResponse = { data: 'authenticate' };
const mockParams = { param: 'authenticate' };
@@ -355,6 +379,31 @@ describe('#asScoped', () => {
);
});
+ test('does not set the authorization header when a service account token is configured', async () => {
+ clusterClient = new LegacyClusterClient(
+ {
+ apiVersion: 'es-version',
+ requestHeadersWhitelist: ['zero'],
+ serviceAccountToken: 'ABC123',
+ } as any,
+ logger.get(),
+ 'custom-type'
+ );
+
+ clusterClient.asScoped(
+ httpServerMock.createRawRequest({ headers: { zero: '0', one: '1', two: '2', three: '3' } })
+ );
+
+ const expectedHeaders = { zero: '0' };
+
+ expect(MockScopedClusterClient).toHaveBeenCalledTimes(1);
+ expect(MockScopedClusterClient).toHaveBeenCalledWith(
+ expect.any(Function),
+ expect.any(Function),
+ expectedHeaders
+ );
+ });
+
test('both scoped and internal API caller fail if cluster client is closed', async () => {
clusterClient.asScoped(
httpServerMock.createRawRequest({ headers: { zero: '0', one: '1', two: '2', three: '3' } })
diff --git a/src/core/server/elasticsearch/legacy/cluster_client.ts b/src/core/server/elasticsearch/legacy/cluster_client.ts
index bdb2ca4d01b3c..6a6765b67da9f 100644
--- a/src/core/server/elasticsearch/legacy/cluster_client.ts
+++ b/src/core/server/elasticsearch/legacy/cluster_client.ts
@@ -147,6 +147,13 @@ export class LegacyClusterClient implements ILegacyClusterClient {
) => {
this.assertIsNotClosed();
+ if (this.config.serviceAccountToken) {
+ clientParams.headers = {
+ ...clientParams.headers,
+ authorization: `Bearer ${this.config.serviceAccountToken}`,
+ };
+ }
+
return await (callAPI.bind(null, this.client) as LegacyAPICaller)(
endpoint,
clientParams,
diff --git a/src/core/server/elasticsearch/legacy/elasticsearch_client_config.test.ts b/src/core/server/elasticsearch/legacy/elasticsearch_client_config.test.ts
index 6239ad270d5b5..a343c0d5d2ad1 100644
--- a/src/core/server/elasticsearch/legacy/elasticsearch_client_config.test.ts
+++ b/src/core/server/elasticsearch/legacy/elasticsearch_client_config.test.ts
@@ -333,6 +333,128 @@ describe('#auth', () => {
});
});
+describe('#serviceAccountToken', () => {
+ it('is set when #auth is true, and a token is provided', () => {
+ expect(
+ parseElasticsearchClientConfig(
+ {
+ apiVersion: 'v7.0.0',
+ customHeaders: { xsrf: 'something' },
+ sniffOnStart: true,
+ sniffOnConnectionFault: true,
+ hosts: ['https://es.local'],
+ requestHeadersWhitelist: [],
+ serviceAccountToken: 'ABC123',
+ },
+ logger.get(),
+ 'custom-type',
+ { auth: true }
+ )
+ ).toMatchInlineSnapshot(`
+ Object {
+ "apiVersion": "v7.0.0",
+ "hosts": Array [
+ Object {
+ "headers": Object {
+ "x-elastic-product-origin": "kibana",
+ "xsrf": "something",
+ },
+ "host": "es.local",
+ "path": "/",
+ "port": "443",
+ "protocol": "https:",
+ "query": null,
+ },
+ ],
+ "keepAlive": true,
+ "log": [Function],
+ "serviceAccountToken": "ABC123",
+ "sniffOnConnectionFault": true,
+ "sniffOnStart": true,
+ }
+ `);
+ });
+
+ it('is not set when #auth is true, and a token is not provided', () => {
+ expect(
+ parseElasticsearchClientConfig(
+ {
+ apiVersion: 'v7.0.0',
+ customHeaders: { xsrf: 'something' },
+ sniffOnStart: true,
+ sniffOnConnectionFault: true,
+ hosts: ['https://es.local'],
+ requestHeadersWhitelist: [],
+ },
+ logger.get(),
+ 'custom-type',
+ { auth: true }
+ )
+ ).toMatchInlineSnapshot(`
+ Object {
+ "apiVersion": "v7.0.0",
+ "hosts": Array [
+ Object {
+ "headers": Object {
+ "x-elastic-product-origin": "kibana",
+ "xsrf": "something",
+ },
+ "host": "es.local",
+ "path": "/",
+ "port": "443",
+ "protocol": "https:",
+ "query": null,
+ },
+ ],
+ "keepAlive": true,
+ "log": [Function],
+ "sniffOnConnectionFault": true,
+ "sniffOnStart": true,
+ }
+ `);
+ });
+
+ it('is not set when #auth is false, and a token is provided', () => {
+ expect(
+ parseElasticsearchClientConfig(
+ {
+ apiVersion: 'v7.0.0',
+ customHeaders: { xsrf: 'something' },
+ sniffOnStart: true,
+ sniffOnConnectionFault: true,
+ hosts: ['https://es.local'],
+ requestHeadersWhitelist: [],
+ serviceAccountToken: 'ABC123',
+ },
+ logger.get(),
+ 'custom-type',
+ { auth: false }
+ )
+ ).toMatchInlineSnapshot(`
+ Object {
+ "apiVersion": "v7.0.0",
+ "hosts": Array [
+ Object {
+ "headers": Object {
+ "x-elastic-product-origin": "kibana",
+ "xsrf": "something",
+ },
+ "host": "es.local",
+ "path": "/",
+ "port": "443",
+ "protocol": "https:",
+ "query": null,
+ },
+ ],
+ "keepAlive": true,
+ "log": [Function],
+ "sniffOnConnectionFault": true,
+ "sniffOnStart": true,
+ }
+ `);
+ });
+});
+
describe('#customHeaders', () => {
test('override the default headers', () => {
const headerKey = Object.keys(DEFAULT_HEADERS)[0];
diff --git a/src/core/server/elasticsearch/legacy/elasticsearch_client_config.ts b/src/core/server/elasticsearch/legacy/elasticsearch_client_config.ts
index d68e7635c57cb..3d81caefad457 100644
--- a/src/core/server/elasticsearch/legacy/elasticsearch_client_config.ts
+++ b/src/core/server/elasticsearch/legacy/elasticsearch_client_config.ts
@@ -35,6 +35,7 @@ export type LegacyElasticsearchClientConfig = Pick & {
pingTimeout?: ElasticsearchConfig['pingTimeout'] | ConfigOptions['pingTimeout'];
requestTimeout?: ElasticsearchConfig['requestTimeout'] | ConfigOptions['requestTimeout'];
@@ -61,6 +62,7 @@ interface LegacyElasticsearchClientConfigOverrides {
/** @internal */
type ExtendedConfigOptions = ConfigOptions &
Partial<{
+ serviceAccountToken?: string;
ssl: Partial<{
rejectUnauthorized: boolean;
checkServerIdentity: typeof checkServerIdentity;
@@ -106,9 +108,14 @@ export function parseElasticsearchClientConfig(
esClientConfig.sniffInterval = getDurationAsMs(config.sniffInterval);
}
- const needsAuth = auth !== false && config.username && config.password;
+ const needsAuth =
+ auth !== false && ((config.username && config.password) || config.serviceAccountToken);
if (needsAuth) {
- esClientConfig.httpAuth = `${config.username}:${config.password}`;
+ if (config.username) {
+ esClientConfig.httpAuth = `${config.username}:${config.password}`;
+ } else if (config.serviceAccountToken) {
+ esClientConfig.serviceAccountToken = config.serviceAccountToken;
+ }
}
if (Array.isArray(config.hosts)) {
diff --git a/src/core/server/server.api.md b/src/core/server/server.api.md
index ed55c6e3d09cb..65ea082c9d8a8 100644
--- a/src/core/server/server.api.md
+++ b/src/core/server/server.api.md
@@ -345,6 +345,7 @@ export const config: {
hosts: Type;
username: Type;
password: Type;
+ serviceAccountToken: Type;
requestHeadersWhitelist: Type;
customHeaders: Type>;
shardTimeout: Type;
@@ -948,7 +949,7 @@ export type ElasticsearchClient = Omit & {
+export type ElasticsearchClientConfig = Pick & {
pingTimeout?: ElasticsearchConfig['pingTimeout'] | ClientOptions['pingTimeout'];
requestTimeout?: ElasticsearchConfig['requestTimeout'] | ClientOptions['requestTimeout'];
ssl?: Partial;
@@ -968,6 +969,7 @@ export class ElasticsearchConfig {
readonly pingTimeout: Duration;
readonly requestHeadersWhitelist: string[];
readonly requestTimeout: Duration;
+ readonly serviceAccountToken?: string;
readonly shardTimeout: Duration;
readonly sniffInterval: false | Duration;
readonly sniffOnConnectionFault: boolean;
@@ -1675,7 +1677,7 @@ export class LegacyClusterClient implements ILegacyClusterClient {
}
// @public @deprecated (undocumented)
-export type LegacyElasticsearchClientConfig = Pick & Pick & {
+export type LegacyElasticsearchClientConfig = Pick & Pick & {
pingTimeout?: ElasticsearchConfig['pingTimeout'] | ConfigOptions['pingTimeout'];
requestTimeout?: ElasticsearchConfig['requestTimeout'] | ConfigOptions['requestTimeout'];
sniffInterval?: ElasticsearchConfig['sniffInterval'] | ConfigOptions['sniffInterval'];
diff --git a/src/dev/build/tasks/os_packages/docker_generator/resources/base/bin/kibana-docker b/src/dev/build/tasks/os_packages/docker_generator/resources/base/bin/kibana-docker
index 39a7665f1ce5e..c7a129418765b 100755
--- a/src/dev/build/tasks/os_packages/docker_generator/resources/base/bin/kibana-docker
+++ b/src/dev/build/tasks/os_packages/docker_generator/resources/base/bin/kibana-docker
@@ -51,6 +51,7 @@ kibana_vars=(
elasticsearch.pingTimeout
elasticsearch.requestHeadersWhitelist
elasticsearch.requestTimeout
+ elasticsearch.serviceAccountToken
elasticsearch.shardTimeout
elasticsearch.sniffInterval
elasticsearch.sniffOnConnectionFault