Changeset - 0b86d3da5a29
[Not reviewed]
0 5 0
Branko Majic (branko) - 6 years ago 2018-07-23 22:27:52
branko@majic.rs
MAR-133: Improve output for certificate checks:

- Do not produce warnings in case no certificates have been configured
for checking.
- Only send out mails about certificates that are about to expire.
- Include information in how many days a certificate is going to
expire.
- Include information on whether the certificates has already expired.
5 files changed with 70 insertions and 19 deletions:
0 comments (0 inline, 0 general)
docs/releasenotes.rst
Show inline comments
 
@@ -33,6 +33,11 @@ New features/improvements:
 
  * The ``pip`` requirements upgrade checks now do not output warning
 
    in case deployed ``.in`` file does not have a matching ``.txt``
 
    file.
 
  * Certificate expiration check is less verbose. No mails are sent
 
    out any longer in case no certificates have been configured for
 
    checking, nor in cases where all certificates have passed the
 
    check. E.g. mails are sent out only in case some of the configured
 
    certificates will expire within next 30 days.
 

	
 

	
 
2.0.0
docs/rolereference.rst
Show inline comments
 
@@ -282,7 +282,9 @@ The role implements the following:
 
* Sets-up system for performing checks on certificates (currently only if they
 
  expire within less than 30 days). Roles that want their certificates checked
 
  should deploy a ``.conf`` to directory ``/etc/check_certificate/`` with paths
 
  to certificate files, one per line. Certificates are checked on daily basis.
 
  to certificate files, one per line. Certificates are checked on
 
  daily basis, using crontab (resulting in failures being sent out to
 
  the ``root`` user).
 
* Deploys ``apticron`` package that performs checks for available package
 
  upgrades on daily basis. Mails are delivered to local ``root`` account, and
 
  can be redirected elsewhere via aliases. If using ``mail_forwarder`` or
docs/usage.rst
Show inline comments
 
