Files
nix/hosts/common/configs/system/kubernetes/secrets/generate-secrets.sh
2025-01-29 12:44:05 +00:00

208 lines
8.6 KiB
Bash
Executable File

#!/usr/bin/env -S nix shell nixpkgs#openssl nixpkgs#yq-go nixpkgs#sops -c bash
set -o errexit
set -o pipefail
generate_ca() {
local target_dir=$1
local ca_name=$2
local ca_days=$3
local cn=$4
mkdir -p "${target_dir}"
local ca_key=${target_dir}/${ca_name}.key
local ca_cert=${target_dir}/${ca_name}.crt
openssl genrsa -out "${ca_key}" 2048
openssl req -x509 -new -nodes -key "${ca_key}" -days "${ca_days}" -out "${ca_cert}" -subj "/CN=${cn}"
}
generate_alt_names() {
local hosts=("$@")
local dns=0
local ip=0
local alt_names=""
for host in "${hosts[@]}"; do
if [[ ${host} =~ ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
alt_names="${alt_names}IP.${ip} = ${host}\n"
((ip++))
else
alt_names="${alt_names}DNS.${dns} = ${host}\n"
((dns++))
fi
done
echo -e "${alt_names}"
}
generate_cnf() {
local target_dir=$1
local cnf_name=$2
local cn=$3
local hosts=("${@:4}")
mkdir -p "${target_dir}"
local cnf_file=${target_dir}/${cnf_name}.cnf
cat <<EOF > "${cnf_file}"
[req]
prompt = no
[ req_ext ]
subjectAltName = @alt_names
[ alt_names ]
$(generate_alt_names "${hosts[@]}")
[ v3_ext ]
authorityKeyIdentifier=keyid,issuer:always
basicConstraints=CA:FALSE
keyUsage=keyEncipherment,dataEncipherment,digitalSignature
extendedKeyUsage=serverAuth,clientAuth
subjectAltName=@alt_names
EOF
}
generate_crt() {
local target_dir=$1
local cert_name=$2
local cert_days=$3
local cn=$4
local o=$5
local ca_key=$6
local ca_cert=$7
local hosts=("${@:8}")
mkdir -p "${target_dir}"
local cert_key=${target_dir}/${cert_name}.key
local cert_csr=${target_dir}/${cert_name}.csr
local cert_cert=${target_dir}/${cert_name}.crt
openssl genrsa -out "${cert_key}" 2048
local subject="/CN=${cn}"
if [ -n "${o}" ]; then
subject="${subject}/O=${o}"
fi
if [ -n "${hosts}" ]; then
generate_cnf "${target_dir}" "${cert_name}" "${cn}" "${hosts[@]}"
openssl req -new -key "${cert_key}" -out "${cert_csr}" -subj "${subject}" -config "${target_dir}"/"${cert_name}".cnf
openssl x509 -req -in "${cert_csr}" -CA "${ca_cert}" -CAkey "${ca_key}" -CAcreateserial -out "${cert_cert}" -days "${cert_days}" -extfile "${target_dir}"/"${cert_name}".cnf -extensions v3_ext
else
openssl req -new -key "${cert_key}" -out "${cert_csr}" -subj "${subject}"
openssl x509 -req -in "${cert_csr}" -CA "${ca_cert}" -CAkey "${ca_key}" -CAcreateserial -out "${cert_cert}" -days "${cert_days}"
fi
}
generate_key_pair() {
local target_dir=$1
local key_name=$2
mkdir -p "${target_dir}"
local private_key=${target_dir}/${key_name}.key
local public_key=${target_dir}/${key_name}.pub
openssl genrsa -out "${private_key}" 2048
openssl rsa -in "${private_key}" -pubout -out "${public_key}"
}
generate_auth_token() {
local target_dir=$1
local token_name=$2
local user=$3
local id=$4
local groups=$5
mkdir -p "${target_dir}"
local token_file="${target_dir}/${token_name}.token"
local token_auth_file="${target_dir}/${token_name}.csv"
token="$(head -c 16 /dev/urandom | od -An -t x | tr -d ' ')"
echo "${token}" > "${token_file}"
echo "${token},${user},${id},\"${groups}\"" > "${token_auth_file}"
}
DEFAULT_CA_DAYS=3650
if [[ -z "$SOPS_AGE_KEY_FILE" ]]; then
echo "Please set the SOPS_AGE_KEY_FILE environment variable"
exit 1
fi
hostname=${1:-$(hostname)}
if [ -z "${hostname}" ]; then
echo "Usage: $0 [hostname]"
exit 1
fi
generate_ca out/ca kubernetes ${DEFAULT_CA_DAYS} kubernetes-ca ""
generate_ca out/ca front-proxy ${DEFAULT_CA_DAYS} kubernetes-front-proxy-ca ""
generate_ca out/ca etcd ${DEFAULT_CA_DAYS} etcd-ca ""
generate_crt out/cert/apiserver server ${DEFAULT_CA_DAYS} kube-apiserver "" out/ca/kubernetes.key out/ca/kubernetes.crt "kubernetes" "kubernetes.default" "kubernetes.default.svc" "kubernetes.default.svc.cluster" "kubernetes.default.svc.cluster.local" "localhost" "10.0.0.1" "127.0.0.1"
generate_crt out/cert/apiserver etcd-client ${DEFAULT_CA_DAYS} kube-apiserver-etcd-client "" out/ca/etcd.key out/ca/etcd.crt ""
generate_crt out/cert/apiserver kubelet-client ${DEFAULT_CA_DAYS} kube-apiserver-kubelet-client "" out/ca/kubernetes.key out/ca/kubernetes.crt ""
generate_crt out/cert/etcd server ${DEFAULT_CA_DAYS} kube-etcd "" out/ca/etcd.key out/ca/etcd.crt "etcd.local" "etcd.cluster.local" "localhost" "127.0.0.1"
generate_crt out/cert/etcd peer ${DEFAULT_CA_DAYS} kube-etcd-peer "" out/ca/etcd.key out/ca/etcd.crt "etcd.local" "etcd.cluster.local" "localhost" "127.0.0.1"
generate_crt out/cert front-proxy ${DEFAULT_CA_DAYS} front-proxy-client "" out/ca/front-proxy.key out/ca/front-proxy.crt ""
generate_key_pair out/cert sa
generate_crt out/cert/accounts scheduler ${DEFAULT_CA_DAYS} system:kube-scheduler "" out/ca/kubernetes.key out/ca/kubernetes.crt ""
generate_crt out/cert/accounts controller-manager ${DEFAULT_CA_DAYS} system:kube-controller-manager "" out/ca/kubernetes.key out/ca/kubernetes.crt ""
generate_crt out/cert/accounts addon-manager ${DEFAULT_CA_DAYS} system:kube-addon-manager "" out/ca/kubernetes.key out/ca/kubernetes.crt ""
generate_crt out/cert/accounts proxy ${DEFAULT_CA_DAYS} system:kube-proxy "" out/ca/kubernetes.key out/ca/kubernetes.crt ""
generate_crt out/cert/accounts admin ${DEFAULT_CA_DAYS} kubernetes-admin system:masters out/ca/kubernetes.key out/ca/kubernetes.crt ""
generate_crt out/cert/accounts users ${DEFAULT_CA_DAYS} kubernetes-users system:masters out/ca/kubernetes.key out/ca/kubernetes.crt ""
generate_auth_token out/token kubelet-bootstrap "kubelet-bootstrap" 10001 "system:bootstrappers"
sops_config="../../../../../$(hostname)/secrets/sops.yaml"
secrets_file="../../../../../$(hostname)/secrets/secrets.yaml"
decrypted_secrets_file="../../../../../$(hostname)/secrets/.decrypted~secrets.yaml"
sops -d "${secrets_file}" > "${decrypted_secrets_file}"
yq -i '
del(.kubernetes) |
.kubernetes.ca.kubernetes.crt = load_str("out/ca/kubernetes.crt") |
.kubernetes.ca.kubernetes.key = load_str("out/ca/kubernetes.key") |
.kubernetes.ca.front-proxy.crt = load_str("out/ca/front-proxy.crt") |
.kubernetes.ca.front-proxy.key = load_str("out/ca/front-proxy.key") |
.kubernetes.ca.etcd.crt = load_str("out/ca/etcd.crt") |
.kubernetes.ca.etcd.key = load_str("out/ca/etcd.key") |
.kubernetes.cert.apiserver.server.crt = load_str("out/cert/apiserver/server.crt") |
.kubernetes.cert.apiserver.server.key = load_str("out/cert/apiserver/server.key") |
.kubernetes.cert.apiserver.etcd-client.crt = load_str("out/cert/apiserver/etcd-client.crt") |
.kubernetes.cert.apiserver.etcd-client.key = load_str("out/cert/apiserver/etcd-client.key") |
.kubernetes.cert.apiserver.kubelet-client.crt = load_str("out/cert/apiserver/kubelet-client.crt") |
.kubernetes.cert.apiserver.kubelet-client.key = load_str("out/cert/apiserver/kubelet-client.key") |
.kubernetes.cert.etcd.server.crt = load_str("out/cert/etcd/server.crt") |
.kubernetes.cert.etcd.server.key = load_str("out/cert/etcd/server.key") |
.kubernetes.cert.etcd.peer.crt = load_str("out/cert/etcd/peer.crt") |
.kubernetes.cert.etcd.peer.key = load_str("out/cert/etcd/peer.key") |
.kubernetes.cert.front-proxy.crt = load_str("out/cert/front-proxy.crt") |
.kubernetes.cert.front-proxy.key = load_str("out/cert/front-proxy.key") |
.kubernetes.cert.sa.key = load_str("out/cert/sa.key") |
.kubernetes.cert.sa.pub = load_str("out/cert/sa.pub") |
.kubernetes.cert.accounts.scheduler.crt = load_str("out/cert/accounts/scheduler.crt") |
.kubernetes.cert.accounts.scheduler.key = load_str("out/cert/accounts/scheduler.key") |
.kubernetes.cert.accounts.controller-manager.crt = load_str("out/cert/accounts/controller-manager.crt") |
.kubernetes.cert.accounts.controller-manager.key = load_str("out/cert/accounts/controller-manager.key") |
.kubernetes.cert.accounts.addon-manager.crt = load_str("out/cert/accounts/addon-manager.crt") |
.kubernetes.cert.accounts.addon-manager.key = load_str("out/cert/accounts/addon-manager.key") |
.kubernetes.cert.accounts.proxy.crt = load_str("out/cert/accounts/proxy.crt") |
.kubernetes.cert.accounts.proxy.key = load_str("out/cert/accounts/proxy.key") |
.kubernetes.cert.accounts.admin.crt = load_str("out/cert/accounts/admin.crt") |
.kubernetes.cert.accounts.admin.key = load_str("out/cert/accounts/admin.key") |
.kubernetes.cert.accounts.users.crt = load_str("out/cert/accounts/users.crt") |
.kubernetes.cert.accounts.users.key = load_str("out/cert/accounts/users.key") |
.kubernetes.token.kubelet-bootstrap.token = load_str("out/token/kubelet-bootstrap.token") |
.kubernetes.token.kubelet-bootstrap.csv = load_str("out/token/kubelet-bootstrap.csv")
' "${decrypted_secrets_file}"
sops --config "${sops_config}" -e "${decrypted_secrets_file}" > "${secrets_file}"
rm -rf ${decrypted_secrets_file} out