#!/bin/bash
# initialize certificate subscription

SPATH="$(dirname "$(readlink -f ${BASH_SOURCE[0]})")"    # dir of the script
SNAME="$(basename ${BASH_SOURCE[0]})"                    # name of the script

ASCEDSCONF='local site certbot hostconf'
ASCEDSLIBS='utils hosts postfix openssl'

if [ ! -r "${SPATH}/asceds-head" ] ; then
   echo "No header ${SPATH}/asceds-head. Exiting"
   exit 9
fi

. ${SPATH}/asceds-head

asceds-init-usage()
{
  cat << ENDUSAGE

Usage: asceds-init [-h] [-r] [-f] [-s <certmanager>]

Initializes certificate client
-h --> display usage and exit
-r --> set noreturn policy, client is read-only
-f --> site using self signed certificates 
-s <certmanager> --> the site certificate manager

Checks/fixes network configuration including hosts, postfix, openssl.cnf.
Builds certificate manager URL:
  if no cert manager is mentioned in the command line, ask for it;
Retrieves the site config file from the certificate manager,
  parse and create {ASCEDSETCDIR}/asceds-site.conf.
Sets the certificate encoding in {ASCEDSETCDIR}/asceds-hostconf.conf.
Generates certificate configuration in cert.conf.
Copies logrotate asceds config file.
Creates renewal crontab: asceds-cert-refresh
Work done on root/sudo@certmanager if access available, 
      otherwise prints instructions and exits:
  Runs setup script: asceds-client-setup -s -c ${CLIENT_DOMAIN_NAME}
Selects and configures services which depend on certificates and 
      have reconfig scripts: asceds-services

ENDUSAGE
exit 0
}

# collect arguments for remote asceds-client-setup execution
CLIENTSETUPARGS=" -q -s "

# default noreturn is false for automatic update of the certs
SETNORETURN=''

# initialize certificate manager
ASCEDSALTCRTMGR=''

# force self signed site
SELFSIGNED=''

# general validation and parse of the command line
for ARG in ${ARGS} ; do
   #echo "ARG=${ARG}"
   if [ "${ARG}" != "${ARG//[^-_a-zA-Z0-9.:\/]/}" ] ; then
      asceds-error "Malformed argument ${ARG}"
   elif [ "${ARG}" == "-h" ] ; then
      asceds-init-usage
   elif [ "${ARG}" == "-r" ] ; then
      shift
      SETNORETURN='yes'
   elif [ "${ARG}" == "-f" ] ; then
      shift
      SELFSIGNED="yes"
   elif [ "${ARG}" == "-s" ] ; then
      shift
      if [[ "$1" != -* ]] && [ -n "$1" ] ; then
         ASCEDSALTCRTMGR=$( cat <<< $1 | tr '[:upper:]' '[:lower:]' )
         asceds-validate-fqdn "${ASCEDSALTCRTMGR}" || \
            asceds-error "Invalid certificate manager FQDN ${ASCEDSALTCRTMGR}"
      fi
   else
      shift
   fi
done

# run as root only
asceds-run-asroot

asceds-refresh-var "${ASCEDSETCDIR}/asceds-certbot.conf" \
   "SELFSIGNED" "${SELFSIGNED}"


echo "This script configures the ASCEDS client on this computer."
echo "To run successfully, the following conditions must be fulfilled:"
echo "1. This computer shold be connected to the network, having a routable"
echo "   IP address, and a DNS record."
echo "2. The certificate manager should be reachable and properly initialized,"
echo "   with the web interface running."
echo "3. The domain of this computer should be among the domains served"
echo "   by the certificate manager."
echo "4. The admin must have an account on the certificate manager, "
echo "   with management rights for the domain."
echo
YES=''
echo -n "Do you want to continue? [Y/n] "
read YES
if [ "${YES}" == "n" ] || [ "${YES}" == "N" ] ; then
   echo "Good bye."
   exit 1
fi

# clean old asceds-local.conf for backwards compatibility
if [ -r "${ASCEDSETCDIR}/asceds-local.conf" ] ; then
   ${RM} -f ${ASCEDSETCDIR}/asceds-local.conf
fi
# identify the local mail sender, if any     
asceds-find-mail
asceds-source-etcconf "${ASCEDSETCDIR}" "${ASCEDSCONF}"

# check/fix network configuration
asceds-check-netconf

# retrieve site config file from the certificate manager
SELFSIGNED="${SELFSIGNED}" ASCEDSALTCRTMGR="${ASCEDSALTCRTMGR}" \
   asceds-update-siteconfig -c || \
   asceds-error "The site config file cannot be retrieved from the certificate manager."
asceds-source-etcconf "${ASCEDSETCDIR}" "${ASCEDSCONF}"

# set choices in asceds-hostconf.conf
asceds-build-hostconf
asceds-source-etcconf "${ASCEDSETCDIR}" "${ASCEDSCONF}"

# clean old configuration and certificates 
asceds-clean

# generates ${ASCEDSHOMEDIR}/cert.conf 
asceds-build-certconf "${SETNORETURN}"
asceds-parse-certconf "${ASCEDSHOMEDIR}/cert.conf"
# manages SANS
if [ -n "${SETNORETURN}" ] ; then
   SANSUPDATEARGS="-l -r"
