|
#!/usr/bin/env bash |
|
|
|
set -e |
|
|
|
[ "$(type -t info)" == "function" ] || . "~/bin/logging.sh" |
|
|
|
show_help() { |
|
cat <<EOF |
|
Usage: $(basename "$0") [options] [project_id] [client_name] [config_dir] |
|
|
|
Options: |
|
-p, --project <project_id> Project id |
|
-c, --client <client_name> Client name |
|
-f, --config <config_dir> Config directory |
|
-r, --refresh Force refresh of credentials |
|
-v, --verbose Verbose output |
|
-d, --debug Debug output |
|
-h, --help Show this help message and exit |
|
EOF |
|
} |
|
|
|
while [ "$#" -gt 0 ]; do |
|
case "$1" in |
|
-p | --project) |
|
PROJECT_ID="$2" |
|
shift;; |
|
-c | --client) |
|
CLIENT_NAME="$2" |
|
shift;; |
|
-f | --config) |
|
CONFIG="$2" |
|
shift;; |
|
-r | --refresh) |
|
FORCE_REFRESH=1;; |
|
-v | --verbose | -d | --debug) |
|
DEBUG=1;; |
|
-h | --help) |
|
show_help; exit 0;; |
|
*) |
|
break ;; |
|
esac |
|
shift |
|
done |
|
|
|
[ -n "$1" ] && [ -z "$PROJECT_ID" ] && PROJECT_ID="$1" && shift |
|
[ -n "$1" ] && [ -z "$CLIENT_NAME" ] && CLIENT_NAME="$1" && shift |
|
[ -n "$1" ] && [ -z "$CONFIG" ] && CONFIG="$1" && shift |
|
|
|
if [ "$#" -gt 0 ]; then |
|
show_help |
|
error "Unknown arguments ($#): >$*<" |
|
exit 1 |
|
fi |
|
|
|
[ -z "$PROJECT_ID" ] && show_help && error "Missing project id" && exit 1 |
|
[ -z "$CLIENT_NAME" ] && show_help && error "Missing client name" && exit 1 |
|
|
|
CONFIG=${CONFIG:-~/.config/$CLIENT_NAME} |
|
|
|
CLIENT_INFO=$CONFIG/iap_client_info.json |
|
CREDS_FILE=$CONFIG/iap_creds.json |
|
REQUEST_CAP=$CONFIG/oauth_cap.json |
|
|
|
get_iap_client_info() { |
|
info "Getting iap client info" |
|
# Assumes there is only one brand in the project |
|
BRAND_NAME="$(gcloud iap oauth-brands list --project "$PROJECT_ID" --format=json | jq -r '.[0].name')" |
|
gcloud iap oauth-clients list --project="$PROJECT_ID" "$BRAND_NAME" --format=json | |
|
jq ".[] | select(.displayName | contains(\"$CLIENT_NAME\"))" > "$CLIENT_INFO" |
|
} |
|
|
|
run_server() { |
|
python3 - <<'__HERE' |
|
from http.server import BaseHTTPRequestHandler, HTTPServer |
|
|
|
class SimpleHandler(BaseHTTPRequestHandler): |
|
# Disable logging for each request |
|
def log_request(self, code="-", size="-"): |
|
pass |
|
|
|
def do_GET(self): |
|
self.send_response(200) |
|
self.send_header("Content-type", "text/plain") |
|
self.end_headers() |
|
self.wfile.write(b"Got it. Thanks! (You can close this tab)\n") |
|
|
|
print(f"{self.requestline}") |
|
|
|
server_address = ("", 4444) |
|
httpd = HTTPServer(server_address, SimpleHandler) |
|
httpd.handle_request() |
|
__HERE |
|
} |
|
|
|
refresh_iap_creds() { |
|
info "Refreshing IAP creds" |
|
|
|
get_client_info |
|
|
|
debug "Starting local server" |
|
run_server > "$REQUEST_CAP" & |
|
SERVER_PID=$! |
|
|
|
debug "Calling oauth login with client id: $CLIENT_ID" |
|
open "https://accounts.google.com/o/oauth2/v2/auth?client_id=${CLIENT_ID}&response_type=code&scope=openid%20email&access_type=offline&redirect_uri=http://localhost:4444&cred_ref=true" |
|
|
|
debug "Waiting for server to get code" |
|
wait $SERVER_PID |
|
|
|
CODE="$(grep 'GET' "$REQUEST_CAP" | awk -F'code=|&' '{print $2}')" |
|
rm "$REQUEST_CAP" |
|
|
|
debug "Received code: $CODE" |
|
|
|
# curl to get oauth token |
|
curl -s \ |
|
--data client_id=$CLIENT_ID \ |
|
--data client_secret=$CLIENT_SECRET \ |
|
--data code=$CODE \ |
|
--data redirect_uri=http://localhost:4444 \ |
|
--data grant_type=authorization_code \ |
|
https://oauth2.googleapis.com/token > "$CREDS_FILE" |
|
} |
|
|
|
get_client_info() { |
|
debug "Checking for cached iap client info" |
|
[ -f "$CLIENT_INFO" ] || get_iap_client_info |
|
|
|
CLIENT_ID="$(jq -r '.name' "$CLIENT_INFO" | awk -F/ '{print $NF}')" |
|
CLIENT_SECRET="$(jq -r '.secret' "$CLIENT_INFO")" |
|
} |
|
|
|
debug "PROJECT_ID: $PROJECT_ID" |
|
debug "CLIENT_NAME: $CLIENT_NAME" |
|
debug "CONFIG: $CONFIG" |
|
debug "FORCE_REFRESH: $FORCE_REFRESH" |
|
debug "DEBUG: $DEBUG" |
|
|
|
[ -n "$FORCE_REFRESH" ] && refresh_iap_creds && exit 0 |
|
|
|
# Resolve credentials from cache, if possible, or by retrieving them |
|
debug "Checking for cached iap creds" |
|
[ -f "$CREDS_FILE" ] || refresh_iap_creds |
|
|
|
jq -r '.id_token' "$CREDS_FILE" |