e58c78d21c
- 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>
139 lines
5.1 KiB
Bash
Executable File
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."
|