#!/bin/bash
# shows current status of certificates and managed services

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-usage()
{
  cat << ENDUSAGE

Usage: asceds [-h] [-d] [-l] [-c] [-m <string>] [-t <type>] [-u <username>]

Shows a summary of current status of certificate files and managed services
-h --> display usage and exit
-d --> describes in detail asceds utilities and usage
-l --> shows summary of warnings/errors from log files
-c --> show details about clients
-m <string> --> name or SANs of the client matches <string> (no regexp)
-t <type> --> type of the client matches type (unman*, pman*, fman*)
-u <username> --> lists unmanaged clients requested by web <username>;
              works only with "-t unman"
-m and -t work only with -c, otherwise they are ignored

ENDUSAGE
exit 0
}

# show details
SHOWDETAILS=''

# show from logs
SHOWFROMLOGS=''

# show detailed client info
SHOWCLIENTDETAILS=''

# match string
MATCHSTRING=''

# client type
CLIENTTYPE=''

# requested by user
REQBYUSER=''

# 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-usage
   elif [ "${ARG}" == "-l" ] ; then
      shift
      SHOWFROMLOGS='yes'
   elif [ "${ARG}" == "-d" ] ; then
      shift
      SHOWDETAILS="yes"
   elif [ "${ARG}" == "-c" ] ; then
      shift
      SHOWCLIENTDETAILS="yes"
   elif [ "${ARG}" == "-m" ] ; then
      shift
      if [[ "$1" != -* ]] && [ -n "$1" ] ; then
         # match string (no regexp)
         MATCHSTRING=$( cat <<< $1 | tr '[:upper:]' '[:lower:]' )
      fi
   elif [ "${ARG}" == "-t" ] ; then
      shift
      if [[ "$1" != -* ]] && [ -n "$1" ] ; then
         # client type
         CLIENTTYPE=$( cat <<< $1 | tr '[:upper:]' '[:lower:]' )
      fi
   elif [ "${ARG}" == "-u" ] ; then
      shift
      if [[ "$1" != -* ]] && [ -n "$1" ] ; then
         # requested by user
         REQBYUSER=$( cat <<< $1 | tr '[:upper:]' '[:lower:]' )
         TESTUSER=$( ${GREP} "\['${REQBYUSER}'\]" ${ASCEDSWEBDIR}/etc/users.php )
         if [ -z "${TESTUSER}" ] ; then
            asceds-error "Web user ${REQBYUSER} does not exist."
         fi
      fi
   else
      shift
   fi
done

if [ ! -d "${ASCEDSDOCDIR}" ] ; then
   asceds-error "No doc dir ${ASCEDSDOCDIR}"
fi
echo
echo "ASCEDS version ${ASCEDSVER}"

echo
cat ${ASCEDSDOCDIR}/Summary

if [ -n "${SHOWDETAILS}" ] ; then
   echo -----------------------------------------------------------
   cat ${ASCEDSDOCDIR}/Scripts
   echo -----------------------------------------------------------
   cat ${ASCEDSDOCDIR}/CronJobs
   echo -----------------------------------------------------------
   cat ${ASCEDSDOCDIR}/DefaultDirs
   echo -----------------------------------------------------------
   cat ${ASCEDSDOCDIR}/Triggers
   echo -----------------------------------------------------------
   cat ${ASCEDSDOCDIR}/Email
   echo -----------------------------------------------------------
   cat ${ASCEDSDOCDIR}/ClientTypeChange
   echo -----------------------------------------------------------
   cat ${ASCEDSDOCDIR}/Chains
fi

