diff --git a/.github/workflows/s3-iam-keycloak.yml b/.github/workflows/s3-iam-keycloak.yml deleted file mode 100644 index d90e13139..000000000 --- a/.github/workflows/s3-iam-keycloak.yml +++ /dev/null @@ -1,59 +0,0 @@ -name: S3 IAM Keycloak Integration - -on: - workflow_dispatch: - pull_request: - paths: - - 'test/s3/iam/**' - - 'weed/**' - - 'go.mod' - - 'go.sum' - -jobs: - keycloak-integration: - runs-on: ubuntu-latest - timeout-minutes: 60 - - steps: - - name: Checkout - uses: actions/checkout@v4 - - - name: Setup Go - uses: actions/setup-go@v5 - with: - go-version-file: go.mod - cache: true - - - name: Install dependencies - run: sudo apt-get update -y && sudo apt-get install -y jq - - - name: Build weed binary - run: | - mkdir -p "$HOME/go/bin" - go build -o "$HOME/go/bin/weed" ./weed - - - name: Configure Keycloak (repo script only) - env: - PATH: ${{ env.PATH }}:$HOME/go/bin - run: | - bash test/s3/iam/setup_keycloak.sh - - - name: Start SeaweedFS services - env: - WEED_BINARY: ${{ github.workspace }}/weed - run: | - export WEED_BINARY="$HOME/go/bin/weed" - make -C test/s3/iam start-services wait-for-services - - - name: Run Keycloak integration tests - env: - KEYCLOAK_URL: http://localhost:8080 - run: | - go test -v -timeout 15m -run "TestKeycloak" ./... - - - name: Stop services - if: always() - run: | - make -C test/s3/iam stop-services - - diff --git a/test/s3/iam/setup_keycloak.sh b/test/s3/iam/setup_keycloak.sh index f4ba48b41..aef988be1 100755 --- a/test/s3/iam/setup_keycloak.sh +++ b/test/s3/iam/setup_keycloak.sh @@ -173,363 +173,3 @@ main() { } main "$@" - -#!/bin/bash - -# Keycloak Setup Script for CI/CD -# This script sets up a Keycloak realm with test users and roles for SeaweedFS S3 IAM testing - -set -e - -KEYCLOAK_URL="${KEYCLOAK_URL:-http://localhost:8080}" -# Support both old and new Keycloak environment variable formats -ADMIN_USER="${KC_BOOTSTRAP_ADMIN_USERNAME:-${KEYCLOAK_ADMIN:-admin}}" -ADMIN_PASSWORD="${KC_BOOTSTRAP_ADMIN_PASSWORD:-${KEYCLOAK_ADMIN_PASSWORD:-admin}}" -REALM_NAME="seaweedfs-test" -CLIENT_ID="seaweedfs-s3" -CLIENT_SECRET="seaweedfs-s3-secret" - -echo "🔧 Setting up Keycloak realm and users for SeaweedFS S3 IAM testing..." -echo "Keycloak URL: $KEYCLOAK_URL" - -# Function to get admin access token with retry logic -get_admin_token() { - local max_attempts=5 - local attempt=1 - - while [ $attempt -le $max_attempts ]; do - echo "🔑 Getting admin access token (attempt $attempt/$max_attempts)..." - - local response=$(curl -s -X POST "$KEYCLOAK_URL/realms/master/protocol/openid-connect/token" \ - -H "Content-Type: application/x-www-form-urlencoded" \ - -d "username=$ADMIN_USER" \ - -d "password=$ADMIN_PASSWORD" \ - -d "grant_type=password" \ - -d "client_id=admin-cli" 2>/dev/null || echo '{"error":"curl_failed"}') - - local token=$(echo "$response" | jq -r '.access_token // empty' 2>/dev/null || echo "") - - if [ -n "$token" ] && [ "$token" != "null" ] && [ "$token" != "" ]; then - echo "✅ Successfully obtained admin token" - echo "$token" - return 0 - fi - - echo "⚠️ Failed to get token (attempt $attempt). Response: $response" - - if [ $attempt -eq $max_attempts ]; then - echo "❌ Failed to get admin access token after $max_attempts attempts" - echo "🔍 Checking Keycloak status..." - curl -s "$KEYCLOAK_URL/realms/master" || echo "Keycloak master realm not accessible" - return 1 - fi - - echo "⏳ Waiting 5 seconds before retry..." - sleep 5 - attempt=$((attempt + 1)) - done -} - -# Function to check if realm exists -realm_exists() { - local token=$1 - curl -s -H "Authorization: Bearer $token" \ - "$KEYCLOAK_URL/admin/realms/$REALM_NAME" \ - -o /dev/null -w "%{http_code}" | grep -q "200" -} - -# Function to create realm -create_realm() { - local token=$1 - echo "📝 Creating realm: $REALM_NAME" - - local payload=$(jq -n \ - --arg realm "$REALM_NAME" \ - '{ - "realm": $realm, - "enabled": true, - "displayName": "SeaweedFS Test Realm", - "accessTokenLifespan": 3600, - "sslRequired": "none" - }') - - local http_code=$(curl -s -w "%{http_code}" -X POST "$KEYCLOAK_URL/admin/realms" \ - -H "Authorization: Bearer $token" \ - -H "Content-Type: application/json" \ - -d "$payload" \ - -o /tmp/realm_response.json) - - local response=$(cat /tmp/realm_response.json 2>/dev/null || echo "") - - if [[ "$http_code" == "201" ]]; then - echo "✅ Realm created successfully" - return 0 - else - echo "❌ Realm creation failed with HTTP $http_code" - echo "📋 Response: $response" - return 1 - fi -} - -# Function to create client -create_client() { - local token=$1 - echo "📝 Creating client: $CLIENT_ID" - - local payload=$(jq -n \ - --arg clientId "$CLIENT_ID" \ - --arg secret "$CLIENT_SECRET" \ - '{ - "clientId": $clientId, - "enabled": true, - "publicClient": false, - "secret": $secret, - "directAccessGrantsEnabled": true, - "serviceAccountsEnabled": true, - "standardFlowEnabled": true, - "implicitFlowEnabled": false, - "redirectUris": ["*"], - "webOrigins": ["*"] - }') - - local http_code=$(curl -s -w "%{http_code}" -X POST "$KEYCLOAK_URL/admin/realms/$REALM_NAME/clients" \ - -H "Authorization: Bearer $token" \ - -H "Content-Type: application/json" \ - -d "$payload" \ - -o /tmp/client_response.json) - - local response=$(cat /tmp/client_response.json 2>/dev/null || echo "") - - if [[ "$http_code" == "201" ]]; then - echo "✅ Client created successfully" - return 0 - else - echo "❌ Client creation failed with HTTP $http_code" - echo "📋 Response: $response" - return 1 - fi -} - -# Function to create role -create_role() { - local token=$1 - local role_name=$2 - local role_description=$3 - - echo "📝 Creating role: $role_name" - - local payload=$(jq -n \ - --arg name "$role_name" \ - --arg description "$role_description" \ - '{ - "name": $name, - "description": $description - }') - - local http_code=$(curl -s -w "%{http_code}" -X POST "$KEYCLOAK_URL/admin/realms/$REALM_NAME/roles" \ - -H "Authorization: Bearer $token" \ - -H "Content-Type: application/json" \ - -d "$payload" \ - -o /tmp/role_response_$role_name.json) - - local response=$(cat /tmp/role_response_$role_name.json 2>/dev/null || echo "") - - if [[ "$http_code" == "201" ]]; then - echo "✅ Role '$role_name' created successfully" - return 0 - else - echo "❌ Role '$role_name' creation failed with HTTP $http_code" - echo "📋 Response: $response" - return 1 - fi -} - -# Function to create user -create_user() { - local token=$1 - local username=$2 - local password=$3 - local email=$4 - local first_name=$5 - local last_name=$6 - local roles=$7 - - echo "📝 Creating user: $username" - - # Create user - local user_payload=$(jq -n \ - --arg username "$username" \ - --arg email "$email" \ - --arg firstName "$first_name" \ - --arg lastName "$last_name" \ - --arg password "$password" \ - '{ - "username": $username, - "email": $email, - "firstName": $firstName, - "lastName": $lastName, - "enabled": true, - "emailVerified": true, - "credentials": [{ - "type": "password", - "value": $password, - "temporary": false - }] - }') - - local http_code=$(curl -s -w "%{http_code}" -X POST "$KEYCLOAK_URL/admin/realms/$REALM_NAME/users" \ - -H "Authorization: Bearer $token" \ - -H "Content-Type: application/json" \ - -d "$user_payload" \ - -o /tmp/user_response_$username.json) - - local user_response=$(cat /tmp/user_response_$username.json 2>/dev/null || echo "") - - if [[ "$http_code" == "201" ]]; then - echo "✅ User '$username' created successfully" - else - echo "❌ User '$username' creation failed with HTTP $http_code" - echo "📋 Response: $user_response" - return 1 - fi - - # Get user ID - local user_id=$(curl -s -H "Authorization: Bearer $token" \ - "$KEYCLOAK_URL/admin/realms/$REALM_NAME/users?username=$username" | \ - jq -r '.[0].id') - - # Assign roles - if [ -n "$roles" ]; then - echo "📝 Assigning roles to $username: $roles" - IFS=',' read -ra ROLE_ARRAY <<< "$roles" - for role in "${ROLE_ARRAY[@]}"; do - # Get role representation - local role_rep=$(curl -s -H "Authorization: Bearer $token" \ - "$KEYCLOAK_URL/admin/realms/$REALM_NAME/roles/$role") - - # Assign role to user - curl -s -X POST "$KEYCLOAK_URL/admin/realms/$REALM_NAME/users/$user_id/role-mappings/realm" \ - -H "Authorization: Bearer $token" \ - -H "Content-Type: application/json" \ - -d "[$role_rep]" - done - fi -} - -# Main setup process -main() { - echo "🚀 Starting Keycloak setup..." - - # Wait for Keycloak to be ready with better health checking - echo "⏳ Waiting for Keycloak to be ready..." - timeout 300 bash -c ' - while true; do - # Try health endpoint first (if available) - if curl -s http://localhost:8080/health/ready > /dev/null 2>&1; then - echo "✅ Keycloak health check passed" - break - fi - - # Fallback to master realm check - if curl -s $KEYCLOAK_URL/realms/master > /dev/null 2>&1; then - echo "✅ Keycloak master realm accessible" - break - fi - - echo "Still waiting for Keycloak..." - sleep 5 - done - ' || { - echo "❌ Keycloak is not ready after 300 seconds" - exit 1 - } - - # Additional wait for admin user to be fully set up - echo "⏳ Waiting for admin user to be fully initialized..." - sleep 10 - - # Get admin token - ADMIN_TOKEN=$(get_admin_token) - if [ -z "$ADMIN_TOKEN" ] || [ "$ADMIN_TOKEN" = "null" ]; then - echo "❌ Failed to get admin access token" - exit 1 - fi - - # Create realm if it doesn't exist - if ! realm_exists "$ADMIN_TOKEN"; then - if ! create_realm "$ADMIN_TOKEN"; then - echo "❌ Failed to create realm $REALM_NAME" - exit 1 - fi - sleep 2 - - # Wait for realm to be fully available - echo "⏳ Waiting for realm to be fully initialized..." - timeout 60 bash -c " - while ! curl -fs $KEYCLOAK_URL/realms/$REALM_NAME/.well-known/openid-configuration >/dev/null 2>&1; do - echo ' ... waiting for realm endpoint' - sleep 3 - done - " || { - echo "❌ Realm $REALM_NAME not accessible after creation" - exit 1 - } - echo "✅ Realm is now accessible" - else - echo "✅ Realm $REALM_NAME already exists" - fi - - # Create client - if ! create_client "$ADMIN_TOKEN"; then - echo "❌ Failed to create client $CLIENT_ID" - exit 1 - fi - sleep 1 - - # Create roles - if ! create_role "$ADMIN_TOKEN" "s3-admin" "SeaweedFS S3 Administrator"; then - echo "❌ Failed to create s3-admin role" - exit 1 - fi - if ! create_role "$ADMIN_TOKEN" "s3-read-only" "SeaweedFS S3 Read-Only User"; then - echo "❌ Failed to create s3-read-only role" - exit 1 - fi - if ! create_role "$ADMIN_TOKEN" "s3-write-only" "SeaweedFS S3 Write-Only User"; then - echo "❌ Failed to create s3-write-only role" - exit 1 - fi - if ! create_role "$ADMIN_TOKEN" "s3-read-write" "SeaweedFS S3 Read-Write User"; then - echo "❌ Failed to create s3-read-write role" - exit 1 - fi - sleep 1 - - # Create test users - if ! create_user "$ADMIN_TOKEN" "admin-user" "admin123" "admin@seaweedfs.test" "Admin" "User" "s3-admin"; then - echo "❌ Failed to create admin-user" - exit 1 - fi - if ! create_user "$ADMIN_TOKEN" "read-user" "read123" "read@seaweedfs.test" "Read" "User" "s3-read-only"; then - echo "❌ Failed to create read-user" - exit 1 - fi - if ! create_user "$ADMIN_TOKEN" "write-user" "write123" "write@seaweedfs.test" "Write" "User" "s3-write-only"; then - echo "❌ Failed to create write-user" - exit 1 - fi - - echo "✅ Keycloak setup completed successfully!" - echo "🔗 Realm: $KEYCLOAK_URL/realms/$REALM_NAME" - echo "👥 Test users created:" - echo " - admin-user (password: admin123) - s3-admin role" - echo " - read-user (password: read123) - s3-read-only role" - echo " - write-user (password: write123) - s3-write-only role" - echo "🔑 Client: $CLIENT_ID (secret: $CLIENT_SECRET)" - - # Cleanup temporary files - rm -f /tmp/realm_response.json /tmp/client_response.json /tmp/role_response_*.json /tmp/user_response_*.json -} - -# Run main function -main "$@"