Přeskočit na obsah
Přihlásit

Logování a audit

Co se loguje kam (chyby PHP, logy webového serveru, audit API a záznam změn), co ne, dotazy kdo-co-kdy, uchování a audit:prune, tabulky záznamu změn a poznámky k soukromí.

Tato stránka vysvětluje, co web na WBengine zaznamenává, kam, jak dlouho a jak se zeptat „kdo, co a kdy změnil“.

Co se loguje kam

Zdroj Kam Co
Chyby PHP a frameworku PHP error_log Varování, výjimky, „cache disabled: ...“ a řádek s krátkým referenčním kódem u každé chyby 5xx v API v2.
Webový server přístupové a chybové logy Nginxu nebo Apache Každý požadavek HTTP: čas, adresa, URL, stav. Jediné místo s IP adresami.
Požadavky API v2 tabulka cms_api_audit Jeden řádek za každé ověřené volání: kdo, jaká operace, výsledek.
Změny obsahu a struktury tabulka cms_api_changes Jeden řádek za každý zápis s aktérem, zdrojem, akcí a daty před a po.
Koncepty článků tabulka cms_api_revisions Historie konceptů článku pro náhled a obnovu.

Chybový log PHP a referenční kódy

PHP zapisuje přes error_log: do souboru z ini hodnoty error_log, jinak do chybového logu webového serveru (log PHP-FPM, ErrorLog Apache, chybový log Nginxu u chyb FastCGI). V produkci ponechte display_errors = Off a log_errors = On. Když volání API v2 skončí chybou serveru (5xx), klient dostane obecnou zprávu s krátkým referenčním kódem, například ref:7f3a9c. Stejný kód se zapíše i s podrobnostmi do error_log a do auditního řádku, takže v logu hledáte přesně tento kód.

Logy webového serveru a kontejnery

Nginx a Apache mají přístupové a chybové logy, obvykle v /var/log/nginx/ a /var/log/apache2/. V dockerových image posílá Apache oba logy i chyby PHP na výstup kontejneru, čtou se příkazem docker compose logs web (nebo docker logs <kontejner>). Výchozí ovladač json-file roste bez omezení: nastavte max-size a max-file v sekci logging souboru Compose nebo v /etc/docker/daemon.json, případně výstup posílejte do sběrače logů. Hostitelský Nginx před kontejnery má navíc vlastní logy.

Auditní tabulka cms_api_audit

Sloupce: audit_id, integration_id (klíč), central_actor (označení redaktora od centrálního Adminu, nedůvěryhodný volný text do 128 znaků), local_user_id (místní správce při správě klíčů), action, outcome, detail a created_at (čas Unix).

outcome Význam
allowed Klíč byl platný a měl scope. Patří sem i čtení, takže čtení obsahu zanechá stopu (kdo, jaká operace, kdy), nikdy však vrácená data.
unauthorized Klíč chyběl, byl neplatný nebo odvolaný (HTTP 401). integration_id je prázdné.
forbidden Klíč je platný, ale nemá požadovaný scope (HTTP 403).
rejected Ověřený zápis byl odmítnut: validace, nenalezeno, konflikt, neúspěšná podmínka If-Match (412 nebo 428). detail obsahuje kód chyby.
error Chyba serveru (5xx). detail je ref:<reference>, tentýž kód jako v error_log.

Záznam změn cms_api_changes

Každá cesta zápisu vytvoří jeden řádek: change_id, resource (pages, menu, sections, boxes a articles u obsahu, user, cache a audit u ostatních operací), resource_id, action, before_data a after_data (snímky JSON), integration_id, central_actor, source, local_user_id a created_at.

source Kdo zapsal Aktér
v2 API v2 (centrální Admin), ve stejné transakci jako změna obsahu integration_id a central_actor
v1 Starší záznamy zapsané již zrušeným rozhraním (nové nevznikají) local_user_id, integration_id je 0
cli bin/wbe user:create, user:password, user:delete a audit:prune central_actor je cli:<uživatel operačního systému>, integration_id je 0

Obsahové zdroje mají množná čísla (pages, menu, sections, boxes, articles); uživatelé, vyprázdnění cache a mazání záznamů používají jednotná čísla user, cache a audit, takže se nikdy neobjeví v historii /changes obsahového zdroje. Koncepty článků a obnovené verze jsou v cms_api_revisions: revision_id, article_id, payload, action, integration_id, central_actor, created_at. Revize, na kterou koncept stále odkazuje, se nikdy nesmaže.

Co se neloguje

  • Těla požadavků a odpovědí. Audit drží operaci a výsledek, záznam změn výsledná data.
  • IP adresy. Existují jen v přístupovém logu webového serveru.
  • Klíče API, tokeny a hesla. Změna hesla se zapíše jako passwordChanged: true a nic víc.
  • Zobrazení veřejných stránek. Vlastní analytika (viz přehled nastavení) drží jen anonymní denní součty.

Redakce

Řádky zapsané přes cli (a starší řádky v1) se redigují: každý klíč nazvaný password, token, secret, key nebo hash (také apiKey, key_hash) se uloží jako [redacted]. Řádky v2 ukládají data tak, jak přišla, protože je přehrává obnova struktury, proto nedávejte tajné hodnoty do obsahu stránek, menu ani článků.

Kdo, co, kdy

Všechny hodnoty created_at jsou časy Unix. Příklady:

