-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Initial commit of probe_saml_idp.sh and saml_tools.sh
- Loading branch information
Tom Scavo
committed
Dec 10, 2016
1 parent
e0391d7
commit 3b13946
Showing
3 changed files
with
1,148 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,334 @@ | ||
| #!/bin/bash | ||
|
|
||
| ####################################################################### | ||
| # Copyright 2016 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. | ||
| ####################################################################### | ||
|
|
||
| ####################################################################### | ||
| # Bootstrap | ||
| ####################################################################### | ||
|
|
||
| script_bin=${0%/*} # equivalent to dirname $0 | ||
| script_name=${0##*/} # equivalent to basename $0 | ||
|
|
||
| # determine the source lib directory | ||
| if [ -z "$LIB_DIR" ]; then | ||
| echo "ERROR: $script_name requires env var LIB_DIR" >&2 | ||
| exit 2 | ||
| fi | ||
| if [ ! -d "$LIB_DIR" ]; then | ||
| echo "ERROR: $script_name: LIB_DIR does not exist: $LIB_DIR" >&2 | ||
| exit 2 | ||
| fi | ||
|
|
||
| # library filenames (always list command_paths first) | ||
| LIB_FILENAMES="command_paths.sh | ||
| compatible_mktemp.sh | ||
| http_tools.sh | ||
| md_tools.sh | ||
| saml_tools.sh" | ||
|
|
||
| # source 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 | ||
| source "$lib_file" | ||
| status_code=$? | ||
| if [ $status_code -ne 0 ]; then | ||
| echo "ERROR: $script_name failed to source lib file ($status_code) $lib_file" >&2 | ||
| exit 2 | ||
| 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 | ||
|
|
||
| # 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 | ||
|
|
||
| ####################################################################### | ||
| # Process command-line options and arguments | ||
| ####################################################################### | ||
|
|
||
| help_mode=false; quiet_mode=false; verbose_mode=false | ||
| md_query_mode=false; md_file_mode=false | ||
| local_opts=; connect_timeout=; max_time=; max_redirs= | ||
| while getopts ":hqvt:m:r:u:f:" opt; do | ||
| case $opt in | ||
| h) | ||
| help_mode=true | ||
| ;; | ||
| q) | ||
| quiet_mode=true | ||
| verbose_mode=false | ||
| #local_opts="$local_opts -$opt" | ||
| ;; | ||
| v) | ||
| quiet_mode=false | ||
| verbose_mode=true | ||
| local_opts="$local_opts -$opt" | ||
| ;; | ||
| t) | ||
| connect_timeout="$OPTARG" | ||
| local_opts="$local_opts -t $OPTARG" | ||
| ;; | ||
| m) | ||
| max_time="$OPTARG" | ||
| local_opts="$local_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" | ||
| ;; | ||
| \?) | ||
| 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 | ||
|
|
||
| # 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 | ||
| 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 | ||
|
|
||
| # check consistency of timeout options | ||
| if [ -n "$max_time" -a -z "$connect_timeout" ]; then | ||
| echo "ERROR: $script_name: the -m option requires the presence of the -t option" >&2 | ||
| exit 2 | ||
| fi | ||
|
|
||
| # set default connect timeout if necessary | ||
| if [ -z "$connect_timeout" ]; then | ||
| connect_timeout=$connect_timeout_default | ||
| local_opts="$local_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 | ||
| exit 2 | ||
| fi | ||
| fi | ||
|
|
||
| # compute max time if necessary | ||
| if [ -z "$max_time" ]; then | ||
| max_time=$(( connect_timeout + 2 )) | ||
| local_opts="$local_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 | ||
| exit 2 | ||
| fi | ||
| fi | ||
|
|
||
| # check maximum number of redirects | ||
| if [ -z "$max_redirs" ]; then | ||
| max_redirs=$max_redirs_default | ||
| local_opts="$local_opts -r $max_redirs" | ||
| fi | ||
|
|
||
| if $verbose_mode; then | ||
| printf "$script_name using connect timeout: %d secs\n" $connect_timeout | ||
| printf "$script_name using max time: %d secs\n" $max_time | ||
| printf "$script_name using max redirects: %d\n" $max_redirs | ||
| fi | ||
|
|
||
| # determine the entityID | ||
| shift $(( OPTIND - 1 )) | ||
| if [ $# -ne 1 ]; then | ||
| echo "ERROR: $script_name: wrong number of arguments: $# (1 required)" >&2 | ||
| exit 2 | ||
| fi | ||
| entityID="$1" | ||
| if [ -z "$entityID" ] ; then | ||
| echo "ERROR: $script_name: empty string" >&2 | ||
| exit 2 | ||
| fi | ||
| $verbose_mode && echo "$script_name using entityID $entityID" | ||
|
|
||
| ##################################################################### | ||
| # Initialization | ||
| ##################################################################### | ||
|
|
||
| # determine temporary directory | ||
| if [ -n "$TMPDIR" ] && [ -d "$TMPDIR" ]; then | ||
| # 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 | ||
| tmp_dir="$( make_temp_file -d )" | ||
| if [ ! -d "$tmp_dir" ] ; then | ||
| printf "ERROR: $script_name unable to create temporary dir\n" >&2 | ||
| exit 2 | ||
| fi | ||
| # use temporary directory (remove trailing slash) | ||
| TMP_DIR="${tmp_dir%%/}/probe_saml_idp_$$" | ||
| $verbose_mode && printf "$script_name creating temp dir: %s\n" "$TMP_DIR" | ||
| 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 | ||
| fi | ||
|
|
||
| # create temporary subdirectories if necessary | ||
| for http_binding in Redirect POST POST-SimpleSign; 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 | ||
| fi | ||
| done | ||
|
|
||
| ##################################################################### | ||
| # Main processing | ||
| ##################################################################### | ||
|
|
||
| # get entity metadata | ||
| 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 | ||
| exit 3 | ||
| fi | ||
|
|
||
| # extract the registrar ID from the entity descriptor | ||
| registrarID=$( echo "$entityDescriptor" \ | ||
| | $_GREP -F -m 1 ' registrationAuthority=' \ | ||
| | $_SED -e 's/^.* registrationAuthority="\([^"]*\)".*$/\1/' | ||
| ) | ||
|
|
||
| # compute all SSO endpoints | ||
| endpoints=$( echo "$entityDescriptor" \ | ||
| | $_GREP -E '<(md:)?SingleSignOnService ' | ||
| ) | ||
|
|
||
| # iterate over the SAML2 browser-facing endpoints | ||
| for http_binding in Redirect POST POST-SimpleSign; do | ||
|
|
||
| # compute the endpoint | ||
| endpoint=$( echo "$endpoints" \ | ||
| | $_GREP -F -m 1 ' Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-'$http_binding'"' | ||
| ) | ||
| [ -z "$endpoint" ] && continue | ||
|
|
||
| # compute the endpoint location and binding | ||
| location=$( echo "$endpoint" \ | ||
| | $_SED -e 's/^.* Location="\([^"]*\)".*$/\1/' | ||
| ) | ||
| binding=$( echo "$endpoint" \ | ||
| | $_SED -e 's/^.* Binding="\([^"]*\)".*$/\1/' | ||
| ) | ||
| $verbose_mode && printf "$script_name probing endpoint with Location=\"%s\" and Binding=\"%s\"\n" "$location" "$binding" | ||
|
|
||
| # construct the SAML message | ||
| saml_message=$( construct_SAML2_AuthnRequest $location ) | ||
| exit_status=$? | ||
| if [ "$exit_status" -ne 0 ]; then | ||
| echo "ERROR: $script_name: construct_SAML2_AuthnRequest failed ($exit_status)" >&2 | ||
| exit 3 | ||
| fi | ||
|
|
||
| # probe the endpoint | ||
| output=$( probe_saml2_idp_endpoint -v \ | ||
| -t $connect_timeout -m $max_time -r $max_redirs \ | ||
| -T "$TMP_DIR/$http_binding" \ | ||
| $location $binding "$saml_message" | ||
| ) | ||
| exit_status=$? | ||
| if [ "$exit_status" -ne 0 ]; then | ||
| echo "ERROR: $script_name: probe_saml2_idp_endpoint failed ($exit_status)" >&2 | ||
| exit 3 | ||
| fi | ||
| echo "$output $entityID $registrarID" | ||
|
|
||
| done |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.