From 06efeffdb8fc5662c1543f9c91940ca5da544c22 Mon Sep 17 00:00:00 2001 From: Zach Bloomquist Date: Thu, 9 Jan 2020 10:23:25 -0500 Subject: [PATCH 1/4] allow e2e tests to pass https options --- packages/https-proxy/lib/proxy.coffee | 4 ++-- packages/https-proxy/test/helpers/https_server.coffee | 5 +++-- packages/server/test/support/helpers/e2e.js | 4 ++-- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/packages/https-proxy/lib/proxy.coffee b/packages/https-proxy/lib/proxy.coffee index 4ecfd4f99d..ed2fa19143 100644 --- a/packages/https-proxy/lib/proxy.coffee +++ b/packages/https-proxy/lib/proxy.coffee @@ -10,7 +10,7 @@ module.exports = { reset: -> Server.reset() - httpsServer: (onRequest) -> - require("../test/helpers/https_server").create(onRequest) + httpsServer: (onRequest, options) -> + require("../test/helpers/https_server").create(onRequest, options) } diff --git a/packages/https-proxy/test/helpers/https_server.coffee b/packages/https-proxy/test/helpers/https_server.coffee index c148cfb7a4..65ca08e252 100644 --- a/packages/https-proxy/test/helpers/https_server.coffee +++ b/packages/https-proxy/test/helpers/https_server.coffee @@ -1,3 +1,4 @@ +_ = require('lodash') https = require("https") Promise = require("bluebird") { allowDestroy } = require("@packages/network") @@ -13,8 +14,8 @@ defaultOnRequest = (req, res) -> servers = [] -create = (onRequest) -> - https.createServer(certs, onRequest ? defaultOnRequest) +create = (onRequest, options) -> + https.createServer(_.merge({}, certs, options), onRequest ? defaultOnRequest) module.exports = { create diff --git a/packages/server/test/support/helpers/e2e.js b/packages/server/test/support/helpers/e2e.js index c161cb1098..a4926f96ad 100644 --- a/packages/server/test/support/helpers/e2e.js +++ b/packages/server/test/support/helpers/e2e.js @@ -151,14 +151,14 @@ const ensurePort = function (port) { const startServer = function (obj) { let s; let srv - const { onServer, port, https } = obj + const { onServer, port, https, httpsOptions } = obj ensurePort(port) const app = express() if (https) { - srv = httpsProxy.httpsServer(app) + srv = httpsProxy.httpsServer(app, httpsOptions) } else { srv = http.Server(app) } From f4e3b12541f4089c721110f8a83557fdb7756f13 Mon Sep 17 00:00:00 2001 From: Zach Bloomquist Date: Thu, 9 Jan 2020 10:29:18 -0500 Subject: [PATCH 2/4] Revert "allow e2e tests to pass https options" This reverts commit 06efeffdb8fc5662c1543f9c91940ca5da544c22. --- packages/https-proxy/lib/proxy.coffee | 4 ++-- packages/https-proxy/test/helpers/https_server.coffee | 5 ++--- packages/server/test/support/helpers/e2e.js | 4 ++-- 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/packages/https-proxy/lib/proxy.coffee b/packages/https-proxy/lib/proxy.coffee index ed2fa19143..4ecfd4f99d 100644 --- a/packages/https-proxy/lib/proxy.coffee +++ b/packages/https-proxy/lib/proxy.coffee @@ -10,7 +10,7 @@ module.exports = { reset: -> Server.reset() - httpsServer: (onRequest, options) -> - require("../test/helpers/https_server").create(onRequest, options) + httpsServer: (onRequest) -> + require("../test/helpers/https_server").create(onRequest) } diff --git a/packages/https-proxy/test/helpers/https_server.coffee b/packages/https-proxy/test/helpers/https_server.coffee index 65ca08e252..c148cfb7a4 100644 --- a/packages/https-proxy/test/helpers/https_server.coffee +++ b/packages/https-proxy/test/helpers/https_server.coffee @@ -1,4 +1,3 @@ -_ = require('lodash') https = require("https") Promise = require("bluebird") { allowDestroy } = require("@packages/network") @@ -14,8 +13,8 @@ defaultOnRequest = (req, res) -> servers = [] -create = (onRequest, options) -> - https.createServer(_.merge({}, certs, options), onRequest ? defaultOnRequest) +create = (onRequest) -> + https.createServer(certs, onRequest ? defaultOnRequest) module.exports = { create diff --git a/packages/server/test/support/helpers/e2e.js b/packages/server/test/support/helpers/e2e.js index a4926f96ad..c161cb1098 100644 --- a/packages/server/test/support/helpers/e2e.js +++ b/packages/server/test/support/helpers/e2e.js @@ -151,14 +151,14 @@ const ensurePort = function (port) { const startServer = function (obj) { let s; let srv - const { onServer, port, https, httpsOptions } = obj + const { onServer, port, https } = obj ensurePort(port) const app = express() if (https) { - srv = httpsProxy.httpsServer(app, httpsOptions) + srv = httpsProxy.httpsServer(app) } else { srv = http.Server(app) } From 79bdca0c5305bd20750980d69c5fa761acf3c2e6 Mon Sep 17 00:00:00 2001 From: Zach Bloomquist Date: Thu, 9 Jan 2020 11:00:05 -0500 Subject: [PATCH 3/4] add test for #5446 --- .../__snapshots__/6_visit_spec.coffee.js | 11 +++---- packages/server/package.json | 1 + packages/server/test/e2e/6_visit_spec.coffee | 29 +++++++++++++++++++ .../e2e/cypress/integration/visit_spec.coffee | 4 +++ 4 files changed, 40 insertions(+), 5 deletions(-) diff --git a/packages/server/__snapshots__/6_visit_spec.coffee.js b/packages/server/__snapshots__/6_visit_spec.coffee.js index f795ab00ec..50383bce5e 100644 --- a/packages/server/__snapshots__/6_visit_spec.coffee.js +++ b/packages/server/__snapshots__/6_visit_spec.coffee.js @@ -21,6 +21,7 @@ exports['e2e visit / low response timeout / passes'] = ` ✓ scrolls automatically to div with id=foo ✓ can load an http page with a huge amount of elements without timing out ✓ can load a local file with a huge amount of elements without timing out + ✓ can load a site via TLSv1 issue #225: hash urls ✓ can visit a hash url and loads ✓ can visit the same hash url and loads @@ -35,14 +36,14 @@ exports['e2e visit / low response timeout / passes'] = ` ✓ sets accept header to text/html,*/* - 11 passing + 12 passing (Results) ┌────────────────────────────────────────────────────────────────────────────────────────────────┐ - │ Tests: 11 │ - │ Passing: 11 │ + │ Tests: 12 │ + │ Passing: 12 │ │ Failing: 0 │ │ Pending: 0 │ │ Skipped: 0 │ @@ -66,9 +67,9 @@ exports['e2e visit / low response timeout / passes'] = ` Spec Tests Passing Failing Pending Skipped ┌────────────────────────────────────────────────────────────────────────────────────────────────┐ - │ ✔ visit_spec.coffee XX:XX 11 11 - - - │ + │ ✔ visit_spec.coffee XX:XX 12 12 - - - │ └────────────────────────────────────────────────────────────────────────────────────────────────┘ - ✔ All specs passed! XX:XX 11 11 - - - + ✔ All specs passed! XX:XX 12 12 - - - ` diff --git a/packages/server/package.json b/packages/server/package.json index 11c7166410..6a35c0e0f1 100644 --- a/packages/server/package.json +++ b/packages/server/package.json @@ -162,6 +162,7 @@ "express-session": "1.16.1", "express-useragent": "1.0.12", "http-mitm-proxy": "0.7.0", + "https-pem": "2.0.0", "https-proxy-agent": "3.0.0", "istanbul": "0.4.5", "mocked-env": "1.2.4", diff --git a/packages/server/test/e2e/6_visit_spec.coffee b/packages/server/test/e2e/6_visit_spec.coffee index 5e94f6e214..a3e9433bab 100644 --- a/packages/server/test/e2e/6_visit_spec.coffee +++ b/packages/server/test/e2e/6_visit_spec.coffee @@ -1,6 +1,29 @@ +_ = require("lodash") +Bluebird = require("bluebird") +cert = require("https-pem") +https = require("https") useragent = require("express-useragent") +{ allowDestroy } = require("@packages/network") e2e = require("../support/helpers/e2e") +## create an HTTPS server that forces TLSv1 +startTlsV1Server = (port) -> + Bluebird.fromCallback (cb) -> + opts = _.merge({ + secureProtocol: "TLSv1_server_method", + }, cert) + + serv = https.createServer opts, (req, res) => + res.setHeader('content-type', 'text/html') + res.end('foo') + + allowDestroy(serv) + + serv.listen port, (err) => + cb(null, serv) + + serv.on('error', cb) + onServer = (app) -> app.get "/agent.json", (req, res) -> source = req.headers["user-agent"] ? "" @@ -75,6 +98,12 @@ describe "e2e visit", -> spec: "visit_spec.coffee" snapshot: true expectedExitCode: 0 + onRun: (exec) -> + startTlsV1Server(6776) + .then (serv) -> + exec() + .then -> + serv.destroy() } e2e.it "fails when network connection immediately fails", { diff --git a/packages/server/test/support/fixtures/projects/e2e/cypress/integration/visit_spec.coffee b/packages/server/test/support/fixtures/projects/e2e/cypress/integration/visit_spec.coffee index 577e601c6f..84a2adf1b2 100644 --- a/packages/server/test/support/fixtures/projects/e2e/cypress/integration/visit_spec.coffee +++ b/packages/server/test/support/fixtures/projects/e2e/cypress/integration/visit_spec.coffee @@ -10,6 +10,10 @@ describe "visits", -> it "can load a local file with a huge amount of elements without timing out", -> cy.visit("/elements.html", {timeout: 5000}) + ## https://github.com/cypress-io/cypress/issues/5446 + it "can load a site via TLSv1", -> + cy.visit("https://localhost:6776") + context "issue #225: hash urls", -> rand = Math.random() From b3b7752def2241ac4d595b731734070bd997a44e Mon Sep 17 00:00:00 2001 From: Zach Bloomquist Date: Thu, 9 Jan 2020 11:00:59 -0500 Subject: [PATCH 4/4] set minVersion to TLSv1 and fix types --- packages/network/lib/agent.ts | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/packages/network/lib/agent.ts b/packages/network/lib/agent.ts index 381edd65b3..632d70191c 100644 --- a/packages/network/lib/agent.ts +++ b/packages/network/lib/agent.ts @@ -11,11 +11,19 @@ const debug = debugModule('cypress:network:agent') const CRLF = '\r\n' const statusCodeRe = /^HTTP\/1.[01] (\d*)/ -interface RequestOptionsWithProxy extends http.RequestOptions { +type WithProxyOpts = RequestOptions & { proxy: string shouldRetry?: boolean } +type RequestOptionsWithProxy = WithProxyOpts + +type HttpsRequestOptions = https.RequestOptions & { + minVersion?: 'TLSv1' +} + +type HttpsRequestOptionsWithProxy = WithProxyOpts + type FamilyCache = { [host: string]: 4 | 6 } @@ -253,14 +261,18 @@ class HttpsAgent extends https.Agent { super(opts) } - createConnection (options: http.RequestOptions, cb: http.SocketCallback) { + createConnection (options: HttpsRequestOptions, cb: http.SocketCallback) { + // allow requests to use older TLS versions + // https://github.com/cypress-io/cypress/issues/5446 + options.minVersion = 'TLSv1' + if (process.env.HTTPS_PROXY) { const proxy = getProxyForUrl(options.href) if (proxy) { options.proxy = proxy - return this.createUpstreamProxyConnection(options, cb) + return this.createUpstreamProxyConnection(options, cb) } } @@ -268,7 +280,7 @@ class HttpsAgent extends https.Agent { cb(null, super.createConnection(options)) } - createUpstreamProxyConnection (options: RequestOptionsWithProxy, cb: http.SocketCallback) { + createUpstreamProxyConnection (options: HttpsRequestOptionsWithProxy, cb: http.SocketCallback) { // heavily inspired by // https://github.com/mknj/node-keepalive-proxy-agent/blob/master/index.js debug(`Creating proxied socket for ${options.href} through ${options.proxy}`)