Skip to content

Commit

Permalink
Implement config file
Browse files Browse the repository at this point in the history
  • Loading branch information
Tom Scavo committed Dec 12, 2016
1 parent 49c2d5d commit d772e18
Show file tree
Hide file tree
Showing 3 changed files with 250 additions and 117 deletions.
225 changes: 108 additions & 117 deletions bin/probe_saml_idp.sh
Original file line number Diff line number Diff line change
Expand Up @@ -28,28 +28,26 @@ display_help () {
${user_agent_string}
Given a single identifier, assumed to be an IdP entityID, probe
all browser-facing SAML2 SSO endpoints in IdP metadata.
all browser-facing SSO endpoints in IdP metadata.
Usage: ${0##*/} [-hvq] [-t CONNECT_TIME [-m MAX_TIME]] [-r MAX_REDIRS] (-u MDQ_BASE_URL | -f MD_PATH) ID
Usage: ${0##*/} [-hvq] [-t CONNECT_TIME [-m MAX_TIME]] [-r MAX_REDIRS] ID
Options:
-h Display this message
-v Write verbose messages to stdout
-q Run quietly (i.e., write no messages to stdout)
-t Time (in secs) to connect to the host
-t Allowed time (in secs) to connect to the host
-m Maximum time (in secs) of a complete probe
-r Maximum number of HTTP redirects followed
-u Base URL of a Metadata Query Server
-f Path to a local metadata file
Option -h is mutually exclusive of all other options. Options
-q and -v are mutually exclusive of each other. Options -u and -f
are mutually exclusive of each other as well.
The argument of the -t option is the TCP connect time, that is,
the maximum time (in secs) allotted to the TCP connection. Note
that the TCP connect time includes the time it takes to do a
DNS name lookup. Since the latter is unconstrained, it may
the maximum time (in secs) allotted to obtain a TCP connection.
Note that the TCP connect time includes the time it takes to do
a DNS name lookup. Since the latter is unconstrained, it may
consume all available TCP connect time. Thus the TCP connect
time should be kept small (on the order of a few seconds) since
larger values will slow this script considerably.
Expand All @@ -59,17 +57,12 @@ display_help () {
beyond the TCP connect time. Any value less than the TCP connect
time causes the script to immediately fail.
Entity metadata is required to process each identifier. Metadata is
obtained in one of two ways, by consulting a Metadata Query Server
just-in-time or by using a pre-provisioned metadata aggregate. These
correspond to options -u and -f, respectively. Exactly one of these
options is required.
CONFIGURATION
Option -f takes an optional file argument (MD_PATH), the absolute
path to a local SAML metadata file. The script searches this file for
a corresponding entity descriptor as it processes each identifier.
Entity metadata is required to process each identifier. Metadata is
obtained by consulting a Metadata Query Server just-in-time.
Option -u takes an optional URI argument (MDQ_BASE_URL), the base
...(MDQ_BASE_URL), the base
URL of a Metadata Query Server (i.e., a server that conforms to the
Metadata Query Protocol). The base URL is used to construct an MDQ
request URL, which the script uses to request entity metadata
Expand Down Expand Up @@ -99,7 +92,8 @@ LIB_FILENAMES="command_paths.sh
compatible_mktemp.sh
http_tools.sh
md_tools.sh
saml_tools.sh"
saml_tools.sh
config_tools.sh"

# source lib files
for lib_filename in $LIB_FILENAMES; do
Expand All @@ -116,37 +110,21 @@ for lib_filename in $LIB_FILENAMES; do
fi
done

# default parameters
connect_timeout_default=2
max_redirs_default=7

# default env vars
saml2_sp_entity_id_default=https://fm.incommon.org/sp
saml2_sp_acs_url_default=https://service1.internet2.edu/Shibboleth.sso/SAML2/POST
saml2_sp_acs_binding_default=urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST
# basic curl defaults
connect_timeout_default=2; max_redirs_default=7

# check env vars, set defaults if neccessary
if [ -z "$SAML2_SP_ENTITY_ID" ]; then
echo "WARNING: $script_name: env var SAML2_SP_ENTITY_ID does not exist, using default: $saml2_sp_entity_id_default" >&2
SAML2_SP_ENTITY_ID=$saml2_sp_entity_id_default
fi
if [ -z "$SAML2_SP_ACS_URL" ]; then
echo "WARNING: $script_name: env var SAML2_SP_ACS_URL does not exist, using default: $saml2_sp_acs_url_default" >&2
SAML2_SP_ACS_URL=$saml2_sp_acs_url_default
fi
if [ -z "$SAML2_SP_ACS_BINDING" ]; then
echo "WARNING: $script_name: env var SAML2_SP_ACS_BINDING does not exist, using default: $saml2_sp_acs_binding_default" >&2
SAML2_SP_ACS_BINDING=$saml2_sp_acs_binding_default
fi
# default config file
config_file_default="${script_bin}/.config"

#######################################################################
# Process command-line options and arguments
#######################################################################

help_mode=false; quiet_mode=false; verbose_mode=false
md_query_mode=false; md_file_mode=false
probe_saml1=false # TODO: implement -1 option
local_opts=; connect_timeout=; max_time=; max_redirs=
while getopts ":hqvt:m:r:u:f:" opt; do
curl_opts=
while getopts ":hqvt:m:r:" opt; do
case $opt in
h)
help_mode=true
Expand All @@ -163,25 +141,15 @@ while getopts ":hqvt:m:r:u:f:" opt; do
;;
t)
connect_timeout="$OPTARG"
local_opts="$local_opts -t $OPTARG"
curl_opts="$curl_opts -t $OPTARG"
;;
m)
max_time="$OPTARG"
local_opts="$local_opts -m $OPTARG"
curl_opts="$curl_opts -m $OPTARG"
;;
r)
max_redirs="$OPTARG"
local_opts="$local_opts -r $OPTARG"
;;
u)
md_query_mode=true
md_file_mode=false
mdq_base_url="$OPTARG"
;;
f)
md_query_mode=false
md_file_mode=true
md_path="$OPTARG"
curl_opts="$curl_opts -r $OPTARG"
;;
\?)
echo "ERROR: $script_name: Unrecognized option: -$OPTARG" >&2
Expand All @@ -199,41 +167,6 @@ if $help_mode; then
exit 0
fi