@@ -594,11 +594,12 @@ one up first. This includes both the LDAP *server* and *client* configuration.
 

	
 
   .. note::
 
      Another useful feature the roles implement is a check to see if
 
      certificates will expire within the next 30 days. This check is performed
 
      via cronjob at midnight, and results will end-up being delivered to the
 
      ``root`` user on local server. Later on, once you have configured the mail
 
      server, you should be able to set-up the necessary aliases to have the
 
      mails delivered to non-local accounts too.
 
      certificates will expire within the next 30 days. This check is
 
      performed via cronjob at midnight, and failing results will
 
      end-up being delivered to the ``root`` user on local
 
      server. Later on, once you have configured the mail server, you
 
      should be able to set-up the necessary aliases to have the mails
 
      delivered to non-local accounts too.
 

	
 
   1. Let's first install a couple of more tools on the Ansible server, since we
 
      will be using ``certtool`` for our improvised CA needs (run this as
roles/common/files/check_certificate.sh
Show inline comments
 
@@ -59,6 +59,8 @@ $program accepts the following options:
 
        can be specified multiple times on the command line in order to verify
 
        multiple certificates.
 

	
 
    -q
 
        Enable quiet mode. Output only warnings and errors.
 

	
 
    -d
 
        Enable debug output.
 
@@ -121,17 +123,15 @@ fi
 

	
 
# Set-up functions for printing coloured messages.
 
function debug() {
 
    if [[ $DEBUG != 0 ]]; then
 
	echo "${_text_bold}${_text_blue}[DEBUG]${_text_reset}" "$@"
 
    fi
 
    [[ $DEBUG != 0 ]] && echo "${_text_bold}${_text_blue}[DEBUG]${_text_reset}" "$@"
 
}
 

	
 
function info() {
 
    echo "${_text_bold}${_text_white}[INFO] ${_text_reset}" "$@"
 
    [[ $QUIET == 0 ]] && echo "${_text_bold}${_text_white}[INFO] ${_text_reset}" "$@"
 
}
 

	
 
function success() {
 
    echo "${_text_bold}${_text_green}[OK]   ${_text_reset}" "$@"
 
    [[ $QUIET == 0 ]] && echo "${_text_bold}${_text_green}[OK]   ${_text_reset}" "$@"
 
}
 

	
 
function warning() {
 
@@ -155,24 +155,65 @@ function error() {
 
#
 
function check_expiration() {
 
    local certificate_file="$1"
 
    local certificate_file_expiration_date
 
    local certificate_expiration_date certificate_expiration_date_in_seconds certificate_expires_in
 
    local current_date_in_seconds
 
    local expiration_period_seconds
 
    local status
 

	
 
    let expiration_period_seconds="$expiration_period"*24*60*60
 

	
 
    debug "Running expiration check for file: $certificate_file"
 
    debug "Expiration period set to: $expiration_period"
 

	
 
    certificate_file_expiration_date=$(openssl x509 -enddate -noout -in "$certificate_file" | sed -e 's/^notAfter=//')
 
    certificate_expiration_date=$(openssl x509 -enddate -noout -in "$certificate_file" | sed -e 's/^notAfter=//')
 
    certificate_expiration_date_in_seconds=$(date -d "$certificate_expiration_date" "+%s")
 
    current_date_in_seconds=$(date "+%s")
 
    let certificate_expires_in="$certificate_expiration_date_in_seconds-$current_date_in_seconds"
 

	
 
    if (( $certificate_expires_in >= 0 )); then
 
        status="expires"
 
    else
 
        status="expired"
 
    fi
 

	
 
    if openssl x509 -noout -in "$certificate_file" -checkend "$expiration_period_seconds" > /dev/null; then
 
	success "Expiration check ($expiration_period days) passed for $certificate_file (expires on $certificate_file_expiration_date)."
 
        success "Certificate $certificate_file $status on $certificate_expiration_date, $(print_relative_period "$certificate_expires_in")."
 
	return 0
 
    else
 
	error "Expiration check ($expiration_period days) failed for $certificate_file (expires on $certificate_file_expiration_date)."
 
        error "Certificate $certificate_file $status on $certificate_expiration_date, $(print_relative_period "$certificate_expires_in")."
 
	return 1
 
    fi
 
}
 

	
 
#
 
# Outputs period relative to current time in human-readable format
 
# with granularity in days.
 
#
 
# Arguments:
 
#
 
#   $1 - Time period in seconds. Can be negative to denote past.
 
#
 
function print_relative_period() {
 
    local seconds="$1"
 
    local days leftover
 

	
 
    let days="$seconds/(60*60*24)"
 

	
 
    if (( $days == 1 )); then
 
        echo "in $days day"
 
    elif (( $days > 1 )); then
 
        echo "in $days days"
 
    elif (( $days == 0 && $seconds > 0 )); then
 
        echo "in less than a day"
 
    elif (( $days == 0 && $seconds < 0 )); then
 
        echo "less than a day ago"
 
    elif (( $days == -1 )); then
 
        echo "one day ago"
 
    elif (( $days < -1 )); then
 
        echo "${days#-} days ago"
 
    fi
 
}
 

	
 
# Exit codes
 
ERROR_SUCCESS=0
 
ERROR_PARAMETERS=1
 
@@ -186,6 +227,7 @@ fi
 

	
 
# Disable debug by default.
 
DEBUG=0
 
QUIET=0
 

	
 
# Set-up default option values.
 
let expiration_period=30
 
@@ -195,11 +237,12 @@ certificate_files=()
 
configuration_directory="/etc/check_certificate"
 

	
 
# Parse the arguments
 
while getopts "e:c:C:xdvh" opt; do
 
while getopts "e:c:C:xqdvh" opt; do
 
    case "$opt" in
 
	e) let expiration_period="$OPTARG";;
 
	c) certificate_files+=("$OPTARG");;
 
	C) configuration_directory="$OPTARG";;
 
        q) QUIET=1;;
 
	d) DEBUG=1;;
 
        v) version
 
           exit $ERROR_SUCCESS;;
 
@@ -238,9 +281,9 @@ if [[ ${#certificate_files[@]} == 0 ]]; then
 
    done
 
fi
 

	
 
# Log a warning if list of certificates is empty.
 
# Inform user that no certificates have been configured for checking.
 
if [[ ${#certificate_files[@]} == 0 ]]; then
 
    warning "No certificate files were specified for checking."
 
    info "No certificate files were specified for checking."
 
fi
 

	
 
# Process the certificate files.
roles/common/tasks/main.yml
Show inline comments
 
@@ -267,7 +267,7 @@
 
    cron_file: "check_certificate"
 
    hour: 0
 
    minute: 0
 
    job: "/usr/local/bin/check_certificate.sh expiration"
 
    job: "/usr/local/bin/check_certificate.sh -q expiration"
 
    state: present
 
    user: nobody
 

	
0 comments (0 inline, 0 general)