feat(astrololo): klucze szyfrowania lacz miedzy warstwami (PRE-16)

Domyka PRE-16 po stronie manifestow. Kod (astrololo#21) potrafi juz szyfrowac
ruch miedzy warstwami AES-256-GCM; tu dokladamy klucze i wymuszenie.

- astrololo-link: nowy sekret z dwoma kluczami (LINK_KEY_PRESENTATION_LOGIC,
  LINK_KEY_LOGIC_DATA), tworzony POZA repo jak pozostale. Osobny klucz na pare
  rozmowcow: przejecie klucza prezentacji nie otwiera warstwy danych. Logika
  bierze oba, prezentacja i dane wylacznie swoj (secretKeyRef).
- LINK_ENCRYPTION_REQUIRED=true we wszystkich trzech: bez klucza pod NIE wstaje,
  a klient nie wysyla niczego. Fail-closed w obie strony jest celowy — usluga,
  ktora wstala i po cichu nie szyfruje, jest gorsza niz CrashLoop, bo awarii
  nie widac.

README: sekcja o sekrecie astrololo-link (tworzenie, wymiana, restart calej
trojki naraz) oraz uczciwa nota, ze szyfrowane sa ciala, nie naglowki — sciezka
i token jada czytelnie, ale sam token bez klucza nic nie daje.

Sprawdzone: kubectl kustomize + apply --dry-run=server przechodza dla obu
profili. Pelna instrukcja wdrozenia: docs/wdrozenie-pre16.md w repo astrololo.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-07-22 23:52:41 +02:00
parent d4a57cc4f5
commit a30a4afece
4 changed files with 72 additions and 0 deletions
+36
View File
@@ -125,6 +125,39 @@ Certyfikat serwera żyje 90 dni i odnawia się sam 30 dni przed końcem. Termin
krótki **celowo** — odnawianie sprawdza się wtedy w praktyce co kwartał, a nie
dopiero za dziesięć lat, gdy nikt nie będzie pamiętał, jak to było skonfigurowane.
## ⚠️ Sekret `astrololo-link` — szyfrowanie między warstwami
Token międzywarstwowy mówi **kto** pyta, ale nie ukrywa **czego dotyczy odpowiedź**
— a płyną nią surowe wiersze oryginalnych baz. Kto podsłuchał ruch wewnątrz sieci
(drugi pod, mirror portu na switchu, zrzut z węzła), miał je w całości. Łącza są
więc szyfrowane **AES-256-GCM**, osobnym kluczem na każdą parę rozmówców.
```bash
kubectl -n astrololo create secret generic astrololo-link \
--from-literal=LINK_KEY_PRESENTATION_LOGIC="$(openssl rand -hex 32)" \
--from-literal=LINK_KEY_LOGIC_DATA="$(openssl rand -hex 32)"
```
Kluczy **nikt nigdy nie musi oglądać** — służą tylko usługom. Rozdzielenie jest
celowe: przejęcie klucza prezentacji nie daje dostępu do warstwy danych, gdzie
leżą całe bazy. Logika trzyma oba, bo rozmawia w obie strony; prezentacja i dane
dostają przez `secretKeyRef` wyłącznie swój.
**Pody nie wstaną bez tych kluczy** (`LINK_ENCRYPTION_REQUIRED=true`) — i tak ma
być. Usługa, która wstała i po cichu nie szyfruje, jest gorsza niż pod w CrashLoop,
bo awarii nie widać.
### Wymiana kluczy
```bash
kubectl -n astrololo create secret generic astrololo-link \
--from-literal=LINK_KEY_PRESENTATION_LOGIC="$(openssl rand -hex 32)" \
--from-literal=LINK_KEY_LOGIC_DATA="$(openssl rand -hex 32)" \
--dry-run=client -o yaml | kubectl apply -f -
kubectl -n astrololo rollout restart deploy/presentation deploy/logic deploy/data
```
Restart **wszystkich trzech naraz** — w trakcie wymiany warstwy chwilowo się nie
dogadują (klucze muszą być zgodne po obu stronach łącza).
## Klucze do modeli w chmurze — sekret `astrololo-llm` (opcjonalny)
Domyślnie działa **model lokalny** i nic nie opuszcza sieci. Żeby móc wybrać w UI
@@ -166,6 +199,9 @@ gdzie faktycznie stoi Ollama/vLLM. Konfiguracja jest **per dostawca**
- **Własne CA to nie to samo co publiczne zaufanie** — każde nowe urządzenie
wymaga importu korzenia (krok 3 powyżej). Gdyby aplikacja miała kiedyś wyjść
na świat, właściwą drogą jest Let's Encrypt przez DNS-01.
- **Szyfrowane są ciała żądań, nie nagłówki** — ścieżka (`/search`) i token
międzywarstwowy jadą czytelnie. Sam token nikomu nic nie daje: bez klucza łącza
każde żądanie kończy się odmową. Pełne ukrycie metadanych wymagałoby mTLS.
- **NFS `192.168.1.34:/mnt/Tank1/astrololo`** — kto ma dostęp do share'u, bierze
pliki baz **z pominięciem całej aplikacji**. Do zamknięcia po stronie infrastruktury
(eksport tylko dla IP węzłów, `root_squash`, najlepiej read-only).
+11
View File
@@ -29,6 +29,17 @@ spec:
- name: INTERNAL_TOKEN
valueFrom:
secretKeyRef: { name: astrololo-auth, key: INTERNAL_TOKEN }
# Szyfrowanie łącza między warstwami (PRE-16). OSOBNY klucz na każdą
# parę rozmówców: przejęcie klucza prezentacji nie otwiera warstwy
# danych, gdzie leżą całe bazy. Sekret tworzony POZA repo — patrz README.
- name: LINK_KEY_LOGIC_DATA
valueFrom:
secretKeyRef: { name: astrololo-link, key: LINK_KEY_LOGIC_DATA }
# Bez klucza usługa ma NIE wstać, a klient ma nie wysłać niczego.
# Sam serwer broni się fail-closed, ale to za mało: klient bez klucza
# zdążyłby wypuścić zapytanie jawnym tekstem, zanim dostanie odmowę.
- name: LINK_ENCRYPTION_REQUIRED
value: "true"
volumeMounts:
- name: cache
mountPath: /app/.cache
+14
View File
@@ -26,6 +26,20 @@ spec:
- name: INTERNAL_TOKEN
valueFrom:
secretKeyRef: { name: astrololo-auth, key: INTERNAL_TOKEN }
# Szyfrowanie łącza między warstwami (PRE-16). OSOBNY klucz na każdą
# parę rozmówców: przejęcie klucza prezentacji nie otwiera warstwy
# danych, gdzie leżą całe bazy. Sekret tworzony POZA repo — patrz README.
- name: LINK_KEY_PRESENTATION_LOGIC
valueFrom:
secretKeyRef: { name: astrololo-link, key: LINK_KEY_PRESENTATION_LOGIC }
- name: LINK_KEY_LOGIC_DATA
valueFrom:
secretKeyRef: { name: astrololo-link, key: LINK_KEY_LOGIC_DATA }
# Bez klucza usługa ma NIE wstać, a klient ma nie wysłać niczego.
# Sam serwer broni się fail-closed, ale to za mało: klient bez klucza
# zdążyłby wypuścić zapytanie jawnym tekstem, zanim dostanie odmowę.
- name: LINK_ENCRYPTION_REQUIRED
value: "true"
# --- Model językowy (LOG-31) ---
# Domyślnie LOKALNY: prompt niesie oryginalne opisy z baz, więc nic nie
+11
View File
@@ -37,6 +37,17 @@ spec:
# nagłówek staje się furtką do ominięcia limitu.
- name: TRUST_PROXY
value: "true"
# Szyfrowanie łącza między warstwami (PRE-16). OSOBNY klucz na każdą
# parę rozmówców: przejęcie klucza prezentacji nie otwiera warstwy
# danych, gdzie leżą całe bazy. Sekret tworzony POZA repo — patrz README.
- name: LINK_KEY_PRESENTATION_LOGIC
valueFrom:
secretKeyRef: { name: astrololo-link, key: LINK_KEY_PRESENTATION_LOGIC }
# Bez klucza usługa ma NIE wstać, a klient ma nie wysłać niczego.
# Sam serwer broni się fail-closed, ale to za mało: klient bez klucza
# zdążyłby wypuścić zapytanie jawnym tekstem, zanim dostanie odmowę.
- name: LINK_ENCRYPTION_REQUIRED
value: "true"
resources:
requests: { cpu: "100m", memory: "128Mi" }
limits: { cpu: "300m", memory: "256Mi" }