eec8c28fb3
Go Benchmark / Performance Regression Check (push) Has been cancelled
Cerberus Integration / Cerberus Security Stack Integration (push) Has been cancelled
Upload Coverage to Codecov / Backend Codecov Upload (push) Has been cancelled
Upload Coverage to Codecov / Frontend Codecov Upload (push) Has been cancelled
CodeQL - Analyze / CodeQL analysis (go) (push) Has been cancelled
CodeQL - Analyze / CodeQL analysis (javascript-typescript) (push) Has been cancelled
CrowdSec Integration / CrowdSec Bouncer Integration (push) Has been cancelled
Docker Build, Publish & Test / build-and-push (push) Has been cancelled
Quality Checks / Auth Route Protection Contract (push) Has been cancelled
Quality Checks / Codecov Trigger/Comment Parity Guard (push) Has been cancelled
Quality Checks / Backend (Go) (push) Has been cancelled
Quality Checks / Frontend (React) (push) Has been cancelled
Rate Limit integration / Rate Limiting Integration (push) Has been cancelled
Security Scan (PR) / Trivy Binary Scan (push) Has been cancelled
Supply Chain Verification (PR) / Verify Supply Chain (push) Has been cancelled
WAF integration / Coraza WAF Integration (push) Has been cancelled
Docker Build, Publish & Test / Security Scan PR Image (push) Has been cancelled
Repo Health Check / Repo health (push) Has been cancelled
History Rewrite Dry-Run / Dry-run preview for history rewrite (push) Has been cancelled
Prune Renovate Branches / prune (push) Has been cancelled
Renovate / renovate (push) Has been cancelled
Nightly Build & Package / sync-development-to-nightly (push) Has been cancelled
Nightly Build & Package / Trigger Nightly Validation Workflows (push) Has been cancelled
Nightly Build & Package / build-and-push-nightly (push) Has been cancelled
Nightly Build & Package / test-nightly-image (push) Has been cancelled
Nightly Build & Package / verify-nightly-supply-chain (push) Has been cancelled
Update GeoLite2 Checksum / update-checksum (push) Has been cancelled
Container Registry Prune / prune-ghcr (push) Has been cancelled
Container Registry Prune / prune-dockerhub (push) Has been cancelled
Container Registry Prune / summarize (push) Has been cancelled
Supply Chain Verification / Verify SBOM (push) Has been cancelled
Supply Chain Verification / Verify Release Artifacts (push) Has been cancelled
Supply Chain Verification / Verify Docker Image Supply Chain (push) Has been cancelled
Monitor Caddy Major Release / check-caddy-major (push) Has been cancelled
Weekly Nightly to Main Promotion / Verify Nightly Branch Health (push) Has been cancelled
Weekly Nightly to Main Promotion / Create Promotion PR (push) Has been cancelled
Weekly Nightly to Main Promotion / Trigger Missing Required Checks (push) Has been cancelled
Weekly Nightly to Main Promotion / Notify on Failure (push) Has been cancelled
Weekly Nightly to Main Promotion / Workflow Summary (push) Has been cancelled
Weekly Security Rebuild / Security Rebuild & Scan (push) Has been cancelled
193 lines
6.3 KiB
Go
Executable File
193 lines
6.3 KiB
Go
Executable File
package caddy
|
|
|
|
import (
|
|
"encoding/json"
|
|
"testing"
|
|
|
|
"github.com/Wikid82/charon/backend/internal/models"
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
func TestBuildCrowdSecHandler_Disabled(t *testing.T) {
|
|
// When crowdsecEnabled is false, should return nil
|
|
h, err := buildCrowdSecHandler(nil, nil, false)
|
|
require.NoError(t, err)
|
|
assert.Nil(t, h)
|
|
}
|
|
|
|
func TestBuildCrowdSecHandler_EnabledWithoutConfig(t *testing.T) {
|
|
// When crowdsecEnabled is true, should return minimal handler
|
|
h, err := buildCrowdSecHandler(nil, nil, true)
|
|
require.NoError(t, err)
|
|
require.NotNil(t, h)
|
|
|
|
assert.Equal(t, "crowdsec", h["handler"])
|
|
// No inline config - all config is at app-level
|
|
assert.Nil(t, h["lapi_url"])
|
|
assert.Nil(t, h["api_key"])
|
|
}
|
|
|
|
func TestBuildCrowdSecHandler_EnabledWithEmptyAPIURL(t *testing.T) {
|
|
// When crowdsecEnabled is true, should return minimal handler
|
|
secCfg := &models.SecurityConfig{
|
|
CrowdSecAPIURL: "",
|
|
}
|
|
h, err := buildCrowdSecHandler(nil, secCfg, true)
|
|
require.NoError(t, err)
|
|
require.NotNil(t, h)
|
|
|
|
assert.Equal(t, "crowdsec", h["handler"])
|
|
// No inline config - all config is at app-level
|
|
assert.Nil(t, h["lapi_url"])
|
|
}
|
|
|
|
func TestBuildCrowdSecHandler_EnabledWithCustomAPIURL(t *testing.T) {
|
|
// When crowdsecEnabled is true, should return minimal handler
|
|
// Custom API URL is configured at app-level, not in handler
|
|
secCfg := &models.SecurityConfig{
|
|
CrowdSecAPIURL: "http://crowdsec-lapi:8081",
|
|
}
|
|
h, err := buildCrowdSecHandler(nil, secCfg, true)
|
|
require.NoError(t, err)
|
|
require.NotNil(t, h)
|
|
|
|
assert.Equal(t, "crowdsec", h["handler"])
|
|
// No inline config - all config is at app-level
|
|
assert.Nil(t, h["lapi_url"])
|
|
}
|
|
|
|
func TestBuildCrowdSecHandler_JSONFormat(t *testing.T) {
|
|
// Test that the handler produces valid JSON with minimal structure
|
|
secCfg := &models.SecurityConfig{
|
|
CrowdSecAPIURL: "http://localhost:8080",
|
|
}
|
|
h, err := buildCrowdSecHandler(nil, secCfg, true)
|
|
require.NoError(t, err)
|
|
require.NotNil(t, h)
|
|
|
|
// Marshal to JSON and verify structure
|
|
b, err := json.Marshal(h)
|
|
require.NoError(t, err)
|
|
s := string(b)
|
|
|
|
// Verify minimal JSON content
|
|
assert.Contains(t, s, `"handler":"crowdsec"`)
|
|
// Should NOT contain inline config fields
|
|
assert.NotContains(t, s, `"lapi_url"`)
|
|
assert.NotContains(t, s, `"api_key"`)
|
|
assert.NotContains(t, s, `"mode"`)
|
|
}
|
|
|
|
func TestBuildCrowdSecHandler_WithHost(t *testing.T) {
|
|
// Test that host parameter is accepted (even if not currently used)
|
|
host := &models.ProxyHost{
|
|
UUID: "test-uuid",
|
|
DomainNames: "example.com",
|
|
}
|
|
secCfg := &models.SecurityConfig{
|
|
CrowdSecAPIURL: "http://custom-crowdsec:8080",
|
|
}
|
|
|
|
h, err := buildCrowdSecHandler(host, secCfg, true)
|
|
require.NoError(t, err)
|
|
require.NotNil(t, h)
|
|
|
|
assert.Equal(t, "crowdsec", h["handler"])
|
|
// No inline config - all config is at app-level
|
|
assert.Nil(t, h["lapi_url"])
|
|
}
|
|
|
|
func TestGenerateConfig_WithCrowdSec(t *testing.T) {
|
|
// Test that CrowdSec is configured at app-level when enabled
|
|
hosts := []models.ProxyHost{
|
|
{
|
|
UUID: "test-uuid",
|
|
DomainNames: "example.com",
|
|
ForwardHost: "app",
|
|
ForwardPort: 8080,
|
|
Enabled: true,
|
|
},
|
|
}
|
|
|
|
secCfg := &models.SecurityConfig{
|
|
CrowdSecMode: "local",
|
|
CrowdSecAPIURL: "http://localhost:8085",
|
|
}
|
|
|
|
// crowdsecEnabled=true should configure app-level CrowdSec
|
|
config, err := GenerateConfig(hosts, "/tmp/caddy-data", "admin@example.com", "", "", false, true, false, false, false, "", nil, nil, nil, secCfg, nil)
|
|
require.NoError(t, err)
|
|
require.NotNil(t, config.Apps.HTTP)
|
|
|
|
// Check app-level CrowdSec configuration
|
|
require.NotNil(t, config.Apps.CrowdSec, "CrowdSec app config should be present")
|
|
assert.Equal(t, "http://localhost:8085", config.Apps.CrowdSec.APIUrl)
|
|
assert.Equal(t, "60s", config.Apps.CrowdSec.TickerInterval)
|
|
assert.NotNil(t, config.Apps.CrowdSec.EnableStreaming)
|
|
assert.True(t, *config.Apps.CrowdSec.EnableStreaming)
|
|
|
|
// Check server-level trusted_proxies configuration
|
|
server := config.Apps.HTTP.Servers["charon_server"]
|
|
require.NotNil(t, server, "Server should be configured")
|
|
require.NotNil(t, server.TrustedProxies, "TrustedProxies should be configured at server level")
|
|
assert.Equal(t, "static", server.TrustedProxies.Source, "TrustedProxies source should be 'static'")
|
|
assert.Contains(t, server.TrustedProxies.Ranges, "127.0.0.1/32", "Should trust localhost")
|
|
assert.Contains(t, server.TrustedProxies.Ranges, "::1/128", "Should trust IPv6 localhost")
|
|
assert.Contains(t, server.TrustedProxies.Ranges, "172.16.0.0/12", "Should trust Docker networks")
|
|
assert.Contains(t, server.TrustedProxies.Ranges, "10.0.0.0/8", "Should trust private networks")
|
|
assert.Contains(t, server.TrustedProxies.Ranges, "192.168.0.0/16", "Should trust private networks")
|
|
|
|
// Check handler is minimal (2 routes: emergency + main)
|
|
require.Len(t, server.Routes, 2)
|
|
|
|
route := server.Routes[1] // Main route is at index 1
|
|
// Handlers should include crowdsec + reverse_proxy
|
|
require.GreaterOrEqual(t, len(route.Handle), 2)
|
|
|
|
// Find the crowdsec handler
|
|
var foundCrowdSec bool
|
|
for _, h := range route.Handle {
|
|
if h["handler"] == "crowdsec" {
|
|
foundCrowdSec = true
|
|
// Verify it has NO inline config
|
|
assert.Nil(t, h["lapi_url"], "Handler should not have inline lapi_url")
|
|
assert.Nil(t, h["api_key"], "Handler should not have inline api_key")
|
|
break
|
|
}
|
|
}
|
|
require.True(t, foundCrowdSec, "crowdsec handler should be present")
|
|
}
|
|
|
|
func TestGenerateConfig_CrowdSecDisabled(t *testing.T) {
|
|
// Test that CrowdSec is NOT configured when disabled
|
|
hosts := []models.ProxyHost{
|
|
{
|
|
UUID: "test-uuid",
|
|
DomainNames: "example.com",
|
|
ForwardHost: "app",
|
|
ForwardPort: 8080,
|
|
Enabled: true,
|
|
},
|
|
}
|
|
|
|
// crowdsecEnabled=false should NOT configure CrowdSec
|
|
config, err := GenerateConfig(hosts, "/tmp/caddy-data", "admin@example.com", "", "", false, false, false, false, false, "", nil, nil, nil, nil, nil)
|
|
require.NoError(t, err)
|
|
require.NotNil(t, config.Apps.HTTP)
|
|
|
|
// No app-level CrowdSec configuration
|
|
assert.Nil(t, config.Apps.CrowdSec, "CrowdSec app config should not be present when disabled")
|
|
|
|
server := config.Apps.HTTP.Servers["charon_server"]
|
|
require.NotNil(t, server)
|
|
require.Len(t, server.Routes, 2) // 2 routes: emergency + main
|
|
|
|
route := server.Routes[1] // Main route is at index 1
|
|
|
|
// Verify no crowdsec handler
|
|
for _, h := range route.Handle {
|
|
assert.NotEqual(t, "crowdsec", h["handler"], "crowdsec handler should not be present when disabled")
|
|
}
|
|
}
|