# now display status
echo
echo ========= ASCEDS STATUS ===============================
echo
if [ -f "${ASCEDSETCDIR}/asceds-certbot.conf" ] && \
   [ -f "/etc/cron.d/asceds-cert-propagate" ] ; then
   echo "Configured as certificate manager:"  
   echo "   ACME server: ${ACMESERVER}"
   echo "   Authorized for domains: ${AUTHDOMAIN}"
   echo "   Current certbot clients:"
   for CMCLIENT in $( ls -1 /etc/letsencrypt/live/ | grep -v README | \
                      xargs ) ; do
      echo "      ${CMCLIENT}"
      if [ ! -r "${ASCEDSHOMEDIR}/${CMCLIENT}_cert.conf" ] ; then
         asceds-warning "Client ${CMCLIENT} does not have cert.conf file"
      fi
      if [ ! -d "${ASCEDSHOMEDIR}/${CMCLIENT}" ] ; then
         asceds-warning "Client ${CMCLIENT} does not have cert dir"
      fi
   done
   if [ "$( echo ${ASCEDSHOMEDIR}/down/* )" != \
            "${ASCEDSHOMEDIR}/down/*" ] ; then 
      echo "   Fully managed clients currently unreachable:"
      for HOSTSDOWN in $( ls -1 ${ASCEDSHOMEDIR}/down/ | xargs ) ; do
         echo "      ${HOSTSDOWN}"
      done
   fi
   echo
fi

if [ -f "/etc/cron.d/asceds-cert-refresh" ] ; then
   echo "Configured as client:"  
   asceds-client-showconf

   echo "   Services using certificates (use asceds-services to reconfigure)"
   # display available services

   AVAILABLESERV=""
   if [ -d "${ASCEDSSERVDIR}" ] && 
      [ "$( echo ${ASCEDSSERVDIR}/*.sh.proto )" != "${ASCEDSSERVDIR}/*.sh.proto" ]  ; then
      cd ${ASCEDSSERVDIR}
      for SERV in *.sh.proto ; do
         if [ -f "${SERV}" ] ; then
            AVAILABLESERV="${AVAILABLESERV} ${SERV%.sh.proto}"
         fi
      done
   elif [ ! -d "${ASCEDSSERVDIR}" ] ; then
      asceds-error "No dir for service templates: ${ASCEDSSERVDIR}"
   fi
   echo "      Available services: ${AVAILABLESERV}"

   # display activated services
   ACTIVESERV=''
   DIFFFROMTEMP=''
   NOTEMPSERV=''
   if [ -d "${ASCEDSSERVCONF}" ] && \
      [ "$( echo ${ASCEDSSERVCONF}/*.sh )" != "${ASCEDSSERVCONF}/*.sh" ]  ; then
      cd ${ASCEDSSERVCONF}
      for SERV in *.sh ; do
         if [ -f "${SERV}" ] ; then
            ACTIVESERV="${ACTIVESERV} ${SERV%.sh}"
         fi

         if [ -r ${ASCEDSSERVDIR}/${SERV}.proto ] ; then
            # take into account: service scripts are selfconfiguring
            if [ -n "$( diff -I "SITESDIR=" ${ASCEDSSERVDIR}/${SERV}.proto ${SERV} )" ] ; then
               DIFFFROMTEMP="${DIFFFROMTEMP} ${SERV%.sh}"
            fi
         else
            NOTEMPSERV="${NOTEMPSERV} ${SERV%.sh}"
         fi
      done
   elif [ ! -d "${ASCEDSSERVCONF}" ] ; then
      asceds-error "No dir for services: ${ASCEDSSERVCONF}"
   fi
   if [ -n "${ACTIVESERV}" ] ; then
      echo "      Active services: ${ACTIVESERV}"
      if [ -n "${DIFFFROMTEMP}" ] ; then
         echo "      Active services not matching templates: ${DIFFFROMTEMP}"
      fi
      if [ -n "${NOTEMPSERV}" ] ; then
         echo "      No templates found for: ${NOTEMPSERV}"
      fi
   fi

   echo
fi

