Improve authentication handling (#908)
This commit is contained in:
committed by
GitHub
parent
24e674469e
commit
0ebbd71e9a
@ -198,63 +198,293 @@ test('Configure host', t => {
|
||||
t.end()
|
||||
})
|
||||
|
||||
test('Node with auth data in the url', t => {
|
||||
t.plan(3)
|
||||
test('Authentication', t => {
|
||||
t.test('Basic', t => {
|
||||
t.test('Node with basic auth data in the url', 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://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'
|
||||
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' }))
|
||||
}
|
||||
}, (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()
|
||||
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()
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
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 => {
|
||||
@ -554,6 +784,45 @@ test('Elastic cloud config', t => {
|
||||
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' },
|
||||
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' },
|
||||
deadCount: 0,
|
||||
resurrectTimeout: 0,
|
||||
|
||||
@ -50,25 +50,6 @@ test('API', t => {
|
||||
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 => {
|
||||
const pool = new ConnectionPool({ Connection })
|
||||
const href = 'http://us"er:p@assword@localhost:9200/'
|
||||
@ -76,8 +57,9 @@ test('API', t => {
|
||||
const conn = pool.getConnection()
|
||||
t.strictEqual(conn.url.username, 'us%22er')
|
||||
t.strictEqual(conn.url.password, 'p%40assword')
|
||||
t.strictEqual(conn.auth.username, 'us"er')
|
||||
t.strictEqual(conn.auth.password, 'p@assword')
|
||||
t.match(conn.headers, {
|
||||
authorization: 'Basic ' + Buffer.from('us"er:p@assword').toString('base64')
|
||||
})
|
||||
t.end()
|
||||
})
|
||||
|
||||
|
||||
@ -811,6 +811,53 @@ test('Port handling', t => {
|
||||
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 => {
|
||||
const connection = new Connection({
|
||||
url: new URL('http://localhost:9200')
|
||||
@ -818,7 +865,7 @@ test('Should not add agent and ssl to the serialized connection', t => {
|
||||
|
||||
t.strictEqual(
|
||||
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()
|
||||
|
||||
Reference in New Issue
Block a user