Created
November 13, 2025 18:41
-
-
Save rleap-m/3f1f66924a7263f93e46c6147fac1654 to your computer and use it in GitHub Desktop.
Script which will obtain access and refresh tokens to interact with MKE4 /api/auth/v1/accounts endpoints
This file contains hidden or 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
| #!/usr/bin/env bash | |
| set -euo pipefail | |
| # ============================================ | |
| # MKE / Dex OAuth2 PKCE token fetcher (bash-only) | |
| # - Auth Code + PKCE: interactive (copy/paste code) | |
| # - Refresh grant: non-interactive | |
| # | |
| # deps: bash, curl, openssl, base64, tr, sed | |
| # (jq optional; script falls back to sed) | |
| # ============================================ | |
| # Defaults | |
| ADDRESS="" # mkectl-style flag name | |
| CLIENT_ID="mke-dashboard" # Only audience registered in Dex (at the time of the script writing) | |
| SCOPES="openid profile email groups offline_access" | |
| REDIRECT_URI="https://127.0.0.1:3000" # To see the accepted redirects for mke-dashboard run: | |
| # kubectl get clusterdeployments.k0rdent.mirantis.com/self-adopted-cluster-mke -n k0rdent -o yaml | grep staticClients -A25 | |
| AUTH_PATH="/dex/auth" | |
| TOKEN_PATH="/dex/token" | |
| OUT_FILE="token.json" | |
| CODE="" | |
| REFRESH_TOKEN="" | |
| QUIET=0 | |
| CURL_OPTS=() # holds curl flags (e.g., -k for insecure) | |
| usage() { | |
| cat <<EOF | |
| Usage: | |
| $0 --address <mke-address> [options] | |
| Flags: | |
| -a, --address string Address of the MKE 4k cluster, e.g. my-mke-cluster.example.com [REQUIRED] | |
| (If no scheme is provided, https:// will be prefixed automatically.) | |
| Options: | |
| --client-id ID Dex client_id (default: ${CLIENT_ID}) | |
| --scopes "..." OAuth scopes (default: ${SCOPES}) | |
| --redirect-uri URL Redirect URI registered in Dex (default: ${REDIRECT_URI}) | |
| --auth-path PATH Auth endpoint path (default: ${AUTH_PATH}) | |
| --token-path PATH Token endpoint path (default: ${TOKEN_PATH}) | |
| --out FILE Where to write token JSON (default: ${OUT_FILE}) | |
| --code CODE Provide the authorization code directly (skip browser step) | |
| --refresh TOKEN Use refresh_token grant to rotate tokens | |
| -k, --insecure Skip TLS verification for curl (testing only) | |
| -q, --quiet Suppress extra output; only write ${OUT_FILE} | |
| -h, --help Show this help | |
| Examples: | |
| # Interactive PKCE (copy/paste code; OOB redirect) | |
| $0 --address 3d1wgb-mke4-lb-9fc5efb34d95595b.elb.us-east-2.amazonaws.com | |
| # Refresh later without browser: | |
| $0 -a 3d1wgb-mke4-lb-9fc5efb34d95595b.elb.us-east-2.amazonaws.com --refresh \$(jq -r .refresh_token token.json) | |
| # Ignore TLS errors (testing only): | |
| $0 -a 3d1wgb-mke4-lb-9fc5efb34d95595b.elb.us-east-2.amazonaws.com --insecure | |
| EOF | |
| } | |
| # tiny URL encoder (no python/jq) | |
| urlencode() { | |
| local s="$1" i c o="" | |
| for (( i=0; i<${#s}; i++ )); do | |
| c="${s:$i:1}" | |
| case "$c" in | |
| [a-zA-Z0-9.~_-]) o+="$c" ;; | |
| *) printf -v o '%s%%%02X' "$o" "'$c" ;; | |
| esac | |
| done | |
| printf '%s' "$o" | |
| } | |
| have_jq() { command -v jq >/dev/null 2>&1; } | |
| # parse args | |
| while [[ $# -gt 0 ]]; do | |
| case "$1" in | |
| -a|--address) ADDRESS="$2"; shift 2;; | |
| --client-id) CLIENT_ID="$2"; shift 2;; | |
| --scopes) SCOPES="$2"; shift 2;; | |
| --redirect-uri) REDIRECT_URI="$2"; shift 2;; | |
| --auth-path) AUTH_PATH="$2"; shift 2;; | |
| --token-path) TOKEN_PATH="$2"; shift 2;; | |
| --out) OUT_FILE="$2"; shift 2;; | |
| --code) CODE="$2"; shift 2;; | |
| --refresh) REFRESH_TOKEN="$2"; shift 2;; | |
| -k|--insecure) CURL_OPTS+=(-k); shift;; | |
| -q|--quiet) QUIET=1; shift;; | |
| -h|--help) usage; exit 0;; | |
| *) echo "Unknown arg: $1" >&2; usage; exit 1;; | |
| esac | |
| done | |
| if [[ -z "$ADDRESS" ]]; then | |
| echo "Error: --address is required" >&2 | |
| usage; exit 1 | |
| fi | |
| # Normalize ADDRESS → HOST with scheme, then trim trailing slash | |
| if [[ "$ADDRESS" =~ ^https?:// ]]; then | |
| HOST="$ADDRESS" | |
| else | |
| HOST="https://$ADDRESS" | |
| fi | |
| HOST="${HOST%/}" | |
| AUTH_URL_BASE="${HOST}${AUTH_PATH}" | |
| TOKEN_URL="${HOST}${TOKEN_PATH}" | |
| # ========================= | |
| # Refresh token flow (if requested) | |
| # ========================= | |
| if [[ -n "$REFRESH_TOKEN" ]]; then | |
| [[ $QUIET -eq 0 ]] && echo "Refreshing access token via ${TOKEN_URL} ..." | |
| RESP="$(curl "${CURL_OPTS[@]}" -sS -X POST "${TOKEN_URL}" \ | |
| -H "Content-Type: application/x-www-form-urlencoded" \ | |
| -d "grant_type=refresh_token" \ | |
| -d "refresh_token=${REFRESH_TOKEN}" \ | |
| -d "client_id=${CLIENT_ID}")" | |
| echo "$RESP" > "$OUT_FILE" | |
| if have_jq; then | |
| ACCESS=$(jq -r '.access_token // empty' "$OUT_FILE") | |
| REFRESH=$(jq -r '.refresh_token // empty' "$OUT_FILE") | |
| else | |
| ACCESS=$(sed -n 's/.*"access_token":"\([^"]*\)".*/\1/p' "$OUT_FILE") | |
| REFRESH=$(sed -n 's/.*"refresh_token":"\([^"]*\)".*/\1/p' "$OUT_FILE") | |
| fi | |
| [[ $QUIET -eq 0 ]] && { | |
| echo "Wrote tokens to ${OUT_FILE}" | |
| [[ -n "$ACCESS" ]] && echo "Access token length: ${#ACCESS}" | |
| [[ -n "$REFRESH" ]] && echo "Refresh token length: ${#REFRESH}" | |
| echo | |
| echo "Try the Accounts API:" | |
| echo " curl -H \"Authorization: Bearer ${ACCESS}\" \"${HOST}/api/auth/v1/orgs\"" | |
| echo | |
| echo "Export helpers:" | |
| echo " export MKE_ACCESS_TOKEN='${ACCESS}'" | |
| [[ -n "$REFRESH" ]] && echo " export MKE_REFRESH_TOKEN='${REFRESH}'" | |
| } | |
| exit 0 | |
| fi | |
| # ========================= | |
| # PKCE Auth Code flow | |
| # ========================= | |
| # Generate PKCE verifier/challenge (URL-safe base64 without '=') | |
| VERIFIER="$(head -c 32 /dev/urandom | base64 | tr '+/' '-_' | tr -d '=')" | |
| CHALLENGE="$(printf %s "$VERIFIER" | openssl dgst -sha256 -binary | base64 | tr '+/' '-_' | tr -d '=')" | |
| SCOPES_ENC="$(printf %s "$SCOPES" | sed 's/ /%20/g')" | |
| REDIRECT_URI_ENC="$(urlencode "$REDIRECT_URI")" | |
| if [[ -z "$CODE" ]]; then | |
| AUTH_URL="${AUTH_URL_BASE}?client_id=${CLIENT_ID}&redirect_uri=${REDIRECT_URI_ENC}&response_type=code&scope=${SCOPES_ENC}&code_challenge=${CHALLENGE}&code_challenge_method=S256" | |
| [[ $QUIET -eq 0 ]] && { | |
| echo "Open this URL, log in, then copy the authorization code shown by Dex (OOB redirect):" | |
| echo | |
| echo " ${AUTH_URL}" | |
| echo | |
| } | |
| read -r -p "Paste authorization code here: " CODE | |
| fi | |
| [[ -z "$CODE" ]] && { echo "No code provided. Aborting." >&2; exit 1; } | |
| # Exchange code for tokens | |
| [[ $QUIET -eq 0 ]] && echo "Exchanging code for tokens at ${TOKEN_URL} ..." | |
| RESP="$(curl "${CURL_OPTS[@]}" -sS -X POST "${TOKEN_URL}" \ | |
| -H "Content-Type: application/x-www-form-urlencoded" \ | |
| -d "grant_type=authorization_code" \ | |
| -d "code=${CODE}" \ | |
| -d "client_id=${CLIENT_ID}" \ | |
| -d "redirect_uri=${REDIRECT_URI}" \ | |
| -d "code_verifier=${VERIFIER}")" | |
| echo "$RESP" > "$OUT_FILE" | |
| # Extract tokens (jq preferred; sed fallback) | |
| if have_jq; then | |
| ACCESS=$(jq -r '.access_token // empty' "$OUT_FILE") | |
| REFRESH=$(jq -r '.refresh_token // empty' "$OUT_FILE") | |
| IDTOK=$(jq -r '.id_token // empty' "$OUT_FILE") | |
| else | |
| ACCESS=$(echo "$RESP" | sed -n 's/.*"access_token":"\([^"]*\)".*/\1/p') | |
| REFRESH=$(echo "$RESP" | sed -n 's/.*"refresh_token":"\([^"]*\)".*/\1/p') | |
| IDTOK=$(echo "$RESP" | sed -n 's/.*"id_token":"\([^"]*\)".*/\1/p') | |
| fi | |
| [[ $QUIET -eq 0 ]] && { | |
| echo "Wrote tokens to ${OUT_FILE}" | |
| [[ -n "$ACCESS" ]] && echo "Access token length: ${#ACCESS}" | |
| [[ -n "$REFRESH" ]] && echo "Refresh token length: ${#REFRESH}" | |
| echo | |
| echo "Use with Accounts API (example):" | |
| echo " curl -H \"Authorization: Bearer ${ACCESS}\" \"${HOST}/api/auth/v1/orgs\"" | |
| echo | |
| echo "Export helpers:" | |
| echo " export MKE_ACCESS_TOKEN='${ACCESS}'" | |
| [[ -n "$REFRESH" ]] && echo " export MKE_REFRESH_TOKEN='${REFRESH}'" | |
| [[ -n "$IDTOK" ]] && echo " export MKE_ID_TOKEN='${IDTOK}'" | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment