Skip to content

Bezpečnost a kontrolní seznam ​

Tato stránka shrnuje bezpečnostní architekturu platformy Než zazvoní CMS, mechanismy oddělení škol v jedné instanci, síťové ochrany, zabezpečení nahrávaných souborů a kontrolní seznam před uvedením do provozu. Je určena pro správce platformy.

Než zazvoní CMS provozuje více škol v jedné společné instanci redakčního systému Strapi a obsluhuje je jedním webovým rozhraním Next.js. Tento model vyžaduje důsledné logické oddělení dat, správné nastavení rolí a kontrolu všech vstupů.

Vrstvy oddělení škol ​

Všechna data jsou uložena v jedné databázi PostgreSQL a logicky rozdělena vazbou na záznam školy. Ochranu dat zajišťují čtyři samostatné a vzájemně nezávislé vrstvy:

  1. Podmínky RBAC v administraci: Role Redaktor školy má přidělena oprávnění s podmínkami own-school a own-school-media. Redaktor v sekci Obsah webu vidí a spravuje pouze stránky, články a kategorie své školy. Přiřazení redaktora ke škole je uloženo v samostatném typu obsahu Redaktor školy, nikoli v názvu role.
  2. Document Service guard: Druhá bezpečnostní vrstva v souboru guard.ts funguje v jádru Strapi nezávisle na nastavení rolí. Hlídá operace findMany, findOne, create, update, delete, clone, publish, unpublish i discardDraft. Při pokusu o zásah do cizího dokumentu operaci odmítne chybou 403 Forbidden. Guard kontroluje i vazby na nadřazené stránky či kategorie a nedovolí propojení s jinou školou.
  3. Upload lifecycles a route guard: Ochrana souborů v upload-guard.ts vynucuje, že každý soubor nahraný redaktorem skončí v kořenové složce médií jeho školy. Redaktor nesmí vytvářet, přejmenovávat ani mazat složky v sekci Knihovna médií. Hromadný přesun souborů a nahrávání z externí adresy URL jsou pro redaktory zakázané. Guard hlídá i celkovou diskovou kvótu školy (výchozích 2048 MB).
  4. Veřejné rozhraní API: Veřejné čtení obsahu obsluhuje strategie public-read. Plugin users-permissions je odstraněn, takže neexistuje veřejná registrace uživatelů. Veřejné API dovoluje pouze čtení publikovaného obsahu (parametr status=draft je ignorován).

Na následujícím snímku z administrace vidíte seznam definovaných rolí v systému:

Nastavení rolí v administraci Než zazvoní CMS

Rate limit a ochrana před přetížením ​

Pro ochranu před útoky hrubou silou a přetížením jsou nasazeny limity na několika úrovních:

  • Přihlášení do administrace: Cesty /admin/login a /admin/forgot-password mají limit 20 pokusů za 5 minut na jednu IP adresu. Po překročení vrátí stavový kód 429.
  • Rozhraní administrace: Cesty /content-manager a /upload jsou omezeny na 600 požadavků za minutu na jednu IP adresu.
  • Veřejné API: Cesta /api má limit 300 požadavků za minutu na jednu IP adresu. Požadavky přicházející z interní sítě Dockeru bez hlavičky X-Forwarded-For se do limitu nezapočítávají.
  • Veřejný web: Aplikační proxy webu (proxy.ts) omezuje provoz na 1200 požadavků za minutu na jednu IP adresu.
  • Reverzní proxy Caddy: V konfiguraci Caddyfile je omezena maximální velikost těla požadavku na 60 MB (max_size 60MB).

Měření limitů v paměti

Počítadla rate limitu běží v operační paměti procesů. Při restartu kontejneru se nulují. Proti distribuovaným útokům (DDoS) slouží v případě potřeby Cloudflare nebo pravidla firewallu na serveru.

Bezpečnostní hlavičky a síťové zabezpečení ​

Veškerý provoz probíhá přes šifrovaný protokol HTTPS. Reverzní proxy Caddy a webový frontend vynucují tyto bezpečnostní hlavičky:

  • HSTS: Strict-Transport-Security: max-age=31536000; includeSubDomains.
  • Content Security Policy (CSP): Web generuje pro každý požadavek náhodný kryptografický řetězec (nonce). Inline skripty Next.js běží pouze s tímto nonce. Objekty jsou zakázány (object-src 'none').
  • Ochrana typů obsahu: X-Content-Type-Options: nosniff.
  • Zásady odkazování: Referrer-Policy: strict-origin-when-cross-origin.
  • Skrytí serveru: Odpovědi neobsahují hlavičky Server ani X-Powered-By. Telemetrie Strapi je vypnuta (STRAPI_TELEMETRY_DISABLED=true).
  • Cookies: Cookie strapi_admin_refresh má příznak HttpOnly a díky nastavení TRUST_PROXY=true i příznak Secure.

