#!/bin/bash ##### # ESG ORP # This script is intended to be an adjunct to the esg-node script # (author: gavin@llnl.gov) #**************************************************************************** #* * #* Organization: Lawrence Livermore National Lab (LLNL) * #* Directorate: Computation * #* Department: Computing Applications and Research * #* Division: S&T Global Security * #* Matrix: Atmospheric, Earth and Energy Division * #* Program: PCMDI * #* Project: Earth Systems Grid (ESG) Data Node Software Stack * #* First Author: Gavin M. Bell (gavin@llnl.gov) * #* * #**************************************************************************** #* * #* Copyright (c) 2009, Lawrence Livermore National Security, LLC. * #* Produced at the Lawrence Livermore National Laboratory * #* Written by: Gavin M. Bell (gavin@llnl.gov) * #* LLNL-CODE-420962 * #* * #* All rights reserved. This file is part of the: * #* Earth System Grid (ESG) Data Node Software Stack, Version 1.0 * #* * #* For details, see http://esg-repo.llnl.gov/esg-node/ * #* Please also read this link * #* http://esg-repo.llnl.gov/LICENSE * #* * #* * Redistribution and use in source and binary forms, with or * #* without modification, are permitted provided that the following * #* conditions are met: * #* * #* * Redistributions of source code must retain the above copyright * #* notice, this list of conditions and the disclaimer below. * #* * #* * Redistributions in binary form must reproduce the above copyright * #* notice, this list of conditions and the disclaimer (as noted below) * #* in the documentation and/or other materials provided with the * #* distribution. * #* * #* Neither the name of the LLNS/LLNL nor the names of its contributors * #* may be used to endorse or promote products derived from this * #* software without specific prior written permission. * #* * #* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * #* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * #* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * #* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL LAWRENCE * #* LIVERMORE NATIONAL SECURITY, LLC, THE U.S. DEPARTMENT OF ENERGY OR * #* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * #* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * #* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * #* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * #* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * #* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * #* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * #* SUCH DAMAGE. * #* * #**************************************************************************** ###### # Description: Installation of the esg ORP security infrastructure. This # file is meant to be sourced by the esg-node # script that has the definition of checked_get(), # stop_tomcat(), start_tomcat(), $workdir, esg_orp_version=${esg_orp_version:-"1.1.0"} #-------------- #User Defined / Setable (public) #-------------- esg_root_dir=${esg_root_dir:-${ESGF_HOME:-"/esg"}} install_prefix=${install_prefix:-"/usr/local"} workdir=${workdir:-~/workbench/esg} install_manifest=${install_manifest:-"${esg_root_dir}/esgf-install-manifest"} #-------------- date_format=${date_format:-"+%Y_%m_%d_%H%M%S"} force_install=${force_install:-0} init() { orp_dist_url="${esg_dist_url}/esg-orp/esg-orp.war" orp_property_file_dist_url="${esg_dist_url}/esg-orp/esg-orp.properties" orp_context_root="esg-orp" orp_service_app_home="${CATALINA_HOME}/webapps/${orp_context_root}" orp_service_endpoint=$(echo "https://${esgf_host}$( if ((esgf_https_port != 443)); then echo "${port}"; fi)/${orp_service_app_home##*/}/html.htm") #------------------------------------------ #Security services associated with ORP #------------------------------------------ orp_security_authorization_service_host=${orp_security_authorization_service_host:-${esgf_host:-$(hostname --fqdn)}} orp_security_authorization_service_port=${orp_security_authorization_service_port:-"443"} orp_security_authorization_service_app_home=${orp_service_app_home} orp_security_authorization_service_endpoint=$(echo "https://${orp_security_authorization_service_host}$( if ((orp_security_authorization_service_port != 443)); then echo ":${orp_security_authorization_service_port}"; fi)/esg-orp/saml/soap/secure/authorizationService.htm") #------------------------------------------ } #arg (1) - install = 0 [default] # upgrade = 1 setup_orp() { init echo -n "Checking for Openid Relying Party ${esg_orp_version}" check_webapp_version "esg-orp" ${esg_orp_version} local ret=$? ((ret == 0)) && (( ! force_install )) && echo " [OK]" && return 0 echo echo "*******************************" echo "Setting up The OpenID Relying Party..." echo "*******************************" echo local upgrade=${1:-0} local default="Y" ((force_install)) && default="N" local dosetup if [ -d ${orp_service_app_home} ]; then echo "Detected an existing openid relying party installation..." read -p "Do you want to continue with openid relying party installation and setup? $([ "$default" = "N" ] && echo "[y/N]" || echo "[Y/n]") " dosetup [ -z "${dosetup}" ] && dosetup=${default} if [ "${dosetup}" != "Y" ] && [ "${dosetup}" != "y" ]; then echo "Skipping node openid relying party installation and setup - will assume it's setup properly" return 0 fi local dobackup="Y" read -p "Do you want to make a back up of the existing distribution?? [Y/n] " dobackup [ -z "${dobackup}" ] && dobackup=${default} if [ "${dobackup}" = "Y" ] || [ "${dobackup}" = "y" ]; then echo "Creating a backup archive of this web application $orp_service_app_home" backup ${orp_service_app_home} fi echo fi mkdir -p $workdir [ $? != 0 ] && return 1 pushd $workdir >& /dev/null #collect the necessary resources... local orp_dist_file=${orp_dist_url##*/} checked_get ${orp_dist_file} ${orp_dist_url} local no_new_update=$? #set to the absolute file name... orp_dist_file=$(readlink -f ${orp_dist_file}) if((upgrade)); then get_orp_support_libs ${orp_service_app_home}/WEB-INF/lib if (($? > 0)); then echo "Upgrading in light of newly fetched libs!!" else ((no_new_update == 1)) && echo "nothing more to do, you are up2date" && return 0 echo "Upgrading the OpenID Relying Party WebApp..." fi fi stop_tomcat #---------------------------- local fetch_file=${orp_property_file_dist_url##*/} checked_get ${fetch_file} ${orp_property_file_dist_url} #NOTE: The saving of the last config file must be done *BEFORE* we untar the new distro! if ((upgrade)) && [ -e WEB-INF/classes/${fetch_file} ]; then cp WEB-INF/classes/${fetch_file} WEB-INF/classes/${fetch_file}.saved chmod 600 WEB-INF/classes/${fetch_file}* fi #---------------------------- #make room for new INSTALL ((upgrade == 0)) && set_aside_web_app ${orp_service_app_home} #---------------------------- mkdir -p ${orp_service_app_home} [ $? != 0 ] && return 1 cd ${orp_service_app_home} echo "Expanding war ${orp_dist_file} in $(pwd)" $JAVA_HOME/bin/jar xf ${orp_dist_file} local _ret=$? ((upgrade == 0)) && set_aside_web_app_cleanup ${orp_service_app_home} ${_ret} unset _ret #---------------------------- #Migration update cleanup #---------------------------- [ -d "${tomcat_install_dir}/webapps/OpenidRelyingParty" ] && \ backup "${tomcat_install_dir}/webapps/OpenidRelyingParty" && \ rm -rf "${tomcat_install_dir}/webapps/OpenidRelyingParty" && \ remove_install_log_entry OpenidRelyingParty && \ echo "Removed old ORP [OK]" [ -f "${tomcat_install_dir}/webapps/thredds/WEB-INF/web.xml" ] && \ sed -i 's/OpenidRelyingParty/esg-orp/g' "${tomcat_install_dir}/webapps/thredds/WEB-INF/web.xml" && \ echo "updated thredds' web.xml accordingly [OK]" #---------------------------- #Property file fetching and token replacement... #---------------------------- pushd WEB-INF/classes >& /dev/null cp ${fetch_file} ${fetch_file}.tmpl if((upgrade)) && [ -e ${fetch_file}.saved ]; then #reuse the last properties file... #pull it out of the tar archive we made a few lines up cp ${fetch_file}.saved ${fetch_file} else orp_startup_hook $(readlink -f ${fetch_file}) fi chown -R ${tomcat_user} ${orp_service_app_home} chgrp -R ${tomcat_group} ${orp_service_app_home} unset fetch_file popd >& /dev/null #---------------------------- popd >& /dev/null echo setup_providers_dropdown get_orp_support_libs ${orp_service_app_home}/WEB-INF/lib write_orp_install_log start_tomcat return 0 } setup_providers_dropdown() { # Do additional setup to configure CEDA-provided ORP with a dropdown list of IDPs known_providers_url="${esg_dist_url}/lists/esgf_known_providers.xml" config_dir=${esg_root_dir}/config known_providers_file=${config_dir}/esgf_known_providers.xml # add /esg/config/ to common.loader in catalina.properties if not already present perl -p -i -e "s@^(common\.loader=.*)\$@\1,$config_dir@ unless m{$config_dir}" ${tomcat_install_dir}/conf/catalina.properties # install known providers file (fetch template file and substitute local IDP) checked_get ${known_providers_file} ${known_providers_url} $((force_install)) # and add orp.provider.list line in esgf.properties config_file=$config_dir/esgf.properties echo "orp.provider.list=${known_providers_file}" >> ${config_file} dedup_properties ${config_file} chown ${tomcat_user}:${tomcat_group} ${config_file} } # Takes the destination directory you wish to have supported libs checked and downloaded to # returns the number of files downloaded (in this case max of 2) # 0 if there was no update of libs necessary get_orp_support_libs() { local dest_dir=${1} local ret=0 if [ -d ${dest_dir} ]; then #---------------------------- #Fetching Dependent Security Jars from Distribution Site... #---------------------------- #version values inherited from esg-node calling script #----- #esgf project generated jarfiles... local esgf_security_jar=esgf-security-${esgf_security_version}.jar local esgf_security_test_jar=esgf-security-test-${esgf_security_version}.jar #----- echo "getting (downloading) dependent library jars from ESGF Distribution Server (Security) to ${dest_dir} ..." local make_backup_file=0 #Do NOT make backup file checked_get ${dest_dir}/${esgf_security_jar} ${esg_dist_url}/esgf-security/${esgf_security_jar} $((force_install)) $((make_backup_file)) (( $? == 0 )) && ((ret++)) && write_security_lib_install_log #yes, I did indeed fetch something new checked_get ${dest_dir}/${esgf_security_test_jar} ${esg_dist_url}/esgf-security/${esgf_security_jar} $((force_install)) $((make_backup_file)) (( $? == 0 )) && ((ret++)) #yes, I did indeed fetch something new #remove all other node manager jars that are not what we want echo "cleaning up (removing) other, unnecessary, orp/security project jars from ${dest_dir} ..." rm -vf $(/bin/ls ${dest_dir}/${esgf_security_jar%-*}-*.jar | grep -v ${esgf_security_version}) rm -vf $(/bin/ls ${dest_dir}/${esgf_security_test_jar%-*}-*.jar | grep -v ${esgf_security_version}) #--- chown -R ${tomcat_user}:${tomcat_group} ${dest_dir} fi return ${ret} } write_orp_install_log() { local esg_orp_version=${esg_orp_version} [ -z "${esg_orp_version}" ] && \ esg_orp_version=$(sed -n '/^Version:[ ]*\(.*\)$/p' ${orp_service_app_home}/META-INF/MANIFEST.MF | awk '{print $2}' | tr -d "\015") echo "$(date ${date_format}) webapp:esg-orp=${esg_orp_version} ${orp_service_app_home}" >> ${install_manifest} dedup ${install_manifest} get_property esgf_https_port [ -n "${esgf_https_port}" ] && local port=":${esgf_https_port}" write_as_property orp_service_endpoint ${orp_service_endpoint} write_as_property orp_service_app_home ${orp_service_app_home} write_as_property orp_security_authorization_service_endpoint write_as_property orp_security_authorization_service_app_home return 0 } #NOTE: an identical implementation exists in the IDP installer... #(this should ideally only exist in one place i.e. a source "functions" file) write_security_lib_install_log() { [ -z "${esgf_security_version}" ] && echo "WARNING: [idp] Could not write install log entry for security library" && return 1 local last_recorded_version=$(sed -n 's/.*esgf-security=\(.[^ ]*\).*/\1/p' ${install_manifest}) [ -n "${last_recorded_version}" ] && [ "${last_recorded_version}" = "${esgf_security_version}" ] && echo "(security install log entry already present) [OK]" && return 0 echo "$(date ${date_format}) esgf->library:esgf-security=${esgf_security_version} " >> ${install_manifest} dedup ${install_manifest} return 0 } #-------------------------------------- # Callout function from esg-node #-------------------------------------- #This function is called by esg-node before starting tomcat! #This is how we make sure we are always using the proper credentials. orp_startup_hook() { init #---------------------- #edit the property file... #NOTE: I really don't like the global scoping of the admin password... but... hmm... echo -n "ORP Startup Hook: Syncing Credential Tokens... " local target_properties_file=${1:-"${orp_service_app_home}/WEB-INF/classes/esg-orp.properties"} [ -e "${target_properties_file}" ] && cp ${target_properties_file} ${target_properties_file}.bak local keystore_file=$(sed -n 's#.*keystoreFile[ ]*=[ ]*"\([^ "]*\)".*$#\1#p' ${tomcat_install_dir}/conf/server.xml) && echo -n "O" || echo -n "x" local keystore_pass=$(sed -n 's#.*keystorePass[ ]*=[ ]*"\([^ "]*\)".*$#\1#p' ${tomcat_install_dir}/conf/server.xml) && echo -n "o" || echo -n "x" local keystore_alias=$(sed -n 's#.*keyAlias[ ]*=[ ]*"\([^ "]*\)".*$#\1#p' ${tomcat_install_dir}/conf/server.xml) && echo -n "." || echo -n "x" sed -i 's#^[ ]*\(keystoreFile=\).*$#\1'${keystore_file}'#' ${target_properties_file} && echo -n ":" || echo -n "8" sed -i 's#^[ ]*\(keystorePassword=\).*$#\1'${keystore_pass}'#' ${target_properties_file} && echo -n "-" || echo -n "." sed -i 's#^[ ]*\(keystoreAlias=\).*$#\1'${keystore_alias:-"tomcat"}'#' ${target_properties_file} && echo -n ")" || echo -n "(" echo #---------------------- } #-------------------------------------- # Clean / Uninstall this module... #-------------------------------------- clean_orp_webapp_subsystem() { init local doit="N" if [ -e ${orp_service_app_home} ]; then read -p "remove ESGF ORP web service? (${orp_service_app_home}) [y/N]: " doit if [ "doit" = "Y" ] || [ "$doit" = "y" ]; then echo "removing ${orp_service_app_home}" if [ -n ${orp_service_app_home} ]; then rm -rf ${orp_service_app_home} [ $? != 0 ] && echo "ERROR: Unable to remove ${orp_service_app_home}" && return 1 perl -n -i -e'print unless m!webapp:esg-orp!' ${install_manifest} fi fi fi if [ ! -e ${orp_service_app_home} ]; then debug_print "removing orp associated properties..." remove_property orp_service_app_home remove_property orp_service_endpoint remove_property orp_security_authorization_service_app_home remove_property orp_security_authorization_service_endpoint fi return 0 } #-------------------------------------- # Misc utility functions #-------------------------------------- fetch_static_ats_file() { local fetch_file=esgf_ats_static.xml local force=1 local make_backup=1 checked_get ${esg_config_dir}/${fetch_file} ${esg_dist_url}/lists/${fetch_file} ${force} ${make_backup} (( $? > 1 )) && [FAIL] && return 2 chown ${tomcat_user}:${tomcat_group} ${esg_config_dir}/${fetch_file} [OK] } fetch_known_providers_file() { local fetch_file=esgf_known_providers.xml local force=1 local make_backup=1 checked_get ${esg_config_dir}/${fetch_file} ${esg_dist_url}/lists/${fetch_file} ${force} ${make_backup} (( $? > 1 )) && [FAIL] && return 2 chown ${tomcat_user}:${tomcat_group} ${esg_config_dir}/${fetch_file} [OK] } fetch_static_idp_file() { local fetch_file=esgf_idp_static.xml local force=1 local make_backup=1 checked_get ${esg_config_dir}/${fetch_file} ${esg_dist_url}/lists/${fetch_file} ${force} ${make_backup} (( $? > 1 )) && [FAIL] && return 2 [OK] }