From 7498d5439a266e39fa84799623390de09f103453 Mon Sep 17 00:00:00 2001 From: girish pasupathy Date: Thu, 16 Apr 2020 11:49:40 +0530 Subject: [PATCH] Support for reading Mariadb and Admin password from file when using docker secrets With this PR, password can be read from docker secrets in both compose as well as swarm environment. ```YAML secrets: mariadb-root-password: file: mariadb-root-password.txt erpnext-admin-password: file: erpnext-admin-password.txt services: erpnext: image: frappe/erpnext-worker:${ERPNEXT_VERSION:-v12.5.2} environment: - SITE_NAME=example.com - DB_ROOT_USER=root - MARIADB_HOST=mariadb - INSTALL_APPS=erpnext - FORCE=1 - REDIS_CACHE=redis-cache:6379 - REDIS_QUEUE=redis-queue:6379 - REDIS_SOCKETIO=redis-socketio:6379 - SOCKETIO_PORT=9000 - AUTO_MIGRATE=1 - ADMIN_PASSWORD_FILE=/run/secrets/erpnext-admin-password - MYSQL_ROOT_PASSWORD_FILE=/run/secrets/mariadb-root-password secrets: - erpnext-admin-password - mariadb-root-password restart: on-failure volumes: - erpnext-data:/home/frappe/frappe-bench/sites - assets-data:/home/frappe/frappe-bench/sites/assets links: - redis-cache - redis-queue - redis-socketio - mariadb depends_on: - mariadb - redis-cache - redis-queue - redis-socketio networks: - erpnext-net ``` Reference: [Addind docker secrets in to your images](https://docs.docker.com/engine/swarm/secrets/#build-support-for-docker-secrets-into-your-images) Changes to be committed: modified: ../../README.md modified: ../common/commands/new.py modified: ../common/commands/restore_backup.py modified: ../erpnext-nginx/docker-entrypoint.sh --- README.md | 6 ++++-- build/common/commands/new.py | 26 ++++++++++++++++++++++-- build/common/commands/restore_backup.py | 5 +++-- build/erpnext-nginx/docker-entrypoint.sh | 4 ++-- 4 files changed, 33 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 0f090c8f..a71ff7dd 100644 --- a/README.md +++ b/README.md @@ -209,7 +209,9 @@ Environment Variables needed: - `SITE_NAME`: name of the new site to create. - `DB_ROOT_USER`: MariaDB Root user. - `MYSQL_ROOT_PASSWORD`: In case of the MariaDB docker container use the one set in `MYSQL_ROOT_PASSWORD` in previous steps. In case of a managed database use the appropriate password. +- `MYSQL_ROOT_PASSWORD_FILE` - When the MariaDB root password is stored using docker secrets. - `ADMIN_PASSWORD`: set the administrator password for the new site. +- `ADMIN_PASSWORD_FILE`: set the administrator password for the new site using docker secrets. - `INSTALL_APPS=erpnext`: available only in erpnext-worker and erpnext containers (or other containers with custom apps). Installs ERPNext (and/or the specified apps, comma-delinieated) on this new site. - `FORCE=1`: optional variable which force installation of the same site. @@ -293,7 +295,7 @@ docker exec -it \ Environment Variables -- `MYSQL_ROOT_PASSWORD`, Required to restore mariadb backups. +- `MYSQL_ROOT_PASSWORD` or `MYSQL_ROOT_PASSWORD_FILE`(when using docker secrets), Required to restore mariadb backups. - `BUCKET_NAME`, Required to set bucket created on S3 compatible storage. - `ACCESS_KEY_ID`, Required to set access key. - `SECRET_ACCESS_KEY`, Required to set secret access key. @@ -464,4 +466,4 @@ This repository includes a complete setup to develop with Frappe/ERPNext and Ben - VSCode Python debugger - Pre-configured Docker containers for an easy start -A complete Readme is available in [development/README.md](development/README.md) \ No newline at end of file +A complete Readme is available in [development/README.md](development/README.md) diff --git a/build/common/commands/new.py b/build/common/commands/new.py index 5fbe2cb9..48ea44fb 100644 --- a/build/common/commands/new.py +++ b/build/common/commands/new.py @@ -3,10 +3,32 @@ import os, frappe, json from frappe.commands.site import _new_site from check_connection import get_config, get_site_config +def get_password(env_var, default=None): + return os.environ.get(env_var) or _get_password_from_secret(f"{env_var}_FILE") or default + + +def _get_password_from_secret(env_var): + """Fetches the secret value from the docker secret file + usually located inside /run/secrets/ + Arguments: + env_var {str} -- Name of the environment variable + containing the path to the secret file. + Returns: + [str] -- Secret value + """ + passwd = None + secret_file_path = os.environ.get(env_var) + if secret_file_path: + with open(secret_file_path) as secret_file: + passwd = secret_file.read().strip() + + return passwd + + def main(): site_name = os.environ.get("SITE_NAME", 'site1.localhost') mariadb_root_username = os.environ.get("DB_ROOT_USER", 'root') - mariadb_root_password = os.environ.get("MYSQL_ROOT_PASSWORD", 'admin') + mariadb_root_password = get_password("MYSQL_ROOT_PASSWORD", 'admin') force = True if os.environ.get("FORCE", None) else False install_apps = os.environ.get("INSTALL_APPS", None) install_apps = install_apps.split(',') if install_apps else [] @@ -17,7 +39,7 @@ def main(): site_name, mariadb_root_username=mariadb_root_username, mariadb_root_password=mariadb_root_password, - admin_password=os.environ.get("ADMIN_PASSWORD", 'admin'), + admin_password=get_password("ADMIN_PASSWORD", 'admin'), verbose=True, install_apps=install_apps, source_sql=None, diff --git a/build/common/commands/restore_backup.py b/build/common/commands/restore_backup.py index 82854e85..f248bbf7 100644 --- a/build/common/commands/restore_backup.py +++ b/build/common/commands/restore_backup.py @@ -5,6 +5,7 @@ import hashlib import frappe import boto3 +from new import get_password from push_backup import DATE_FORMAT, check_environment_variables from frappe.utils import get_sites, random_string from frappe.commands.site import _new_site @@ -38,7 +39,7 @@ def decompress_db(files_base, site): os.system(command) def restore_database(files_base, site): - db_root_password = os.environ.get('MYSQL_ROOT_PASSWORD') + db_root_password = get_password('MYSQL_ROOT_PASSWORD') if not db_root_password: print('Variable MYSQL_ROOT_PASSWORD not set') exit(1) @@ -158,7 +159,7 @@ def main(): restore_private_files(files_base) restore_files(files_base) else: - mariadb_root_password = os.environ.get('MYSQL_ROOT_PASSWORD') + mariadb_root_password = get_password('MYSQL_ROOT_PASSWORD') if not mariadb_root_password: print('Variable MYSQL_ROOT_PASSWORD not set') exit(1) diff --git a/build/erpnext-nginx/docker-entrypoint.sh b/build/erpnext-nginx/docker-entrypoint.sh index aec5b0aa..c1caad54 100755 --- a/build/erpnext-nginx/docker-entrypoint.sh +++ b/build/erpnext-nginx/docker-entrypoint.sh @@ -40,8 +40,8 @@ envsubst '${API_HOST} echo "Waiting for frappe-python to be available on $FRAPPE_PY port $FRAPPE_PY_PORT" timeout 10 bash -c 'until printf "" 2>>/dev/null >>/dev/tcp/$0/$1; do sleep 1; done' $FRAPPE_PY $FRAPPE_PY_PORT echo "Frappe-python available on $FRAPPE_PY port $FRAPPE_PY_PORT" -echo "Waiting for frappe-socketio to be available on $FRAPPE_PY port $FRAPPE_PY_PORT" +echo "Waiting for frappe-socketio to be available on $FRAPPE_SOCKETIO port $SOCKETIO_PORT" timeout 10 bash -c 'until printf "" 2>>/dev/null >>/dev/tcp/$0/$1; do sleep 1; done' $FRAPPE_SOCKETIO $SOCKETIO_PORT -echo "Frappe-socketio available on $FRAPPE_PY port $FRAPPE_PY_PORT" +echo "Frappe-socketio available on $FRAPPE_SOCKETIO port $SOCKETIO_PORT" exec "$@"