|
| 1 | +#!/usr/bin/env bash |
| 2 | +# configure.sh (c) NGINX, Inc. [23-Nov-2018] Liam Crilly <[email protected]> |
| 3 | + |
| 4 | +COMMAND=${0##*/} |
| 5 | +CONFDIR=${0%/*} |
| 6 | +if [ $# -lt 1 ]; then |
| 7 | + echo "USAGE: $COMMAND [options] <OpenID Connect confinguration URL>" |
| 8 | + echo "" |
| 9 | + echo "Configures NGINX Plus OpenID Connect reference implementation by using the IdP's Discovery interface" |
| 10 | + echo "" |
| 11 | + echo " URL typically ends with '/openid-configuration'" |
| 12 | + echo " Options:" |
| 13 | + echo " -k | --auth_jwt_key <file|request> # Use auth_jwt_key_file (default) or auth_jwt_key_request (R17+)" |
| 14 | + echo " -i | --client_id <id> # Client ID as obtained from OpenID Connect Provider" |
| 15 | + echo " -s | --client_secret <secret> # Client secret as obtained from OpenID Connect Provider" |
| 16 | + echo " -x | --insecure # Do not verify IdP's SSL certificate" |
| 17 | + echo " -d | --dry_run # Produce configuration to stdout without modifying frontend.conf" |
| 18 | + echo "" |
| 19 | + exit 1 |
| 20 | +fi |
| 21 | + |
| 22 | +# Process command line options |
| 23 | +# |
| 24 | +DO_JWKS_URI=0 |
| 25 | +CLIENT_ID="" |
| 26 | +CLIENT_SECRET="" |
| 27 | +SED_OPT="-i.ORIG " |
| 28 | +while [ $# -gt 1 ]; do |
| 29 | + case "$1" in |
| 30 | + "-k" | "--auth_jwt_key") |
| 31 | + if [ "$2" == "request" ]; then |
| 32 | + DO_JWKS_URI=1 |
| 33 | + elif [ "$2" != "file" ]; then |
| 34 | + echo "$COMMAND: ERROR: Valid arguments to $1 are 'file' or 'request'" |
| 35 | + exit 1 |
| 36 | + fi |
| 37 | + shift; shift |
| 38 | + ;; |
| 39 | + "-i" | "--client_id" | "--client-id") |
| 40 | + CLIENT_ID=$2 |
| 41 | + shift; shift |
| 42 | + ;; |
| 43 | + "-s" | "--client_secret" | "--client-secret") |
| 44 | + CLIENT_SECRET=$2 |
| 45 | + shift; shift |
| 46 | + ;; |
| 47 | + "-x" | "--insecure" ) |
| 48 | + CURL_OPT="-k " |
| 49 | + WGET_OPT="--no-check-certificate " |
| 50 | + shift |
| 51 | + ;; |
| 52 | + "-d" | "--dry_run" | "--dry-run") |
| 53 | + SED_OPT="" |
| 54 | + shift |
| 55 | + ;; |
| 56 | + *) |
| 57 | + echo "$COMMAND: ERROR: Invalid command line option ($1) - quitting" |
| 58 | + exit 1 |
| 59 | + ;; |
| 60 | + esac |
| 61 | +done |
| 62 | +IDP_URL=$1 |
| 63 | + |
| 64 | +# Check for dependencies |
| 65 | +# |
| 66 | +hash jq 2> /dev/null |
| 67 | +if [ $? -ne 0 ]; then |
| 68 | + echo "$COMMAND: ERROR: 'jq' must be installed" |
| 69 | + jq |
| 70 | + exit 1 |
| 71 | +fi |
| 72 | + |
| 73 | +for http_cli in "wget ${WGET_OPT}-q -O -" "curl ${CURL_OPT}-sS"; do |
| 74 | + hash ${http_cli%% *} 2> /dev/null # Remove chars beyond space |
| 75 | + if [ $? -eq 0 ]; then |
| 76 | + GET_URL=$http_cli |
| 77 | + break #for |
| 78 | + fi |
| 79 | +done |
| 80 | +if [ "$GET_URL" == "" ]; then |
| 81 | + echo "$COMMAND: ERROR: 'curl' or 'wget' must be installed to download configuration data" |
| 82 | + exit 1 |
| 83 | +fi |
| 84 | + |
| 85 | +# Download the OpenID Connect Discovery document |
| 86 | +$GET_URL $IDP_URL > /tmp/${COMMAND}_$$_json |
| 87 | + |
| 88 | +# Test for exit error |
| 89 | +if [ $? -ne 0 ]; then |
| 90 | + echo "$COMMAND: ERROR: Unable to connect to $IDP_URL" |
| 91 | + cat /tmp/${COMMAND}_$$_json |
| 92 | + rm /tmp/${COMMAND}_$$_json |
| 93 | + exit 1 |
| 94 | +fi |
| 95 | + |
| 96 | +# Test for valid JSON object |
| 97 | +jq -r .authorization_endpoint < /tmp/${COMMAND}_$$_json 2>&1 | grep -c ^http > /dev/null |
| 98 | +if [ $? -ne 0 ]; then |
| 99 | + echo "$COMMAND: ERROR: $IDP_URL returned invalid OpenID Connect Discovery document" |
| 100 | + cat /tmp/${COMMAND}_$$_json |
| 101 | + rm /tmp/${COMMAND}_$$_json |
| 102 | + exit 1 |
| 103 | +fi |
| 104 | + |
| 105 | +# Build an intermediate configuration file (will be converted to sed(1) command file. |
| 106 | +# File format is: <NGINX variable name><space><IdP value> |
| 107 | +# |
| 108 | +jq -r '. | "$oidc_authz_endpoint \(.authorization_endpoint)\n$oidc_token_endpoint \(.token_endpoint)\n$oidc_jwks_uri \(.jwks_uri)"' < /tmp/${COMMAND}_$$_json > /tmp/${COMMAND}_$$_conf |
| 109 | + |
| 110 | +# Create a random value for HMAC key, adding to the base mapping file |
| 111 | +echo "\$oidc_hmac_key `openssl rand -base64 18`" >> /tmp/${COMMAND}_$$_conf |
| 112 | + |
| 113 | +# Add client ID and secret to the base mapping file (if provided) |
| 114 | +if [ "$CLIENT_ID" != "" ]; then |
| 115 | + echo "\$oidc_client $CLIENT_ID" >> /tmp/${COMMAND}_$$_conf |
| 116 | +fi |
| 117 | +if [ "$CLIENT_SECRET" != "" ]; then |
| 118 | + echo "\$oidc_client_secret $CLIENT_SECRET" >> /tmp/${COMMAND}_$$_conf |
| 119 | +fi |
| 120 | + |
| 121 | +# Fetch or configure the JWK file depending on configuration input |
| 122 | +# Also apply appropriate auth_jwt_key_ configuration directive. |
| 123 | +# NB: auth_jwt_key_request requires NGINX Plus R17 or later |
| 124 | +# |
| 125 | +JWKS_URI=`jq -r .jwks_uri < /tmp/${COMMAND}_$$_json` |
| 126 | +if [ $DO_JWKS_URI -eq 0 ]; then |
| 127 | + echo "$COMMAND: NOTICE: Downloading $CONFDIR/idp_jwk.json" |
| 128 | + $GET_URL $JWKS_URI > $CONFDIR/idp_jwk.json |
| 129 | + if [ $? -ne 0 ] || [ ! -s $CONFDIR/idp_jwk.json ]; then |
| 130 | + echo "$COMMAND: ERROR: Failed to download from $JWKS_URI" |
| 131 | + cat $CONFDIR/idp_jwk.json |
| 132 | + exit 1 |
| 133 | + fi |
| 134 | + echo "\$oidc_jwt_keyfile conf.d/idp_jwk.json" >> /tmp/${COMMAND}_$$_conf |
| 135 | + echo "s/#\(auth_jwt_key_file\)/\1/" > /tmp/${COMMAND}_$$_sed # Uncomment |
| 136 | + echo "s/ \(auth_jwt_key_request\)/ #\1/" >> /tmp/${COMMAND}_$$_sed # Comment-out |
| 137 | +else |
| 138 | + echo "\$oidc_jwt_keyfile $JWKS_URI" >> /tmp/${COMMAND}_$$_conf |
| 139 | + echo "s/ \(auth_jwt_key_file\)/ #\1/" > /tmp/${COMMAND}_$$_sed # Comment-out |
| 140 | + echo "s/#\(auth_jwt_key_request\)/\1/" >> /tmp/${COMMAND}_$$_sed # Uncomment |
| 141 | +fi |
| 142 | + |
| 143 | +# Build the sed(1) command file (requires a lot of escaping) |
| 144 | +# |
| 145 | +sed -e "s/\//\\\\\//g" /tmp/${COMMAND}_$$_conf | awk '{print "s/\\("$1"\\) \\(.*\\);/\\1 \""$2"\";/"}' >> /tmp/${COMMAND}_$$_sed |
| 146 | + |
| 147 | +# Perform the substitutions on frontend.conf |
| 148 | +# |
| 149 | +echo "$COMMAND: NOTICE: Configuring $CONFDIR/frontend.conf" |
| 150 | +sed ${SED_OPT}-f /tmp/${COMMAND}_$$_sed $CONFDIR/frontend.conf |
| 151 | + |
| 152 | +if [ $? -eq 0 ]; then |
| 153 | + echo "$COMMAND: NOTICE: Success - test configuration with 'nginx -t'" |
| 154 | + rm /tmp/${COMMAND}_$$_* |
| 155 | +else |
| 156 | + echo "$COMMAND: ERROR: Configuration failed, check intermediate files `ls -1 /tmp/${COMMAND}_$$_* | tr '\n' ' '`" |
| 157 | +fi |
0 commit comments