diff --git a/connector/microsoft/TESTING.md b/connector/microsoft/TESTING.md new file mode 100644 index 00000000..f9e8e7c8 --- /dev/null +++ b/connector/microsoft/TESTING.md @@ -0,0 +1,422 @@ +# Testing the Microsoft Connector + +This guide covers how to test the Microsoft connector with both client secret and client assertion authentication methods. + +## Prerequisites + +- `az` CLI installed and logged in (`az login`) +- `openssl` (for generating keypairs) +- Dex built locally (`make build examples`) +- `jq` (for JSON parsing) +- `kubectl` - for testing using Federated Credential + +## Setup Azure AD Application + +First, create an Azure AD application that will be used for testing: + +```bash +# Set variables +APP_NAME="dex-test-$(date +%s)" +REDIRECT_URI="http://127.0.0.1:5556/dex/callback" + +# Create the application +APP_JSON=$(az ad app create \ + --display-name "${APP_NAME}" \ + --sign-in-audience AzureADMyOrg \ + --web-redirect-uris "${REDIRECT_URI}" \ + --query '{appId:appId,displayName:displayName}' \ + -o json) + +APP_ID=$(echo "${APP_JSON}" | jq -r .appId) + +# Get your tenant ID +TENANT_ID=$(az account show --query tenantId -o tsv) +``` + +Add Microsoft Graph API permissions: + +```bash +# Add User.Read and Directory.Read.All permissions +az ad app permission add \ + --id "${APP_ID}" \ + --api 00000003-0000-0000-c000-000000000000 \ + --api-permissions \ + e1fe6dd8-ba31-4d61-89e7-88639da4683d=Scope \ + 06da0dbc-49e2-44d2-8312-53f166ab848a=Scope + +# Note: Admin consent may be required for Directory.Read.All +# You can grant it via Azure Portal or with admin permissions: +az ad app permission admin-consent --id "${APP_ID}" +``` + +## Method 1: Testing with Client Secret + +### Create Client Secret + +```bash +# Create a client secret (expires in 1 year) +SECRET_JSON=$(az ad app credential reset \ + --id "${APP_ID}" \ + --append \ + --years 1 \ + --query '{secret:password}' \ + -o json) + +CLIENT_SECRET=$(echo "${SECRET_JSON}" | jq -r '.secret') +``` + +### Create Dex Configuration for Client Secret + +```bash +# Create temporary config file with client secret +CONFIG_FILE=$(mktemp -t dex-config-secret.yaml) +cat > "${CONFIG_FILE}" < "${KEYS_DIR}/generate-jwt.sh" <<'SCRIPT' +#!/bin/bash +set -e + +PRIVATE_KEY="$1" +CERT="$2" +APP_ID="$3" +TENANT_ID="$4" + +if [[ -z "${PRIVATE_KEY}" || -z "${CERT}" || -z "${APP_ID}" || -z "${TENANT_ID}" ]]; then + echo "Usage: $0 " + exit 1 +fi + +# Base64URL encode function +base64url() { + openssl base64 -e -A | tr '+/' '-_' | tr -d '=' +} + +# Get certificate thumbprint for x5t header +X5T=$(openssl x509 -in "${CERT}" -fingerprint -noout -sha1 | \ + sed 's/://g' | cut -d= -f2 | xxd -r -p | base64url) + +# JWT Header +HEADER=$(echo -n "{\"alg\":\"RS256\",\"typ\":\"JWT\",\"x5t\":\"${X5T}\"}" | base64url) + +# JWT Claims +NOW=$(date +%s) +EXP=$((NOW + 3600)) # Expires in 1 hour +JTI=$(uuidgen 2>/dev/null || cat /proc/sys/kernel/random/uuid 2>/dev/null || echo "$(date +%s)-$$") + +CLAIMS=$(cat < "${KEYS_DIR}/assertion.jwt" + +``` + +### Create Dex Configuration for Client Assertion + +```bash +# Create temporary config file with client assertion +CONFIG_FILE=$(mktemp -t dex-config-assertion.XXXXXX.yaml) +cat > "${CONFIG_FILE}" < "${KEYS_DIR}/assertion.jwt" + +# Terminal 1: Start Dex +./bin/dex serve "${CONFIG_FILE}" + +# Terminal 2: Start example app +./bin/example-app --issuer http://127.0.0.1:5556/dex + +# Open browser to http://127.0.0.1:5555 and test login +echo "Test the config with the following:" +echo "Authenticate for: example-app" +echo "Connector ID: microsoft-assertion" + +# When done, remove the temporary files +rm "${CONFIG_FILE}" +rm -rf "${KEYS_DIR}" +``` + +## Method 3: Testing with Client Assertion Using Kubernetes Workload Identity + +If you have a Kubernetes cluster with a publicly available OIDC issuer configured for service accounts: + +### Create Service Account + +```bash +kubectl create serviceaccount dex-test -n default +``` + +### Configure Federated Credential in Azure + +```bash +# Get your Kubernetes OIDC issuer +K8S_ISSUER=$(kubectl get --raw /.well-known/openid-configuration | jq -r '.issuer') + +# Create federated credential +az ad app federated-credential create \ + --id "${APP_ID}" \ + --parameters "{ + \"name\": \"k8s-dex-test\", + \"issuer\": \"${K8S_ISSUER}\", + \"subject\": \"system:serviceaccount:default:dex-test\", + \"audiences\": [\"api://AzureADTokenExchange\"] + }" +``` + +### Generate Kubernetes Token + +```bash +# Create temporary file for the Kubernetes token +K8S_TOKEN_FILE=$(mktemp -t k8s-token.jwt) + +# Create token with correct audience +kubectl create token dex-test \ + -n default \ + --duration=1h \ + --audience=api://AzureADTokenExchange \ + > "${K8S_TOKEN_FILE}" +``` + +### Create Dex Configuration for Kubernetes + +```bash +# Create temporary config file with Kubernetes token +CONFIG_FILE=$(mktemp -t dex-config-k8s.yaml) +cat > "${CONFIG_FILE}" <