From a346e35cc1c9b7c7e2333bcba5bd76d77f441baa Mon Sep 17 00:00:00 2001 From: Tim Roes Date: Tue, 6 Mar 2018 18:02:43 -0800 Subject: [PATCH] Make plugin installer proxy work for HTTPS (#15588) --- package.json | 1 + src/cli_plugin/install/__tests__/download.js | 25 +++++++++++++++++++- src/cli_plugin/install/downloaders/http.js | 8 ++++++- 3 files changed, 32 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index a62eab5c37306..cf06568a40305 100644 --- a/package.json +++ b/package.json @@ -133,6 +133,7 @@ "hapi": "14.2.0", "hjson": "3.1.0", "http-proxy-agent": "1.0.0", + "https-proxy-agent": "2.1.1", "imports-loader": "0.7.1", "inert": "4.0.2", "jade": "1.11.0", diff --git a/src/cli_plugin/install/__tests__/download.js b/src/cli_plugin/install/__tests__/download.js index 8c738acfa1bb0..b39fdce7e6183 100644 --- a/src/cli_plugin/install/__tests__/download.js +++ b/src/cli_plugin/install/__tests__/download.js @@ -264,6 +264,7 @@ describe('kibana cli', function () { const proxyUrl = `http://localhost:${proxyPort}`; let proxyHit = false; + let proxyConnectHit = false; const proxy = http.createServer(function (req, res) { proxyHit = true; @@ -273,12 +274,26 @@ describe('kibana cli', function () { res.end(); }); + proxy.on('connect', (req, socket) => { + // When the proxy is hit with a HTTPS request instead of a HTTP request, + // the above call handler will never be triggered. Instead the client + // sends a CONNECT request to the proxy, so that the proxy can setup + // a HTTPS connection between the client and the upstream server. + // We just intercept this CONNECT call here, write it an empty response + // and close the socket, which will fail the actual request, but we know + // that it tried to use the proxy. + proxyConnectHit = true; + socket.write('\r\n\r\n'); + socket.end(); + }); + function expectProxyHit() { expect(proxyHit).to.be(true); } function expectNoProxyHit() { expect(proxyHit).to.be(false); + expect(proxyConnectHit).to.be(false); } function nockPluginForUrl(url) { @@ -293,6 +308,7 @@ describe('kibana cli', function () { beforeEach(function () { proxyHit = false; + proxyConnectHit = false; }); afterEach(function () { @@ -314,7 +330,14 @@ describe('kibana cli', function () { settings.urls = ['https://example.com/plugin.zip']; return download(settings, logger) - .then(expectProxyHit); + .then(() => { + // If the proxy is hit, the request should fail, since our test proxy + // doesn't actually forward HTTPS requests. + expect().fail('Should not succeed a HTTPS proxy request.'); + }, () => { + // Check if the proxy was actually hit before the failure. + expect(proxyConnectHit).to.be(true); + }); }); it('should not use http_proxy for HTTPS urls', function () { diff --git a/src/cli_plugin/install/downloaders/http.js b/src/cli_plugin/install/downloaders/http.js index 6ce760de44516..acd02e81f455b 100644 --- a/src/cli_plugin/install/downloaders/http.js +++ b/src/cli_plugin/install/downloaders/http.js @@ -3,6 +3,7 @@ import Progress from '../progress'; import { fromNode as fn } from 'bluebird'; import { createWriteStream } from 'fs'; import HttpProxyAgent from 'http-proxy-agent'; +import HttpsProxyAgent from 'https-proxy-agent'; import { getProxyForUrl } from 'proxy-from-env'; function getProxyAgent(sourceUrl, logger) { @@ -13,7 +14,12 @@ function getProxyAgent(sourceUrl, logger) { } logger.log(`Picked up proxy ${proxy} from environment variable.`); - return new HttpProxyAgent(proxy); + + if (/^https/.test(sourceUrl)) { + return new HttpsProxyAgent(proxy); + } else { + return new HttpProxyAgent(proxy); + } } function sendRequest({ sourceUrl, timeout }, logger) {