feat: ensure ACL is disabled when Cerberus is off in security status response
This commit is contained in:
@@ -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,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user