304 lines
6.8 KiB
Bash
304 lines
6.8 KiB
Bash
#!/usr/bin/env bash
|
|
set -euo pipefail
|
|
|
|
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
|
OUT_DIR="${ROOT_DIR}/certs"
|
|
TLS_DIR="${OUT_DIR}/tls"
|
|
SSH_DIR="${OUT_DIR}/ssh"
|
|
SERVER_DNS="localhost"
|
|
FORCE=0
|
|
DO_TLS=1
|
|
DO_SSH=1
|
|
|
|
usage() {
|
|
cat <<'USAGE'
|
|
Generate local development TLS certificates and SSH keys for RTR Docker deploys.
|
|
|
|
Usage:
|
|
scripts/10_generate-certs.sh [options]
|
|
|
|
Options:
|
|
--out-dir DIR Output directory, default: ./certs
|
|
--server-dns NAME TLS server dNSName SAN, default: localhost
|
|
--tls-only Generate only TLS files
|
|
--ssh-only Generate only SSH files
|
|
--force Overwrite existing files
|
|
-h, --help Show this help
|
|
|
|
Generated TLS files:
|
|
certs/tls/client-ca.crt
|
|
certs/tls/client-ca.key
|
|
certs/tls/server-dns.crt
|
|
certs/tls/server-dns.key
|
|
certs/tls/client-good.crt
|
|
certs/tls/client-good.key
|
|
|
|
Generated SSH files:
|
|
certs/ssh/ssh_host_rsa_key
|
|
certs/ssh/ssh_host_rsa_key.pub
|
|
certs/ssh/rtr-client.key
|
|
certs/ssh/rtr-client.key.pub
|
|
certs/ssh/rtr-authorized_keys
|
|
USAGE
|
|
}
|
|
|
|
die() {
|
|
echo "error: $*" >&2
|
|
exit 1
|
|
}
|
|
|
|
info() {
|
|
echo "[generate-certs] $*"
|
|
}
|
|
|
|
need_cmd() {
|
|
command -v "$1" >/dev/null 2>&1 || die "required command not found: $1"
|
|
}
|
|
|
|
run_quiet() {
|
|
local log_file
|
|
log_file="$(mktemp)"
|
|
if "$@" >"${log_file}" 2>&1; then
|
|
rm -f "${log_file}"
|
|
return 0
|
|
fi
|
|
|
|
cat "${log_file}" >&2
|
|
rm -f "${log_file}"
|
|
return 1
|
|
}
|
|
|
|
ensure_abs_out_dir() {
|
|
case "${OUT_DIR}" in
|
|
/*) ;;
|
|
[A-Za-z]:*) ;;
|
|
*) OUT_DIR="${ROOT_DIR}/${OUT_DIR}" ;;
|
|
esac
|
|
TLS_DIR="${OUT_DIR}/tls"
|
|
SSH_DIR="${OUT_DIR}/ssh"
|
|
}
|
|
|
|
check_overwrite() {
|
|
local path="$1"
|
|
if [[ -e "${path}" && "${FORCE}" != "1" ]]; then
|
|
die "${path} already exists; rerun with --force to overwrite"
|
|
fi
|
|
}
|
|
|
|
write_tls_config_files() {
|
|
local tmp_dir="$1"
|
|
|
|
cat >"${tmp_dir}/ca.cnf" <<'EOF'
|
|
[ req ]
|
|
distinguished_name = req_distinguished_name
|
|
prompt = no
|
|
|
|
[ req_distinguished_name ]
|
|
CN = rpki-rtr-client-ca
|
|
EOF
|
|
|
|
cat >"${tmp_dir}/server.cnf" <<EOF
|
|
[ req ]
|
|
distinguished_name = req_distinguished_name
|
|
prompt = no
|
|
|
|
[ req_distinguished_name ]
|
|
CN = ${SERVER_DNS}
|
|
EOF
|
|
|
|
cat >"${tmp_dir}/client.cnf" <<'EOF'
|
|
[ req ]
|
|
distinguished_name = req_distinguished_name
|
|
prompt = no
|
|
|
|
[ req_distinguished_name ]
|
|
CN = rpki-rtr-client
|
|
EOF
|
|
|
|
cat >"${tmp_dir}/server.ext" <<EOF
|
|
basicConstraints=CA:FALSE
|
|
keyUsage=digitalSignature,keyEncipherment
|
|
extendedKeyUsage=serverAuth
|
|
subjectAltName=DNS:${SERVER_DNS}
|
|
EOF
|
|
|
|
cat >"${tmp_dir}/client.ext" <<'EOF'
|
|
basicConstraints=CA:FALSE
|
|
keyUsage=digitalSignature,keyEncipherment
|
|
extendedKeyUsage=clientAuth
|
|
EOF
|
|
}
|
|
|
|
generate_tls() {
|
|
need_cmd openssl
|
|
mkdir -p "${TLS_DIR}"
|
|
|
|
info "generating TLS certificates in ${TLS_DIR}"
|
|
info "TLS server dNSName SAN: ${SERVER_DNS}"
|
|
|
|
local files=(
|
|
"${TLS_DIR}/client-ca.crt"
|
|
"${TLS_DIR}/client-ca.key"
|
|
"${TLS_DIR}/server-dns.crt"
|
|
"${TLS_DIR}/server-dns.key"
|
|
"${TLS_DIR}/client-good.crt"
|
|
"${TLS_DIR}/client-good.key"
|
|
)
|
|
for file in "${files[@]}"; do
|
|
check_overwrite "${file}"
|
|
done
|
|
|
|
local tmp_dir
|
|
tmp_dir="$(mktemp -d)"
|
|
write_tls_config_files "${tmp_dir}"
|
|
|
|
run_quiet openssl genrsa -out "${TLS_DIR}/client-ca.key" 2048
|
|
info "created TLS CA key: ${TLS_DIR}/client-ca.key"
|
|
run_quiet openssl req -x509 -new -nodes \
|
|
-config "${tmp_dir}/ca.cnf" \
|
|
-key "${TLS_DIR}/client-ca.key" \
|
|
-sha256 -days 3650 \
|
|
-out "${TLS_DIR}/client-ca.crt"
|
|
info "created TLS CA cert: ${TLS_DIR}/client-ca.crt"
|
|
|
|
run_quiet openssl genrsa -out "${TLS_DIR}/server-dns.key" 2048
|
|
info "created TLS server key: ${TLS_DIR}/server-dns.key"
|
|
run_quiet openssl req -new \
|
|
-config "${tmp_dir}/server.cnf" \
|
|
-key "${TLS_DIR}/server-dns.key" \
|
|
-out "${tmp_dir}/server-dns.csr"
|
|
run_quiet openssl x509 -req \
|
|
-in "${tmp_dir}/server-dns.csr" \
|
|
-CA "${TLS_DIR}/client-ca.crt" \
|
|
-CAkey "${TLS_DIR}/client-ca.key" \
|
|
-CAcreateserial \
|
|
-out "${TLS_DIR}/server-dns.crt" \
|
|
-days 3650 -sha256 \
|
|
-extfile "${tmp_dir}/server.ext"
|
|
info "created TLS server cert: ${TLS_DIR}/server-dns.crt"
|
|
|
|
run_quiet openssl genrsa -out "${TLS_DIR}/client-good.key" 2048
|
|
info "created TLS client key: ${TLS_DIR}/client-good.key"
|
|
run_quiet openssl req -new \
|
|
-config "${tmp_dir}/client.cnf" \
|
|
-key "${TLS_DIR}/client-good.key" \
|
|
-out "${tmp_dir}/client-good.csr"
|
|
run_quiet openssl x509 -req \
|
|
-in "${tmp_dir}/client-good.csr" \
|
|
-CA "${TLS_DIR}/client-ca.crt" \
|
|
-CAkey "${TLS_DIR}/client-ca.key" \
|
|
-CAcreateserial \
|
|
-out "${TLS_DIR}/client-good.crt" \
|
|
-days 3650 -sha256 \
|
|
-extfile "${tmp_dir}/client.ext"
|
|
info "created TLS client cert: ${TLS_DIR}/client-good.crt"
|
|
|
|
rm -f "${TLS_DIR}/client-ca.srl"
|
|
rm -rf "${tmp_dir}"
|
|
chmod 600 "${TLS_DIR}"/*.key
|
|
chmod 644 "${TLS_DIR}"/*.crt
|
|
}
|
|
|
|
generate_ssh_key() {
|
|
local path="$1"
|
|
local comment="$2"
|
|
check_overwrite "${path}"
|
|
check_overwrite "${path}.pub"
|
|
rm -f "${path}" "${path}.pub"
|
|
run_quiet ssh-keygen -q -t rsa -b 3072 -m PEM -N "" -C "${comment}" -f "${path}"
|
|
}
|
|
|
|
generate_ssh() {
|
|
need_cmd ssh-keygen
|
|
mkdir -p "${SSH_DIR}"
|
|
|
|
info "generating SSH keys in ${SSH_DIR}"
|
|
generate_ssh_key "${SSH_DIR}/ssh_host_rsa_key" "rpki-rtr-host"
|
|
info "created SSH host key: ${SSH_DIR}/ssh_host_rsa_key"
|
|
generate_ssh_key "${SSH_DIR}/rtr-client.key" "rpki-rtr-debug-client"
|
|
info "created SSH client key: ${SSH_DIR}/rtr-client.key"
|
|
|
|
check_overwrite "${SSH_DIR}/rtr-authorized_keys"
|
|
cp "${SSH_DIR}/rtr-client.key.pub" "${SSH_DIR}/rtr-authorized_keys"
|
|
info "created SSH authorized_keys: ${SSH_DIR}/rtr-authorized_keys"
|
|
|
|
chmod 600 \
|
|
"${SSH_DIR}/ssh_host_rsa_key" \
|
|
"${SSH_DIR}/rtr-client.key"
|
|
chmod 644 "${SSH_DIR}"/*.pub "${SSH_DIR}/rtr-authorized_keys"
|
|
}
|
|
|
|
while [[ $# -gt 0 ]]; do
|
|
case "$1" in
|
|
--out-dir)
|
|
[[ $# -ge 2 ]] || die "--out-dir requires a value"
|
|
OUT_DIR="$2"
|
|
shift 2
|
|
;;
|
|
--server-dns)
|
|
[[ $# -ge 2 ]] || die "--server-dns requires a value"
|
|
SERVER_DNS="$2"
|
|
shift 2
|
|
;;
|
|
--tls-only)
|
|
DO_TLS=1
|
|
DO_SSH=0
|
|
shift
|
|
;;
|
|
--ssh-only)
|
|
DO_TLS=0
|
|
DO_SSH=1
|
|
shift
|
|
;;
|
|
--force)
|
|
FORCE=1
|
|
shift
|
|
;;
|
|
-h|--help)
|
|
usage
|
|
exit 0
|
|
;;
|
|
*)
|
|
die "unknown option: $1"
|
|
;;
|
|
esac
|
|
done
|
|
|
|
ensure_abs_out_dir
|
|
|
|
if [[ "${DO_TLS}" == "1" ]]; then
|
|
generate_tls
|
|
fi
|
|
|
|
if [[ "${DO_SSH}" == "1" ]]; then
|
|
generate_ssh
|
|
fi
|
|
|
|
info "done"
|
|
info "generated files under ${OUT_DIR}"
|
|
|
|
if [[ "${DO_TLS}" == "1" ]]; then
|
|
cat <<EOF
|
|
|
|
TLS files:
|
|
${TLS_DIR}/client-ca.crt
|
|
${TLS_DIR}/server-dns.crt
|
|
${TLS_DIR}/server-dns.key
|
|
${TLS_DIR}/client-good.crt
|
|
${TLS_DIR}/client-good.key
|
|
${TLS_DIR}/client-ca.key (local signing key; not mounted by compose)
|
|
EOF
|
|
fi
|
|
|
|
if [[ "${DO_SSH}" == "1" ]]; then
|
|
cat <<EOF
|
|
|
|
SSH files:
|
|
${SSH_DIR}/ssh_host_rsa_key
|
|
${SSH_DIR}/ssh_host_rsa_key.pub
|
|
${SSH_DIR}/rtr-client.key
|
|
${SSH_DIR}/rtr-client.key.pub
|
|
${SSH_DIR}/rtr-authorized_keys
|
|
EOF
|
|
fi
|