diff options
-rw-r--r-- | .gitignore | 5 | ||||
-rw-r--r-- | Makefile | 15 | ||||
-rw-r--r-- | ca.conf | 9 | ||||
-rw-r--r-- | generate-and-upload-self-signed-keys.conf | 8 | ||||
-rwxr-xr-x | generate-and-upload-self-signed-keys.in | 125 | ||||
-rw-r--r-- | generate-and-upload-self-signed-keys.service.in | 6 | ||||
-rwxr-xr-x | sign-ca | 12 | ||||
-rwxr-xr-x | sign-ca.in | 63 | ||||
-rw-r--r-- | sign-ca.service.in | 6 | ||||
-rw-r--r-- | sign-ca.timer (renamed from generate-and-upload-self-signed-keys.timer) | 0 | ||||
-rwxr-xr-x | sign-request.in (renamed from sign-request) | 19 |
11 files changed, 105 insertions, 163 deletions
@@ -1,2 +1,3 @@ -generate-and-upload-self-signed-keys -generate-and-upload-self-signed-keys.service +sign-ca +sign-ca.service +sign-request @@ -1,5 +1,5 @@ # -# generate-and-upload-self-signed-keys - script to handle self signed keys +# simple-pki - scripts to handle a simple pki # # Copyright (c) 2019 Erich Eckner <opensource at eckner dot net> # @@ -27,7 +27,7 @@ MANDIR = /usr/share/man VERSION = 0.2 -all: generate-and-upload-self-signed-keys generate-and-upload-self-signed-keys.service +all: sign-ca sign-request sign-ca.service %: %.in sed " \ @@ -36,14 +36,15 @@ all: generate-and-upload-self-signed-keys generate-and-upload-self-signed-keys.s s@#ETCDIR#@$(ETCDIR)@; \ s@#HELPTEXT#\(\s\+\)#@ --help \1display this help and exit\n --version\1display version and exit@; \ " $< > $@ - [ "$@" = "generate-and-upload-self-signed-keys" ] && chmod +x "$@" || true + [ "$@" = "sign-ca" ] && chmod +x "$@" || true .PHONY: install dist clean -install: - install -D -m0755 generate-and-upload-self-signed-keys $(DESTDIR)$(BINDIR)/generate-and-upload-self-signed-keys - install -D -m0644 generate-and-upload-self-signed-keys.conf $(DESTDIR)$(ETCDIR)/generate-and-upload-self-signed-keys.conf - install -D -m0644 -t $(DESTDIR)$(LIBDIR)/systemd/system generate-and-upload-self-signed-keys.service generate-and-upload-self-signed-keys.timer +install-ca: + install -D -m0755 -t $(DESTDIR)$(BINDIR) sign-ca sign-request + install -D -m0644 -t $(DESTDIR)$(ETCDIR)/simple-pki ca.conf + install -d -m0700 $(DESTDIR)$(ETCDIR)/simple-pki/keys + install -D -m0644 -t $(DESTDIR)$(LIBDIR)/systemd/system sign-ca.service sign-ca.timer clean: ls -A | \ @@ -0,0 +1,9 @@ +#!/bin/bash + +# details of the ca +ca_name='eckner-ca' +ca_subject_prefix='/C=DE/ST=Thuringia/L=Jena/O=Eckner/OU=Net' + +# where should the ca certificates be published? +remote_host='user@example.com' +remote_dir='httpdocs/certs' diff --git a/generate-and-upload-self-signed-keys.conf b/generate-and-upload-self-signed-keys.conf deleted file mode 100644 index a83ab66..0000000 --- a/generate-and-upload-self-signed-keys.conf +++ /dev/null @@ -1,8 +0,0 @@ -#!/bin/bash - -# ignore these hosts -ignore_hosts=('localhost') - -# where should the certificates be published? -remote_host='user@example.com' -remote_dir='httpdocs/certs' diff --git a/generate-and-upload-self-signed-keys.in b/generate-and-upload-self-signed-keys.in deleted file mode 100755 index 9215d22..0000000 --- a/generate-and-upload-self-signed-keys.in +++ /dev/null @@ -1,125 +0,0 @@ -#!/bin/bash - -if [ -r '#ETCDIR#/generate-and-upload-self-signed-keys.conf' ]; then - . '#ETCDIR#/generate-and-upload-self-signed-keys.conf' -fi - -key_dir='#ETCDIR#/nginx/keys' - -cd / - -hosts=$( - find '#ETCDIR#/nginx/' \ - -name keys -prune , \ - -name sites-available -prune , \ - \( -type f -o -type l \) \ - -exec sed -n ' - s/^\s*// - /^server_name\s.*;/ p - /^server_name[^;]*$/,/;/ p - ' {} \; 2>/dev/null \ - | tr '\n' ' ' \ - | sed ' - s/\s\+/ /g - s/;\s*/;\n/g - '"$( - printf 's/\\s%s\\(;\\|\\s\)//\n' "${ignore_hosts[@]}" - )"' - ' \ - | sed -n ' - s/^server_name // - T - s/;$// - T - p - ' \ - | sort -u -) - -host_key_files=$( - printf '%s\n' "${hosts}" \ - | cut -d' ' -f1 -) - -if [ "$(whoami)" = 'root' ]; then - updated_something=false - for host_key_file in ${host_key_files}; do - if [ -f "${key_dir}/${host_key_file}.key.pem.new" ] \ - && [ -f "${key_dir}/${host_key_file}.cert.pem.new" ]; then - if [ "$(stat -c%Y "${key_dir}/${host_key_file}.key.pem.new")" -ge "$(($(date +%s)-60*60*24*30))" ] \ - && [ -f "${key_dir}/${host_key_file}.key.pem" ] \ - && [ "$(stat -c%Y "${key_dir}/${host_key_file}.cert.pem.new")" -ge "$(($(date +%s)-60*60*24*30))" ] \ - && [ -f "${key_dir}/${host_key_file}.cert.pem" ]; then - continue - fi - mv "${key_dir}/${host_key_file}.key.pem"{.new,} - mv "${key_dir}/${host_key_file}.cert.pem"{.new,} - updated_something=true - fi - done - if ${updated_something}; then - systemctl try-restart nginx - fi - - su http -s /bin/bash -c "$0" -fi - -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 - 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 "${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 - -if [ ! -s "${tmp_dir}/commands" ]; then - >&2 echo 'nothing to do.' - exit -fi - -cd "${tmp_dir}" - -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 diff --git a/generate-and-upload-self-signed-keys.service.in b/generate-and-upload-self-signed-keys.service.in deleted file mode 100644 index 2f851c4..0000000 --- a/generate-and-upload-self-signed-keys.service.in +++ /dev/null @@ -1,6 +0,0 @@ -[Unit] -Description=generate and manage self-signed keys - -[Service] -Type=oneshot -ExecStart=#BINDIR#/generate-and-manage-self-signed-keys diff --git a/sign-ca b/sign-ca deleted file mode 100755 index f2e8200..0000000 --- a/sign-ca +++ /dev/null @@ -1,12 +0,0 @@ -#!/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-ca.in b/sign-ca.in new file mode 100755 index 0000000..ff0e0c5 --- /dev/null +++ b/sign-ca.in @@ -0,0 +1,63 @@ +#!/bin/bash + +# generate new ca certificate, roll over the old one(s) + +set -e + +key_dir='#ETCDIR#/simple-pki/keys' + +if [ -r '#ETCDIR#/simple-pki/ca.conf' ]; then + . '#ETCDIR#/simple-pki/ca.conf' +fi + +if [ -f "${key_dir}/${ca_name}.key.new" ] \ +&& [ -f "${key_dir}/${ca_name}.crt.new" ]; then + if [ "$(stat -c%Y "${key_dir}/${ca_name}.key.new")" -lt "$(($(date +%s)-60*60*24*30))" ] \ + || [ ! -f "${key_dir}/${ca_name}.key" ] \ + || [ "$(stat -c%Y "${key_dir}/${ca_name}.crt.new")" -lt "$(($(date +%s)-60*60*24*30))" ] \ + || [ ! -f "${key_dir}/${ca_name}.crt" ]; then + mv "${key_dir}/${host_key_file}.key"{.new,} + mv "${key_dir}/${host_key_file}.crt"{.new,} + fi +fi + +if [ ! -f "${key_dir}/${ca_name}.key.new" ] \ +|| [ ! -f "${key_dir}/${ca_name}.crt.new" ]; then + openssl req -x509 -new \ + -newkey rsa:4096 -sha256 \ + -keyout "${key_dir}/${ca_name}.key.new" \ + -out "${key_dir}/${ca_name}.crt.new" \ + -days 365 -nodes \ + -subj "${ca_subject}"'/CN=Certification Authority' \ + -addext 'subjectKeyIdentifier = hash' \ + -addext 'authorityKeyIdentifier = keyid:always, issuer' \ + -addext 'basicConstraints = critical, CA:true' \ + -addext 'keyUsage = keyCertSign, cRLSign' +done + +rsync --ignore-missing-args \ + "${key_dir}/${ca_name}.crt"{.new,} \ + "${remote_host}:${remote_dir}/" + +( + cd "${key_dir}" + printf '%s %s\n' "$( + date -u --iso-8601=seconds -d@$(stat -c%Y "${ca_name}.key") \ + | cut -d+ -f1 + )" "$( + sha512sum "${ca_name}.key" \ + | sed 's/\s\+/ /' + )" +) \ +| 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 +' diff --git a/sign-ca.service.in b/sign-ca.service.in new file mode 100644 index 0000000..b87ad36 --- /dev/null +++ b/sign-ca.service.in @@ -0,0 +1,6 @@ +[Unit] +Description=generate new ca key and certificate + +[Service] +Type=oneshot +ExecStart=#BINDIR#/sign-ca diff --git a/generate-and-upload-self-signed-keys.timer b/sign-ca.timer index 308a8e6..308a8e6 100644 --- a/generate-and-upload-self-signed-keys.timer +++ b/sign-ca.timer diff --git a/sign-request b/sign-request.in index cf3442e..f70c99a 100755 --- a/sign-request +++ b/sign-request.in @@ -1,5 +1,11 @@ #!/bin/bash +key_dir='#ETCDIR#/simple-pki/keys' + +if [ -r '#ETCDIR#/simple-pki/ca.conf' ]; then + . '#ETCDIR#/simple-pki/ca.conf' +fi + cd "${0%/*}" remove_leading_spaces() { @@ -36,11 +42,18 @@ while read -r csr; do cn=$( printf '%s\n' "${content}" \ | sed ' - s/^Subject: .*, CN = \(\S\+\)$/\1/ + s/^Subject: // t d - ' + ' \ + | tr -d ' ' \ + | tr ',' '/' ) + if [ -n "${cn#${ca_subject_prefix}/CN=*/}" ]; then + continue + fi + cn="${cn#${ca_subject_prefix}/CN=}" + cn="${cn%/}" sans=$( printf '%s\n' "${content}" \ | sed -n ' @@ -82,7 +95,7 @@ while read -r csr; do 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' + openssl req -x509 -key "${key_dir}/${ca_name}.key" -in "${csr_local}" -out "${csr_local%.csr}.crt" -addext 'basicConstraints = critical, CA:false' rm "${csr_local}" done |