Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .github/workflows/container-validation.yml
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,9 @@ jobs:
- name: simplerisk-minimal credential escaping
run: ./simplerisk-minimal/test_escaping.sh

- name: simplerisk-minimal DB TLS flags per mysql client
run: ./simplerisk-minimal/test_db_ssl_flags.sh

- name: simplerisk-minimal Apache worker setting
run: ./simplerisk-minimal/test_set_apache_workers.sh

Expand Down
2 changes: 1 addition & 1 deletion simplerisk-minimal/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ docker run -d --name simplerisk -e SIMPLERISK_DB_PASSWORD=pass -e SIMPLERISK_DB_
| `DB_SETUP_PASS` | `root` (the bundled `stack.yml` ships `simplerisk_setup`) | Used when `DB_SETUP=automatic\|automatic-only\|delete`. Password of the privileged MySQL user used **only** to install the SimpleRisk schema and create the app DB user. In `stack.yml` it is also the bundled MySQL root password; since that MySQL is not exposed outside the stack network, a documented default is used for the zero-config trial. Override it (and `MYSQL_ROOT_PASSWORD` in `stack.yml`) for any non-trial deployment. |
| `DB_SETUP_WAIT` | 20 | Used when `DB_SETUP=automatic\|automatic-only`. Time, in seconds, the application is going to wait to set up the database. Useful if you are deploying the database and SimpleRisk at the same time |
| `DB_UPGRADE` | `null` (Accepts any value) | Run SimpleRisk's release-by-release database **schema upgrade** against an already-installed database (as opposed to `DB_SETUP`, which installs a fresh one), then continue running (`automatic`) or stop the container (`automatic-only`, for a one-shot upgrade job). Uses the `SIMPLERISK_DB_*` application credentials — no privileged user. The structured per-release JSON result is written to the container log, and the container exits non-zero if the upgrade fails. Idempotent — a no-op when the schema is already current |
| `DB_SSL_ENABLED` | `false` (off) | Opt-in, used when `DB_SETUP=automatic\|automatic-only\|delete`. Set to exactly `true` to require TLS on the privileged setup/delete MySQL client connection (adds `--ssl-mode=REQUIRED --enable-cleartext-plugin`). Any other value, or unset, leaves the connection unchanged (plaintext-capable) |
| `DB_SSL_ENABLED` | `false` (off) | Opt-in, used when `DB_SETUP=automatic\|automatic-only\|delete`. Set to exactly `true` to require TLS on the privileged setup/delete MySQL client connection (adds `--ssl-mode=REQUIRED --enable-cleartext-plugin`; on the arm64 image, whose `mysql` is MariaDB's client and has no `--ssl-mode`, it adds the equivalent `--ssl --skip-ssl-verify-server-cert`). Any other value, or unset, leaves the connection unchanged (plaintext-capable) |
| `SIMPLERISK_DB_HOSTNAME` | `localhost` | Hostname of the database server |
| `SIMPLERISK_DB_PORT` | 3306 | Port to contact the database |
| `SIMPLERISK_DB_USERNAME` |`simplerisk` | User name to be used to access the SimpleRisk database |
Expand Down
22 changes: 20 additions & 2 deletions simplerisk-minimal/common/entrypoint.sh
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ config_define() {
# password via MYSQL_PWD, so no value is subject to shell interpretation.
mysql_setup() {
local -a flags=()
# DB_SSL_FLAGS is an internal constant ("--ssl-mode=... --enable-cleartext-plugin")
# DB_SSL_FLAGS is an internal value from set_db_ssl_flags (client-specific TLS flags)
[ -n "${DB_SSL_FLAGS:-}" ] && read -ra flags <<< "$DB_SSL_FLAGS"
MYSQL_PWD="$DB_SETUP_PASS" mysql ${flags[@]+"${flags[@]}"} \
-u "$DB_SETUP_USER" -h "$SIMPLERISK_DB_HOSTNAME" -P "$SIMPLERISK_DB_PORT"
Expand Down Expand Up @@ -473,14 +473,32 @@ set_mail_settings(){
[ -n "${MAIL_PASSWORD:-}" ] && apply_mail_setting phpmailer_password "$MAIL_PASSWORD" || true
}

# True when the mysql client understands --ssl-mode. Oracle's client does (amd64 image). MariaDB's
# does not, and it is the only client packaged for arm64 (MySQL's apt repo has no arm64 builds), so
# there `mysql` rejects it with "unknown variable 'ssl-mode=REQUIRED'". If the client cannot be asked,
# assume Oracle's, which is what these flags were written for.
mysql_client_supports_ssl_mode() {
local help
help=$(mysql --help 2>/dev/null) || return 0
[ -n "$help" ] || return 0
grep -q -- '--ssl-mode' <<< "$help"
}

set_db_ssl_flags(){
# Some databases require the privileged setup/delete mysql client to send
# its credential via the cleartext auth plugin, which the server only
# accepts over TLS (e.g. when DB_SETUP_PASS is a short-lived auth token
# rather than a static password). Set DB_SSL_ENABLED=true to opt in.
DB_SSL_FLAGS=""
if [ "${DB_SSL_ENABLED:-}" = "true" ]; then
DB_SSL_FLAGS="--ssl-mode=REQUIRED --enable-cleartext-plugin"
if mysql_client_supports_ssl_mode; then
DB_SSL_FLAGS="--ssl-mode=REQUIRED --enable-cleartext-plugin"
else
# MariaDB client: --ssl makes TLS mandatory and --skip-ssl-verify-server-cert matches
# REQUIRED (encrypt, do not verify the certificate). The cleartext plugin is built in;
# --enable-cleartext-plugin is obsolete there and only prints a warning.
DB_SSL_FLAGS="--ssl --skip-ssl-verify-server-cert"
fi
fi
}

Expand Down
72 changes: 72 additions & 0 deletions simplerisk-minimal/test_db_ssl_flags.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
#!/usr/bin/env bash
# Verifies set_db_ssl_flags in common/entrypoint.sh picks TLS flags the installed mysql client
# understands. Oracle's client (amd64 image) takes --ssl-mode=REQUIRED --enable-cleartext-plugin.
# MariaDB's client (arm64 image: Debian's default-mysql-client, since MySQL's apt repo has no arm64
# packages) rejects --ssl-mode ("unknown variable 'ssl-mode=REQUIRED'"), which made every DB setup
# and delete fail on Graviton against a TLS-only RDS. Its equivalent is --ssl plus
# --skip-ssl-verify-server-cert (TLS required, server certificate not verified: the same as
# REQUIRED); the cleartext plugin is built in and --enable-cleartext-plugin is obsolete there.
#
# `mysql` is faked with --help output shaped like the real clients (the MariaDB lines were captured
# from mariadb 11.8.6 in the arm64 image). Requires bash >= 4.
set -uo pipefail
cd "$(dirname "$(readlink -f "$0")")" || exit 1

fail=0
ok() { echo "ok: $1"; }
bad() { echo "FAIL: $1"; echo " expected: $2"; echo " actual: $3"; fail=1; }
check() { [ "$2" = "$3" ] && ok "$1" || bad "$1" "$2" "$3"; }

work=$(mktemp -d); trap 'rm -rf "$work"' EXIT
mkdir -p "$work/mysql-oracle" "$work/mariadb" "$work/none"

cat > "$work/mysql-oracle/mysql" <<'FAKE'
#!/bin/sh
cat <<'HELP'
mysql Ver 8.4.8 for Linux on x86_64 (MySQL Community Server - GPL)
--ssl-mode=name SSL connection mode.
--ssl-ca=name CA file in PEM format.
--enable-cleartext-plugin
Enable/disable the clear text authentication plugin.
HELP
FAKE
cat > "$work/mariadb/mysql" <<'FAKE'
#!/bin/sh
cat <<'HELP'
mysql from 11.8.6-MariaDB, client 15.2 for debian-linux-gnu (aarch64)
--ssl Enable SSL for connection (automatically enabled with
--ssl-ca=name CA file in PEM format (check OpenSSL docs, implies
--ssl-verify-server-cert
Verify server's "Common Name" in its cert against
HELP
FAKE
chmod +x "$work/mysql-oracle/mysql" "$work/mariadb/mysql"

# Pull in only the functions under test.
eval "$(sed -n '/^mysql_client_supports_ssl_mode() {/,/^}/p;/^set_db_ssl_flags(){/,/^}/p' common/entrypoint.sh)"

# flags_with <client dir|none> <DB_SSL_ENABLED value|unset>
flags_with() {
( PATH="$work/$1:/usr/bin:/bin"
[ "$1" = none ] && PATH="$work/none:/nonexistent"
if [ "$2" = unset ]; then unset DB_SSL_ENABLED; else DB_SSL_ENABLED="$2"; fi
set_db_ssl_flags; printf '%s' "$DB_SSL_FLAGS" )
}

# Oracle client: behaviour must be exactly what it was (amd64 images depend on it).
check "oracle client + DB_SSL_ENABLED=true" "--ssl-mode=REQUIRED --enable-cleartext-plugin" "$(flags_with mysql-oracle true)"
# MariaDB client: no flag it rejects.
got=$(flags_with mariadb true)
check "mariadb client + DB_SSL_ENABLED=true" "--ssl --skip-ssl-verify-server-cert" "$got"
case "$got" in *--ssl-mode*) bad "mariadb flags must not contain --ssl-mode" "(none)" "$got";; *) ok "mariadb flags contain no --ssl-mode";; esac
case "$got" in *--enable-cleartext-plugin*) bad "mariadb flags must not contain the obsolete --enable-cleartext-plugin" "(none)" "$got";; *) ok "mariadb flags contain no --enable-cleartext-plugin";; esac
# Opt-in only: anything but exactly "true" leaves the connection unchanged, for either client.
for c in mysql-oracle mariadb; do
for v in unset false TRUE 1 ""; do
check "$c + DB_SSL_ENABLED='$v' -> no flags" "" "$(flags_with $c "$v")"
done
done
# If the client cannot be asked (not on PATH), keep the historical flags rather than guess.
check "no mysql on PATH + DB_SSL_ENABLED=true keeps the historical flags" "--ssl-mode=REQUIRED --enable-cleartext-plugin" "$(flags_with none true)"

exit $fail
Loading