#!/bin/bash
#< Script to generate HTML for JMX and Web console login pages (JBoss), and convert from BASIC auth to FORM auth

# Notes:
#   This script assumes that you're already using BASIC auth for the JMX and Web consoles.
#   Doesn't sanity check if FORM is already being used
# Requires:
#   GNU sed

BASENAME="/usr/bin/basename"
CP="/bin/cp"
DATE="/usr/bin/date"
ECHO="/usr/bin/echo"
EGREP="/bin/egrep"
ID="/usr/xpg4/bin/id"
MV="/bin/mv"
SED="/usr/local/bin/sed"
TOUCH="/usr/bin/touch"
TR="/usr/bin/tr"

THISPROG=$( ${BASENAME} $0 )

JBOSS_USER="jboss"
JBOSS_ROOT="/usr/local/jboss4"
JBOSS_SERVER_ROOT="${JBOSS_ROOT}/server"
BACKUP_DIR="/home/jboss/xml/backup"
TEMPLATE_DIR="/home/jboss/converter/lib"
LOGIN_TEMPLATE="${TEMPLATE_DIR}/login.html"
FAILED_TEMPLATE="${TEMPLATE_DIR}/failedlogin.html"
TMP_DIR="/home/jboss/converter/tmp"

FQDN=""
SERVER=""
TYPE=""
VERBOSE=0

function print_error {
   ${ECHO} "Error: $@" >&2
}

function printv {
   (( VERBOSE )) && {
      ${ECHO} "--> $@" >&2
   }
}

function print_usage {
   {
      ${ECHO} "Usage: ${THISPROG} [-hv] -f <fqdn> -s <server> -t <type>"
      ${ECHO} "       -f   JBoss servers FQDN"
      ${ECHO} "       -s   JBoss servers instance name"
      ${ECHO} "       -t   Login HTML type to generate"
      ${ECHO} "            Valid types:"
      ${ECHO} "            jmx   Generate login pages for JMX console"
      ${ECHO} "            web   Generate login pages for web console"
      ${ECHO} "       -h   Display this usage message"
      ${ECHO} "       -v   Verbose mode"
   } >&2
}

function check_user {
   CURRENT_USER=$( ${ID} -un )
   if [ "${CURRENT_USER}" != "${JBOSS_USER}" ]; then
      print_error "This script must be run as user ${JBOSS_USER}" && exit 1
   fi
}

function check_args {
   CHECK_THESE="FQDN SERVER TYPE"
   ERRORCOUNT=0
   for VARIABLE in ${CHECK_THESE}; do
      eval VALUE=\$${VARIABLE}
      if [ "${VALUE}" = "" ]; then
         print_error "${VARIABLE} must be specified"
	 (( ERRORCOUNT = ERRORCOUNT + 1 ))
      fi
   done
   (( ERRORCOUNT )) && exit 1
   ${ECHO} "${TYPE}" | ${EGREP} '^(jmx|web)$' >/dev/null 2>&1   
   if [ "$?" -ne "0" ]; then
      print_error "Invalid type specified. Type \"${THISPROG} -h\" to see valid types"
      exit 1
   fi
}

