Extract each page into colocated _components/ sections to bring page.tsx files from 1008/891/769 LOC down to 57/23/21 LOC, well within the 500-line hard cap. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
111 lines
6.9 KiB
TypeScript
111 lines
6.9 KiB
TypeScript
import { CodeBlock, InfoBox } from '@/components/DevPortalLayout'
|
|
|
|
export function EncryptionNamespaceSection() {
|
|
return (
|
|
<>
|
|
<h2 id="verschluesselung">6. Ende-zu-Ende-Verschluesselung</h2>
|
|
<p>
|
|
Die Verschluesselung findet <strong>vollstaendig auf dem System des Kunden</strong> statt --
|
|
der Cloud-Server bekommt nur verschluesselte Daten zu sehen.
|
|
</p>
|
|
|
|
<h3>6.1 Der Verschluesselungsvorgang</h3>
|
|
<CodeBlock language="text" filename="Client-seitige Verschluesselung (im SDK)">
|
|
{`┌─────────────────────────────────────────────────────────────────┐
|
|
│ System des Kunden (SDK) │
|
|
├─────────────────────────────────────────────────────────────────┤
|
|
│ 1. Kunde konfiguriert Passphrase im SDK │
|
|
│ → Passphrase bleibt hier -- wird NIE gesendet │
|
|
│ │
|
|
│ 2. Schluessel-Ableitung: │
|
|
│ PBKDF2-SHA256(Passphrase, zufaelliger Salt, 100.000 Runden) │
|
|
│ → Ergebnis: 256-Bit-Schluessel (32 Bytes) │
|
|
│ │
|
|
│ 3. Verschluesselung: │
|
|
│ AES-256-GCM(Schluessel, zufaelliger IV, Dokument) │
|
|
│ → GCM: Garantiert Integritaet (Manipulation erkennbar) │
|
|
│ │
|
|
│ 4. Schluessel-Hash: │
|
|
│ SHA-256(abgeleiteter Schluessel) → Hash fuer Verifikation │
|
|
│ → Vom Hash kann der Schluessel NICHT zurueckberechnet werden│
|
|
│ │
|
|
│ 5. Upload: Nur diese Daten gehen an den Cloud-Server: │
|
|
│ • Verschluesselter Blob • Salt • IV • Schluessel-Hash │
|
|
│ │
|
|
│ Was NICHT an den Server geht: │
|
|
│ ✗ Passphrase ✗ Abgeleiteter Schluessel ✗ Klartext │
|
|
└─────────────────────────────────────────────────────────────────┘`}
|
|
</CodeBlock>
|
|
|
|
<h3>6.2 Sicherheitsgarantien</h3>
|
|
<div className="not-prose my-6 overflow-x-auto">
|
|
<table className="min-w-full divide-y divide-gray-200 text-sm">
|
|
<thead className="bg-gray-50">
|
|
<tr>
|
|
<th className="px-4 py-3 text-left font-medium text-gray-500">Angriffsszenario</th>
|
|
<th className="px-4 py-3 text-left font-medium text-gray-500">Was der Angreifer sieht</th>
|
|
<th className="px-4 py-3 text-left font-medium text-gray-500">Ergebnis</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody className="divide-y divide-gray-200">
|
|
<tr><td className="px-4 py-3 font-medium">Cloud-Server wird gehackt</td><td className="px-4 py-3">Verschluesselte Blobs + Hashes</td><td className="px-4 py-3 text-green-700 font-medium">Keine lesbaren Dokumente</td></tr>
|
|
<tr><td className="px-4 py-3 font-medium">Datenbank wird geleakt</td><td className="px-4 py-3">encrypted_identity_map (verschluesselt)</td><td className="px-4 py-3 text-green-700 font-medium">Keine personenbezogenen Daten</td></tr>
|
|
<tr><td className="px-4 py-3 font-medium">Netzwerkverkehr abgefangen</td><td className="px-4 py-3">Verschluesselte Daten (TLS + AES)</td><td className="px-4 py-3 text-green-700 font-medium">Doppelt verschluesselt</td></tr>
|
|
<tr><td className="px-4 py-3 font-medium">Betreiber (Breakpilot) will mitlesen</td><td className="px-4 py-3">Verschluesselte Blobs, kein Schluessel</td><td className="px-4 py-3 text-green-700 font-medium">Operator Blindness</td></tr>
|
|
<tr><td className="px-4 py-3 font-medium">Anderer Kunde versucht Zugriff</td><td className="px-4 py-3">Nichts (Tenant-Isolation)</td><td className="px-4 py-3 text-green-700 font-medium">Namespace blockiert</td></tr>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
|
|
<h2 id="namespace">7. Namespace-Isolation: Jeder Kunde hat seinen eigenen Bereich</h2>
|
|
<p>
|
|
Ein <strong>Namespace</strong> ist ein vollstaendig abgeschotteter Bereich im System -- wie
|
|
<strong> separate Tresorraeume in einer Bank</strong>. Jeder Kunde hat seinen eigenen Raum,
|
|
und kein Schluessel passt in einen anderen.
|
|
</p>
|
|
|
|
<CodeBlock language="text" filename="Tenant-Isolation in der Vektordatenbank (Qdrant)">
|
|
{`Kunde A (tenant_id: "firma-alpha-001")
|
|
├── Dokument 1 (verschluesselt)
|
|
└── Referenz: Pruefkriterien 2025
|
|
|
|
Kunde B (tenant_id: "firma-beta-002")
|
|
└── Referenz: Compliance-Vorgaben 2025
|
|
|
|
Suchanfrage von Kunde A:
|
|
→ Suche NUR in tenant_id = "firma-alpha-001"
|
|
→ Kunde B's Daten sind UNSICHTBAR
|
|
|
|
Jede Qdrant-Query hat diesen Pflichtfilter:
|
|
must_conditions = [
|
|
FieldCondition(key="tenant_id", match="firma-alpha-001")
|
|
]`}
|
|
</CodeBlock>
|
|
|
|
<h3>7.2 Drei Ebenen der Isolation</h3>
|
|
<div className="not-prose my-6 overflow-x-auto">
|
|
<table className="min-w-full divide-y divide-gray-200 text-sm">
|
|
<thead className="bg-gray-50">
|
|
<tr>
|
|
<th className="px-4 py-3 text-left font-medium text-gray-500">Ebene</th>
|
|
<th className="px-4 py-3 text-left font-medium text-gray-500">System</th>
|
|
<th className="px-4 py-3 text-left font-medium text-gray-500">Isolation</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody className="divide-y divide-gray-200">
|
|
<tr><td className="px-4 py-3 font-medium">Dateisystem</td><td className="px-4 py-3">MinIO (S3-Storage)</td><td className="px-4 py-3">Eigener Bucket/Pfad pro Kunde</td></tr>
|
|
<tr><td className="px-4 py-3 font-medium">Vektordatenbank</td><td className="px-4 py-3">Qdrant</td><td className="px-4 py-3">Pflichtfilter <code>tenant_id</code> bei jeder Suche</td></tr>
|
|
<tr><td className="px-4 py-3 font-medium">Metadaten-DB</td><td className="px-4 py-3">PostgreSQL</td><td className="px-4 py-3">Jede Tabelle hat <code>tenant_id</code> als Pflichtfeld</td></tr>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
|
|
<InfoBox type="warning" title="Kein Training mit Kundendaten">
|
|
Auf allen Vektoren in Qdrant ist das Flag <code>training_allowed: false</code> gesetzt.
|
|
Kundeninhalte werden <strong>ausschliesslich fuer RAG-Suchen</strong> innerhalb des
|
|
Kunden-Namespace verwendet.
|
|
</InfoBox>
|
|
</>
|
|
)
|
|
}
|