-- posledních 20 změn s tím, kdo a kdy
SELECT FROM_UNIXTIME(created_at) AS at, source, resource, resource_id, action,
       COALESCE(central_actor, local_user_id) AS actor, integration_id
FROM cms_api_changes ORDER BY change_id DESC LIMIT 20;

-- historie jednoho článku i s daty
SELECT FROM_UNIXTIME(created_at) AS at, action, central_actor, before_data, after_data
FROM cms_api_changes WHERE resource = 'articles' AND resource_id = '12' ORDER BY change_id;

-- vše, co jeden redaktor udělal za posledních 7 dní
SELECT FROM_UNIXTIME(created_at) AS at, resource, resource_id, action
FROM cms_api_changes WHERE central_actor = 'anna@example.com' AND created_at > UNIX_TIMESTAMP() - 7 * 86400;

-- odmítnutá a selhaná volání dnes a neúspěšné ověření
SELECT FROM_UNIXTIME(created_at) AS at, integration_id, central_actor, action, outcome, detail
FROM cms_api_audit WHERE outcome <> 'allowed' AND created_at > UNIX_TIMESTAMP(CURDATE()) ORDER BY audit_id DESC;

-- jak často se které klíče používají
SELECT integration_id, outcome, COUNT(*) FROM cms_api_audit GROUP BY integration_id, outcome;

Z příkazové řádky vypíše audit:list poslední změny bez dat před a po:

php vendor/bin/wbengine.php audit:list --limit=50 --resource=articles --actor=anna@example.com --config=src/Config/Settings.json --root=src

--limit je 1 až 500 (výchozí 20), --actor odpovídá označení aktéra přesně, nebo místnímu ID uživatele, je-li číselné. Centrální Admin čte tatáž data přes HTTP, viz další část.

Přehled změn přes HTTP

GET /api/v2/changes vrací záznam změn od nejnovějších, bez dat před a po. Vyžaduje HTTPS a integrační klíč s oprávněním audit:read. Centrální Admin přehled zobrazuje na stránce Aktivita webu, a to jen správcům webu. Klíč bez tohoto oprávnění je třeba nahradit novým klíčem.

Parametry dotazu: page a per_page (1 až 100, výchozí 25); filtry s přesnou shodou resource, resource_id, action, source (v2, v1 nebo cli) a actor; since a until jako epoch sekundy. Neplatný filtr vrací 400. S outcome=rejected přehled místo toho vypíše odmítnuté a neúspěšné zápisy z cms_api_audit s kódem chyby v detail.

Každý záznam má change_id, created_at, resource, resource_id, action, source, actor, integration_id a local_user_id. Samotné čtení přehledu se zapisuje do auditní tabulky jako changes.list.

Uchování a mazání

Nic se nemaže automaticky. Klíče v Settings.json (oba mají výchozí hodnotu 365, povoleno 30 až 3650, neplatná hodnota vyvolá chybu):

"audit": { "retentionDays": 365, "revisionRetentionDays": 365 }

audit.retentionDays platí pro cms_api_audit a cms_api_changes, audit.revisionRetentionDays pro cms_api_revisions. Mazání spouštějte z cronu:

27 3 * * * www-data /usr/bin/php /var/www/wbengine-skeleton-app/vendor/bin/wbengine.php audit:prune --config=/var/www/wbengine-skeleton-app/src/Config/Settings.json --root=/var/www/wbengine-skeleton-app/src >> /var/log/wbengine-cron.log 2>&1

audit:prune --dry-run jen spočítá, --days=N přepíše oba klíče pro jedno spuštění. Nejnovější změna každého zdroje zůstává, ať je jakkoli stará (její id je součástí ETagu struktury a obnovy), stejně jako každá revize, na kterou odkazuje koncept. Každé skutečné spuštění se zapíše jako změna cli zdroje audit. V Dockeru spusťte příkaz z cronu na hostiteli jako docker compose -f docker-compose.production.yml exec -T web php vendor/bin/wbengine.php audit:prune ....

Příprava tabulek záznamu změn

Weby, které používají API v2, potřebují sloupce záznamu změn source, local_user_id a detail a indexy created_at. Jednou po záloze spusťte sh bin/update-database.sh DATABASE; lze ho bezpečně spustit znovu. vendor/bin/wbengine.php doctor hlásí neúspěšnou kontrolu, dokud sloupce neexistují; do té doby se přeskakují a nic jiného se nemění.

sh bin/update-database.sh wbengine_skeleton_app
docker compose -f docker-compose.production.yml exec -T web sh bin/update-database.sh --print \
  | docker compose -f docker-compose.production.yml exec -T db sh -c 'MYSQL_PWD="$MYSQL_ROOT_PASSWORD" mysql -uroot wbengine_skeleton_app'

První příkaz je pro databázi na hostiteli, druhý pro produkční Compose.

Poznámky k soukromí

  • Označení aktérů, řádky uživatelů a snímky obsahu mohou obsahovat osobní údaje, například e-mailové adresy a jména. Auditní tabulky berte jako osobní údaje: omezte přístup k databázi a zahrňte je do záznamů o zpracování.
  • Zvolte uchování podle svých zásad a pamatujte, že zálohy databáze drží řádky déle, než říká nastavení.
  • IP adresa žije jen v logách webového serveru. Jejich rotaci a uchování nastavte zvlášť (logrotate, volby logů Dockeru).
  • Audit je stopa toho, kdo co udělal, nikoli toho, co návštěvníci četli: zobrazení veřejných stránek se po návštěvnících nezaznamenávají.