feat: ensure ACL is disabled when Cerberus is off in security status response

This commit is contained in:
GitHub Actions
2025-12-01 02:40:57 +00:00
parent 9259257986
commit 581229e454
2 changed files with 54 additions and 7 deletions

View File

@@ -30,10 +30,8 @@ func (h *SecurityHandler) GetStatus(c *gin.Context) {
// Check runtime setting override
var settingKey = "security.cerberus.enabled"
if h.db != nil {
var setting struct {
Value string
}
if err := h.db.Raw("SELECT value FROM settings WHERE key = ? LIMIT 1", settingKey).Scan(&setting).Error; err == nil {
var setting struct{ Value string }
if err := h.db.Raw("SELECT value FROM settings WHERE key = ? LIMIT 1", settingKey).Scan(&setting).Error; err == nil && setting.Value != "" {
if strings.EqualFold(setting.Value, "true") {
enabled = true
} else {
@@ -65,14 +63,20 @@ func (h *SecurityHandler) GetStatus(c *gin.Context) {
// Allow runtime override for ACL enabled flag via settings table
aclEnabled := h.cfg.ACLMode == "enabled"
aclEffective := aclEnabled && enabled
if h.db != nil {
var a struct{ Value string }
if err := h.db.Raw("SELECT value FROM settings WHERE key = ? LIMIT 1", "security.acl.enabled").Scan(&a).Error; err == nil {
if err := h.db.Raw("SELECT value FROM settings WHERE key = ? LIMIT 1", "security.acl.enabled").Scan(&a).Error; err == nil && a.Value != "" {
if strings.EqualFold(a.Value, "true") {
aclEnabled = true
} else if strings.EqualFold(a.Value, "false") {
aclEnabled = false
}
// If Cerberus is disabled, ACL should not be considered enabled even
// if the ACL setting is true. This keeps ACL tied to the Cerberus
// suite state in the UI and APIs.
aclEffective = aclEnabled && enabled
}
}
@@ -93,7 +97,7 @@ func (h *SecurityHandler) GetStatus(c *gin.Context) {
},
"acl": gin.H{
"mode": h.cfg.ACLMode,
"enabled": aclEnabled,
"enabled": aclEffective,
},
})
}

View File

@@ -52,6 +52,7 @@ func TestSecurityHandler_GetStatus_Clean(t *testing.T) {
var response map[string]interface{}
err := json.Unmarshal(w.Body.Bytes(), &response)
assert.NoError(t, err)
// response body intentionally not printed in clean test
assert.NotNil(t, response["cerberus"])
}
@@ -89,8 +90,18 @@ func TestSecurityHandler_ACL_DBOverride(t *testing.T) {
if err := db.Create(&models.Setting{Key: "security.acl.enabled", Value: "true"}).Error; err != nil {
t.Fatalf("failed to insert setting: %v", err)
}
// Confirm the DB write succeeded
var s models.Setting
if err := db.Where("key = ?", "security.acl.enabled").First(&s).Error; err != nil {
t.Fatalf("setting not found in DB: %v", err)
}
if s.Value != "true" {
t.Fatalf("unexpected value in DB for security.acl.enabled: %s", s.Value)
}
// DB write succeeded; no additional dump needed
cfg := config.SecurityConfig{ACLMode: "disabled"}
// Ensure Cerberus is enabled so ACL can be active
cfg := config.SecurityConfig{ACLMode: "disabled", CerberusEnabled: true}
handler := NewSecurityHandler(cfg, db)
router := gin.New()
router.GET("/security/status", handler.GetStatus)
@@ -107,6 +118,38 @@ func TestSecurityHandler_ACL_DBOverride(t *testing.T) {
assert.Equal(t, true, acl["enabled"].(bool))
}
func TestSecurityHandler_ACL_DisabledWhenCerberusOff(t *testing.T) {
gin.SetMode(gin.TestMode)
db := setupTestDB(t)
// set DB to enable ACL but disable Cerberus
if err := db.Create(&models.Setting{Key: "security.acl.enabled", Value: "true"}).Error; err != nil {
t.Fatalf("failed to insert setting: %v", err)
}
if err := db.Create(&models.Setting{Key: "security.cerberus.enabled", Value: "false"}).Error; err != nil {
t.Fatalf("failed to insert setting: %v", err)
}
cfg := config.SecurityConfig{ACLMode: "enabled", CerberusEnabled: true}
handler := NewSecurityHandler(cfg, db)
router := gin.New()
router.GET("/security/status", handler.GetStatus)
w := httptest.NewRecorder()
req, _ := http.NewRequest("GET", "/security/status", nil)
router.ServeHTTP(w, req)
assert.Equal(t, http.StatusOK, w.Code)
var response map[string]interface{}
err := json.Unmarshal(w.Body.Bytes(), &response)
assert.NoError(t, err)
cerb := response["cerberus"].(map[string]interface{})
assert.Equal(t, false, cerb["enabled"].(bool))
acl := response["acl"].(map[string]interface{})
// ACL must be false because Cerberus is disabled
assert.Equal(t, false, acl["enabled"].(bool))
}
func TestSecurityHandler_CrowdSec_Mode_DBOverride(t *testing.T) {
gin.SetMode(gin.TestMode)