feat(bezpieczeństwo): konta imienne i dziennik audytowy (PRE-17) #54

Merged
gitea merged 1 commits from feat/pre17-accounts-audit into master 2026-08-03 19:57:04 +00:00
Owner

Jedno wspólne hasło nie mówiło, kto sięgał do baz, a odebranie dostępu jednej
osobie wymagało zmiany hasła wszystkim. Przy bazach o realnej wartości handlowej
to za mało.

Konta imienne

APP_USERS='alicja:scrypt$…,bartek:scrypt$…'. Hash liczy scrypt ze stdlib
zero nowych zależności, hasła nie ma w konfiguracji jawnie. Zakładanie konta:
scripts/make_user.py (hasło interaktywnie — nie trafia do historii powłoki ani
listy procesów). Odebranie dostępu = usunięcie wpisu, reszta nie zmienia haseł.

Gdy APP_USERS jest ustawione, wspólne APP_PASSWORD przestaje działać
(ostrzeżenie przy starcie) — działające obok kont byłoby tylnym wejściem bez śladu
w dzienniku, czyli problemem, który to wymaganie zamyka. Dopóki APP_USERS nie
jest ustawione, stary tryb działa jak dotąd (zgodność wstecz — aktualizacja nie
wywraca wdrożenia).

Dziennik audytowy

AUDYT user=alicja ip=10.1.2.3 method=POST path=/interpret status=200 records=428 ms=1530

records jest tu sednem: pojedyncze zapytanie wygląda niewinnie, ale suma pokazuje
powolne wypompowywanie bazy przez osobę uprawnioną — czego żadne
uwierzytelnienie nie wykryje. Liczone dla wyszukiwarki sygnifikatorów, raportu i
eksportu do Excela (ten wynosi najwięcej naraz). W logach nie ma treści
ani rekordów, ani promptów, ani danych urodzeniowych.

Dwa realne błędy złapane po drodze (oba z testami regresji)

  1. Błąd zastany: secrets.compare_digest rzuca TypeError na znakach spoza
    ASCII — hasło z polskimi literami wywracało logowanie błędem 500 zamiast
    zwykłej odmowy. Porównujemy teraz bajty.
  2. Dziennik był pusty na żywym serwerze: domyślna konfiguracja uvicorna nie
    obsługuje naszych loggerów. Niewidoczny dziennik jest gorszy niż jego brak
    (złudzenie kontroli) → audyt dostał własny handler na stdout.

Weryfikacja

Na żywym serwerze: dwa konta z hashem → 200/200, złe hasło → 401, nieznany login →
401, hasło z polskimi znakami → 401 (dawniej 500); wpisy audytowe faktycznie
wychodzą. Instrukcja: docs/konta-i-audyt.md.
Testy: +15, prezentacja 243.

Domyka PRE-17. Zostaje „czysto": PRE-09/DAN-15 (przegląd baz NFS + toggle).

