fix(client-certificates): keep ignoreHTTPSErrors false by default (#31760)
This commit is contained in:
parent
6dbc7b54e8
commit
708def8804
|
|
@ -26,7 +26,7 @@ import zlib from 'zlib';
|
||||||
import type { HTTPCredentials } from '../../types/types';
|
import type { HTTPCredentials } from '../../types/types';
|
||||||
import { TimeoutSettings } from '../common/timeoutSettings';
|
import { TimeoutSettings } from '../common/timeoutSettings';
|
||||||
import { getUserAgent } from '../utils/userAgent';
|
import { getUserAgent } from '../utils/userAgent';
|
||||||
import { assert, createGuid, monotonicTime } from '../utils';
|
import { assert, createGuid, isUnderTest, monotonicTime } from '../utils';
|
||||||
import { HttpsProxyAgent, SocksProxyAgent } from '../utilsBundle';
|
import { HttpsProxyAgent, SocksProxyAgent } from '../utilsBundle';
|
||||||
import { BrowserContext, verifyClientCertificates } from './browserContext';
|
import { BrowserContext, verifyClientCertificates } from './browserContext';
|
||||||
import { CookieStore, domainMatches } from './cookieStore';
|
import { CookieStore, domainMatches } from './cookieStore';
|
||||||
|
|
@ -196,7 +196,7 @@ export abstract class APIRequestContext extends SdkObject {
|
||||||
...clientCertificatesToTLSOptions(this._defaultOptions().clientCertificates, requestUrl.toString()),
|
...clientCertificatesToTLSOptions(this._defaultOptions().clientCertificates, requestUrl.toString()),
|
||||||
__testHookLookup: (params as any).__testHookLookup,
|
__testHookLookup: (params as any).__testHookLookup,
|
||||||
};
|
};
|
||||||
if (process.env.PWTEST_UNSUPPORTED_CUSTOM_CA)
|
if (process.env.PWTEST_UNSUPPORTED_CUSTOM_CA && isUnderTest())
|
||||||
options.ca = [fs.readFileSync(process.env.PWTEST_UNSUPPORTED_CUSTOM_CA)];
|
options.ca = [fs.readFileSync(process.env.PWTEST_UNSUPPORTED_CUSTOM_CA)];
|
||||||
// rejectUnauthorized = undefined is treated as true in Node.js 12.
|
// rejectUnauthorized = undefined is treated as true in Node.js 12.
|
||||||
if (params.ignoreHTTPSErrors || defaults.ignoreHTTPSErrors)
|
if (params.ignoreHTTPSErrors || defaults.ignoreHTTPSErrors)
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,7 @@ import fs from 'fs';
|
||||||
import tls from 'tls';
|
import tls from 'tls';
|
||||||
import stream from 'stream';
|
import stream from 'stream';
|
||||||
import { createSocket } from '../utils/happy-eyeballs';
|
import { createSocket } from '../utils/happy-eyeballs';
|
||||||
import { globToRegex } from '../utils';
|
import { globToRegex, isUnderTest } from '../utils';
|
||||||
import type { SocksSocketClosedPayload, SocksSocketDataPayload, SocksSocketRequestedPayload } from '../common/socksProxy';
|
import type { SocksSocketClosedPayload, SocksSocketDataPayload, SocksSocketRequestedPayload } from '../common/socksProxy';
|
||||||
import { SocksProxy } from '../common/socksProxy';
|
import { SocksProxy } from '../common/socksProxy';
|
||||||
import type * as channels from '@protocol/channels';
|
import type * as channels from '@protocol/channels';
|
||||||
|
|
@ -98,11 +98,14 @@ class SocksProxyConnection {
|
||||||
this.internalTLS = internalTLS;
|
this.internalTLS = internalTLS;
|
||||||
internalTLS.on('close', () => this.socksProxy._socksProxy.sendSocketEnd({ uid: this.uid }));
|
internalTLS.on('close', () => this.socksProxy._socksProxy.sendSocketEnd({ uid: this.uid }));
|
||||||
|
|
||||||
const targetTLS = tls.connect({
|
const tlsOptions: tls.ConnectionOptions = {
|
||||||
socket: this.target,
|
socket: this.target,
|
||||||
rejectUnauthorized: this.socksProxy.contextOptions.ignoreHTTPSErrors === true ? false : true,
|
rejectUnauthorized: !this.socksProxy.ignoreHTTPSErrors,
|
||||||
...clientCertificatesToTLSOptions(this.socksProxy.contextOptions.clientCertificates, `https://${this.host}:${this.port}/`),
|
...clientCertificatesToTLSOptions(this.socksProxy.clientCertificates, `https://${this.host}:${this.port}/`),
|
||||||
});
|
};
|
||||||
|
if (process.env.PWTEST_UNSUPPORTED_CUSTOM_CA && isUnderTest())
|
||||||
|
tlsOptions.ca = [fs.readFileSync(process.env.PWTEST_UNSUPPORTED_CUSTOM_CA)];
|
||||||
|
const targetTLS = tls.connect(tlsOptions);
|
||||||
|
|
||||||
internalTLS.pipe(targetTLS);
|
internalTLS.pipe(targetTLS);
|
||||||
targetTLS.pipe(internalTLS);
|
targetTLS.pipe(internalTLS);
|
||||||
|
|
@ -118,13 +121,14 @@ class SocksProxyConnection {
|
||||||
|
|
||||||
internalTLS.on('error', () => closeBothSockets());
|
internalTLS.on('error', () => closeBothSockets());
|
||||||
targetTLS.on('error', error => {
|
targetTLS.on('error', error => {
|
||||||
internalTLS.write('HTTP/1.1 503 Internal Server Error\r\n');
|
|
||||||
internalTLS.write('Content-Type: text/html; charset=utf-8\r\n');
|
|
||||||
const responseBody = 'Playwright client-certificate error: ' + error.message;
|
const responseBody = 'Playwright client-certificate error: ' + error.message;
|
||||||
internalTLS.write('Content-Length: ' + Buffer.byteLength(responseBody) + '\r\n');
|
internalTLS.end([
|
||||||
internalTLS.write('\r\n');
|
'HTTP/1.1 503 Internal Server Error',
|
||||||
internalTLS.write(responseBody);
|
'Content-Type: text/html; charset=utf-8',
|
||||||
internalTLS.end();
|
'Content-Length: ' + Buffer.byteLength(responseBody),
|
||||||
|
'\r\n',
|
||||||
|
responseBody,
|
||||||
|
].join('\r\n'));
|
||||||
closeBothSockets();
|
closeBothSockets();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
@ -133,10 +137,14 @@ class SocksProxyConnection {
|
||||||
export class ClientCertificatesProxy {
|
export class ClientCertificatesProxy {
|
||||||
_socksProxy: SocksProxy;
|
_socksProxy: SocksProxy;
|
||||||
private _connections: Map<string, SocksProxyConnection> = new Map();
|
private _connections: Map<string, SocksProxyConnection> = new Map();
|
||||||
|
ignoreHTTPSErrors: boolean | undefined;
|
||||||
|
clientCertificates: channels.BrowserNewContextOptions['clientCertificates'];
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
public readonly contextOptions: Pick<channels.BrowserNewContextOptions, 'clientCertificates' | 'ignoreHTTPSErrors'>
|
contextOptions: Pick<channels.BrowserNewContextOptions, 'clientCertificates' | 'ignoreHTTPSErrors'>
|
||||||
) {
|
) {
|
||||||
|
this.ignoreHTTPSErrors = contextOptions.ignoreHTTPSErrors;
|
||||||
|
this.clientCertificates = contextOptions.clientCertificates;
|
||||||
this._socksProxy = new SocksProxy();
|
this._socksProxy = new SocksProxy();
|
||||||
this._socksProxy.setPattern('*');
|
this._socksProxy.setPattern('*');
|
||||||
this._socksProxy.addListener(SocksProxy.Events.SocksRequested, async (payload: SocksSocketRequestedPayload) => {
|
this._socksProxy.addListener(SocksProxy.Events.SocksRequested, async (payload: SocksSocketRequestedPayload) => {
|
||||||
|
|
|
||||||
|
|
@ -249,6 +249,21 @@ test.describe('browser', () => {
|
||||||
await page.close();
|
await page.close();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('should have ignoreHTTPSErrors=false by default', async ({ browser, httpsServer, asset }) => {
|
||||||
|
const page = await browser.newPage({
|
||||||
|
clientCertificates: [{
|
||||||
|
url: 'https://just-there-that-the-client-certificates-proxy-server-is-getting-launched.com',
|
||||||
|
certs: [{
|
||||||
|
certPath: asset('client-certificates/client/trusted/cert.pem'),
|
||||||
|
keyPath: asset('client-certificates/client/trusted/key.pem'),
|
||||||
|
}],
|
||||||
|
}],
|
||||||
|
});
|
||||||
|
await page.goto(httpsServer.EMPTY_PAGE);
|
||||||
|
await expect(page.getByText('Playwright client-certificate error')).toBeVisible();
|
||||||
|
await page.close();
|
||||||
|
});
|
||||||
|
|
||||||
test.describe('persistentContext', () => {
|
test.describe('persistentContext', () => {
|
||||||
test('validate input', async ({ launchPersistent }) => {
|
test('validate input', async ({ launchPersistent }) => {
|
||||||
test.slow();
|
test.slow();
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue