Script to dynamically update FMS public certificates

The updateCert.sh bash script may be used to replace an existing client certificate with a new certificate in the FMS keystore. Prior to running this ensure that the fmsconf utility is installed and working before using this script.

The script makes a backup copy of the existing client certificate being replaced, then deletes it and then loads the new client certificate.

The following environment variables may be set prior to running the script.

\
\#/usr/bin/env bash
\
\##
\## RCSfile: updateCert.sh,v Revision: 1.1.2.8 Date: 2019-08-01 10:08:45
\##
\# (c) Flame Computing Enterprises cc - All rights reserved
\# 
\# Update FMS public certificate at specified time
\#
\# Usage: updateCert.sh truststore cert_file cert_alias [fms_host]
\# where
\#   truststore: name of the Java Keystore known to FMS in which the certificate must be updated
\#   cert_file: file containing the certificate in x format
\#   cert_alias: alias to be associated with the certificate
\#   fms_host: host on which the FMS administration interface is listening
\#
\# Eg.
\#   updateCert.sh certs.flame /path/to/cert.crt myalias 127.0.0.1
\#
\# To update a certificate on a specific date use the 'at' command to schedule this command as follows
\#
\#   echo "/home/fms/trigger/updateCert.sh flame.jks /home/fms/remotePartner.crt remotePartner" | at '11:15 Oct 17'
\#
\# where
\#   flame.jks is the FMS truststore in which the certificate must be updated
\#   /home/fms/remotePartner.crt is the file containing the public certificate
\#   remotePartner is the alias of the certificate to be updated in the truststore
\#
\# Requirements
\#   fmsconf
\#   fms
\#
\# set -x
\
\# Default ENV variables
\TRUSTSTORE_TYPE=${TRUSTSTORE_TYPE:="JKS"}
\
\TRUSTSTORE_PW=${TRUSTSTORE_PW:="changeit"}
\
\FMS_HOME=${FMS_HOME:="$( grep '^fms:' /etc/passwd |cut -d: -f 6 )"}
\
\if [ "${FMS_HOME}" == "" ]
\then
\  FMS_HOME="/home/fms" # hardwire it.
\fi
\
\BACKUP_DIR=${BACKUP_DIR:="${FMS_HOME}/tmp"}
\
\Usage () {
\  echo <<EOF "Usage: $0 truststore cert_file cert_alias [fms_host]
\  where
\    truststore: name of the Java Keystore known to FMS in which the certificate must be updated
\    cert_file: file containing the certificate in x format
\    cert_alias: alias to be associated with the certificate
\    fms_host: host on which the FMS administration interface is listening. Default is '127.0.0.1'
\
\  Use this utility from the 'at' command to dynamically update a running FMS certificate on a specified date and time.
\
\  The following environment variables may be set before invoking '${0}' 
\
\    FMS_HOME with default '${FMS_HOME}'.
\
\    TRUSTSTORE_TYPE with default '${TRUSTSTORE_TYPE}'.
\
\    TRUSTSTORE_PW with default '${TRUSTSTORE_PW}'.
\
\    BACKUP_DIR with default '${BACKUP_DIR}' for saving certificates being refreshed.
\  "
\EOF
\  exit 1
\}
\
\if [ $# -lt 3 -o $# -gt 4 ]
\then
\  Usage
\fi
\
\TRUSTSTORE=$1
\
\CERT_FILE=$2
\
\if ! test -f ${CERT_FILE}; then
\  echo "Could not locate certificate file '${CERT_FILE}'." 
\  Usage
\else # Determine certificate
\  if grep -q "BEGIN CERTIFICATE" ${CERT_FILE}
\  then # Looks like a cert
\    CERTIFICATE=$(cat ${CERT_FILE} | grep -v 'CERTIFICATE')
\  else
\    echo "Could not locate a certificate in ${CERT_FILE}."
\    Usage
\  fi
\fi
\
\CERT_ALIAS=$3
\
\FMS_HOST=${FMS_HOST:='127.0.0.1'}
\
\if [ $# -eq 4 ]
\then
\  FMS_HOST=$4
\fi
\
\if ! test -d ${BACKUP_DIR}
\then
\  echo "Could not locate the backup directory ${BACKUP_DIR}."
\  Usage
\fi
\
\echo "Saving certificate with alias '${CERT_ALIAS}' to ${BACKUP_DIR}/${CERT_ALIAS}.$$.crt"
\
\# First save the current cert
\
\fmsconf -h ${FMS_HOST} -x "__FMS_Admin_GetCert ${TRUSTSTORE} ${TRUSTSTORE_TYPE} ${TRUSTSTORE_PW} ${CERT_ALIAS}" |grep -v '^OK$' |grep -v '_BLOCK' > ${BACKUP_DIR}/${CERT_ALIAS}.$$.crt
\retval=$?
\if [ $retval -ne 0 ]
\then
\  echo "fmsconf returned error '$retval'. Could not retrieve certificate for '${CERT_ALIAS}' from '${TRUSTSTORE}' at '${FMS_HOST}'."
\  Usage
\fi
\
\# Delete the current cert
\
\echo "Replacing certificate with alias '${CERT_ALIAS}' in '${FMS_HOME}/${TRUSTSTORE}' and details as follows ..."
\echo
\keytool -v -list -keystore ${FMS_HOME}/${TRUSTSTORE} -storepass changeit -alias ${CERT_ALIAS} 2>/dev/null |head -12 |tail -8
\echo
\
\fmsconf -h ${FMS_HOST} -x "__FMS_Admin_DeleteCert ${TRUSTSTORE} ${TRUSTSTORE_TYPE} ${TRUSTSTORE_PW} ${CERT_ALIAS}"
\retval=$?
\if [ $retval -ne 0 ]
\then
\  echo "fmsconf returned error '$retval'. Could not delete certificate for '${CERT_ALIAS}' from '${TRUSTSTORE}' at '${FMS_HOST}'."
\  Usage
\fi
\
\# Add the new cert
\echo "with new certificate and details as follows ..."
\echo
\keytool -printcert -file ${CERT_FILE} |head -8
\echo
\
\fmsconf -h ${FMS_HOST} -x "__FMS_Admin_AddCert ${TRUSTSTORE} ${TRUSTSTORE_TYPE} ${TRUSTSTORE_PW} ${CERT_ALIAS} ${CERTIFICATE}"
\retval=$?
\if [ $retval -ne 0 ]
\then
\  echo "fmsconf returned error '$retval'. Could not add certificate for '${CERT_ALIAS}' to '${TRUSTSTORE}' at '${FMS_HOST}'."
\  Usage
\fi
\
\      

Certificate updates may be scheduled using the at command and the above updateCert.sh script as per the following example on *nix systems

\
\echo "/home/fms/trigger/updateCert.sh '2019-06-11 09:55:00' /home/fms/flame.jks /path/to/NewCert.pem CERTALIAS localhost" | at '10:00 Jun 11'
\
\