From cc18563f9ff6c3a63ec0031cf81ec00da1abcc41 Mon Sep 17 00:00:00 2001 From: Tim Walling Date: Tue, 29 Oct 2024 16:13:39 -0600 Subject: [PATCH 1/3] add support for trustProxy option --- args.js | 11 +++-- start.js | 4 ++ test/args.test.js | 111 +++++++++++++++++++++++++++++++++++++++++++--- 3 files changed, 116 insertions(+), 10 deletions(-) diff --git a/args.js b/args.js index 1f842bc2..810f936d 100644 --- a/args.js +++ b/args.js @@ -27,9 +27,9 @@ module.exports = function parseArgs (args) { configuration: { 'populate--': true }, - number: ['port', 'inspect-port', 'body-limit', 'plugin-timeout', 'close-grace-delay'], - string: ['log-level', 'address', 'socket', 'prefix', 'ignore-watch', 'logging-module', 'debug-host', 'lang', 'require', 'import', 'config', 'method'], - boolean: ['pretty-logs', 'options', 'watch', 'verbose-watch', 'debug', 'standardlint', 'common-prefix', 'include-hooks'], + number: ['port', 'inspect-port', 'body-limit', 'plugin-timeout', 'close-grace-delay', 'trust-proxy-hop'], + string: ['log-level', 'address', 'socket', 'prefix', 'ignore-watch', 'logging-module', 'debug-host', 'lang', 'require', 'import', 'config', 'method', 'trust-proxy-ips'], + boolean: ['pretty-logs', 'options', 'watch', 'verbose-watch', 'debug', 'standardlint', 'common-prefix', 'include-hooks', 'trust-proxy-enabled'], envPrefix: 'FASTIFY_', alias: { port: ['p'], @@ -67,6 +67,8 @@ module.exports = function parseArgs (args) { // Merge objects from lower to higher priority const parsedArgs = { ...DEFAULT_ARGUMENTS, ...configFileOptions, ...commandLineArguments } + const trustProxy = parsedArgs.trustProxyEnabled || parsedArgs.trustProxyIps || parsedArgs.trustProxyHop; + return { _: parsedArgs._, '--': additionalArgs, @@ -93,6 +95,7 @@ module.exports = function parseArgs (args) { lang: parsedArgs.lang, method: parsedArgs.method, commonPrefix: parsedArgs.commonPrefix, - includeHooks: parsedArgs.includeHooks + includeHooks: parsedArgs.includeHooks, + trustProxy } } diff --git a/start.js b/start.js index e359369e..710d07f8 100755 --- a/start.js +++ b/start.js @@ -164,6 +164,10 @@ async function runFastify (args, additionalOptions, serverOptions) { options = deepmerge(options, file.options) } + if (opts.trustProxy) { + options.trustProxy = opts.trustProxy; + } + const fastify = Fastify(options) if (opts.prefix) { diff --git a/test/args.test.js b/test/args.test.js index 5d024a83..d42de3d6 100644 --- a/test/args.test.js +++ b/test/args.test.js @@ -27,6 +27,7 @@ test('should parse args correctly', t => { '--debug-port', 1111, '--debug-host', '1.1.1.1', '--logging-module', './custom-logger.js', + '--trust-proxy-enabled', 'true', 'app.js' ] const parsedArgs = parseArgs(argv) @@ -57,7 +58,8 @@ test('should parse args correctly', t => { lang: 'js', method: undefined, commonPrefix: false, - includeHooks: undefined + includeHooks: undefined, + trustProxy: true }) }) @@ -84,6 +86,7 @@ test('should parse args with = assignment correctly', t => { '--debug-port', 1111, '--debug-host', '1.1.1.1', '--logging-module', './custom-logger.js', + '--trust-proxy-hop', '2', 'app.js' ] const parsedArgs = parseArgs(argv) @@ -114,7 +117,8 @@ test('should parse args with = assignment correctly', t => { lang: 'js', method: undefined, commonPrefix: false, - includeHooks: undefined + includeHooks: undefined, + trustProxy: 2 }) }) @@ -190,7 +194,8 @@ test('should parse env vars correctly', t => { lang: 'js', method: undefined, commonPrefix: false, - includeHooks: undefined + includeHooks: undefined, + trustProxy: undefined }) }) @@ -284,7 +289,8 @@ test('should parse custom plugin options', t => { lang: 'js', method: undefined, commonPrefix: false, - includeHooks: undefined + includeHooks: undefined, + trustProxy: undefined }) }) @@ -323,7 +329,8 @@ test('should parse config file correctly and prefer config values over default o lang: 'js', method: undefined, commonPrefix: false, - includeHooks: undefined + includeHooks: undefined, + trustProxy: undefined }) }) @@ -366,6 +373,98 @@ test('should prefer command line args over config file options', t => { lang: 'js', method: undefined, commonPrefix: false, - includeHooks: undefined + includeHooks: undefined, + trustProxy: undefined + }) +}) + +test('should favor trust proxy enabled over trust proxy ips and trust proxy hop', t => { + t.plan(1); + + const argv = [ + '--port', '4000', + '--close-grace-delay', '30000', + '--debug-port', '1111', + '--debug-host', '1.1.1.1', + '--trust-proxy-enabled', 'true', + '--trust-proxy-ips', '127.0.0.1', + '--trust-proxy-hop', '2', + 'app.js' + ] + const parsedArgs = parseArgs(argv) + + t.strictSame(parsedArgs, { + _: ['app.js'], + '--': [], + port: 4000, + bodyLimit: undefined, + pluginTimeout: 10000, + closeGraceDelay: 30000, + pluginOptions: {}, + prettyLogs: false, + options: false, + watch: false, + debug: false, + debugPort: 1111, + debugHost: '1.1.1.1', + ignoreWatch: 'node_modules build dist .git bower_components logs .swp .nyc_output', + verboseWatch: false, + logLevel: 'fatal', + address: undefined, + socket: undefined, + require: undefined, + import: undefined, + prefix: undefined, + loggingModule: undefined, + lang: 'js', + method: undefined, + commonPrefix: false, + includeHooks: undefined, + trustProxy: true + }) +}) + +test('should favor trust proxy enabled over trust proxy ips and trust proxy hop', t => { + t.plan(1); + + const argv = [ + '--port', '4000', + '--close-grace-delay', '30000', + '--debug-port', '1111', + '--debug-host', '1.1.1.1', + '--trust-proxy-ips', '127.0.0.1', + '--trust-proxy-hop', '2', + 'app.js' + ] + const parsedArgs = parseArgs(argv) + + t.strictSame(parsedArgs, { + _: ['app.js'], + '--': [], + port: 4000, + bodyLimit: undefined, + pluginTimeout: 10000, + closeGraceDelay: 30000, + pluginOptions: {}, + prettyLogs: false, + options: false, + watch: false, + debug: false, + debugPort: 1111, + debugHost: '1.1.1.1', + ignoreWatch: 'node_modules build dist .git bower_components logs .swp .nyc_output', + verboseWatch: false, + logLevel: 'fatal', + address: undefined, + socket: undefined, + require: undefined, + import: undefined, + prefix: undefined, + loggingModule: undefined, + lang: 'js', + method: undefined, + commonPrefix: false, + includeHooks: undefined, + trustProxy: '127.0.0.1' }) }) From 4c985c7466a3d576636db9665c024345d86e2406 Mon Sep 17 00:00:00 2001 From: Tim Walling Date: Tue, 29 Oct 2024 16:42:22 -0600 Subject: [PATCH 2/3] update test and documentation --- README.md | 3 +++ args.js | 5 ++++- test/args.test.js | 4 +++- 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 21657bee..6015afc4 100644 --- a/README.md +++ b/README.md @@ -171,6 +171,9 @@ You can pass the following options via CLI arguments. You can also use `--config | Set the plugin timeout | `-T` | `--plugin-timeout` | `FASTIFY_PLUGIN_TIMEOUT` | | Defines the maximum payload, in bytes,
that the server is allowed to accept | | `--body-limit` | `FASTIFY_BODY_LIMIT` | | Set the maximum ms delay before forcefully closing pending requests after receiving SIGTERM or SIGINT signals; and uncaughtException or unhandledRejection errors (default: 500) | `-g` | `--close-grace-delay` | `FASTIFY_CLOSE_GRACE_DELAY` | +| Set the boolean value for `trustProxy` (1st precedence) | | `--trust-proxy-enabled` | `FASTIFY_TRUST_PROXY_ENABLED` | +| Set the IP/CIDR value for `trustProxy` (2nd precedence) | | `--trust-proxy-ips` | `FASTIFY_TRUST_PROXY_IPS` | +| Set the nth hop value for `trustProxy` (3rd precedence) | | `--trust-proxy-hop` | `FASTIFY_TRUST_PROXY_HOP` | By default `fastify-cli` runs [`dotenv`](https://www.npmjs.com/package/dotenv), so it will load all the env variables stored in `.env` in your current working directory. diff --git a/args.js b/args.js index 810f936d..82d09cb5 100644 --- a/args.js +++ b/args.js @@ -67,7 +67,10 @@ module.exports = function parseArgs (args) { // Merge objects from lower to higher priority const parsedArgs = { ...DEFAULT_ARGUMENTS, ...configFileOptions, ...commandLineArguments } - const trustProxy = parsedArgs.trustProxyEnabled || parsedArgs.trustProxyIps || parsedArgs.trustProxyHop; + // Set `trustProxy` with enabled taking precedence, followed by IPs and finally hop count + const trustProxyEnabled = parsedArgs.trustProxyEnabled === undefined ? undefined : + parsedArgs.trustProxyEnabled === true || parsedArgs.trustProxyEnabled === 'true'; + const trustProxy = trustProxyEnabled || parsedArgs.trustProxyIps || parsedArgs.trustProxyHop; return { _: parsedArgs._, diff --git a/test/args.test.js b/test/args.test.js index d42de3d6..9fc45142 100644 --- a/test/args.test.js +++ b/test/args.test.js @@ -144,6 +144,7 @@ test('should parse env vars correctly', t => { process.env.FASTIFY_DEBUG_PORT = '1111' process.env.FASTIFY_DEBUG_HOST = '1.1.1.1' process.env.FASTIFY_LOGGING_MODULE = './custom-logger.js' + process.env.FASTIFY_TRUST_PROXY_ENABLED = 'true' t.teardown(function () { delete process.env.FASTIFY_PORT @@ -164,6 +165,7 @@ test('should parse env vars correctly', t => { delete process.env.FASTIFY_DEBUG delete process.env.FASTIFY_DEBUG_PORT delete process.env.FASTIFY_LOGGING_MODULE + delete process.env.FASTIFY_TRUST_PROXY_ENABLED }) const parsedArgs = parseArgs([]) @@ -195,7 +197,7 @@ test('should parse env vars correctly', t => { method: undefined, commonPrefix: false, includeHooks: undefined, - trustProxy: undefined + trustProxy: true }) }) From 863247fcd5ca4a14abee3c0732955c3fd93f0f17 Mon Sep 17 00:00:00 2001 From: Tim Walling Date: Sat, 7 Dec 2024 15:09:25 -0700 Subject: [PATCH 3/3] fix test --- args.js | 7 ++++--- start.js | 2 +- test/args.test.js | 10 +++++----- 3 files changed, 10 insertions(+), 9 deletions(-) diff --git a/args.js b/args.js index 82d09cb5..3fa05366 100644 --- a/args.js +++ b/args.js @@ -68,9 +68,10 @@ module.exports = function parseArgs (args) { const parsedArgs = { ...DEFAULT_ARGUMENTS, ...configFileOptions, ...commandLineArguments } // Set `trustProxy` with enabled taking precedence, followed by IPs and finally hop count - const trustProxyEnabled = parsedArgs.trustProxyEnabled === undefined ? undefined : - parsedArgs.trustProxyEnabled === true || parsedArgs.trustProxyEnabled === 'true'; - const trustProxy = trustProxyEnabled || parsedArgs.trustProxyIps || parsedArgs.trustProxyHop; + const trustProxyEnabled = parsedArgs.trustProxyEnabled === undefined + ? undefined + : parsedArgs.trustProxyEnabled === true || parsedArgs.trustProxyEnabled === 'true' + const trustProxy = trustProxyEnabled || parsedArgs.trustProxyIps || parsedArgs.trustProxyHop return { _: parsedArgs._, diff --git a/start.js b/start.js index 710d07f8..cb6bf1be 100755 --- a/start.js +++ b/start.js @@ -165,7 +165,7 @@ async function runFastify (args, additionalOptions, serverOptions) { } if (opts.trustProxy) { - options.trustProxy = opts.trustProxy; + options.trustProxy = opts.trustProxy } const fastify = Fastify(options) diff --git a/test/args.test.js b/test/args.test.js index 9a781db5..616291b5 100644 --- a/test/args.test.js +++ b/test/args.test.js @@ -380,7 +380,7 @@ test('should prefer command line args over config file options', t => { }) test('should favor trust proxy enabled over trust proxy ips and trust proxy hop', t => { - t.plan(1); + t.plan(1) const argv = [ '--port', '4000', @@ -394,7 +394,7 @@ test('should favor trust proxy enabled over trust proxy ips and trust proxy hop' ] const parsedArgs = parseArgs(argv) - t.strictSame(parsedArgs, { + t.assert.deepStrictEqual(parsedArgs, { _: ['app.js'], '--': [], port: 4000, @@ -425,8 +425,8 @@ test('should favor trust proxy enabled over trust proxy ips and trust proxy hop' }) }) -test('should favor trust proxy enabled over trust proxy ips and trust proxy hop', t => { - t.plan(1); +test('should favor trust proxy ips over trust proxy hop', t => { + t.plan(1) const argv = [ '--port', '4000', @@ -439,7 +439,7 @@ test('should favor trust proxy enabled over trust proxy ips and trust proxy hop' ] const parsedArgs = parseArgs(argv) - t.strictSame(parsedArgs, { + t.assert.deepStrictEqual(parsedArgs, { _: ['app.js'], '--': [], port: 4000,