docs(bezpieczeństwo): runbook zamknięcia dostępu do baz na NFS (DAN-25)
build / build (push) Successful in 19s
Testy / Testy warstwy logicznej (silnik) (push) Successful in 10m29s
Testy / Testy warstwy prezentacji (dostęp do baz) (push) Successful in 9m28s
Testy / Testy warstwy bazodanowej (ochrona baz) (push) Successful in 9m28s
Testy / Build obrazu silnika B (swisseph) (push) Successful in 14s
Testy / Kontrola składni wszystkich warstw (push) Successful in 11s
build / build (push) Successful in 19s
Testy / Testy warstwy logicznej (silnik) (push) Successful in 10m29s
Testy / Testy warstwy prezentacji (dostęp do baz) (push) Successful in 9m28s
Testy / Testy warstwy bazodanowej (ochrona baz) (push) Successful in 9m28s
Testy / Build obrazu silnika B (swisseph) (push) Successful in 14s
Testy / Kontrola składni wszystkich warstw (push) Successful in 11s
Bazy leżą na udziale osiągalnym z całej sieci — to najkrótsza droga do wycieku, z pominięciem logowania, limitów, audytu i canary. Runbook zawęża udział `astrololo` do trzech węzłów k3s, ustawia tylko odczyt i root_squash. Krok po kroku, komenda po komendzie: rozpoznanie → dowód dziury (montowanie z maszyny spoza klastra) → kopia konfiguracji → zmiana → cztery testy weryfikacyjne → ścieżka wycofania. Dwie zasady wynikające z tego, że Tank1 obsługuje CAŁY homelab (Proxmox, conjurer z zapisem, media, LXC-e, stacja robocza): - ruszamy WYŁĄCZNIE udział astrololo, nigdy globalnych ustawień usługi NFS — inaczej padną VM-y, bot i biblioteka mediów; - w TrueNAS SCALE nie edytuje się /etc/exports ręcznie (middleware nadpisze) — wszystko przez midclt albo GUI. Runbook każe też sprawdzić nazwy pól w API PRZED zapisem, bo middleware zmieniało je między wersjami SCALE (path vs paths). Opisane pułapki: hookscript Proxmoxa czekający na showmount przed startem VM; utrata możliwości wgrywania baz przez NFS po ro=true; lista IP to nie uwierzytelnianie (docelowo NFSv4+Kerberos, jak mówi samo wymaganie). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit was merged in pull request #57.
This commit is contained in:
@@ -0,0 +1,195 @@
|
|||||||
|
# DAN-25 — zamknięcie dostępu do baz na NFS (TrueNAS SCALE)
|
||||||
|
|
||||||
|
Bazy interpretacyjne leżą na `192.168.1.34:/mnt/Tank1/astrololo`. Dziś udział jest
|
||||||
|
osiągalny z całej sieci, więc **kto ma dostęp do LAN, bierze kompletne bazy
|
||||||
|
w oryginale — z pominięciem logowania, limitów, audytu i canary**. Żadne
|
||||||
|
zabezpieczenie w kodzie tego nie zamyka: to najkrótsza droga do wycieku.
|
||||||
|
|
||||||
|
Cel: udział `astrololo` widoczny **tylko dla trzech węzłów k3s**, **tylko do
|
||||||
|
odczytu**, z **root_squash**.
|
||||||
|
|
||||||
|
## ⚠️ Zasada nadrzędna: ruszamy WYŁĄCZNIE udział astrololo
|
||||||
|
|
||||||
|
Tank1 obsługuje cały homelab — Proxmox (`proxmox-NFS`), conjurera (`conjurer_swap`,
|
||||||
|
z **zapisem**), media, LXC-e, stację roboczą. **Nie dotykamy globalnych ustawień
|
||||||
|
usługi NFS ani innych udziałów** — inaczej wywalimy VM-y, bota i bibliotekę mediów.
|
||||||
|
Każda komenda niżej celuje w jeden konkretny udział.
|
||||||
|
|
||||||
|
Druga zasada: **w TrueNAS SCALE nie edytuje się `/etc/exports` ręcznie.** Plik
|
||||||
|
generuje middleware i nadpisze każdą ręczną zmianę. Wszystko robimy przez `midclt`
|
||||||
|
(albo GUI: *Shares → Unix (NFS) Shares*).
|
||||||
|
|
||||||
|
## Ustalone dane
|
||||||
|
|
||||||
|
| Co | Wartość |
|
||||||
|
|---|---|
|
||||||
|
| NAS | `192.168.1.34` (TrueNAS SCALE / Community Edition) |
|
||||||
|
| Udział do zamknięcia | `/mnt/Tank1/astrololo` |
|
||||||
|
| Węzły k3s (jedyni uprawnieni) | `192.168.1.73` (server), `192.168.1.80` (agent2), `192.168.1.81` (agent1) |
|
||||||
|
| Kto montuje astrololo | wyłącznie pod `data` w ns `astrololo`, **read-only** |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Faza 0 — rozpoznanie (nic nie zmienia)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
ssh admin@192.168.1.34
|
||||||
|
```
|
||||||
|
|
||||||
|
Wersja systemu (potwierdza, że komendy niżej pasują):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
midclt call system.version
|
||||||
|
```
|
||||||
|
|
||||||
|
Lista udziałów NFS z ich obecnymi ustawieniami — **stąd bierzemy ID udziału astrololo**:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
midclt call sharing.nfs.query | python3 -m json.tool
|
||||||
|
```
|
||||||
|
|
||||||
|
> W wyniku poszukaj wpisu ze ścieżką `/mnt/Tank1/astrololo` i zapamiętaj jego `id`.
|
||||||
|
> **Sprawdź też, jak nazywają się pola** (`path` vs `paths`, `hosts`, `networks`,
|
||||||
|
> `ro`, `maproot_user`, `mapall_user`) — middleware zmieniało ich nazwy między
|
||||||
|
> wersjami SCALE. Dalsze komendy używają nazw z Twojego wyniku.
|
||||||
|
|
||||||
|
Kto jest teraz podłączony (żeby nie odciąć czegoś w trakcie pracy):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
ss -tn state established '( sport = :2049 )'
|
||||||
|
```
|
||||||
|
|
||||||
|
## Faza 1 — dowód dziury (zrób PRZED zmianą)
|
||||||
|
|
||||||
|
Na **stacji roboczej** (Mac mini, czyli host spoza klastra):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
mkdir -p /tmp/nfs-test && sudo mount -t nfs -o ro,vers=3 192.168.1.34:/mnt/Tank1/astrololo /tmp/nfs-test
|
||||||
|
```
|
||||||
|
|
||||||
|
```bash
|
||||||
|
ls -la /tmp/nfs-test | head
|
||||||
|
```
|
||||||
|
|
||||||
|
Jeśli widzisz pliki baz — **to jest dokładnie problem, który zamykamy**. Odmontuj:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo umount /tmp/nfs-test
|
||||||
|
```
|
||||||
|
|
||||||
|
## Faza 2 — kopia obecnej konfiguracji (możliwość cofnięcia)
|
||||||
|
|
||||||
|
Na NAS-ie, podstaw `<ID>` z Fazy 0:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
midclt call sharing.nfs.query '[["id","=",<ID>]]' > /root/astrololo-nfs-share.backup.json && cat /root/astrololo-nfs-share.backup.json
|
||||||
|
```
|
||||||
|
|
||||||
|
## Faza 3 — zawężenie udziału
|
||||||
|
|
||||||
|
Jedna komenda ustawia wszystkie trzy zabezpieczenia naraz: listę hostów, tylko
|
||||||
|
odczyt i root_squash. Podstaw `<ID>`:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
midclt call sharing.nfs.update <ID> '{"hosts": ["192.168.1.73", "192.168.1.80", "192.168.1.81"], "ro": true, "maproot_user": null, "maproot_group": null, "mapall_user": null, "mapall_group": null}'
|
||||||
|
```
|
||||||
|
|
||||||
|
Co robi każdy element:
|
||||||
|
|
||||||
|
| Ustawienie | Znaczenie |
|
||||||
|
|---|---|
|
||||||
|
| `hosts` | eksport **tylko** dla trzech węzłów k3s — reszta LAN przestaje widzieć udział |
|
||||||
|
| `ro: true` | tylko odczyt; aplikacja i tak montuje read-only, więc niczego nie łamie |
|
||||||
|
| `maproot_*`, `mapall_*` = `null` | **root_squash**: root z klienta nie jest rootem na udziale |
|
||||||
|
|
||||||
|
Zastosuj i sprawdź, że middleware przepisał eksporty:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
midclt call service.reload nfs && exportfs -v | grep -A1 astrololo
|
||||||
|
```
|
||||||
|
|
||||||
|
> Jeśli Twoja wersja nie ma `service.reload`, użyj GUI (*Shares → NFS → zapisz*),
|
||||||
|
> co wymusi to samo.
|
||||||
|
|
||||||
|
## Faza 4 — weryfikacja (wszystkie cztery testy)
|
||||||
|
|
||||||
|
**1. Spoza klastra ma NIE działać.** Na Macu:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo mount -t nfs -o ro,vers=3 192.168.1.34:/mnt/Tank1/astrololo /tmp/nfs-test
|
||||||
|
```
|
||||||
|
|
||||||
|
Oczekiwane: `access denied` / `Operation not permitted`. **Jeśli montuje się dalej —
|
||||||
|
zmiana nie zadziałała, nie idź dalej.**
|
||||||
|
|
||||||
|
**2. Z węzła klastra ma działać.**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
ssh 192.168.1.73 'sudo mount -t nfs -o ro 192.168.1.34:/mnt/Tank1/astrololo /mnt/test && ls /mnt/test | head -3 && sudo umount /mnt/test'
|
||||||
|
```
|
||||||
|
|
||||||
|
**3. Aplikacja żyje.** Pody muszą wstać i realnie czytać bazy:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
kubectl -n astrololo rollout restart deploy/data && kubectl -n astrololo rollout status deploy/data
|
||||||
|
```
|
||||||
|
|
||||||
|
```bash
|
||||||
|
kubectl -n astrololo exec deploy/data -- ls /app/data_files | head -3
|
||||||
|
```
|
||||||
|
|
||||||
|
**4. Reszta homelabu nietknięta** — conjurer (zapis!) i pozostałe udziały:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
kubectl -n conjurer get pods
|
||||||
|
```
|
||||||
|
|
||||||
|
```bash
|
||||||
|
midclt call sharing.nfs.query | python3 -c "import sys,json;[print(s.get('path') or s.get('paths'), '| hosts:', s.get('hosts'), '| ro:', s.get('ro')) for s in json.load(sys.stdin)]"
|
||||||
|
```
|
||||||
|
|
||||||
|
Oczekiwane: **tylko** astrololo ma zawężone `hosts` i `ro: true`; reszta bez zmian.
|
||||||
|
|
||||||
|
## Faza 5 — wycofanie (gdyby coś padło)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
midclt call sharing.nfs.update <ID> '{"hosts": [], "ro": false}'
|
||||||
|
```
|
||||||
|
|
||||||
|
```bash
|
||||||
|
midclt call service.reload nfs
|
||||||
|
```
|
||||||
|
|
||||||
|
To przywraca poprzedni stan (pełna kopia w `/root/astrololo-nfs-share.backup.json`).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Pułapki, o których warto wiedzieć
|
||||||
|
|
||||||
|
**Hookscript Proxmoxa.** Na Proxmoxie działa `wait-truenas.sh`, który przed startem
|
||||||
|
VM czeka w pętli na `showmount -e 192.168.1.34`. Zawężamy tylko udział astrololo,
|
||||||
|
więc `showmount` nadal zwróci pozostałe eksporty i pętla przejdzie. Mimo to sprawdź
|
||||||
|
po zmianie:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
ssh root@pve2 'showmount -e 192.168.1.34'
|
||||||
|
```
|
||||||
|
|
||||||
|
**Aktualizacja baz przestanie działać przez NFS.** Po `ro: true` nikt nie wgra
|
||||||
|
nowych plików baz przez ten udział — również Ty. Do wgrywania użyj GUI TrueNAS,
|
||||||
|
SMB albo SSH bezpośrednio na NAS-ie. To celowe: udział ma być drogą tylko do
|
||||||
|
czytania przez aplikację.
|
||||||
|
|
||||||
|
**`hosts` przyjmuje adresy IP, nie nazwy** — świadomie, żeby dostęp nie zależał od
|
||||||
|
DNS-u (AdGuard na `.57`). Gdyby doszedł czwarty węzeł k3s, trzeba dopisać jego IP,
|
||||||
|
inaczej pod `data` na nim nie wstanie.
|
||||||
|
|
||||||
|
**To nie jest uwierzytelnianie.** Lista IP zatrzymuje przypadkowy i oportunistyczny
|
||||||
|
dostęp, ale adres da się podszyć w tej samej sieci. Docelowo (poza zakresem tego
|
||||||
|
kroku): NFSv4 + Kerberos albo przeniesienie plików na wolumen nieosiągalny poza
|
||||||
|
klastrem — tak mówi samo wymaganie DAN-25.
|
||||||
|
|
||||||
|
## Po wykonaniu
|
||||||
|
|
||||||
|
Zaktualizuj status DAN-25 w `docs/astrololo_wymagania.xlsx` na **Zrobione** (albo
|
||||||
|
**W trakcie**, jeśli zostawiasz Kerberosa jako etap docelowy).
|
||||||
Reference in New Issue
Block a user