function check_valid_server {
   if [ ! -d "${JBOSS_SERVER_ROOT}/${SERVER}" ]; then
      print_error "${SERVER} is not a valid JBoss server instance"
      exit 1
   else
      JBOSS_SERVER="${JBOSS_SERVER_ROOT}/${SERVER}"
      JBOSS_DEPLOY="${JBOSS_SERVER}/deploy"
      JBOSS_MANAGEMENT="${JBOSS_DEPLOY}/management"
      JBOSS_CONSOLE_MGR="${JBOSS_MANAGEMENT}/console-mgr.sar"
      JBOSS_CONSOLE_MGR_META_INF="${JBOSS_CONSOLE_MGR}/META-INF"
      JBOSS_CONSOLE_MGR_JBOSS_SERVICE_XML="${JBOSS_CONSOLE_MGR_META_INF}/jboss-service.xml"
      JBOSS_WEB_CONSOLE="${JBOSS_CONSOLE_MGR}/web-console.war"
      JBOSS_WEB_CONSOLE_WEB_INF="${JBOSS_WEB_CONSOLE}/WEB-INF"
      JBOSS_WEB_CONSOLE_WEB_XML="${JBOSS_WEB_CONSOLE_WEB_INF}/web.xml"
      JBOSS_JMX_CONSOLE="${JBOSS_DEPLOY}/jmx-console.war"
      JBOSS_JMX_CONSOLE_WEB_INF="${JBOSS_JMX_CONSOLE}/WEB-INF"
      JBOSS_JMX_CONSOLE_WEB_XML="${JBOSS_JMX_CONSOLE_WEB_INF}/web.xml"
      # We won't check all these directories, the following should suffice
      if [ ! -f "${JBOSS_CONSOLE_MGR_JBOSS_SERVICE_XML}" ]; then
         print_error "${JBOSS_CONSOLE_MGR_JBOSS_SERVICE_XML} does not exist"
	 exit 1
      fi
      if [ ! -f "${JBOSS_WEB_CONSOLE_WEB_XML}" ]; then
         print_error "${JBOSS_WEB_CONSOLE_WEB_XML} does not exist"
	 exit 1
      fi
      if [ ! -f "${JBOSS_JMX_CONSOLE_WEB_XML}" ]; then
         print_error "${JBOSS_JMX_CONSOLE_WEB_XML} does not exist"
	 exit 1
      fi
      ### TEMP OVERRIDES !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
    # JBOSS_WEB_CONSOLE_WEB_XML="../tmp/web.xml-BASIC-WEB"  # !!
    # JBOSS_JMX_CONSOLE_WEB_XML="../tmp/web.xml-BASIC-JMX"  # !!
      ### END TEMP OVERRIDES !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
   fi
   case ${TYPE} in
     "jmx" )
             ${EGREP} "<auth-method>FORM<\/auth-method>" ${JBOSS_JMX_CONSOLE_WEB_XML} >/dev/null 2>&1
             if [ "$?" -eq "0" ]; then
                print_error "FORM auth already used for ${JBOSS_JMX_CONSOLE_WEB_XML##*/} (JMX)" && exit 1
             fi
             ;;
     "web" )
             ${EGREP} "<auth-method>FORM<\/auth-method>" ${JBOSS_WEB_CONSOLE_WEB_XML} >/dev/null 2>&1
             if [ "$?" -eq "0" ]; then
                print_error "FORM auth already used for ${JBOSS_WEB_CONSOLE_WEB_XML##*/} (WEB)" && exit 1
             fi
   esac
}

function check_backup_dir {
   if [ ! -d "${BACKUP_DIR}" ]; then
      print_error "Backup directory ${BACKUP_DIR} does not exist"
      exit 1
   fi
}

function check_templates {
   if [ ! -d "${TEMPLATE_DIR}" ]; then
      print_error "Template directory ${TEMPLATE_DIR} does not exist"
      exit 1
   else
      if [ ! -f "${LOGIN_TEMPLATE}" ]; then
         print_error "Login template ${LOGIN_TEMPLATE} does not exist"
  	 exit 1
      fi
      if [ ! -f "${FAILED_TEMPLATE}" ]; then
         print_error "Failed login template ${FAILED_TEMPLATE} does not exist"
  	 exit 1
      fi
   fi
}

function create_web_console_xml_backup {
   check_backup_dir
   BACKUP_FILENAME="${BACKUP_DIR}/${SERVER}_web_console_web_xml.$( ${DATE} +%Y%m%d_%H%M ).$$"
   printv "Creating backup of web.xml (WEB) as ${BACKUP_FILENAME}"
   ${CP} -p ${JBOSS_WEB_CONSOLE_WEB_XML} ${BACKUP_FILENAME}
}

function create_jmx_console_xml_backup {
   check_backup_dir
   BACKUP_FILENAME="${BACKUP_DIR}/${SERVER}_jmx_console_web_xml.$( ${DATE} +%Y%m%d_%H%M ).$$"
   printv "Creating backup of web.xml (JMX) as ${BACKUP_FILENAME}"
   ${CP} -p ${JBOSS_JMX_CONSOLE_WEB_XML} ${BACKUP_FILENAME}
}

function convert_web_console_xml {
   ${SED} '/<login-config>/,/<\/login-config>/ {
      s/^.*$/##REPLACEME##/
   }' ${JBOSS_WEB_CONSOLE_WEB_XML} |\
      ${SED} '$!N; /^\(.*\)\n\1$/!P; D' |\
      ${SED} '/##REPLACEME##/ { c \
      <login-config> \
         <auth-method>FORM<\/auth-method> \
         <form-login-config> \
            <form-login-page>\/login.html<\/form-login-page> \
            <form-error-page>\/failedlogin.html<\/form-error-page> \
         <\/form-login-config> \
      <\/login-config> 
   }' > ${JBOSS_WEB_CONSOLE_WEB_XML}.new
   printv "${JBOSS_WEB_CONSOLE_WEB_XML} modified to support FORM auth"
   ${MV} ${JBOSS_WEB_CONSOLE_WEB_XML}.new ${JBOSS_WEB_CONSOLE_WEB_XML}
}

