mirror of
https://github.com/rustfs/rustfs.git
synced 2026-08-13 08:36:54 +00:00
fix(docker): warn instead of rejecting default or missing credentials (#4728)
* fix(docker): warn instead of rejecting default or missing credentials The entrypoint hard-reject from #4278 broke the container-first UX and the repo's own scheduled e2e lanes (e2e-s3tests, mint boot rustfs-ci images with default credentials and died at startup). Maintainer decision: ship no baked-in credentials, warn instead of block. - missing credentials: warn and start; wording accounts for the RUSTFS_ROOT_*/MINIO_* alias sources the entrypoint does not inspect - default rustfsadmin via env/CLI/file: warn and start; the warning notes all-default pairs cannot derive an internode RPC secret - malformed config stays fatal: source conflicts, unreadable files, empty or whitespace-only values, flags missing their argument - present-but-empty env vars now hit the empty-value hard failure instead of running the binary with an empty root credential - empty/default checks trim CR and blanks like the binary; files without a trailing newline are no longer falsely rejected as empty - the no-baked-credentials guard covers all four Dockerfiles, and the test harness refuses hosts where /usr/bin/rustfs exists - e2e-s3tests/mint move to non-default credentials (rustfsadmin-ci), which also restores RPC-secret derivation for the multi-node lane GHSA-68cw fail-closed RPC derivation (#4402) is untouched; helm stays fail-closed by design. * chore(docker): reword entrypoint comment flagged by typos check
This commit is contained in:
+35
-17
@@ -35,15 +35,21 @@ resolve_credential_source() {
|
||||
CREDENTIAL_FILE_SET=false
|
||||
CREDENTIAL_FILE_VALUE=""
|
||||
|
||||
# ${VAR+x} distinguishes unset from present-but-empty: an env var explicitly
|
||||
# set to "" (e.g. an unexpanded compose interpolation) is a malformed value
|
||||
# that must hit the empty-value hard failure, not the missing-credential
|
||||
# warning — the binary would otherwise run with an empty root credential.
|
||||
eval "CREDENTIAL_ENV_PRESENT=\${$CREDENTIAL_ENV_NAME+x}"
|
||||
eval "CREDENTIAL_ENV_VALUE=\${$CREDENTIAL_ENV_NAME:-}"
|
||||
eval "CREDENTIAL_ENV_FILE_PRESENT=\${$CREDENTIAL_FILE_ENV_NAME+x}"
|
||||
eval "CREDENTIAL_ENV_FILE_VALUE=\${$CREDENTIAL_FILE_ENV_NAME:-}"
|
||||
|
||||
if [ -n "$CREDENTIAL_ENV_VALUE" ]; then
|
||||
if [ -n "$CREDENTIAL_ENV_PRESENT" ]; then
|
||||
CREDENTIAL_DIRECT_SET=true
|
||||
CREDENTIAL_DIRECT_VALUE="$CREDENTIAL_ENV_VALUE"
|
||||
fi
|
||||
|
||||
if [ -n "$CREDENTIAL_ENV_FILE_VALUE" ]; then
|
||||
if [ -n "$CREDENTIAL_ENV_FILE_PRESENT" ]; then
|
||||
CREDENTIAL_FILE_SET=true
|
||||
CREDENTIAL_FILE_VALUE="$CREDENTIAL_ENV_FILE_VALUE"
|
||||
fi
|
||||
@@ -103,10 +109,26 @@ resolve_credential_source() {
|
||||
echo "missing"
|
||||
}
|
||||
|
||||
# Mirrors the binary's .trim() so the empty/default checks below agree with
|
||||
# what the server will actually use: strips CR (CRLF-edited files) and
|
||||
# surrounding blanks. Comparison only — the value passed to the binary is
|
||||
# untouched.
|
||||
trim_credential() {
|
||||
printf '%s' "$1" | tr -d '\r' | sed 's/^[[:space:]]*//;s/[[:space:]]*$//'
|
||||
}
|
||||
|
||||
# Credential policy: images ship no baked-in credentials, but default or
|
||||
# missing credentials only WARN — the container still starts (the binary falls
|
||||
# back to its built-in default, and warns when both keys end up default).
|
||||
# Hard failures (ERROR, exit 1) are reserved for malformed configuration
|
||||
# (conflicting sources, unreadable files, empty values). The binary also accepts credentials via
|
||||
# legacy/compat envs (RUSTFS_ROOT_*, MINIO_*) that this script does not
|
||||
# inspect, so the missing-credential warning is phrased conditionally.
|
||||
validate_credential_source() {
|
||||
CREDENTIAL_NAME="$1"
|
||||
FILE_NAME="$2"
|
||||
CREDENTIAL_SOURCE="$3"
|
||||
ALIAS_HINT="$3"
|
||||
CREDENTIAL_SOURCE="$4"
|
||||
|
||||
case "$CREDENTIAL_SOURCE" in
|
||||
error:*)
|
||||
@@ -118,18 +140,16 @@ validate_credential_source() {
|
||||
exit 1
|
||||
;;
|
||||
missing)
|
||||
echo "ERROR: $CREDENTIAL_NAME or $FILE_NAME must be set explicitly for container startup." >&2
|
||||
exit 1
|
||||
echo "WARNING: $CREDENTIAL_NAME or $FILE_NAME is not set; unless credentials are provided via another supported source (e.g. $ALIAS_HINT), rustfs falls back to its built-in default credential. Set non-default credentials for production deployments." >&2
|
||||
;;
|
||||
value:*)
|
||||
CREDENTIAL_VALUE="${CREDENTIAL_SOURCE#value:}"
|
||||
CREDENTIAL_VALUE=$(trim_credential "${CREDENTIAL_SOURCE#value:}")
|
||||
if [ -z "$CREDENTIAL_VALUE" ]; then
|
||||
echo "ERROR: $CREDENTIAL_NAME must not be empty." >&2
|
||||
exit 1
|
||||
fi
|
||||
if [ "$CREDENTIAL_VALUE" = "$DEFAULT_ROOT_CREDENTIAL" ]; then
|
||||
echo "ERROR: $CREDENTIAL_NAME must not use the default $DEFAULT_ROOT_CREDENTIAL credential." >&2
|
||||
exit 1
|
||||
echo "WARNING: $CREDENTIAL_NAME uses the default $DEFAULT_ROOT_CREDENTIAL credential. Set non-default credentials for production deployments; with an all-default pair, multi-node clusters additionally need RUSTFS_RPC_SECRET to derive internode RPC auth." >&2
|
||||
fi
|
||||
;;
|
||||
file:*)
|
||||
@@ -142,18 +162,16 @@ validate_credential_source() {
|
||||
echo "ERROR: $FILE_NAME points to an unreadable file." >&2
|
||||
exit 1
|
||||
fi
|
||||
if IFS= read -r CREDENTIAL_FILE_CONTENT < "$CREDENTIAL_FILE"; then
|
||||
:
|
||||
else
|
||||
CREDENTIAL_FILE_CONTENT=""
|
||||
fi
|
||||
# `read` fails at EOF-without-newline but still fills the variable;
|
||||
# keep the partial line so newline-less secret files stay valid.
|
||||
IFS= read -r CREDENTIAL_FILE_CONTENT < "$CREDENTIAL_FILE" || :
|
||||
CREDENTIAL_FILE_CONTENT=$(trim_credential "$CREDENTIAL_FILE_CONTENT")
|
||||
if [ -z "$CREDENTIAL_FILE_CONTENT" ]; then
|
||||
echo "ERROR: $FILE_NAME must not be empty." >&2
|
||||
exit 1
|
||||
fi
|
||||
if [ "$CREDENTIAL_FILE_CONTENT" = "$DEFAULT_ROOT_CREDENTIAL" ]; then
|
||||
echo "ERROR: $FILE_NAME must not contain the default $DEFAULT_ROOT_CREDENTIAL credential." >&2
|
||||
exit 1
|
||||
echo "WARNING: $FILE_NAME contains the default $DEFAULT_ROOT_CREDENTIAL credential. Set non-default credentials for production deployments; with an all-default pair, multi-node clusters additionally need RUSTFS_RPC_SECRET to derive internode RPC auth." >&2
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
@@ -162,8 +180,8 @@ validate_credential_source() {
|
||||
if [ "$1" = "/usr/bin/rustfs" ]; then
|
||||
ACCESS_SOURCE=$(resolve_credential_source "RUSTFS_ACCESS_KEY" "RUSTFS_ACCESS_KEY_FILE" "access-key" "access-key-file" "$@")
|
||||
SECRET_SOURCE=$(resolve_credential_source "RUSTFS_SECRET_KEY" "RUSTFS_SECRET_KEY_FILE" "secret-key" "secret-key-file" "$@")
|
||||
validate_credential_source "RUSTFS_ACCESS_KEY" "RUSTFS_ACCESS_KEY_FILE" "$ACCESS_SOURCE"
|
||||
validate_credential_source "RUSTFS_SECRET_KEY" "RUSTFS_SECRET_KEY_FILE" "$SECRET_SOURCE"
|
||||
validate_credential_source "RUSTFS_ACCESS_KEY" "RUSTFS_ACCESS_KEY_FILE" "RUSTFS_ROOT_USER or MINIO_ROOT_USER" "$ACCESS_SOURCE"
|
||||
validate_credential_source "RUSTFS_SECRET_KEY" "RUSTFS_SECRET_KEY_FILE" "RUSTFS_ROOT_PASSWORD or MINIO_ROOT_PASSWORD" "$SECRET_SOURCE"
|
||||
fi
|
||||
|
||||
# 2) Process data volumes (separate from log directory)
|
||||
|
||||
Reference in New Issue
Block a user