# report bootstrap operations
if $verbose_mode; then
printf "$script_name using source lib directory: %s\n" "$LIB_DIR"
for lib_filename in $LIB_FILENAMES; do
lib_file="$LIB_DIR/$lib_filename"
printf "$script_name sourced lib file: %s\n" "$lib_file"
done
fi

# determine the metadata source
if $md_query_mode; then
if [ -z "$mdq_base_url" ]; then
echo "ERROR: $script_name: option -u requires an argument" >&2
exit 2
fi
$verbose_mode && printf "$script_name using base URL: %s\n" "$mdq_base_url"
elif $md_file_mode; then
# temporary
echo "ERROR: $script_name: option -f not yet implemented" >&2
exit 2

if [ -z "$md_path" ]; then
echo "ERROR: $script_name: option -f requires an argument" >&2
exit 2
fi
if [ ! -f "$md_path" ]; then
echo "ERROR: $script_name: file does not exist: $md_path" >&2
exit 2
fi
$verbose_mode && printf "$script_name using metadata file: %s\n" "$md_path"
else
echo "ERROR: $script_name: one of options -u or -f required" >&2
exit 2
fi

# redirect stdout and stderr to the bit bucket
$quiet_mode && exec 1>/dev/null
$quiet_mode && exec 2>/dev/null
Expand All @@ -247,7 +180,7 @@ fi
# set default connect timeout if necessary
if [ -z "$connect_timeout" ]; then
connect_timeout=$connect_timeout_default
local_opts="$local_opts -t $connect_timeout"
curl_opts="$curl_opts -t $connect_timeout"
else
if [ "$connect_timeout" -le 0 ] ; then
echo "ERROR: $script_name: connect timeout ($connect_timeout) must be a positive integer" >&2
Expand All @@ -258,7 +191,7 @@ fi
# compute max time if necessary
if [ -z "$max_time" ]; then
max_time=$(( connect_timeout + 2 ))
local_opts="$local_opts -m $max_time"
curl_opts="$curl_opts -m $max_time"
else
if [ "$max_time" -le "$connect_timeout" ]; then
echo "ERROR: $script_name: max time ($max_time) must be greater than the connect timeout ($connect_timeout)" >&2
Expand All @@ -269,7 +202,7 @@ fi
# check maximum number of redirects
if [ -z "$max_redirs" ]; then
max_redirs=$max_redirs_default
local_opts="$local_opts -r $max_redirs"
curl_opts="$curl_opts -r $max_redirs"
fi

