Torna agli aggiornamenti
New releaseAug 20, 2026

LeitWacht v1.21.0

Leitwacht control plane — sicurezza runtime per CI/CD di GitLab Runner: authoring di policy, multi-tenancy, audit, integrazione con GitLab

Condividi

GitLab Runner Leitwacht

Applicazione dell'egress di rete per i container CI/CD di GitLab Runner. Leitwacht previene gli attacchi alla supply chain impedendo l'esfiltrazione di segreti, controllando a cosa ogni container job può accedere sulla rete.

Come Funziona

Leitwacht è un agente standalone che viene eseguito insieme a GitLab Runner su ogni nodo. Intercetta gli eventi di avvio dei container, applica primitive di enforcement e segnala tutta l'attività di rete a un backend centrale. Non sono necessarie modifiche a GitLab Runner.

Stack di Enforcement (per container)

Container Process
    |
    | DNS query (port 53)
    v
nftables redirect ──> DNS Proxy (:15353)
                         |
                         |── Allowlist check (FQDN match)
                         |── Block: NXDOMAIN response
                         |── Allow: forward to upstream, add resolved IPs to eBPF allow map
                         |── Record: domain, resolved IPs, PID, process name
                         v
                    Upstream DNS (CoreDNS / external)
    
Container Process
    |
    | TCP/UDP egress (any port)
    v
eBPF cgroup-skb/egress filter
    |── IP in allow map? ──> ALLOW (counted)
    |── IP in trusted CIDRs? ──> ALLOW (pod net, svc net)
    |── Cloud metadata (169.254.169.254)? ──> BLOCK (always)
    |── DoT (port 853)? ──> BLOCK (always)
    |── IPv6 (non-loopback)? ──> BLOCK (always)
    |── Default ──> BLOCK (drop event to ringbuf)

Condivisione a Livello di Pod (Kubernetes)

Tutti i container in un pod K8s condividono un unico namespace di rete. Leitwacht crea un singolo NetnsContext per pod che possiede lo stato condiviso (proxy DNS, regole nftables, mappe eBPF). Ogni container ottiene il proprio attachment cgroup-skb in modo che nessun sibling possa bypassare il filtro.

