Skip to content

feat(hasla): polityka haseł wg NIST — min. 15 znaków, bez rotacji - #892

Merged
mpasternak merged 2 commits into
devfrom
feat/polityka-hasel
Oct 24, 2026
Merged

mpasternak merged 2 commits into
devfrom
feat/polityka-hasel

Conversation

@mpasternak

@mpasternak mpasternak commented Oct 24, 2026 •

Copy link
Copy Markdown
Member

Co się zmienia

Polityka haseł zgodna z NIST SP 800-63B (rev. 4): długość zamiast reguł złożoności, bez cyklicznej rotacji.

  • Min. 15 znaków (PASSWORD_MIN_LENGTH, env DJANGO_BPP_PASSWORD_MIN_LENGTH).
  • Bez reguł złożoności: wyzerowane PASSWORD_MIN_LETTERS/NUMBERS/SYMBOLS i entropia. Zostają: popularne ciągi (qwerty, 12345…), >3 jednakowe znaki z rzędu, e-mail jako hasło, historia 12 haseł bez zmian.
  • AUTH_PASSWORD_VALIDATORS (długość 15, CommonPasswordValidator, UserAttributeSimilarityValidator). Wcześniej nie było ich wcale, więc w adminie i kreatorze pierwszego uruchomienia przechodziło każde hasło (test Playwright zakładał konto z hasłem as).
  • Rotacja domyślnie wyłączona: PASSWORD_DURATION_SECONDS = 0. Instalacja może ją przywrócić przez DJANGO_BPP_PASSWORD_DURATION_SECONDS.
  • Istniejące hasła zostają ważne: nowa długość obowiązuje od najbliższej zmiany lub resetu.
  • Podpowiedź przy polu nowego hasła, sekcja „Polityka haseł” w docs/administrator/zaawansowane.md, newsfragment.

Pułapka przy duration = 0

Middleware password_policies przy zerowym duration się wyłącza, ale PasswordHistory.objects.change_required() liczy now - timedelta(0). Przez to context processor uznawał każde hasło za przeterminowane, a base.html pokazywał na każdej stronie komunikat „Twoje hasło uległo przeterminowaniu” z pustym formularzem.

Testy

  • Nowy plik src/django_bpp/tests/test_polityka_hasel.py:
    • przy domyślnym duration=0 nie ma przekierowania ani komunikatu;
    • formularz przyjmuje 15+ znaków bez cyfr i symboli (także z polskimi znakami);
    • hasło 14-znakowe i ciąg powtórzonych znaków są odrzucane;
    • walidatory Django sprawdzają długość i popularne hasła.
  • Dwa istniejące testy egzekwowania rotacji (test_conditional_password_middleware, test_password_policies_session) włączają teraz rotację jawnie przez monkeypatch.
  • Test Playwright zakładania użytkownika używa hasła spełniającego politykę.
  • Lokalnie testy BPP nie były uruchamiane: maszyna była zajęta cudzymi przebiegami, więc weryfikację robi CI. Suita forka przechodzi lokalnie (64 passed).

Do sprawdzenia w bpp-deploy

Czy któraś instalacja nie ustawia jawnie DJANGO_BPP_PASSWORD_DURATION_SECONDS. Jeśli tak, rotacja zostanie u niej włączona.

Wymuszona zmiana hasła nadal działa

Wyłączamy tylko rotację cykliczną. Wpis PasswordChangeRequired dodany w adminie (np. po podejrzeniu wycieku hasła) nadal przekierowuje użytkownika do zmiany hasła, a zapis nowego hasła kasuje ten wpis.

  • Przy duration=0 biblioteka nie sprawdzała nic, więc ConditionalPasswordChangeMiddleware i conditional_password_status sprawdzają wtedy sam ten wpis.
  • Testy: przekierowanie i komunikat przy wpisie, brak przekierowania na samej stronie zmiany hasła.

Komenda wymus_zmiane_hasel

manage.py wymus_zmiane_hasel [--dry-run] [--username X ...] [--grupa G ...] zakłada wpis PasswordChangeRequired aktywnym kontom z hasłem BPP (has_usable_password), a konta wyłącznie OAuth pomija.

  • Ponowne uruchomienie jest bezpieczne: nie dubluje wpisów.
  • Nieznany login lub nieznana grupa kończy się CommandError i nic nie zostaje zapisane.
  • Testy: src/bpp/tests/test_management_commands_wymus_zmiane_hasel.py.

🤖 Generated with Claude Code

https://claude.ai/code/session_01SgHJbMvTRmBeVQZ5bD37gj

@gitguardian

gitguardian Bot commented Oct 24, 2026 •

Copy link
Copy Markdown

️✅ There are no secrets present in this pull request anymore.

If these secrets were true positive and are still valid, we highly recommend you to revoke them.
While these secrets were previously flagged, we no longer have a reference to the
specific commits where they were detected. Once a secret has been leaked into a git
repository, you should consider it compromised, even if it was deleted immediately.
Find here more information about risks.


🦉 GitGuardian detects secrets in your source code to help developers and security teams secure the modern development process. You are seeing this because you or someone else with access to this repository has authorized GitGuardian to scan your pull request.

- PASSWORD_MIN_LENGTH = 15 (DJANGO_BPP_PASSWORD_MIN_LENGTH), bez wymogu
  liter/cyfr/symboli i entropii; zostają: popularne ciągi, >3 jednakowe
  znaki z rzędu, e-mail jako hasło, historia 12 haseł
- AUTH_PASSWORD_VALIDATORS (długość, popularne hasła, podobieństwo do
  loginu) — ta sama polityka w adminie i kreatorze
- PASSWORD_DURATION_SECONDS domyślnie 0 (rotacja wyłączona); przy 0
  middleware i context processor egzekwują tylko ręczne wymuszenie
  (PasswordChangeRequired) — obejście buga w password-policies <= 0.9.4,
  poprawka: iplweb/django-password-policies-iplweb#56
- komenda wymus_zmiane_hasel (--dry-run, --username, --grupa)
- podpowiedź przy polu nowego hasła, dokumentacja, newsfragment

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SgHJbMvTRmBeVQZ5bD37gj
Zawiera poprawkę change_required() przy PASSWORD_DURATION_SECONDS = 0
(iplweb/django-password-policies-iplweb#56).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SgHJbMvTRmBeVQZ5bD37gj
@mpasternak
mpasternak merged commit 61fa94d into dev Oct 24, 2026
25 of 26 checks passed
@mpasternak
mpasternak deleted the feat/polityka-hasel branch October 24, 2026 10:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant