diff options
-rwxr-xr-x | generate-and-upload-self-signed-keys.in | 93 | ||||
-rwxr-xr-x | sign-ca | 12 | ||||
-rwxr-xr-x | sign-request | 90 |
3 files changed, 147 insertions, 48 deletions
diff --git a/generate-and-upload-self-signed-keys.in b/generate-and-upload-self-signed-keys.in index 951bf72..9215d22 100755 --- a/generate-and-upload-self-signed-keys.in +++ b/generate-and-upload-self-signed-keys.in @@ -68,61 +68,58 @@ if [ "$(whoami)" != 'http' ]; then exit fi +if [ -n "$(trap)" ]; then + >&2 echo 'outer traps set - those will be forgotten!' + exit 1 +fi + +tmp_dir=$(mktemp -d '/srv/http/httpdocs/.csr/tmp.XXXXXXXXXX') +trap 'rm -rf --one-file-system "${tmp_dir}"' EXIT + printf '%s\n' "${hosts}" \ | while read -r host other_hosts; do if [ -f "${key_dir}/${host}.key.pem.new" ] \ && [ -f "${key_dir}/${host}.cert.pem.new" ]; then continue fi - openssl req -x509 -newkey rsa:4096 \ + if [ -n "${other_hosts}" ]; then + extensions="-addext subjectAltName=$( + printf ',DNS:%s' \ + "${host}" \ + ${other_hosts} \ + | sed 's/^,//' + )" + else + extensions='' + fi + openssl req -newkey rsa:4096 \ -keyout "${key_dir}/${host}.key.pem.new" \ - -out "${key_dir}/${host}.cert.pem.new" \ - -days 365 -nodes -subj '/C=DE/ST=Thuringia/L=Jena/O=Eckner/OU=Net/CN='"${host}" -sha256 \ - -config <( - cat '#ETCDIR#/ssl/openssl.cnf' - if [ -n "${other_hosts}" ]; then - printf '\n[SAN]\nsubjectAltName' - printf ',DNS:%s' \ - "${host}" \ - ${other_hosts} \ - | sed 's/^,/=/' - fi - ) + -out "${tmp_dir}/${host}.csr" \ + -nodes -subj '/C=DE/ST=Thuringia/L=Jena/O=Eckner/OU=Net/CN='"${host}" -sha256 \ + ${extensions} + printf 'https://%s/.csr/%s/%s.csr %s %s\n' \ + "${host}" \ + "${tmp_dir##*/}" \ + "${host}" \ + '/C=DE/ST=Thuringia/L=Jena/O=Eckner/OU=Net/CN='"${host}" \ + "${extensions}" \ + >> "${tmp_dir}/commands" done -rsync --ignore-missing-args \ - $( - printf -- "${key_dir}"'/%s.cert.pem\n' ${host_key_files} - printf -- "${key_dir}"'/%s.cert.pem.new\n' ${host_key_files} - ) \ - "${remote_host}:${remote_dir}/" +if [ ! -s "${tmp_dir}/commands" ]; then + >&2 echo 'nothing to do.' + exit +fi + +cd "${tmp_dir}" -( - cd "${key_dir}" - { - printf '%s.cert.pem\n' ${host_key_files} - printf '%s.cert.pem.new\n' ${host_key_files} - } \ - | while read -r key; do - [ -f "${key}" ] || continue - printf '%s %s\n' "$( - date -u --iso-8601=seconds -d@$(stat -c%Y "${key}") \ - | cut -d+ -f1 - )" "$( - sha512sum "${key}" \ - | sed 's/\s\+/ /' - )" - done -) \ -| ssh "${remote_host}" ' - cd "'"${remote_dir}"'" - while read -r time sum file; do - rm -f ????-??-??T??\:??\:??".${file}" - mv "${file}" "${time}.${file}" - sed -i '"'"' - / [^.]\+\.'"'"'"${file//./\.}"'"'"'$/d - '"'"' sha512sums - printf '"'"'%s %s\n'"'"' "${sum}" "${time}.${file}" \ - >> sha512sums - done -' +cut -d' ' -f1 \ +< 'commands' \ +| ssh -T erich@192.168.1.3 \ +| tar -xzf - + +for host_key_file in ${host_key_files}; do + [ -f "${tmp_dir}/${host_key_file}.crt" ] || continue + cat "${tmp_dir}/${host_key_file}.crt" \ + > "${key_dir}/${host_key_file}.cert.pem.new" +done @@ -0,0 +1,12 @@ +#!/bin/bash + +openssl req -x509 \ + -new -nodes \ + -key eckner-ca.key \ + -sha256 -days 3654 \ + -out eckner-ca.crt \ + -subj '/C=DE/ST=Thuringia/L=Jena/O=Eckner/OU=Net/CN=Certification Authority' \ + -addext 'subjectKeyIdentifier = hash' \ + -addext 'authorityKeyIdentifier = keyid:always, issuer' \ + -addext 'basicConstraints = critical, CA:true' \ + -addext 'keyUsage = keyCertSign, cRLSign' diff --git a/sign-request b/sign-request new file mode 100755 index 0000000..cf3442e --- /dev/null +++ b/sign-request @@ -0,0 +1,90 @@ +#!/bin/bash + +cd "${0%/*}" + +remove_leading_spaces() { + sed ' + s/^ \{'"$1"'\}// + t + d + ' +} + +tmp_dir=$(mktemp -d) +trap 'rm -rf --one-file-system "${tmp_dir}"' EXIT + +while read -r csr; do + csr_local="${tmp_dir}/${csr##*/}" + curl -Ss "${csr}" -o "${csr_local}" + if ! content=$( + openssl req -text -noout -verify -in "${csr_local}" 2>/dev/null + ); then + rm "${csr_local}" + continue + fi + content=$( + printf '%s\n' "${content}" \ + | sed -n ' + /^Certificate Request:$/,/^\S/p + ' \ + | remove_leading_spaces 4 \ + | sed -n ' + /^Data:$/,/^\S/p + ' \ + | remove_leading_spaces 4 + ) + cn=$( + printf '%s\n' "${content}" \ + | sed ' + s/^Subject: .*, CN = \(\S\+\)$/\1/ + t + d + ' + ) + sans=$( + printf '%s\n' "${content}" \ + | sed -n ' + /^Requested Extensions:$/,/^\S/ p + ' \ + | remove_leading_spaces 4 \ + | sed -n ' + /^X\S\+ Subject Alternative Name:\s*$/,/^\S/ p + ' \ + | remove_leading_spaces 4 \ + | sed ' + s/, /\n/g + ' + ) + if printf '%s\n' "${sans}" | grep -vq '^\(DNS\|IP\):'; then + continue + fi + sans=$( + printf '%s\n' "${sans}" \ + | sed ' + s/^\(DNS\|IP\):// + ' + ) + ok_sans=$( + printf '%s\n' "${cn}" "${sans}" \ + | while read -r san; do + if ! curl -Ss --insecure 'https://'"${san}/${csr#*//*/}" \ + | diff -q - "${csr_local}"; then + rm "${csr_local}" + break + fi + printf '%s\n' "${san}" + done + ) + if [ ! -f "${csr_local}" ]; then + continue + fi + if [ "$(printf '%s\n' "${cn}" "${sans}")" != "${ok_sans}" ]; then + rm "${csr_local}" + continue + fi + openssl req -x509 -key eckner-ca.key -in "${csr_local}" -out "${csr_local%.csr}.crt" -addext 'basicConstraints = critical, CA:false' + rm "${csr_local}" +done + +cd "${tmp_dir}" +tar -czf - * |