Porty databáze PostgreSQL ani aplikací Strapi a Next.js nejsou publikovány do internetu. Jediným vstupním bodem je Caddy na portech 80 a 443.

Ochrana souborů a médií ​

Knihovna médií přijímá pouze prověřené formáty:

  • Povolené: Běžné obrázky (JPEG, PNG, WebP, GIF, AVIF), video, audio, PDF, dokumenty MS Office (.doc, .docx, .xls, .xlsx, .ppt, .pptx), prostý text (.txt) a CSV (.csv).
  • Zakázané: Vektorové obrázky SVG (image/svg+xml kvůli riziku XSS), spustitelné soubory (.exe, .sh, skripty), archivy (.zip, .rar) a OpenDocument formáty (.odt, .ods, .odp).

Velikost jednoho souboru je omezena na 50 MB. Disková kvóta pro celou školu je 2048 MB (2 GB).

Odkazy na webu mají atribut rel="noopener noreferrer". React 19 blokuje adresy začínající na javascript:. Vložené mapy a videa z YouTube se načítají až po kliknutí návštěvníka.

Správa hesel a účtů ​

  • Heslo správce: Heslo prvního superadmina (ADMIN_PASSWORD) se předává přes Docker secret /run/secrets/admin_password. Nedostane se do prostředí kontejneru. Po prvním spuštění proměnnou ze souboru .env smažte.
  • Obnova hesla e-mailem: Pokud server nemá nastaveno odesílání e-mailů, zpráva pro obnovu hesla nedorazí. V takovém případě kontaktujte podporu Než zazvoní, heslo vám obnoví.
  • Role: V systému existují role Super Admin a Redaktor školy.
  • Audit log: Všechny zápisy v administraci eviduje protokol v sekci Historie změn. Protokol je přes web určen pouze ke čtení.

Na následujícím snímku vidíte přehled zaznamenaných událostí v sekci Historie změn:

Přehled historie změn v administraci

Kontrolní seznam před nasazením na server ​

Před spuštěním produkčního provozu na novém serveru zkontrolujte tyto body:

  • [ ] Všechny automatizované testy proběhly úspěšně (node tests/site-schema-test.mjs, node tests/tenant-test.mjs, node tests/web-test.mjs a node web/scripts/crawl.mjs).
  • [ ] Všechny bezpečnostní klíče v .env jsou nově vygenerovány příkazem openssl rand -base64 32 a uloženy v Passboltu.
  • [ ] Soubor .env má přístupová práva chmod 600 a není sledován gitem (git ls-files | grep -i env nic nevrací).
  • [ ] Po prvním úspěšném startu byla proměnná ADMIN_PASSWORD ze souboru .env smazána.
  • [ ] Proměnná DEFAULT_SCHOOL_SLUG je prázdná, SITE_BASE_DOMAIN a SITE_HOSTS obsahují správné domény a TRUST_PROXY má hodnotu true.
  • [ ] Kontrola hlaviček přes curl -I: administrace vrací HSTS a neobsahuje X-Powered-By, web vrací CSP s nonce a nosniff.
  • [ ] Při přihlášení přes HTTPS má cookie strapi_admin_refresh příznaky Secure a HttpOnly.
  • [ ] V databázi nejsou testovací školy test ani demo, ani laboratorní redaktoři.
  • [ ] Role Redaktor školy má přístup pouze k obsahu své školy a médiím ve své složce, nikoli k nastavení administrace.
  • [ ] Každý redaktor má vytvořený odpovídající záznam v typu obsahu Redaktor školy.
  • [ ] Firewall povoluje pouze porty 22, 80 a 443. Přístup přes SSH funguje výhradně přes klíč.
  • [ ] Pravidelná záloha ops/backup.sh běží v cronu, ukládá se mimo server a obnova byla vyzkoušena.

Tipy a doporučení ​

Bezpečné ukládání přístupových údajů

Všechna systémová hesla a klíče ukládejte výhradně do týmového správce Passbolt. Nikdy je neposílejte nešifrovanými kanály.

Testování změn na stagingu

Před každou aktualizací systému nebo úpravou kódu oddělení škol v src/tenant/ nejprve ověřte funkčnost na stagingové kopii databáze.

Související ​