fix(openbao): write .env through set_env, not an interpolated sed

947c899 removed this idiom from copyparty, headscale, pocket-id and squid;
openbao was missed. Its first-run seed still interpolated values into
`sed -i -e "s|^KEY=.*|KEY=${VAL}|"`, which silently corrupts any value
containing & (sed expands it to the whole match) and aborts the run under
set -e on one containing the s||| delimiter.

That was survivable while .env held only an address, a bind and an image tag.
It stops being survivable the moment an OIDC client secret or an issuer URL
with a query string goes in there, which is the next commit -- so this lands
first, on its own, with no behaviour change.

Adds the same awk/ENVIRON helper the other four use, replaces the seed's sed
block with set_env calls, and collapses the inlined copy of that awk (added
in dc9761a for the UI write-through) into a call to it.

Verified against plain, sec&ret, pipe|val, back\slash, an Authentik-shaped
discovery URL with an & query string, p@ss&w|rd and the empty string; plus
non-target lines left intact and the 0600 mode preserved across an in-place
update.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-09-16 15:09:35 -05:00
co-authored by Claude Opus 5
parent dc9761a668
commit 185f404549
+27 -14
View File
@@ -320,15 +320,35 @@ log "Web UI: ${UI_HCL} (OPENBAO_UI=${EFFECTIVE_UI})"
install -m 0750 "$SCRIPT_DIR/gen-tls.sh" "$STACK_DIR/gen-tls.sh"
ENV_FILE="$STACK_DIR/.env"
set_env() { # <KEY> <value>: update KEY in .env, or append if absent
# The value goes through the ENVIRONMENT, never interpolated into a sed
# script. Interpolating it corrupts any value containing & (sed expands it
# to the whole match) and aborts the run on one containing the s|||
# delimiter -- both reachable for an OIDC client secret or an issuer URL
# with a query string. Same helper as 947c899 gave the other stacks.
local key="$1" val="$2" tmp
if [[ ! -f "$ENV_FILE" ]]; then
printf '%s=%s\n' "$key" "$val" >> "$ENV_FILE"
return 0
fi
tmp="$(mktemp)"
_SE_KEY="$key" _SE_VAL="$val" awk '
BEGIN { k = ENVIRON["_SE_KEY"]; v = ENVIRON["_SE_VAL"]; seen = 0 }
!seen && index($0, k "=") == 1 { print k "=" v; seen = 1; next }
{ print }
END { if (!seen) print k "=" v }
' "$ENV_FILE" > "$tmp"
cat "$tmp" > "$ENV_FILE" # rewrite in place: keeps the 0600 mode/owner
rm -f "$tmp"
}
if [[ ! -f "$ENV_FILE" ]]; then
log "Seeding $ENV_FILE..."
install -m 0600 "$SCRIPT_DIR/.env.example" "$ENV_FILE"
sed -i \
-e "s|^OPENBAO_ADDR=.*|OPENBAO_ADDR=${OPENBAO_ADDR}|" \
-e "s|^OPENBAO_BIND=.*|OPENBAO_BIND=${OPENBAO_BIND}|" \
-e "s|^OPENBAO_TLS_SANS=.*|OPENBAO_TLS_SANS=${SANS}|" \
-e "s|^OPENBAO_UI=.*|OPENBAO_UI=${EFFECTIVE_UI}|" \
"$ENV_FILE"
set_env OPENBAO_ADDR "$OPENBAO_ADDR"
set_env OPENBAO_BIND "$OPENBAO_BIND"
set_env OPENBAO_TLS_SANS "$SANS"
set_env OPENBAO_UI "$EFFECTIVE_UI"
else
log ".env exists; leaving it alone."
# ...except a UI switch passed to THIS run: config.hcl is rendered from
@@ -337,14 +357,7 @@ else
if [[ "$UI_FROM_ENV" == "1" ]]; then
_cur_ui=$(sed -n 's/^OPENBAO_UI=//p' "$ENV_FILE" | tail -n1)
if [[ "$_cur_ui" != "$EFFECTIVE_UI" ]]; then
_t=$(mktemp)
_SE_V="$EFFECTIVE_UI" awk '
BEGIN { v = ENVIRON["_SE_V"]; seen = 0 }
!seen && index($0, "OPENBAO_UI=") == 1 { print "OPENBAO_UI=" v; seen = 1; next }
{ print }
END { if (!seen) print "OPENBAO_UI=" v }
' "$ENV_FILE" > "$_t"
cat "$_t" > "$ENV_FILE"; rm -f "$_t"
set_env OPENBAO_UI "$EFFECTIVE_UI"
log " OPENBAO_UI: ${_cur_ui:-<unset>} -> ${EFFECTIVE_UI}"
fi
fi