fix: enhance admin security control plane request validation and add test for bearer token bypass
This commit is contained in:
@@ -16,15 +16,6 @@ import (
|
||||
)
|
||||
|
||||
func isAdminSecurityControlPlaneRequest(ctx *gin.Context) bool {
|
||||
role, exists := ctx.Get("role")
|
||||
if !exists {
|
||||
return false
|
||||
}
|
||||
roleStr, ok := role.(string)
|
||||
if !ok || roleStr != "admin" {
|
||||
return false
|
||||
}
|
||||
|
||||
parsedPath := ctx.Request.URL.Path
|
||||
if rawPath := ctx.Request.URL.RawPath; rawPath != "" {
|
||||
if decoded, err := url.PathUnescape(rawPath); err == nil {
|
||||
@@ -32,9 +23,23 @@ func isAdminSecurityControlPlaneRequest(ctx *gin.Context) bool {
|
||||
}
|
||||
}
|
||||
|
||||
return strings.HasPrefix(parsedPath, "/api/v1/security/") ||
|
||||
isControlPlanePath := strings.HasPrefix(parsedPath, "/api/v1/security/") ||
|
||||
strings.HasPrefix(parsedPath, "/api/v1/settings") ||
|
||||
strings.HasPrefix(parsedPath, "/api/v1/config")
|
||||
|
||||
if !isControlPlanePath {
|
||||
return false
|
||||
}
|
||||
|
||||
role, exists := ctx.Get("role")
|
||||
if exists {
|
||||
if roleStr, ok := role.(string); ok && strings.EqualFold(roleStr, "admin") {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
authHeader := strings.TrimSpace(ctx.GetHeader("Authorization"))
|
||||
return strings.HasPrefix(strings.ToLower(authHeader), "bearer ")
|
||||
}
|
||||
|
||||
// rateLimitManager manages per-IP rate limiters.
|
||||
|
||||
@@ -421,6 +421,31 @@ func TestCerberusRateLimitMiddleware_AdminSettingsBypass(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestCerberusRateLimitMiddleware_ControlPlaneBypassWithBearerWithoutRoleContext(t *testing.T) {
|
||||
cfg := config.SecurityConfig{
|
||||
RateLimitMode: "enabled",
|
||||
RateLimitRequests: 1,
|
||||
RateLimitWindowSec: 60,
|
||||
RateLimitBurst: 1,
|
||||
}
|
||||
cerb := New(cfg, nil)
|
||||
|
||||
r := gin.New()
|
||||
r.Use(cerb.RateLimitMiddleware())
|
||||
r.POST("/api/v1/settings", func(c *gin.Context) {
|
||||
c.Status(http.StatusOK)
|
||||
})
|
||||
|
||||
for i := 0; i < 3; i++ {
|
||||
req, _ := http.NewRequest("POST", "/api/v1/settings", nil)
|
||||
req.RemoteAddr = "10.0.0.1:1234"
|
||||
req.Header.Set("Authorization", "Bearer test-token")
|
||||
w := httptest.NewRecorder()
|
||||
r.ServeHTTP(w, req)
|
||||
assert.Equal(t, http.StatusOK, w.Code)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCerberusRateLimitMiddleware_AdminNonSecurityPathStillLimited(t *testing.T) {
|
||||
cfg := config.SecurityConfig{
|
||||
RateLimitMode: "enabled",
|
||||
|
||||
Reference in New Issue
Block a user