Používejte distribuční balíčky

Rozmohl se mi na projektech takový nešvar. ‎Z různých důvodů provozáci nebo architekti klienta nepoužívají, nebo požadují od nás nepoužívat, připravené balíčky použité linuxové distribuce pro instalaci potřebných komponent (databáze, servery atd.). Vzhledem k tomu, že si (v českých podmínkách) neumím představit situaci, kdy by to byl rozumný kompromis prakticky s jakýmkoli jiným požadavkem, začal jsem blíže zjišťovat logiku takového rozhodnutí. Přišlo mi, že zatímco argumenty proti použití balíčku jsou velmi promyšlené konstrukce často nepřímých souvislostí, povědomí o přímých dopadech (resp. nákladech) takového rozhodnutí je spíše mlhavé. Prostě se stáhnou zdrojáky a udělá se .configure & make. To je bohužel naprosto tragicky naivní představa, kterou bych chtěl alespoň trochu poopravit.

Kompilace

U většiny reálných projektů je konfigurace kompilace podobně komplexní činnost, jako konfigurace runtimová a vyžaduje podobnou hloubku znalostí projektu a běhového prostředí. Používat configure je asi jako používat výchozí nastavení aplikace. Na první instalaci a ověření funkčnosti dobré, ale pro provoz s produkční zátěží a požadavky na spolehlivost byste měli sakra dobře vědět, jaké kompromisy a workaroundy configure udělal a případně je korigovat.

Úplně samostatnou kapitolou kompilace jsou závislosti. Je potřeba si uvědomit že z celkového objemu kódu, který běží pod jménem daného procesu, tvoří ve skutečnosti ‎objem použitých knihoven významnou část. Tyto knihovny jsou samostatné projekty, které buď musíte zkompilovat zvlášť, nebo použít zase ty, které poskytuje balíčkovací systém. Ve vztahu k původnímu důvodu, který vás vedl k obejití balíčkovacího systému je potřeba řešit otázku, kterou závislost použijete systémovou (protože kompilovat i všechny závislosti by bylo úplné bláznovství) a kterou závislost je opravdu nutné zkompilovat (aby to nepodkopalo smysl celého konání).

A až budete mít architektonicky jasno v tomhle, musíte ještě vyřešit technickou část - jak se závislosti slinkují. Staticky nebo dynamicky? Systémové umístění nebo vlastní? Přeju příjemnou zábavu.

Údržba

Vlastní kompilace, jakkoli už sama o sobě vypadá proti očekávání mnohem složitěji, je teprve začátek všech trampot. To největší břímě obcházení standardních balíčků představuje dlouhodobá údržba. To znamená sledovat změny a bezpečnostní incidenty v kompilovaných projektech, vyhodnocovat je a adekvátně reagovat. Často si to lidé představují tak, že jednou, dvakrát za rok stáhnou aktuální zdrojáky a překompilují, ale to je opět velmi naivní.

Jako reality-check bych doporučil sledovat nějakou dobu mailing listy s bezpečnostními aktualizacemi nějaké distribuce. Oprava středně až vysoce kritické chyby v některém z balíčků se tam i ve stable streamu ohlašuje *jednou až dvakrát denně‎*. Reálně se vás bude týkat pouze zlomek z takových událostí, ale ilustruje to zhruba kadenci informací (z CVE, projektových mailing listů atd.) které budete muset vyhodnocovat. Když už se totiž nějaká informace vašeho projektu týkat bude, je potřeba být schopný reagovat v řádu hodin, ne až při nejbližší výroční příležitosti. Chybu v databázi vedoucí ke ztrátě dat ani kritickou bezpečnostní chybu na své infrastruktuře déle mít nechcete.

Zjištěním, že je potřeba něco dělat, to pak zdaleka nekončí, protože ono většinou není úplně jednoduché zjistit co dělat. Ideální situace je, když používáte LTS verzi produktu a jeho vývojáři pro daný stream udržují správně patchovanou a testovanou větev zdrojáků s minimem funkčních změn. Málokterý projekt však dosahuje takové vyspělosti (a některé to tak mají dokonce záměrně) a málokterý uživatel je natolik konzervativní, aby se s LTS verzí spokojil. A pak teprve začíná opravdová sranda.

