Jetstack
Zpět na blog Blog

Ochrana API – rate limity, throttling a ověřovací výzvy

Publikováno 1. ledna 2023

Technická ilustrace k článku Jetstacku

API, se kterým se vyplatí integrovat, je zároveň API, na které se vyplatí útočit, zneužít ho nebo ho omylem zahltit. Skript, kterému se rozjede smyčka a dotazuje se každé dvě vteřiny místo každé dvě minuty. Pokus o uhodnutí hesla k administrátorskému účtu hrubou silou. Čerstvě spuštěná partnerská integrace, jejíž autor zapomněl doplnit zpomalení mezi pokusy. Nevinná chyba, ze které se bez ochrany stane skutečný incident. Smysl ochrany není říkat ne – je to říct "ne tak rychle" způsobem, se kterým se slušně napsaní klienti umí sami vypořádat, a upozornit na problém dřív, než z něj bude výpadek.

Jádrem je rate limiting pro každé prostředí zvlášť. Každé prostředí má vlastní kvóty – ne jeden sdílený globální strop –, takže vytížené prostředí nemůže připravit o kapacitu ta klidnější a integrace, která se zbláznila v jednom prostředí, neovlivní dostupnost API pro ostatní. Limity se nastavují pro každé prostředí a dají se vyladit podle jeho skutečného provozu, ne podle jedné univerzální hodnoty pro všechny. Prostředí s velkým a dobře zmapovaným integračním provozem dostanou vyšší stropy; prostředí s minimem integrací dostanou přísnější výchozí meze, které včas odhalí překvapení.

Hlavičky Retry-After jsou standardní signál, díky kterému integrace umí slušně zpomalit. Když klient překročí limit, platforma vrátí HTTP 429 s hlavičkou Retry-After, která říká, jak dlouho počkat. Slušně napsané integrace – a prakticky všichni moderní HTTP klienti – ji respektují automaticky. Autor integrace nemusí psát žádnou vlastní logiku; správné zpomalení a opakování zvládne běžná klientská knihovna sama. To je důležité: ochrana je užitečná jen do té míry, do jaké se s ní integrace dokážou srovnat, a použití standardního mechanismu znamená, že se ten náš nemusí učit.

Limity pro jednotlivé endpointy počítají s tím, že ne každé volání API stojí stejně. Odlehčené načtení jednoho záznamu si zaslouží jiný strop než hromadné vytváření, složitý dotaz s vnořenými filtry nebo nahrání souboru. Různé endpointy mají různé limity, takže celková kvóta je vážený obraz skutečné spotřeby zdrojů, a ne plochý čítač, který trestá levné požadavky stejně jako ty drahé.

Na opačném konci ochrany stojí zpomalování opakovaných přihlášení (throttling). Opakovaně neúspěšná přihlášení ke stejnému účtu nebo ze stejného zdroje jsou postupně čím dál pomalejší, a právě to udělá z útoku hrubou silou záležitost na roky místo na patnáct minut. Mechanismus platí pro webové rozhraní, pro přihlášení přes API klíč i pro jakýkoli jiný vstup, který po uživateli chce přihlašovací údaje – jednotná politika napříč všemi místy, kde se ověřuje.

Logika ověřovacích výzev (challenge) řeší případy, kdy rate limit není ten správný nástroj, ale přesto chcete zařadit krok navíc. U citlivých operací – změna platební metody, schválení velkého převodu, udělení administrátorských oprávnění – lze před dokončením vyžádat ověřovací výzvu (potvrzení, druhý faktor). Nastavuje se na úrovni konkrétní akce, takže si provozovatel vybere, které operace krok navíc opravdu potřebují, aniž by komplikoval běžné použití. Je to ta tichá funkce, díky které nejsou scénáře s kompromitovanou relací (session) tak katastrofické.

Autentizace přes API klíč je hlavní způsob, jak se externí integrace ověřují. Klíče se vydávají pro každou integraci a dají se odvolávat nezávisle, takže výměna klíče u jednoho partnera nerozbije ostatní. Samostatný endpoint pro ověření platnosti klíče umožní klientovi zkontrolovat svůj klíč, aniž by prováděl skutečnou operaci – to se hodí pro kontroly stavu integrace i pro partnerské portály, které chtějí ukázat jasné "vaše připojení funguje". Autentizaci podrobněji rozebírá článek o REST API; tady je podstatné, že ochrana a autentizace jsou navrstvené, ne propletené, takže se každá dá upravit bez vlivu na tu druhou.

Oznámení o blížícím se limitu drží správce prostředí před problémem, ne za ním. Když se využití prostředí blíží k limitu, platforma pošle administrátorům e-mail s dostatečným předstihem na to, aby stihli zareagovat – prověřit integraci, která provoz žene nahoru, zvednout strop, jde-li o legitimní zátěž, nebo odhalit proces, který se utrhl ze řetězu. Většina prostředí na své limity v praxi nikdy nenarazí; ta, která ano, se tam obvykle dostanou proto, že se něco změnilo – nová partnerská integrace, nechtěná nekonečná smyčka, nárůst zákaznického provozu – a oznámení tuto změnu zachytí dřív, než z ní bude příval chyb 429.

Vynulování limitu (rate limitu) dává administrátorům nástroj k obnově, když se na limit narazí z legitimního důvodu. Náhlý, nečekaný nárůst – spuštění produktu, migrace, hromadný import – může normální příděl prostředí oprávněně překročit. Administrátor může vynulovat aktuální čítač a okamžitě tak obnovit kapacitu, a samostatně pak zvednout limit, pokud nový provoz představuje trvalou změnu. Vynulování čítače je výslovná operace s jasnou stopou v protokolu, ne tiché obejití – což mechanismus drží poctivý.

Zpracování CORS je praktický detail, na kterém záleží u integrací běžících v prohlížeči. Front-endový kód běžící na vlastní doméně zákazníka může, když je to tak nastaveno, volat API přímo, s řízeným seznamem povolených původů (origin) na straně prostředí. U jednoduchých veřejných integrací – widget na marketingovém webu, malý dashboard, front-end partnerského portálu – je právě tohle to, co umožní přímé použití API bez proxy na backendu.

Ochrana patří mezi funkce, které jsou nejcennější, když nejsou vidět. Dobře vyladěné limity, na které integrace nikdy nenarazí. Throttling, který útoky hrubou silou tiše zpomalí k nule. Oznámení, která zachytí neobvyklé využití dřív, než z něj bude problém. Cílem je API, které zůstane dostupné a svižné pro každého legitimního volajícího, a přitom neztratí zuby vůči zneužití ani nebude na obtíž integracím, které dělají věci správně. Právě tahle rovnováha je celý záměr návrhu a právě ona dělá z API něco, co se dá bezpečně otevřít – ne jen bezpečně zdokumentovat.