* feat: add S3 bucket size and object count metrics Adds periodic collection of bucket size metrics: - SeaweedFS_s3_bucket_size_bytes: logical size (deduplicated across replicas) - SeaweedFS_s3_bucket_physical_size_bytes: physical size (including replicas) - SeaweedFS_s3_bucket_object_count: object count (deduplicated) Collection runs every 1 minute via background goroutine that queries filer Statistics RPC for each bucket's collection. Also adds Grafana dashboard panels for: - S3 Bucket Size (logical vs physical) - S3 Bucket Object Count * address PR comments: fix bucket size metrics collection 1. Fix collectCollectionInfoFromMaster to use master VolumeList API - Now properly queries master for topology info - Uses WithMasterClient to get volume list from master - Correctly calculates logical vs physical size based on replication 2. Return error when filerClient is nil to trigger fallback - Changed from 'return nil, nil' to 'return nil, error' - Ensures fallback to filer stats is properly triggered 3. Implement pagination in listBucketNames - Added listBucketPageSize constant (1000) - Uses StartFromFileName for pagination - Continues fetching until fewer entries than limit returned 4. Handle NewReplicaPlacementFromByte error and prevent division by zero - Check error return from NewReplicaPlacementFromByte - Default to 1 copy if error occurs - Add explicit check for copyCount == 0 * simplify bucket size metrics: remove filer fallback, align with quota enforcement - Remove fallback to filer Statistics RPC - Use only master topology for collection info (same as s3.bucket.quota.enforce) - Updated comments to clarify this runs the same collection logic as quota enforcement - Simplified code by removing collectBucketSizeFromFilerStats * use s3a.option.Masters directly instead of querying filer * address PR comments: fix dashboard overlaps and improve metrics collection Grafana dashboard fixes: - Fix overlapping panels 55 and 59 in grafana_seaweedfs.json (moved 59 to y=30) - Fix grid collision in k8s dashboard (moved panel 72 to y=48) - Aggregate bucket metrics with max() by (bucket) for multi-instance S3 gateways Go code improvements: - Add graceful shutdown support via context cancellation - Use ticker instead of time.Sleep for better shutdown responsiveness - Distinguish EOF from actual errors in stream handling * improve bucket size metrics: multi-master failover and proper error handling - Initial delay now respects context cancellation using select with time.After - Use WithOneOfGrpcMasterClients for multi-master failover instead of hardcoding Masters[0] - Properly propagate stream errors instead of just logging them (EOF vs real errors) * improve bucket size metrics: distributed lock and volume ID deduplication - Add distributed lock (LiveLock) so only one S3 instance collects metrics at a time - Add IsLocked() method to LiveLock for checking lock status - Fix deduplication: use volume ID tracking instead of dividing by copyCount - Previous approach gave wrong results if replicas were missing - Now tracks seen volume IDs and counts each volume only once - Physical size still includes all replicas for accurate disk usage reporting * rename lock to s3.leader * simplify: remove StartBucketSizeMetricsCollection wrapper function * fix data race: use atomic operations for LiveLock.isLocked field - Change isLocked from bool to int32 - Use atomic.LoadInt32/StoreInt32 for all reads/writes - Sync shared isLocked field in StartLongLivedLock goroutine * add nil check for topology info to prevent panic * fix bucket metrics: use Ticker for consistent intervals, fix pagination logic - Use time.Ticker instead of time.After for consistent interval execution - Fix pagination: count all entries (not just directories) for proper termination - Update lastFileName for all entries to prevent pagination issues * address PR comments: remove redundant atomic store, propagate context - Remove redundant atomic.StoreInt32 in StartLongLivedLock (AttemptToLock already sets it) - Propagate context through metrics collection for proper cancellation on shutdown - collectAndUpdateBucketSizeMetrics now accepts ctx - collectCollectionInfoFromMaster uses ctx for VolumeList RPC - listBucketNames uses ctx for ListEntries RPC
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
- S3 API Gateway - SeaweedFS S3-compatible API server with IAM integration
- IAM Manager - Core IAM orchestration and policy evaluation
- STS Service - Security Token Service for temporary credentials
- Policy Engine - AWS IAM-compatible policy evaluation
- Identity Providers - OIDC and LDAP authentication providers
- 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
- Go 1.19+ with modules enabled
- SeaweedFS Binary (
weed) built with IAM support - 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
-
Create Test Function:
func TestS3IAMNewFeature(t *testing.T) { framework := NewS3IAMTestFramework(t) defer framework.Cleanup() // Test implementation } -
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) -
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
-
Mock Provider Setup:
// In test framework func (f *S3IAMTestFramework) setupCustomProvider() { provider := custom.NewCustomProvider("test-custom") // Configure and register } -
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:
-
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() -
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
-
Follow Test Patterns:
- Use
S3IAMTestFrameworkfor setup - Include cleanup with
defer framework.Cleanup() - Use descriptive test names and subtests
- Assert both success and failure cases
- Use
-
Update Documentation:
- Add test descriptions to this README
- Include Makefile targets for new test categories
- Document any new configuration options
-
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:
- Check Logs: Use
make logsto inspect service logs - Verify Configuration: Ensure
test_config.jsonis correct - Test Services: Run
make statusto check service health - Clean Environment: Try
make clean && make test
License
This test suite is part of the SeaweedFS project and follows the same licensing terms.