aboutsummaryrefslogtreecommitdiff
path: root/test/s3/iam
diff options
context:
space:
mode:
Diffstat (limited to 'test/s3/iam')
-rw-r--r--test/s3/iam/docker-compose-simple.yml2
-rw-r--r--test/s3/iam/docker-compose.test.yml2
-rw-r--r--test/s3/iam/docker-compose.yml2
-rwxr-xr-xtest/s3/iam/run_all_tests.sh14
-rwxr-xr-xtest/s3/iam/run_performance_tests.sh2
-rwxr-xr-xtest/s3/iam/run_stress_tests.sh2
-rw-r--r--test/s3/iam/s3_iam_distributed_test.go4
-rw-r--r--test/s3/iam/s3_iam_framework.go22
-rw-r--r--test/s3/iam/s3_iam_integration_test.go92
-rwxr-xr-xtest/s3/iam/setup_all_tests.sh32
-rwxr-xr-xtest/s3/iam/setup_keycloak.sh64
-rwxr-xr-xtest/s3/iam/setup_keycloak_docker.sh26
12 files changed, 130 insertions, 134 deletions
diff --git a/test/s3/iam/docker-compose-simple.yml b/test/s3/iam/docker-compose-simple.yml
index 9e3b91e42..b52a158a3 100644
--- a/test/s3/iam/docker-compose-simple.yml
+++ b/test/s3/iam/docker-compose-simple.yml
@@ -1,5 +1,3 @@
-version: '3.8'
-
services:
# Keycloak Identity Provider
keycloak:
diff --git a/test/s3/iam/docker-compose.test.yml b/test/s3/iam/docker-compose.test.yml
index e759f63dc..bb229cfc3 100644
--- a/test/s3/iam/docker-compose.test.yml
+++ b/test/s3/iam/docker-compose.test.yml
@@ -1,6 +1,4 @@
# Docker Compose for SeaweedFS S3 IAM Integration Tests
-version: '3.8'
-
services:
# SeaweedFS Master
seaweedfs-master:
diff --git a/test/s3/iam/docker-compose.yml b/test/s3/iam/docker-compose.yml
index 9e9c00f6d..fd3e3039f 100644
--- a/test/s3/iam/docker-compose.yml
+++ b/test/s3/iam/docker-compose.yml
@@ -1,5 +1,3 @@
-version: '3.8'
-
services:
# Keycloak Identity Provider
keycloak:
diff --git a/test/s3/iam/run_all_tests.sh b/test/s3/iam/run_all_tests.sh
index f5c2cea59..7bb8ba956 100755
--- a/test/s3/iam/run_all_tests.sh
+++ b/test/s3/iam/run_all_tests.sh
@@ -34,10 +34,10 @@ run_test_category() {
echo -e "${YELLOW}๐Ÿงช Running $description...${NC}"
if go test -v -timeout=$TEST_TIMEOUT -run "$test_pattern" ./...; then
- echo -e "${GREEN}โœ… $description completed successfully${NC}"
+ echo -e "${GREEN}[OK] $description completed successfully${NC}"
return 0
else
- echo -e "${RED}โŒ $description failed${NC}"
+ echo -e "${RED}[FAIL] $description failed${NC}"
return 1
fi
}
@@ -83,10 +83,10 @@ fi
echo -e "\n${BLUE}5. Benchmark Tests${NC}"
TOTAL_CATEGORIES=$((TOTAL_CATEGORIES + 1))
if go test -bench=. -benchmem -timeout=$TEST_TIMEOUT ./...; then
- echo -e "${GREEN}โœ… Benchmark tests completed successfully${NC}"
+ echo -e "${GREEN}[OK] Benchmark tests completed successfully${NC}"
PASSED_CATEGORIES=$((PASSED_CATEGORIES + 1))
else
- echo -e "${RED}โŒ Benchmark tests failed${NC}"
+ echo -e "${RED}[FAIL] Benchmark tests failed${NC}"
fi
# 6. Versioning Stress Tests
@@ -94,10 +94,10 @@ echo -e "\n${BLUE}6. S3 Versioning Stress Tests${NC}"
TOTAL_CATEGORIES=$((TOTAL_CATEGORIES + 1))
if [ -f "../versioning/enable_stress_tests.sh" ]; then
if (cd ../versioning && ./enable_stress_tests.sh); then
- echo -e "${GREEN}โœ… Versioning stress tests completed successfully${NC}"
+ echo -e "${GREEN}[OK] Versioning stress tests completed successfully${NC}"
PASSED_CATEGORIES=$((PASSED_CATEGORIES + 1))
else
- echo -e "${RED}โŒ Versioning stress tests failed${NC}"
+ echo -e "${RED}[FAIL] Versioning stress tests failed${NC}"
fi
else
echo -e "${YELLOW}โš ๏ธ Versioning stress tests not available${NC}"
@@ -114,6 +114,6 @@ if [ $PASSED_CATEGORIES -eq $TOTAL_CATEGORIES ]; then
echo -e "\n${GREEN}๐ŸŽ‰ All test categories passed!${NC}"
exit 0
else
- echo -e "\n${RED}โŒ Some test categories failed${NC}"
+ echo -e "\n${RED}[FAIL] Some test categories failed${NC}"
exit 1
fi
diff --git a/test/s3/iam/run_performance_tests.sh b/test/s3/iam/run_performance_tests.sh
index 293632b2c..e8e8983fb 100755
--- a/test/s3/iam/run_performance_tests.sh
+++ b/test/s3/iam/run_performance_tests.sh
@@ -23,4 +23,4 @@ go test -bench=. -benchmem -timeout=$TEST_TIMEOUT ./...
echo -e "${YELLOW}๐Ÿงช Running performance test suite...${NC}"
go test -v -timeout=$TEST_TIMEOUT -run "TestS3IAMPerformanceTests" ./...
-echo -e "${GREEN}โœ… Performance tests completed${NC}"
+echo -e "${GREEN}[OK] Performance tests completed${NC}"
diff --git a/test/s3/iam/run_stress_tests.sh b/test/s3/iam/run_stress_tests.sh
index a302c4488..d7520012a 100755
--- a/test/s3/iam/run_stress_tests.sh
+++ b/test/s3/iam/run_stress_tests.sh
@@ -33,4 +33,4 @@ for i in $(seq 1 $STRESS_ITERATIONS); do
sleep 2
done
-echo -e "${GREEN}โœ… All stress test iterations completed successfully${NC}"
+echo -e "${GREEN}[OK] All stress test iterations completed successfully${NC}"
diff --git a/test/s3/iam/s3_iam_distributed_test.go b/test/s3/iam/s3_iam_distributed_test.go
index 545a56bcb..fbaf25e9d 100644
--- a/test/s3/iam/s3_iam_distributed_test.go
+++ b/test/s3/iam/s3_iam_distributed_test.go
@@ -243,7 +243,7 @@ func TestS3IAMDistributedTests(t *testing.T) {
// Report results
if len(errorList) == 0 {
- t.Logf("๐ŸŽ‰ All %d concurrent operations completed successfully with retry mechanisms!", totalOperations)
+ t.Logf("All %d concurrent operations completed successfully with retry mechanisms!", totalOperations)
} else {
t.Logf("Concurrent operations summary:")
t.Logf(" Total operations: %d", totalOperations)
@@ -262,7 +262,7 @@ func TestS3IAMDistributedTests(t *testing.T) {
// With proper retry mechanisms, we should expect near-zero failures
// Any remaining errors likely indicate real concurrency issues or system problems
if len(errorList) > 0 {
- t.Errorf("โŒ %d operation(s) failed even after retry mechanisms (%.1f%% failure rate). This indicates potential system issues or race conditions that need investigation.",
+ t.Errorf("%d operation(s) failed even after retry mechanisms (%.1f%% failure rate). This indicates potential system issues or race conditions that need investigation.",
len(errorList), float64(len(errorList))/float64(totalOperations)*100)
}
})
diff --git a/test/s3/iam/s3_iam_framework.go b/test/s3/iam/s3_iam_framework.go
index aee70e4a1..92e880bdc 100644
--- a/test/s3/iam/s3_iam_framework.go
+++ b/test/s3/iam/s3_iam_framework.go
@@ -333,7 +333,7 @@ func (t *BearerTokenTransport) extractPrincipalFromJWT(tokenString string) strin
// This is safe because the actual validation happens server-side
return []byte("dummy-key"), nil
})
-
+
// Even if parsing fails due to signature verification, we might still get claims
if claims, ok := token.Claims.(jwt.MapClaims); ok {
// Try multiple possible claim names for the principal ARN
@@ -348,7 +348,7 @@ func (t *BearerTokenTransport) extractPrincipalFromJWT(tokenString string) strin
}
}
}
-
+
return ""
}
@@ -693,13 +693,25 @@ func (f *S3IAMTestFramework) CreateBucketWithCleanup(s3Client *s3.S3, bucketName
if err != nil {
// If bucket already exists, clean it up first
- if awsErr, ok := err.(awserr.Error); ok && awsErr.Code() == "BucketAlreadyExists" {
+ if awsErr, ok := err.(awserr.Error); ok && (awsErr.Code() == "BucketAlreadyExists" || awsErr.Code() == "BucketAlreadyOwnedByYou") {
f.t.Logf("Bucket %s already exists, cleaning up first", bucketName)
- // Empty the existing bucket
+ // First try to delete the bucket completely
f.emptyBucket(s3Client, bucketName)
+ _, deleteErr := s3Client.DeleteBucket(&s3.DeleteBucketInput{
+ Bucket: aws.String(bucketName),
+ })
+ if deleteErr != nil {
+ f.t.Logf("Warning: Failed to delete existing bucket %s: %v", bucketName, deleteErr)
+ }
- // Don't need to recreate - bucket already exists and is now empty
+ // Now create it fresh
+ _, err = s3Client.CreateBucket(&s3.CreateBucketInput{
+ Bucket: aws.String(bucketName),
+ })
+ if err != nil {
+ return fmt.Errorf("failed to recreate bucket after cleanup: %v", err)
+ }
} else {
return err
}
diff --git a/test/s3/iam/s3_iam_integration_test.go b/test/s3/iam/s3_iam_integration_test.go
index 5c89bda6f..c7836c4bf 100644
--- a/test/s3/iam/s3_iam_integration_test.go
+++ b/test/s3/iam/s3_iam_integration_test.go
@@ -1,7 +1,6 @@
package iam
import (
- "bytes"
"fmt"
"io"
"strings"
@@ -15,15 +14,11 @@ import (
)
const (
- testEndpoint = "http://localhost:8333"
- testRegion = "us-west-2"
- testBucketPrefix = "test-iam-bucket"
- testObjectKey = "test-object.txt"
- testObjectData = "Hello, SeaweedFS IAM Integration!"
-)
-
-var (
- testBucket = testBucketPrefix
+ testEndpoint = "http://localhost:8333"
+ testRegion = "us-west-2"
+ testBucket = "test-iam-bucket"
+ testObjectKey = "test-object.txt"
+ testObjectData = "Hello, SeaweedFS IAM Integration!"
)
// TestS3IAMAuthentication tests S3 API authentication with IAM JWT tokens
@@ -98,12 +93,14 @@ func TestS3IAMPolicyEnforcement(t *testing.T) {
adminClient, err := framework.CreateS3ClientWithJWT("admin-user", "TestAdminRole")
require.NoError(t, err)
- err = framework.CreateBucket(adminClient, testBucket)
+ // Use unique bucket name to avoid collection conflicts
+ bucketName := framework.GenerateUniqueBucketName("test-iam-policy")
+ err = framework.CreateBucket(adminClient, bucketName)
require.NoError(t, err)
// Put test object with admin client
_, err = adminClient.PutObject(&s3.PutObjectInput{
- Bucket: aws.String(testBucket),
+ Bucket: aws.String(bucketName),
Key: aws.String(testObjectKey),
Body: strings.NewReader(testObjectData),
})
@@ -116,7 +113,7 @@ func TestS3IAMPolicyEnforcement(t *testing.T) {
// Should be able to read objects
result, err := readOnlyClient.GetObject(&s3.GetObjectInput{
- Bucket: aws.String(testBucket),
+ Bucket: aws.String(bucketName),
Key: aws.String(testObjectKey),
})
require.NoError(t, err)
@@ -128,7 +125,7 @@ func TestS3IAMPolicyEnforcement(t *testing.T) {
// Should be able to list objects
listResult, err := readOnlyClient.ListObjects(&s3.ListObjectsInput{
- Bucket: aws.String(testBucket),
+ Bucket: aws.String(bucketName),
})
require.NoError(t, err)
assert.Len(t, listResult.Contents, 1)
@@ -136,7 +133,7 @@ func TestS3IAMPolicyEnforcement(t *testing.T) {
// Should NOT be able to put objects
_, err = readOnlyClient.PutObject(&s3.PutObjectInput{
- Bucket: aws.String(testBucket),
+ Bucket: aws.String(bucketName),
Key: aws.String("forbidden-object.txt"),
Body: strings.NewReader("This should fail"),
})
@@ -147,7 +144,7 @@ func TestS3IAMPolicyEnforcement(t *testing.T) {
// Should NOT be able to delete objects
_, err = readOnlyClient.DeleteObject(&s3.DeleteObjectInput{
- Bucket: aws.String(testBucket),
+ Bucket: aws.String(bucketName),
Key: aws.String(testObjectKey),
})
require.Error(t, err)
@@ -166,7 +163,7 @@ func TestS3IAMPolicyEnforcement(t *testing.T) {
testWriteData := "Write-only test data"
_, err = writeOnlyClient.PutObject(&s3.PutObjectInput{
- Bucket: aws.String(testBucket),
+ Bucket: aws.String(bucketName),
Key: aws.String(testWriteKey),
Body: strings.NewReader(testWriteData),
})
@@ -174,14 +171,14 @@ func TestS3IAMPolicyEnforcement(t *testing.T) {
// Should be able to delete objects
_, err = writeOnlyClient.DeleteObject(&s3.DeleteObjectInput{
- Bucket: aws.String(testBucket),
+ Bucket: aws.String(bucketName),
Key: aws.String(testWriteKey),
})
require.NoError(t, err)
// Should NOT be able to read objects
_, err = writeOnlyClient.GetObject(&s3.GetObjectInput{
- Bucket: aws.String(testBucket),
+ Bucket: aws.String(bucketName),
Key: aws.String(testObjectKey),
})
require.Error(t, err)
@@ -191,7 +188,7 @@ func TestS3IAMPolicyEnforcement(t *testing.T) {
// Should NOT be able to list objects
_, err = writeOnlyClient.ListObjects(&s3.ListObjectsInput{
- Bucket: aws.String(testBucket),
+ Bucket: aws.String(bucketName),
})
require.Error(t, err)
if awsErr, ok := err.(awserr.Error); ok {
@@ -206,7 +203,7 @@ func TestS3IAMPolicyEnforcement(t *testing.T) {
// Should be able to put objects
_, err = adminClient.PutObject(&s3.PutObjectInput{
- Bucket: aws.String(testBucket),
+ Bucket: aws.String(bucketName),
Key: aws.String(testAdminKey),
Body: strings.NewReader(testAdminData),
})
@@ -214,7 +211,7 @@ func TestS3IAMPolicyEnforcement(t *testing.T) {
// Should be able to read objects
result, err := adminClient.GetObject(&s3.GetObjectInput{
- Bucket: aws.String(testBucket),
+ Bucket: aws.String(bucketName),
Key: aws.String(testAdminKey),
})
require.NoError(t, err)
@@ -226,14 +223,14 @@ func TestS3IAMPolicyEnforcement(t *testing.T) {
// Should be able to list objects
listResult, err := adminClient.ListObjects(&s3.ListObjectsInput{
- Bucket: aws.String(testBucket),
+ Bucket: aws.String(bucketName),
})
require.NoError(t, err)
assert.GreaterOrEqual(t, len(listResult.Contents), 1)
// Should be able to delete objects
_, err = adminClient.DeleteObject(&s3.DeleteObjectInput{
- Bucket: aws.String(testBucket),
+ Bucket: aws.String(bucketName),
Key: aws.String(testAdminKey),
})
require.NoError(t, err)
@@ -241,14 +238,14 @@ func TestS3IAMPolicyEnforcement(t *testing.T) {
// Should be able to delete buckets
// First delete remaining objects
_, err = adminClient.DeleteObject(&s3.DeleteObjectInput{
- Bucket: aws.String(testBucket),
+ Bucket: aws.String(bucketName),
Key: aws.String(testObjectKey),
})
require.NoError(t, err)
// Then delete the bucket
_, err = adminClient.DeleteBucket(&s3.DeleteBucketInput{
- Bucket: aws.String(testBucket),
+ Bucket: aws.String(bucketName),
})
require.NoError(t, err)
})
@@ -398,7 +395,9 @@ func TestS3IAMBucketPolicyIntegration(t *testing.T) {
adminClient, err := framework.CreateS3ClientWithJWT("admin-user", "TestAdminRole")
require.NoError(t, err)
- err = framework.CreateBucket(adminClient, testBucket)
+ // Use unique bucket name to avoid collection conflicts
+ bucketName := framework.GenerateUniqueBucketName("test-iam-bucket-policy")
+ err = framework.CreateBucket(adminClient, bucketName)
require.NoError(t, err)
t.Run("bucket_policy_allows_public_read", func(t *testing.T) {
@@ -414,17 +413,17 @@ func TestS3IAMBucketPolicyIntegration(t *testing.T) {
"Resource": ["arn:seaweed:s3:::%s/*"]
}
]
- }`, testBucket)
+ }`, bucketName)
_, err = adminClient.PutBucketPolicy(&s3.PutBucketPolicyInput{
- Bucket: aws.String(testBucket),
+ Bucket: aws.String(bucketName),
Policy: aws.String(bucketPolicy),
})
require.NoError(t, err)
// Put test object
_, err = adminClient.PutObject(&s3.PutObjectInput{
- Bucket: aws.String(testBucket),
+ Bucket: aws.String(bucketName),
Key: aws.String(testObjectKey),
Body: strings.NewReader(testObjectData),
})
@@ -435,7 +434,7 @@ func TestS3IAMBucketPolicyIntegration(t *testing.T) {
require.NoError(t, err)
result, err := readOnlyClient.GetObject(&s3.GetObjectInput{
- Bucket: aws.String(testBucket),
+ Bucket: aws.String(bucketName),
Key: aws.String(testObjectKey),
})
require.NoError(t, err)
@@ -459,17 +458,17 @@ func TestS3IAMBucketPolicyIntegration(t *testing.T) {
"Resource": ["arn:seaweed:s3:::%s/*"]
}
]
- }`, testBucket)
+ }`, bucketName)
_, err = adminClient.PutBucketPolicy(&s3.PutBucketPolicyInput{
- Bucket: aws.String(testBucket),
+ Bucket: aws.String(bucketName),
Policy: aws.String(bucketPolicy),
})
require.NoError(t, err)
// Verify that the bucket policy was stored successfully by retrieving it
policyResult, err := adminClient.GetBucketPolicy(&s3.GetBucketPolicyInput{
- Bucket: aws.String(testBucket),
+ Bucket: aws.String(bucketName),
})
require.NoError(t, err)
assert.Contains(t, *policyResult.Policy, "s3:DeleteObject")
@@ -483,18 +482,18 @@ func TestS3IAMBucketPolicyIntegration(t *testing.T) {
// Cleanup - delete bucket policy first, then objects and bucket
_, err = adminClient.DeleteBucketPolicy(&s3.DeleteBucketPolicyInput{
- Bucket: aws.String(testBucket),
+ Bucket: aws.String(bucketName),
})
require.NoError(t, err)
_, err = adminClient.DeleteObject(&s3.DeleteObjectInput{
- Bucket: aws.String(testBucket),
+ Bucket: aws.String(bucketName),
Key: aws.String(testObjectKey),
})
require.NoError(t, err)
_, err = adminClient.DeleteBucket(&s3.DeleteBucketInput{
- Bucket: aws.String(testBucket),
+ Bucket: aws.String(bucketName),
})
require.NoError(t, err)
}
@@ -527,15 +526,6 @@ func TestS3IAMContextualPolicyEnforcement(t *testing.T) {
})
}
-// Helper function to create test content of specific size
-func createTestContent(size int) *bytes.Reader {
- content := make([]byte, size)
- for i := range content {
- content[i] = byte(i % 256)
- }
- return bytes.NewReader(content)
-}
-
// TestS3IAMPresignedURLIntegration tests presigned URL generation with IAM
func TestS3IAMPresignedURLIntegration(t *testing.T) {
framework := NewS3IAMTestFramework(t)
@@ -546,12 +536,12 @@ func TestS3IAMPresignedURLIntegration(t *testing.T) {
require.NoError(t, err)
// Use static bucket name but with cleanup to handle conflicts
- err = framework.CreateBucketWithCleanup(adminClient, testBucketPrefix)
+ err = framework.CreateBucketWithCleanup(adminClient, testBucket)
require.NoError(t, err)
// Put test object
_, err = adminClient.PutObject(&s3.PutObjectInput{
- Bucket: aws.String(testBucketPrefix),
+ Bucket: aws.String(testBucket),
Key: aws.String(testObjectKey),
Body: strings.NewReader(testObjectData),
})
@@ -573,13 +563,13 @@ func TestS3IAMPresignedURLIntegration(t *testing.T) {
// Test direct object access with JWT Bearer token (recommended approach)
_, err := adminClient.GetObject(&s3.GetObjectInput{
- Bucket: aws.String(testBucketPrefix),
+ Bucket: aws.String(testBucket),
Key: aws.String(testObjectKey),
})
require.NoError(t, err, "Direct object access with JWT Bearer token works correctly")
- t.Log("โœ… JWT Bearer token authentication confirmed working for direct S3 API calls")
- t.Log("โ„น๏ธ Note: Presigned URLs are not supported with JWT Bearer authentication by design")
+ t.Log("JWT Bearer token authentication confirmed working for direct S3 API calls")
+ t.Log("Note: Presigned URLs are not supported with JWT Bearer authentication by design")
})
// Cleanup
diff --git a/test/s3/iam/setup_all_tests.sh b/test/s3/iam/setup_all_tests.sh
index 597d367aa..aaec54691 100755
--- a/test/s3/iam/setup_all_tests.sh
+++ b/test/s3/iam/setup_all_tests.sh
@@ -30,12 +30,12 @@ check_prerequisites() {
done
if [ ${#missing_tools[@]} -gt 0 ]; then
- echo -e "${RED}โŒ Missing required tools: ${missing_tools[*]}${NC}"
+ echo -e "${RED}[FAIL] Missing required tools: ${missing_tools[*]}${NC}"
echo -e "${YELLOW}Please install the missing tools and try again${NC}"
exit 1
fi
- echo -e "${GREEN}โœ… All prerequisites met${NC}"
+ echo -e "${GREEN}[OK] All prerequisites met${NC}"
}
# Set up Keycloak for OIDC testing
@@ -43,11 +43,11 @@ setup_keycloak() {
echo -e "\n${BLUE}1. Setting up Keycloak for OIDC testing...${NC}"
if ! "${SCRIPT_DIR}/setup_keycloak.sh"; then
- echo -e "${RED}โŒ Failed to set up Keycloak${NC}"
+ echo -e "${RED}[FAIL] Failed to set up Keycloak${NC}"
return 1
fi
- echo -e "${GREEN}โœ… Keycloak setup completed${NC}"
+ echo -e "${GREEN}[OK] Keycloak setup completed${NC}"
}
# Set up SeaweedFS test cluster
@@ -58,7 +58,7 @@ setup_seaweedfs_cluster() {
echo -e "${YELLOW}๐Ÿ”ง Building SeaweedFS binary...${NC}"
cd "${SCRIPT_DIR}/../../../" # Go to seaweedfs root
if ! make > /dev/null 2>&1; then
- echo -e "${RED}โŒ Failed to build SeaweedFS binary${NC}"
+ echo -e "${RED}[FAIL] Failed to build SeaweedFS binary${NC}"
return 1
fi
@@ -68,7 +68,7 @@ setup_seaweedfs_cluster() {
echo -e "${YELLOW}๐Ÿงน Cleaning up existing test data...${NC}"
rm -rf test-volume-data/* 2>/dev/null || true
- echo -e "${GREEN}โœ… SeaweedFS cluster setup completed${NC}"
+ echo -e "${GREEN}[OK] SeaweedFS cluster setup completed${NC}"
}
# Set up test data and configurations
@@ -79,18 +79,18 @@ setup_test_configurations() {
if [ ! -f "${SCRIPT_DIR}/iam_config.json" ]; then
echo -e "${YELLOW}โš ๏ธ IAM configuration not found, using default config${NC}"
cp "${SCRIPT_DIR}/iam_config.local.json" "${SCRIPT_DIR}/iam_config.json" 2>/dev/null || {
- echo -e "${RED}โŒ No IAM configuration files found${NC}"
+ echo -e "${RED}[FAIL] No IAM configuration files found${NC}"
return 1
}
fi
# Validate configuration
if ! jq . "${SCRIPT_DIR}/iam_config.json" >/dev/null; then
- echo -e "${RED}โŒ Invalid IAM configuration JSON${NC}"
+ echo -e "${RED}[FAIL] Invalid IAM configuration JSON${NC}"
return 1
fi
- echo -e "${GREEN}โœ… Test configurations set up${NC}"
+ echo -e "${GREEN}[OK] Test configurations set up${NC}"
}
# Verify services are ready
@@ -113,13 +113,13 @@ verify_services() {
done
if [ "$keycloak_ready" = true ]; then
- echo -e "${GREEN}โœ… Keycloak is ready${NC}"
+ echo -e "${GREEN}[OK] Keycloak is ready${NC}"
else
echo -e "${YELLOW}โš ๏ธ Keycloak may not be fully ready yet${NC}"
echo -e "${YELLOW}This is okay - tests will wait for Keycloak when needed${NC}"
fi
- echo -e "${GREEN}โœ… Service verification completed${NC}"
+ echo -e "${GREEN}[OK] Service verification completed${NC}"
}
# Set up environment variables
@@ -145,7 +145,7 @@ export TEST_TIMEOUT=60m
export CGO_ENABLED=0
EOF
- echo -e "${GREEN}โœ… Environment variables set${NC}"
+ echo -e "${GREEN}[OK] Environment variables set${NC}"
}
# Display setup summary
@@ -157,7 +157,7 @@ display_summary() {
echo -e "Test Timeout: ${TEST_TIMEOUT:-60m}"
echo -e "IAM Config: ${SCRIPT_DIR}/iam_config.json"
echo -e ""
- echo -e "${GREEN}โœ… Complete test environment setup finished!${NC}"
+ echo -e "${GREEN}[OK] Complete test environment setup finished!${NC}"
echo -e "${YELLOW}๐Ÿ’ก You can now run tests with: make run-all-tests${NC}"
echo -e "${YELLOW}๐Ÿ’ก Or run specific tests with: go test -v -timeout=60m -run TestName${NC}"
echo -e "${YELLOW}๐Ÿ’ก To stop Keycloak: docker stop keycloak-iam-test${NC}"
@@ -173,21 +173,21 @@ main() {
if setup_keycloak; then
setup_steps+=("keycloak")
else
- echo -e "${RED}โŒ Failed to set up Keycloak${NC}"
+ echo -e "${RED}[FAIL] Failed to set up Keycloak${NC}"
exit 1
fi
if setup_seaweedfs_cluster; then
setup_steps+=("seaweedfs")
else
- echo -e "${RED}โŒ Failed to set up SeaweedFS cluster${NC}"
+ echo -e "${RED}[FAIL] Failed to set up SeaweedFS cluster${NC}"
exit 1
fi
if setup_test_configurations; then
setup_steps+=("config")
else
- echo -e "${RED}โŒ Failed to set up test configurations${NC}"
+ echo -e "${RED}[FAIL] Failed to set up test configurations${NC}"
exit 1
fi
diff --git a/test/s3/iam/setup_keycloak.sh b/test/s3/iam/setup_keycloak.sh
index 5d3cc45d6..14fb08435 100755
--- a/test/s3/iam/setup_keycloak.sh
+++ b/test/s3/iam/setup_keycloak.sh
@@ -54,7 +54,7 @@ ensure_container() {
if [[ -n "$extracted_port" ]]; then
KEYCLOAK_PORT="$extracted_port"
KEYCLOAK_URL="http://localhost:${KEYCLOAK_PORT}"
- echo -e "${GREEN}โœ… Using existing container '${CONTAINER_NAME}' on port ${KEYCLOAK_PORT}${NC}"
+ echo -e "${GREEN}[OK] Using existing container '${CONTAINER_NAME}' on port ${KEYCLOAK_PORT}${NC}"
return 0
fi
fi
@@ -71,11 +71,11 @@ ensure_container() {
KEYCLOAK_URL="http://localhost:${KEYCLOAK_PORT}"
fi
fi
- echo -e "${GREEN}โœ… Using existing container '${CONTAINER_NAME}' on port ${KEYCLOAK_PORT}${NC}"
+ echo -e "${GREEN}[OK] Using existing container '${CONTAINER_NAME}' on port ${KEYCLOAK_PORT}${NC}"
return 0
fi
if docker ps --format '{{.Names}}' | grep -q "^${CONTAINER_NAME}$"; then
- echo -e "${GREEN}โœ… Using existing container '${CONTAINER_NAME}'${NC}"
+ echo -e "${GREEN}[OK] Using existing container '${CONTAINER_NAME}'${NC}"
return 0
fi
echo -e "${YELLOW}๐Ÿณ Starting Keycloak container (${KEYCLOAK_IMAGE})...${NC}"
@@ -94,16 +94,16 @@ wait_ready() {
echo -e "${YELLOW}โณ Waiting for Keycloak to be ready...${NC}"
for i in $(seq 1 120); do
if curl -sf "${KEYCLOAK_URL}/health/ready" >/dev/null; then
- echo -e "${GREEN}โœ… Keycloak health check passed${NC}"
+ echo -e "${GREEN}[OK] Keycloak health check passed${NC}"
return 0
fi
if curl -sf "${KEYCLOAK_URL}/realms/master" >/dev/null; then
- echo -e "${GREEN}โœ… Keycloak master realm accessible${NC}"
+ echo -e "${GREEN}[OK] Keycloak master realm accessible${NC}"
return 0
fi
sleep 2
done
- echo -e "${RED}โŒ Keycloak did not become ready in time${NC}"
+ echo -e "${RED}[FAIL] Keycloak did not become ready in time${NC}"
exit 1
}
@@ -122,7 +122,7 @@ kcadm() {
done
if [[ "$auth_success" == false ]]; then
- echo -e "${RED}โŒ Failed to authenticate with any known admin password${NC}"
+ echo -e "${RED}[FAIL] Failed to authenticate with any known admin password${NC}"
return 1
fi
@@ -136,17 +136,17 @@ admin_login() {
ensure_realm() {
if kcadm get realms | grep -q "${REALM_NAME}"; then
- echo -e "${GREEN}โœ… Realm '${REALM_NAME}' already exists${NC}"
+ echo -e "${GREEN}[OK] Realm '${REALM_NAME}' already exists${NC}"
else
echo -e "${YELLOW}๐Ÿ“ Creating realm '${REALM_NAME}'...${NC}"
if kcadm create realms -s realm="${REALM_NAME}" -s enabled=true 2>/dev/null; then
- echo -e "${GREEN}โœ… Realm created${NC}"
+ echo -e "${GREEN}[OK] Realm created${NC}"
else
# Check if it exists now (might have been created by another process)
if kcadm get realms | grep -q "${REALM_NAME}"; then
- echo -e "${GREEN}โœ… Realm '${REALM_NAME}' already exists (created concurrently)${NC}"
+ echo -e "${GREEN}[OK] Realm '${REALM_NAME}' already exists (created concurrently)${NC}"
else
- echo -e "${RED}โŒ Failed to create realm '${REALM_NAME}'${NC}"
+ echo -e "${RED}[FAIL] Failed to create realm '${REALM_NAME}'${NC}"
return 1
fi
fi
@@ -157,7 +157,7 @@ ensure_client() {
local id
id=$(kcadm get clients -r "${REALM_NAME}" -q clientId="${CLIENT_ID}" | jq -r '.[0].id // empty')
if [[ -n "${id}" ]]; then
- echo -e "${GREEN}โœ… Client '${CLIENT_ID}' already exists${NC}"
+ echo -e "${GREEN}[OK] Client '${CLIENT_ID}' already exists${NC}"
else
echo -e "${YELLOW}๐Ÿ“ Creating client '${CLIENT_ID}'...${NC}"
kcadm create clients -r "${REALM_NAME}" \
@@ -169,7 +169,7 @@ ensure_client() {
-s standardFlowEnabled=true \
-s implicitFlowEnabled=false \
-s secret="${CLIENT_SECRET}" >/dev/null
- echo -e "${GREEN}โœ… Client created${NC}"
+ echo -e "${GREEN}[OK] Client created${NC}"
fi
# Create and configure role mapper for the client
@@ -179,7 +179,7 @@ ensure_client() {
ensure_role() {
local role="$1"
if kcadm get roles -r "${REALM_NAME}" | jq -r '.[].name' | grep -qx "${role}"; then
- echo -e "${GREEN}โœ… Role '${role}' exists${NC}"
+ echo -e "${GREEN}[OK] Role '${role}' exists${NC}"
else
echo -e "${YELLOW}๐Ÿ“ Creating role '${role}'...${NC}"
kcadm create roles -r "${REALM_NAME}" -s name="${role}" >/dev/null
@@ -201,7 +201,7 @@ ensure_user() {
-s lastName="User" \
-i)
else
- echo -e "${GREEN}โœ… User '${username}' exists${NC}"
+ echo -e "${GREEN}[OK] User '${username}' exists${NC}"
fi
echo -e "${YELLOW}๐Ÿ”‘ Setting password for '${username}'...${NC}"
kcadm set-password -r "${REALM_NAME}" --userid "${uid}" --new-password "${password}" --temporary=false >/dev/null
@@ -214,7 +214,7 @@ assign_role() {
rid=$(kcadm get roles -r "${REALM_NAME}" | jq -r ".[] | select(.name==\"${role}\") | .id")
# Check if role already assigned
if kcadm get "users/${uid}/role-mappings/realm" -r "${REALM_NAME}" | jq -r '.[].name' | grep -qx "${role}"; then
- echo -e "${GREEN}โœ… User '${username}' already has role '${role}'${NC}"
+ echo -e "${GREEN}[OK] User '${username}' already has role '${role}'${NC}"
return 0
fi
echo -e "${YELLOW}โž• Assigning role '${role}' to '${username}'...${NC}"
@@ -229,7 +229,7 @@ configure_role_mapper() {
internal_id=$(kcadm get clients -r "${REALM_NAME}" -q clientId="${CLIENT_ID}" | jq -r '.[0].id // empty')
if [[ -z "${internal_id}" ]]; then
- echo -e "${RED}โŒ Could not find client ${client_id} to configure role mapper${NC}"
+ echo -e "${RED}[FAIL] Could not find client ${client_id} to configure role mapper${NC}"
return 1
fi
@@ -238,7 +238,7 @@ configure_role_mapper() {
existing_mapper=$(kcadm get "clients/${internal_id}/protocol-mappers/models" -r "${REALM_NAME}" | jq -r '.[] | select(.name=="realm roles" and .protocolMapper=="oidc-usermodel-realm-role-mapper") | .id // empty')
if [[ -n "${existing_mapper}" ]]; then
- echo -e "${GREEN}โœ… Realm roles mapper already exists${NC}"
+ echo -e "${GREEN}[OK] Realm roles mapper already exists${NC}"
else
echo -e "${YELLOW}๐Ÿ“ Creating realm roles mapper...${NC}"
@@ -254,11 +254,11 @@ configure_role_mapper() {
-s 'config."access.token.claim"=true' \
-s 'config."claim.name"=roles' \
-s 'config."jsonType.label"=String' >/dev/null || {
- echo -e "${RED}โŒ Failed to create realm roles mapper${NC}"
+ echo -e "${RED}[FAIL] Failed to create realm roles mapper${NC}"
return 1
}
- echo -e "${GREEN}โœ… Realm roles mapper created${NC}"
+ echo -e "${GREEN}[OK] Realm roles mapper created${NC}"
fi
}
@@ -270,7 +270,7 @@ configure_audience_mapper() {
internal_id=$(kcadm get clients -r "${REALM_NAME}" -q clientId="${CLIENT_ID}" | jq -r '.[0].id // empty')
if [[ -z "${internal_id}" ]]; then
- echo -e "${RED}โŒ Could not find client ${CLIENT_ID} to configure audience mapper${NC}"
+ echo -e "${RED}[FAIL] Could not find client ${CLIENT_ID} to configure audience mapper${NC}"
return 1
fi
@@ -279,7 +279,7 @@ configure_audience_mapper() {
existing_mapper=$(kcadm get "clients/${internal_id}/protocol-mappers/models" -r "${REALM_NAME}" | jq -r '.[] | select(.name=="audience-mapper" and .protocolMapper=="oidc-audience-mapper") | .id // empty')
if [[ -n "${existing_mapper}" ]]; then
- echo -e "${GREEN}โœ… Audience mapper already exists${NC}"
+ echo -e "${GREEN}[OK] Audience mapper already exists${NC}"
else
echo -e "${YELLOW}๐Ÿ“ Creating audience mapper...${NC}"
@@ -292,17 +292,17 @@ configure_audience_mapper() {
-s 'config."included.client.audience"='"${CLIENT_ID}" \
-s 'config."id.token.claim"=false' \
-s 'config."access.token.claim"=true' >/dev/null || {
- echo -e "${RED}โŒ Failed to create audience mapper${NC}"
+ echo -e "${RED}[FAIL] Failed to create audience mapper${NC}"
return 1
}
- echo -e "${GREEN}โœ… Audience mapper created${NC}"
+ echo -e "${GREEN}[OK] Audience mapper created${NC}"
fi
}
main() {
- command -v docker >/dev/null || { echo -e "${RED}โŒ Docker is required${NC}"; exit 1; }
- command -v jq >/dev/null || { echo -e "${RED}โŒ jq is required${NC}"; exit 1; }
+ command -v docker >/dev/null || { echo -e "${RED}[FAIL] Docker is required${NC}"; exit 1; }
+ command -v jq >/dev/null || { echo -e "${RED}[FAIL] jq is required${NC}"; exit 1; }
ensure_container
echo "Keycloak URL: ${KEYCLOAK_URL}"
@@ -347,7 +347,7 @@ main() {
-o /tmp/auth_test_response.json)
if [[ "${validation_result: -3}" == "200" ]]; then
- echo -e "${GREEN}โœ… Authentication validation successful${NC}"
+ echo -e "${GREEN}[OK] Authentication validation successful${NC}"
# Extract and decode JWT token to check for roles
local access_token=$(cat /tmp/auth_test_response.json | jq -r '.access_token // empty')
@@ -363,7 +363,7 @@ main() {
local roles=$(echo "${decoded}" | jq -r '.roles // empty' 2>/dev/null || echo "")
if [[ -n "${roles}" && "${roles}" != "null" ]]; then
- echo -e "${GREEN}โœ… JWT token includes roles: ${roles}${NC}"
+ echo -e "${GREEN}[OK] JWT token includes roles: ${roles}${NC}"
else
echo -e "${YELLOW}โš ๏ธ JWT token does not include 'roles' claim${NC}"
echo -e "${YELLOW}Decoded payload sample:${NC}"
@@ -371,14 +371,14 @@ main() {
fi
fi
else
- echo -e "${RED}โŒ Authentication validation failed with HTTP ${validation_result: -3}${NC}"
+ echo -e "${RED}[FAIL] Authentication validation failed with HTTP ${validation_result: -3}${NC}"
echo -e "${YELLOW}Response body:${NC}"
cat /tmp/auth_test_response.json 2>/dev/null || echo "No response body"
echo -e "${YELLOW}This may indicate a setup issue that needs to be resolved${NC}"
fi
rm -f /tmp/auth_test_response.json
- echo -e "${GREEN}โœ… Keycloak test realm '${REALM_NAME}' configured${NC}"
+ echo -e "${GREEN}[OK] Keycloak test realm '${REALM_NAME}' configured${NC}"
}
setup_iam_config() {
@@ -400,7 +400,7 @@ setup_iam_config() {
# Verify source config exists
if [[ ! -f "$config_source" ]]; then
- echo -e "${RED}โŒ Config file $config_source not found in $script_dir${NC}"
+ echo -e "${RED}[FAIL] Config file $config_source not found in $script_dir${NC}"
exit 1
fi
@@ -408,7 +408,7 @@ setup_iam_config() {
cp "$config_source" "iam_config.json"
local detected_issuer=$(cat iam_config.json | jq -r '.providers[] | select(.name=="keycloak") | .config.issuer')
- echo -e "${GREEN}โœ… IAM configuration set successfully${NC}"
+ echo -e "${GREEN}[OK] IAM configuration set successfully${NC}"
echo " - Using config: $config_source"
echo " - Keycloak issuer: $detected_issuer"
}
diff --git a/test/s3/iam/setup_keycloak_docker.sh b/test/s3/iam/setup_keycloak_docker.sh
index e648bb7b6..6dce68abf 100755
--- a/test/s3/iam/setup_keycloak_docker.sh
+++ b/test/s3/iam/setup_keycloak_docker.sh
@@ -19,7 +19,7 @@ timeout 120 bash -c '
echo "Waiting for Keycloak..."
sleep 5
done
- echo "โœ… Keycloak health check passed"
+ echo "[OK] Keycloak health check passed"
' "$KEYCLOAK_URL"
# Download kcadm.sh if not available
@@ -51,14 +51,14 @@ kcadm() {
sleep 5
done
- echo "โŒ Failed to execute kcadm command after $max_retries retries"
+ echo "[FAIL] Failed to execute kcadm command after $max_retries retries"
return 1
}
# Create realm
echo "๐Ÿ“ Creating realm '$REALM_NAME'..."
kcadm create realms -s realm="$REALM_NAME" -s enabled=true || echo "Realm may already exist"
-echo "โœ… Realm created"
+echo "[OK] Realm created"
# Create OIDC client
echo "๐Ÿ“ Creating client '$CLIENT_ID'..."
@@ -74,9 +74,9 @@ CLIENT_UUID=$(kcadm create clients -r "$REALM_NAME" \
-i 2>/dev/null || echo "existing-client")
if [ "$CLIENT_UUID" != "existing-client" ]; then
- echo "โœ… Client created with ID: $CLIENT_UUID"
+ echo "[OK] Client created with ID: $CLIENT_UUID"
else
- echo "โœ… Using existing client"
+ echo "[OK] Using existing client"
CLIENT_UUID=$(kcadm get clients -r "$REALM_NAME" -q clientId="$CLIENT_ID" --fields id --format csv --noquotes | tail -n +2)
fi
@@ -94,8 +94,8 @@ MAPPER_CONFIG='{
}
}'
-kcadm create clients/"$CLIENT_UUID"/protocol-mappers/models -r "$REALM_NAME" -b "$MAPPER_CONFIG" 2>/dev/null || echo "โœ… Role mapper already exists"
-echo "โœ… Realm roles mapper configured"
+kcadm create clients/"$CLIENT_UUID"/protocol-mappers/models -r "$REALM_NAME" -b "$MAPPER_CONFIG" 2>/dev/null || echo "[OK] Role mapper already exists"
+echo "[OK] Realm roles mapper configured"
# Configure audience mapper to ensure JWT tokens have correct audience claim
echo "๐Ÿ”ง Configuring audience mapper for client '$CLIENT_ID'..."
@@ -110,8 +110,8 @@ AUDIENCE_MAPPER_CONFIG='{
}
}'
-kcadm create clients/"$CLIENT_UUID"/protocol-mappers/models -r "$REALM_NAME" -b "$AUDIENCE_MAPPER_CONFIG" 2>/dev/null || echo "โœ… Audience mapper already exists"
-echo "โœ… Audience mapper configured"
+kcadm create clients/"$CLIENT_UUID"/protocol-mappers/models -r "$REALM_NAME" -b "$AUDIENCE_MAPPER_CONFIG" 2>/dev/null || echo "[OK] Audience mapper already exists"
+echo "[OK] Audience mapper configured"
# Create realm roles
echo "๐Ÿ“ Creating realm roles..."
@@ -393,11 +393,11 @@ ACCESS_TOKEN=$(curl -s -X POST "$KEYCLOAK_TOKEN_URL" \
-d "scope=openid profile email" | jq -r '.access_token')
if [ "$ACCESS_TOKEN" = "null" ] || [ -z "$ACCESS_TOKEN" ]; then
- echo "โŒ Failed to obtain access token"
+ echo "[FAIL] Failed to obtain access token"
exit 1
fi
-echo "โœ… Authentication validation successful"
+echo "[OK] Authentication validation successful"
# Decode and check JWT claims
PAYLOAD=$(echo "$ACCESS_TOKEN" | cut -d'.' -f2)
@@ -410,10 +410,10 @@ CLAIMS=$(echo "$PAYLOAD" | base64 -d 2>/dev/null | jq .)
ROLES=$(echo "$CLAIMS" | jq -r '.roles[]?')
if [ -n "$ROLES" ]; then
- echo "โœ… JWT token includes roles: [$(echo "$ROLES" | tr '\n' ',' | sed 's/,$//' | sed 's/,/, /g')]"
+ echo "[OK] JWT token includes roles: [$(echo "$ROLES" | tr '\n' ',' | sed 's/,$//' | sed 's/,/, /g')]"
else
echo "โš ๏ธ No roles found in JWT token"
fi
-echo "โœ… Keycloak test realm '$REALM_NAME' configured for Docker environment"
+echo "[OK] Keycloak test realm '$REALM_NAME' configured for Docker environment"
echo "๐Ÿณ Setup complete! You can now run: docker-compose up -d"