Skip to content

Instantly share code, notes, and snippets.

@trscavo
Created January 10, 2016 18:34
Show Gist options
  • Save trscavo/faae23e5ed06b736d40b to your computer and use it in GitHub Desktop.
Save trscavo/faae23e5ed06b736d40b to your computer and use it in GitHub Desktop.
SAML metadata helper tools for bash scripts
#!/bin/bash
#######################################################################
# Copyright 2016 InCommon, LLC.
#
# 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.
#######################################################################
#######################################################################
# Get entity metadata from a local file.
#
# Usage: getEntityFromFile ENTITY_ID
#
# Depends on env var MD_PATH, the absolute path to the metadata file.
#######################################################################
getEntityFromFile () {
local entityID
local entityDescriptor
if [ -z "$MD_PATH" ]; then
echo "ERROR: $FUNCNAME: MD_PATH env var does not exist" >&2
return 2
fi
if [ ! -f "$MD_PATH" ]; then
echo "ERROR: $FUNCNAME: file does not exist: $MD_PATH" >&2
return 2
fi
# make sure there is one (and only one) command-line argument
if [ $# -ne 1 ]; then
echo "ERROR: $FUNCNAME: incorrect number of arguments: $# (1 required)" >&2
return 2
fi
entityID=$1
# get the entity descriptor from a local file
entityDescriptor=$( /bin/cat $MD_PATH \
| sed -n -e '\;<\(md:\)\{0,1\}EntityDescriptor.* entityID="'${entityID}'";,\;EntityDescriptor>;p'
)
if [ -z "$entityDescriptor" ]; then
echo "ERROR: $FUNCNAME: no entity descriptor for entityID: $entityID" >&2
return 1
fi
echo "$entityDescriptor"
}
#######################################################################
# Get entity metadata from a Metadata Query Server.
#
# Usage: getEntityFromServer ENTITY_ID
#
# Depends on two env vars:
#
# 1. MDQ_BASE_URL, the base URL of the query server
# 2. TMP_DIR, a temporary directory
#
# A temporary file containing the HTTP response is created in TMP_DIR.
#######################################################################
getEntityFromServer () {
local tmp_file
local entityID
local encoded_id
local return_status
local mdq_request_url
local output
local exit_code
local response_code
if [ -z "$MDQ_BASE_URL" ]; then
echo "ERROR: $FUNCNAME: MDQ_BASE_URL env var does not exist" >&2
return 2
fi
if [ -z "$TMP_DIR" ]; then
echo "ERROR: $FUNCNAME: TMP_DIR env var does not exist" >&2
return 2
fi
if [ ! -d "$TMP_DIR" ]; then
echo "ERROR: $FUNCNAME: temp directory does not exist: $TMP_DIR" >&2
return 2
fi
tmp_file="$TMP_DIR/mdq_response_$$.txt"
# make sure there is one (and only one) command-line argument
if [ $# -ne 1 ]; then
echo "ERROR: $FUNCNAME: incorrect number of arguments: $# (1 required)" >&2
return 2
fi
entityID=$1
# URL-encode the identifier
encoded_id=$( urlencode $entityID )
return_status=$?
if [ "$return_status" -ne 0 ]; then
echo "ERROR: $FUNCNAME: failed to URL-encode the entityID: $entityID" >&2
return 3
fi
# compute the MDQ protocol request URL
mdq_request_url=$( construct_mdq_url $MDQ_BASE_URL $encoded_id )
return_status=$?
if [ "$return_status" -ne 0 ]; then
echo "ERROR: $FUNCNAME: failed to construct the request URL from the encoded entityID: $encoded_id" >&2
return 3
fi
# get a single entity descriptor via the MDQ protocol
output=$( /usr/bin/curl --silent \
--output "$tmp_file" \
--write-out 'response:%{http_code};dns:%{time_namelookup};tcp:%{time_connect};ssl:%{time_appconnect};total:%{time_total}' \
"$mdq_request_url"
)
exit_code=$?
if [ "$exit_code" -ne 0 ]; then
echo "ERROR: $FUNCNAME: curl failed (exit code $exit_code $output): $mdq_request_url" >&2
return 3
fi
# check the HTTP response code
response_code=$( echo "$output" | sed -e 's/^response:\([^;]*\).*$/\1/' )
if [[ "$response_code" != 200 ]]; then
echo "ERROR: $FUNCNAME: query failed (response code $response_code): $mdq_request_url" >&2
return 1
fi
/bin/cat "$tmp_file"
}
#######################################################################
# Construct a request URL per the MDQ Protocol specification.
# See: https://github.com/iay/md-query
#
# Usage: construct_mdq_url <base_url> <url_encoded_id>
#
# To construct a reference to ALL entities served by the
# metadata query server, simply omit the second argument
#######################################################################
construct_mdq_url () {
# make sure there are one or two 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
local base_url=$1
# strip the trailing slash from the base URL if necessary
local length="${#1}"
if [[ "${base_url:length-1:1}" == '/' ]]; then
base_url="${base_url:0:length-1}"
fi
# append the identifier if there is one
if [ $# -eq 2 ]; then
echo "${base_url}/entities/$2"
else
echo "${base_url}/entities"
fi
}
#######################################################################
# URL-encode an arbitrary string.
# See: https://gist.github.com/cdown/1163649
#
# Usage: urlencode <string>
#######################################################################
urlencode () {
# make sure there is one (and only one) command-line argument
if [ $# -ne 1 ]; then
echo "ERROR: $FUNCNAME: incorrect number of arguments: $# (1 required)" >&2
return 2
fi
local length="${#1}"
for (( i = 0; i < length; i++ )); do
local c="${1:i:1}"
case "$c" in
[a-zA-Z0-9.~_-]) printf "$c" ;;
*) printf '%%%02X' "'$c"
esac
done
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment