From 652fce93b09673ecf4525f2262660c09d4940a8b Mon Sep 17 00:00:00 2001 From: chrislu Date: Sun, 24 Aug 2025 14:58:08 -0700 Subject: [PATCH] feat: add comprehensive S3 IAM integration tests GitHub Action This GitHub Action provides comprehensive testing coverage for the SeaweedFS IAM system including STS, policy engine, roles, and S3 API integration. ### Test Coverage: #### IAM Unit Tests: - STS service tests (token generation, validation, providers) - Policy engine tests (evaluation, storage, distribution) - Integration tests (role management, cross-component) - S3 API IAM middleware tests #### S3 IAM Integration Tests (3 test types): - Basic: Authentication, token validation, basic workflows - Advanced: Session expiration, multipart uploads, presigned URLs - Policy Enforcement: IAM policies, bucket policies, contextual rules #### Keycloak Integration Tests: - Real OIDC provider integration via Docker Compose - End-to-end authentication flow with Keycloak - Claims mapping and role-based access control - Only runs on master pushes or when Keycloak files change #### Distributed IAM Tests: - Cross-instance token validation - Persistent storage (filer-based stores) - Configuration consistency across instances - Only runs on master pushes to avoid PR overhead #### Performance Tests: - IAM component benchmarks - Load testing for authentication flows - Memory and performance profiling - Only runs on master pushes ### Workflow Features: - Path-based triggering (only runs when IAM code changes) - Matrix strategy for comprehensive coverage - Proper service startup/shutdown with health checks - Detailed logging and artifact upload on failures - Timeout protection and resource cleanup - Docker Compose integration for complex scenarios ### CI/CD Integration: - Runs on pull requests for core functionality - Extended tests on master branch pushes - Artifact preservation for debugging failed tests - Efficient concurrency control to prevent conflicts --- .github/workflows/s3-iam-tests.yml | 386 +++++++++++++++++++++++++++++ 1 file changed, 386 insertions(+) create mode 100644 .github/workflows/s3-iam-tests.yml diff --git a/.github/workflows/s3-iam-tests.yml b/.github/workflows/s3-iam-tests.yml new file mode 100644 index 000000000..5ba3acf58 --- /dev/null +++ b/.github/workflows/s3-iam-tests.yml @@ -0,0 +1,386 @@ +name: "S3 IAM Integration Tests" + +on: + pull_request: + paths: + - 'weed/iam/**' + - 'weed/s3api/**' + - 'test/s3/iam/**' + - '.github/workflows/s3-iam-tests.yml' + push: + branches: [ master ] + paths: + - 'weed/iam/**' + - 'weed/s3api/**' + - 'test/s3/iam/**' + - '.github/workflows/s3-iam-tests.yml' + +concurrency: + group: ${{ github.head_ref }}/s3-iam-tests + cancel-in-progress: true + +permissions: + contents: read + +defaults: + run: + working-directory: weed + +jobs: + # Unit tests for IAM components + iam-unit-tests: + name: IAM Unit Tests + runs-on: ubuntu-22.04 + timeout-minutes: 15 + + steps: + - name: Check out code + uses: actions/checkout@v5 + + - name: Set up Go + uses: actions/setup-go@v5 + with: + go-version-file: 'go.mod' + id: go + + - name: Get dependencies + run: | + go mod download + + - name: Run IAM Unit Tests + timeout-minutes: 10 + run: | + set -x + echo "=== Running IAM STS Tests ===" + go test -v -timeout 5m ./iam/sts/... + + echo "=== Running IAM Policy Tests ===" + go test -v -timeout 5m ./iam/policy/... + + echo "=== Running IAM Integration Tests ===" + go test -v -timeout 5m ./iam/integration/... + + echo "=== Running S3 API IAM Tests ===" + go test -v -timeout 5m ./s3api/... -run ".*IAM.*|.*JWT.*|.*Auth.*" + + - name: Upload test results on failure + if: failure() + uses: actions/upload-artifact@v4 + with: + name: iam-unit-test-results + path: | + weed/testdata/ + weed/**/testdata/ + retention-days: 3 + + # S3 IAM integration tests with SeaweedFS services + s3-iam-integration-tests: + name: S3 IAM Integration Tests + runs-on: ubuntu-22.04 + timeout-minutes: 25 + strategy: + matrix: + test-type: ["basic", "advanced", "policy-enforcement"] + + steps: + - name: Check out code + uses: actions/checkout@v5 + + - name: Set up Go + uses: actions/setup-go@v5 + with: + go-version-file: 'go.mod' + id: go + + - name: Install SeaweedFS + working-directory: weed + run: | + go install -buildvcs=false + + - name: Run S3 IAM Integration Tests - ${{ matrix.test-type }} + timeout-minutes: 20 + working-directory: test/s3/iam + run: | + set -x + echo "=== System Information ===" + uname -a + free -h + df -h + echo "=== Starting S3 IAM Integration Tests (${{ matrix.test-type }}) ===" + + # Set WEED_BINARY to use the installed version + export WEED_BINARY=$(which weed) + export TEST_TIMEOUT=15m + + # Run tests based on type + case "${{ matrix.test-type }}" in + "basic") + echo "Running basic IAM functionality tests..." + make clean setup start-services wait-for-services + go test -v -timeout 15m -run "TestS3IAMAuthentication|TestS3IAMBasicWorkflow|TestS3IAMTokenValidation" ./... + ;; + "advanced") + echo "Running advanced IAM feature tests..." + make clean setup start-services wait-for-services + go test -v -timeout 15m -run "TestS3IAMSessionExpiration|TestS3IAMMultipart|TestS3IAMPresigned" ./... + ;; + "policy-enforcement") + echo "Running policy enforcement tests..." + make clean setup start-services wait-for-services + go test -v -timeout 15m -run "TestS3IAMPolicyEnforcement|TestS3IAMBucketPolicy|TestS3IAMContextual" ./... + ;; + esac + + # Always cleanup + make stop-services + + - name: Show service logs on failure + if: failure() + working-directory: test/s3/iam + run: | + echo "=== Service Logs ===" + echo "--- Master Log ---" + tail -50 weed-master.log 2>/dev/null || echo "No master log found" + echo "" + echo "--- Filer Log ---" + tail -50 weed-filer.log 2>/dev/null || echo "No filer log found" + echo "" + echo "--- Volume Log ---" + tail -50 weed-volume.log 2>/dev/null || echo "No volume log found" + echo "" + echo "--- S3 API Log ---" + tail -50 weed-s3.log 2>/dev/null || echo "No S3 log found" + echo "" + + echo "=== Process Information ===" + ps aux | grep -E "(weed|test)" || true + netstat -tlnp | grep -E "(8333|8888|9333|8080)" || true + + - name: Upload test logs on failure + if: failure() + uses: actions/upload-artifact@v4 + with: + name: s3-iam-integration-logs-${{ matrix.test-type }} + path: test/s3/iam/weed-*.log + retention-days: 5 + + # Keycloak integration tests with Docker Compose + s3-iam-keycloak-tests: + name: S3 IAM Keycloak Integration + runs-on: ubuntu-22.04 + timeout-minutes: 30 + # Only run on master branch pushes or when Keycloak-related files change + if: | + github.event_name == 'push' && github.ref == 'refs/heads/master' || + contains(github.event.pull_request.changed_files, 'test/s3/iam/keycloak') || + contains(github.event.pull_request.changed_files, 'test/s3/iam/docker-compose') || + contains(github.event.pull_request.changed_files, 'test/s3/iam/s3_keycloak') + + steps: + - name: Check out code + uses: actions/checkout@v5 + + - name: Set up Go + uses: actions/setup-go@v5 + with: + go-version-file: 'go.mod' + id: go + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Build SeaweedFS IAM Image + working-directory: test/s3/iam + run: | + echo "Building custom SeaweedFS image with IAM support..." + docker build -f Dockerfile.s3 -t seaweedfs-iam:latest ../../.. + + - name: Start Keycloak and SeaweedFS Services + working-directory: test/s3/iam + run: | + echo "Starting services with Docker Compose..." + docker compose up -d + + echo "Waiting for Keycloak to be ready..." + timeout 120 bash -c 'until curl -s http://localhost:8080/realms/seaweedfs-test/.well-known/openid-configuration > /dev/null; do sleep 5; done' || { + echo "Keycloak failed to start" + docker compose logs keycloak + exit 1 + } + + echo "Waiting for SeaweedFS S3 API to be ready..." + timeout 60 bash -c 'until curl -s http://localhost:8333 > /dev/null 2>&1; do sleep 3; done' || { + echo "SeaweedFS S3 API failed to start" + docker compose logs s3 + exit 1 + } + + echo "All services are ready" + + - name: Run Keycloak Integration Tests + timeout-minutes: 20 + working-directory: test/s3/iam + run: | + set -x + echo "=== Running Keycloak Integration Tests ===" + + export KEYCLOAK_URL="http://localhost:8080" + export S3_ENDPOINT="http://localhost:8333" + + # Give services extra time to fully initialize + sleep 15 + + # Run Keycloak-specific tests + go test -v -timeout 15m -run "TestKeycloak" ./... || { + echo "❌ Keycloak integration tests failed" + echo "=== Service Logs ===" + docker compose logs --tail=100 + exit 1 + } + + - name: Show Docker logs on failure + if: failure() + working-directory: test/s3/iam + run: | + echo "=== Docker Compose Service Logs ===" + docker compose logs --tail=200 + + echo "=== Container Status ===" + docker compose ps + + echo "=== Network Information ===" + docker network ls + curl -v http://localhost:8080/realms/seaweedfs-test/.well-known/openid-configuration || true + curl -v http://localhost:8333 || true + + - name: Cleanup Docker Services + if: always() + working-directory: test/s3/iam + run: | + echo "Stopping Docker Compose services..." + docker compose down -v --remove-orphans + docker image prune -f + + - name: Upload Docker logs on failure + if: failure() + uses: actions/upload-artifact@v4 + with: + name: s3-iam-keycloak-logs + path: test/s3/iam/docker-*.log + retention-days: 5 + + # Distributed IAM tests + s3-iam-distributed-tests: + name: S3 IAM Distributed Tests + runs-on: ubuntu-22.04 + timeout-minutes: 25 + # Only run on master branch pushes to avoid overloading PR testing + if: github.event_name == 'push' && github.ref == 'refs/heads/master' + + steps: + - name: Check out code + uses: actions/checkout@v5 + + - name: Set up Go + uses: actions/setup-go@v5 + with: + go-version-file: 'go.mod' + id: go + + - name: Install SeaweedFS + working-directory: weed + run: | + go install -buildvcs=false + + - name: Run Distributed IAM Tests + timeout-minutes: 20 + working-directory: test/s3/iam + run: | + set -x + echo "=== System Information ===" + uname -a + free -h + + export WEED_BINARY=$(which weed) + export TEST_TIMEOUT=15m + + # Test distributed configuration + echo "Testing distributed IAM configuration..." + make clean setup + + # Start services with distributed IAM config + echo "Starting services with distributed configuration..." + make start-services + make wait-for-services + + # Run distributed-specific tests + go test -v -timeout 15m -run "TestDistributed|TestCrossInstance|TestPersistence" ./... || { + echo "❌ Distributed tests failed, checking logs..." + make logs + exit 1 + } + + make stop-services + + - name: Upload distributed test logs + if: always() + uses: actions/upload-artifact@v4 + with: + name: s3-iam-distributed-logs + path: test/s3/iam/weed-*.log + retention-days: 7 + + # Performance and stress tests + s3-iam-performance-tests: + name: S3 IAM Performance Tests + runs-on: ubuntu-22.04 + timeout-minutes: 30 + # Only run on master branch pushes to avoid overloading PR testing + if: github.event_name == 'push' && github.ref == 'refs/heads/master' + + steps: + - name: Check out code + uses: actions/checkout@v5 + + - name: Set up Go + uses: actions/setup-go@v5 + with: + go-version-file: 'go.mod' + id: go + + - name: Install SeaweedFS + working-directory: weed + run: | + go install -buildvcs=false + + - name: Run IAM Performance Benchmarks + timeout-minutes: 25 + working-directory: test/s3/iam + run: | + set -x + echo "=== Running IAM Performance Tests ===" + + export WEED_BINARY=$(which weed) + export TEST_TIMEOUT=20m + + make clean setup start-services wait-for-services + + # Run performance benchmarks + echo "Running performance benchmarks..." + go test -bench=. -benchmem -timeout 20m ./... || { + echo "❌ Performance tests failed" + make logs + exit 1 + } + + make stop-services + + - name: Upload performance test results + if: always() + uses: actions/upload-artifact@v4 + with: + name: s3-iam-performance-results + path: | + test/s3/iam/weed-*.log + test/s3/iam/*.test + retention-days: 7