Browse Source

fixes

pull/7160/head
chrislu 1 month ago
parent
commit
a5761aa42d
  1. 116
      test/s3/iam/setup_keycloak.sh
  2. 42
      weed/iam/policy/policy_engine_distributed_test.go
  3. 10
      weed/iam/policy/policy_engine_test.go

116
test/s3/iam/setup_keycloak.sh

@ -77,15 +77,21 @@ create_realm() {
"sslRequired": "none" "sslRequired": "none"
}') }')
local response=$(curl -s -X POST "$KEYCLOAK_URL/admin/realms" \
local http_code=$(curl -s -w "%{http_code}" -X POST "$KEYCLOAK_URL/admin/realms" \
-H "Authorization: Bearer $token" \ -H "Authorization: Bearer $token" \
-H "Content-Type: application/json" \ -H "Content-Type: application/json" \
-d "$payload")
-d "$payload" \
-o /tmp/realm_response.json)
if [[ -n "$response" && "$response" != *"error"* ]]; then
local response=$(cat /tmp/realm_response.json 2>/dev/null || echo "")
if [[ "$http_code" == "201" ]]; then
echo "✅ Realm created successfully" echo "✅ Realm created successfully"
return 0
else else
echo "⚠️ Realm creation response: $response"
echo "❌ Realm creation failed with HTTP $http_code"
echo "📋 Response: $response"
return 1
fi fi
} }
@ -110,15 +116,21 @@ create_client() {
"webOrigins": ["*"] "webOrigins": ["*"]
}') }')
local response=$(curl -s -X POST "$KEYCLOAK_URL/admin/realms/$REALM_NAME/clients" \
local http_code=$(curl -s -w "%{http_code}" -X POST "$KEYCLOAK_URL/admin/realms/$REALM_NAME/clients" \
-H "Authorization: Bearer $token" \ -H "Authorization: Bearer $token" \
-H "Content-Type: application/json" \ -H "Content-Type: application/json" \
-d "$payload")
-d "$payload" \
-o /tmp/client_response.json)
local response=$(cat /tmp/client_response.json 2>/dev/null || echo "")
if [[ -n "$response" && "$response" != *"error"* ]]; then
if [[ "$http_code" == "201" ]]; then
echo "✅ Client created successfully" echo "✅ Client created successfully"
return 0
else else
echo "⚠️ Client creation response: $response"
echo "❌ Client creation failed with HTTP $http_code"
echo "📋 Response: $response"
return 1
fi fi
} }
@ -138,15 +150,21 @@ create_role() {
"description": $description "description": $description
}') }')
local response=$(curl -s -X POST "$KEYCLOAK_URL/admin/realms/$REALM_NAME/roles" \
local http_code=$(curl -s -w "%{http_code}" -X POST "$KEYCLOAK_URL/admin/realms/$REALM_NAME/roles" \
-H "Authorization: Bearer $token" \ -H "Authorization: Bearer $token" \
-H "Content-Type: application/json" \ -H "Content-Type: application/json" \
-d "$payload")
-d "$payload" \
-o /tmp/role_response_$role_name.json)
local response=$(cat /tmp/role_response_$role_name.json 2>/dev/null || echo "")
if [[ -n "$response" && "$response" != *"error"* ]]; then
if [[ "$http_code" == "201" ]]; then
echo "✅ Role '$role_name' created successfully" echo "✅ Role '$role_name' created successfully"
return 0
else else
echo "⚠️ Role creation response: $response"
echo "❌ Role '$role_name' creation failed with HTTP $http_code"
echo "📋 Response: $response"
return 1
fi fi
} }
@ -183,15 +201,20 @@ create_user() {
}] }]
}') }')
local user_response=$(curl -s -X POST "$KEYCLOAK_URL/admin/realms/$REALM_NAME/users" \
local http_code=$(curl -s -w "%{http_code}" -X POST "$KEYCLOAK_URL/admin/realms/$REALM_NAME/users" \
-H "Authorization: Bearer $token" \ -H "Authorization: Bearer $token" \
-H "Content-Type: application/json" \ -H "Content-Type: application/json" \
-d "$user_payload")
-d "$user_payload" \
-o /tmp/user_response_$username.json)
if [[ -n "$user_response" && "$user_response" != *"error"* ]]; then
local user_response=$(cat /tmp/user_response_$username.json 2>/dev/null || echo "")
if [[ "$http_code" == "201" ]]; then
echo "✅ User '$username' created successfully" echo "✅ User '$username' created successfully"
else else
echo "⚠️ User creation response: $user_response"
echo "❌ User '$username' creation failed with HTTP $http_code"
echo "📋 Response: $user_response"
return 1
fi fi
# Get user ID # Get user ID
@ -258,27 +281,67 @@ main() {
# Create realm if it doesn't exist # Create realm if it doesn't exist
if ! realm_exists "$ADMIN_TOKEN"; then if ! realm_exists "$ADMIN_TOKEN"; then
create_realm "$ADMIN_TOKEN"
if ! create_realm "$ADMIN_TOKEN"; then
echo "❌ Failed to create realm $REALM_NAME"
exit 1
fi
sleep 2 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 else
echo "✅ Realm $REALM_NAME already exists" echo "✅ Realm $REALM_NAME already exists"
fi fi
# Create client # Create client
create_client "$ADMIN_TOKEN"
if ! create_client "$ADMIN_TOKEN"; then
echo "❌ Failed to create client $CLIENT_ID"
exit 1
fi
sleep 1 sleep 1
# Create roles # Create roles
create_role "$ADMIN_TOKEN" "s3-admin" "SeaweedFS S3 Administrator"
create_role "$ADMIN_TOKEN" "s3-read-only" "SeaweedFS S3 Read-Only User"
create_role "$ADMIN_TOKEN" "s3-write-only" "SeaweedFS S3 Write-Only User"
create_role "$ADMIN_TOKEN" "s3-read-write" "SeaweedFS S3 Read-Write User"
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 sleep 1
# Create test users # Create test users
create_user "$ADMIN_TOKEN" "admin-user" "admin123" "admin@seaweedfs.test" "Admin" "User" "s3-admin"
create_user "$ADMIN_TOKEN" "read-user" "read123" "read@seaweedfs.test" "Read" "User" "s3-read-only"
create_user "$ADMIN_TOKEN" "write-user" "write123" "write@seaweedfs.test" "Write" "User" "s3-write-only"
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 "✅ Keycloak setup completed successfully!"
echo "🔗 Realm: $KEYCLOAK_URL/realms/$REALM_NAME" echo "🔗 Realm: $KEYCLOAK_URL/realms/$REALM_NAME"
@ -287,6 +350,9 @@ main() {
echo " - read-user (password: read123) - s3-read-only role" echo " - read-user (password: read123) - s3-read-only role"
echo " - write-user (password: write123) - s3-write-only role" echo " - write-user (password: write123) - s3-write-only role"
echo "🔑 Client: $CLIENT_ID (secret: $CLIENT_SECRET)" 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 # Run main function

42
weed/iam/policy/policy_engine_distributed_test.go

@ -59,23 +59,23 @@ func TestDistributedPolicyEngine(t *testing.T) {
} }
// Store policy on instance 1 // Store policy on instance 1
err := instance1.AddPolicy("TestPolicy", testPolicy)
err := instance1.AddPolicy("", "TestPolicy", testPolicy)
require.NoError(t, err, "Should be able to store policy on instance 1") require.NoError(t, err, "Should be able to store policy on instance 1")
// For memory storage, each instance has separate storage // For memory storage, each instance has separate storage
// In production with filer storage, all instances would share the same policies // In production with filer storage, all instances would share the same policies
// Verify policy exists on instance 1 // Verify policy exists on instance 1
storedPolicy1, err := instance1.store.GetPolicy(ctx, "TestPolicy")
storedPolicy1, err := instance1.store.GetPolicy(ctx, "", "TestPolicy")
require.NoError(t, err, "Policy should exist on instance 1") require.NoError(t, err, "Policy should exist on instance 1")
assert.Equal(t, "2012-10-17", storedPolicy1.Version) assert.Equal(t, "2012-10-17", storedPolicy1.Version)
assert.Len(t, storedPolicy1.Statement, 2) assert.Len(t, storedPolicy1.Statement, 2)
// For demonstration: store same policy on other instances // For demonstration: store same policy on other instances
err = instance2.AddPolicy("TestPolicy", testPolicy)
err = instance2.AddPolicy("", "TestPolicy", testPolicy)
require.NoError(t, err, "Should be able to store policy on instance 2") require.NoError(t, err, "Should be able to store policy on instance 2")
err = instance3.AddPolicy("TestPolicy", testPolicy)
err = instance3.AddPolicy("", "TestPolicy", testPolicy)
require.NoError(t, err, "Should be able to store policy on instance 3") require.NoError(t, err, "Should be able to store policy on instance 3")
}) })
@ -92,9 +92,9 @@ func TestDistributedPolicyEngine(t *testing.T) {
} }
// Evaluate policy on all instances // Evaluate policy on all instances
result1, err1 := instance1.Evaluate(ctx, evalCtx, []string{"TestPolicy"})
result2, err2 := instance2.Evaluate(ctx, evalCtx, []string{"TestPolicy"})
result3, err3 := instance3.Evaluate(ctx, evalCtx, []string{"TestPolicy"})
result1, err1 := instance1.Evaluate(ctx, "", evalCtx, []string{"TestPolicy"})
result2, err2 := instance2.Evaluate(ctx, "", evalCtx, []string{"TestPolicy"})
result3, err3 := instance3.Evaluate(ctx, "", evalCtx, []string{"TestPolicy"})
require.NoError(t, err1, "Evaluation should succeed on instance 1") require.NoError(t, err1, "Evaluation should succeed on instance 1")
require.NoError(t, err2, "Evaluation should succeed on instance 2") require.NoError(t, err2, "Evaluation should succeed on instance 2")
@ -124,9 +124,9 @@ func TestDistributedPolicyEngine(t *testing.T) {
} }
// All instances should consistently apply deny precedence // All instances should consistently apply deny precedence
result1, err1 := instance1.Evaluate(ctx, evalCtx, []string{"TestPolicy"})
result2, err2 := instance2.Evaluate(ctx, evalCtx, []string{"TestPolicy"})
result3, err3 := instance3.Evaluate(ctx, evalCtx, []string{"TestPolicy"})
result1, err1 := instance1.Evaluate(ctx, "", evalCtx, []string{"TestPolicy"})
result2, err2 := instance2.Evaluate(ctx, "", evalCtx, []string{"TestPolicy"})
result3, err3 := instance3.Evaluate(ctx, "", evalCtx, []string{"TestPolicy"})
require.NoError(t, err1) require.NoError(t, err1)
require.NoError(t, err2) require.NoError(t, err2)
@ -151,9 +151,9 @@ func TestDistributedPolicyEngine(t *testing.T) {
Resource: "arn:seaweed:filer::path/test", Resource: "arn:seaweed:filer::path/test",
} }
result1, err1 := instance1.Evaluate(ctx, evalCtx, []string{"TestPolicy"})
result2, err2 := instance2.Evaluate(ctx, evalCtx, []string{"TestPolicy"})
result3, err3 := instance3.Evaluate(ctx, evalCtx, []string{"TestPolicy"})
result1, err1 := instance1.Evaluate(ctx, "", evalCtx, []string{"TestPolicy"})
result2, err2 := instance2.Evaluate(ctx, "", evalCtx, []string{"TestPolicy"})
result3, err3 := instance3.Evaluate(ctx, "", evalCtx, []string{"TestPolicy"})
require.NoError(t, err1) require.NoError(t, err1)
require.NoError(t, err2) require.NoError(t, err2)
@ -201,8 +201,8 @@ func TestPolicyEngineConfigurationConsistency(t *testing.T) {
Resource: "arn:seaweed:test:::resource", Resource: "arn:seaweed:test:::resource",
} }
result1, _ := instance1.Evaluate(context.Background(), evalCtx, []string{})
result2, _ := instance2.Evaluate(context.Background(), evalCtx, []string{})
result1, _ := instance1.Evaluate(context.Background(), "", evalCtx, []string{})
result2, _ := instance2.Evaluate(context.Background(), "", evalCtx, []string{})
// Results should be different due to different default effects // Results should be different due to different default effects
assert.NotEqual(t, result1.Effect, result2.Effect, "Different default effects should produce different results") assert.NotEqual(t, result1.Effect, result2.Effect, "Different default effects should produce different results")
@ -253,15 +253,15 @@ func TestPolicyStoreDistributed(t *testing.T) {
} }
// Store policy in store1 // Store policy in store1
err := store1.StorePolicy(ctx, "TestPolicy", policy)
err := store1.StorePolicy(ctx, "", "TestPolicy", policy)
require.NoError(t, err) require.NoError(t, err)
// Policy should exist in store1 // Policy should exist in store1
_, err = store1.GetPolicy(ctx, "TestPolicy")
_, err = store1.GetPolicy(ctx, "", "TestPolicy")
assert.NoError(t, err, "Policy should exist in store1") assert.NoError(t, err, "Policy should exist in store1")
// Policy should NOT exist in store2 (different instance) // Policy should NOT exist in store2 (different instance)
_, err = store2.GetPolicy(ctx, "TestPolicy")
_, err = store2.GetPolicy(ctx, "", "TestPolicy")
assert.Error(t, err, "Policy should not exist in store2") assert.Error(t, err, "Policy should not exist in store2")
assert.Contains(t, err.Error(), "not found", "Should be a not found error") assert.Contains(t, err.Error(), "not found", "Should be a not found error")
}) })
@ -283,7 +283,7 @@ func TestPolicyStoreDistributed(t *testing.T) {
} }
// Evaluate with non-existent policies // Evaluate with non-existent policies
result, err := engine.Evaluate(ctx, evalCtx, []string{"NonExistentPolicy1", "NonExistentPolicy2"})
result, err := engine.Evaluate(ctx, "", evalCtx, []string{"NonExistentPolicy1", "NonExistentPolicy2"})
require.NoError(t, err, "Should not error on missing policies") require.NoError(t, err, "Should not error on missing policies")
// Should use default effect when no policies can be loaded // Should use default effect when no policies can be loaded
@ -355,7 +355,7 @@ func TestPolicyEvaluationPerformance(t *testing.T) {
}, },
} }
err := engine.AddPolicy(fmt.Sprintf("Policy%d", i), policy)
err := engine.AddPolicy("", fmt.Sprintf("Policy%d", i), policy)
require.NoError(t, err) require.NoError(t, err)
} }
@ -374,7 +374,7 @@ func TestPolicyEvaluationPerformance(t *testing.T) {
// Measure evaluation time // Measure evaluation time
start := time.Now() start := time.Now()
for i := 0; i < 100; i++ { for i := 0; i < 100; i++ {
_, err := engine.Evaluate(ctx, evalCtx, policyNames)
_, err := engine.Evaluate(ctx, "", evalCtx, policyNames)
require.NoError(t, err) require.NoError(t, err)
} }
duration := time.Since(start) duration := time.Since(start)

10
weed/iam/policy/policy_engine_test.go

@ -153,7 +153,7 @@ func TestPolicyEvaluation(t *testing.T) {
}, },
} }
err := engine.AddPolicy("read-policy", readPolicy)
err := engine.AddPolicy("", "read-policy", readPolicy)
require.NoError(t, err) require.NoError(t, err)
denyPolicy := &PolicyDocument{ denyPolicy := &PolicyDocument{
@ -168,7 +168,7 @@ func TestPolicyEvaluation(t *testing.T) {
}, },
} }
err = engine.AddPolicy("deny-policy", denyPolicy)
err = engine.AddPolicy("", "deny-policy", denyPolicy)
require.NoError(t, err) require.NoError(t, err)
tests := []struct { tests := []struct {
@ -224,7 +224,7 @@ func TestPolicyEvaluation(t *testing.T) {
for _, tt := range tests { for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) { t.Run(tt.name, func(t *testing.T) {
result, err := engine.Evaluate(context.Background(), tt.context, tt.policies)
result, err := engine.Evaluate(context.Background(), "", tt.context, tt.policies)
assert.NoError(t, err) assert.NoError(t, err)
assert.Equal(t, tt.want, result.Effect) assert.Equal(t, tt.want, result.Effect)
@ -259,7 +259,7 @@ func TestConditionEvaluation(t *testing.T) {
}, },
} }
err := engine.AddPolicy("ip-conditional", conditionalPolicy)
err := engine.AddPolicy("", "ip-conditional", conditionalPolicy)
require.NoError(t, err) require.NoError(t, err)
tests := []struct { tests := []struct {
@ -307,7 +307,7 @@ func TestConditionEvaluation(t *testing.T) {
for _, tt := range tests { for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) { t.Run(tt.name, func(t *testing.T) {
result, err := engine.Evaluate(context.Background(), tt.context, []string{"ip-conditional"})
result, err := engine.Evaluate(context.Background(), "", tt.context, []string{"ip-conditional"})
assert.NoError(t, err) assert.NoError(t, err)
assert.Equal(t, tt.want, result.Effect) assert.Equal(t, tt.want, result.Effect)

Loading…
Cancel
Save