Pod (shared netns)
 +-- NetnsContext (1 per pod)
 |    +-- DNS Proxy (1 goroutine pair)
 |    +-- nftables redirect rules
 |    +-- eBPF program + maps
 |    +-- Ringbuf reader
 |
 +-- Container A
 |    +-- CgroupLink (eBPF attached to A's cgroup)
 |    +-- ViolationRecorder
 |
 +-- Container B
      +-- CgroupLink (eBPF attached to B's cgroup)
      +-- ViolationRecorder

Comunicazione Agente-Backend

+------------------+          gRPC           +------------------+
|  Leitwacht Agent  | ──────────────────────> |  Leitwacht Server |
|  (per node)      |                         |  (central)       |
|                  |  GetPolicy(project)     |                  |
|  - Watcher       | <───────────────────── |  - Policy store  |
|  - Enforcer      |                         |  - Violation DB  |
|  - DNS Proxy     |  ReportViolations(job)  |  - REST API      |
|  - Reporter      | ──────────────────────> |  - Frontend SPA  |
|  - Honeypot LSM  |                         |  - Notifications |
|                  |  Heartbeat()            |  - Baselines     |
|                  | ──────────────────────> |  - Anomaly det.  |
+------------------+                         +------------------+

Architettura

Componenti

ComponenteDescrizione
Agente (cmd/agent)DaemonSet sui nodi runner. Monitora containerd per i container job, applica eBPF + proxy DNS, segnala le violazioni. Richiede root + Linux.
Server (cmd/server)Backend centrale. API REST per il frontend, gRPC per gli agenti. Memorizza policy, violazioni, baseline. Postgres o SQLite.
Frontend (frontend/)SPA in SvelteKit. Gestione policy, visualizzatore violazioni, gestione baseline, rilevamento anomalie, log di audit.

Pacchetti Principali

Questo repository contiene il server EE e l'agente con licenza EE. Il data plane di enforcement di rete mostrato nei diagrammi sopra (eBPF, proxy DNS, nftables, watcher containerd) risiede nel modulo separato della Community Edition con licenza MPL-2.0 leitwacht-agent, che questo repository consuma come dipendenza; cmd/agent + ee/ sono la build EE che lo riutilizza e lo collega al backend.

PacchettoScopo
internal/agentgrpcServer gRPC: riceve report di violazioni dagli agenti, fornisce stream di policy e regole
internal/apiGestori API REST, middleware autenticazione, ambiti RBAC
internal/authAutenticazione OIDC (GitLab), sessioni, CSRF
internal/storeAccesso dati GORM (progetti, violazioni, baseline) + ClickHouse
internal/license, internal/licensemgrVerifica licenza EE (Ed25519 JWS) + ciclo di vita e gate di configurazione (vedi LICENSE)
internal/notifyConsegna alert (email/SES, Slack) + template
internal/retentionConservazione / pruning dati
internal/mcp, internal/mcpauthServer MCP + auth
ee/reporterClient gRPC agente EE che invia violazioni e avvisi al backend
ee/policycache, ee/rulewatcher, ee/rulestoreCache policy agente EE + watch/store regole (BBolt)
contract/Modulo Go condiviso: sorgenti .proto + tipi wire generati agentpb

Deployment

Prerequisiti

  • Cluster Kubernetes con runtime containerd
  • GitLab Runner che utilizza l'esecutore Kubernetes
  • FF_NETWORK_PER_BUILD=true sui runner (ogni job ha il proprio namespace di rete)

Helm Charts

Server (helm/) — pubblicato come chart OCI. Richiede Postgres + ClickHouse e alcuni segreti pre-creati (DSN DB, chiavi auth). Vedi docs/DEPLOY.md per il runbook completo.

helm install leitwacht \
  oci://registry.gitlab.com/leitwacht/leitwacht/charts/leitwacht --version 1.18.0 \
  --set image.tag=1.18.0 \
  --set ingress.domain=example.com --set ingress.hosts[0]=leitwacht.example.com \
  --set grpcIngress.domain=example.com --set grpcIngress.hosts[0]=grpc-leitwacht.example.com \
  --set app.oidcIssuer=https://gitlab.com --set app.oidcClientId=<oauth-app-id> \
  --set clickhouse.embedded.password=<password>

Agente (helm/agent/):

helm install leitwacht-agent \
  oci://registry.gitlab.com/leitwacht/leitwacht/charts/leitwacht-agent --version 1.18.0 \
  --set agent.backendAddr="leitwacht.namespace.svc.cluster.local:9090" \
  --set agent.defaultAction=audit \
  --set agent.dnsUpstream="10.96.0.10:53,1.1.1.1:53" \
  --set agent.trustedCIDRs="10.244.0.0/16,10.96.0.0/12"

Modalità di Enforcement

ModalitàPolitica DNSFiltro eBPFCaso d'Uso
auditInoltra tutto, registra violazioniConsenti tutto, registra scartiCostruzione baseline, rollout iniziale
blockNXDOMAIN per non consentitiBlocca IP non consentitiEnforcement in produzione
allowNessun enforcementNessun enforcementProgetti esentati

Sviluppo

Build

# Backend
go build ./cmd/agent
go build ./cmd/server

# Frontend
cd frontend && pnpm install && pnpm build

# gRPC contract regeneration (edit contract/proto/**, then):
cd contract && buf generate proto/

Il data plane eBPF non si trova in questo repository — risiede nel modulo leitwacht-agent (CE). Rigenera i suoi scheletri BPF lì (vedi Makefile di quel repository: make ebpf-generate).

Test

# Unit tests (any platform)
go test ./...

# Integration / e2e tests requiring sidecars (ClickHouse + Postgres) live under
# internal/store, internal/api, internal/agentgrpc — bring those up first.

# Frontend
cd frontend && pnpm test

Lint

# Backend
golangci-lint run ./...

# Frontend
cd frontend && pnpm lint

Documentazione

DocumentoContenuto
docs/DEPLOY.mdRunbook completo di deployment Kubernetes (segreti, ClickHouse, migrazioni, installazione licenza, esposizione)
docs/MULTI_ORG.mdConfigurazione multi-organizzazione / multi-tenant
LICENSE, NOTICETermini BSL 1.1 (Change License: MPL-2.0) e suddivisione licenze CE/EE
leitwacht-agentL'agente data-plane della Community Edition MPL-2.0 (eBPF/proxy DNS/enforcement nftables) – il motore dietro i diagrammi sopra

Categorie