Nouveaux modules: - cmd/ja4sentinel/main.go : point d'entrée avec pipeline capture→parse→fingerprint→output - internal/config/loader.go : chargement YAML + env (JA4SENTINEL_*) + validation - internal/tlsparse/parser.go : extraction ClientHello avec suivi d'état de flux (NEW/WAIT_CLIENT_HELLO/JA4_DONE) - internal/fingerprint/engine.go : génération JA4/JA3 via psanford/tlsfingerprint - internal/output/writers.go : StdoutWriter, FileWriter, UnixSocketWriter, MultiWriter Infrastructure: - Dockerfile (multi-stage), Dockerfile.dev, Dockerfile.test-server - Makefile (build, test, lint, docker-build-*) - docker-compose.test.yml pour tests d'intégration - README.md (276 lignes) avec architecture, config, exemples API (api/types.go): - Ajout Close() aux interfaces Capture et Parser - Ajout FlowTimeoutSec dans Config (défaut: 30s, env: JA4SENTINEL_FLOW_TIMEOUT) - ServiceLog: +Timestamp, +TraceID, +ConnID - LogRecord: champs flatten (ip_meta_*, tcp_meta_*, ja4*) - Helper NewLogRecord() pour conversion TLSClientHello+Fingerprints→LogRecord Architecture (architecture.yml): - Documentation module logging + interfaces LoggerFactory/Logger - Section service.systemd complète (unit, security, capabilities) - Section logging.strategy (JSON lines, champs, règles) - api.Config: +FlowTimeoutSec documenté Fixes/cleanup: - Suppression internal/api/types.go (consolidé dans api/types.go) - Correction imports logging (ja4sentinel/api) - .dockerignore / .gitignore - config.yml.example Tests: - Tous les modules ont leurs tests (*_test.go) - Tests unitaires : capture, config, fingerprint, output, tlsparse - Tests d'intégration via docker-compose.test.yml Build: - Binaires dans dist/ (make build → dist/ja4sentinel) - Docker runtime avec COPY --from=builder /app/dist/ Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
82 lines
1.6 KiB
Go
82 lines
1.6 KiB
Go
package capture
|
|
|
|
import (
|
|
"testing"
|
|
)
|
|
|
|
func TestBuildBPFForPorts(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
ports []uint16
|
|
want string
|
|
}{
|
|
{
|
|
name: "single port",
|
|
ports: []uint16{443},
|
|
want: "(tcp port 443)",
|
|
},
|
|
{
|
|
name: "multiple ports",
|
|
ports: []uint16{443, 8443},
|
|
want: "(tcp port 443) or (tcp port 8443)",
|
|
},
|
|
{
|
|
name: "no ports",
|
|
ports: []uint16{},
|
|
want: "tcp",
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
got := buildBPFForPorts(tt.ports)
|
|
if got != tt.want {
|
|
t.Errorf("buildBPFForPorts() = %v, want %v", got, tt.want)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestJoinString(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
parts []string
|
|
sep string
|
|
want string
|
|
}{
|
|
{
|
|
name: "empty slices",
|
|
parts: []string{},
|
|
sep: ", ",
|
|
want: "",
|
|
},
|
|
{
|
|
name: "single element",
|
|
parts: []string{"hello"},
|
|
sep: ", ",
|
|
want: "hello",
|
|
},
|
|
{
|
|
name: "multiple elements",
|
|
parts: []string{"hello", "world", "test"},
|
|
sep: ", ",
|
|
want: "hello, world, test",
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
got := joinString(tt.parts, tt.sep)
|
|
if got != tt.want {
|
|
t.Errorf("joinString() = %v, want %v", got, tt.want)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
// Tests d'intégration nécessitant une interface valide seront à faire dans des environnements de test appropriés
|
|
// car la capture réseau nécessite des permissions élevées
|
|
func TestCaptureIntegration(t *testing.T) {
|
|
t.Skip("Skipping integration test requiring network access and elevated privileges")
|
|
}
|