Skip to content

Commit

Permalink
Allow overwriting the Authorization header. (#488)
Browse files Browse the repository at this point in the history
Signed-off-by: dblock <[email protected]>
  • Loading branch information
dblock authored Aug 11, 2024
1 parent 56a5a22 commit 00711ea
Show file tree
Hide file tree
Showing 4 changed files with 98 additions and 34 deletions.
49 changes: 49 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
"@types/titlecase": "^1.1.2",
"@types/tmp": "^0.2.6",
"@typescript-eslint/eslint-plugin": "^6.21.0",
"axios-mock-adapter": "^2.0.0",
"ajv": "^8.13.0",
"ajv-errors": "^3.0.0",
"ajv-formats": "^3.0.1",
Expand Down
20 changes: 12 additions & 8 deletions tools/src/OpenSearchHttpClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -133,18 +133,23 @@ export class OpenSearchHttpClient {
this._opts = opts
this._logger = opts?.logger ?? new Logger()

let auth = undefined
let sigv4_interceptor = undefined
let auth_middleware = undefined

if (opts?.basic_auth !== undefined) {
this._logger.info(`Authenticating with ${opts.basic_auth.username} ...`)
auth = opts.basic_auth
auth_middleware = ((request: any): any => {
if (request.headers.Authorization === undefined) {
const base64 = Buffer.from(`${opts.basic_auth?.username}:${opts.basic_auth?.password}`, 'utf8').toString('base64');
request.headers.Authorization = `Basic ${base64}`
}
return request
})
} else if (opts?.aws_auth !== undefined) {
this._logger.info(`Authenticating using SigV4 with ${opts.aws_auth.aws_access_key_id} (${opts.aws_auth.aws_region}) ...`)
sigv4_interceptor = aws4Interceptor({
auth_middleware = aws4Interceptor({
options: {
region: opts.aws_auth.aws_region,
service: 'es'
service: opts.aws_auth.aws_service
},
credentials: {
accessKeyId: opts.aws_auth.aws_access_key_id,
Expand All @@ -158,13 +163,12 @@ export class OpenSearchHttpClient {

this._axios = axios.create({
baseURL: opts?.url ?? DEFAULT_URL,
auth,
httpsAgent: new https.Agent({ rejectUnauthorized: !(opts?.insecure ?? DEFAULT_INSECURE) }),
responseType: opts?.responseType,
})

if (sigv4_interceptor !== undefined) {
this._axios.interceptors.request.use(sigv4_interceptor)
if (auth_middleware !== undefined) {
this._axios.interceptors.request.use(auth_middleware)
}
}

Expand Down
62 changes: 36 additions & 26 deletions tools/tests/tester/OpenSearchHttpClient.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,58 +9,68 @@

import axios from "axios";
import { OpenSearchHttpClient } from "OpenSearchHttpClient"

jest.mock('axios')
import AxiosMockAdapter from "axios-mock-adapter";

describe('OpenSearchHttpClient', () => {
let mocked_axios: jest.Mocked<typeof axios> = axios as jest.Mocked<typeof axios>
var mock = new AxiosMockAdapter(axios)

beforeEach(() => {
mocked_axios.create.mockReturnThis()
mocked_axios.interceptors.request.use = jest.fn().mockReturnValue({ headers: {} })
afterEach(() => {
mock.reset()
})

afterEach(() => {
jest.clearAllMocks()
it('adds a Basic auth header', async () => {
let client = new OpenSearchHttpClient({
url: 'https://localhost:9200',
basic_auth: {
username: 'u',
password: 'p'
}
})

mock.onAny().reply((config) => {
expect(config.headers?.Authorization).toMatch(/^Basic /)
return [200, { called: true }]
})

expect((await client.get('/')).data).toEqual({ called: true })
})

it('uses password authentication', () => {
new OpenSearchHttpClient({
it('allows to overwrite Authorization', async () => {
let client = new OpenSearchHttpClient({
url: 'https://localhost:9200',
basic_auth: {
username: 'admin',
password: 'password'
username: 'u',
password: 'p'
}
})

expect(mocked_axios.create.mock.calls[0][0]).toMatchObject({
auth: {
username: 'admin',
password: 'password'
},
baseURL: 'https://localhost:9200'
mock.onAny().reply((config) => {
expect(config.headers?.Authorization).toEqual('custom')
return [200, { called: true }]
})

expect(mocked_axios.interceptors.request.use).not.toHaveBeenCalled()
expect((await client.get('/', { headers: { Authorization: 'custom' } })).data).toEqual({ called: true })
})

it('assigns a request interceptor with SigV4 authentication', () => {
new OpenSearchHttpClient({
it('adds a Sigv4 header', async () => {
let client = new OpenSearchHttpClient({
url: 'https://localhost:9200',
aws_auth: {
aws_access_key_id: 'key id',
aws_access_secret_key: 'secret key',
aws_access_session_token: 'session token',
aws_region: 'us-west-2',
aws_region: 'us-west-42',
aws_service: 'aoss'
}
})

expect(mocked_axios.create.mock.calls[0][0]).toMatchObject({
auth: undefined,
baseURL: 'https://localhost:9200'
mock.onAny().reply((config) => {
expect(config.headers?.Authorization).toMatch(
/^AWS4-HMAC-SHA256 Credential=key id\/\d*\/us-west-42\/aoss\/aws4_request/
)
return [200, { called: true }]
})

expect(mocked_axios.interceptors.request.use).toHaveBeenCalled()
expect((await client.get('/')).data).toEqual({ called: true })
})
})

0 comments on commit 00711ea

Please sign in to comment.