if [ -n "${SHOWCLIENTDETAILS}" ] ; then
   echo
   echo ========= ASCEDS client details =====================
   echo
   if [ "$( echo ${ASCEDSHOMEDIR}/*_cert.conf )" != \
            "${ASCEDSHOMEDIR}/*_cert.conf" ] ; then
      # find hostname of client
      for HSTCONF in ${ASCEDSHOMEDIR}/*_cert.conf ; do
         if [ -r "${HSTCONF}" ] ; then
            HST=$( basename ${HSTCONF} )
            HST=${HST%%_*}
            asceds-parse-certconf "${HSTCONF}"
            if [ -z "${CLIENT_DOMAIN_NAME}" ] || \
               [ -z "${HST}" ] || \
               [ "${HST}" != "${CLIENT_DOMAIN_NAME}" ] ; then
               asceds-error "Client '${HST}' is misconfigured"
            fi
            MATCHCLIENT='yes'
            if [ -n "${MATCHSTRING}" ] && 
               ! [[ "${HST}" =~ "${MATCHSTRING}" ]] && \
               ! [[ "${CLIENT_SANS_LIST}" =~ "${MATCHSTRING}" ]] ; then
               MATCHCLIENT=''
            fi
            if [ -n "${CLIENTTYPE}" ] ; then 
               if [ -z "${NO_RETURN}" ] ; then
                  if [[ "${CLIENTTYPE}" != "fman"* ]] ; then
                     MATCHCLIENT=''
                  fi
               else   
                  if [ -z "${NO_ASCEDS}" ] ; then
                     if [[ "${CLIENTTYPE}" != "pman"* ]] ; then
                        MATCHCLIENT=''
                     fi
                  else
                     if [[ "${CLIENTTYPE}" != "unman"* ]] ; then
                        MATCHCLIENT=''
                     fi
                  fi
               fi
            fi
            if [ -n "${REQBYUSER}" ] ; then
               if [ "${NO_ASCEDS}" != "${REQBYUSER}" ] ; then
                  MATCHCLIENT=''
               fi
            fi
            if [ -n "${MATCHCLIENT}" ] ; then
               echo "Client name: ${CLIENT_DOMAIN_NAME}"
               if [ -n "${CLIENT_SANS_LIST}" ] ; then
                  echo "   SAN list: ${CLIENT_SANS_LIST}"
               fi
               if [ -n "${NO_ASCEDS}" ] ; then
                  echo "   Client type: Unmanaged, requested by ${NO_ASCEDS}"
               elif [ -n "${NO_RETURN}" ] ; then
                  echo "   Client type: Privately managed"
               else
                  echo "   Client type: Fully managed"
               fi
               if [ -n "${CLIENT_PLATFORM}" ] ; then
                  echo "   Client platform: ${CLIENT_PLATFORM}"
               fi
               if [ -n "${CLIENT_ENC}" ] ; then
                  echo "   Certificate encoding: ${CLIENT_ENC}"
               fi
               CERTFILE="${ASCEDSHOMEDIR}/${HST}/cert.pem"
               if [ -r "${CERTFILE}" ] ; then
                  openssl x509 -dates -noout < ${CERTFILE} | \
                     ${GREP} "notAfter=" | \
                     sed -e "s/notAfter=/   Certificate expiration: /"
               fi
               if [ -z "${NO_RETURN}" ] ; then
                  if [ -r "${ASCEDSHOMEDIR}/down/${CLIENT_DOMAIN_NAME}" ] ; then
                     echo "   Client status: UNREACHEABLE"
                  else
                     echo "   Client status: online"
                  fi
               fi
               echo
            fi
         fi
      done
   else
      echo "No ASCEDS clients found"
   fi
fi

if [ -n "${SHOWFROMLOGS}" ] ; then
   echo
   echo ========= LOG summary ===============================
   if [ -d "${ASCEDSLOGDIR}" ] ; then
   
      if [ "$( echo ${ASCEDSLOGDIR}/*.log )" != "${ASCEDSLOGDIR}/*.log" ]  ; then

         for LOGFILE in ${ASCEDSLOGDIR}/*.log ; do
            ${GREP} -f ${DIGESTREGEXP} ${LOGFILE}
         done
      else
         asceds-warning "No .log file found in ${ASCEDSLOGDIR}"
      fi
      if [ "$( echo ${ASCEDSLOGDIR}/*.error )" != "${ASCEDSLOGDIR}/*.error" ]  ; then
         for LOGFILE in ${ASCEDSLOGDIR}/*.error ; do
            ${GREP} -f ${DIGESTREGEXP} ${LOGFILE}
         done
      else
         asceds-warning "No .error file found in ${ASCEDSLOGDIR}"
      fi
   else
      asceds-error "No log dir ${ASCEDSLOGDIR} found"
   fi
fi

