#!/bin/bash
# Generate a "modern" TLS CSR (using SANs and ECC)

# Copyright (C) 2022  Johannes Truschnigg <johannes@truschnigg.info>
#
# This program is free software: you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the Free
# Software Foundation, either version 3 of the License, or (at your option)
# any later version.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
# more details.
#
# You should have received a copy of the GNU General Public License along with
# this program. If not, see <https://www.gnu.org/licenses/>.

echo 'Hostnames (space-separated, 1st will be CN, issuer, and filename prefix): '
read -r -e -i "${hostname:-host.example.com}" hostnames
echo 'IP addresses (optional; space-separated): '
read -r -e -i "${ip:-192.168.2.1}"  ips
echo 'Country Name (2 letter code): '
read -r -e -i "${country:-US}" country
echo 'State or Province Name: '
read -r -e -i "${state:-Some-State}" state
echo 'City/Locality: '
read -r -e -i "${city:-Some-City}" city
echo 'Org. Name: '
read -r -e -i "${o:-Example Organisation, Ltd.}" o
echo 'Org. Unit Name: '
read -r -e -i "${ou:-Example Department}" ou
echo 'Email address: '
read -r -e -i "${email:-some-certmaster-address@example.com}" email


umask 0077

san_dns=''
for h in ${hostnames}
do
  [[ -z ${cn} ]] && dn="CN=${h}" && cn="${h}"
  san_dns="DNS:${h},${san_dns}"
done

for i in ${ips}
do
  san_ip="IP:${i},${san_ip}"
done

subjectAltName="${san_dns}"
[[ -n ${san_ip} ]] && subjectAltName="${subjectAltName}${san_ip}"
subjectAltName="${subjectAltName%,*}"
[[ -n ${email} ]] && subjectAltName="${subjectAltName},email:${email}"

set -u
set -e
echo Generting key in "${cn}.key.pem" ...
openssl ecparam -genkey -name secp521r1 -noout -out "${cn}.key.pem"
echo Generting CSR in "${cn}.csr.pem" ...
openssl req -reqexts san_details -new -key "${cn}.key.pem" -sha256 -utf8 -subj "/CN=${cn}/C=${country}/ST=${state}/L=${city}/O=${o}/OU=${ou}/" -extensions san_details -out "${cn}.csr.pem" -config <(
cat <<-EODATA
	[req]
	prompt=no
	distinguished_name=dn_details

	[dn_details]
	${dn}

	[san_details]
	subjectAltName=${subjectAltName}
EODATA
)

echo "========================================================================================"
echo "All done, csr data follows:"
openssl req -in "${cn}.csr.pem" -noout -text
ls -l "./${cn}.key.pem" "./${cn}.csr.pem"
