From fb2178e5d3f732117b1de038b701d3b9d70aa295 Mon Sep 17 00:00:00 2001 From: Dave Page Date: Fri, 17 Jul 2020 17:54:12 +0530 Subject: [PATCH] Support configuration files that are external to the application installation. Fixes #5235 --- docs/en_US/code_overview.rst | 11 ++++++----- docs/en_US/config_py.rst | 19 +++++++++++++++---- docs/en_US/enabling_ldap_authentication.rst | 14 +++++++++----- docs/en_US/query_tool.rst | 6 ++++-- docs/en_US/release_notes_4_24.rst | 1 + web/config.py | 19 +++++++++++++++++-- 6 files changed, 52 insertions(+), 18 deletions(-) diff --git a/docs/en_US/code_overview.rst b/docs/en_US/code_overview.rst index 6809b610d..c3cf2d8a7 100644 --- a/docs/en_US/code_overview.rst +++ b/docs/en_US/code_overview.rst @@ -29,9 +29,10 @@ Configuration The core application configuration is found in **config.py**. This file includes all configurable settings for the application, along with descriptions of their -use. It is essential that various settings are configured prior to deployent on -a web server; these can be overriden in **config_local.py** to avoid modifying -the main configuration file. +use. It is essential that various settings are configured prior to deployment on +a web server; these can be overridden in **config_local.py** or +**config_system.py** (see the :ref:`config.py ` documentation) to +avoid modifying the main configuration file. User Settings ============= @@ -108,7 +109,7 @@ PgAdminModule class. This is responsible for providing hook points to integrate the module into the rest of the application - for example, a hook might tell the caller what CSS files need to be included on the rendered page, or what menu options to include and what they should do. Hook points need not exist if they -are not required. It is the responsiblity of the caller to ensure they are +are not required. It is the responsibility of the caller to ensure they are present before attempting to utilise them. Hooks currently implemented are: @@ -210,6 +211,6 @@ bootstrap for UI look and feel, Backbone for data manipulation of a node, Backform for generating properties/create dialog for selected node. We have divided each module in small chunks as much as possible. Not all javascript modules are required to be loaded (i.e. loading a javascript module for -database will make sense only when a server node is loaded competely.) Please +database will make sense only when a server node is loaded completely.) Please look at the the javascript files node.js, browser.js, menu.js, panel.js, etc for better understanding of the code. \ No newline at end of file diff --git a/docs/en_US/config_py.rst b/docs/en_US/config_py.rst index 37a1114d6..79ab6440b 100644 --- a/docs/en_US/config_py.rst +++ b/docs/en_US/config_py.rst @@ -23,10 +23,21 @@ are as follows: and may be created by users in the same directory as ``config.py`` if needed. -.. note:: If the SERVER_MODE setting is changed in ``config_distro.py`` or ``config_local.py``, - you will most likely need to re-set the LOG_FILE, SQLITE_PATH, SESSION_DB_PATH - and STORAGE_DIR values as well as they will have been set based on the default - configuration or overridden by the runtime. +* ``config_system.py``: This file is read after ``config_local.py`` and is + intended for system administrators to include settings that are configured + system-wide from a secure location that users cannot normally modify and that + is outside of the pgAdmin installation. The location for this file varies + based on the platform, and only needs to be created if desired: + + * Linux: ``/etc/pgadmin/config_system.py`` + * macOS: ``/Library/Preferences/pgadmin/config_system.py`` + * Windows: ``%CommonProgramFiles%\pgadmin\config_system.py`` + +.. note:: If the SERVER_MODE setting is changed in ``config_distro.py``, + ``config_local.py``, or ``config_system.py`` you will most likely need to + re-set the LOG_FILE, SQLITE_PATH, SESSION_DB_PATH and STORAGE_DIR values + as well as they will have been set based on the default configuration or + overridden by the runtime. The default ``config.py`` file is shown below for reference: diff --git a/docs/en_US/enabling_ldap_authentication.rst b/docs/en_US/enabling_ldap_authentication.rst index 534a953c6..62c269da3 100644 --- a/docs/en_US/enabling_ldap_authentication.rst +++ b/docs/en_US/enabling_ldap_authentication.rst @@ -5,9 +5,10 @@ ************************************************** To enable LDAP authentication for pgAdmin, you must configure the LDAP -settings in the *config_local.py* or *config_distro.py* file on the system where -pgAdmin is installed in Server mode. You can copy these settings from *config.py* -file and modify the values for the following parameters: +settings in the *config_local.py* or *config_system.py* file (see the +:ref:`config.py ` documentation) on the system where pgAdmin is +installed in Server mode. You can copy these settings from *config.py* file +and modify the values for the following parameters: .. csv-table:: :header: "**Parameter**", "**Description**" @@ -21,9 +22,12 @@ file and modify the values for the following parameters: * [‘ldap’]: pgAdmin will use only LDAP authentication. * [‘ldap’, ‘internal’]: pgAdmin will first try to authenticate the user through - LDAP. If that authentication fails, then internal user entries of pgAdmin will be used for authentication. + LDAP. If that authentication fails, then internal user entries of pgAdmin + will be used for authentication. - * [‘internal’, ‘ldap’]: pgAdmin will first try to authenticate the user through internal user entries. If that authentication fails, then LDAP authentication will be used." + * [‘internal’, ‘ldap’]: pgAdmin will first try to authenticate the user + through internal user entries. If that authentication fails, then LDAP + authentication will be used." "LDAP_AUTO_CREATE_USER", "Specifies if you want to automatically create a pgAdmin user corresponding to the LDAP user credentials. Please note that LDAP password is not stored in the pgAdmin database." diff --git a/docs/en_US/query_tool.rst b/docs/en_US/query_tool.rst index 7aef6840a..83933f0ad 100644 --- a/docs/en_US/query_tool.rst +++ b/docs/en_US/query_tool.rst @@ -286,8 +286,10 @@ the *Clear* drop-down menu. Query History is maintained across sessions for each database on a per-user basis when running in Query Tool mode. In View/Edit Data mode, history is not retained. By default, the last 20 queries are stored for each database. This -can be adjusted in `config_local.py` by overriding the `MAX_QUERY_HIST_STORED` -value. See the :ref:`Deployment ` section for more information. +can be adjusted in ``config_local.py`` or ``config_system.py`` (see the +:ref:`config.py ` documentation) by overriding the +`MAX_QUERY_HIST_STORED` value. See the :ref:`Deployment ` section +for more information. Connection Status ***************** diff --git a/docs/en_US/release_notes_4_24.rst b/docs/en_US/release_notes_4_24.rst index 4be39cf8d..3e91dbe55 100644 --- a/docs/en_US/release_notes_4_24.rst +++ b/docs/en_US/release_notes_4_24.rst @@ -9,6 +9,7 @@ This release contains a number of bug fixes and new features since the release o New features ************ +| `Issue #5235 `_ - Support configuration files that are external to the application installation. | `Issue #5484 `_ - Added support for LDAP authentication with different DN by setting the dedicated user for the LDAP connection. | `Issue #5583 `_ - Added support for schema level restriction. | `Issue #5601 `_ - Added RLS Policy support in Schema Diff. diff --git a/web/config.py b/web/config.py index adc5f60d9..569327e89 100644 --- a/web/config.py +++ b/web/config.py @@ -16,7 +16,6 @@ import logging import os import sys - # We need to include the root directory in sys.path to ensure that we can # find everything we need when running in the standalone runtime. root = os.path.dirname(os.path.realpath(__file__)) @@ -572,7 +571,23 @@ try: except ImportError: pass -# Override DEFAULT_SERVE value from environment variable. +# Load system config overrides. We do this last, so that the sysadmin can +# override anything they want from a config file that's in a protected system +# directory and away from pgAdmin to avoid invalidating signatures. +system_config_dir = '/etc/pgadmin' +if sys.platform.startswith('win32'): + system_config_dir = os.environ['CommonProgramFiles'] + '/pgadmin' +elif sys.platform.startswith('darwin'): + system_config_dir = '/Library/Preferences/pgadmin' + +if os.path.exists(system_config_dir + '/config_system.py'): + try: + sys.path.insert(0, system_config_dir) + from config_system import * + except ImportError: + pass + +# Override DEFAULT_SERVER value from environment variable. if 'PGADMIN_CONFIG_DEFAULT_SERVER' in os.environ: DEFAULT_SERVER = os.environ['PGADMIN_CONFIG_DEFAULT_SERVER']