Convert axios auth to basic auth header in the sub actions framework

This commit is contained in:
Christos Nasikas 2024-05-10 19:06:41 +03:00
parent 7d9edabd6e
commit ee27353051
3 changed files with 70 additions and 4 deletions

View file

@ -78,6 +78,18 @@ export class TestSubActionConnector extends SubActionConnector<TestConfig, TestS
return res;
}
public async testAuth({ headers }: { headers?: Record<string, unknown> } = {}) {
const res = await this.request({
url: 'https://example.com',
data: {},
auth: { username: 'username', password: 'password' },
headers: { 'X-Test-Header': 'test', ...headers },
responseSchema: schema.object({ status: schema.string() }),
});
return res;
}
}
export class TestNoSubActions extends SubActionConnector<TestConfig, TestSecrets> {

View file

@ -210,5 +210,43 @@ describe('SubActionConnector', () => {
'Request to external service failed. Connector Id: test-id. Connector type: .test. Method: get. URL: https://example.com'
);
});
it('converts auth axios property to a basic auth header if provided', async () => {
await service.testAuth();
expect(requestMock).toHaveBeenCalledTimes(1);
expect(requestMock).toBeCalledWith({
axios: axiosInstanceMock,
configurationUtilities: mockedActionsConfig,
logger,
method: 'get',
data: {},
headers: {
'Content-Type': 'application/json',
'X-Test-Header': 'test',
Authorization: `Basic ${Buffer.from('username:password').toString('base64')}`,
},
url: 'https://example.com',
});
});
it('does not override an authorization header if provided', async () => {
await service.testAuth({ headers: { Authorization: 'Bearer my_token' } });
expect(requestMock).toHaveBeenCalledTimes(1);
expect(requestMock).toBeCalledWith({
axios: axiosInstanceMock,
configurationUtilities: mockedActionsConfig,
logger,
method: 'get',
data: {},
headers: {
'Content-Type': 'application/json',
'X-Test-Header': 'test',
Authorization: 'Bearer my_token',
},
url: 'https://example.com',
});
});
});
});

View file

@ -15,6 +15,7 @@ import axios, {
AxiosRequestHeaders,
AxiosHeaders,
AxiosHeaderValue,
AxiosBasicCredentials,
} from 'axios';
import { SavedObjectsClientContract } from '@kbn/core-saved-objects-api-server';
import { ElasticsearchClient } from '@kbn/core-elasticsearch-server';
@ -87,8 +88,21 @@ export abstract class SubActionConnector<Config, Secrets> {
}
}
private getHeaders(headers?: AxiosRequestHeaders): Record<string, AxiosHeaderValue> {
return { 'Content-Type': 'application/json', ...headers };
private getHeaders(
auth?: AxiosBasicCredentials,
headers?: AxiosRequestHeaders
): Record<string, AxiosHeaderValue> {
const headersWithBasicAuth =
auth != null
? {
Authorization: `Basic ${Buffer.from(`${auth.username}:${auth.password}`).toString(
'base64'
)}`,
...headers,
}
: headers;
return { 'Content-Type': 'application/json', ...headersWithBasicAuth };
}
private validateResponse(responseSchema: Type<unknown>, data: unknown) {
@ -137,15 +151,17 @@ export abstract class SubActionConnector<Config, Secrets> {
`Request to external service. Connector Id: ${this.connector.id}. Connector type: ${this.connector.type} Method: ${method}. URL: ${normalizedURL}`
);
const { auth, ...restConfig } = config;
const res = await request({
...config,
...restConfig,
axios: this.axiosInstance,
url: normalizedURL,
logger: this.logger,
method,
data: this.normalizeData(data),
configurationUtilities: this.configurationUtilities,
headers: this.getHeaders(headers as AxiosHeaders),
headers: this.getHeaders(auth, headers as AxiosHeaders),
timeout,
});