else 
   SANSUPDATEARGS="-l"
fi
asceds-sans-update ${SANSUPDATEARGS} || \
      asceds-error "asceds-sans-update failed"
# refresh cert parameters
asceds-parse-certconf "${ASCEDSHOMEDIR}/cert.conf" 
if [ -z "${CLIENT_DOMAIN_NAME}" ] ; then
   asceds-error "empty CLIENT_DOMAIN_NAME after asceds-build-certconf"
fi
CLIENTSETUPARGS="${CLIENTSETUPARGS} -c ${CLIENT_DOMAIN_NAME} "

# make sure ${ASCEDSHOMEDIR} contains the right dirs
if [ ! -d "${ASCEDSHOMEDIR}/certs" ] ; then
   mkdir ${ASCEDSHOMEDIR}/certs
   chown asceds:asceds ${ASCEDSHOMEDIR}/certs
fi

# Copies logrotate asceds config file
if [ -d "/etc/logrotate.d" ] && [ -r "${ASCEDSCONFDIR}/asceds-logrotate.proto" ] ; then
   if [ ! -f "/etc/logrotate.d/asceds" ] ; then
      asceds-echo "Configuring ASCEDS logrotate policy; please check and reconfigure if needed."
      ${CP} ${ASCEDSCONFDIR}/asceds-logrotate.proto /etc/logrotate.d/asceds
   else
      asceds-echo "ASCEDS logrotate policy already exists; please check and reconfigure if needed."
   fi
else
   asceds-warning "System doesn't have logrotate, or prototype logrotate 
     policy ${ASCEDSCONFDIR}/asceds-logrotate.proto is missing"
fi

if [ -d "/etc/cron.d" ] ; then 
   # Creates renewal crontab: asceds-cert-refresh
   CRONF="/etc/cron.d/asceds-cert-refresh"
   if [ ! -r "${CRONF}" ] ; then
      asceds-echo "Creating cron file asceds-cert-refresh"
      cat <<< "# performs service reconfiguration when triggered by ${ASCEDSHOMEDIR}/.asceds-reconf" \
          > ${CRONF}
      if [ -x "${SPATH}/asceds-service-reconfig" ] ; then 
         # run it every day at 23:23
         cat <<< "23 23 * * * root ${SPATH}/asceds-service-reconfig -q -t > /dev/null 2>&1" \
             >> ${CRONF}
      else
         asceds-error "The service reconfig script ${SPATH}/asceds-service-reconfig not found. Please fix and try again"
      fi
   else
      asceds-echo "Cron file ${CRONF} exists, please tune it to your needs"
   fi
elif [ -n "${NO_RETURN}" ] ; then
   asceds-echo "Client set NO_RETURN to read-only; No crontab needed"
else
   asceds-error "No cron dir /etc/cron.d on client with automatic updates"
fi

# Show the final config before going for the certificate
echo
echo "The final config before going for the certificate."
echo "Please check it carefully"
asceds-client-showconf

#######################################
# work on root@certmanager follows
YE=''
echo
echo "Do you have root/sudo ssh access" 
echo -n "to the certificate manager ${ASCEDSCRTMGR}? [Y/n] "
read YE
if [ "${YE}" == "n" ] || [ "${YE}" == "N" ] ; then
   # use the web interface to initialize cert.conf  
   echo
   if [ -n "${ASCEDSCRTMGR}" ] ; then
      echo "Please login to the web interface"
      echo "https://${ASCEDSCRTMGR}/cert/host_check.php?client_type=asceds&hostname=${CLIENT_DOMAIN_NAME%%.*}&domain=${CLIENT_DOMAIN_NAME#*.}"
      echo "to initialize the certificate manager for this managed client." 
      echo "Client name: ${CLIENT_DOMAIN_NAME}"
   else
      echo "--> Please run as root/sudo on the certificate manager ${ASCEDSCRTMGR}:"
      echo "asceds-client-setup -q -s -c ${CLIENT_DOMAIN_NAME}"
   fi
   echo "--> Then run as root/sudo asceds-services on the client (here) to configure" 
   echo "local services with the new certificate."
   exit 0
fi

SUDOUSER='root'
YE=''
echo "Sudo user to be used on ${ASCEDSCRTMGR}: (default 'root')"
read -e -p 'SUDOUSER = ' -i 'root' SUDOUSER0
echo
SUDOUSER0=$( cat <<< "${SUDOUSER0}" | sed -e "s/\s*//g" )
if [ -n "${SUDOUSER0}" ] && [[ "${SUDOUSER0}" != -* ]] && \
   [ "${SUDOUSER0}" == "${SUDOUSER0}" ] ; then
   SUDOUSER="${SUDOUSER0}"
fi

# Run setup script: asceds-client-setup
eval /usr/bin/ssh -ax -o ClearAllForwardings=yes ${SUDOUSER}@${ASCEDSCRTMGR} \
   sudo -S asceds-client-setup ${CLIENTSETUPARGS} \
   || asceds-error "asceds-client-setup failed"

#####################################

# which services need certificates? activate and reconfigure them
# first the existing services
${SPATH}/asceds-service-reconfig -q -t \
   || asceds-error "asceds-service-reconfig failed"
# then other services which may be available
${SPATH}/asceds-services

