proxyAuth: add exclusion path

had to move the ~ login/logout regexp inside. This is because of
https://www.ruby-forum.com/t/proxy-pass-location-inheritance/239135

What it says is that a regexp inside a matching location prefix is
given precedence regardless of how it appears in the file. This means
that the negative regexp got precedence over login|logout and thus
went into infinite redirect. By moving it to same level, the regexps
are considered in order.

Some notes on nginx location:

* First, it will match the prefixes (= and the /). If =, the matching stops.
  If /xx then the longest match is "remembered"
* It will then match the regex inside the longest match. First match wins
* It will then match the rest of the regex locations. First match win
* If no regex matched, it will then do the remembered longest prefix

fixes #762
This commit is contained in:
Girish Ramakrishnan
2021-01-08 14:10:11 -08:00
parent 4a6f36bc0e
commit 29ab352846
3 changed files with 98 additions and 88 deletions

View File

@@ -57,6 +57,14 @@ var acme2 = require('./cert/acme2.js'),
var NGINX_APPCONFIG_EJS = fs.readFileSync(__dirname + '/nginxconfig.ejs', { encoding: 'utf8' }),
RELOAD_NGINX_CMD = path.join(__dirname, 'scripts/reloadnginx.sh');
function nginxLocation(s) {
if (!s.startsWith('!')) return s;
let re = s.replace(/[\^$\\.*+?()[\]{}|]/g, '\\$&'); // https://github.com/es-shims/regexp.escape/blob/master/implementation.js
return `~ ^(?!(${re.slice(1)}))`; // negative regex assertion - https://stackoverflow.com/questions/16302897/nginx-location-not-equal-to-regex
}
function getAcmeApi(domainObject, callback) {
assert.strictEqual(typeof domainObject, 'object');
assert.strictEqual(typeof callback, 'function');
@@ -383,7 +391,7 @@ function writeDashboardNginxConfig(bundle, configFileName, vhost, callback) {
certFilePath: bundle.certFilePath,
keyFilePath: bundle.keyFilePath,
robotsTxtQuoted: JSON.stringify('User-agent: *\nDisallow: /\n'),
proxyAuth: { enabled: false, id: null, path: '/' }
proxyAuth: { enabled: false, id: null, location: nginxLocation('/') }
};
var nginxConf = ejs.render(NGINX_APPCONFIG_EJS, data);
var nginxConfigFilename = path.join(paths.NGINX_APPCONFIG_DIR, configFileName);
@@ -463,7 +471,7 @@ function writeAppNginxConfig(app, bundle, callback) {
proxyAuth: {
enabled: app.sso && app.manifest.addons && app.manifest.addons.proxyAuth,
id: app.id,
path: safe.query(app.manifest, 'addons.proxyAuth.path') || '/'
location: nginxLocation(safe.query(app.manifest, 'addons.proxyAuth.path') || '/')
},
httpPaths: app.manifest.httpPaths || {}
};
@@ -497,7 +505,7 @@ function writeAppRedirectNginxConfig(app, fqdn, bundle, callback) {
robotsTxtQuoted: null,
cspQuoted: null,
hideHeaders: [],
proxyAuth: { enabled: false, id: app.id, path: '/' }
proxyAuth: { enabled: false, id: app.id, location: nginxLocation('/') }
};
var nginxConf = ejs.render(NGINX_APPCONFIG_EJS, data);
@@ -685,7 +693,7 @@ function writeDefaultConfig(options, callback) {
certFilePath,
keyFilePath,
robotsTxtQuoted: JSON.stringify('User-agent: *\nDisallow: /\n'),
proxyAuth: { enabled: false, id: null, path: '/' }
proxyAuth: { enabled: false, id: null, location: nginxLocation('/') }
};
const nginxConf = ejs.render(NGINX_APPCONFIG_EJS, data);
const nginxConfigFilename = path.join(paths.NGINX_APPCONFIG_DIR, constants.NGINX_DEFAULT_CONFIG_FILE_NAME);