.. Zdroj: docs/admin-guide/source/05-security.rst, elza 18b7804099

.. _admin_security:

==========================
Autentizace a zabezpečení
==========================

Metody autentizace
==================

Elza podporuje tyto metody autentizace:

- **Interní účty** - uživatelé a hesla uložená v Elze (vždy k dispozici).
- **Active Directory (LDAP)** - jméno a heslo uživatele se ověří vůči
  doméně Active Directory.
- **Kerberos (SPNEGO)** - jednotné přihlášení (SSO) v doméně Windows,
  volitelně i ověření jména a hesla vůči KDC.
- **SSO hlavička** - reverzní proxy, která uživatele ověřila, předá jeho
  uživatelské jméno v HTTP hlavičce.
- **OAuth2 / JWT** - požadavky nesou token (bearer) vydaný poskytovatelem
  identit.
- **Osobní API klíče** - pro integrace volající rozhraní REST.

Metody lze kombinovat. Při přihlášení jménem a heslem (přihlašovací
formulář nebo HTTP Basic) se zkoušejí v tomto pořadí: Active Directory,
Kerberos, interní heslo. Platí první metoda, která heslo přijme.

Kromě OAuth2 všechny metody pouze ověřují identitu: **uživatel musí
v Elze již existovat** se stejným uživatelským jménem a musí být aktivní.
Uživatelé se nezakládají automaticky a skupiny ani role z adresářové
služby se nepoužívají; oprávnění se vždy přidělují v Elze.

První administrátor
===================

Dokud databáze neobsahuje žádného uživatele, nabízí aplikace *Úvodní
nastavení*, které založí prvního administrátora; viz
:ref:`admin_install_first_admin`. Jeho endpointy (``/api/v1/setup``) jsou
dostupné bez přihlášení a uživatele založí, jen dokud žádný uživatel
neexistuje. Do té doby může prvního administrátora založit kdokoli, kdo se
k aplikaci dostane; založte jej proto dříve, než aplikaci zpřístupníte
v síti. Jakmile existuje jakýkoli uživatel, je úvodní nastavení trvale
uzavřeno.

Uživatele lze nastavit také v konfiguraci, v seznamu
``elza.security.override``; viz :ref:`admin_install_users_from_config`.
Seznam se uplatní při každém startu: chybějící uživatel se založí jako
administrátor bez hesla v databázi, deaktivovaný uživatel se aktivuje
a heslo existujícího uživatele v databázi se nemění. Uvedený uživatel se
přihlásí svým vlastním heslem nebo heslem z konfigurace. Heslo
z konfigurace je prostý text a platí vedle vlastního hesla uživatele;
položku odstraňte, jakmile ji nepotřebujete.

Výchozí uživatel
================

Nová instalace obsahuje vestavěného uživatele ``admin`` s heslem
``admin`` a oprávněním administrátora. Existuje pouze v konfiguraci,
nikoli v databázi, a je dostupný, dokud v databázi neexistuje uživatel
stejného jména.

.. warning::

   Výchozího uživatele vypněte, jakmile existují účty administrátorů:

   .. code-block:: yaml

      elza:
        security:
          allowDefaultUser: false

   Výchozí uživatel se rozpoznává pouze podle jména. Dokud je zapnutý,
   metody SSO hlavička, Kerberos, Active Directory a OAuth2 přijmou
   identitu ``admin`` bez hesla a přidělí jí oprávnění administrátora.
   Při použití kterékoli z těchto metod výchozího uživatele vždy vypněte.
   Dokud je výchozí uživatel zapnutý, nezakládejte ani databázového
   uživatele se jménem ``admin``: jeho vlastní heslo a oprávnění by byly
   ignorovány.

.. list-table::
   :header-rows: 1
   :widths: 36 18 46

   * - Klíč
     - Výchozí hodnota
     - Význam
   * - ``elza.security.allowDefaultUser``
     - ``true``
     - Zapíná výchozího uživatele.
   * - ``elza.security.defaultUsername``
     - ``admin``
     - Jméno výchozího uživatele.
   * - ``elza.security.defaultPassword``
     - hash hesla ``admin``
     - Heslo výchozího uživatele jako zakódovaný hash (``{bcrypt}...``),
       nikoli jako prostý text.

