diff --git a/LibreNMS/Util/Env.php b/LibreNMS/Util/Env.php new file mode 100644 index 0000000000..04baecb943 --- /dev/null +++ b/LibreNMS/Util/Env.php @@ -0,0 +1,48 @@ +. + * + * @package LibreNMS + * @link http://librenms.org + * @copyright 2018 Tony Murray + * @author Tony Murray + */ + +namespace LibreNMS\Util; + +class Env +{ + /** + * Parse comma separated environment variable into an array. + * + * @param string $env_name + * @param mixed $default + * @param array $except Ignore these values and return the unexploded string + * @return array|mixed + */ + public static function parseArray($env_name, $default = null, $except = ['']) + { + $value = env($env_name, $default); + + if (is_string($value) && !in_array($value, $except)) { + $value = explode(',', $value); + } + + return $value; + } +} diff --git a/app/Http/Kernel.php b/app/Http/Kernel.php index 754ab7225f..d4d0ab4a37 100644 --- a/app/Http/Kernel.php +++ b/app/Http/Kernel.php @@ -19,6 +19,7 @@ class Kernel extends HttpKernel \Illuminate\Foundation\Http\Middleware\ValidatePostSize::class, \App\Http\Middleware\TrimStrings::class, \Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class, + \Fideloper\Proxy\TrustProxies::class, ]; /** diff --git a/composer.json b/composer.json index 5b5bedd128..b1f87d9a08 100644 --- a/composer.json +++ b/composer.json @@ -49,6 +49,7 @@ "oriceon/toastr-5-laravel": "dev-master", "wpb/string-blade-compiler": "3.4.x-dev", "fico7489/laravel-pivot": "*", + "fideloper/proxy": "^4.0", "vlucas/phpdotenv": "2.4.0", "doctrine/inflector": "1.1.*", diff --git a/composer.lock b/composer.lock index 49b744adaf..aefc5b8058 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "dda22b18b92903eddb7a35e421dce8bf", + "content-hash": "235afb0a259569a0377d16a27ccc9dc0", "packages": [ { "name": "amenadiel/jpgraph", @@ -469,6 +469,60 @@ ], "time": "2018-03-08T16:05:59+00:00" }, + { + "name": "fideloper/proxy", + "version": "4.0.0", + "source": { + "type": "git", + "url": "https://github.com/fideloper/TrustedProxy.git", + "reference": "cf8a0ca4b85659b9557e206c90110a6a4dba980a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/fideloper/TrustedProxy/zipball/cf8a0ca4b85659b9557e206c90110a6a4dba980a", + "reference": "cf8a0ca4b85659b9557e206c90110a6a4dba980a", + "shasum": "" + }, + "require": { + "illuminate/contracts": "~5.0", + "php": ">=5.4.0" + }, + "require-dev": { + "illuminate/http": "~5.6", + "mockery/mockery": "~1.0", + "phpunit/phpunit": "^6.0" + }, + "type": "library", + "extra": { + "laravel": { + "providers": [ + "Fideloper\\Proxy\\TrustedProxyServiceProvider" + ] + } + }, + "autoload": { + "psr-4": { + "Fideloper\\Proxy\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Chris Fidao", + "email": "fideloper@gmail.com" + } + ], + "description": "Set trusted proxies for Laravel", + "keywords": [ + "load balancing", + "proxy", + "trusted proxy" + ], + "time": "2018-02-07T20:20:57+00:00" + }, { "name": "guzzlehttp/guzzle", "version": "6.3.3", diff --git a/config/app.php b/config/app.php index 865b0b6776..6c82768534 100644 --- a/config/app.php +++ b/config/app.php @@ -167,6 +167,7 @@ return [ */ Laravel\Tinker\TinkerServiceProvider::class, Kamaln7\Toastr\ToastrServiceProvider::class, + Fideloper\Proxy\TrustedProxyServiceProvider::class, /* * Application Service Providers... diff --git a/config/trustedproxy.php b/config/trustedproxy.php new file mode 100644 index 0000000000..c11ded75c7 --- /dev/null +++ b/config/trustedproxy.php @@ -0,0 +1,51 @@ + \LibreNMS\Util\Env::parseArray('APP_TRUSTED_PROXIES', '*', ['', '*', '**']), + + /* + * To trust one or more specific proxies that connect + * directly to your server, use an array of IP addresses: + */ + # 'proxies' => ['192.168.1.1'], + + /* + * Or, to trust all proxies that connect + * directly to your server, use a "*" + */ + # 'proxies' => '*', + + /* + * Which headers to use to detect proxy related data (For, Host, Proto, Port) + * + * Options include: + * + * - Illuminate\Http\Request::HEADER_X_FORWARDED_ALL (use all x-forwarded-* headers to establish trust) + * - Illuminate\Http\Request::HEADER_FORWARDED (use the FORWARDED header to establish trust) + * + * @link https://symfony.com/doc/current/deployment/proxies.html + */ + 'headers' => Illuminate\Http\Request::HEADER_X_FORWARDED_ALL, +// 'headers' => [ +// (defined('Illuminate\Http\Request::HEADER_FORWARDED') ? Illuminate\Http\Request::HEADER_FORWARDED : 'forwarded') => 'FORWARDED', +// \Illuminate\Http\Request::HEADER_CLIENT_IP => 'X_FORWARDED_FOR', +// \Illuminate\Http\Request::HEADER_CLIENT_HOST => 'X_FORWARDED_HOST', +// \Illuminate\Http\Request::HEADER_CLIENT_PROTO => 'X_FORWARDED_PROTO', +// \Illuminate\Http\Request::HEADER_CLIENT_PORT => 'X_FORWARDED_PORT', +// ] + +]; diff --git a/doc/General/Security.md b/doc/General/Security.md index 32dd42afae..a147afa281 100644 --- a/doc/General/Security.md +++ b/doc/General/Security.md @@ -22,7 +22,7 @@ Like anyone, we appreciate the work people put in to find flaws in software and to do so with LibreNMS, this will lead to better quality and more secure software for everyone. If you think you've found a vulnerability and want to discuss it with some of the core team then -you can email us at [team@librenms.org](team@librenms.org) and we will endeavour to get back to +you can email us at [team@librenms.org](mailto:team@librenms.org) and we will endeavour to get back to as quick as we can, this is usually within 24 hours. We are happy to attribute credit to the findings but we ask that we're given a chance to patch diff --git a/doc/Support/Environment-Variables.md b/doc/Support/Environment-Variables.md new file mode 100644 index 0000000000..854acd796d --- /dev/null +++ b/doc/Support/Environment-Variables.md @@ -0,0 +1,46 @@ +# Environment Variables + +LibreNMS allows certain settings to be set via the environment or through the .env file. + +## Database + +Set the variables to connect to the database. The default values are shown below. + +```dotenv +DB_HOST=localhost +DB_PORT=3306 +DB_DATABASE=librenms +DB_USERNAME=librenms +DB_PASSWORD= +DB_SOCKET= + +``` + +## Trusted Reverse Proxies + +A comma separated list of trusted reverse proxy IPs or CIDR. +For legacy reasons the default is `'*'`, which means any proxy is allowed. +`'**'` means trust any proxy up the chain. + +```dotenv +APP_TRUSTED_PROXIES=192.168.1.0/24,192.167.8.20 +``` + +## User / Group + +The user and group that LibreNMS should operate as. +Group will default to the same as the user if unset. + +```dotenv +LIBRENMS_USER=librenms +LIBRENMS_GROUP=librenms +``` + +## Debug + +Increases the amount of information shown when an error occurs. +> WARNING: This may leak information, do not leave enabled. + +```dotenv +APP_DEBUG=true +``` diff --git a/doc/Support/FAQ.md b/doc/Support/FAQ.md index 314ec1ddaa..1dda582155 100644 --- a/doc/Support/FAQ.md +++ b/doc/Support/FAQ.md @@ -32,6 +32,7 @@ source: Support/FAQ.md - [Why would alert un-mute itself](#faq32) - [How do I change the Device Type?](#faq33) - [Where do I update my database credentials?](#faq-where-do-i-update-my-database-credentials) + - [My reverse proxy is not working](#my-reverse-proxy-is-not-working) ### Developing - [How do I add support for a new OS?](#faq8) @@ -370,11 +371,18 @@ $config['db_pass'] = ''; $config['db_name'] = ''; ``` -.env: +[.env](../Support/Environment-Variables.md#database): ```bash DB_HOST= DB_DATABASE= DB_USERNAME= DB_PASSWORD= DB_PORT= -``` \ No newline at end of file +``` + +### My reverse proxy is not working + +Make sure your proxy is passing the proper variables. +At a minimum: X-Forwarded-For and X-Forwarded-Proto (X-Forwarded-Port if needed) + +You also need to [Set the proxy or proxies as trusted](../Support/Environment-Variables.md#trusted-reverse-proxies) diff --git a/includes/defaults.inc.php b/includes/defaults.inc.php index cc89d747d7..197206c4be 100644 --- a/includes/defaults.inc.php +++ b/includes/defaults.inc.php @@ -31,9 +31,13 @@ $config['log_dir'] = $config['install_dir'].'/logs'; // MySQL Debug level $config['mysql_log_level'] = 'ERROR'; -//MySQL port +//MySQL Settings $config['db_port'] = 3306; $config['db_socket'] = null; +$config['db_name'] = 'librenms'; +$config['db_user'] = 'librenms'; +$config['db_pass'] = null; +$config['db_socket'] = null; // What is my own hostname (used to identify this host in its own database) $config['own_hostname'] = 'localhost'; diff --git a/mkdocs.yml b/mkdocs.yml index 3a7851ab95..a28c37aa86 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -54,6 +54,7 @@ pages: - 5. Advanced Setup: - Support/1-Minute-Polling.md - Fast Ping Checking: Extensions/Fast-Ping-Check.md + - Support/Environment-Variables.md - Configuration docs: Support/Configuration.md - Authentication Options: Extensions/Authentication.md - Two-Factor Auth: Extensions/Two-Factor-Auth.md diff --git a/tests/Unit/Util/EnvTest.php b/tests/Unit/Util/EnvTest.php new file mode 100644 index 0000000000..fbfe45af7d --- /dev/null +++ b/tests/Unit/Util/EnvTest.php @@ -0,0 +1,51 @@ +. + * + * @package LibreNMS + * @link http://librenms.org + * @copyright 2018 Tony Murray + * @author Tony Murray + */ + +namespace LibreNMS\Tests\Unit\Util; + +use LibreNMS\Tests\TestCase; +use LibreNMS\Util\Env; + +class EnvTest extends TestCase +{ + public function testParseArray() + { + putenv('PARSETEST=one,two'); + $this->assertSame(['one', 'two'], Env::parseArray('PARSETEST'), 'Could not parse simple array'); + $this->assertSame(['default'], Env::parseArray('PARSETESTNOTSET', 'default'), 'Did not get default value as expected'); + $this->assertSame(null, Env::parseArray('PARSETESTNOTSET'), 'Did not get null as expected when env not set'); + $this->assertSame(3, Env::parseArray('PARSETESTNOTSET', 3), 'Did not get default value (non-array) as expected'); + $this->assertSame('default', Env::parseArray('PARSETESTNOTSET', 'default', ['default']), 'Did not get default value as expected, excluding it from exploding'); + + putenv('PARSETEST='); + $this->assertSame([''], Env::parseArray('PARSETEST', null, []), 'Did not get empty string as expected when env set to empty'); + + putenv('PARSETEST=*'); + $this->assertSame('*', Env::parseArray('PARSETEST', null, ['*', '*']), 'Did not properly ignore exclude values'); + + // clean the environment + putenv('PARSETEST'); + } +}