Files
pi-extensions/scripts/install-browser-certs.sh
T
shahondin1624 e58c78d21c Add setup scripts for onboarding new machines
- scripts/install-client.sh: bootstraps a pi client — fetches certs from
  the Caddy host via scp, rsyncs the extensions into ~/.pi/agent/, sets
  up SSH key-auth to the ai-server for admin commands, probes the mTLS
  /health endpoint to verify.
- scripts/issue-client-cert.sh: run on the Caddy host to mint a new
  device identity — generates key + CSR, signs with the local root CA,
  and emits both a modern p12 (AES-256) and a -legacy p12 (3DES/RC2-40)
  for NSS-based browsers.
- scripts/install-browser-certs.sh: imports certs into Brave Flatpak's
  isolated NSS DB, ~/.pki/nssdb for packaged Chromium-family browsers,
  each Firefox profile, optionally the system trust store, and
  optionally drops a Brave AutoSelectCertificateForUrls policy so the
  cert prompt stops appearing on every page load.

All three are idempotent, --help-aware, and accept env/flag overrides
for the hardcoded defaults.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-23 21:26:08 +02:00

139 lines
5.1 KiB
Bash
Executable File

#!/usr/bin/env bash
#
# install-browser-certs.sh — Import the mTLS client cert + root CA into
# every browser's cert store on this Linux machine.
#
# Handles:
# - Brave (Flatpak) — isolated NSS DB at ~/.var/app/com.brave.Browser/.pki/nssdb
# - Chromium-family (rpm/deb, Brave-rpm) — ~/.pki/nssdb
# - Firefox — each ~/.mozilla/firefox/*.default*/ profile
# - System trust (optional, sudo) — /etc/pki/ca-trust (curl, wget, git, …)
#
# If only the modern (PBES2/AES-256) p12 exists, this script converts it to a
# legacy bundle that NSS-based stores can actually parse.
#
# Also optionally writes the Brave enterprise policy
# AutoSelectCertificateForUrls so Brave stops prompting on every page load.
#
# Usage:
# scripts/install-browser-certs.sh [options]
# --certs-dir PATH default: $HOME/.pi/agent/certs
# --system-trust also install root CA into system trust store
# --brave-policy also install AutoSelectCertificateForUrls
# --auto-select-url URL default: https://ai.shahondin1624.de
# --auto-select-issuer CN default: ShahODin Root CA
# --help show this message
set -euo pipefail
CERTS_DIR="${CERTS_DIR:-$HOME/.pi/agent/certs}"
DO_SYSTEM_TRUST=0
DO_BRAVE_POLICY=0
AUTO_SELECT_URL="https://ai.shahondin1624.de"
AUTO_SELECT_ISSUER_CN="ShahODin Root CA"
usage() { sed -n '2,/^$/p' "$0" | sed 's/^#\{0,1\} \{0,1\}//'; exit 0; }
while [[ $# -gt 0 ]]; do
case "$1" in
--certs-dir) CERTS_DIR="$2"; shift 2 ;;
--system-trust) DO_SYSTEM_TRUST=1; shift ;;
--brave-policy) DO_BRAVE_POLICY=1; shift ;;
--auto-select-url) AUTO_SELECT_URL="$2"; shift 2 ;;
--auto-select-issuer) AUTO_SELECT_ISSUER_CN="$2"; shift 2 ;;
-h|--help) usage ;;
*) echo "Unknown arg: $1" >&2; exit 1 ;;
esac
done
CLIENT_CRT="$CERTS_DIR/client.pem"
CLIENT_KEY="$CERTS_DIR/client-key.pem"
ROOT_CA="$CERTS_DIR/root-ca.pem"
LEGACY_P12="$CERTS_DIR/client-legacy.p12"
for f in "$CLIENT_CRT" "$CLIENT_KEY" "$ROOT_CA"; do
[[ -f "$f" ]] || { echo "Missing: $f" >&2; exit 1; }
done
command -v pk12util >/dev/null || { echo "pk12util not found — install nss-tools (Fedora: 'sudo dnf install nss-tools')" >&2; exit 1; }
command -v certutil >/dev/null || { echo "certutil not found — install nss-tools" >&2; exit 1; }
command -v openssl >/dev/null || { echo "openssl not found" >&2; exit 1; }
# Ensure a legacy-format p12 exists (required by NSS on most distros)
if [[ ! -f "$LEGACY_P12" ]]; then
echo "==> Generating legacy-format p12 for NSS stores"
umask 077
tmp="$(mktemp)"
trap 'shred -u "$tmp" 2>/dev/null || rm -f "$tmp"' EXIT
cat "$CLIENT_CRT" "$CLIENT_KEY" "$ROOT_CA" > "$tmp"
openssl pkcs12 -legacy -export -in "$tmp" \
-out "$LEGACY_P12" \
-name "Client (legacy)" \
-passout pass:
chmod 600 "$LEGACY_P12"
fi
import_nss() {
local db="$1" label="$2"
[[ -d "$db" && -f "$db/cert9.db" ]] || { echo " [$label] no NSS DB at $db — skipping"; return 0; }
echo "==> $label ($db)"
if certutil -d "sql:$db" -L -n "$AUTO_SELECT_ISSUER_CN" >/dev/null 2>&1; then
echo " root CA already present"
else
certutil -d "sql:$db" -A -t "CT,C,C" -n "$AUTO_SELECT_ISSUER_CN" -i "$ROOT_CA"
echo " root CA imported"
fi
if certutil -d "sql:$db" -L 2>/dev/null | grep -q 'Client (legacy)'; then
echo " client cert already present"
else
pk12util -d "sql:$db" -i "$LEGACY_P12" -W ''
echo " client cert imported"
fi
}
# 1) Brave Flatpak (isolated NSS DB)
import_nss "$HOME/.var/app/com.brave.Browser/.pki/nssdb" "Brave (Flatpak)"
# 2) Regular Chromium family (packaged Brave/Chrome/Chromium) and pki-aware CLIs
import_nss "$HOME/.pki/nssdb" "Chromium-family NSS DB (~/.pki/nssdb)"
# 3) Firefox profiles
shopt -s nullglob
for profile in "$HOME"/.mozilla/firefox/*.default* "$HOME"/.mozilla/firefox/*.default-release; do
import_nss "$profile" "Firefox profile $(basename "$profile")"
done
shopt -u nullglob
# 4) System trust (optional)
if [[ $DO_SYSTEM_TRUST -eq 1 ]]; then
anchor_name="$(basename "$ROOT_CA")"
echo "==> Installing root CA into system trust (requires sudo)"
sudo install -m 644 "$ROOT_CA" "/etc/pki/ca-trust/source/anchors/$anchor_name"
sudo update-ca-trust extract
fi
# 5) Brave enterprise policy (optional)
if [[ $DO_BRAVE_POLICY -eq 1 ]]; then
echo "==> Installing Brave AutoSelectCertificateForUrls policy"
if command -v flatpak >/dev/null && flatpak list 2>/dev/null | grep -q com.brave.Browser; then
sudo flatpak override com.brave.Browser --filesystem=/etc/brave:ro
fi
sudo mkdir -p /etc/brave/policies/managed
# Policy JSON has a JSON-string value inside an array.
policy_tmp="$(mktemp)"
cat > "$policy_tmp" <<EOF
{
"AutoSelectCertificateForUrls": [
"{\"pattern\":\"${AUTO_SELECT_URL}\",\"filter\":{\"ISSUER\":{\"CN\":\"${AUTO_SELECT_ISSUER_CN}\"}}}"
]
}
EOF
sudo install -m 644 "$policy_tmp" /etc/brave/policies/managed/ai-server-mtls.json
rm -f "$policy_tmp"
flatpak kill com.brave.Browser 2>/dev/null || pkill -x brave 2>/dev/null || true
echo " policy installed; Brave was killed if running — relaunch to apply"
fi
echo
echo "==> Done. Restart any already-running browser for NSS changes to take effect."