if $verbose_mode; then
Expand All @@ -278,6 +211,10 @@ if $verbose_mode; then
printf "$script_name using max redirects: %d\n" $max_redirs
fi

# TODO: implement new option
config_file="$config_file_default"
$verbose_mode && echo "$script_name using config file $config_file"

# determine the entityID
shift $(( OPTIND - 1 ))
if [ $# -ne 1 ]; then
Expand All @@ -295,56 +232,98 @@ $verbose_mode && echo "$script_name using entityID $entityID"
# Initialization
#####################################################################

if $verbose_mode; then
printf "$script_name using source lib directory: %s\n" "$LIB_DIR"
for lib_filename in $LIB_FILENAMES; do
lib_file="$LIB_DIR/$lib_filename"
printf "$script_name sourcing lib file: %s\n" "$lib_file"
done
fi

# determine temporary directory
if [ -n "$TMP_DIR" ] && [ -d "$TMP_DIR" ]; then
# use user-provided temporary directory (remove trailing slash)
$verbose_mode && printf "$script_name using existing temporary dir: %s\n" "$TMP_DIR"
# use existing temporary directory (remove trailing slash)
tmp_dir="${TMP_DIR%%/}/probe_saml_idp_$$"
$verbose_mode && printf "$script_name using temp dir: %s\n" "$tmp_dir"
elif [ -n "$TMPDIR" ] && [ -d "$TMPDIR" ]; then
$verbose_mode && printf "$script_name using system temporary dir: %s\n" "$TMPDIR"
# use system temporary directory (remove trailing slash)
tmp_dir="${TMPDIR%%/}/probe_saml_idp_$$"
$verbose_mode && printf "$script_name using temp dir: %s\n" "$tmp_dir"
else
# create temporary directory
new_dir="$( make_temp_file -d )"
if [ ! -d "$new_dir" ] ; then
printf "ERROR: $script_name unable to create temporary dir\n" >&2
exit 2
fi
# use temporary directory (remove trailing slash)
$verbose_mode && printf "$script_name using new temporary dir: %s\n" "$new_dir"
# use new temporary directory (remove trailing slash)
tmp_dir="${new_dir%%/}/probe_saml_idp_$$"
$verbose_mode && printf "$script_name creating temp dir: %s\n" "$tmp_dir"
fi

# every run of this script gets its own subdir
if [ -d "$tmp_dir" ]; then
echo "ERROR: $script_name: directory already exists: $tmp_dir" >&2
exit 2
fi

# create temporary directory if necessary
if [ ! -d "$tmp_dir" ]; then
/bin/mkdir "$tmp_dir"
exit_status=$?
if [ $exit_status -ne 0 ]; then
echo "ERROR: $script_name failed to create tmp dir ($exit_status) $tmp_dir" >&2
exit 2
fi
$verbose_mode && printf "$script_name creating temporary subdir: %s\n" "$tmp_dir"
/bin/mkdir "$tmp_dir"
status_code=$?
if [ $status_code -ne 0 ]; then
echo "ERROR: $script_name failed to create tmp dir ($status_code) $tmp_dir" >&2
exit 2
fi

# create temporary subdirectories if necessary
http_bindings="Redirect POST POST-SimpleSign"
for http_binding in $http_bindings; do
if [ ! -d "$tmp_dir/$http_binding" ]; then
/bin/mkdir "$tmp_dir/$http_binding"
exit_status=$?
if [ $exit_status -ne 0 ]; then
echo "ERROR: $script_name failed to create tmp dir ($exit_status) $tmp_dir/$http_binding" >&2
exit 2
fi
# load config file
$verbose_mode && echo "$script_name loading config file $config_file"
load_config $local_opts "$config_file"
status_code=$?
if [ $status_code -ne 0 ]; then
echo "ERROR: $script_name failed to load $config_file" >&2
exit 2
fi

# validate config parameters
if [ -z "$MDQ_BASE_URL" ]; then
echo "ERROR: $script_name requires config param MDQ_BASE_URL" >&2
exit 2
fi
if [ -z "$SAML2_SP_ENTITY_ID" ]; then
echo "ERROR: $script_name requires config param SAML2_SP_ENTITY_ID" >&2
exit 2
fi
if [ -z "$SAML2_SP_ACS_URL" ]; then
echo "ERROR: $script_name requires config param SAML2_SP_ACS_URL" >&2
exit 2
fi
if [ -z "$SAML2_SP_ACS_BINDING" ]; then
echo "ERROR: $script_name requires config param SAML2_SP_ACS_BINDING" >&2
exit 2
fi

if $probe_saml1; then
if [ -z "$SAML1_SP_ENTITY_ID" ]; then
echo "ERROR: $script_name requires config param SAML1_SP_ENTITY_ID" >&2
exit 2
fi
done
if [ -z "$SAML1_SP_ACS_URL" ]; then
echo "ERROR: $script_name requires config param SAML1_SP_ACS_URL" >&2
exit 2
fi
if [ -z "$SAML1_SP_ACS_BINDING" ]; then
echo "ERROR: $script_name requires config param SAML1_SP_ACS_BINDING" >&2
exit 2
fi
fi

#####################################################################
# Main processing
#####################################################################

# get entity metadata
entityDescriptor=$( getEntityFromServer -d "$tmp_dir" -u "$mdq_base_url" $entityID )
entityDescriptor=$( getEntityFromServer -d "$tmp_dir" -u "$MDQ_BASE_URL" $entityID )
exit_status=$?
if [ "$exit_status" -ne 0 ]; then
echo "ERROR: $script_name: unable to obtain metadata for entityID: $entityID" >&2
Expand All @@ -363,6 +342,7 @@ endpoints=$( echo "$entityDescriptor" \
)

# iterate over the SAML2 browser-facing SSO endpoints
http_bindings="Redirect POST POST-SimpleSign"
for http_binding in $http_bindings; do

# compute the endpoint
Expand All @@ -388,10 +368,21 @@ for http_binding in $http_bindings; do
exit 3
fi

# create temporary subdirectory if necessary
tmp_subdir="$tmp_dir/$http_binding"
if [ ! -d "$tmp_subdir" ]; then
/bin/mkdir "$tmp_subdir"
exit_status=$?
if [ $exit_status -ne 0 ]; then
echo "ERROR: $script_name failed to create tmp dir ($exit_status) $tmp_subdir" >&2
exit 2
fi
fi

# probe the endpoint
output=$( probe_saml2_idp_endpoint -v \
-t $connect_timeout -m $max_time -r $max_redirs \
-T "$tmp_dir/$http_binding" \
-T "$tmp_subdir" \
$location $binding "$saml_message"
)
exit_status=$?
Expand Down
1 change: 1 addition & 0 deletions install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ done <<SOURCES
$script_bin/lib/command_paths.sh
$script_bin/lib/compatible_date.sh
$script_bin/lib/compatible_mktemp.sh
$script_bin/lib/config_tools.sh
$script_bin/lib/extract_entity.xsl
$script_bin/lib/http_tools.sh
$script_bin/lib/md_tools.sh
Expand Down
Loading

0 comments on commit d772e18

Please sign in to comment.