Files
seaweedfs/test/s3/iam
Chris LuandGitHub e77f8ae204 fix(s3api): route STS GetFederationToken to STS handler (#9157) (#9167)
* fix(s3api): route STS GetFederationToken requests to STS handler (#9157)

The STS GetFederationToken handler was implemented but never reachable.
Three routing gaps sent requests to the S3/IAM path instead of STS:

- No explicit mux route for Action=GetFederationToken in the URL query
- iamMatcher did not exclude GetFederationToken, so authenticated POSTs
  with Action in the form body were matched and dispatched to IAM
- UnifiedPostHandler only dispatched AssumeRole* and GetCallerIdentity
  to STS, leaving GetFederationToken to fall through to DoActions and
  return NotImplemented

Add the missing route, the matcher exclusion, and the dispatch branch.

Also wire TestSTS, TestAssumeRoleWithWebIdentity, and TestServiceAccount
into the s3-iam-tests workflow as a new "sts" matrix entry. Before this
change, none of test/s3/iam/s3_sts_get_federation_token_test.go's four
test functions ran in CI, which is why this regression shipped.

* test(iam): make orphaned STS/service-account tests pass under auth-enabled CI

Follow-up to wiring STS tests into CI: fixes several pre-existing issues
that made the newly-included tests fail locally.

Server fixes:
- weed/s3api/s3api_sts.go: handleGetFederationToken no longer 500s when
  the caller is a legacy S3-config identity (not in the IAM user store).
  Previously any GetPoliciesForUser error short-circuited to InternalError,
  which hard-failed every SigV4 caller using keys from -s3.config.
- weed/s3api/s3api_embedded_iam.go: CreateServiceAccount now generates IDs
  in the sa:<parent>:<uuid> format required by
  credential.ValidateServiceAccountId. The old "sa-XXXXXXXX" format failed
  the persistence-layer regex and caused every CreateServiceAccount call
  to return 500 once a filer-backed credential store validated the ID.

Test helpers:
- test/s3/iam/s3_sts_assume_role_test.go: callSTSAPIWithSigV4 no longer
  sets req.Header["Host"]. aws-sdk-go v1 v4.Signer already signs Host from
  req.URL.Host, and a manual Host header made the signer emit host;host in
  SignedHeaders, producing SignatureDoesNotMatch. Updated missing_role_arn
  subtest to match the existing SeaweedFS behavior (user-context
  assumption).
- test/s3/iam/s3_service_account_test.go: callIAMAPI now SigV4-signs
  requests when STS_TEST_{ACCESS,SECRET}_KEY env vars are set. Unsigned
  IAM writes otherwise fall through to the STS fallback and return
  InvalidAction.

CI matrix:
- .github/workflows/s3-iam-tests.yml: skip
  TestServiceAccountLifecycle/use_service_account_credentials only. The
  rest of the service-account suite passes; that one subtest depends on a
  separate credential-reload issue where new ABIA keys briefly register
  into accessKeyIdent but aren't persisted to the filer, so they vanish
  on the next reload. Out of scope for the #9157 GetFederationToken fix.

* fix(credential): accept AWS IAM username chars in service-account IDs

Gemini review on #9167 pointed out that ServiceAccountIdPattern's
parent-user segment was more restrictive than an AWS IAM username:
`[A-Za-z0-9_-]` vs. IAM's `[\w+=,.@-]`. Realistic usernames with
`@`, `.`, `+`, `=`, or `,` (e.g. email-style principals) would fail
validation at the filer store even though the embedded IAM API
happily created them.

Broaden the regex to `[A-Za-z0-9_+=,.@-]` (matching the AWS IAM spec
at https://docs.aws.amazon.com/IAM/latest/APIReference/API_User.html)
and add a table-driven test that locks the expansion in.

* address PR review feedback on #9167

All five review items were valid; changes keyed to review bullets:

- weed/s3api/s3api_sts.go: handleGetFederationToken no longer swallows
  arbitrary policy-lookup failures. Only credential.ErrUserNotFound is
  treated leniently (the legacy-config SigV4 path); any other error now
  returns InternalError so we don't mint tokens with an incomplete
  policy set.
- weed/credential/grpc/grpc_identity.go: GetUser translates gRPC
  NotFound back to credential.ErrUserNotFound so errors.Is(...) above
  matches for gRPC-backed stores, not just memory/filer-direct.
- weed/s3api/s3api_embedded_iam.go: CreateServiceAccount now validates
  the generated saId against credential.ValidateServiceAccountId before
  returning. Surfaces a client 400 with the offending ID instead of the
  opaque 500 that used to bubble up from the persistence layer.
- weed/s3api/s3api_server_routing_test.go: seed a routing-test identity
  with a known AK/SK, sign TestRouting_GetFederationTokenAuthenticatedBody
  with aws-sdk-go v4.Signer so the request actually passes
  AuthSignatureOnly. Assert 503 ServiceUnavailable (from STSHandlers
  with no stsService) instead of just NotEqual(501) — 503 proves the
  dispatch reached STSHandlers.HandleSTSRequest.
- test/s3/iam/s3_service_account_test.go: callIAMAPI signs with
  service="iam" instead of "s3" (SeaweedFS verifies against whichever
  service the client signed with, but "iam" is semantically correct).
- weed/credential/validation_test.go: add positive rows for an
  uppercase parent (sa:ALICE:...) and a canonical hyphenated UUID
  suffix (sa:alice:123e4567-e89b-12d3-a456-426614174000).
2026-04-20 19:33:22 -07:00
..
2026-03-09 23:10:27 -07:00
2026-03-09 11:54:32 -07:00
2025-11-12 22:14:50 -08:00
2025-10-13 18:05:17 -07:00
2025-10-13 18:05:17 -07:00

SeaweedFS S3 IAM Integration Tests

This directory contains comprehensive integration tests for the SeaweedFS S3 API with Advanced IAM (Identity and Access Management) system integration.

Overview

Important: The STS service uses a stateless JWT design where all session information is embedded directly in the JWT token. No external session storage is required.

The S3 IAM integration tests validate the complete end-to-end functionality of:

  • JWT Authentication: OIDC token-based authentication with S3 API
  • Policy Enforcement: Fine-grained access control for S3 operations
  • Stateless Session Management: JWT-based session token validation and expiration (no external storage)
  • Role-Based Access Control (RBAC): IAM roles with different permission levels
  • Bucket Policies: Resource-based access control integration
  • Multipart Upload IAM: Policy enforcement for multipart operations
  • Contextual Policies: IP-based, time-based, and conditional access control
  • Presigned URLs: IAM-integrated temporary access URL generation

Test Architecture

Components Tested

  1. S3 API Gateway - SeaweedFS S3-compatible API server with IAM integration
  2. IAM Manager - Core IAM orchestration and policy evaluation
  3. STS Service - Security Token Service for temporary credentials
  4. Policy Engine - AWS IAM-compatible policy evaluation
  5. Identity Providers - OIDC and LDAP authentication providers
  6. Policy Store - Persistent policy storage using SeaweedFS filer

Test Framework

  • S3IAMTestFramework: Comprehensive test utilities and setup
  • Mock OIDC Provider: In-memory OIDC server with JWT signing
  • Service Management: Automatic SeaweedFS service lifecycle management
  • Resource Cleanup: Automatic cleanup of buckets and test data

Test Scenarios

1. Authentication Tests (TestS3IAMAuthentication)

  • Valid JWT Token: Successful authentication with proper OIDC tokens
  • Invalid JWT Token: Rejection of malformed or invalid tokens
  • Expired JWT Token: Proper handling of expired authentication tokens

2. Policy Enforcement Tests (TestS3IAMPolicyEnforcement)

  • Read-Only Policy: Users can only read objects and list buckets
  • Write-Only Policy: Users can only create/delete objects but not read
  • Admin Policy: Full access to all S3 operations including bucket management

3. Session Expiration Tests (TestS3IAMSessionExpiration)

  • Short-Lived Sessions: Creation and validation of time-limited sessions
  • Manual Expiration: Testing session expiration enforcement
  • Expired Session Rejection: Proper access denial for expired sessions

4. Multipart Upload Tests (TestS3IAMMultipartUploadPolicyEnforcement)

  • Admin Multipart Access: Full multipart upload capabilities
  • Read-Only Denial: Rejection of multipart operations for read-only users
  • Complete Upload Flow: Initiate → Upload Parts → Complete workflow

5. Bucket Policy Tests (TestS3IAMBucketPolicyIntegration)

  • Public Read Policy: Bucket-level policies allowing public access
  • Explicit Deny Policy: Bucket policies that override IAM permissions
  • Policy CRUD Operations: Get/Put/Delete bucket policy operations

6. Contextual Policy Tests (TestS3IAMContextualPolicyEnforcement)

  • 🔧 IP-Based Restrictions: Source IP validation in policy conditions
  • 🔧 Time-Based Restrictions: Temporal access control policies
  • 🔧 User-Agent Restrictions: Request context-based policy evaluation

7. Presigned URL Tests (TestS3IAMPresignedURLIntegration)

  • URL Generation: IAM-validated presigned URL creation
  • Permission Validation: Ensuring users have required permissions
  • 🔧 HTTP Request Testing: Direct HTTP calls to presigned URLs

Quick Start

Prerequisites

  1. Go 1.19+ with modules enabled
  2. SeaweedFS Binary (weed) built with IAM support
  3. Test Dependencies:
    go get github.com/stretchr/testify
    go get github.com/aws/aws-sdk-go
    go get github.com/golang-jwt/jwt/v5
    

Running Tests

Complete Test Suite

# Run all tests with service management
make test

# Quick test run (assumes services running)
make test-quick

Specific Test Categories

# Test only authentication
make test-auth

# Test only policy enforcement  
make test-policy

# Test only session expiration
make test-expiration

# Test only multipart uploads
make test-multipart

# Test only bucket policies
make test-bucket-policy

Development & Debugging

# Start services and keep running
make debug

# Show service logs
make logs

# Check service status
make status

# Watch for changes and re-run tests
make watch

Manual Service Management

If you prefer to manage services manually:

# Start services
make start-services

# Wait for services to be ready
make wait-for-services

# Run tests
make run-tests

# Stop services
make stop-services

Configuration

Test Configuration (test_config.json)

The test configuration defines:

  • Identity Providers: OIDC and LDAP configurations
  • IAM Roles: Role definitions with trust policies
  • IAM Policies: Permission policies for different access levels
  • Policy Stores: Persistent storage configurations for IAM policies and roles

Service Ports

Service Port Purpose
Master 9333 Cluster coordination
Volume 8080 Object storage
Filer 8888 Metadata & IAM storage
S3 API 8333 S3-compatible API with IAM

Environment Variables

# SeaweedFS binary location
export WEED_BINARY=../../../weed

# Service ports (optional)
export S3_PORT=8333
export FILER_PORT=8888  
export MASTER_PORT=9333
export VOLUME_PORT=8080

# Test timeout
export TEST_TIMEOUT=30m

# Log level (0-4)
export LOG_LEVEL=2

Test Data & Cleanup

Automatic Cleanup

The test framework automatically:

  • 🗑️ Deletes test buckets created during tests
  • 🗑️ Removes test objects and multipart uploads
  • 🗑️ Cleans up IAM sessions and temporary tokens
  • 🗑️ Stops services after test completion

Manual Cleanup

# Clean everything
make clean

# Clean while keeping services running
rm -rf test-volume-data/

Extending Tests

Adding New Test Scenarios

  1. Create Test Function:

    func TestS3IAMNewFeature(t *testing.T) {
        framework := NewS3IAMTestFramework(t)
        defer framework.Cleanup()
    
        // Test implementation
    }
    
  2. Use Test Framework:

    // Create authenticated S3 client
    s3Client, err := framework.CreateS3ClientWithJWT("user", "TestRole")
    require.NoError(t, err)
    
    // Test S3 operations
    err = framework.CreateBucket(s3Client, "test-bucket")
    require.NoError(t, err)
    
  3. Add to Makefile:

    test-new-feature: ## Test new feature
    	go test -v -run TestS3IAMNewFeature ./...
    

Creating Custom Policies

Add policies to test_config.json:

{
  "policies": {
    "CustomPolicy": {
      "Version": "2012-10-17",
      "Statement": [
        {
          "Effect": "Allow",
          "Action": ["s3:GetObject"],
          "Resource": ["arn:aws:s3:::specific-bucket/*"],
          "Condition": {
            "StringEquals": {
              "s3:prefix": ["allowed-prefix/"]
            }
          }
        }
      ]
    }
  }
}

Adding Identity Providers

  1. Mock Provider Setup:

    // In test framework
    func (f *S3IAMTestFramework) setupCustomProvider() {
        provider := custom.NewCustomProvider("test-custom")
        // Configure and register
    }
    
  2. Configuration:

    {
      "providers": {
        "custom": {
          "test-custom": {
            "endpoint": "http://localhost:8080",
            "clientId": "custom-client"
          }
        }
      }
    }
    

Troubleshooting

Common Issues

1. Services Not Starting

# Check if ports are available
netstat -an | grep -E "(8333|8888|9333|8080)"

# Check service logs
make logs

# Try different ports
export S3_PORT=18333
make start-services

2. JWT Token Issues

# Verify OIDC mock server
curl http://localhost:8080/.well-known/openid_configuration

# Check JWT token format in logs
make logs | grep -i jwt

3. Permission Denied Errors

# Verify IAM configuration
cat test_config.json | jq '.policies'

# Check policy evaluation in logs  
export LOG_LEVEL=4
make start-services

4. Test Timeouts

# Increase timeout
export TEST_TIMEOUT=60m
make test

# Run individual tests
make test-auth

Debug Mode

Start services in debug mode to inspect manually:

# Start and keep running
make debug

# In another terminal, run specific operations
aws s3 ls --endpoint-url http://localhost:8333

# Stop when done (Ctrl+C in debug terminal)

Log Analysis

# Service-specific logs
tail -f weed-s3.log       # S3 API server
tail -f weed-filer.log    # Filer (IAM storage)  
tail -f weed-master.log   # Master server
tail -f weed-volume.log   # Volume server

# Filter for IAM-related logs
make logs | grep -i iam
make logs | grep -i jwt
make logs | grep -i policy

Performance Testing

Benchmarks

# Run performance benchmarks
make benchmark

# Profile memory usage  
go test -bench=. -memprofile=mem.prof
go tool pprof mem.prof

Load Testing

For load testing with IAM:

  1. Create Multiple Clients:

    // Generate multiple JWT tokens
    tokens := framework.GenerateMultipleJWTTokens(100)
    
    // Create concurrent clients
    var wg sync.WaitGroup
    for _, token := range tokens {
        wg.Add(1)
        go func(token string) {
            defer wg.Done()
            // Perform S3 operations
        }(token)
    }
    wg.Wait()
    
  2. Measure Performance:

    # Run with verbose output
    go test -v -bench=BenchmarkS3IAMOperations
    

CI/CD Integration

GitHub Actions

name: S3 IAM Integration Tests
on: [push, pull_request]

jobs:
  s3-iam-test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - uses: actions/setup-go@v3
        with:
          go-version: '1.19'
      
      - name: Build SeaweedFS
        run: go build -o weed ./main.go
      
      - name: Run S3 IAM Tests  
        run: |
          cd test/s3/iam
          make ci

Jenkins Pipeline

pipeline {
    agent any
    stages {
        stage('Build') {
            steps {
                sh 'go build -o weed ./main.go'
            }
        }
        stage('S3 IAM Tests') {
            steps {
                dir('test/s3/iam') {
                    sh 'make ci'
                }
            }
            post {
                always {
                    dir('test/s3/iam') {
                        sh 'make clean'
                    }
                }
            }
        }
    }
}

Contributing

Adding New Tests

  1. Follow Test Patterns:

    • Use S3IAMTestFramework for setup
    • Include cleanup with defer framework.Cleanup()
    • Use descriptive test names and subtests
    • Assert both success and failure cases
  2. Update Documentation:

    • Add test descriptions to this README
    • Include Makefile targets for new test categories
    • Document any new configuration options
  3. Ensure Test Reliability:

    • Tests should be deterministic and repeatable
    • Include proper error handling and assertions
    • Use appropriate timeouts for async operations

Code Style

  • Follow standard Go testing conventions
  • Use require.NoError() for critical assertions
  • Use assert.Equal() for value comparisons
  • Include descriptive error messages in assertions

Support

For issues with S3 IAM integration tests:

  1. Check Logs: Use make logs to inspect service logs
  2. Verify Configuration: Ensure test_config.json is correct
  3. Test Services: Run make status to check service health
  4. Clean Environment: Try make clean && make test

License

This test suite is part of the SeaweedFS project and follows the same licensing terms.