mirror of
https://github.com/MengMengCode/CLICD.git
synced 2026-08-05 05:36:07 +08:00
149 lines
3.5 KiB
Go
149 lines
3.5 KiB
Go
package api
|
|
|
|
import (
|
|
"fmt"
|
|
"testing"
|
|
|
|
"clicd/internal/config"
|
|
)
|
|
|
|
func TestDetectReflectionAbuseIgnoresSingleDNSResolver(t *testing.T) {
|
|
resetSecurityTestConfig()
|
|
|
|
stats := newTrafficStats()
|
|
for i := 0; i < 180; i++ {
|
|
stats.add(connEntry{
|
|
dstIP: "1.1.1.1",
|
|
dstPort: 53,
|
|
proto: "udp",
|
|
state: "UNREPLIED",
|
|
})
|
|
}
|
|
|
|
ss := newSecurityScanner()
|
|
ss.detectReflectionAbuse("ct-dns", "10.0.0.2", stats)
|
|
|
|
if len(ss.alerts) != 0 {
|
|
t.Fatalf("normal DNS queries to one resolver should not trigger reflection alert: %+v", ss.alerts)
|
|
}
|
|
}
|
|
|
|
func TestDetectReflectionAbuseFlagsWideDNSFanout(t *testing.T) {
|
|
resetSecurityTestConfig()
|
|
|
|
stats := newTrafficStats()
|
|
for i := 0; i < 120; i++ {
|
|
stats.add(connEntry{
|
|
dstIP: fmt.Sprintf("203.0.113.%d", i),
|
|
dstPort: 53,
|
|
proto: "udp",
|
|
state: "UNREPLIED",
|
|
})
|
|
}
|
|
|
|
ss := newSecurityScanner()
|
|
ss.detectReflectionAbuse("ct-dns", "10.0.0.2", stats)
|
|
|
|
if len(ss.alerts) != 1 {
|
|
t.Fatalf("expected one reflection alert, got %+v", ss.alerts)
|
|
}
|
|
if got := ss.alerts[0].Type; got != "reflection" {
|
|
t.Fatalf("expected reflection alert, got %q", got)
|
|
}
|
|
}
|
|
|
|
func TestDetectPortScansUsesHalfOpenConnections(t *testing.T) {
|
|
resetSecurityTestConfig()
|
|
|
|
established := newTrafficStats()
|
|
for port := 8000; port < 8020; port++ {
|
|
established.add(connEntry{
|
|
dstIP: "198.51.100.10",
|
|
dstPort: port,
|
|
proto: "tcp",
|
|
state: "ESTABLISHED",
|
|
})
|
|
}
|
|
|
|
ss := newSecurityScanner()
|
|
ss.detectPortScans("ct-web", "10.0.0.3", established)
|
|
if len(ss.alerts) != 0 {
|
|
t.Fatalf("established multi-port connections should not trigger port scan alert: %+v", ss.alerts)
|
|
}
|
|
|
|
halfOpen := newTrafficStats()
|
|
for port := 8000; port < 8012; port++ {
|
|
halfOpen.add(connEntry{
|
|
dstIP: "198.51.100.10",
|
|
dstPort: port,
|
|
proto: "tcp",
|
|
state: "SYN_SENT",
|
|
})
|
|
}
|
|
|
|
ss.detectPortScans("ct-web", "10.0.0.3", halfOpen)
|
|
if len(ss.alerts) != 1 {
|
|
t.Fatalf("expected one port scan alert, got %+v", ss.alerts)
|
|
}
|
|
if got := ss.alerts[0].Type; got != "port_scan" {
|
|
t.Fatalf("expected port_scan alert, got %q", got)
|
|
}
|
|
}
|
|
|
|
func TestCancelPendingSecurityStops(t *testing.T) {
|
|
resetSecurityTestConfig()
|
|
|
|
q := &TaskQueue{
|
|
tasks: map[string]*Task{},
|
|
}
|
|
securityTask := &Task{
|
|
ID: "task-1",
|
|
Type: TaskStop,
|
|
ContainerID: 1,
|
|
Status: "pending",
|
|
User: "system:security",
|
|
}
|
|
userTask := &Task{
|
|
ID: "task-2",
|
|
Type: TaskStop,
|
|
ContainerID: 2,
|
|
Status: "pending",
|
|
User: "admin",
|
|
}
|
|
runningSecurityTask := &Task{
|
|
ID: "task-3",
|
|
Type: TaskStop,
|
|
ContainerID: 3,
|
|
Status: "running",
|
|
User: "system:security",
|
|
}
|
|
q.tasks[securityTask.ID] = securityTask
|
|
q.tasks[userTask.ID] = userTask
|
|
q.tasks[runningSecurityTask.ID] = runningSecurityTask
|
|
q.opQueue = []*Task{securityTask, userTask, runningSecurityTask}
|
|
|
|
if got := q.CancelPendingSecurityStops(); got != 1 {
|
|
t.Fatalf("expected one pending security stop to be cancelled, got %d", got)
|
|
}
|
|
if _, ok := q.tasks[securityTask.ID]; ok {
|
|
t.Fatal("pending security stop task was not removed")
|
|
}
|
|
if _, ok := q.tasks[userTask.ID]; !ok {
|
|
t.Fatal("user stop task should not be removed")
|
|
}
|
|
if _, ok := q.tasks[runningSecurityTask.ID]; !ok {
|
|
t.Fatal("running security stop task should be left for worker-side skip")
|
|
}
|
|
if len(q.opQueue) != 2 {
|
|
t.Fatalf("expected op queue to keep two tasks, got %d", len(q.opQueue))
|
|
}
|
|
}
|
|
|
|
func resetSecurityTestConfig() {
|
|
config.AppConfig = &config.ClicdConfig{
|
|
Containers: []config.Container{},
|
|
AuditLogs: []config.AuditLog{},
|
|
Tasks: []config.SavedTask{},
|
|
}
|
|
}
|