#!/bin/bash # Test script to verify Temporal authorization setup set -e echo "==================================" echo "Temporal Authorization Test Script" echo "==================================" echo "" # Colors for output GREEN='\033[0;32m' RED='\033[0;31m' YELLOW='\033[1;33m' NC='\033[0m' # No Color # Function to print colored output print_success() { echo -e "${GREEN}✓ $1${NC}" } print_error() { echo -e "${RED}✗ $1${NC}" } print_warning() { echo -e "${YELLOW}⚠ $1${NC}" } print_info() { echo "ℹ $1" } # Check if required tools are installed echo "Checking prerequisites..." command -v jq >/dev/null 2>&1 || { print_error "jq is not installed. Install with: apt-get install jq"; exit 1; } command -v curl >/dev/null 2>&1 || { print_error "curl is not installed."; exit 1; } print_success "Prerequisites OK" echo "" # Configuration read -p "Enter Keycloak URL (e.g., https://keycloak.example.com): " KEYCLOAK_URL read -p "Enter Realm name: " REALM read -p "Enter Client ID (e.g., temporal-ui): " CLIENT_ID read -sp "Enter Client Secret: " CLIENT_SECRET echo "" read -p "Enter test username: " USERNAME read -sp "Enter test password: " PASSWORD echo "" echo "" # Get token from Keycloak print_info "Requesting token from Keycloak..." TOKEN_ENDPOINT="${KEYCLOAK_URL}/realms/${REALM}/protocol/openid-connect/token" RESPONSE=$(curl -s -X POST "$TOKEN_ENDPOINT" \ -d "client_id=${CLIENT_ID}" \ -d "client_secret=${CLIENT_SECRET}" \ -d "grant_type=password" \ -d "username=${USERNAME}" \ -d "password=${PASSWORD}") if [ $? -ne 0 ]; then print_error "Failed to connect to Keycloak" exit 1 fi # Check for errors if echo "$RESPONSE" | jq -e '.error' >/dev/null 2>&1; then print_error "Authentication failed:" echo "$RESPONSE" | jq '.error_description' exit 1 fi # Extract access token ACCESS_TOKEN=$(echo "$RESPONSE" | jq -r '.access_token') if [ "$ACCESS_TOKEN" == "null" ] || [ -z "$ACCESS_TOKEN" ]; then print_error "Failed to get access token" echo "$RESPONSE" exit 1 fi print_success "Successfully obtained access token" echo "" # Decode and display JWT print_info "Decoding JWT token..." echo "" # Split token into header, payload, signature IFS='.' read -ra TOKEN_PARTS <<< "$ACCESS_TOKEN" # Decode header HEADER=$(echo "${TOKEN_PARTS[0]}" | base64 -d 2>/dev/null || echo "${TOKEN_PARTS[0]}" | base64 -d -i 2>/dev/null) echo "JWT Header:" echo "$HEADER" | jq '.' 2>/dev/null || echo "$HEADER" echo "" # Decode payload PAYLOAD=$(echo "${TOKEN_PARTS[1]}" | base64 -d 2>/dev/null || echo "${TOKEN_PARTS[1]}" | base64 -d -i 2>/dev/null) echo "JWT Payload:" echo "$PAYLOAD" | jq '.' 2>/dev/null || echo "$PAYLOAD" echo "" # Extract relevant claims print_info "Checking for Temporal authorization claims..." echo "" # Check for permissions claim PERMISSIONS=$(echo "$PAYLOAD" | jq -r '.permissions // empty' 2>/dev/null) if [ ! -z "$PERMISSIONS" ] && [ "$PERMISSIONS" != "null" ]; then print_success "Found 'permissions' claim" echo "Permissions:" echo "$PAYLOAD" | jq '.permissions' echo "" else print_warning "No 'permissions' claim found in JWT" echo "Temporal requires a 'permissions' array in the JWT token." echo "Each permission should be in the format: 'namespace:role'" echo "" fi # Check for groups claim GROUPS=$(echo "$PAYLOAD" | jq -r '.groups // empty' 2>/dev/null) if [ ! -z "$GROUPS" ] && [ "$GROUPS" != "null" ]; then print_info "Found 'groups' claim:" echo "$PAYLOAD" | jq '.groups' echo "" else print_warning "No 'groups' claim found" echo "" fi # Check for roles claim ROLES=$(echo "$PAYLOAD" | jq -r '.roles // empty' 2>/dev/null) if [ ! -z "$ROLES" ] && [ "$ROLES" != "null" ]; then print_info "Found 'roles' claim:" echo "$PAYLOAD" | jq '.roles' echo "" else print_warning "No 'roles' claim found" echo "" fi # Check token expiration EXP=$(echo "$PAYLOAD" | jq -r '.exp // empty' 2>/dev/null) if [ ! -z "$EXP" ]; then CURRENT_TIME=$(date +%s) TIME_LEFT=$((EXP - CURRENT_TIME)) if [ $TIME_LEFT -gt 0 ]; then print_success "Token is valid (expires in $((TIME_LEFT / 60)) minutes)" else print_error "Token has expired!" fi echo "" fi # Check issuer ISSUER=$(echo "$PAYLOAD" | jq -r '.iss // empty' 2>/dev/null) if [ ! -z "$ISSUER" ]; then print_info "Token issuer: $ISSUER" echo "" fi # Verify JWKS endpoint is accessible print_info "Verifying JWKS endpoint..." JWKS_URL="${ISSUER}/protocol/openid-connect/certs" JWKS_RESPONSE=$(curl -s "$JWKS_URL") if echo "$JWKS_RESPONSE" | jq -e '.keys' >/dev/null 2>&1; then KEY_COUNT=$(echo "$JWKS_RESPONSE" | jq '.keys | length') print_success "JWKS endpoint accessible ($KEY_COUNT keys available)" echo "JWKS URL: $JWKS_URL" else print_error "JWKS endpoint not accessible or invalid response" echo "URL: $JWKS_URL" echo "Response: $JWKS_RESPONSE" fi echo "" # Test Temporal Server connection (optional) read -p "Do you want to test connection to Temporal Server? (y/n): " TEST_TEMPORAL if [ "$TEST_TEMPORAL" == "y" ]; then read -p "Enter Temporal Server address (e.g., localhost:7233): " TEMPORAL_ADDR print_info "Testing Temporal Server connection..." # Try to list namespaces with the token # Note: This requires grpcurl to be installed if command -v grpcurl >/dev/null 2>&1; then RESULT=$(grpcurl -plaintext \ -H "authorization: Bearer $ACCESS_TOKEN" \ -d '{"pageSize": 10}' \ "$TEMPORAL_ADDR" \ temporal.api.workflowservice.v1.WorkflowService/ListNamespaces 2>&1) if echo "$RESULT" | grep -q "PermissionDenied"; then print_warning "Server rejected request (PermissionDenied)" echo "This likely means authorization is working but the user lacks permissions." echo "Check that the 'permissions' claim in the JWT matches your Temporal namespaces." elif echo "$RESULT" | grep -q "namespaces"; then print_success "Successfully connected to Temporal Server!" echo "User has access to namespaces." else print_error "Unexpected response from Temporal Server:" echo "$RESULT" fi else print_warning "grpcurl not installed, skipping Temporal Server test" echo "Install grpcurl to test server connection: https://github.com/fullstorydev/grpcurl" fi fi echo "" # Summary echo "==================================" echo "Summary" echo "==================================" echo "" if [ ! -z "$PERMISSIONS" ] && [ "$PERMISSIONS" != "null" ]; then print_success "JWT token contains 'permissions' claim - ready for Temporal authorization!" echo "" echo "Next steps:" echo "1. Verify the permissions match your Temporal namespace names" echo "2. Deploy the custom Temporal server with authorization enabled" echo "3. Test access with different user groups" else print_warning "JWT token does NOT contain 'permissions' claim" echo "" echo "Next steps:" echo "1. Configure Keycloak protocol mapper to add 'permissions' claim" echo "2. Map user groups/roles to permissions in format: 'namespace:role'" echo "3. Re-run this test script to verify" echo "" echo "See: custom-server/example-keycloak-mapper.json for an example" fi echo "" echo "==================================" echo "Full JWT Token (for debugging):" echo "==================================" echo "$ACCESS_TOKEN" echo ""