#!/bin/bash

# generate new ca certificates, roll over the old one(s)

set -e

if [ -r '/etc/simple-pki/ca.conf' ]; then
  . '/etc/simple-pki/ca.conf'
fi

if [ -n "${ca_user}" ] \
&& [ "$(whoami)" != "${ca_user}" ]; then
  chown -R "${ca_user}" '/etc/simple-pki/ca'
  exec su "${ca_user}" -c "$0"
fi

move_old_ca() {
  mv \
    '/etc/simple-pki/ca/'"$1"'.crt' \
    '/etc/simple-pki/ca/'"$1"'.old.crt'
  rm -rf --one-file-system \
    '/etc/simple-pki/ca/'"$1"'.old'
  mv \
    '/etc/simple-pki/ca/'"$1" \
    '/etc/simple-pki/ca/'"$1"'.old'
  find '/etc/simple-pki/ca/'"$1"'.old' \
    -type f \
    -name "$1"'.*' \
  | sed 's@^\(.*/'"$1"'\)\(\..*\)$@\0 \1.old\2@' \
  | while read -r from to; do
    mv "${from}" "${to}"
  done
}

level_ground_for_new_ca() {
  install -d -m0755 '/etc/simple-pki/ca/'"$1"'/db'
  install -d -m0700 '/etc/simple-pki/ca/'"$1"'/private'
  touch \
    '/etc/simple-pki/ca/'"$1"'/db/'"$1"'.db' \
    '/etc/simple-pki/ca/'"$1"'/db/'"$1"'.db.attr'
  for srl in 'crl' 'crt'; do
    old='/etc/simple-pki/ca/'"$1"'.old/db/'"$1"'.old.'"${srl}"'.srl'
    new='/etc/simple-pki/ca/'"$1"'/db/'"$1"'.'"${srl}"'.srl'
    if [ -f "${old}" ]; then
      cp "${old}" "${new}"
    else
      echo '01' \
      >"${new}"
    fi
  done
}

if [ -f '/etc/simple-pki/ca/root-ca.crt' ]; then
  if [ ! -f '/etc/simple-pki/ca/root-ca.old.crt' ] \
  || [ "$(stat -c%Y '/etc/simple-pki/ca/root-ca.old.crt')" -lt "$(($(date +%s)-60*60*24*ca_keep_duration))" ]; then
    move_old_ca 'root-ca'
  else
    >&2 echo 'nothing to do: "old" root certificate is too new'
    exit
  fi
fi

level_ground_for_new_ca 'root-ca'

if [ -f '/etc/simple-pki/ca/signing-ca.crt' ]; then
  move_old_ca 'signing-ca'
fi

level_ground_for_new_ca 'signing-ca'

CA=root-ca CA_TYPE='Root' openssl req -new \
  -config '/etc/simple-pki/ca-ssl.conf' \
  -out '/etc/simple-pki/ca/root-ca.csr' \
  -keyout '/etc/simple-pki/ca/root-ca/private/root-ca.key'

CA=root-ca CA_TYPE='Root' openssl ca -batch -name root_ca -selfsign \
  -config '/etc/simple-pki/ca-ssl.conf' \
  -in '/etc/simple-pki/ca/root-ca.csr' \
  -out '/etc/simple-pki/ca/root-ca.crt' \
  -extensions root_ca_ext

CA=signing-ca CA_TYPE='Intermediate' openssl req -new \
  -config '/etc/simple-pki/ca-ssl.conf' \
  -out '/etc/simple-pki/ca/signing-ca.csr' \
  -keyout '/etc/simple-pki/ca/signing-ca/private/signing-ca.key'

CA=root-ca CA_TYPE='Root' openssl ca -batch -name root_ca \
  -config '/etc/simple-pki/ca-ssl.conf' \
  -in '/etc/simple-pki/ca/signing-ca.csr' \
  -out '/etc/simple-pki/ca/signing-ca.crt' \
  -extensions signing_ca_ext

rm \
  '/etc/simple-pki/ca/root-ca.csr' \
  '/etc/simple-pki/ca/signing-ca.csr'

rsync --ignore-missing-args \
  '/etc/simple-pki/ca/root-ca'{,.old}'.crt' \
  "${remote_host}:${remote_dir}/"

(
  cd '/etc/simple-pki/ca/'
  find . -maxdepth 1 \
    -type f \( \
      -name root-ca.crt -o \
      -name root-ca.old.crt \
    \) \
    -printf '%TY-%Tm-%TdT%TT ' \
    -exec sha512sum {} \; \
  | sed '
    s/\.[0-9]\+ / /
    s@\s\s\+\(\S\+/\)\?@ @
  '
) \
| ssh "${remote_host}" '
  cd "'"${remote_dir}"'"
  while read -r time sum file; do
    for f in ????-??-??T??\:??\:??".${file}"; do
      [ -f "${f}" ] || continue
      if [ $(date -d"$(openssl x509 -noout -enddate -in "${f}" | cut -d= -f2)" +%s) -lt $(($(date +%s)-24*60*60*30)) ]; then
        rm "${f}"
        sed -i '"'"'
          /^[0-9a-f]\{128\}  '"'"'"${f//./\\.}"'"'"'$/d
        '"'"' sha512sums
      fi
    done
    mv "${file}" "${time}.${file}"
    printf '"'"'%s  %s\n'"'"' "${sum}" "${time}.${file}" \
    >> sha512sums
  done
'
