feat(validation): catch a container running a different secret than the config
Speedtest's config held one password while its container ran another, so the WebUI credentials card advertised a login that could not work. Validation only caught it by accident: the rename left a stale tag behind, and the tag-name check fired on that. Had the rename kept the name, the divergence would have been invisible — and it is the divergence, not the tag, that actually breaks someone's login. So compare them directly: for every app-prefixed tag in the DEPLOYED compose, check the substituted value against the deployed config's. Live files only — in the templates one side is a placeholder and the other a RANDOMIZED token, so they could never agree. Resolves the slot rather than giving up: a compose written before a key gained its _<n> suffix still carries the old tag, so fall back to the numbered variant and compare anyway. That is warned about, not passed over — the compose is due a re-template — but the warning is separate from the failure, so a stale name with matching values reports only the warning. Verified both ways against a fixture of speedtest's real pre-fix state (warning plus failure), the same fixture with values agreed (warning only), and the live install across 39 apps (silent). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
parent
6861358809
commit
abcfdc134a
@ -116,6 +116,56 @@ _lpvCheckDeployedSecrets()
|
||||
| sed 's/^[^=]*=//' | tr -d '"' | sort | uniq -d)
|
||||
}
|
||||
|
||||
# --- deployed: does the container actually run what the config advertises? --
|
||||
# Only meaningful on a live install, where both sides hold real values: in the
|
||||
# templates one side is a placeholder and the other a RANDOMIZED token, so they
|
||||
# would never match.
|
||||
#
|
||||
# This is the symptom that matters. Speedtest's config said one password while
|
||||
# its container ran another, so the WebUI credentials card showed a login that
|
||||
# could not work — and nothing detected it, because the tag-name check only
|
||||
# caught it by accident (the rename left a stale tag behind). Had the rename kept
|
||||
# the name, the divergence would have been invisible.
|
||||
#
|
||||
# Slot resolution: a deployed compose written before a key gained its _<n> slot
|
||||
# still carries the old tag, so fall back to the numbered variant rather than
|
||||
# giving up — but say so, because that compose is due a re-template.
|
||||
_lpvCheckDeployedValues()
|
||||
{
|
||||
local app="$1" cfg="$2" comp="$3"
|
||||
[[ -n "$cfg" && -n "$comp" ]] || return 0
|
||||
local up="${app^^}"; up="${up//-/_}"
|
||||
|
||||
local line tag val key slot cfgval
|
||||
while IFS='|' read -r tag val; do
|
||||
[[ -n "$tag" && -n "$val" ]] || continue
|
||||
key="CFG_${tag%_TAG}"
|
||||
|
||||
cfgval=$(grep -m1 "^${key}=" "$cfg" 2>/dev/null | cut -d= -f2-)
|
||||
if [[ -z "$cfgval" ]]; then
|
||||
# No exact key — try the slot the rename introduced.
|
||||
slot=$(grep -m1 -oE "^CFG_${tag%_TAG}_[0-9]+=" "$cfg" 2>/dev/null | tr -d '=')
|
||||
[[ -n "$slot" ]] || continue
|
||||
_lpvWarn "$app: compose still uses ${tag}, but the config declares ${slot} — re-template ('libreportal app install $app') so the name matches."
|
||||
key="$slot"
|
||||
cfgval=$(grep -m1 "^${key}=" "$cfg" 2>/dev/null | cut -d= -f2-)
|
||||
fi
|
||||
|
||||
cfgval="${cfgval%%#*}"
|
||||
cfgval="${cfgval//\"/}"
|
||||
cfgval="${cfgval//[[:space:]]/}"
|
||||
# Not generated yet, or the compose still holds its placeholder: other
|
||||
# checks own those cases.
|
||||
[[ -z "$cfgval" || "$cfgval" == RANDOMIZED* ]] && continue
|
||||
[[ "$val" =~ ^[A-Z][A-Z0-9_]*_DATA(_[0-9]+)?$ ]] && continue
|
||||
|
||||
if [[ "$cfgval" != "$val" ]]; then
|
||||
_lpvFail "$app: $key in the config does not match what the container runs (tag $tag) — anything showing this value, the WebUI card included, is advertising something that will not work."
|
||||
fi
|
||||
done < <(grep -oE "#LIBREPORTAL\|${up}_[A-Z0-9_]+_TAG\|[^|[:space:]]+" "$comp" 2>/dev/null \
|
||||
| sed 's/#LIBREPORTAL|//' | sed 's/_TAG|/_TAG|/' | awk -F'|' '!seen[$1]++ {print $1"|"$2}')
|
||||
}
|
||||
|
||||
# --- compose: annotations substitutable, tags backed -----------------------
|
||||
_lpvCheckCompose()
|
||||
{
|
||||
@ -215,6 +265,7 @@ validateAppConfiguration()
|
||||
_lpvCheckCompose "$app" "${_lpv_comp_live:-$_lpv_comp_tmpl}" \
|
||||
"$( [[ -n "$_lpv_comp_live" ]] && echo "deployed compose" || echo "compose template" )" \
|
||||
"${_lpv_cfg_live:-$_lpv_cfg_tmpl}"
|
||||
_lpvCheckDeployedValues "$app" "$_lpv_cfg_live" "$_lpv_comp_live"
|
||||
_lpvCheckAuthAdapter "$app" "${_lpv_cfg_live:-$_lpv_cfg_tmpl}"
|
||||
|
||||
# A single-app run that says nothing is indistinguishable from one that did
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user