Jedno wspólne hasło nie mówiło, **kto** sięgał do baz, a odebranie dostępu jednej osobie wymagało zmiany hasła wszystkim. Przy bazach o realnej wartości handlowej to za mało. ## Konta imienne `APP_USERS='alicja:scrypt$…,bartek:scrypt$…'`. Hash liczy **scrypt ze stdlib** — zero nowych zależności, hasła nie ma w konfiguracji jawnie. Zakładanie konta: `scripts/make_user.py` (hasło interaktywnie — nie trafia do historii powłoki ani listy procesów). **Odebranie dostępu = usunięcie wpisu**, reszta nie zmienia haseł. Gdy `APP_USERS` jest ustawione, wspólne `APP_PASSWORD` **przestaje działać** (ostrzeżenie przy starcie) — działające obok kont byłoby tylnym wejściem bez śladu w dzienniku, czyli problemem, który to wymaganie zamyka. Dopóki `APP_USERS` nie jest ustawione, stary tryb działa jak dotąd (**zgodność wstecz** — aktualizacja nie wywraca wdrożenia). ## Dziennik audytowy ``` AUDYT user=alicja ip=10.1.2.3 method=POST path=/interpret status=200 records=428 ms=1530 ``` `records` jest tu sednem: pojedyncze zapytanie wygląda niewinnie, ale suma pokazuje **powolne wypompowywanie bazy przez osobę uprawnioną** — czego żadne uwierzytelnienie nie wykryje. Liczone dla wyszukiwarki sygnifikatorów, raportu i **eksportu do Excela** (ten wynosi najwięcej naraz). **W logach nie ma treści** — ani rekordów, ani promptów, ani danych urodzeniowych. ## Dwa realne błędy złapane po drodze (oba z testami regresji) 1. **Błąd zastany:** `secrets.compare_digest` rzuca `TypeError` na znakach spoza ASCII — hasło z polskimi literami wywracało logowanie **błędem 500** zamiast zwykłej odmowy. Porównujemy teraz bajty. 2. Dziennik był **pusty na żywym serwerze**: domyślna konfiguracja uvicorna nie obsługuje naszych loggerów. Niewidoczny dziennik jest gorszy niż jego brak (złudzenie kontroli) → audyt dostał własny handler na stdout. ## Weryfikacja Na żywym serwerze: dwa konta z hashem → 200/200, złe hasło → 401, nieznany login → 401, hasło z polskimi znakami → 401 (dawniej 500); wpisy audytowe faktycznie wychodzą. Instrukcja: [`docs/konta-i-audyt.md`](docs/konta-i-audyt.md). Testy: **+15**, prezentacja **243**. Domyka **PRE-17**. Zostaje „czysto": PRE-09/DAN-15 (przegląd baz NFS + toggle).
gitea added 1 commit 2026-08-03 19:50:10 +00:00
feat(bezpieczeństwo): konta imienne i dziennik audytowy (PRE-17)
Testy / Testy warstwy logicznej (silnik) (push) Successful in 10m30s
Testy / Testy warstwy prezentacji (dostęp do baz) (push) Successful in 9m29s
Testy / Build obrazu silnika B (swisseph) (push) Successful in 11s
Testy / Kontrola składni wszystkich warstw (push) Successful in 8s
Testy / Testy warstwy logicznej (silnik) (pull_request) Successful in 10m27s
Testy / Testy warstwy prezentacji (dostęp do baz) (pull_request) Successful in 9m28s
Testy / Build obrazu silnika B (swisseph) (pull_request) Successful in 11s
Testy / Kontrola składni wszystkich warstw (pull_request) Successful in 7s
c6b6f43cb9
Jedno wspólne hasło nie mówiło, KTO sięgał do baz, a odebranie dostępu jednej
osobie wymagało zmiany hasła wszystkim. Przy bazach o realnej wartości handlowej
to za mało.

KONTA IMIENNE: `APP_USERS='alicja:scrypt$…,bartek:scrypt$…'`. Hash liczy scrypt ze
STDLIB — zero nowych zależności; hasła nie ma w konfiguracji jawnie. Zakładanie
konta: scripts/make_user.py (hasło interaktywnie, nie w historii powłoki).
Odebranie dostępu = usunięcie wpisu, reszta nie zmienia haseł.

Gdy APP_USERS jest ustawione, wspólne APP_PASSWORD PRZESTAJE działać (ostrzeżenie
przy starcie) — działające obok kont byłoby tylnym wejściem bez śladu w dzienniku.
Dopóki APP_USERS nie jest ustawione, stary tryb działa jak dotąd (zgodność wstecz).

DZIENNIK AUDYTOWY: każde żądanie zostawia wpis „kto, skąd, co, status, ILE
rekordów, ile ms". Liczba rekordów jest tu sednem — pojedyncze zapytanie wygląda
niewinnie, suma pokazuje powolne wypompowywanie bazy przez osobę uprawnioną.
Liczona dla wyszukiwarki sygnifikatorów, raportu i eksportu do Excela (ten wynosi
najwięcej naraz). W logach NIE MA treści — ani rekordów, ani promptów.

Dwa realne błędy złapane po drodze:
- `secrets.compare_digest` rzuca TypeError na znakach spoza ASCII, więc hasło z
  polskimi literami wywracało logowanie błędem 500 zamiast odmowy (błąd ZASTANY,
  sprzed tej zmiany) — porównujemy teraz bajty;
- dziennik był PUSTY na żywym serwerze: domyślna konfiguracja uvicorna nie
  obsługuje naszych loggerów. Niewidoczny dziennik jest gorszy niż jego brak,
  więc audyt dostał własny handler na stdout. Oba przypadki mają testy regresji.

Instrukcja wdrożeniowa: docs/konta-i-audyt.md. Testy: +15. Prezentacja 243.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
gitea merged commit d3d9b365fe into master 2026-08-03 19:57:04 +00:00
gitea deleted branch feat/pre17-accounts-audit 2026-08-03 19:57:04 +00:00
Sign in to join this conversation.
No Reviewers
No Label
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: gitea/astrololo#54