#!/bin/bash
# assist initial setup of a new client

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

ASCEDSCONF='local site certbot'
ASCEDSLIBS='utils'

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

. ${SPATH}/asceds-head

asceds-client-setup-usage()
{
  cat << ENDUSAGE

Usage: asceds-client-setup [-h] [-s] [-q] -c <client_name>

Gets client parameters, generates new certificate, copies files to the client;
to be run on the cert manager as root/sudo through asceds-init on the client;
-h --> display usage and exit
-c <client_name> --> client to be setup; print usage if missing
-q --> no question asked; sends output to the logs
-s --> clean old keys of the client in ~asceds/.ssh/known_hosts

Scp client's cert.conf to ${ASCEDSHOMEDIR}/${CLIENT_NAME}_cert.conf
Validity checks
    DOMAIN_NAME --> CLIENT_DOMAIN_NAME
    SANS_LIST --> CLIENT_SANS_LIST
Generates new certificate: asceds-certbot-gencert
Creates flag for transferring the certificates .newcerts
Transfers cert back: asceds-send-cert -c <client_name>

ENDUSAGE
exit 0
}

# collect arguments for remote asceds-client-setup execution
GENCERTARGS="-e -d "

# output to terminal by default
QUIETRUN=''

# clean old ssh known_hosts client keys (default = no)
KNOWNHOSTSCLEAN=''

# initialize CLIENT_NAME
CLIENT_NAME=''

# general validation and parse of the command line
if  [ -z "${ARGS}" ] ; then
   asceds-client-setup-usage
else
   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-client-setup-usage
      elif [ "${ARG}" == "-q" ] ; then
         shift
         asceds-exec-noninteractive "$*"
         # bring other scripts in non-interactive mode
         QUIETRUN="y"
      elif [ "${ARG}" == "-s" ] ; then
         shift
         KNOWNHOSTSCLEAN="yes"
      elif [ "${ARG}" == "-c" ] ; then
         shift
         if [[ "$1" != -* ]] && [ -n "$1" ] ; then
            CLIENT_NAME=$( cat <<< $1 | tr '[:upper:]' '[:lower:]' )
            asceds-validate-fqdn "${CLIENT_NAME}" || \
               asceds-error "Invalid client FQDN ${CLIENT_NAME}"
         fi
      else
         shift
      fi
   done
fi
if [ -z "${CLIENT_NAME}" ] ; then
   asceds-client-setup-usage
fi
# run as root only
asceds-run-asroot

# checks on client name
if [ -z "${CLIENT_NAME}" ] || [[ "${CLIENT_NAME}" = "-"* ]] ; then
   asceds-error "No client name passed as argument"
else
   asceds-echo "Setting up client ${CLIENT_NAME}"
fi

# clean old keys in known_hosts
if [ -n "${KNOWNHOSTSCLEAN}" ] ; then
   asceds-echo "Clening up known_hosts on the client ${CLIENT_NAME}"
   eval sudo -u asceds -i ssh-keygen -f ${ASCEDSHOMEDIR}/.ssh/known_hosts \
                                     -R ${CLIENT_NAME}
   asceds-ip-resolve ${CLIENT_NAME} && \
   eval sudo -u asceds -i ssh-keygen -f ${ASCEDSHOMEDIR}/.ssh/known_hosts \
                                     -R ${ASCEDS_IP}
fi

# Scp client's cert.conf to ${ASCEDSHOMEDIR}/${DOMAIN_NAME}_cert.conf
asceds-echo "Retrieving cert.conf from the client ${CLIENT_NAME}"
eval sudo -u asceds -i ${SCP} asceds@${CLIENT_NAME}:cert.conf \
     ${ASCEDSHOMEDIR}/${CLIENT_NAME}_cert.conf
sed -i -e "s/^SANS_LIST=/CLIENT_SANS_LIST=/" ${ASCEDSHOMEDIR}/${CLIENT_NAME}_cert.conf
sed -i -e "s/^DOMAIN_NAME=/CLIENT_DOMAIN_NAME=/" ${ASCEDSHOMEDIR}/${CLIENT_NAME}_cert.conf
asceds-parse-certconf "${ASCEDSHOMEDIR}/${CLIENT_NAME}_cert.conf"
if [ "${CLIENT_NAME}" != "${CLIENT_DOMAIN_NAME}" ] ; then
   asceds-warning "The client name ${CLIENT_NAME} passed as a script argument is different
   from the DOMAIN_NAME claimed by the client's cert.conf file"
   TESTNAME=$( echo ${CLIENT_SANS_LIST} | ${GREP} -w ${CLIENT_NAME} )
   if [ -z "${TESTNAME}" ] ; then
      asceds-error "The client name ${CLIENT_NAME} passed as a script argument is not
      even in the SANS list claimed by the client's cert.conf file"
   fi
else
   GENCERTARGS="${GENCERTARGS} -c ${CLIENT_DOMAIN_NAME} "
   asceds-echo "Handling certificate for DOMAIN_NAME=${CLIENT_DOMAIN_NAME}"
fi
if [ -n "${CLIENT_SANS_LIST}" ] ; then
   GENCERTARGS="${GENCERTARGS} -s ${CLIENT_SANS_LIST} "
   asceds-echo "Client SANS_LIST=${CLIENT_SANS_LIST}"
fi

#    generates initial cert asceds-certbot-gencert
if [ -z "${QUIETRUN}" ] ; then
   # if in interactive mode ask before acting
   echo -n "Generating certificate files ... continue? [N/y] "
   read YE
else
   # else generate without asking
   YE='y'
fi
if [ "${YE}" = "y" ] || [ "${YE}" = "Y" ] ; then
   GENCERTARGS="-e -q -c ${CLIENT_DOMAIN_NAME}"
   if [ -n "${CLIENT_SANS_LIST}" ] ; then
      GENCERTARGS="${GENCERTARGS} -s ${CLIENT_SANS_LIST}"
   fi 
   asceds-certbot-gencert ${GENCERTARGS}
else
   asceds-echo "Aborted interactively."
   exit 4
fi

if [ -d "${ASCEDSHOMEDIR}/${CLIENT_NAME}" ] &&
   [ "$( echo ${ASCEDSHOMEDIR}/${CLIENT_NAME}/* )" != \
            "${ASCEDSHOMEDIR}/${CLIENT_NAME}/*" ] ; then
   touch ${ASCEDSHOMEDIR}/${CLIENT_NAME}/.newcerts
   chown asceds:asceds ${ASCEDSHOMEDIR}/${CLIENT_NAME}/.newcerts
else
   asceds-error "Host cert directory ${ASCEDSHOMEDIR}/${CLIENT_NAME} not found"
fi

# send certificate files back to ${CLIENT_NAME} and 
#        set service reconfiguration trigger
sudo -u asceds -i asceds-send-cert -q -c ${CLIENT_NAME}

