summaryrefslogtreecommitdiff
path: root/rotate-keys.in
diff options
context:
space:
mode:
Diffstat (limited to 'rotate-keys.in')
-rw-r--r--rotate-keys.in127
1 files changed, 127 insertions, 0 deletions
diff --git a/rotate-keys.in b/rotate-keys.in
new file mode 100644
index 0000000..f965928
--- /dev/null
+++ b/rotate-keys.in
@@ -0,0 +1,127 @@
+#!/bin/bash
+
+key_dir='#ETCDIR#/simple-pki/keys'
+
+if [ -r '#ETCDIR#/simple-pki/cb.conf' ]; then
+ . '#ETCDIR#/simple-pki/cb.conf'
+fi
+
+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)" != "${certificate_user}" ]; then
+
+ if [ "$(whoami)" = 'root' ]; then
+ updated_something=false
+ for host_key_file in ${host_key_files}; do
+ if [ -f "${key_dir}/${host_key_file}.key.new" ] \
+ && [ -f "${key_dir}/${host_key_file}.crt.new" ]; then
+ if [ "$(stat -c%Y "${key_dir}/${host_key_file}.key.new")" -ge "$(($(date +%s)-60*60*24*30))" ] \
+ && [ -f "${key_dir}/${host_key_file}.key" ] \
+ && [ "$(stat -c%Y "${key_dir}/${host_key_file}.crt.new")" -ge "$(($(date +%s)-60*60*24*30))" ] \
+ && [ -f "${key_dir}/${host_key_file}.crt" ]; then
+ continue
+ fi
+ mv "${key_dir}/${host_key_file}.key"{.new,}
+ mv "${key_dir}/${host_key_file}.crt"{.new,}
+ updated_something=true
+ fi
+ done
+ if ${updated_something}; then
+ systemctl try-restart nginx
+ fi
+
+ su "${certificate_user}" -s /bin/bash -c "$0"
+ fi
+
+ 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.new" ] \
+ && [ -f "${key_dir}/${host}.crt.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.new" \
+ -out "${tmp_dir}/${host}.csr" \
+ -nodes -subj "${subject_prefix}"'/CN='"${host}" -sha256 \
+ ${extensions}
+ printf 'https://%s/.csr/%s/%s.csr %s/CN=%s %s\n' \
+ "${host}" \
+ "${tmp_dir##*/}" \
+ "${host}" \
+ "${subject_prefix}" \
+ "${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 "${ca_host}" \
+| tar -xzf -
+
+for host_key_file in ${host_key_files}; do
+ if [ ! -f "${tmp_dir}/${host_key_file}.crt" ]; then
+ continue
+ fi
+ cat "${tmp_dir}/${host_key_file}.crt" \
+ > "${key_dir}/${host_key_file}.crt.new"
+done