Open kale1d0code opened 5 months ago
If you have examples for how you would propose for this to work, we are happy to consider implementing them into the project.
take the DB_SETUP_PASS environment variable as an example
you can expect a DB_SETUP_PASS_FILE environment variable which would be set to a file path (typically /run/secrets/
if this environment variable is set then take the contents of the file found in DB_SETUP_PASS_FILE and set DB_SETUP_PASS with it. if the environment variable is not set then it can check to see if DB_SETUP_PASS has been set otherwise use a default.
I made the following for my own docker images:
load_envs() {
local var_str="$1"
local var
local def
for pair in $var_str; do
var="${pair%%:-*}"
def="${pair#*:-}"
file_env "$var" "$def"
done
}
file_env() {
local var="$1"
local fileVar="${var}_FILE"
local def="${2:-}"
local varVal=$(eval "echo \$$var")
local fileVarVal=$(eval "echo \$$fileVar")
if [ -n "$varVal" ] && [ -n "$fileVarVal" ]; then
echo >&2 "error: both $var and $fileVar are set (but are exclusive)"
exit 1
fi
local val="$def"
if [ -n "$varVal" ]; then
val="$varVal"
elif [ -n "$fileVarVal" ]; then
echo "loading $var from file"
val=$(< "$fileVarVal")
fi
export "$var"="$val"
unset "$fileVar"
}
and can be used like
load_envs "DATABASE_HOST DATABASE_PORT:-3306 DATABASE_NAME DATABASE_USER DATABASE_PASS ADMIN_USER:-admin ADMIN_PASS:-secret"
I have also made sure that these functions work in a posix compliant environment
placing values like passwords for database connections or certificates for tls within environment variables is inherently insecure as these can easily be printed out and more importantly it mixes sensitive information with deployment files (passwords embedded in docker-compose files etc) docker secrets avoid this issue by mounting a file containing the secret within /run/secrets/ and then only populating the environment variable the secret is for on the process which docker is watching inside the container. any other process like a shell session into the container will not be able to see the secret within the environment variable.
This can be taken one step further by changing the config.php file to use a function to resolve the values from environment variables instead of the values being stored plain text within the config file. Wordpress takes a similar approach with their docker flavour of deployment using a function to populate their config file from environment variables.
The function I provided would be used within the entrypoint script to populate the environment variables containing secrets. The PHP function for the config.php is not required although would synergise with the entrypoint function.
This would enable end users to set secrets for the root database password, database name, user name, hostname, etc.
example docker-compose file could be as follows:
version: 3.8
secrets:
dbms_root_pass:
external: true
name: grc-dbms-root-pass
db_name:
external: true
name: grc-db-name
db_user:
external: true
name: grc-db-user
db_pass:
external: true
name: grc-db-pass
services:
simplerisk:
image: simplerisk/simplerisk-minimal:${SIMPLERISK_VERSION:-latest}
restart: always
depends_on:
- dbms
environment:
- SIMPLERISK_DB_HOSTNAME=dbms
- SIMPLERISK_DB_PORT=3306
- DB_SETUP=manual
- DB_SETUP_USER=root
- DB_SETUP_PASS_FILE=/run/secrets/dbms_root_pass
- SIMPLERISK_DB_USERNAME_FILE=/run/secrets/db_user
- SIMPLERISK_DB_PASSWORD_FILE=/run/secrets/db_pass
- SIMPLERISK_DB_DATABASE_FILE=/run/secrets/db_name
- SIMPLERISK_DB_FOR_SESSIONS=false
- SIMPLERISK_CRON_SETUP=true
secrets:
- db_name
- db_user
- db_pass
- dbms_root_pass
dbms:
image: mariadb:${MARIADB_VERSION}
restart: always
command: --sql-mode=""
environment:
- MARIADB_ROOT_PASSWORD_FILE=/run/secrets/dbms_root_pass
#- MARIADB_DATABASE_FILE=/run/secrets/db_name
#- MARIADB_USER_FILE=/run/secrets/db_user
#- MARIADB_PASSWORD_FILE=/run/secrets/db_pass
secrets:
#- db_name
#- db_user
#- db_pass
- dbms_root_pass
I sincerely appreciate the additional explanation. We are a product built by and for security practitioners so I understood the value proposition when you originally mentioned it. That's why it has remained open. That said, all of our resources are tied up working on other projects right now so this will need to be on the backburner. I will keep it open as a reminder of a future enhancement to the Docker image, but since both our customers and us use these images, changing them would need to come with a deployment plan, as well, so no small task.
the readme does not provide information on how to use secrets, many projects opt for a prefix or suffix like "_FILE" for their environment variables.
I have a posix compliant function for fetching secrets and populating environment variables if you need one provided. my function also supports default values if the variable is not set.