82 lines
3.6 KiB
Bash
Executable File
82 lines
3.6 KiB
Bash
Executable File
#!/bin/bash
|
|
# ansipa-portal-auth-setup.sh — generate the HTTP Basic Auth credential file
|
|
# that gates the ansipa nginx gateway (portal + every proxied web UI).
|
|
#
|
|
# Runs on every container start via ansipa-portal-auth.service so the
|
|
# htpasswd file is always in place after container recreation (rootfs is
|
|
# ephemeral; only /data survives). The file itself is written to the shared
|
|
# 'portal-auth' volume so the nginx container (which has no access to /data)
|
|
# can read it — same pattern as the cmk-creds volume shared with checkmk.
|
|
#
|
|
# This is a DELIBERATE extra sign-in layer in front of the whole gateway —
|
|
# FreeIPA, CheckMK and Keycloak all still enforce their own logins behind it.
|
|
# Two prompts beats one attacker who only had to beat one lock.
|
|
#
|
|
# Password sources (first match wins):
|
|
# 1. ANSIPA_PORTAL_PASSWORD env var (first boot / explicit override)
|
|
# 2. /data/portal-auth.env (persisted from first boot)
|
|
# 3. auto-generated, logged once (so nothing is silently left with a
|
|
# predictable/blank credential)
|
|
#
|
|
# To add more accounts later, hand-edit the persisted file directly:
|
|
# printf 'alice:%s\n' "$(openssl passwd -apr1 'their password')" \
|
|
# >> /data/portal-auth/htpasswd (then re-copy to the shared volume, or
|
|
# just re-run this script with ANSIPA_PORTAL_USER=alice ANSIPA_PORTAL_PASSWORD=...
|
|
# — it appends/updates rather than truncating).
|
|
|
|
set -euo pipefail
|
|
|
|
LOG_TAG="ansipa-portal-auth-setup"
|
|
ENV_FILE="/data/portal-auth.env"
|
|
PERSIST_HTPASSWD="/data/portal-auth/htpasswd"
|
|
SHARED_HTPASSWD="/portal-auth/htpasswd" # mounted from the portal-auth docker volume
|
|
|
|
log() { echo "[$LOG_TAG] $*"; }
|
|
warn() { echo "[$LOG_TAG][WARN] $*" >&2; }
|
|
|
|
mkdir -p "$(dirname "$PERSIST_HTPASSWD")" /portal-auth
|
|
|
|
PORTAL_USER="${ANSIPA_PORTAL_USER:-}"
|
|
PORTAL_PASS="${ANSIPA_PORTAL_PASSWORD:-}"
|
|
|
|
if [[ -f "$ENV_FILE" ]]; then
|
|
# shellcheck source=/dev/null
|
|
source "$ENV_FILE"
|
|
PORTAL_USER="${ANSIPA_PORTAL_USER:-$PORTAL_USER}"
|
|
PORTAL_PASS="${ANSIPA_PORTAL_PASSWORD:-$PORTAL_PASS}"
|
|
fi
|
|
|
|
PORTAL_USER="${PORTAL_USER:-ansipa}"
|
|
|
|
if [[ -z "$PORTAL_PASS" ]]; then
|
|
PORTAL_PASS=$(tr -dc 'A-Za-z0-9' < /dev/urandom 2>/dev/null | head -c 32 \
|
|
|| openssl rand -base64 24 | tr -d '/+=\n')
|
|
warn "ANSIPA_PORTAL_PASSWORD not set — generated one for user '$PORTAL_USER':"
|
|
warn " $PORTAL_PASS"
|
|
warn "Set ANSIPA_PORTAL_PASSWORD in .env to pin it; otherwise it is reused as-is on every restart."
|
|
fi
|
|
|
|
# ── Persist for subsequent restarts ──────────────────────────────────────────
|
|
{
|
|
printf 'ANSIPA_PORTAL_USER=%q\n' "$PORTAL_USER"
|
|
printf 'ANSIPA_PORTAL_PASSWORD=%q\n' "$PORTAL_PASS"
|
|
} > "$ENV_FILE"
|
|
chmod 600 "$ENV_FILE"
|
|
|
|
# ── Write the htpasswd entry (apr1 — natively understood by nginx's
|
|
# auth_basic_module, no dependency on the base image's libc crypt()) ─────────
|
|
HASH=$(openssl passwd -apr1 "$PORTAL_PASS")
|
|
|
|
touch "$PERSIST_HTPASSWD"
|
|
# Replace this user's line if present, else append.
|
|
grep -vE "^${PORTAL_USER}:" "$PERSIST_HTPASSWD" > "${PERSIST_HTPASSWD}.tmp" 2>/dev/null || true
|
|
printf '%s:%s\n' "$PORTAL_USER" "$HASH" >> "${PERSIST_HTPASSWD}.tmp"
|
|
mv "${PERSIST_HTPASSWD}.tmp" "$PERSIST_HTPASSWD"
|
|
chmod 644 "$PERSIST_HTPASSWD"
|
|
|
|
# ── Publish to the volume nginx reads from ───────────────────────────────────
|
|
cp "$PERSIST_HTPASSWD" "$SHARED_HTPASSWD"
|
|
chmod 644 "$SHARED_HTPASSWD"
|
|
|
|
log "Gateway credential ready for user '$PORTAL_USER' ($SHARED_HTPASSWD)"
|