diff --git a/packages/core/src/execution-engine/node-execution-context/utils/__tests__/request-helper-functions.test.ts b/packages/core/src/execution-engine/node-execution-context/utils/__tests__/request-helper-functions.test.ts index 1f60ad1943ff2..2310227f20ebc 100644 --- a/packages/core/src/execution-engine/node-execution-context/utils/__tests__/request-helper-functions.test.ts +++ b/packages/core/src/execution-engine/node-execution-context/utils/__tests__/request-helper-functions.test.ts @@ -31,6 +31,8 @@ import { requestOAuth2, } from '../request-helper-functions'; +const TEST_CA_CERT = '-----BEGIN CERTIFICATE-----\nTEST\n-----END CERTIFICATE-----'; + describe('Request Helper Functions', () => { describe('proxyRequestToAxios', () => { const baseUrl = 'https://example.de'; @@ -447,7 +449,7 @@ describe('Request Helper Functions', () => { describe('should set SSL certificates', () => { const agentOptions: SecureContextOptions = { - ca: '-----BEGIN CERTIFICATE-----\nTEST\n-----END CERTIFICATE-----', + ca: TEST_CA_CERT, }; const requestObject: IRequestOptions = { method: 'GET', @@ -644,6 +646,36 @@ describe('Request Helper Functions', () => { expect(axiosConfig.validateStatus!(401)).toBe(true); expect(axiosConfig.validateStatus!(500)).toBe(true); }); + + test('should pass agentOptions through to the https agent', () => { + const requestOptions: IHttpRequestOptions = { + method: 'GET', + url: 'https://example.com', + agentOptions: { + ca: TEST_CA_CERT, + }, + }; + + const axiosConfig = convertN8nRequestToAxios(requestOptions); + + expect((axiosConfig.httpsAgent as HttpsAgent).options.ca).toBe(TEST_CA_CERT); + }); + + test('should merge agentOptions with skipSslCertificateValidation', () => { + const requestOptions: IHttpRequestOptions = { + method: 'GET', + url: 'https://example.com', + skipSslCertificateValidation: true, + agentOptions: { + ca: TEST_CA_CERT, + }, + }; + + const axiosConfig = convertN8nRequestToAxios(requestOptions); + + expect((axiosConfig.httpsAgent as HttpsAgent).options.rejectUnauthorized).toBe(false); + expect((axiosConfig.httpsAgent as HttpsAgent).options.ca).toBe(TEST_CA_CERT); + }); }); describe('applyPaginationRequestData', () => { diff --git a/packages/core/src/execution-engine/node-execution-context/utils/request-helper-functions.ts b/packages/core/src/execution-engine/node-execution-context/utils/request-helper-functions.ts index 2f33ffada219a..944447e8f31c9 100644 --- a/packages/core/src/execution-engine/node-execution-context/utils/request-helper-functions.ts +++ b/packages/core/src/execution-engine/node-execution-context/utils/request-helper-functions.ts @@ -541,7 +541,7 @@ export function convertN8nRequestToAxios( } const host = getHostFromRequestObject(n8nRequest); - const agentOptions: AgentOptions = {}; + const agentOptions: AgentOptions = { ...n8nRequest.agentOptions }; if (host) { agentOptions.servername = host; } diff --git a/packages/workflow/src/interfaces.ts b/packages/workflow/src/interfaces.ts index 15c6b0d7b7381..a7b14859c5ec7 100644 --- a/packages/workflow/src/interfaces.ts +++ b/packages/workflow/src/interfaces.ts @@ -6,6 +6,7 @@ import type * as express from 'express'; import type FormData from 'form-data'; import type { PathLike } from 'fs'; import type { IncomingHttpHeaders } from 'http'; +import type { AgentOptions } from 'https'; import type { ReplyHeaders, RequestBodyMatcher, RequestHeaderMatcher } from 'nock'; import type { Client as SSHClient } from 'ssh2'; import type { Readable } from 'stream'; @@ -514,6 +515,7 @@ export interface IHttpRequestOptions { * If set, requests to domains not in this list will be blocked. */ allowedDomains?: string; + agentOptions?: Omit; } /**