diff options
Diffstat (limited to 'rotate-keys.in')
-rw-r--r-- | rotate-keys.in | 127 |
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 |