#!/bin/bash

if [[ $# -eq 0 ]] && ! [[ -v RENEWED_LINEAGE ]]; then
  echo "Usage: $0 <certfile> [keyfile]" >&2
  exit 2
fi

# Setup Journal Logging
exec {STDOUT}>&1
exec {STDERR}>&2
exec {JOURNAL}> >(systemd-cat -t zimbra-deploy-certificate)
exec 1> >(tee >(sed -uE 's/^/<6>/' >&$JOURNAL) >&$STDOUT)
exec 2> >(tee >(sed -uE 's/^/<4>/' >&$JOURNAL) >&$STDERR)

CERT_TO_DEPLOY="<none>"
KEY_TO_DEPLOY="/opt/zimbra/ssl/zimbra/commercial/commercial.key"

if [[ $# -ne 0 ]]; then
  CERT_TO_DEPLOY="$1"
  shift
  if [[ $# -ne 0 ]]; then
    KEY_TO_DEPLOY="$1"
  fi
else
  echo
fi

if [[ -v RENEWED_LINEAGE ]]; then
  # We're running as certbot deploy-hook
  SOURCE_DIR="${RENEWED_LINEAGE%/}"
  CERT_TO_DEPLOY="$SOURCE_DIR/cert.pem"
  KEY_TO_DEPLOY="$SOURCE_DIR/privkey.pem"
fi

if ! [[ -r "$CERT_TO_DEPLOY" && -r "$KEY_TO_DEPLOY" ]]; then
  echo "No cert/key to deploy found ( $CERT_TO_DEPLOY / $KEY_TO_DEPLOY )" >&2
  exit 1
fi

function __AS_ZIMBRA () {
  local __CMD="${@@Q}"
  echo "Executing as zimbra: $__CMD"
  sudo -u zimbra bash -c "source /opt/zimbra/.bashrc; exec $__CMD"
}

WD=$(mktemp -d)
if ! [[ -n "$WD" && -d "$WD" ]]; then
  echo 'Workdir creation failed!'
  exit 1
fi

echo "Working dir: $WD"
cd "$WD"

echo 'Building CA-Chain'
CURRENT="$CERT_TO_DEPLOY"
I=0
while true; do
  echo "Getting issuer of $CURRENT"
  # Read the file using keytool, as it does automatically detect the type
  ISSUER=$(/opt/zimbra/common/bin/keytool -printcert -rfc -file "$CURRENT" | openssl x509 -noout -ext authorityInfoAccess | sed -En 's/^\s*CA Issuers - URI://p')
  if [[ -z "$ISSUER" ]]; then
    echo "Got no issuer"
    break
  fi
  echo "Got issuer #$((++I)): $ISSUER"
  curl -o "issuer_$I.der" "$ISSUER" 2>/dev/null
  /opt/zimbra/common/bin/keytool -printcert -rfc -file "issuer_$I.der" >> ca_chain.pem
  CURRENT="issuer_$I.der"
done
echo "CA-Cain built, fetched $I issuer certificates"

if ! __AS_ZIMBRA test -r "$CERT_TO_DEPLOY"; then
  echo "Zimbra user cannot read $CERT_TO_DEPLOY, copying to $WD"
  cp "$CERT_TO_DEPLOY" cert.pem
  CERT_TO_DEPLOY="$WD/cert.pem"
fi
if ! __AS_ZIMBRA test -r "$KEY_TO_DEPLOY"; then
  echo "Zimbra user cannot read $KEY_TO_DEPLOY, copying to $WD"
  cp "$KEY_TO_DEPLOY" priv.key
  KEY_TO_DEPLOY="$WD/priv.key"
fi

chown -R zimbra:zimbra "$WD"

echo 'Verifying certificate'
__AS_ZIMBRA zmcertmgr verifycrt comm "$KEY_TO_DEPLOY" "$CERT_TO_DEPLOY" "$WD/ca_chain.pem"
if [[ $? == 0 ]]; then
  echo 'Certificates verified successfully!'
else
  echo 'Certificate verification failed!' >&2
  exit 1
fi

if ! cmp --silent "$KEY_TO_DEPLOY" /opt/zimbra/ssl/zimbra/commercial/commercial.key; then
  echo 'Copying private key to zimbra'
  cp "$KEY_TO_DEPLOY" /opt/zimbra/ssl/zimbra/commercial/commercial.key
  chmod 600 /opt/zimbra/ssl/zimbra/commercial/commercial.key
  chown zimbra:zimbra /opt/zimbra/ssl/zimbra/commercial/commercial.key
fi
echo 'Deploying certificate to zimbra'
__AS_ZIMBRA zmcertmgr deploycrt comm "$CERT_TO_DEPLOY" "$WD/ca_chain.pem"
if [[ $? == 0 ]]; then
  echo 'Certificates deployed successfully!'
else
  echo 'Certificate deployment failed!' >&2
  exit 1
fi

echo 'Restarting zimbra'
cd /opt/zimbra
__AS_ZIMBRA zmcontrol restart
if [[ $? == 0 ]]; then
  echo 'Zimbra restarted successfully!'
else
  echo 'Zimbra restart failed!' >&2
  exit 1
fi

echo 'Cleaning temporary certificate data'
rm -r "$WD"