diff --git a/docs/en_US/container_deployment.rst b/docs/en_US/container_deployment.rst index 0546eb55f..c28f00f47 100644 --- a/docs/en_US/container_deployment.rst +++ b/docs/en_US/container_deployment.rst @@ -142,6 +142,13 @@ Override the default file path for the preferences customization at the containe /pgadmin4/preferences.json mapped file below for more information. See the format of the `Preferences JSON file `_. +**PGADMIN_CONFIG_DISTRO_FILE** + +*Default: /pgadmin4/config_distro.py* + +Override the default file path for the pgadmin configurations file.This can be used while provisioning +container with read only root file system to achieve a more secure pgadmin4 deployment for docker and kubernetes. + **PGPASS_FILE** *Default: * diff --git a/pkg/docker/entrypoint.sh b/pkg/docker/entrypoint.sh index b4887fefa..dc539bc79 100755 --- a/pkg/docker/entrypoint.sh +++ b/pkg/docker/entrypoint.sh @@ -36,12 +36,15 @@ if [ -n "${PGADMIN_CONFIG_CONFIG_DATABASE_URI_FILE}" ]; then fi file_env PGADMIN_DEFAULT_PASSWORD +# TO enable custom path for config_distro, pass config distro path via environment variable. +export CONFIG_DISTRO_FILE_PATH="${PGADMIN_CONFIG_DISTRO_FILE:-/pgadmin4/config_distro.py}" + # Populate config_distro.py. This has some default config, as well as anything # provided by the user through the PGADMIN_CONFIG_* environment variables. # Only update the file on first launch. The empty file is created during the # container build so it can have the required ownership. -if [ "$(wc -m /pgadmin4/config_distro.py | awk '{ print $1 }')" = "0" ]; then - cat << EOF > /pgadmin4/config_distro.py +if [ "$(wc -m "${CONFIG_DISTRO_FILE_PATH}" | awk '{ print $1 }')" = "0" ]; then + cat << EOF > "${CONFIG_DISTRO_FILE_PATH}" CA_FILE = '/etc/ssl/certs/ca-certificates.crt' LOG_FILE = '/dev/null' HELP_PATH = '../../docs' @@ -61,7 +64,7 @@ EOF for var in $(env | grep "^PGADMIN_CONFIG_" | cut -d "=" -f 1); do # shellcheck disable=SC2086 # shellcheck disable=SC2046 - echo ${var#PGADMIN_CONFIG_} = $(eval "echo \$$var") >> /pgadmin4/config_distro.py + echo ${var#PGADMIN_CONFIG_} = $(eval "echo \$$var") >> "${CONFIG_DISTRO_FILE_PATH}" done fi diff --git a/web/pgadmin/evaluate_config.py b/web/pgadmin/evaluate_config.py index a4739604e..2f3e9b150 100644 --- a/web/pgadmin/evaluate_config.py +++ b/web/pgadmin/evaluate_config.py @@ -10,7 +10,7 @@ import os import sys import keyring -import email_validator +import importlib.util # User configs loaded from config_local, config_distro etc. custom_config_settings = {} @@ -27,6 +27,17 @@ def get_variables_from_module(module_name): return variables +# Function to load config_distro at custom path +def import_module_from_path(module_name, file_path): + # Create a module spec + spec = importlib.util.spec_from_file_location(module_name, file_path) + # Create the module based on the spec + module = importlib.util.module_from_spec(spec) + # Execute the module (this loads it) + spec.loader.exec_module(module) + return module + + def validate_config_variable(key, value): boolean_keys = ['SERVER_MODE', 'ENHANCED_COOKIE_PROTECTION', 'SUPPORT_SSH_TUNNEL', 'ALLOW_SAVE_TUNNEL_PASSWORD', @@ -47,7 +58,12 @@ def validate_config_variable(key, value): # Load distribution-specific config overrides try: - import config_distro + if 'CONFIG_DISTRO_FILE_PATH' in os.environ: + config_distro_path = os.environ['CONFIG_DISTRO_FILE_PATH'] + config_distro = import_module_from_path('config_distro', + config_distro_path) + else: + import config_distro config_distro_settings = get_variables_from_module('config_distro') custom_config_settings.update(config_distro_settings) except ImportError: