Files
astrololo/docs/dan25-zabezpieczenie-nfs.md
gitea 6e7cfcbbd7
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
docs(bezpieczeństwo): runbook zamknięcia dostępu do baz na NFS (DAN-25)
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>
2026-08-04 14:43:12 +00:00

6.5 KiB

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)

ssh admin@192.168.1.34

Wersja systemu (potwierdza, że komendy niżej pasują):

midclt call system.version

Lista udziałów NFS z ich obecnymi ustawieniami — stąd bierzemy ID udziału astrololo:

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):

ss -tn state established '( sport = :2049 )'

Faza 1 — dowód dziury (zrób PRZED zmianą)

Na stacji roboczej (Mac mini, czyli host spoza klastra):

mkdir -p /tmp/nfs-test && sudo mount -t nfs -o ro,vers=3 192.168.1.34:/mnt/Tank1/astrololo /tmp/nfs-test
ls -la /tmp/nfs-test | head

Jeśli widzisz pliki baz — to jest dokładnie problem, który zamykamy. Odmontuj:

sudo umount /tmp/nfs-test

Faza 2 — kopia obecnej konfiguracji (możliwość cofnięcia)

Na NAS-ie, podstaw <ID> z Fazy 0:

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>:

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:

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:

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ć.

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:

kubectl -n astrololo rollout restart deploy/data && kubectl -n astrololo rollout status deploy/data
kubectl -n astrololo exec deploy/data -- ls /app/data_files | head -3

4. Reszta homelabu nietknięta — conjurer (zapis!) i pozostałe udziały:

kubectl -n conjurer get pods
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)

midclt call sharing.nfs.update <ID> '{"hosts": [], "ro": false}'
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:

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).