Je potřeba zjistit, jaké změny v kódu ve spojitosti s danou událostí nastaly a v jakých větvích. Celkem jistě se můžete spolehnout, že příslušné změny budou v hlavní větvi vývoje, ale zda byly backportovány i do větví nižších, a konkrétně do té vaší, není vůbec jisté. V nejhorším případě je potřeba backport udělat vlastnoručně. Vyhráno ale není ani v případě, že je změna zařazena do vaší větve přímo od vývojářů. V takovém případě je dál nutné řešit otázku, jaké další změny v dané větvi se s tou vaší svezou, pokud si ke kompilaci jen jednoduše stáhnete její aktuální zdrojáky. Ačkoli právě kvůli tomu vznikl SemVer, staří mazáci vědí, že nic takového jako zpětně kompatibilní změna neexistuje.

XKCD

A to mě přivádí k další kapitole.

QA

Každý build softwarového projektu je svým způsobem jedinečný. V Java (a Maven) světě se proti tomu všemožně bojuje, takže už o tom nejsme zvyklí přemýšlet, ale na úrovni systémových komponent je to celkem běžný jev. I když pominu tu možnost, že si nějaké patche backportujete sami a unikátní jsou tak už samotné zdrojáky, tak z principu popsaném v první kapitole vzniká každý vlastní build se specifickou sadou závislostí a pro specifické prostředí. A jakmile si něco specifického vyrábíte sami, tak byste si to taky měli sami testovat, než to pustíte do produkce.

O tom, že i minimalistické bezpečnostní opravy mohou ve skutečnosti představovat regresi, je možné se opět přesvědčit na zmíněných mailing listech distribucí, kde k takovým nehodám dochází několikrát do roka a musí se vydávat “opravy oprav”. Pokud to tedy myslíte s obcházením balíčkovacího systému vážně, měli byste i externí změny v kódu komponent vaší infrastruktury zapojit do úplně stejných QA procesů jako změny ve vlastním produktu.

Sláva maintainerům

Celé jsem to vyprávěl proto, abych vysvětlil, co je ve skutečnosti ona hodnota, kterou balíčkovací systém přináší. Není to těch pár minut strojového času, který ušetříte za kompilaci. Jsou to hodiny a možná dny času vysoce kvalifikované lidské práce měsíčně, nemluvě o technické a organizační infrastruktuře, která je k tomu potřeba. Dělají ji maintaineři balíčků v distribucích, aby ji tisíce dalších dělat nemuseli, aby jim stačilo napsat sudo apt upgrade. Patří jim za to naše nekonečná vděčnost.

Pokud si myslíte, že to budete dělat lépe nebo flexibilněji, tak buď pracujete v Netflixu, Googlu nebo Amazonu nebo jste blázni. Pokud to chcete dělat místo nich třeba proto, že jsou vaše servery na vnitřní síti a nechcete jim dát přístup k internetu a zařídit si vlastní repositář vám přijde moc pracné, tak se teď nad tím zamyslete ještě jednou. A o těch bizarnějších důvodech ani mluvit nebudu.

Není úniku

Všechno výše uvedené se většině lidí může zdát jako hyperkorektní perfekcionismus a tyto náklady proto pro svojí situaci považují za nulové, protože buď jejich data zas tak důležité nejsou nebo mají pocit, že ohledně bezpečnosti je přeci chrání anonymní bezvýznamnost v moři jiných serverů na internetu. To je problém, se kterým se snažím bojovat už několik let.

Je to důsledek staré pravdy, že “co oči nevidí, to srdce nebolí”. To, co v tomto případě není vidět je, kam se v posledních letech posunula praxe při zneužívání nezáplatovaných chyb a problémů. Obecná představa je totiž pořád ještě založena na holywoodském obrázku geniálního teenagera v mikině s kapucí, který se snaží nabourat studiem binárního kódu v příkazové řádce do nějakých ultratajných serverů Pentagonu.

Proto většinu lidí překvapí, když na vlastní oči uvidí průmyslově banální realitu v podobě Shodanu a Metasploitu. Když uvidí, že žádný server na internetu není anonymně bezvýznamný, ale že do několika hodin začne doslovně červeně blikat na přehledné mapě kdekoli na světě v aplikaci, kterou by dokázala používat i jejich babička. A když na vlastní oči vidí, že v té chvíli je i sebeblbější uhrovatý deprivant, který si zaplatí pár dolarů měsíčně za “pentesting” nástroj, doslova pár kliknutí od získání serveru pod svojí úplnou kontrolu.

Používejte balíčky svojí linuxové distribuce, šetří to nepředstavitelně mnoho prostředků.