Improve authentication handling (#908)
This commit is contained in:
committed by
delvedor
parent
a55856c60b
commit
708f9abe3e
@ -3,53 +3,11 @@
|
|||||||
|
|
||||||
This document contains code snippets to show you how to connect to various Elasticsearch providers.
|
This document contains code snippets to show you how to connect to various Elasticsearch providers.
|
||||||
|
|
||||||
=== Basic Auth
|
|
||||||
|
|
||||||
You can provide your credentials in the node(s) URL.
|
|
||||||
|
|
||||||
[source,js]
|
|
||||||
----
|
|
||||||
const { Client } = require('@elastic/elasticsearch')
|
|
||||||
const client = new Client({
|
|
||||||
node: 'https://username:password@localhost:9200'
|
|
||||||
})
|
|
||||||
----
|
|
||||||
|
|
||||||
Or you can use the full node declaration.
|
|
||||||
|
|
||||||
[source,js]
|
|
||||||
----
|
|
||||||
const { URL } = require('url')
|
|
||||||
const { Client } = require('@elastic/elasticsearch')
|
|
||||||
const client = new Client({
|
|
||||||
node: {
|
|
||||||
url: new URL('https://username:password@localhost:9200'),
|
|
||||||
id: 'node-1',
|
|
||||||
...
|
|
||||||
}
|
|
||||||
})
|
|
||||||
----
|
|
||||||
|
|
||||||
=== SSL configuration
|
|
||||||
|
|
||||||
Without any additional configuration you can specify `https://` node urls, but the certificates used to sign these requests will not verified (`rejectUnauthorized: false`). To turn on certificate verification you must specify an `ssl` object either in the top level config or in each host config object and set `rejectUnauthorized: true`. The ssl config object can contain many of the same configuration options that https://nodejs.org/api/tls.html#tls_tls_connect_options_callback[tls.connect()] accepts.
|
|
||||||
|
|
||||||
[source,js]
|
|
||||||
----
|
|
||||||
const { Client } = require('@elastic/elasticsearch')
|
|
||||||
const client = new Client({
|
|
||||||
node: 'http://username:password@localhost:9200',
|
|
||||||
ssl: {
|
|
||||||
ca: fs.readFileSync('./cacert.pem'),
|
|
||||||
rejectUnauthorized: true
|
|
||||||
}
|
|
||||||
})
|
|
||||||
----
|
|
||||||
|
|
||||||
=== Elastic Cloud
|
=== Elastic Cloud
|
||||||
|
|
||||||
If you are using https://www.elastic.co/cloud[Elastic Cloud], the client offers a easy way to connect to it via the `cloud` option. +
|
If you are using https://www.elastic.co/cloud[Elastic Cloud], the client offers a easy way to connect to it via the `cloud` option. +
|
||||||
You must pass the Cloud ID that you can find in the cloud console, then your username and password.
|
You must pass the Cloud ID that you can find in the cloud console, then your username and password inside the `auth` option.
|
||||||
|
|
||||||
NOTE: When connecting to Elastic Cloud, the client will automatically enable both request and response compression by default, since it yields significant throughput improvements. +
|
NOTE: When connecting to Elastic Cloud, the client will automatically enable both request and response compression by default, since it yields significant throughput improvements. +
|
||||||
Moreover, the client will also set the ssl option `secureProtocol` to `TLSv1_2_method` unless specified otherwise.
|
Moreover, the client will also set the ssl option `secureProtocol` to `TLSv1_2_method` unless specified otherwise.
|
||||||
@ -63,8 +21,87 @@ const { Client } = require('@elastic/elasticsearch')
|
|||||||
const client = new Client({
|
const client = new Client({
|
||||||
cloud: {
|
cloud: {
|
||||||
id: 'name:bG9jYWxob3N0JGFiY2QkZWZnaA==',
|
id: 'name:bG9jYWxob3N0JGFiY2QkZWZnaA==',
|
||||||
|
},
|
||||||
|
auth: {
|
||||||
username: 'elastic',
|
username: 'elastic',
|
||||||
password: 'changeme'
|
password: 'changeme'
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
----
|
----
|
||||||
|
|
||||||
|
=== Basic authentication
|
||||||
|
|
||||||
|
You can provide your credentials by passing the `username` and `password` parameters via the `auth` option.
|
||||||
|
|
||||||
|
[source,js]
|
||||||
|
----
|
||||||
|
const { Client } = require('@elastic/elasticsearch')
|
||||||
|
const client = new Client({
|
||||||
|
node: 'https://localhost:9200',
|
||||||
|
auth: {
|
||||||
|
username: 'elastic',
|
||||||
|
password: 'changeme'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
----
|
||||||
|
|
||||||
|
Otherwise, you can provide your credentials in the node(s) URL.
|
||||||
|
|
||||||
|
[source,js]
|
||||||
|
----
|
||||||
|
const { Client } = require('@elastic/elasticsearch')
|
||||||
|
const client = new Client({
|
||||||
|
node: 'https://username:password@localhost:9200'
|
||||||
|
})
|
||||||
|
----
|
||||||
|
|
||||||
|
=== ApiKey authentication
|
||||||
|
|
||||||
|
You can use the https://www.elastic.co/guide/en/elasticsearch/reference/7.x/security-api-create-api-key.html[ApiKey] authentication by passing the `apiKey` parameter via the `auth` option. +
|
||||||
|
The `apiKey` parameter can be either a base64 encoded string or an object with the values that you can obtain from the https://www.elastic.co/guide/en/elasticsearch/reference/7.x/security-api-create-api-key.html[create api key endpoint].
|
||||||
|
|
||||||
|
[source,js]
|
||||||
|
----
|
||||||
|
const { Client } = require('@elastic/elasticsearch')
|
||||||
|
const client = new Client({
|
||||||
|
node: 'https://localhost:9200',
|
||||||
|
auth: {
|
||||||
|
apiKey: 'base64EncodedKey'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
----
|
||||||
|
|
||||||
|
[source,js]
|
||||||
|
----
|
||||||
|
const { Client } = require('@elastic/elasticsearch')
|
||||||
|
const client = new Client({
|
||||||
|
node: 'https://localhost:9200',
|
||||||
|
auth: {
|
||||||
|
apiKey: {
|
||||||
|
id: 'foo',
|
||||||
|
api_key: 'bar'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
----
|
||||||
|
|
||||||
|
|
||||||
|
=== SSL configuration
|
||||||
|
|
||||||
|
Without any additional configuration you can specify `https://` node urls, but the certificates used to sign these requests will not verified (`rejectUnauthorized: false`). To turn on certificate verification you must specify an `ssl` object either in the top level config or in each host config object and set `rejectUnauthorized: true`. The ssl config object can contain many of the same configuration options that https://nodejs.org/api/tls.html#tls_tls_connect_options_callback[tls.connect()] accepts.
|
||||||
|
|
||||||
|
[source,js]
|
||||||
|
----
|
||||||
|
const { Client } = require('@elastic/elasticsearch')
|
||||||
|
const client = new Client({
|
||||||
|
node: 'http://localhost:9200',
|
||||||
|
auth: {
|
||||||
|
username: 'elastic',
|
||||||
|
password: 'changeme'
|
||||||
|
},
|
||||||
|
ssl: {
|
||||||
|
ca: fs.readFileSync('./cacert.pem'),
|
||||||
|
rejectUnauthorized: true
|
||||||
|
}
|
||||||
|
})
|
||||||
|
----
|
||||||
@ -43,6 +43,28 @@ node: {
|
|||||||
}
|
}
|
||||||
----
|
----
|
||||||
|
|
||||||
|
|`auth`
|
||||||
|
a|Your authentication data. You can use both Basic authentication and https://www.elastic.co/guide/en/elasticsearch/reference/7.x/security-api-create-api-key.html[ApiKey]. +
|
||||||
|
See https://www.elastic.co/guide/en/elasticsearch/client/javascript-api/current/auth-reference.html[Authentication] for more details. +
|
||||||
|
_Default:_ `null`
|
||||||
|
|
||||||
|
Basic authentication:
|
||||||
|
[source,js]
|
||||||
|
----
|
||||||
|
auth: {
|
||||||
|
username: 'elastic',
|
||||||
|
password: 'changeme'
|
||||||
|
}
|
||||||
|
----
|
||||||
|
https://www.elastic.co/guide/en/elasticsearch/reference/7.x/security-api-create-api-key.html[ApiKey] authentication:
|
||||||
|
[source,js]
|
||||||
|
----
|
||||||
|
auth: {
|
||||||
|
apiKey: 'base64EncodedKey'
|
||||||
|
}
|
||||||
|
----
|
||||||
|
|
||||||
|
|
||||||
|`maxRetries`
|
|`maxRetries`
|
||||||
|`number` - Max number of retries for each request. +
|
|`number` - Max number of retries for each request. +
|
||||||
_Default:_ `3`
|
_Default:_ `3`
|
||||||
@ -163,7 +185,9 @@ _Cloud configuration example:_
|
|||||||
----
|
----
|
||||||
const client = new Client({
|
const client = new Client({
|
||||||
cloud: {
|
cloud: {
|
||||||
id: 'name:bG9jYWxob3N0JGFiY2QkZWZnaA==',
|
id: 'name:bG9jYWxob3N0JGFiY2QkZWZnaA=='
|
||||||
|
},
|
||||||
|
auth: {
|
||||||
username: 'elastic',
|
username: 'elastic',
|
||||||
password: 'changeme'
|
password: 'changeme'
|
||||||
}
|
}
|
||||||
|
|||||||
4
index.d.ts
vendored
4
index.d.ts
vendored
@ -33,7 +33,7 @@ import Transport, {
|
|||||||
} from './lib/Transport';
|
} from './lib/Transport';
|
||||||
import { URL } from 'url';
|
import { URL } from 'url';
|
||||||
import Connection, { AgentOptions, agentFn } from './lib/Connection';
|
import Connection, { AgentOptions, agentFn } from './lib/Connection';
|
||||||
import ConnectionPool, { ResurrectEvent } from './lib/ConnectionPool';
|
import ConnectionPool, { ResurrectEvent, BasicAuth, ApiKeyAuth } from './lib/ConnectionPool';
|
||||||
import Serializer from './lib/Serializer';
|
import Serializer from './lib/Serializer';
|
||||||
import * as RequestParams from './api/requestParams';
|
import * as RequestParams from './api/requestParams';
|
||||||
import * as errors from './lib/errors';
|
import * as errors from './lib/errors';
|
||||||
@ -111,8 +111,10 @@ interface ClientOptions {
|
|||||||
headers?: anyObject;
|
headers?: anyObject;
|
||||||
generateRequestId?: generateRequestIdFn;
|
generateRequestId?: generateRequestIdFn;
|
||||||
name?: string;
|
name?: string;
|
||||||
|
auth?: BasicAuth | ApiKeyAuth;
|
||||||
cloud?: {
|
cloud?: {
|
||||||
id: string;
|
id: string;
|
||||||
|
// TODO: remove username and password here in 8
|
||||||
username: string;
|
username: string;
|
||||||
password: string;
|
password: string;
|
||||||
}
|
}
|
||||||
|
|||||||
52
index.js
52
index.js
@ -20,6 +20,7 @@
|
|||||||
'use strict'
|
'use strict'
|
||||||
|
|
||||||
const { EventEmitter } = require('events')
|
const { EventEmitter } = require('events')
|
||||||
|
const { URL } = require('url')
|
||||||
const debug = require('debug')('elasticsearch')
|
const debug = require('debug')('elasticsearch')
|
||||||
const Transport = require('./lib/Transport')
|
const Transport = require('./lib/Transport')
|
||||||
const Connection = require('./lib/Connection')
|
const Connection = require('./lib/Connection')
|
||||||
@ -43,7 +44,12 @@ class Client extends EventEmitter {
|
|||||||
// the url is a string divided by two '$', the first is the cloud url
|
// the url is a string divided by two '$', the first is the cloud url
|
||||||
// the second the elasticsearch instance, the third the kibana instance
|
// the second the elasticsearch instance, the third the kibana instance
|
||||||
const cloudUrls = Buffer.from(id.split(':')[1], 'base64').toString().split('$')
|
const cloudUrls = Buffer.from(id.split(':')[1], 'base64').toString().split('$')
|
||||||
opts.node = `https://${username}:${password}@${cloudUrls[1]}.${cloudUrls[0]}`
|
|
||||||
|
// TODO: remove username and password here in 8
|
||||||
|
if (username && password) {
|
||||||
|
opts.auth = Object.assign({}, opts.auth, { username, password })
|
||||||
|
}
|
||||||
|
opts.node = `https://${cloudUrls[1]}.${cloudUrls[0]}`
|
||||||
|
|
||||||
// Cloud has better performances with compression enabled
|
// Cloud has better performances with compression enabled
|
||||||
// see https://github.com/elastic/elasticsearch-py/pull/704.
|
// see https://github.com/elastic/elasticsearch-py/pull/704.
|
||||||
@ -61,6 +67,11 @@ class Client extends EventEmitter {
|
|||||||
throw new ConfigurationError('Missing node(s) option')
|
throw new ConfigurationError('Missing node(s) option')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const checkAuth = getAuth(opts.node || opts.nodes)
|
||||||
|
if (checkAuth && checkAuth.username && checkAuth.password) {
|
||||||
|
opts.auth = Object.assign({}, opts.auth, { username: checkAuth.username, password: checkAuth.password })
|
||||||
|
}
|
||||||
|
|
||||||
const options = Object.assign({}, {
|
const options = Object.assign({}, {
|
||||||
Connection,
|
Connection,
|
||||||
ConnectionPool,
|
ConnectionPool,
|
||||||
@ -82,7 +93,8 @@ class Client extends EventEmitter {
|
|||||||
nodeFilter: null,
|
nodeFilter: null,
|
||||||
nodeSelector: 'round-robin',
|
nodeSelector: 'round-robin',
|
||||||
generateRequestId: null,
|
generateRequestId: null,
|
||||||
name: 'elasticsearch-js'
|
name: 'elasticsearch-js',
|
||||||
|
auth: null
|
||||||
}, opts)
|
}, opts)
|
||||||
|
|
||||||
this[kInitialOptions] = options
|
this[kInitialOptions] = options
|
||||||
@ -96,6 +108,7 @@ class Client extends EventEmitter {
|
|||||||
ssl: options.ssl,
|
ssl: options.ssl,
|
||||||
agent: options.agent,
|
agent: options.agent,
|
||||||
Connection: options.Connection,
|
Connection: options.Connection,
|
||||||
|
auth: options.auth,
|
||||||
emit: this.emit.bind(this),
|
emit: this.emit.bind(this),
|
||||||
sniffEnabled: options.sniffInterval !== false ||
|
sniffEnabled: options.sniffInterval !== false ||
|
||||||
options.sniffOnStart !== false ||
|
options.sniffOnStart !== false ||
|
||||||
@ -209,6 +222,41 @@ class Client extends EventEmitter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getAuth (node) {
|
||||||
|
if (Array.isArray(node)) {
|
||||||
|
for (const url of node) {
|
||||||
|
const auth = getUsernameAndPassword(url)
|
||||||
|
if (auth.username !== '' && auth.password !== '') {
|
||||||
|
return auth
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
const auth = getUsernameAndPassword(node)
|
||||||
|
if (auth.username !== '' && auth.password !== '') {
|
||||||
|
return auth
|
||||||
|
}
|
||||||
|
|
||||||
|
return null
|
||||||
|
|
||||||
|
function getUsernameAndPassword (node) {
|
||||||
|
if (typeof node === 'string') {
|
||||||
|
const { username, password } = new URL(node)
|
||||||
|
return {
|
||||||
|
username: decodeURIComponent(username),
|
||||||
|
password: decodeURIComponent(password)
|
||||||
|
}
|
||||||
|
} else if (node.url instanceof URL) {
|
||||||
|
return {
|
||||||
|
username: decodeURIComponent(node.url.username),
|
||||||
|
password: decodeURIComponent(node.url.password)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const events = {
|
const events = {
|
||||||
RESPONSE: 'response',
|
RESPONSE: 'response',
|
||||||
REQUEST: 'request',
|
REQUEST: 'request',
|
||||||
|
|||||||
2
lib/Connection.d.ts
vendored
2
lib/Connection.d.ts
vendored
@ -21,6 +21,7 @@
|
|||||||
|
|
||||||
import { URL } from 'url';
|
import { URL } from 'url';
|
||||||
import { inspect, InspectOptions } from 'util';
|
import { inspect, InspectOptions } from 'util';
|
||||||
|
import { ApiKeyAuth, BasicAuth } from './ConnectionPool'
|
||||||
import * as http from 'http';
|
import * as http from 'http';
|
||||||
import { ConnectionOptions as TlsConnectionOptions } from 'tls';
|
import { ConnectionOptions as TlsConnectionOptions } from 'tls';
|
||||||
|
|
||||||
@ -34,6 +35,7 @@ interface ConnectionOptions {
|
|||||||
agent?: AgentOptions | agentFn;
|
agent?: AgentOptions | agentFn;
|
||||||
status?: string;
|
status?: string;
|
||||||
roles?: any;
|
roles?: any;
|
||||||
|
auth?: BasicAuth | ApiKeyAuth;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface RequestOptions extends http.ClientRequestArgs {
|
interface RequestOptions extends http.ClientRequestArgs {
|
||||||
|
|||||||
@ -34,8 +34,7 @@ class Connection {
|
|||||||
this.url = opts.url
|
this.url = opts.url
|
||||||
this.ssl = opts.ssl || null
|
this.ssl = opts.ssl || null
|
||||||
this.id = opts.id || stripAuth(opts.url.href)
|
this.id = opts.id || stripAuth(opts.url.href)
|
||||||
this.headers = opts.headers || null
|
this.headers = prepareHeaders(opts.headers, opts.auth)
|
||||||
this.auth = opts.auth || { username: null, password: null }
|
|
||||||
this.deadCount = 0
|
this.deadCount = 0
|
||||||
this.resurrectTimeout = 0
|
this.resurrectTimeout = 0
|
||||||
|
|
||||||
@ -181,7 +180,6 @@ class Connection {
|
|||||||
|
|
||||||
buildRequestObject (params) {
|
buildRequestObject (params) {
|
||||||
const url = this.url
|
const url = this.url
|
||||||
const { username, password } = this.auth
|
|
||||||
const request = {
|
const request = {
|
||||||
protocol: url.protocol,
|
protocol: url.protocol,
|
||||||
hostname: url.hostname[0] === '['
|
hostname: url.hostname[0] === '['
|
||||||
@ -196,9 +194,6 @@ class Connection {
|
|||||||
// https://github.com/elastic/elasticsearch-js/issues/843
|
// https://github.com/elastic/elasticsearch-js/issues/843
|
||||||
port: url.port !== '' ? url.port : undefined,
|
port: url.port !== '' ? url.port : undefined,
|
||||||
headers: this.headers,
|
headers: this.headers,
|
||||||
auth: username != null && password != null
|
|
||||||
? `${username}:${password}`
|
|
||||||
: undefined,
|
|
||||||
agent: this.agent
|
agent: this.agent
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -230,10 +225,15 @@ class Connection {
|
|||||||
// the logs very hard to read. The user can still
|
// the logs very hard to read. The user can still
|
||||||
// access them with `instance.agent` and `instance.ssl`.
|
// access them with `instance.agent` and `instance.ssl`.
|
||||||
[inspect.custom] (depth, options) {
|
[inspect.custom] (depth, options) {
|
||||||
|
const {
|
||||||
|
authorization,
|
||||||
|
...headers
|
||||||
|
} = this.headers
|
||||||
|
|
||||||
return {
|
return {
|
||||||
url: stripAuth(this.url.toString()),
|
url: stripAuth(this.url.toString()),
|
||||||
id: this.id,
|
id: this.id,
|
||||||
headers: this.headers,
|
headers,
|
||||||
deadCount: this.deadCount,
|
deadCount: this.deadCount,
|
||||||
resurrectTimeout: this.resurrectTimeout,
|
resurrectTimeout: this.resurrectTimeout,
|
||||||
_openRequests: this._openRequests,
|
_openRequests: this._openRequests,
|
||||||
@ -243,10 +243,15 @@ class Connection {
|
|||||||
}
|
}
|
||||||
|
|
||||||
toJSON () {
|
toJSON () {
|
||||||
|
const {
|
||||||
|
authorization,
|
||||||
|
...headers
|
||||||
|
} = this.headers
|
||||||
|
|
||||||
return {
|
return {
|
||||||
url: stripAuth(this.url.toString()),
|
url: stripAuth(this.url.toString()),
|
||||||
id: this.id,
|
id: this.id,
|
||||||
headers: this.headers,
|
headers,
|
||||||
deadCount: this.deadCount,
|
deadCount: this.deadCount,
|
||||||
resurrectTimeout: this.resurrectTimeout,
|
resurrectTimeout: this.resurrectTimeout,
|
||||||
_openRequests: this._openRequests,
|
_openRequests: this._openRequests,
|
||||||
@ -302,4 +307,21 @@ function resolve (host, path) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function prepareHeaders (headers = {}, auth) {
|
||||||
|
if (auth != null && headers.authorization == null) {
|
||||||
|
if (auth.username && auth.password) {
|
||||||
|
headers.authorization = 'Basic ' + Buffer.from(`${auth.username}:${auth.password}`).toString('base64')
|
||||||
|
}
|
||||||
|
|
||||||
|
if (auth.apiKey) {
|
||||||
|
if (typeof auth.apiKey === 'object') {
|
||||||
|
headers.authorization = 'ApiKey ' + Buffer.from(`${auth.apiKey.id}:${auth.apiKey.api_key}`).toString('base64')
|
||||||
|
} else {
|
||||||
|
headers.authorization = `ApiKey ${auth.apiKey}`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return headers
|
||||||
|
}
|
||||||
|
|
||||||
module.exports = Connection
|
module.exports = Connection
|
||||||
|
|||||||
16
lib/ConnectionPool.d.ts
vendored
16
lib/ConnectionPool.d.ts
vendored
@ -26,6 +26,7 @@ import { nodeFilterFn, nodeSelectorFn } from './Transport';
|
|||||||
interface ConnectionPoolOptions {
|
interface ConnectionPoolOptions {
|
||||||
ssl?: SecureContextOptions;
|
ssl?: SecureContextOptions;
|
||||||
agent?: AgentOptions;
|
agent?: AgentOptions;
|
||||||
|
auth: BasicAuth | ApiKeyAuth;
|
||||||
pingTimeout?: number;
|
pingTimeout?: number;
|
||||||
Connection: typeof Connection;
|
Connection: typeof Connection;
|
||||||
resurrectStrategy?: string;
|
resurrectStrategy?: string;
|
||||||
@ -36,6 +37,20 @@ export interface getConnectionOptions {
|
|||||||
selector?: nodeSelectorFn;
|
selector?: nodeSelectorFn;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface ApiKeyAuth {
|
||||||
|
apiKey:
|
||||||
|
| string
|
||||||
|
| {
|
||||||
|
id: string;
|
||||||
|
api_key: string;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface BasicAuth {
|
||||||
|
username: string;
|
||||||
|
password: string;
|
||||||
|
}
|
||||||
|
|
||||||
export interface resurrectOptions {
|
export interface resurrectOptions {
|
||||||
now?: number;
|
now?: number;
|
||||||
requestId: string;
|
requestId: string;
|
||||||
@ -66,6 +81,7 @@ export default class ConnectionPool {
|
|||||||
resurrectTimeout: number;
|
resurrectTimeout: number;
|
||||||
resurrectTimeoutCutoff: number;
|
resurrectTimeoutCutoff: number;
|
||||||
pingTimeout: number;
|
pingTimeout: number;
|
||||||
|
auth: BasicAuth | ApiKeyAuth;
|
||||||
Connection: typeof Connection;
|
Connection: typeof Connection;
|
||||||
resurrectStrategy: number;
|
resurrectStrategy: number;
|
||||||
constructor(opts?: ConnectionPoolOptions);
|
constructor(opts?: ConnectionPoolOptions);
|
||||||
|
|||||||
@ -30,7 +30,7 @@ class ConnectionPool {
|
|||||||
this.connections = new Map()
|
this.connections = new Map()
|
||||||
this.dead = []
|
this.dead = []
|
||||||
this.selector = opts.selector
|
this.selector = opts.selector
|
||||||
this._auth = null
|
this.auth = opts.auth || null
|
||||||
this._ssl = opts.ssl
|
this._ssl = opts.ssl
|
||||||
this._agent = opts.agent
|
this._agent = opts.agent
|
||||||
// the resurrect timeout is 60s
|
// the resurrect timeout is 60s
|
||||||
@ -217,23 +217,14 @@ class ConnectionPool {
|
|||||||
if (typeof opts === 'string') {
|
if (typeof opts === 'string') {
|
||||||
opts = this.urlToHost(opts)
|
opts = this.urlToHost(opts)
|
||||||
}
|
}
|
||||||
// if a given node has auth data we store it in the connection pool,
|
|
||||||
// so if we add new nodes without auth data (after a sniff for example)
|
|
||||||
// we can add it to them once the connection instance has been created
|
|
||||||
if (opts.url.username !== '' && opts.url.password !== '') {
|
if (opts.url.username !== '' && opts.url.password !== '') {
|
||||||
this._auth = {
|
opts.auth = {
|
||||||
username: decodeURIComponent(opts.url.username),
|
username: decodeURIComponent(opts.url.username),
|
||||||
password: decodeURIComponent(opts.url.password)
|
password: decodeURIComponent(opts.url.password)
|
||||||
}
|
}
|
||||||
opts.auth = this._auth
|
} else if (this.auth !== null) {
|
||||||
}
|
opts.auth = this.auth
|
||||||
|
|
||||||
if (this._auth != null) {
|
|
||||||
if (opts.auth == null || (opts.auth.username == null && opts.auth.password == null)) {
|
|
||||||
opts.auth = this._auth
|
|
||||||
opts.url.username = this._auth.username
|
|
||||||
opts.url.password = this._auth.password
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (opts.ssl == null) opts.ssl = this._ssl
|
if (opts.ssl == null) opts.ssl = this._ssl
|
||||||
|
|||||||
@ -50,6 +50,26 @@ const nodeOpts: NodeOptions = {
|
|||||||
|
|
||||||
const client2 = new Client({ node: nodeOpts })
|
const client2 = new Client({ node: nodeOpts })
|
||||||
|
|
||||||
|
const clientBasicAuth = new Client({
|
||||||
|
node: 'http://localhost:9200',
|
||||||
|
auth: { username: 'foo', password: 'bar' }
|
||||||
|
})
|
||||||
|
|
||||||
|
const clientApiKeyString = new Client({
|
||||||
|
node: 'http://localhost:9200',
|
||||||
|
auth: { apiKey: 'foobar' }
|
||||||
|
})
|
||||||
|
|
||||||
|
const clientApiKeyObject = new Client({
|
||||||
|
node: 'http://localhost:9200',
|
||||||
|
auth: {
|
||||||
|
apiKey: {
|
||||||
|
id: 'foo',
|
||||||
|
api_key: 'bar'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
client.on(events.RESPONSE, (err: errors.ElasticsearchClientError | null, request: RequestEvent) => {
|
client.on(events.RESPONSE, (err: errors.ElasticsearchClientError | null, request: RequestEvent) => {
|
||||||
if (err) console.log(err)
|
if (err) console.log(err)
|
||||||
const { body, statusCode } = request
|
const { body, statusCode } = request
|
||||||
|
|||||||
@ -198,63 +198,293 @@ test('Configure host', t => {
|
|||||||
t.end()
|
t.end()
|
||||||
})
|
})
|
||||||
|
|
||||||
test('Node with auth data in the url', t => {
|
test('Authentication', t => {
|
||||||
t.plan(3)
|
t.test('Basic', t => {
|
||||||
|
t.test('Node with basic auth data in the url', t => {
|
||||||
|
t.plan(3)
|
||||||
|
|
||||||
function handler (req, res) {
|
function handler (req, res) {
|
||||||
t.match(req.headers, {
|
t.match(req.headers, {
|
||||||
authorization: 'Basic Zm9vOmJhcg=='
|
authorization: 'Basic Zm9vOmJhcg=='
|
||||||
})
|
})
|
||||||
res.setHeader('Content-Type', 'application/json;utf=8')
|
res.setHeader('Content-Type', 'application/json;utf=8')
|
||||||
res.end(JSON.stringify({ hello: 'world' }))
|
res.end(JSON.stringify({ hello: 'world' }))
|
||||||
}
|
|
||||||
|
|
||||||
buildServer(handler, ({ port }, server) => {
|
|
||||||
const client = new Client({
|
|
||||||
node: `http://foo:bar@localhost:${port}`
|
|
||||||
})
|
|
||||||
|
|
||||||
client.info((err, { body }) => {
|
|
||||||
t.error(err)
|
|
||||||
t.deepEqual(body, { hello: 'world' })
|
|
||||||
server.stop()
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
test('Custom authentication per request', t => {
|
|
||||||
t.plan(6)
|
|
||||||
|
|
||||||
var first = true
|
|
||||||
function handler (req, res) {
|
|
||||||
t.match(req.headers, {
|
|
||||||
authorization: first ? 'hello' : 'Basic Zm9vOmJhcg=='
|
|
||||||
})
|
|
||||||
res.setHeader('Content-Type', 'application/json;utf=8')
|
|
||||||
res.end(JSON.stringify({ hello: 'world' }))
|
|
||||||
}
|
|
||||||
|
|
||||||
buildServer(handler, ({ port }, server) => {
|
|
||||||
const client = new Client({
|
|
||||||
node: `http://foo:bar@localhost:${port}`
|
|
||||||
})
|
|
||||||
|
|
||||||
client.info({}, {
|
|
||||||
headers: {
|
|
||||||
authorization: 'hello'
|
|
||||||
}
|
}
|
||||||
}, (err, { body }) => {
|
|
||||||
t.error(err)
|
|
||||||
t.deepEqual(body, { hello: 'world' })
|
|
||||||
first = false
|
|
||||||
|
|
||||||
client.info((err, { body }) => {
|
buildServer(handler, ({ port }, server) => {
|
||||||
t.error(err)
|
const client = new Client({
|
||||||
t.deepEqual(body, { hello: 'world' })
|
node: `http://foo:bar@localhost:${port}`
|
||||||
server.stop()
|
})
|
||||||
|
|
||||||
|
client.info((err, { body }) => {
|
||||||
|
t.error(err)
|
||||||
|
t.deepEqual(body, { hello: 'world' })
|
||||||
|
server.stop()
|
||||||
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
t.test('Node with basic auth data in the url (array of nodes)', t => {
|
||||||
|
t.plan(3)
|
||||||
|
|
||||||
|
function handler (req, res) {
|
||||||
|
t.match(req.headers, {
|
||||||
|
authorization: 'Basic Zm9vOmJhcg=='
|
||||||
|
})
|
||||||
|
res.setHeader('Content-Type', 'application/json;utf=8')
|
||||||
|
res.end(JSON.stringify({ hello: 'world' }))
|
||||||
|
}
|
||||||
|
|
||||||
|
buildServer(handler, ({ port }, server) => {
|
||||||
|
const client = new Client({
|
||||||
|
nodes: [`http://foo:bar@localhost:${port}`]
|
||||||
|
})
|
||||||
|
|
||||||
|
client.info((err, { body }) => {
|
||||||
|
t.error(err)
|
||||||
|
t.deepEqual(body, { hello: 'world' })
|
||||||
|
server.stop()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
t.test('Node with basic auth data in the options', t => {
|
||||||
|
t.plan(3)
|
||||||
|
|
||||||
|
function handler (req, res) {
|
||||||
|
t.match(req.headers, {
|
||||||
|
authorization: 'Basic Zm9vOmJhcg=='
|
||||||
|
})
|
||||||
|
res.setHeader('Content-Type', 'application/json;utf=8')
|
||||||
|
res.end(JSON.stringify({ hello: 'world' }))
|
||||||
|
}
|
||||||
|
|
||||||
|
buildServer(handler, ({ port }, server) => {
|
||||||
|
const client = new Client({
|
||||||
|
node: `http://localhost:${port}`,
|
||||||
|
auth: {
|
||||||
|
username: 'foo',
|
||||||
|
password: 'bar'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
client.info((err, { body }) => {
|
||||||
|
t.error(err)
|
||||||
|
t.deepEqual(body, { hello: 'world' })
|
||||||
|
server.stop()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
t.test('Custom basic authentication per request', t => {
|
||||||
|
t.plan(6)
|
||||||
|
|
||||||
|
var first = true
|
||||||
|
function handler (req, res) {
|
||||||
|
t.match(req.headers, {
|
||||||
|
authorization: first ? 'hello' : 'Basic Zm9vOmJhcg=='
|
||||||
|
})
|
||||||
|
res.setHeader('Content-Type', 'application/json;utf=8')
|
||||||
|
res.end(JSON.stringify({ hello: 'world' }))
|
||||||
|
}
|
||||||
|
|
||||||
|
buildServer(handler, ({ port }, server) => {
|
||||||
|
const client = new Client({
|
||||||
|
node: `http://foo:bar@localhost:${port}`
|
||||||
|
})
|
||||||
|
|
||||||
|
client.info({}, {
|
||||||
|
headers: {
|
||||||
|
authorization: 'hello'
|
||||||
|
}
|
||||||
|
}, (err, { body }) => {
|
||||||
|
t.error(err)
|
||||||
|
t.deepEqual(body, { hello: 'world' })
|
||||||
|
first = false
|
||||||
|
|
||||||
|
client.info((err, { body }) => {
|
||||||
|
t.error(err)
|
||||||
|
t.deepEqual(body, { hello: 'world' })
|
||||||
|
server.stop()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
t.test('Override default basic authentication per request', t => {
|
||||||
|
t.plan(6)
|
||||||
|
|
||||||
|
var first = true
|
||||||
|
function handler (req, res) {
|
||||||
|
t.match(req.headers, {
|
||||||
|
authorization: first ? 'hello' : 'Basic Zm9vOmJhcg=='
|
||||||
|
})
|
||||||
|
res.setHeader('Content-Type', 'application/json;utf=8')
|
||||||
|
res.end(JSON.stringify({ hello: 'world' }))
|
||||||
|
}
|
||||||
|
|
||||||
|
buildServer(handler, ({ port }, server) => {
|
||||||
|
const client = new Client({
|
||||||
|
node: `http://localhost:${port}`,
|
||||||
|
auth: {
|
||||||
|
username: 'foo',
|
||||||
|
password: 'bar'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
client.info({}, {
|
||||||
|
headers: {
|
||||||
|
authorization: 'hello'
|
||||||
|
}
|
||||||
|
}, (err, { body }) => {
|
||||||
|
t.error(err)
|
||||||
|
t.deepEqual(body, { hello: 'world' })
|
||||||
|
first = false
|
||||||
|
|
||||||
|
client.info((err, { body }) => {
|
||||||
|
t.error(err)
|
||||||
|
t.deepEqual(body, { hello: 'world' })
|
||||||
|
server.stop()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
t.end()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
t.test('ApiKey', t => {
|
||||||
|
t.test('Node with ApiKey auth data in the options as string', t => {
|
||||||
|
t.plan(3)
|
||||||
|
|
||||||
|
function handler (req, res) {
|
||||||
|
t.match(req.headers, {
|
||||||
|
authorization: 'ApiKey Zm9vOmJhcg=='
|
||||||
|
})
|
||||||
|
res.setHeader('Content-Type', 'application/json;utf=8')
|
||||||
|
res.end(JSON.stringify({ hello: 'world' }))
|
||||||
|
}
|
||||||
|
|
||||||
|
buildServer(handler, ({ port }, server) => {
|
||||||
|
const client = new Client({
|
||||||
|
node: `http://localhost:${port}`,
|
||||||
|
auth: {
|
||||||
|
apiKey: 'Zm9vOmJhcg=='
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
client.info((err, { body }) => {
|
||||||
|
t.error(err)
|
||||||
|
t.deepEqual(body, { hello: 'world' })
|
||||||
|
server.stop()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
t.test('Node with ApiKey auth data in the options as object', t => {
|
||||||
|
t.plan(3)
|
||||||
|
|
||||||
|
function handler (req, res) {
|
||||||
|
t.match(req.headers, {
|
||||||
|
authorization: 'ApiKey Zm9vOmJhcg=='
|
||||||
|
})
|
||||||
|
res.setHeader('Content-Type', 'application/json;utf=8')
|
||||||
|
res.end(JSON.stringify({ hello: 'world' }))
|
||||||
|
}
|
||||||
|
|
||||||
|
buildServer(handler, ({ port }, server) => {
|
||||||
|
const client = new Client({
|
||||||
|
node: `http://localhost:${port}`,
|
||||||
|
auth: {
|
||||||
|
apiKey: { id: 'foo', api_key: 'bar' }
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
client.info((err, { body }) => {
|
||||||
|
t.error(err)
|
||||||
|
t.deepEqual(body, { hello: 'world' })
|
||||||
|
server.stop()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
t.test('Custom ApiKey authentication per request', t => {
|
||||||
|
t.plan(6)
|
||||||
|
|
||||||
|
var first = true
|
||||||
|
function handler (req, res) {
|
||||||
|
t.match(req.headers, {
|
||||||
|
authorization: first ? 'ApiKey Zm9vOmJhcg==' : 'Basic Zm9vOmJhcg=='
|
||||||
|
})
|
||||||
|
res.setHeader('Content-Type', 'application/json;utf=8')
|
||||||
|
res.end(JSON.stringify({ hello: 'world' }))
|
||||||
|
}
|
||||||
|
|
||||||
|
buildServer(handler, ({ port }, server) => {
|
||||||
|
const client = new Client({
|
||||||
|
node: `http://foo:bar@localhost:${port}`
|
||||||
|
})
|
||||||
|
|
||||||
|
client.info({}, {
|
||||||
|
headers: {
|
||||||
|
authorization: 'ApiKey Zm9vOmJhcg=='
|
||||||
|
}
|
||||||
|
}, (err, { body }) => {
|
||||||
|
t.error(err)
|
||||||
|
t.deepEqual(body, { hello: 'world' })
|
||||||
|
first = false
|
||||||
|
|
||||||
|
client.info((err, { body }) => {
|
||||||
|
t.error(err)
|
||||||
|
t.deepEqual(body, { hello: 'world' })
|
||||||
|
server.stop()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
t.test('Override default ApiKey authentication per request', t => {
|
||||||
|
t.plan(6)
|
||||||
|
|
||||||
|
var first = true
|
||||||
|
function handler (req, res) {
|
||||||
|
t.match(req.headers, {
|
||||||
|
authorization: first ? 'hello' : 'ApiKey Zm9vOmJhcg=='
|
||||||
|
})
|
||||||
|
res.setHeader('Content-Type', 'application/json;utf=8')
|
||||||
|
res.end(JSON.stringify({ hello: 'world' }))
|
||||||
|
}
|
||||||
|
|
||||||
|
buildServer(handler, ({ port }, server) => {
|
||||||
|
const client = new Client({
|
||||||
|
node: `http://localhost:${port}`,
|
||||||
|
auth: {
|
||||||
|
apiKey: 'Zm9vOmJhcg=='
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
client.info({}, {
|
||||||
|
headers: {
|
||||||
|
authorization: 'hello'
|
||||||
|
}
|
||||||
|
}, (err, { body }) => {
|
||||||
|
t.error(err)
|
||||||
|
t.deepEqual(body, { hello: 'world' })
|
||||||
|
first = false
|
||||||
|
|
||||||
|
client.info((err, { body }) => {
|
||||||
|
t.error(err)
|
||||||
|
t.deepEqual(body, { hello: 'world' })
|
||||||
|
server.stop()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
t.end()
|
||||||
|
})
|
||||||
|
|
||||||
|
t.end()
|
||||||
})
|
})
|
||||||
|
|
||||||
test('Custom headers per request', t => {
|
test('Custom headers per request', t => {
|
||||||
@ -554,6 +784,45 @@ test('Elastic cloud config', t => {
|
|||||||
t.match(pool.connections.get('https://abcd.localhost/'), {
|
t.match(pool.connections.get('https://abcd.localhost/'), {
|
||||||
url: new URL('https://elastic:changeme@abcd.localhost'),
|
url: new URL('https://elastic:changeme@abcd.localhost'),
|
||||||
id: 'https://abcd.localhost/',
|
id: 'https://abcd.localhost/',
|
||||||
|
headers: {
|
||||||
|
authorization: 'Basic ' + Buffer.from('elastic:changeme').toString('base64')
|
||||||
|
},
|
||||||
|
ssl: { secureProtocol: 'TLSv1_2_method' },
|
||||||
|
deadCount: 0,
|
||||||
|
resurrectTimeout: 0,
|
||||||
|
roles: {
|
||||||
|
master: true,
|
||||||
|
data: true,
|
||||||
|
ingest: true,
|
||||||
|
ml: false
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.strictEqual(client.transport.compression, 'gzip')
|
||||||
|
t.strictEqual(client.transport.suggestCompression, true)
|
||||||
|
t.deepEqual(pool._ssl, { secureProtocol: 'TLSv1_2_method' })
|
||||||
|
})
|
||||||
|
|
||||||
|
t.test('Auth as separate option', t => {
|
||||||
|
t.plan(4)
|
||||||
|
const client = new Client({
|
||||||
|
cloud: {
|
||||||
|
// 'localhost$abcd$efgh'
|
||||||
|
id: 'name:bG9jYWxob3N0JGFiY2QkZWZnaA=='
|
||||||
|
},
|
||||||
|
auth: {
|
||||||
|
username: 'elastic',
|
||||||
|
password: 'changeme'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const pool = client.connectionPool
|
||||||
|
t.match(pool.connections.get('https://abcd.localhost/'), {
|
||||||
|
url: new URL('https://elastic:changeme@abcd.localhost'),
|
||||||
|
id: 'https://abcd.localhost/',
|
||||||
|
headers: {
|
||||||
|
authorization: 'Basic ' + Buffer.from('elastic:changeme').toString('base64')
|
||||||
|
},
|
||||||
ssl: { secureProtocol: 'TLSv1_2_method' },
|
ssl: { secureProtocol: 'TLSv1_2_method' },
|
||||||
deadCount: 0,
|
deadCount: 0,
|
||||||
resurrectTimeout: 0,
|
resurrectTimeout: 0,
|
||||||
|
|||||||
@ -50,25 +50,6 @@ test('API', t => {
|
|||||||
t.end()
|
t.end()
|
||||||
})
|
})
|
||||||
|
|
||||||
t.test('addConnection (should store the auth data)', t => {
|
|
||||||
const pool = new ConnectionPool({ Connection })
|
|
||||||
const href = 'http://localhost:9200/'
|
|
||||||
pool.addConnection('http://foo:bar@localhost:9200')
|
|
||||||
|
|
||||||
t.ok(pool.connections.get(href) instanceof Connection)
|
|
||||||
t.strictEqual(pool.connections.get(href).status, Connection.statuses.ALIVE)
|
|
||||||
t.deepEqual(pool.dead, [])
|
|
||||||
t.deepEqual(pool._auth, { username: 'foo', password: 'bar' })
|
|
||||||
|
|
||||||
pool.addConnection('http://localhost:9201')
|
|
||||||
const conn = pool.connections.get('http://localhost:9201/')
|
|
||||||
t.strictEqual(conn.url.username, 'foo')
|
|
||||||
t.strictEqual(conn.url.password, 'bar')
|
|
||||||
t.strictEqual(conn.auth.username, 'foo')
|
|
||||||
t.strictEqual(conn.auth.password, 'bar')
|
|
||||||
t.end()
|
|
||||||
})
|
|
||||||
|
|
||||||
t.test('addConnection should handle not-friendly url parameters for user and password', t => {
|
t.test('addConnection should handle not-friendly url parameters for user and password', t => {
|
||||||
const pool = new ConnectionPool({ Connection })
|
const pool = new ConnectionPool({ Connection })
|
||||||
const href = 'http://us"er:p@assword@localhost:9200/'
|
const href = 'http://us"er:p@assword@localhost:9200/'
|
||||||
@ -76,8 +57,9 @@ test('API', t => {
|
|||||||
const conn = pool.getConnection()
|
const conn = pool.getConnection()
|
||||||
t.strictEqual(conn.url.username, 'us%22er')
|
t.strictEqual(conn.url.username, 'us%22er')
|
||||||
t.strictEqual(conn.url.password, 'p%40assword')
|
t.strictEqual(conn.url.password, 'p%40assword')
|
||||||
t.strictEqual(conn.auth.username, 'us"er')
|
t.match(conn.headers, {
|
||||||
t.strictEqual(conn.auth.password, 'p@assword')
|
authorization: 'Basic ' + Buffer.from('us"er:p@assword').toString('base64')
|
||||||
|
})
|
||||||
t.end()
|
t.end()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@ -811,6 +811,53 @@ test('Port handling', t => {
|
|||||||
t.end()
|
t.end()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
test('Authorization header', t => {
|
||||||
|
t.test('None', t => {
|
||||||
|
const connection = new Connection({
|
||||||
|
url: new URL('http://localhost:9200')
|
||||||
|
})
|
||||||
|
|
||||||
|
t.deepEqual(connection.headers, {})
|
||||||
|
|
||||||
|
t.end()
|
||||||
|
})
|
||||||
|
|
||||||
|
t.test('Basic', t => {
|
||||||
|
const connection = new Connection({
|
||||||
|
url: new URL('http://localhost:9200'),
|
||||||
|
auth: { username: 'foo', password: 'bar' }
|
||||||
|
})
|
||||||
|
|
||||||
|
t.deepEqual(connection.headers, { authorization: 'Basic Zm9vOmJhcg==' })
|
||||||
|
|
||||||
|
t.end()
|
||||||
|
})
|
||||||
|
|
||||||
|
t.test('ApiKey (string)', t => {
|
||||||
|
const connection = new Connection({
|
||||||
|
url: new URL('http://localhost:9200'),
|
||||||
|
auth: { apiKey: 'Zm9vOmJhcg==' }
|
||||||
|
})
|
||||||
|
|
||||||
|
t.deepEqual(connection.headers, { authorization: 'ApiKey Zm9vOmJhcg==' })
|
||||||
|
|
||||||
|
t.end()
|
||||||
|
})
|
||||||
|
|
||||||
|
t.test('ApiKey (object)', t => {
|
||||||
|
const connection = new Connection({
|
||||||
|
url: new URL('http://localhost:9200'),
|
||||||
|
auth: { apiKey: { id: 'foo', api_key: 'bar' } }
|
||||||
|
})
|
||||||
|
|
||||||
|
t.deepEqual(connection.headers, { authorization: 'ApiKey Zm9vOmJhcg==' })
|
||||||
|
|
||||||
|
t.end()
|
||||||
|
})
|
||||||
|
|
||||||
|
t.end()
|
||||||
|
})
|
||||||
|
|
||||||
test('Should not add agent and ssl to the serialized connection', t => {
|
test('Should not add agent and ssl to the serialized connection', t => {
|
||||||
const connection = new Connection({
|
const connection = new Connection({
|
||||||
url: new URL('http://localhost:9200')
|
url: new URL('http://localhost:9200')
|
||||||
@ -818,7 +865,7 @@ test('Should not add agent and ssl to the serialized connection', t => {
|
|||||||
|
|
||||||
t.strictEqual(
|
t.strictEqual(
|
||||||
JSON.stringify(connection),
|
JSON.stringify(connection),
|
||||||
'{"url":"http://localhost:9200/","id":"http://localhost:9200/","headers":null,"deadCount":0,"resurrectTimeout":0,"_openRequests":0,"status":"alive","roles":{"master":true,"data":true,"ingest":true,"ml":false}}'
|
'{"url":"http://localhost:9200/","id":"http://localhost:9200/","headers":{},"deadCount":0,"resurrectTimeout":0,"_openRequests":0,"status":"alive","roles":{"master":true,"data":true,"ingest":true,"ml":false}}'
|
||||||
)
|
)
|
||||||
|
|
||||||
t.end()
|
t.end()
|
||||||
|
|||||||
Reference in New Issue
Block a user