function convert_jmx_console_xml {
   ${SED} '/<login-config>/,/<\/login-config>/ {
      s/^.*$/##REPLACEME##/
   }' ${JBOSS_JMX_CONSOLE_WEB_XML} |\
      ${SED} '$!N; /^\(.*\)\n\1$/!P; D' |\
      ${SED} '/##REPLACEME##/ { c \
      <login-config> \
         <auth-method>FORM<\/auth-method> \
         <form-login-config> \
            <form-login-page>\/login.html<\/form-login-page> \
            <form-error-page>\/failedlogin.html<\/form-error-page> \
         <\/form-login-config> \
      <\/login-config> 
   }' > ${JBOSS_JMX_CONSOLE_WEB_XML}.new
   printv "${JBOSS_JMX_CONSOLE_WEB_XML} modified to support FORM auth"
   ${MV} ${JBOSS_JMX_CONSOLE_WEB_XML}.new ${JBOSS_JMX_CONSOLE_WEB_XML}
}

function generate_web_html {
   for TEMPLATE_NAME in ${LOGIN_TEMPLATE} ${FAILED_TEMPLATE}; do
      TMP_FILE="${TMP_DIR}/${TEMPLATE_NAME##*/}_${HOSTNAME}_${SERVER}_${TYPE}"
      ${CP} -p ${TEMPLATE_NAME} ${TMP_FILE}
      UPPER_TYPE=$( ${ECHO} "${TYPE}" | ${TR} '[a-z]' '[A-Z]' )
      ${SED} "s/^\(.*<h2>\)[^<]*\(<\/.*\)$/\1WEB Console Login\2/" ${TMP_FILE} > ${TMP_FILE}.new
      ${MV} ${TMP_FILE}.new ${TMP_FILE}
      ${SED} "s/^\(.*<h3><i>\)[^<]*\(<\/.*\)$/\1${SERVER}@${FQDN}\2/" ${TMP_FILE} > ${TMP_FILE}.new
      ${MV} ${TMP_FILE}.new ${TMP_FILE}
      printv "Installing ${TMP_FILE} to ${JBOSS_WEB_CONSOLE}"
      ${CP} ${TMP_FILE} ${JBOSS_WEB_CONSOLE}/${TEMPLATE_NAME##*/}
   done
}

function generate_jmx_html {
   for TEMPLATE_NAME in ${LOGIN_TEMPLATE} ${FAILED_TEMPLATE}; do
      TMP_FILE="${TMP_DIR}/${TEMPLATE_NAME##*/}_${HOSTNAME}_${SERVER}_${TYPE}"
      ${CP} -p ${TEMPLATE_NAME} ${TMP_FILE}
      UPPER_TYPE=$( ${ECHO} "${TYPE}" | ${TR} '[a-z]' '[A-Z]' )
      ${SED} "s/^\(.*<h2>\)[^<]*\(<\/.*\)$/\1JMX Console Login\2/" ${TMP_FILE} > ${TMP_FILE}.new
      ${MV} ${TMP_FILE}.new ${TMP_FILE}
      ${SED} "s/^\(.*<h3><i>\)[^<]*\(<\/.*\)$/\1${SERVER}@${FQDN}\2/" ${TMP_FILE} > ${TMP_FILE}.new
      ${MV} ${TMP_FILE}.new ${TMP_FILE}
      printv "Installing ${TMP_FILE} to ${JBOSS_JMX_CONSOLE}"
      ${CP} ${TMP_FILE} ${JBOSS_JMX_CONSOLE}/${TEMPLATE_NAME##*/}
   done
}

function deploy_web_app {
   printv "Deploying Web Console application"
   ${TOUCH} ${JBOSS_CONSOLE_MGR_JBOSS_SERVICE_XML}
}

function deploy_jmx_app {
   # not strictly required as the cp would have deployed this
   printv "Deploying JMX Console application"
   ${TOUCH} ${JBOSS_JMX_CONSOLE_WEB_XML}
}

function convert_web {
   create_web_console_xml_backup
   convert_web_console_xml
   generate_web_html
   deploy_web_app
}

function convert_jmx {
   create_jmx_console_xml_backup
   convert_jmx_console_xml
   generate_jmx_html
   deploy_jmx_app
}

#
# main()
#
while getopts ":hf:s:t:v" OPTION; do
   case ${OPTION} in
      "h")  print_usage && exit 0   ;;
      "f")  FQDN=${OPTARG}          ;;
      "s")  SERVER=${OPTARG}       ;;
      "t")  TYPE=${OPTARG}          ;;
      "v")  VERBOSE=1               ;;
      *  )  print_usage && exit 1   ;;
   esac
done

shift $(( ${OPTIND} - 1 ))

if [ "$#" -ne "0" ]; then
   print_usage && exit 1
fi

check_user
check_args
check_valid_server
check_templates

case ${TYPE} in
   "jmx" )   convert_jmx ;;
   "web" )   convert_web ;;
esac

exit 0