Interní účty a hesla
====================

Uživatelé se zakládají v modulu *Administrace* > *Uživatelé*. Hesla se
ukládají jako hash bcrypt. Hesla ze starých verzí uložená pomocí SHA-256
se převedou na bcrypt při dalším přihlášení uživatele heslem.

Když se deaktivovaný uživatel přihlásí správným heslem, přihlašovací
formulář oznámí, že je účet deaktivovaný. Při chybném hesle formulář
zobrazí stejnou zprávu jako pro neznámého uživatele ("Neplatné uživatelské
jméno nebo heslo"), takže neprozradí, zda účet existuje nebo je
deaktivovaný.

``elza.security.salt`` slouží pouze k ověření těchto starých hashů
SHA-256. Neměňte jej: uživatelé, jejichž heslo ještě nebylo převedeno, by
se už nemohli přihlásit a administrátor by jim musel heslo nastavit
znovu.

Uživatele, kteří mají heslo stále ve starém formátu (od aktualizace se
heslem nepřihlásili), vypíše dotaz:

.. code-block:: sql

   SELECT u.username FROM usr_user u
   JOIN usr_authentication a ON a.user_id = u.user_id
   WHERE a.auth_type = 'PASSWORD' AND a.auth_value NOT LIKE '{%';

Pravidla pro hesla
------------------

Pravidla pro interní hesla se nastavují v *Administrace* > *Uživatelé* >
*Pravidla pro hesla*; tlačítko vyžaduje oprávnění *Správa oprávnění
a uživatelů* (nebo oprávnění administrátora). Pravidla platí pro celou
instanci:

*Platnost hesla (dní)*
   Jak dlouho heslo platí od svého nastavení.
*Minimální délka hesla*
   Minimální počet znaků.
*Minimální počet skupin znaků*
   Z kolika ze čtyř skupin - malá písmena, velká písmena, číslice, ostatní
   znaky - musí heslo obsahovat alespoň jeden znak (1-4).

Prázdná hodnota nebo 0 pravidlo vypíná; nová instalace má všechna
pravidla vypnutá. Prázdné heslo se nepřijme nikdy.

Délka a skupiny znaků se kontrolují při každém nastavení hesla: když si
uživatel mění vlastní heslo, když administrátor nastavuje heslo
uživatele a když se uživatel zakládá nebo upravuje s novým heslem.
Administrátoři nejsou výjimkou; nepřijme se ani slabé dočasné heslo.
Existující hesla se nekontrolují, dokud se nezmění.

Platnost se počítá od okamžiku posledního nastavení hesla. Převod starého
hashe SHA-256 při přihlášení heslo nemění a lhůtu znovu nespouští.

.. warning::

   Hesla nastavená před aktualizací na verzi s pravidly pro hesla se
   počítají jako nastavená 1. 1. 2016. Zapnutí platnosti proto způsobí,
   že všechna hesla nezměněná od aktualizace okamžitě expirují: každý
   takový uživatel si musí heslo při příštím přihlášení změnit.

Expirované heslo a vyžadovaná změna hesla
-----------------------------------------

Když administrátor nastavuje heslo uživatele (*Administrace* >
*Uživatelé* > *Změnit heslo*), jsou k dispozici dvě volby:

*Vyžadovat změnu hesla při dalším přihlášení*
   Typicky pro dočasné heslo předávané uživateli.
*Heslo bez expirace*
   Vyjme účet z platnosti hesla, například technický účet.

Po přihlášení interním heslem, které expirovalo nebo jehož změna je
vyžadována, je přihlášení úspěšné a aplikace otevře dialog, který nelze
zavřít, dokud uživatel nenastaví nové heslo. Nové heslo musí splňovat
pravidla. Po změně se požadavek zruší a lhůta platnosti začne znovu.

Změnu hesla vynucuje pouze webový klient. Požadavky na rozhraní REST
v takové session blokovány nejsou.

Platnost a vyžadovaná změna se týkají jen přihlášení interním heslem.
Uživatelé přihlášení přes Active Directory, Kerberos, SSO hlavičku, OAuth2
nebo API klíč nejsou ke změně hesla nikdy vyzváni; pokud hesla ověřuje
Active Directory nebo Kerberos, použije se interní heslo jen tehdy, když
doména heslo odmítne. Vyzván není ani výchozí uživatel: jeho heslo se
nastavuje jen v konfiguraci (``elza.security.defaultPassword``) a v aplikaci
je změnit nelze.

Obnovení přístupu k účtu
------------------------

Pokud administrátor zapomněl heslo a žádný jiný administrátor mu nemůže
nastavit nové, obnoví se přístup pomocí uživatelů z konfigurace (viz
:ref:`admin_install_users_from_config`):

1. Přidejte uživatele s dočasným heslem do ``elza.security.override``
   v :file:`elza.yaml` a restartujte Elzu. Deaktivovaný uživatel se
   aktivuje; vlastní heslo uživatele v databázi se nemění.
2. Přihlaste se dočasným heslem a změňte heslo v aplikaci.
3. Odstraňte položku z :file:`elza.yaml` a restartujte Elzu. Do té doby
   platí dočasné heslo vedle nového.

Bezpečnostní auditní log zaznamená, že je dočasné heslo aktivní
(``override_active``), a každé přihlášení jím (``authentication_type``
``OVERRIDE``). Výchozí uživatel se tímto způsobem neobnovuje; jeho heslo
se nastavuje v konfiguraci (``elza.security.defaultPassword``).

Active Directory
================

.. code-block:: yaml

   elza:
     security:
       ldap:
         ad-domain: archiv.example
         ad-server: ldap://dc1.archiv.example/

``ad-domain``
   Doména Active Directory. Jejím nastavením se metoda zapne.
``ad-server``
   URL řadiče domény.

Uživatel se přihlašuje doménovým jménem a heslem. Poté, co doména heslo
přijme, Elza vyhledá uživatele podle zadaného jména; uživatele v Elze
zakládejte se stejnými jmény jako v doméně. Pokud doména heslo odmítne,
zkusí se interní heslo.

Při nastaveném Active Directory kontroluje kontrola stavu (viz
:doc:`09-monitorovani`) i spojení s řadičem domény.

Kerberos (SPNEGO)
=================

.. code-block:: yaml

   elza:
     security:
       kerberos:
         service-principal: HTTP/elza.archiv.example@ARCHIV.EXAMPLE
         keytab-location: /etc/elza/elza.keytab
         authenticate-with-password: true

``service-principal``
   Jméno služby (SPN) aplikace Elza. Jeho nastavením se metoda zapne.
``keytab-location``
   Cesta k souboru keytab s klíčem služby. Soubor smí číst pouze
   uživatel, pod kterým běží služba.
``authenticate-with-password``
   Ověřovat jména a hesla z přihlašovacího formuláře také vůči KDC
   (výchozí ``true``).
``kerberos-client-debug``, ``ticket-validator-debug``
   Ladicí výpisy klienta Kerberos a ověřování ticketů (výchozí
   ``false``).

Konfigurace Kerberos pro JVM (realm a KDC, :file:`krb5.conf`) se přebírá
z operačního systému nebo z nastavení Javy.

Při nastaveném Kerberos nabízí přihlašovací dialog jednotné přihlášení.
Prohlížeč se pak ověří doménovým ticketem uživatele; pro adresu Elzy musí
mít povolenou integrovanou autentizaci. Z principalu se odstraní realm a
uživatel se vyhledá podle zbytku jména (``jan.novak@ARCHIV.EXAMPLE`` se
změní na ``jan.novak``). Samotný realm se nekontroluje. Pokud jednotné
přihlášení selže, uživatel se může přihlásit formulářem.

SSO hlavička
============

Reverzní proxy nebo přístupová brána, která uživatele ověřuje, může
předávat uživatelské jméno v HTTP hlavičce:

.. code-block:: yaml

   elza:
     security:
       allowDefaultUser: false
       sso-header:
         user-header: X-SSO-User

Elza vyhledá uživatele podle hodnoty hlavičky. Pokud hlavička uvádí jiného
uživatele než aktuální session, session se nahradí.

.. warning::

   Elza hlavičce plně důvěřuje. Řešení je bezpečné, jen pokud:

   - je Elza dostupná výhradně přes proxy (naslouchá na ``127.0.0.1``
     nebo je port omezen firewallem),
   - proxy hlavičku u každého požadavku odstraní nebo přepíše, takže ji
     klient nemůže poslat sám,
   - je výchozí uživatel vypnutý.

Do ``elza.security.logoutUrl`` nastavte adresu odhlášení brány, aby
odhlášení z Elzy ukončilo i session na bráně.

OAuth2 / JWT
============

Elza může přijímat tokeny (``Authorization: Bearer ...``) vydané
poskytovatelem identit. Vystupuje pouze jako resource server;
přesměrování na přihlášení u poskytovatele neprovádí.

.. code-block:: yaml

   elza:
     security:
       o-auth2:
         key-url: https://idp.archiv.example/oauth/token_key
         permissions:
           - authority: ELZA_ADMIN
             permissions: [ADMIN]

``key-url``
   URL, které vrací veřejný klíč pro ověření podpisu tokenů, jako JSON
   s klíčem RSA ve formátu PEM v poli ``value``. Klíč se načte jednou při
   startu; pokud jej nelze načíst, aplikace nenastartuje. Tokeny musí být
   podepsány algoritmem RS256.
``permissions``
   Mapování hodnot z položky ``authorities`` tokenu na oprávnění Elzy.
   ``scope`` omezuje oprávnění na oblast archivních entit (podle kódu).
``user-scope``, ``user-ap-type``
   Oblast a třída archivních entit uživatelů zakládaných z tokenů;
   výchozí ``JWT_USERS`` a ``PERSON_INDIVIDUAL``. Třídu musí nabízet
   pravidla oblasti.

Položka ``sub`` tokenu je uživatelské jméno a ``name`` zobrazované jméno.
Na rozdíl od ostatních metod se neexistující uživatel založí, a to včetně
archivní entity osoby v oblasti ``user-scope``. Přímo přidělená oprávnění
uživatele se nahradí oprávněními odvozenými z tokenu. Údaje o uživateli se
ukládají do cache na pět minut, změna oprávnění nebo deaktivace se tedy
projeví do pěti minut.

Osobní API klíče
================

Integrace volají rozhraní REST s osobním API klíčem místo hesla
uživatele. Klíč patří uživateli a pracuje s jeho oprávněními; pro každou
integraci založte samostatného uživatele.

Uživatelé zakládají a ruší své klíče v uživatelském nastavení (kategorie
*Elza*). Celý klíč se zobrazí pouze jednou, při vytvoření; Elza ukládá jen
jeho hash. Administrátoři mohou zobrazit a zrušit klíče ostatních
uživatelů. Klíče lze zakládat a rušit jen po interaktivním přihlášení,
nikoli s jiným API klíčem. Požadavek ověřený API klíčem nemůže měnit ani
hesla či jiné přihlašovací údaje žádného uživatele; je odmítnut s 403.

Klíč se posílá v hlavičce:

.. code-block:: bash

   curl -H "X-API-Key: elza_..." https://elza.archiv.example/api/v1/...

.. list-table::
   :header-rows: 1
   :widths: 44 12 44

   * - Klíč
     - Výchozí hodnota
     - Význam
   * - ``elza.security.api-keys.enabled``
     - ``true``
     - Přijímat API klíče. Při ``false`` se hlavička ignoruje.
   * - ``elza.security.api-keys.header-name``
     - ``X-API-Key``
     - Název hlavičky.
   * - ``elza.security.api-keys.default-validity-days``
     - 365
     - Platnost nového klíče, pokud ji uživatel nezvolí.
   * - ``elza.security.api-keys.max-validity-days``
     - 730
     - Maximální platnost klíče.

Odmítnutý klíč je zodpovězen HTTP 401 s tělem JSON uvádějícím důvod
(``MALFORMED_TOKEN``, ``UNKNOWN_KEY``, ``INVALID_SECRET``, ``EXPIRED``,
``REVOKED``, ``USER_INACTIVE``).

Bezpečnostní auditní log
========================

Při nastaveném ``elza.siemLogFile`` (viz :doc:`04-konfigurace`) zapisuje Elza
události autentizace, uživatelských účtů a archivních souborů do
samostatného logu ve formátu JSON, jedna událost na řádek, vhodného pro
systém SIEM. Názvy polí odpovídají schématu OSSEC/Wazuh, takže je mohou
využít vestavěná pravidla takového SIEM. Každá událost obsahuje:

.. list-table::
   :header-rows: 1
   :widths: 25 75

   * - Pole
     - Význam
   * - ``timestamp``
     - Čas události (ISO 8601).
   * - ``program_name``
     - Vždy ``elza``.
   * - ``log_type``
     - ``secure`` pro autentizaci, ``audit`` pro změny uživatelů a jejich
       přístupu.
   * - ``event_type``, ``action``
     - Druh události a operace, viz tabulka níže.
   * - ``result``
     - ``success`` nebo ``failed``.
   * - ``srcuser``
     - Kdo akci provedl: přihlášený uživatel, nebo ``configuration`` pro
       změny provedené z ``elza.security.override``, ``setup`` pro prvního
       administrátora založeného v dialogu úvodního nastavení, ``system``
       pro uživatele založeného automaticky při prvním přihlášení JWT.
   * - ``dstuser``
     - Koho se akce týká; u přihlášení totéž co ``srcuser``.
   * - ``srcip``
     - Zdrojová adresa požadavku; chybí u událostí mimo požadavek (start).
   * - ``reason``
     - Důvod selhání (jen při ``result`` = ``failed``).
   * - ``msg``
     - Stručný popis v angličtině, např. ``User martin logged in from IP
       192.168.1.10.``
   * - ``details``
     - Volitelný technický popis selhání v angličtině, např. důvod
       odmítnutí JWT.
   * - ``dstgroup``
     - Kód skupiny, které se akce týká (oprávnění a skupiny).
   * - ``permission``, ``permission_target``
     - Změněné oprávnění (např. ``FUND_ARR``) a entita, na kterou se
       vztahuje, jako ``typ:id`` (``fund:123``, ``node:456``, ``scope:5``,
       ``user:7``, ``group:3``, ``issue_list:9``); u globálního oprávnění
       cíl chybí.

Události:

.. list-table::
   :header-rows: 1
   :widths: 22 22 56

   * - ``event_type``
     - ``action``
     - Popis
   * - ``user_login``
     - ``login``
     - Přihlášení uživatele, úspěšné nebo neúspěšné.
       ``authentication_type`` uvádí metodu (``PASSWORD``,
       ``ACTIVE_DIRECTORY``, ``KERBEROS``, ``SSO_HEADER``, ``JWT``,
       ``API_KEY``, ``OVERRIDE`` pro heslo z ``elza.security.override``),
       ``key_id`` veřejný identifikátor API klíče; obě pole jsou uvedena
       i při selhání. ``reason`` selhání: ``INVALID_USERNAME`` (uživatel
       v Elze neexistuje), ``INVALID_PASSWORD``, ``INACTIVE_USER``,
       ``INVALID_CREDENTIALS`` (SSO hlavička), ``INVALID_TOKEN`` /
       ``TOKEN_DECODING_FAILED`` (JWT), kódy API klíčů uvedené výše, nebo
       ``AUTHENTICATION_ERROR`` pro neočekávanou chybu s popisem
       v ``details``. Neúspěšné přihlášení API klíčem nebo JWT nemá
       ``srcuser``. JWT a API klíč se ověřují u každého požadavku, proto se
       jejich úspěšné přihlášení zapisuje nejvýše jednou za hodinu pro
       tentýž klíč (nebo uživatele) a adresu; selhání se zapisují vždy.
   * - ``user_logout``
     - ``logout``
     - Odhlášení uživatele. Vypršení session se nezapisuje.
   * - ``api_key_create``
     - ``create_api_key``
     - Byl založen API klíč; ``key_id`` a ``expire_date``.
   * - ``api_key_revoke``
     - ``revoke_api_key``
     - Byl zrušen API klíč (vlastníkem nebo administrátorem); ``key_id``.
   * - ``user_create``
     - ``create_user``
     - Uživatele založil administrátor (UI, REST, SOAP), byl založen
       v úvodním nastavení, automaticky při prvním přihlášení JWT, nebo při
       startu z ``elza.security.override``.
   * - ``password_change``
     - ``change_password``
     - Heslo změnil uživatel (``srcuser`` = ``dstuser``) nebo administrátor.
       Změna uživatelem selže s ``reason`` = ``OLD_PASSWORD_MISMATCH``,
       pokud nesouhlasí původní heslo.
   * - ``user_activate``
     - ``activate_user``
     - Účet aktivoval administrátor nebo byl aktivován při startu
       z ``elza.security.override``. Zapisuje se jen při změně stavu.
   * - ``user_rename``
     - ``rename_user``
     - Administrátor přejmenoval uživatele; ``dstuser`` je nové jméno,
       ``old_username`` předchozí.
   * - ``override_active``
     - ``enable_override``
     - Zapisuje se při každém startu pro každého uživatele
       v ``elza.security.override``: heslo z konfigurace platí pro
       uživatele (``dstuser``) vedle jeho vlastního.
   * - ``user_disable``
     - ``disable_user``
     - Administrátor deaktivoval účet. Zapisuje se jen při změně stavu.
   * - ``permission_grant``, ``permission_revoke``, ``permission_change``
     - ``grant_permission``, ``revoke_permission``, ``change_permission``
     - Oprávnění uživatele (``dstuser``) nebo skupiny (``dstgroup``) bylo
       přiděleno, odebráno nebo upraveno - administrátorem, přes SOAP, při
       kopírování oprávnění, autorovi nového archivního souboru, nebo
       z tokenu poskytovatele identit (JWT, ``srcuser`` = ``system``;
       zapisují se jen skutečné změny).
   * - ``group_member_add``, ``group_member_remove``
     - ``add_group_member``, ``remove_group_member``
     - Uživatel byl přidán do skupiny nebo z ní odebrán.
   * - ``group_create``, ``group_delete``
     - ``create_group``, ``delete_group``
     - Skupina byla založena nebo smazána. Smazání skupiny odebere její
       oprávnění všem jejím členům; to se po jednotlivých členech
       nezapisuje.
   * - ``fund_create``
     - ``create_fund``
     - Byl založen archivní soubor, ručně nebo importem
       (``fund_import`` = ``true``); ``fund_id`` a ``fund_name``.
   * - ``fund_delete``
     - ``delete_fund``
     - Archivní soubor byl smazán se všemi daty; ``fund_id``
       a ``fund_name``.
   * - ``fund_history_delete``
     - ``delete_fund_history``
     - Byla smazána historie archivního souboru (staré verze a změny);
       ``fund_id`` a ``fund_name``.
   * - ``config_admin``
     - ``apply_config_admin``
     - Uživatele z ``elza.security.override`` nebylo možné uplatnit (vždy
       ``failed``).

Log se rotuje denně a uchovává se 90 dní. Za reverzní proxy je ``srcip``
adresou klienta jen se zapnutým ``elza.security.acceptForwardedHeaders``
a proxy nastavenou podle :ref:`Admin_InstallRevProxy_ClientAddress`;
jinak je to adresa proxy.

Další nastavení
===============

.. list-table::
   :header-rows: 1
   :widths: 40 12 48

   * - Klíč
     - Výchozí hodnota
     - Význam
   * - ``elza.security.acceptForwardedHeaders``
     - ``false``
     - Přijímat hlavičky ``X-Forwarded-*`` od reverzní proxy; nutné,
       pokud Elza běží pod cestou, a pro adresu klienta v bezpečnostním
       auditním logu (viz :doc:`06-reverzni-proxy`).
   * - ``elza.security.logoutUrl``
     - (nenastaveno)
     - Adresa, kterou prohlížeč otevře po odhlášení, například stránka
       odhlášení SSO brány.
   * - ``elza.security.displayUserInfo``
     - ``true``
     - Zobrazovat v záhlaví aplikace nabídku uživatele.

Session vyprší po standardní době nečinnosti vloženého serveru (30 minut),
kterou lze změnit klíčem ``server.servlet.session.timeout``. Jeden uživatel
může mít současně nejvýše deset session; jedenácté přihlášení ukončí
nejstarší z nich.

Endpointy monitorování nevyžadují autentizaci a musí zůstat dostupné jen
lokálně (viz :doc:`09-monitorovani`).
