#!/usr/bin/env bash

set -eo pipefail
shopt -s nullglob

# --------------------------- Set Default Parameters ---------------------------

TLS_DIR=${TLS_DIR:-"/opt/imply/manager/tls"}

# --------------------------- Check if TLS is Enabled --------------------------

if [[ ! -f ${IMPLY_MANAGER_CA_KEY_PATH} ]] && [[ ! -f ${IMPLY_MANAGER_CA_CERT_PATH} ]]; then
  echo "TLS: Disabled"
  [[ "${BASH_SOURCE[0]}" != "${0}" ]] && return 0 || exit 0
fi

echo "TLS: Enabled"

# ---------------------------- Set SSL Asset Paths -----------------------------

if [[ -z "${IMPLY_MANAGER_SSL_KEY_PATH}" || -z "${IMPLY_MANAGER_SSL_CERT_PATH}" ]]; then
  GENERATE_SSL_ASSETS=true
  IMPLY_MANAGER_SSL_KEY_PATH="${TLS_DIR}/onprem.key"
  IMPLY_MANAGER_SSL_CERT_PATH="${TLS_DIR}/onprem.crt"
elif [[ ! -f "${IMPLY_MANAGER_SSL_KEY_PATH}" ]]; then
  echo "IMPLY_MANAGER_SSL_KEY_PATH [${IMPLY_MANAGER_SSL_KEY_PATH}] does not exist"
  exit 1
elif [[ ! -f "${IMPLY_MANAGER_SSL_CERT_PATH}" ]]; then
  echo "IMPLY_MANAGER_SSL_KEY_PATH [${IMPLY_MANAGER_SSL_CERT_PATH}] does not exist"
  exit 1
else
  GENERATE_SSL_ASSETS=false
fi

# ------------------------- Create TLS Asset Directory  ------------------------

mkdir -p "${TLS_DIR}"
chmod 750 "${TLS_DIR}"

# ------------------------------ Compute SHASUM  -------------------------------

SHASUMS="${TLS_DIR}/.sha256sums"
NEW_SHASUMS="${TLS_DIR}/.sha256sums-$$"

sha256sum "${IMPLY_MANAGER_CA_KEY_PATH}" "${IMPLY_MANAGER_CA_CERT_PATH}" > "${NEW_SHASUMS}"

## Only generate TLS assets for a new CA key and cert
if [[ -f "${SHASUMS}" ]] && cmp --silent "${SHASUMS}" "${NEW_SHASUMS}"; then
  rm -f "${NEW_SHASUMS}"
  [[ "${BASH_SOURCE[0]}" != "${0}" ]] && return 0 || exit 0
fi

# --------------------------- Recreate TLS Directory ---------------------------

rm -rf "${TLS_DIR:?}/"*

# --------------------------- Maybe Generate SSL Cert --------------------------

if "${GENERATE_SSL_ASSETS}"; then

  # ------------------------------ Validate Expiry -----------------------------

  EXPIRY_SEC=$(
    openssl x509 -enddate -noout -in "${IMPLY_MANAGER_CA_CERT_PATH}" |
    cut -d= -f 2 |
    xargs -0 date +%s -d
  )

  NOW_SEC=$(date +%s)
  SECONDS_IN_DAY=86400

  NEW_EXPIRY=$(((EXPIRY_SEC - NOW_SEC) / SECONDS_IN_DAY))

  if [ ! "${NEW_EXPIRY}" -gt 0 ]; then
    echo "Certificate [${IMPLY_MANAGER_CA_CERT_PATH}] has expired."
    exit 1
  fi

  # ------------------------------ Detect Hostnames ----------------------------

  HOSTS=$(
    hostname -A |
    tr " " "\n" |
    grep -v '^[[:blank:]]*$' |
    uniq |
    tr "\n" " "
  )

  if [ -n "${IMPLY_MANAGER_HOSTNAMES}" ]; then
    HOSTS="${HOSTS} ${IMPLY_MANAGER_HOSTNAMES}"
  fi

  # ----------------------------- Detect IP Addresses --------------------------

  IP_ADDRESSES=$(
    hostname -I |
    tr " " "\n" |
    grep -v '^[[:blank:]]*$' |
    uniq |
    tr "\n" " "
  )

  # -------------------------- Generate OpenSSL Config -------------------------

  cat <<EOT > "${TLS_DIR}/cert.conf"
