116 lines
2.3 KiB
Bash
116 lines
2.3 KiB
Bash
|
|
#!/bin/sh
|
||
|
|
set -eu
|
||
|
|
|
||
|
|
CA_DIR="${CA_DIR:-$(dirname $0)/ca}"
|
||
|
|
CERTS_DIR="${CERTS_DIR:-$(dirname $0)/certs}"
|
||
|
|
|
||
|
|
CA_KEY="${CA_DIR}/ca.key"
|
||
|
|
CA_CERT="${CA_DIR}/ca.pem"
|
||
|
|
|
||
|
|
NAME="${1:-}"
|
||
|
|
DAYS="${DAYS:-825}"
|
||
|
|
KEY_BITS="${KEY_BITS:-2048}"
|
||
|
|
|
||
|
|
if [ -z "${NAME}" ]; then
|
||
|
|
echo "Usage:"
|
||
|
|
echo " $0 <name> [san1 san2 ...]"
|
||
|
|
echo
|
||
|
|
echo "Examples:"
|
||
|
|
echo " $0 api.local api.local localhost 127.0.0.1"
|
||
|
|
echo " $0 client-1"
|
||
|
|
exit 1
|
||
|
|
fi
|
||
|
|
|
||
|
|
if [ ! -f "${CA_KEY}" ] || [ ! -f "${CA_CERT}" ]; then
|
||
|
|
echo "CA files not found. Run gen-ca.sh first."
|
||
|
|
exit 1
|
||
|
|
fi
|
||
|
|
|
||
|
|
shift || true
|
||
|
|
|
||
|
|
if [ -e "${CERTS_DIR}/${NAME}" ]; then
|
||
|
|
echo "Certificate for ${NAME} already exists."
|
||
|
|
echo "Nothing to do."
|
||
|
|
exit 0
|
||
|
|
fi
|
||
|
|
|
||
|
|
mkdir -p "${CERTS_DIR}/${NAME}"
|
||
|
|
|
||
|
|
KEY="${CERTS_DIR}/${NAME}/${NAME}.key.pem"
|
||
|
|
CSR="${CERTS_DIR}/${NAME}/${NAME}.csr.pem"
|
||
|
|
CERT="${CERTS_DIR}/${NAME}/${NAME}.cert.pem"
|
||
|
|
EXT="${CERTS_DIR}/${NAME}/${NAME}.ext.cnf"
|
||
|
|
FULLCHAIN="${CERTS_DIR}/${NAME}/${NAME}.fullchain.pem"
|
||
|
|
|
||
|
|
SUBJECT="${SUBJECT:-/C=US/O=Localhost LLC/CN=${NAME}}"
|
||
|
|
|
||
|
|
cat > "${EXT}" <<EOF
|
||
|
|
[req]
|
||
|
|
distinguished_name = req_distinguished_name
|
||
|
|
req_extensions = v3_req
|
||
|
|
prompt = no
|
||
|
|
|
||
|
|
[req_distinguished_name]
|
||
|
|
CN = ${NAME}
|
||
|
|
|
||
|
|
[v3_req]
|
||
|
|
basicConstraints = CA:FALSE
|
||
|
|
keyUsage = critical, digitalSignature, keyEncipherment
|
||
|
|
extendedKeyUsage = serverAuth, clientAuth
|
||
|
|
subjectAltName = @alt_names
|
||
|
|
|
||
|
|
[alt_names]
|
||
|
|
EOF
|
||
|
|
|
||
|
|
i=1
|
||
|
|
if [ "$#" -gt 0 ]; then
|
||
|
|
for san in "$@"; do
|
||
|
|
case "${san}" in
|
||
|
|
*[!0-9.]* | .* | *.)
|
||
|
|
echo "DNS.${i} = ${san}" >> "${EXT}"
|
||
|
|
;;
|
||
|
|
*.*.*.*)
|
||
|
|
echo "IP.${i} = ${san}" >> "${EXT}"
|
||
|
|
;;
|
||
|
|
*)
|
||
|
|
echo "DNS.${i} = ${san}" >> "${EXT}"
|
||
|
|
;;
|
||
|
|
esac
|
||
|
|
i=$((i + 1))
|
||
|
|
done
|
||
|
|
else
|
||
|
|
echo "DNS.1 = ${NAME}" >> "${EXT}"
|
||
|
|
fi
|
||
|
|
|
||
|
|
openssl genrsa -out "${KEY}" "${KEY_BITS}"
|
||
|
|
chmod 600 "${KEY}"
|
||
|
|
|
||
|
|
openssl req \
|
||
|
|
-new \
|
||
|
|
-key "${KEY}" \
|
||
|
|
-subj "${SUBJECT}" \
|
||
|
|
-out "${CSR}"
|
||
|
|
|
||
|
|
openssl x509 \
|
||
|
|
-req \
|
||
|
|
-in "${CSR}" \
|
||
|
|
-CA "${CA_CERT}" \
|
||
|
|
-CAkey "${CA_KEY}" \
|
||
|
|
-CAcreateserial \
|
||
|
|
-out "${CERT}" \
|
||
|
|
-days "${DAYS}" \
|
||
|
|
-sha256 \
|
||
|
|
-extfile "${EXT}" \
|
||
|
|
-extensions v3_req
|
||
|
|
|
||
|
|
cat "${CERT}" "${CA_CERT}" > "${FULLCHAIN}"
|
||
|
|
|
||
|
|
chmod 644 "${CSR}" "${CERT}" "${EXT}" "${FULLCHAIN}"
|
||
|
|
|
||
|
|
echo "Certificate issued:"
|
||
|
|
echo " key: ${KEY}"
|
||
|
|
echo " csr: ${CSR}"
|
||
|
|
echo " cert: ${CERT}"
|
||
|
|
echo " fullchain: ${FULLCHAIN}"
|
||
|
|
|
||
|
|
openssl x509 -in "${CERT}" -noout -subject -issuer -dates -ext subjectAltName
|