scripts/generate-certs.shblame
View source
3e3af551#!/usr/bin/env bash
0d60b202# Grove - Generate self-signed TLS certificates for Mononoke
0d60b203# Mononoke SLAPI and git_server require TLS. This generates a CA, server cert,
0d60b204# and client cert (for sl push mTLS).
3e3af555#
0d60b206# Usage: ./generate-certs.sh [domain-or-ip]
0d60b207#
0d60b208# Examples:
0d60b209# ./generate-certs.sh # localhost/dev only
0d60b2010# ./generate-certs.sh grove.host # production hub
0d60b2011# ./generate-certs.sh 203.0.113.5 # instance by IP
3e3af5512
3e3af5513set -euo pipefail
3e3af5514
0d60b2015DOMAIN_OR_IP="${1:-}"
0d60b2016TLS_DIR="${GROVE_TLS_DIR:-/data/grove/tls}"
0d60b2017
0d60b2018mkdir -p "$TLS_DIR"
0d60b2019
0d60b2020echo "Generating Grove TLS certificates in $TLS_DIR..."
0d60b2021
0d60b2022# ── Build SAN list ─────────────────────────────────────────────────
0d60b2023
0d60b2024SAN_DNS=("localhost" "mononoke-slapi" "mononoke-git")
0d60b2025SAN_IP=("127.0.0.1")
0d60b2026
0d60b2027if [[ -n "$DOMAIN_OR_IP" ]]; then
0d60b2028 if [[ "$DOMAIN_OR_IP" =~ ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
0d60b2029 SAN_IP+=("$DOMAIN_OR_IP")
0d60b2030 else
0d60b2031 SAN_DNS+=("$DOMAIN_OR_IP")
0d60b2032 fi
0d60b2033fi
0d60b2034
0d60b2035# Build the SAN config section
0d60b2036SAN_ENTRIES=""
0d60b2037for i in "${!SAN_DNS[@]}"; do
0d60b2038 SAN_ENTRIES+="DNS.$((i + 1)) = ${SAN_DNS[$i]}"$'\n'
0d60b2039done
0d60b2040for i in "${!SAN_IP[@]}"; do
0d60b2041 SAN_ENTRIES+="IP.$((i + 1)) = ${SAN_IP[$i]}"$'\n'
0d60b2042done
3e3af5543
0d60b2044# ── CA ─────────────────────────────────────────────────────────────
3e3af5545
0d60b2046openssl genrsa -out "$TLS_DIR/ca.key" 4096 2>/dev/null
0d60b2047openssl req -new -x509 -key "$TLS_DIR/ca.key" \
0d60b2048 -out "$TLS_DIR/ca.crt" -days 3650 \
0d60b2049 -subj "/CN=Grove CA/O=Letterpress Labs" 2>/dev/null
3e3af5550
0d60b2051# ── Server cert ────────────────────────────────────────────────────
3e3af5552
0d60b2053openssl genrsa -out "$TLS_DIR/server.key" 4096 2>/dev/null
0d60b2054openssl req -new -key "$TLS_DIR/server.key" \
0d60b2055 -out "$TLS_DIR/server.csr" \
0d60b2056 -subj "/CN=${DOMAIN_OR_IP:-localhost}/O=Letterpress Labs" 2>/dev/null
3e3af5557
0d60b2058cat > "$TLS_DIR/ext.cnf" <<EOF
0d60b2059authorityKeyIdentifier=keyid,issuer
0d60b2060basicConstraints=CA:FALSE
0d60b2061keyUsage=digitalSignature,keyEncipherment
0d60b2062extendedKeyUsage=serverAuth,clientAuth
0d60b2063subjectAltName=@alt_names
3e3af5564
3e3af5565[alt_names]
0d60b2066${SAN_ENTRIES}
3e3af5567EOF
3e3af5568
0d60b2069openssl x509 -req -in "$TLS_DIR/server.csr" \
0d60b2070 -CA "$TLS_DIR/ca.crt" -CAkey "$TLS_DIR/ca.key" \
0d60b2071 -CAcreateserial -out "$TLS_DIR/server.crt" \
0d60b2072 -days 3650 -extfile "$TLS_DIR/ext.cnf" 2>/dev/null
0d60b2073
0d60b2074# ── Client cert (for sl push mTLS) ────────────────────────────────
0d60b2075
0d60b2076openssl genrsa -out "$TLS_DIR/client.key" 4096 2>/dev/null
0d60b2077openssl req -new -key "$TLS_DIR/client.key" \
0d60b2078 -out "$TLS_DIR/client.csr" \
0d60b2079 -subj "/CN=grove-client/O=Letterpress Labs" 2>/dev/null
0d60b2080
0d60b2081openssl x509 -req -in "$TLS_DIR/client.csr" \
0d60b2082 -CA "$TLS_DIR/ca.crt" -CAkey "$TLS_DIR/ca.key" \
0d60b2083 -CAcreateserial -out "$TLS_DIR/client.crt" \
0d60b2084 -days 3650 2>/dev/null
0d60b2085
0d60b2086# ── Cleanup temp files ─────────────────────────────────────────────
0d60b2087
0d60b2088rm -f "$TLS_DIR"/*.csr "$TLS_DIR"/*.cnf "$TLS_DIR"/*.srl
3e3af5589
3e3af5590echo ""
0d60b2091echo "Certificates generated in $TLS_DIR:"
0d60b2092echo " ca.crt - Certificate Authority certificate"
0d60b2093echo " ca.key - Certificate Authority private key"
0d60b2094echo " server.crt - Server certificate (Mononoke SLAPI + git_server)"
0d60b2095echo " server.key - Server private key"
0d60b2096echo " client.crt - Client certificate (sl push mTLS)"
0d60b2097echo " client.key - Client private key"
0d60b2098if [[ -n "$DOMAIN_OR_IP" ]]; then
0d60b2099 echo ""
0d60b20100 echo "SANs: ${SAN_DNS[*]} / ${SAN_IP[*]}"
0d60b20101fi