From 53bf3014cab5161b6e229dba62c0f303848b4a5b Mon Sep 17 00:00:00 2001 From: Christoph Date: Thu, 13 Mar 2025 13:59:32 +0100 Subject: [PATCH] Add script 'check_cert_for_keycloak.sh' and sample configuration file. --- .gitignore | 2 +- check_cert_for_keycloak.sh | 426 +++++++++++++++++++++++ conf/check_cert_for_keycloak.conf.sample | 123 +++++++ 3 files changed, 550 insertions(+), 1 deletion(-) create mode 100755 check_cert_for_keycloak.sh create mode 100644 conf/check_cert_for_keycloak.conf.sample diff --git a/.gitignore b/.gitignore index 12b01d2..8356ed2 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,4 @@ *.swp /conf/*.conf -/conf/*.conf.* +/conf/*.conf /BAK/* diff --git a/check_cert_for_keycloak.sh b/check_cert_for_keycloak.sh new file mode 100755 index 0000000..7d5c85b --- /dev/null +++ b/check_cert_for_keycloak.sh @@ -0,0 +1,426 @@ +#!/usr/bin/env bash + +# =============================================================== +# - Don't make definitions here! Do this at the configuration file +# ================================================================ + +script_name="$(basename $(realpath $0))" +working_dir="$(dirname $(realpath $0))" + +conf_file="${working_dir}/conf/${script_name%%.*}.conf" + +# ---------- +# - +# - Script checks, whether the certificate for mumble services are up to date. If +# - newer versions than the installed one found, script changes the installed +# - key/cert to the latest version. +# - +# - Note !! +# - This script is very special to the server environment of machine 'o13-il.oopen.de' +# - +# ---------- + +LOCK_DIR="/tmp/${script_name%%.*}.LOCK" +log_file="${LOCK_DIR}/${script_name%%.*}.log" + +restart_service=false + + +# ------------- +# --- Some functions +# ------------- + +clean_up() { + + # Perform program exit housekeeping + rm -rf "$LOCK_DIR" + exit $1 +} + +echononl(){ + if $terminal ; then + echo X\\c > /tmp/shprompt$$ + if [ `wc -c /tmp/shprompt$$ | awk '{print $1}'` -eq 1 ]; then + echo -e -n "$*\\c" 1>&2 + else + echo -e -n "$*" 1>&2 + fi + rm /tmp/shprompt$$ + fi +} + +fatal(){ + echo "" + if $terminal ; then + echo -e " [ \033[31m\033[1mFatal\033[m ]: $*" + echo "" + echo -e " \033[31m\033[1mScript was interupted\033[m!" + else + echo " [ Fatal ]: $*" + echo "" + echo " Script was terminated...." + fi + echo "" + clean_up 1 +} + +error() { + echo "" + if $terminal ; then + echo -e " [ \033[31m\033[1mError\033[m ]: $*" + else + echo " [ Error ]: $*" + fi + echo "" +} + +warn() { + echo "" + if $terminal ; then + echo -e " [ \033[33m\033[1mWarning\033[m ]: $*" + else + echo " [ Warning ]: $*" + fi + echo "" +} + +info() { + if $terminal ; then + echo "" + echo -e " [ \033[32m\033[1mInfo\033[m ]: $*" + echo "" + fi +} + +echo_failed(){ + if $terminal ; then + echo -e "\033[75G[ \033[1;31mfailed\033[m ]" + fi +} + +echo_skipped() { + if $terminal ; then + echo -e "\033[75G[ \033[33m\033[1mskipped\033[m ]" + fi +} + + +echo_done() { + if $terminal ; then + echo -e "\033[75G[ \033[32mok\033[m ]" + fi +} + +blank_line() { + if $terminal ; then + echo "" + fi +} + + +# ------------- +# - Job is already running? +# ------------- + +# - If job already runs, stop execution.. +# - +if mkdir "$LOCK_DIR" 2> /dev/null ; then + + # - Remove lockdir when the script finishes, or when it receives a signal + # - + trap clean_up SIGHUP SIGINT SIGTERM + +else + + msg="A previos instance of script \"`basename $0`\" seems already be running." + + echo "" + if $terminal ; then + echo -e "[ \033[31m\033[1mFatal\033[m ]: $msg" + echo "" + echo -e " \033[31m\033[1mScript was interupted\033[m!" + else + echo " [ Fatal ]: $msg" + echo "" + echo " Script was interupted!" + fi + echo + + exit 1 + +fi + + +# ------------- +# --- Some checks +# ------------- + +# - Running in a terminal? +# - +if [[ -t 1 ]] ; then + terminal=true +else + terminal=false +fi + + +# - Read Configurations from $conf_file +# - +if [[ ! -f "$conf_file" ]]; then + fatal " Configuration file '$(basename ${conf_file})' not found!" +else + source $conf_file +fi + +[[ -z "$service_domain" ]] && fatal " Parameter 'service_domain' not set but is reqired!" + +[[ -z "$cert_installed" ]] && cert_installed="/opt/keycloak/certs/${service_domain}.crt" +[[ -z "$cert_newest" ]] && cert_newest="/var/lib/dehydrated/certs/${service_domain}/fullchain.pem" +[[ -z "$key_installed" ]] && key_installed="/opt/keycloak/certs/${service_domain}.key" +[[ -z "$key_newest" ]] && key_newest="/var/lib/dehydrated/certs/${service_domain}/privkey.pem" + +[[ -z "$service_name" ]] && service_name="Keycloak" +[[ -z "$check_string_ps" ]] && check_string_ps="[[:digit:]]\ lua[[:digit:]].[[:digit:]] /usr/bin/prosody" +[[ -z "$service_user" ]] && service_user="keycloak" +[[ -z "$service_group" ]] && service_group="keycloak" + +# - Systemd supported ? +# - +systemd_supported=false +systemd=$(which systemd) +systemctl=$(which systemctl) + +if [[ -n "$systemd" ]] && [[ -n "$systemctl" ]] ; then + systemd_supported=true +fi + +SYSTEMD_SERVICE= + +if systemctl -t service list-unit-files \ + | grep -e "^${service_name,,}d" \ + | grep -q -E "(enabled|disabled|generated)" 2> /devnull ; then + + SYSTEMD_SERVICE="$(systemctl -t service list-unit-files | grep -e "^${service_name,,}d" | awk '{print$1}' | head -1)" +elif systemctl -t service list-unit-files \ + | grep -e "^${service_name,,}-server" \ + | grep -q -E "(enabled|disabled|generated)" 2> /devnull ; then + + SYSTEMD_SERVICE="$(systemctl -t service list-unit-files | grep -e "^${service_name,,}-server" | awk '{print$1}' | head -1)" +elif systemctl -t service list-unit-files \ + | grep -e "^${service_name,,}" \ + | grep -q -E "(enabled|disabled|generated)" 2> /devnull ; then + + SYSTEMD_SERVICE="$(systemctl -t service list-unit-files | grep -e "^${service_name,,}" | awk '{print$1}' | head -1)" +fi + + +if [[ -z "$SYSTEMD_SERVICE" ]] ; then + fatal "No service file for $service_name found!" +fi + + +# ------------- +# - Don't run script, if any give path for cert/key does not exists +# ------------- + +if [[ ! -f "$cert_newest" ]] ; then + fatal "Newest Certificate '$cert_newest' for service '${service_name}' not found!" +elif [[ ! -f "$key_newest" ]] ; then + fatal "Newest Key '$key_newest' for service '${service_name}' not found!" +fi + +blank_line +echononl " Create Cert/Key Directory '$(dirname "$cert_installed")'.." +if [[ ! -d "$(dirname "$cert_installed")" ]] ; then + mkdir -p "$(dirname "$cert_installed")" > $log_file 2>&1 + if [[ $? -eq 0 ]] ; then + echo_done + + echononl " Change Permissions for Cert/Key Directory '$(dirname "$cert_installed")'.." + chmod 755 "$(dirname "$cert_installed")" > $log_file 2>&1 + if [[ $? -eq 0 ]] ; then + echo_done + else + echo_failed + error "$(cat "$log_file")" + fi + + else + echo_failed + error "$(cat "$log_file")" + fi +else + echo_skipped +fi + + +# ------------- +# - Check if key/cert are up to date, change them if needed. +# ------------- + +if ! diff "$(realpath "$cert_installed")" "$(realpath "$cert_newest")" > /dev/null 2>&1 ; then + + _failed=false + + warn "Certificate for service '${service_name}' is outdated! + + Try to update certificate and key.." + + echononl " Update certificat for for service '${service_name}' .." + > $log_file + if [[ -h "$cert_installed" ]] ; then + if [[ "$(dirname "$cert_installed")" = "$(dirname "$(realpath "$cert_installed")")" ]]; then + rm "$(realpath "$cert_installed")" >> $log_file 2>&1 + if [[ $? -ne 0 ]]; then + _failed=true + fi + fi + fi + + rm -f "$cert_installed" >> $log_file 2>&1 + if [[ $? -ne 0 ]]; then + _failed=true + fi + + cp -a "$(realpath "$cert_newest")" "$(dirname "$cert_installed")" >> $log_file 2>&1 + if [[ $? -ne 0 ]]; then + _failed=true + fi + + chown ${service_user}:$service_group "$(dirname "$cert_installed")/$(basename "$(realpath "$cert_newest")")" >> $log_file 2>&1 + if [[ $? -ne 0 ]]; then + _failed=true + fi + + ln -s "$(basename "$(realpath "$cert_newest")")" "$cert_installed" >> $log_file 2>&1 + if [[ $? -ne 0 ]]; then + _failed=true + fi + + if $_failed ; then + echo_failed + error "$(cat "$log_file")" + else + echo_done + fi + + if ! $_failed ; then + + _failed=false + + echononl " Update key for service '${service_name}' .." + if [[ -h "$key_installed" ]] ; then + if [[ "$(dirname "$key_installed")" = "$(dirname "$(realpath "$key_installed")")" ]]; then + rm "$(realpath "$key_installed")" >> $log_file 2>&1 + if [[ $? -ne 0 ]]; then + _failed=true + fi + fi + fi + + rm -f "$key_installed" > $log_file 2>&1 + if [[ $? -ne 0 ]]; then + _failed=true + fi + + cp -a "$(realpath "$key_newest")" "$(dirname "$key_installed")" >> $log_file 2>&1 + if [[ $? -ne 0 ]]; then + _failed=true + fi + + chown ${service_user}:$service_group "$(dirname "$key_installed")/$(basename "$(realpath "$key_newest")")" >> $log_file 2>&1 + if [[ $? -ne 0 ]]; then + _failed=true + fi + + ln -s "$(basename "$(realpath "$key_newest")")" "$key_installed" >> $log_file 2>&1 + if [[ $? -ne 0 ]]; then + _failed=true + fi + + if $_failed ; then + echo_failed + error "$(cat "$log_file")" + else + echo_done + restart_service=true + fi + + fi + + if ! $_failed ; then + if $terminal ; then + info "Certificate/Key for service '${service_name}' is now up to date" + else + echo "" + echo " [ Info ]: Certificate/Key for service '${service_name}' is now up to date" + echo "" + fi + else + error "Updating Certificate/Key for service '${service_name}' failed!" + fi + +else + up_to_date=true + info "Certificate for service '${service_name}' is up to date!" +fi + +if $restart_service ; then + + _failed=false + echononl "Going to restart Service '${service_name}' .." + $systemctl daemon-reload > $log_file 2>&1 + if [[ $? -ne 0 ]]; then + _failed=true + fi + sleep 2 + + $systemctl stop $SYSTEMD_SERVICE >> $log_file 2>&1 + if [[ $? -ne 0 ]]; then + _failed=true + fi + sleep 10 + + $systemctl start $SYSTEMD_SERVICE >> $log_file 2>&1 + if [[ $? -ne 0 ]]; then + _failed=true + fi + if $_failed ; then + echo_failed + error "$($log_file)" + else + echo_done + fi + + if ! $_failed ; then + + _failed=false + declare -i counter=0 + while ! $(systemctl is-active --quiet ${SYSTEMD_SERVICE}) ; do + if [[ $counter -gt 10 ]]; then + _failed=true + break + else + ((counter++)) + fi + sleep 1 + done + + fi + + if $_failed ; then + error "Restarting service '${service_name}' failed!" + else + if $terminal ; then + info "'${service_name}' Service was restarted. the new pid is '$PID'." + else + echo "" + echo " '${service_name}' Service was restarted. the new pid is '$PID'." + echo "" + fi + fi + +fi + +clean_up 0 + diff --git a/conf/check_cert_for_keycloak.conf.sample b/conf/check_cert_for_keycloak.conf.sample new file mode 100644 index 0000000..9a0c1f3 --- /dev/null +++ b/conf/check_cert_for_keycloak.conf.sample @@ -0,0 +1,123 @@ +# ---------------------------------------------- +# Settings for script check_cert_for_keycloak.sh +# ---------------------------------------------- + +# - service_domain +# - +#service_domain="" + + +# - service_name +# - +# - Name of service. +# - +# - Note: this var will also be used to determin systemd service file +# - or sysVinit script. +# - +# - Example: +# - service_name="Mumble" +# - service_name="Prosody" +# - +# - Defaults to: +# - service_name="Prosody" +# - +#service_name="" + + +# - check_string_ps +# - +# - String wich (clearly) identifies the service at the process list (ps) +# - +# - Example: +# - check_string_ps="[[:digit:]]\ /usr/sbin/murmurd" +# - check_string_ps="" +# - +# - Defaults to: +# - check_string_ps="[[:digit:]]\ lua[[:digit:]].[[:digit:]] /usr/bin/prosody" +# - +#check_string_ps="" + + +# - service_user +# - +# - User under which the service is running. +# - +# - Example: +# - service_user="mumble-server" +# - service_user="prosody" +# - +# - Defaults to: +# - service_user="prosody" +# - +#service_user="" + + +# - service_group +# - +# - Group under which the service is running. +# - +# - Example: +# - service_group="mumble-server" +# - service_group="prosody" +# - +# - Defaults to: +# - service_group="prosody" +# - +#service_group="" + + +# - cert_installed +# - +# - Locataion of certificate read by service +# - +# - Example: +# - cert_installed="/var/lib/mumble-server/fullchain.pem" +# - cert_installed="/var/lib/dehydrated/certs/jabber.so36.net/fullchain.pem" +# - +# - Defaults to: +# - /etc/prosody/certs/${service_domain}.crt +# - +#cert_installed="" + + +# - key_installed +# - +# - Location of the key read by service +# - +# - Example: +# - key_installed="/var/lib/mumble-server/privkey.pem" +# - key_installed="/etc/prosody/certs/privkey_jabber.so36.pem" +# - +# - Defaults to: +# - /etc/prosody/certs/${service_domain}.key +# - +#key_installed="" + + +# - cert_newest +# - +# - Location of the newest certificate. +# - +# - Example: +# - cert_newest="/var/lib/dehydrated/certs/il-mumble.oopen.de/fullchain.pem" +# - cert_newest="/var/lib/dehydrated/certs/jabber.so36.net/fullchain.pem" +# - +# - Defaults to: +# - /var/lib/dehydrated/certs/${service_domain}/fullchain.pem +# - +#cert_newest="" + + +# - key_newest +# - +# - Location of the newest Key +# - +# - Example: +# - key_newest="/var/lib/dehydrated/certs/il-mumble.oopen.de/privkey.pem" +# - key_newest="/var/lib/dehydrated/certs/jabber.so36.net/privkey.pem" +# - +# - Defaults to: +# - /var/lib/dehydrated/certs/${service_domain}/privkey.pem +# - +#key_newest="" +