mirror of
https://github.com/syntrex-lab/gomcp.git
synced 2026-05-09 19:42:37 +02:00
Release prep: 54 engines, self-hosted signatures, i18n, dashboard updates
This commit is contained in:
parent
694e32be26
commit
41cbfd6e0a
178 changed files with 36008 additions and 399 deletions
153
internal/transport/http/rbac_test.go
Normal file
153
internal/transport/http/rbac_test.go
Normal file
|
|
@ -0,0 +1,153 @@
|
|||
package httpserver
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestRBAC_Disabled_PassesThrough(t *testing.T) {
|
||||
rbac := NewRBACMiddleware(RBACConfig{Enabled: false})
|
||||
|
||||
handler := rbac.Require(RoleAdmin, func(w http.ResponseWriter, r *http.Request) {
|
||||
w.WriteHeader(http.StatusOK)
|
||||
w.Write([]byte("ok"))
|
||||
})
|
||||
|
||||
req := httptest.NewRequest("GET", "/test", nil)
|
||||
rec := httptest.NewRecorder()
|
||||
handler(rec, req)
|
||||
|
||||
if rec.Code != http.StatusOK {
|
||||
t.Fatalf("expected 200, got %d", rec.Code)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRBAC_Enabled_NoKey_Returns401(t *testing.T) {
|
||||
rbac := NewRBACMiddleware(RBACConfig{Enabled: true})
|
||||
|
||||
handler := rbac.Require(RoleViewer, func(w http.ResponseWriter, r *http.Request) {
|
||||
w.WriteHeader(http.StatusOK)
|
||||
})
|
||||
|
||||
req := httptest.NewRequest("GET", "/test", nil)
|
||||
rec := httptest.NewRecorder()
|
||||
handler(rec, req)
|
||||
|
||||
if rec.Code != http.StatusUnauthorized {
|
||||
t.Fatalf("expected 401, got %d", rec.Code)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRBAC_Enabled_ValidKey_AdminAccess(t *testing.T) {
|
||||
rbac := NewRBACMiddleware(RBACConfig{Enabled: true})
|
||||
rbac.RegisterKey("admin-key", "sk-admin-123", RoleAdmin)
|
||||
|
||||
handler := rbac.Require(RoleAdmin, func(w http.ResponseWriter, r *http.Request) {
|
||||
w.WriteHeader(http.StatusOK)
|
||||
w.Write([]byte("admin"))
|
||||
})
|
||||
|
||||
req := httptest.NewRequest("GET", "/test", nil)
|
||||
req.Header.Set("Authorization", "Bearer sk-admin-123")
|
||||
rec := httptest.NewRecorder()
|
||||
handler(rec, req)
|
||||
|
||||
if rec.Code != http.StatusOK {
|
||||
t.Fatalf("expected 200, got %d", rec.Code)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRBAC_Enabled_InsufficientRole_Returns403(t *testing.T) {
|
||||
rbac := NewRBACMiddleware(RBACConfig{Enabled: true})
|
||||
rbac.RegisterKey("viewer-key", "sk-viewer-456", RoleViewer)
|
||||
|
||||
handler := rbac.Require(RoleAdmin, func(w http.ResponseWriter, r *http.Request) {
|
||||
w.WriteHeader(http.StatusOK)
|
||||
})
|
||||
|
||||
req := httptest.NewRequest("GET", "/test", nil)
|
||||
req.Header.Set("Authorization", "Bearer sk-viewer-456")
|
||||
rec := httptest.NewRecorder()
|
||||
handler(rec, req)
|
||||
|
||||
if rec.Code != http.StatusForbidden {
|
||||
t.Fatalf("expected 403, got %d", rec.Code)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRBAC_XAPIKeyHeader(t *testing.T) {
|
||||
rbac := NewRBACMiddleware(RBACConfig{Enabled: true})
|
||||
rbac.RegisterKey("sensor", "sk-sensor-789", RoleSensor)
|
||||
|
||||
handler := rbac.Require(RoleSensor, func(w http.ResponseWriter, r *http.Request) {
|
||||
w.WriteHeader(http.StatusOK)
|
||||
})
|
||||
|
||||
req := httptest.NewRequest("POST", "/ingest", nil)
|
||||
req.Header.Set("X-API-Key", "sk-sensor-789")
|
||||
rec := httptest.NewRecorder()
|
||||
handler(rec, req)
|
||||
|
||||
if rec.Code != http.StatusOK {
|
||||
t.Fatalf("expected 200, got %d", rec.Code)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRBAC_RevokedKey_Returns401(t *testing.T) {
|
||||
rbac := NewRBACMiddleware(RBACConfig{Enabled: true})
|
||||
rbac.RegisterKey("temp-key", "sk-temp-000", RoleAdmin)
|
||||
rbac.RevokeKey("sk-temp-000")
|
||||
|
||||
handler := rbac.Require(RoleViewer, func(w http.ResponseWriter, r *http.Request) {
|
||||
w.WriteHeader(http.StatusOK)
|
||||
})
|
||||
|
||||
req := httptest.NewRequest("GET", "/test", nil)
|
||||
req.Header.Set("Authorization", "Bearer sk-temp-000")
|
||||
rec := httptest.NewRecorder()
|
||||
handler(rec, req)
|
||||
|
||||
if rec.Code != http.StatusUnauthorized {
|
||||
t.Fatalf("expected 401, got %d", rec.Code)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRBAC_ListKeys_MasksKeys(t *testing.T) {
|
||||
rbac := NewRBACMiddleware(RBACConfig{Enabled: true})
|
||||
rbac.RegisterKey("admin", "sk-admin-very-long-key-12345", RoleAdmin)
|
||||
|
||||
keys := rbac.ListKeys()
|
||||
if len(keys) != 1 {
|
||||
t.Fatalf("expected 1 key, got %d", len(keys))
|
||||
}
|
||||
if keys[0].Key == "sk-admin-very-long-key-12345" {
|
||||
t.Fatal("key should be masked")
|
||||
}
|
||||
if keys[0].Name != "admin" {
|
||||
t.Fatalf("expected name='admin', got %q", keys[0].Name)
|
||||
}
|
||||
t.Logf("masked key: %s", keys[0].Key)
|
||||
}
|
||||
|
||||
func TestRBAC_RoleHierarchy(t *testing.T) {
|
||||
tests := []struct {
|
||||
userRole Role
|
||||
minRole Role
|
||||
allowed bool
|
||||
}{
|
||||
{RoleAdmin, RoleAdmin, true},
|
||||
{RoleAdmin, RoleSensor, true},
|
||||
{RoleAnalyst, RoleViewer, true},
|
||||
{RoleViewer, RoleAnalyst, false},
|
||||
{RoleSensor, RoleViewer, false},
|
||||
{RoleExternal, RoleAdmin, false},
|
||||
{RoleSensor, RoleSensor, true},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
got := hasPermission(tt.userRole, tt.minRole)
|
||||
if got != tt.allowed {
|
||||
t.Errorf("hasPermission(%s, %s) = %v, want %v", tt.userRole, tt.minRole, got, tt.allowed)
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue