Files
Charon/backend/internal/api/handlers/security_geoip_endpoints_test.go
GitHub Actions 25082778c9 feat(cerberus): integrate Cerberus security features (WAF, ACLs, rate limiting, CrowdSec)
- Implement GeoIPService for IP-to-country lookups with comprehensive error handling.
- Add tests for GeoIPService covering various scenarios including invalid IPs and database loading.
- Extend AccessListService to handle GeoIP service integration, including graceful degradation when GeoIP service is unavailable.
- Introduce new tests for AccessListService to validate geo ACL behavior and country code parsing.
- Update SecurityService to include new fields for WAF configuration and enhance decision logging functionality.
- Add extensive tests for SecurityService covering rule set management and decision logging.
- Create a detailed Security Coverage QA Plan to ensure 100% code coverage for security-related functionality.
2025-12-12 17:56:30 +00:00

123 lines
3.7 KiB
Go

package handlers
import (
"bytes"
"encoding/json"
"net/http"
"net/http/httptest"
"testing"
"github.com/Wikid82/charon/backend/internal/config"
"github.com/Wikid82/charon/backend/internal/services"
"github.com/gin-gonic/gin"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestSecurityHandler_GetGeoIPStatus_NotInitialized(t *testing.T) {
gin.SetMode(gin.TestMode)
h := NewSecurityHandler(config.SecurityConfig{}, nil, nil)
r := gin.New()
r.GET("/security/geoip/status", h.GetGeoIPStatus)
w := httptest.NewRecorder()
req := httptest.NewRequest(http.MethodGet, "/security/geoip/status", http.NoBody)
r.ServeHTTP(w, req)
assert.Equal(t, http.StatusOK, w.Code)
var body map[string]any
require.NoError(t, json.Unmarshal(w.Body.Bytes(), &body))
assert.Equal(t, false, body["loaded"])
assert.Equal(t, "GeoIP service not initialized", body["message"])
}
func TestSecurityHandler_GetGeoIPStatus_Initialized_NotLoaded(t *testing.T) {
gin.SetMode(gin.TestMode)
h := NewSecurityHandler(config.SecurityConfig{}, nil, nil)
h.SetGeoIPService(&services.GeoIPService{})
r := gin.New()
r.GET("/security/geoip/status", h.GetGeoIPStatus)
w := httptest.NewRecorder()
req := httptest.NewRequest(http.MethodGet, "/security/geoip/status", http.NoBody)
r.ServeHTTP(w, req)
assert.Equal(t, http.StatusOK, w.Code)
var body map[string]any
require.NoError(t, json.Unmarshal(w.Body.Bytes(), &body))
assert.Equal(t, false, body["loaded"])
assert.Equal(t, "GeoIP service available", body["message"])
}
func TestSecurityHandler_ReloadGeoIP_NotInitialized(t *testing.T) {
gin.SetMode(gin.TestMode)
h := NewSecurityHandler(config.SecurityConfig{}, nil, nil)
r := gin.New()
r.POST("/security/geoip/reload", h.ReloadGeoIP)
w := httptest.NewRecorder()
req := httptest.NewRequest(http.MethodPost, "/security/geoip/reload", http.NoBody)
r.ServeHTTP(w, req)
assert.Equal(t, http.StatusServiceUnavailable, w.Code)
}
func TestSecurityHandler_ReloadGeoIP_LoadError(t *testing.T) {
gin.SetMode(gin.TestMode)
h := NewSecurityHandler(config.SecurityConfig{}, nil, nil)
h.SetGeoIPService(&services.GeoIPService{}) // dbPath empty => Load() will error
r := gin.New()
r.POST("/security/geoip/reload", h.ReloadGeoIP)
w := httptest.NewRecorder()
req := httptest.NewRequest(http.MethodPost, "/security/geoip/reload", http.NoBody)
r.ServeHTTP(w, req)
assert.Equal(t, http.StatusInternalServerError, w.Code)
assert.Contains(t, w.Body.String(), "Failed to reload GeoIP database")
}
func TestSecurityHandler_LookupGeoIP_MissingIPAddress(t *testing.T) {
gin.SetMode(gin.TestMode)
h := NewSecurityHandler(config.SecurityConfig{}, nil, nil)
r := gin.New()
r.POST("/security/geoip/lookup", h.LookupGeoIP)
payload := []byte(`{}`)
w := httptest.NewRecorder()
req := httptest.NewRequest(http.MethodPost, "/security/geoip/lookup", bytes.NewReader(payload))
req.Header.Set("Content-Type", "application/json")
r.ServeHTTP(w, req)
assert.Equal(t, http.StatusBadRequest, w.Code)
assert.Contains(t, w.Body.String(), "ip_address is required")
}
func TestSecurityHandler_LookupGeoIP_ServiceUnavailable(t *testing.T) {
gin.SetMode(gin.TestMode)
h := NewSecurityHandler(config.SecurityConfig{}, nil, nil)
h.SetGeoIPService(&services.GeoIPService{}) // present but not loaded
r := gin.New()
r.POST("/security/geoip/lookup", h.LookupGeoIP)
payload, _ := json.Marshal(map[string]string{"ip_address": "8.8.8.8"})
w := httptest.NewRecorder()
req := httptest.NewRequest(http.MethodPost, "/security/geoip/lookup", bytes.NewReader(payload))
req.Header.Set("Content-Type", "application/json")
r.ServeHTTP(w, req)
assert.Equal(t, http.StatusServiceUnavailable, w.Code)
assert.Contains(t, w.Body.String(), "GeoIP service not available")
}