Skip to content
Permalink
master
Switch branches/tags

Name already in use

A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
Go to file
 
 
Cannot retrieve contributors at this time
executable file 391 lines (325 sloc) 10.9 KB
#!/bin/bash
#######################################################################
# Copyright 2017 Internet2
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#######################################################################
#######################################################################
# Help message
#######################################################################
display_help () {
/bin/cat <<- HELP_MSG
This script applies an arbitrary sequence of XSLT scripts
against a SAML metadata aggregate. The output files will
be written to the output directory specified on the
command line.
The script depends on cached metadata. It will not fetch
a metadata file from the server.
Usage: ${0##*/} [-hv] -u MD_LOCATION -d OUT_DIR ["XSL_FILENAME [OUTPUT_FILENAME]" ...]
The script takes an arbitrary sequence of compound command-line
arguments. The second sub-argument of each compound argument is
OPTIONAL. If no OUTPUT_FILENAME is given for a particular
XSL_FILENAME, the script computes an output filename as best
it can. If there are no command-line arguments, the script takes
its input from stdin.
Options:
-h Display this help message
-v Enable DEBUG mode
-u Specify the metadata location
-d Specify the output directory
Option -h is mutually exclusive of all other options.
Option -u specifies the location of the metadata file on the
network. The script uses the location to retrieve the file
from cache. If the file is not cached, the script will fail.
This option is REQUIRED.
Option -d specifies the ultimate output directory, which is
usually a web directory. This option is REQUIRED.
Output is all or none. The output files are computed
sequentially and assembled one-by-one in a temporary
directory. All of the output files are moved to the
destination directory at the same time. If even one output
file can not be computed---for whatever reason---none are
written to the output directory.
ENVIRONMENT
This script leverages a handful of environment variables:
LIB_DIR A source library directory
CACHE_DIR A persistent HTTP cache
TMPDIR A temporary directory
LOG_FILE A persistent log file
LOG_LEVEL The global log level [0..5]
All of the above environment variables are REQUIRED
except LOG_LEVEL, which defaults to LOG_LEVEL=3.
The following environment variables are REQUIRED:
$( printf " %s\n" ${env_vars[*]} )
The following directories MUST exist:
$( printf " %s\n" ${dir_paths[*]} )
The following files MUST exist:
$( printf " %s\n" $LOG_FILE )
CONFIGURATION
The following source library files MUST be installed in LIB_DIR:
$( printf " %s\n" ${lib_filenames[*]} )
EXAMPLES
\$ ${0##*/} -h
\$ md_location=http://md.incommon.org/InCommon/InCommon-metadata-export.xml
\$ out_dir=/home/htdocs/www.incommonfederation.org/federation/metadata/
\$ ${0##*/} -u \$md_location -d \$out_dir \\
"list_all_IdPs_csv.xsl all_IdPs_exported.csv" \\
"list_all_SPs_csv.xsl all_SPs_exported.csv"
HELP_MSG
}
#######################################################################
# Bootstrap
#######################################################################
script_name=${0##*/} # equivalent to basename $0
# required environment variables
env_vars[1]="LIB_DIR"
env_vars[2]="CACHE_DIR"
env_vars[3]="TMPDIR"
env_vars[4]="LOG_FILE"
# check environment variables
for env_var in ${env_vars[*]}; do
eval "env_var_val=\${$env_var}"
if [ -z "$env_var_val" ]; then
echo "ERROR: $script_name requires env var $env_var" >&2
exit 2
fi
done
# required directories
dir_paths[1]="$LIB_DIR"
dir_paths[2]="$CACHE_DIR"
dir_paths[3]="$TMPDIR"
# check required directories
for dir_path in ${dir_paths[*]}; do
if [ ! -d "$dir_path" ]; then
echo "ERROR: $script_name: directory does not exist: $dir_path" >&2
exit 2
fi
done
# check the log file
# devices such as /dev/tty and /dev/null are allowed
if [ ! -f "$LOG_FILE" ] && [[ $LOG_FILE != /dev/* ]]; then
echo "ERROR: $script_name: file does not exist: $LOG_FILE" >&2
exit 2
fi
# default to INFO logging
if [ -z "$LOG_LEVEL" ]; then
LOG_LEVEL=3
fi
# library filenames
lib_filenames[1]="core_lib.sh"
lib_filenames[2]="http_tools.sh"
# check lib files
for lib_filename in ${lib_filenames[*]}; do
lib_file="$LIB_DIR/$lib_filename"
if [ ! -f "$lib_file" ]; then
echo "ERROR: $script_name: lib file does not exist: $lib_file" >&2
exit 2
fi
done
#######################################################################
# Process command-line options and arguments
#######################################################################
help_mode=false; local_opts=
while getopts ":hvu:d:" opt; do
case $opt in
h)
help_mode=true
;;
v)
LOG_LEVEL=4
local_opts="$local_opts -$opt"
;;
u)
md_location="$OPTARG"
;;
d)
out_dir="$OPTARG"
;;
\?)
echo "ERROR: $script_name: Unrecognized option: -$OPTARG" >&2
exit 2
;;
:)
echo "ERROR: $script_name: Option -$OPTARG requires an argument" >&2
exit 2
;;
esac
done
if $help_mode; then
display_help
exit 0
fi
# check the metadata location
if [ -z "$md_location" ]; then
echo "ERROR: $script_name: no metadata location specified (option -u)" >&2
exit 2
fi
# check the output directory
if [ -z "$out_dir" ]; then
echo "ERROR: $script_name: no output directory specified (option -d)" >&2
exit 2
fi
if [ ! -d "$out_dir" ]; then
echo "ERROR: $script_name: directory does not exist: $out_dir" >&2
exit 2
fi
#######################################################################
# Functions
#######################################################################
# process a compound command-line argument
#
# present a pair of arguments to this function:
# XSL_FILENAME [OUTPUT_FILENAME]
# if the latter is omitted, the function computes an output
# filename according to the following algorithm:
#
# if the XSL filename is of the form
# base_filename_csv.xsl
# or
# base_filename_json.xsl
# then construct the output filename with the indicated extension:
# base_filename.csv
# or
# base_filename.json
# otherwise the output filename is the XSL filename sans the .xsl extension
process_arg () {
local xsl_file
local base_filename
local output_filename
# check the command-line arguments
if [ $# -lt 1 -o $# -gt 2 ]; then
echo "ERROR: $FUNCNAME: incorrect number of arguments: $# (1 or 2 required)" >&2
return 2
fi
# the first arg is an XSL filename
# the second arg is an (optional) output filename
# does the first arg end in .xsl?
if [[ $1 != *.xsl ]]; then
echo "ERROR: $FUNCNAME: XSL filename does not end in .xsl: $1" >&2
return 3
fi
# does the corresponding file exist?
xsl_file="$LIB_DIR/$1"
if [ ! -f "$xsl_file" ]; then
echo "ERROR: $FUNCNAME: lib file does not exist: $xsl_file" >&2
return 4
fi
# capture array elements
xsl_filenames+=("$1")
xsl_files+=("$xsl_file")
# determine the output filename
output_filename="$2"
if [ -z "$output_filename" ]; then
# compute the output filename
base_filename="${1%%.*}"
if [[ $base_filename =~ _(csv|json)$ ]]; then
output_filename=$( echo "$base_filename" | $_SED -e 's/^\(.*\)_\([^_]*\)$/\1.\2/' )
else
output_filename="$base_filename"
fi
fi
# capture remaining array elements
out_filenames+=("$output_filename")
out_files+=("${tmp_dir}/$output_filename")
}
#######################################################################
# Initialization
#######################################################################
# source lib files
for lib_filename in ${lib_filenames[*]}; do
lib_file="$LIB_DIR/$lib_filename"
source "$lib_file"
status_code=$?
if [ $status_code -ne 0 ]; then
echo "ERROR: $script_name failed ($status_code) to source lib file $lib_file" >&2
exit 2
fi
done
# create a temporary subdirectory
tmp_dir="${TMPDIR%%/}/${script_name%%.*}_$$"
/bin/mkdir "$tmp_dir"
status_code=$?
if [ $status_code -ne 0 ]; then
echo "ERROR: $script_name failed ($status_code) to create tmp dir $tmp_dir" >&2
exit 2
fi
# specify output file for SAML metadata
xml_file="${tmp_dir}/saml-metadata.xml"
# read the input arguments into a temporary file
in_file="${tmp_dir}/tmp_file_in.txt"
shift $(( OPTIND - 1 ))
if [ "$#" -gt 0 ]; then
# read input from the command line
while (( "$#" )); do
# copy command-line arg into the temp file
echo "$1" >> "$in_file"
shift
done
else
# read input from stdin
/bin/cat - > "$in_file"
fi
# declare arrays
declare -a xsl_filenames
declare -a xsl_files
declare -a out_filenames
declare -a out_files
# iterate over the input arguments
while read line; do
# process the next line
# (do not quote the line)
process_arg $line
status_code=$?
if [ $status_code -ne 0 ]; then
echo "ERROR: $script_name failed ($status_code) to process data: $line" >&2
exit 2
fi
done < "$in_file"
#######################################################################
# Main processing
#######################################################################
print_log_message -I "$script_name BEGIN"
# get a cached metadata file
print_log_message -I "$script_name retrieving cached metadata file: $md_location"
conditional_get $local_opts -C -d "$CACHE_DIR" -T "$tmp_dir" "$md_location" > "$xml_file"
status_code=$?
if [ $status_code -eq 1 ]; then
# metadata must be cached
print_log_message -E "$script_name: metadata file not cached: $md_location"
clean_up_and_exit -d "$tmp_dir" 1
fi
if [ $status_code -gt 1 ]; then
print_log_message -E "$script_name: conditional_get failed ($status_code) on location: $md_location"
clean_up_and_exit -d "$tmp_dir" $status_code
fi
print_log_message -D "$script_name using XML file: $xml_file"
# create the output files
for i in ${!out_files[*]}; do
print_log_message -I "$script_name writing output file: ${out_filenames[$i]}"
/usr/bin/xsltproc ${xsl_files[$i]} $xml_file > ${out_files[$i]}
status_code=$?
if [ $status_code -ne 0 ]; then
print_log_message -E "$script_name: xsltproc failed ($status_code) on stylesheet: ${xsl_files[$i]}"
clean_up_and_exit -d "$tmp_dir" $status_code
fi
done
# move the output files to the web directory
print_log_message -I "$script_name moving output files to dir: $out_dir"
/bin/mv $( echo -n ${out_files[*]} ) $out_dir
status_code=$?
if [ $status_code -ne 0 ]; then
print_log_message -E "$script_name: mv failed ($status_code) to dir: $out_dir"
clean_up_and_exit -d "$tmp_dir" $status_code
fi
print_log_message -I "$script_name END"
clean_up_and_exit -d "$tmp_dir" 0