| 3e3af55 | | | 1 | #!/usr/bin/env bash |
| 0d60b20 | | | 2 | # Grove - Generate self-signed TLS certificates for Mononoke |
| 0d60b20 | | | 3 | # Mononoke SLAPI and git_server require TLS. This generates a CA, server cert, |
| 0d60b20 | | | 4 | # and client cert (for sl push mTLS). |
| 3e3af55 | | | 5 | # |
| 0d60b20 | | | 6 | # Usage: ./generate-certs.sh [domain-or-ip] |
| 0d60b20 | | | 7 | # |
| 0d60b20 | | | 8 | # Examples: |
| 0d60b20 | | | 9 | # ./generate-certs.sh # localhost/dev only |
| 0d60b20 | | | 10 | # ./generate-certs.sh grove.host # production hub |
| 0d60b20 | | | 11 | # ./generate-certs.sh 203.0.113.5 # instance by IP |
| 3e3af55 | | | 12 | |
| 3e3af55 | | | 13 | set -euo pipefail |
| 3e3af55 | | | 14 | |
| 0d60b20 | | | 15 | DOMAIN_OR_IP="${1:-}" |
| 0d60b20 | | | 16 | TLS_DIR="${GROVE_TLS_DIR:-/data/grove/tls}" |
| 0d60b20 | | | 17 | |
| 0d60b20 | | | 18 | mkdir -p "$TLS_DIR" |
| 0d60b20 | | | 19 | |
| 0d60b20 | | | 20 | echo "Generating Grove TLS certificates in $TLS_DIR..." |
| 0d60b20 | | | 21 | |
| 0d60b20 | | | 22 | # ── Build SAN list ───────────────────────────────────────────────── |
| 0d60b20 | | | 23 | |
| 0d60b20 | | | 24 | SAN_DNS=("localhost" "mononoke-slapi" "mononoke-git") |
| 0d60b20 | | | 25 | SAN_IP=("127.0.0.1") |
| 0d60b20 | | | 26 | |
| 0d60b20 | | | 27 | if [[ -n "$DOMAIN_OR_IP" ]]; then |
| 0d60b20 | | | 28 | if [[ "$DOMAIN_OR_IP" =~ ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$ ]]; then |
| 0d60b20 | | | 29 | SAN_IP+=("$DOMAIN_OR_IP") |
| 0d60b20 | | | 30 | else |
| 0d60b20 | | | 31 | SAN_DNS+=("$DOMAIN_OR_IP") |
| 0d60b20 | | | 32 | fi |
| 0d60b20 | | | 33 | fi |
| 0d60b20 | | | 34 | |
| 0d60b20 | | | 35 | # Build the SAN config section |
| 0d60b20 | | | 36 | SAN_ENTRIES="" |
| 0d60b20 | | | 37 | for i in "${!SAN_DNS[@]}"; do |
| 0d60b20 | | | 38 | SAN_ENTRIES+="DNS.$((i + 1)) = ${SAN_DNS[$i]}"$'\n' |
| 0d60b20 | | | 39 | done |
| 0d60b20 | | | 40 | for i in "${!SAN_IP[@]}"; do |
| 0d60b20 | | | 41 | SAN_ENTRIES+="IP.$((i + 1)) = ${SAN_IP[$i]}"$'\n' |
| 0d60b20 | | | 42 | done |
| 3e3af55 | | | 43 | |
| 0d60b20 | | | 44 | # ── CA ───────────────────────────────────────────────────────────── |
| 3e3af55 | | | 45 | |
| 0d60b20 | | | 46 | openssl genrsa -out "$TLS_DIR/ca.key" 4096 2>/dev/null |
| 0d60b20 | | | 47 | openssl req -new -x509 -key "$TLS_DIR/ca.key" \ |
| 0d60b20 | | | 48 | -out "$TLS_DIR/ca.crt" -days 3650 \ |
| 0d60b20 | | | 49 | -subj "/CN=Grove CA/O=Letterpress Labs" 2>/dev/null |
| 3e3af55 | | | 50 | |
| 0d60b20 | | | 51 | # ── Server cert ──────────────────────────────────────────────────── |
| 3e3af55 | | | 52 | |
| 0d60b20 | | | 53 | openssl genrsa -out "$TLS_DIR/server.key" 4096 2>/dev/null |
| 0d60b20 | | | 54 | openssl req -new -key "$TLS_DIR/server.key" \ |
| 0d60b20 | | | 55 | -out "$TLS_DIR/server.csr" \ |
| 0d60b20 | | | 56 | -subj "/CN=${DOMAIN_OR_IP:-localhost}/O=Letterpress Labs" 2>/dev/null |
| 3e3af55 | | | 57 | |
| 0d60b20 | | | 58 | cat > "$TLS_DIR/ext.cnf" <<EOF |
| 0d60b20 | | | 59 | authorityKeyIdentifier=keyid,issuer |
| 0d60b20 | | | 60 | basicConstraints=CA:FALSE |
| 0d60b20 | | | 61 | keyUsage=digitalSignature,keyEncipherment |
| 0d60b20 | | | 62 | extendedKeyUsage=serverAuth,clientAuth |
| 0d60b20 | | | 63 | subjectAltName=@alt_names |
| 3e3af55 | | | 64 | |
| 3e3af55 | | | 65 | [alt_names] |
| 0d60b20 | | | 66 | ${SAN_ENTRIES} |
| 3e3af55 | | | 67 | EOF |
| 3e3af55 | | | 68 | |
| 0d60b20 | | | 69 | openssl x509 -req -in "$TLS_DIR/server.csr" \ |
| 0d60b20 | | | 70 | -CA "$TLS_DIR/ca.crt" -CAkey "$TLS_DIR/ca.key" \ |
| 0d60b20 | | | 71 | -CAcreateserial -out "$TLS_DIR/server.crt" \ |
| 0d60b20 | | | 72 | -days 3650 -extfile "$TLS_DIR/ext.cnf" 2>/dev/null |
| 0d60b20 | | | 73 | |
| 0d60b20 | | | 74 | # ── Client cert (for sl push mTLS) ──────────────────────────────── |
| 0d60b20 | | | 75 | |
| 0d60b20 | | | 76 | openssl genrsa -out "$TLS_DIR/client.key" 4096 2>/dev/null |
| 0d60b20 | | | 77 | openssl req -new -key "$TLS_DIR/client.key" \ |
| 0d60b20 | | | 78 | -out "$TLS_DIR/client.csr" \ |
| 0d60b20 | | | 79 | -subj "/CN=grove-client/O=Letterpress Labs" 2>/dev/null |
| 0d60b20 | | | 80 | |
| 0d60b20 | | | 81 | openssl x509 -req -in "$TLS_DIR/client.csr" \ |
| 0d60b20 | | | 82 | -CA "$TLS_DIR/ca.crt" -CAkey "$TLS_DIR/ca.key" \ |
| 0d60b20 | | | 83 | -CAcreateserial -out "$TLS_DIR/client.crt" \ |
| 0d60b20 | | | 84 | -days 3650 2>/dev/null |
| 0d60b20 | | | 85 | |
| 0d60b20 | | | 86 | # ── Cleanup temp files ───────────────────────────────────────────── |
| 0d60b20 | | | 87 | |
| 0d60b20 | | | 88 | rm -f "$TLS_DIR"/*.csr "$TLS_DIR"/*.cnf "$TLS_DIR"/*.srl |
| 3e3af55 | | | 89 | |
| 3e3af55 | | | 90 | echo "" |
| 0d60b20 | | | 91 | echo "Certificates generated in $TLS_DIR:" |
| 0d60b20 | | | 92 | echo " ca.crt - Certificate Authority certificate" |
| 0d60b20 | | | 93 | echo " ca.key - Certificate Authority private key" |
| 0d60b20 | | | 94 | echo " server.crt - Server certificate (Mononoke SLAPI + git_server)" |
| 0d60b20 | | | 95 | echo " server.key - Server private key" |
| 0d60b20 | | | 96 | echo " client.crt - Client certificate (sl push mTLS)" |
| 0d60b20 | | | 97 | echo " client.key - Client private key" |
| 0d60b20 | | | 98 | if [[ -n "$DOMAIN_OR_IP" ]]; then |
| 0d60b20 | | | 99 | echo "" |
| 0d60b20 | | | 100 | echo "SANs: ${SAN_DNS[*]} / ${SAN_IP[*]}" |
| 0d60b20 | | | 101 | fi |