From 08a9b88f7f46b28ec9a8f5129af6a69545679efa Mon Sep 17 00:00:00 2001 From: Diana Barsan Date: Thu, 9 Nov 2023 14:58:05 +0300 Subject: [PATCH] Allow self signed certs by default for localhost-like --- src/lib/environment.js | 2 +- src/lib/get-api-url.js | 16 ++++++++-- src/lib/main.js | 10 +++--- test/lib/get-api-url.spec.js | 59 ++++++++++++++++++++++++++---------- 4 files changed, 63 insertions(+), 24 deletions(-) diff --git a/src/lib/environment.js b/src/lib/environment.js index b336e1cff..1fd8057bf 100644 --- a/src/lib/environment.js +++ b/src/lib/environment.js @@ -20,7 +20,7 @@ const initialize = ( } Object.assign(state, { - apiUrl, + apiUrl: apiUrl.toString(), archiveDestination, extraArgs, initialized: true, diff --git a/src/lib/get-api-url.js b/src/lib/get-api-url.js index fcbbc5564..6c9f8c86a 100644 --- a/src/lib/get-api-url.js +++ b/src/lib/get-api-url.js @@ -36,7 +36,16 @@ const getApiUrl = (cmdArgs, env = {}) => { instanceUrl = new url.URL(cmdArgs.url); } - return `${instanceUrl.href}medic`; + instanceUrl.pathname = `${instanceUrl.pathname}medic`; + return instanceUrl; +}; + +const isLocalhost = (apiUrl) => { + if (!apiUrl) { + return false; + } + const localhosts = [/^localhost$/, /^127\.0\.0\.\d+$/]; + return !!localhosts.find(localhost => localhost.test(apiUrl.hostname)); }; const parseLocalUrl = (couchUrl) => { @@ -56,4 +65,7 @@ const parseLocalUrl = (couchUrl) => { return new url.URL('http://admin:pass@localhost:5988'); }; -module.exports = getApiUrl; +module.exports = { + getApiUrl, + isLocalhost, +}; diff --git a/src/lib/main.js b/src/lib/main.js index 88a38050d..5f9822fda 100755 --- a/src/lib/main.js +++ b/src/lib/main.js @@ -3,7 +3,7 @@ const checkForUpdates = require('../lib/check-for-updates'); const checkChtConfDependencyVersion = require('../lib/check-cht-conf-dependency-version'); const environment = require('./environment'); const fs = require('../lib/sync-fs'); -const getApiUrl = require('../lib/get-api-url'); +const { getApiUrl, isLocalhost } = require('../lib/get-api-url'); const log = require('../lib/log'); const userPrompt = require('../lib/user-prompt'); const redactBasicAuth = require('redact-basic-auth'); @@ -110,10 +110,6 @@ module.exports = async (argv, env) => { throw new Error('--destination= is required with --archive.'); } - if (cmdArgs['accept-self-signed-certs']) { - process.env.NODE_TLS_REJECT_UNAUTHORIZED = 0; - } - // // Logging // @@ -147,6 +143,10 @@ module.exports = async (argv, env) => { const requiresInstance = actions.some(action => action.requiresInstance); const apiUrl = requiresInstance && getApiUrl(cmdArgs, env); + if (cmdArgs['accept-self-signed-certs'] || isLocalhost(apiUrl)) { + process.env.NODE_TLS_REJECT_UNAUTHORIZED = 0; + } + let extraArgs = cmdArgs['--']; if (!extraArgs.length) { extraArgs = undefined; diff --git a/test/lib/get-api-url.spec.js b/test/lib/get-api-url.spec.js index ddbbb5005..0e492ac7a 100644 --- a/test/lib/get-api-url.spec.js +++ b/test/lib/get-api-url.spec.js @@ -1,8 +1,9 @@ const sinon = require('sinon'); const rewire = require('rewire'); const { expect } = require('chai'); +const url = require('url'); -const getApiUrl = rewire('../../src/lib/get-api-url'); +const apiUrlLib = rewire('../../src/lib/get-api-url'); const userPrompt = rewire('../../src/lib/user-prompt'); describe('get-api-url', () => { @@ -13,32 +14,32 @@ describe('get-api-url', () => { keyInYN: sinon.stub().throws('unexpected'), }; userPrompt.__set__('readline', readline); - getApiUrl.__set__('userPrompt', userPrompt); + apiUrlLib.__set__('userPrompt', userPrompt); }); it('multiple destinations yields error', () => { - const actual = () => getApiUrl({ local: true, instance: 'demo' }); + const actual = () => apiUrlLib.getApiUrl({ local: true, instance: 'demo' }); expect(actual).to.throw('One of these'); }); it('no destination yields error', () => { - const actual = () => getApiUrl({}); + const actual = () => apiUrlLib.getApiUrl({}); expect(actual).to.throw('One of these'); }); describe('--local', () => { it('no environment variable has a default', () => { - const actual = getApiUrl({ local: true }); - expect(actual).to.eq('http://admin:pass@localhost:5988/medic'); + const actual = apiUrlLib.getApiUrl({ local: true }); + expect(actual).to.deep.equal(new url.URL('http://admin:pass@localhost:5988/medic')); }); it('use environment variable', () => { - const actual = getApiUrl({ local: true }, { COUCH_URL: 'http://user:pwd@localhost:5984/db' }); - expect(actual).to.eq('http://user:pwd@localhost:5988/medic'); + const actual = apiUrlLib.getApiUrl({ local: true }, { COUCH_URL: 'http://user:pwd@localhost:5984/db' }); + expect(actual).to.deep.equal(new url.URL('http://user:pwd@localhost:5988/medic')); }); it('warn if environment variable targets remote', () => { - const actual = () => getApiUrl({ local: true }, { COUCH_URL: 'http://user:pwd@remote:5984/db' }); + const actual = () => apiUrlLib.getApiUrl({ local: true }, { COUCH_URL: 'http://user:pwd@remote:5984/db' }); expect(actual).to.throw('remote'); }); }); @@ -46,26 +47,26 @@ describe('get-api-url', () => { describe('--instance', () => { it('with default user', () => { readline.question.returns('entered'); - const actual = getApiUrl({ instance: 'inst' }); - expect(actual).to.eq('https://admin:entered@inst.medicmobile.org/medic'); + const actual = apiUrlLib.getApiUrl({ instance: 'inst' }); + expect(actual).to.deep.equal(new url.URL('https://admin:entered@inst.medicmobile.org/medic')); }); it('with --user', () => { readline.question.returns('entered'); - const actual = getApiUrl({ instance: 'inst', user: 'user' }); - expect(actual).to.eq('https://user:entered@inst.medicmobile.org/medic'); + const actual = apiUrlLib.getApiUrl({ instance: 'inst', user: 'user' }); + expect(actual).to.deep.equal(new url.URL('https://user:entered@inst.medicmobile.org/medic')); }); }); describe('--url', () => { it('basic', () => { - const actual = getApiUrl({ url: 'https://admin:pwd@url.medicmobile.org/' }); - expect(actual).to.eq('https://admin:pwd@url.medicmobile.org/medic'); + const actual = apiUrlLib.getApiUrl({ url: 'https://admin:pwd@url.medicmobile.org/' }); + expect(actual).to.deep.equal(new url.URL('https://admin:pwd@url.medicmobile.org/medic')); }); }); describe('parseLocalUrl', () => { - const parseLocalUrl = getApiUrl.__get__('parseLocalUrl'); + const parseLocalUrl = apiUrlLib.__get__('parseLocalUrl'); it('basic', () => expect(parseLocalUrl('http://admin:pass@localhost:5988/medic').href).to.eq('http://admin:pass@localhost:5988/')); @@ -75,4 +76,30 @@ describe('get-api-url', () => { it('ignores path', () => expect(parseLocalUrl('http://admin:pass@localhost:5984/foo').href).to.eq('http://admin:pass@localhost:5988/')); }); + + describe('isLocalhost', () => { + it('should return true for localhost', () => { + expect(apiUrlLib.isLocalhost(new url.URL('http://admin:pass@localhost/medic'))).to.be.true; + expect(apiUrlLib.isLocalhost(new url.URL('http://admin:pass@localhost:5988/medic'))).to.be.true; + expect(apiUrlLib.isLocalhost(new url.URL('https://admin:pass@localhost/medic'))).to.be.true; + expect(apiUrlLib.isLocalhost(new url.URL('https://admin:pass@localhost/whatever'))).to.be.true; + }); + + it('should return true for 127.0.0.x', () => { + expect(apiUrlLib.isLocalhost(new url.URL('http://admin:pass@127.0.0.1/medic'))).to.be.true; + expect(apiUrlLib.isLocalhost(new url.URL('http://admin:pass@127.0.0.3/medic'))).to.be.true; + expect(apiUrlLib.isLocalhost(new url.URL('http://admin:pass@127.0.0.1:5988/medic'))).to.be.true; + expect(apiUrlLib.isLocalhost(new url.URL('http://admin:pass@127.0.0.13:5988/medic'))).to.be.true; + expect(apiUrlLib.isLocalhost(new url.URL('https://admin:pass@127.0.0.1/medic'))).to.be.true; + expect(apiUrlLib.isLocalhost(new url.URL('https://admin:pass@127.0.0.232/medic'))).to.be.true; + expect(apiUrlLib.isLocalhost(new url.URL('https://admin:pass@127.0.0.22/whatever'))).to.be.true; + }); + + it('should return false for anything else', () => { + expect(apiUrlLib.isLocalhost(new url.URL('http://admin:pass@host/medic'))).to.be.false; + expect(apiUrlLib.isLocalhost(new url.URL('http://admin:pass@notlocalhost/medic'))).to.be.false; + expect(apiUrlLib.isLocalhost(new url.URL('http://admin:pass@127.1.0.9/medic'))).to.be.false; + expect(apiUrlLib.isLocalhost(new url.URL('http://admin:pass@192.168.1.0/medic'))).to.be.false; + }); + }); });