[req]
default_bits = 2048
prompt = no
encrypt_key = no
req_extensions = v3_req
distinguished_name = dn

[dn]
commonName = ${IMPLY_MANAGER_HOST}
stateOrProvinceName = California
countryName = US
organizationName = Imply Data, Inc
organizationalUnitName = Development

[v3_req]
subjectAltName = @alt_names

[alt_names]
DNS.1 = ${IMPLY_MANAGER_HOST}
DNS.2 = localhost
EOT

  i=3
  for HOST in ${HOSTS}; do
    echo "DNS.$((i++)) = ${HOST}" >> "${TLS_DIR}/cert.conf"
  done

  i=1
  for IP in ${IP_ADDRESSES}; do
    echo "IP.$((i++)) = ${IP}" >> "${TLS_DIR}/cert.conf"
  done

  openssl req \
    -new\
    -nodes\
    -keyout "${IMPLY_MANAGER_SSL_KEY_PATH}"\
    -out "${TLS_DIR}/manager.csr"\
    -config "${TLS_DIR}/cert.conf" &> /dev/null

  # --------------------------------  Sign Cert --------------------------------
  openssl x509 \
    -req\
    -in "${TLS_DIR}/manager.csr"\
    -CA "${IMPLY_MANAGER_CA_CERT_PATH}"\
    -CAkey "${IMPLY_MANAGER_CA_KEY_PATH}"\
    -CAcreateserial\
    -CAserial "${TLS_DIR}/ca.srl"\
    -extensions v3_req\
    -out "${IMPLY_MANAGER_SSL_CERT_PATH}"\
    -days "${NEW_EXPIRY}"\
    -extfile "${TLS_DIR}/cert.conf" &> /dev/null
fi

# --------------------------- Convert Cert to PKCS12 ---------------------------

openssl pkcs12\
  -export\
  -in "${IMPLY_MANAGER_CA_CERT_PATH}"\
  -inkey "${IMPLY_MANAGER_CA_KEY_PATH}"\
  -out "${TLS_DIR}/ca.p12"\
  -name imply-onprem\
  -passout pass: &> /dev/null

openssl pkcs12\
  -export\
  -in "${IMPLY_MANAGER_SSL_CERT_PATH}"\
  -inkey "${IMPLY_MANAGER_SSL_KEY_PATH}"\
  -out "${TLS_DIR}/onprem.p12"\
  -name manager\
  -passout pass: &> /dev/null

# -------------------------------- Generate JKS --------------------------------

keytool\
  -importkeystore\
  -srckeystore "${TLS_DIR}/ca.p12"\
  -srcstoretype PKCS12\
  -srcstorepass ""\
  -alias imply-onprem\
  -destkeystore "${TLS_DIR}/ca.jks"\
  -deststorepass "onprem"\
  -destkeypass "onprem" &> /dev/null

keytool\
  -importkeystore\
  -srckeystore "${TLS_DIR}/onprem.p12"\
  -srcstoretype PKCS12\
  -srcstorepass ""\
  -alias manager\
  -destkeystore "${TLS_DIR}/onprem.jks"\
  -deststorepass "onprem"\
  -destkeypass "onprem" &> /dev/null

# ------------------------- Cleanup Intermediate Files -------------------------

rm -f "${TLS_DIR:?}/"*.p12

# ------------------------------- Rename SHASUM --------------------------------

## Mark tls asset folder as up to date
mv "${NEW_SHASUMS}" "${SHASUMS}"
