Výlet do říše verzí: CVS přes síť

19. 1. 2004
Doba čtení: 9 minut

Sdílet

Již mnohokrát slunce vyšlo a zapadlo od předchozího dílu našeho seriálu. Ale byly Vánoce, takže by se patřil nějaký --- pravda poněkud opožděný --- dárek. Krom toho jsem konečně našel dostatek času, chuti i motivace, a o další pokračování našeho nekonečného seriálu si napsalo už tolik lidí, že mi dost dobře nezbývá než se do toho zase pustit. Tak si pojďme zase povídat s CVS, tentokráte přes síť!

Dosud jsme pracovali s CVS pouze na lokálním systému, tedy jsme měli repository v nějakém adresáři na svém vlastním počítači. Ovšem v řadě případů je vhodné, abychom mohli s obsahem našeho repository pracovat i síťově. Dnes si ukážeme, jak na to. Předem upozorňuji, že můj popis realitu poněkud zjednodušuje a některé detaily záměrně vynechávám; jednak mám pochybnosti o jejich praktické využitelnosti a jednak si myslím, že byste je ani využívat neměli, nebo by článek jejich popisem příliš nabobtnal (a já bych měl více práce za stejné peníze ;-).

Možná, že vám ještě od minulého dílu někde zbylo nějaké funkční CVS repository. Pokud ne, tak si teď nějaké vytvořte podle návodu v předchozím dílu, budeme ho potřebovat.

Nejdříve ovšem budeme muset probrat ještě jistou záležitost, o které bude dobré později vědět.

Jak se spouští CVS

V minulém článku jsme pro samotné CVS zapomněli nějak pečlivě popsat, jak se vlastně přesně spouští. Ano, jistě, napíšeme cvs, ale jak dál? Nejdříve vždy následují tzv. globální parametry, tedy parametry společné pro všechny příkazy, které ovlivňují nějakou obecnou vlastnost CVS (například -q způsobí, že CVS během své činnosti téměř ani nepípne). Dále pokračujeme jménem příkazu, který chceme provést, a poté tzv. lokálními parametry, specifickými pro konkrétní příkaz (například -m pro příkaz commit uvádíme… ale to už byste měli vědět!).

~/.cvsrc

Často se stává, že chceme trvale změnit chování nějakého příkazu, proto k němu vždy píšeme určité parametry. Ovšem stroje nám mají pomáhat a šetřit práci, a proto je tu právě .cvsrc. Na každý řádek napíšeme nejdříve jméno příkazu a za něj parametry, které vždy u onoho příkazu chceme mít. Můžeme zde uvádět i globální parametry, pak místo příkazu napíšeme „cvs“. Pokud tedy vždy hodláme cvs update dát parametry -dP, nesnášíme, když nám cvs log vypisuje tagy, z cvs diff bychom rádi vždy unified diff a také chceme mít veškerý síťový provoz zkomprimovaný, do ~/.cvsrc uložíme:

update -dP
log -N
diff -u
cvs -z4

Čas od času se však stává, že příkaz potřebujeme spustit bez těchto parametrů. Pak na příkazovou řádku uvedeme globální parametr -f, díky kterému bude soubor .cvsrc ignorován: cvs -f log -h soubor (vypíše základní informace o souboru a právě seznam tagů).

Jak si udělat CVS server

Pro síťovou komunikaci je — jak známo — obvykle třeba serveru a klienta, a ne jinak tomu bude i v tomto případě. Dokud jsme s repository pracovali na lokálním souborovém systému, vše dělal přímo CVS klient a žádný server nebyl třeba. Ovšem při síťové komunikaci s repository manipuluje program jménem pserver (p podle Password authentication). Toho CVS klient přes síť instruuje, co a jak má provádět. pserver je nutno spouštět z inetd (případně xinetd, daemontools či podobných stvoření) — tedy pro každé spojení s nějakým klientem se pouští nová instance pserveru.

Prvním krokem by tedy mělo být řádné nastavení spouštění pserveru. Budeme konfigurovat službu cvspserver (port 2401/tcp), kterou bude obsluhovat příkaz cvs pserver. Tomu musíme však ještě říci, k jakým repository povolíme přes síť přístup, a to sérií globálních parametrů –allow-root=/cesta/k/cvsro­otu (tedy klidně můžeme mít repository více).

Obvykle se pserver spouští pod rootem. Asi zejména ti paranoidnější již nespokojeně mlaskají — vydržte, na konci si povíme, jak bezpečnosti CVS pomoci. Ovšem protože root může používat cvs i jako klienta, třeba má v ~/.cvsrc nějaké parametry, které by nám mohly dělat neplechu. Je proto dobré ještě použít globální parametr -f.

Nuže, přikročme k věci. Nejdříve si do /etc/services přidáme službu cvspserver:

cvspserver  2401/tcp

Nyní naučíme inetd spouštět pserver:

cvspserver stream tcp nowait root /usr/bin/cvs cvs -f --allow-root=/cesta/k/cvsrootu pserver 

Verze pro xinetd:

service cvspserver
{
  flags       = REUSE NAMEINARGS
  socket_type = stream
  protocol    = tcp
  wait        = no
  user        = root
  server      = /usr/bin/cvs
  server_args = --allow-root=/cesta/k/cvsrootu --allow-root=/dalsi/cvsroot pserver
} 

(Laskavý čtenář si jistě za /cesty/k/cvsrootu dosadí něco smysluplného, stejně jako si dle potřeby upraví cestu k cvs.)

A jak si CVS server nakonfigurovat

Konfiguraci CVS obecně se budeme hlouběji věnovat až v některém dalším dílu, omezím se tedy nyní pouze na to nejnutnější, více se dozvíte až později.

Na server se mohou připojovat různí uživatelé, přičemž každý má vlastní heslo, kterým se autentikuje. Zatímco je vhodné, aby uživatelé, kteří mají již na systému účet, měli stejné uživatelské jméno i pro CVS, naopak nelze doporučit, aby měli i stejné heslo — to se totiž standardně přenáší po síti v nezašifrované podobě, zabezpečení je tedy ekvivalentní tomu, když se na server přes internet logujete obyčejným telnetem.

Po navázání spojení a autentizaci se pserver přejinačí na uživatele, který se mu právě představil, a dále již běží s jeho právy. To znamená, že tento uživatel musí mít práva pro čtení i zápis v rámci repository (je vhodné si zavést grupu cvs, která bude celé repository vlastnit). Ovšem i pokud plánujete uživateli povolit pouze čtení, musí mít tento uživatel právo zápisu do repository, a to kvůli zamykání (jinak by se mohlo stát, že uživatel dostane stav stromu uprostřed commitu, kdy některé soubory už jsou nové a jiné ještě ne). O tom, jak zakázat uživateli zápis dorepository, si povíme, až budeme probírat konfiguraci CVS.

Není samozřejmě nutné, aby každý uživatel CVS měl i účet v systému. V CVS můžete libovolné uživatele „mapovat“ na různé systémové uživatele. Často se tak uživatelé v CVS například všichni namapují na společného systémového uživatele cvs, nad kterým pak pserver vždy běží.

Nyní tedy poprvé přišel čas zanořit se do onoho tajemného modulu CVSROOT, přítomného jistě v každém vašem repository. V souboru passwd nalezneme seznam uživatelů spolu s jejich hesly a případným mapováním. Má ovšem poněkud zvláštní postavení, není to klasický RCSsoubor, ale přebývá v repository přímo ve své „surové“ podobě a vždy ho také editujeme přímo tam. Důvod je zřejmý — každý, kdo si modul CVSROOT checkoutne, by asi neměl dostat i soubor passwd se seznamem všech uživatelů i jejich hesel (byť zašifrovaných).

Formát souboru je jednoduchý: login:heslo[:systémový_login]. Heslo by přitom mělo být zašifrováno DES šifrou — tu si můžete vygenerovat například zde, ti šikovnější si můžou tady stáhnout výjimečně praktickou utilitku mkpasswd, která to umí také (pokud si ji budete umět sami zkompilovat).

Blahopřeji, v tuto chvíli byste měli mít konečně hotový funkční CVS server! To je hezké, ale co s tím?

Povídáme si s CVS serverem

Teď by bylo dobré náš novotou zářící CVS server i nějak využít, co říkáte? Použití cvs se příliš neliší od práce s lokálním repository, ovšem několik změn tu přeci jen je. Předně, dosud jsme — při práci mimo vycheckoutovaný strom — parametrem -d určovali cestu k repository. Nyní místo cesty k repository použijeme komplikovanější zápis. Jeho obecná forma jest :metoda_přístupu:umístění. Například pro metodu přístupu local bude umístění jednoduše cesta k repository na lokálním stroji a zápis -d:local:/home/cvs je ekvivalentní našemu starému známému -d/home/cvs. Ovšem nás zajímámetoda přístupu pserver: umístění pak bude mít formát login@server:/cesta/k/repository. Tedy pokud mám jako uživatel pasky na serveru pasky.ji.cz repository v adresáři /home/cvs, jako parametr uvedu -d:pserver:pasky@pasky.ji.cz:/home/cvs. Existují i jiné metody přístupu; některé (mnohé) přesahují rámec tohoto článku, o jiných se dozvíte níže.

Před tím, než si začneme z repository checkoutovat jednotlivé moduly, se musíme serveru řádně představit a ujistit ho, že jsme skutečně ten (ta, to?), za koho se vydáváme. To provedeme příkazem cvs login, samozřejmě nesmíme zapomenout na parametr -d:

pasky@machine:~$ cvs -d:pserver:pasky@pasky.ji.cz:/home/cvs login
Logging in to :pserver:pasky@pasky.ji.cz:2401/home/cvs
CVS password:
pasky@machine:~$ 

Nyní stačí už jen vesele checkoutovat, updatovat, commitovat a vůbec jinak se síťově radovat. Pokud ovšem vaše připojení není přímo broadband ani nepracujete na lokální síti, vřele doporučuji zapnout kompresi přenášených dat. Stačí dát cvs klientu při každém spuštění globální parametr -zčíslo, kde číslo určuje úroveň komprese od 1 do 9. Obecně se doporučuje -z3 či -z4; nižší úrovně nejsou dostatečně účinné, zatímco vyšší přespříliš zatěžují procesor a na výsledku se to již tolik neprojeví. (Uvědomme si, že komprimace nezatěžuje pouze náš procesor, ale i jeho kolegu na serveru, a pokud je takových spojení více, může to dát vcelku zabrat.)

O bezpečnosti

Jak již jsme si několikrát ukázali, s bezpečností to u CVS není příliš růžové a zvláště se to projevuje právě při komunikaci přes síť. Každému, komu umožníte přes síť přístup k CVS, dáváte potenciálně poměrně velkou moc a kód CVS myslím mnoho bezpečnostních auditů nezažil. K tomu připočítejme, že často mnozí (vlastně skoro všechny veřejné projekty) poskytují přístup k tzv. anonymnímu CVS, tedy mají zřízeného speciálního uživatele, který nemá práva pro zápis do repository, ovšem má k němu přístup kdokoliv (typicky je uživatelské jméno anoncvs nebo anonymous a heslo bývá prázdné). I s takovým uživatelem však můžeme provádět relativně širokou škálu příkazů a stačí malá chybička…

Ukážeme si nyní dva způsoby, jak poněkud zlepšit situaci a CVS alespoň částečně opevnit proti strachem opředené odvrácené tváři internetu.

Přístup přes ssh

Mechanismus různých metod přístupu je v CVS nečekaně flexibilní. My jsme si zatím pověděli o metodě local a pserver. Ovšem chronologicky někde mezi těmito dvěma metodami leží metoda ext. Ta zajišťuje spojení mezi serverem a klientem pomocí externího programu, standardně rsh. Srsh bychom si ovšem příliš nepomohli, můžeme však změnit hodnotu proměnné prostředí $CVS_RSH na ssh. A ono to bude i fungovat!

pasky@machine:~$ export CVS_RSH=ssh
pasky@machine:~$ cvs -d:ext:pasky@pasky.ji.cz:/home/cvs co coolmodul
... 

Ejhle, naše komunikace je tunelována skrze SSH, to ovšem není k zahození. Díky této metodě máme již mnohem větší šanci, že nikdo neodchytí naše heslo, nenaloguje se jako my a nezačne zběsile commitovat. Na druhou stranu musíme mít na serveru plnohodnotný účet a tato metoda asi také nebude příliš dobře fungovat pro anonymní CVS.

Wrapper jménem cvsd

Obvykle se pserver spouští přímo z inetd, ovšem existuje projekt cvsd, kterýžto inetd nahrazuje. Navíc automaticky CVS server spouští v chroot jailu (tzn. ve vlastním virtuálním filesystému) a obvykle již jako obyčejný uživatel.

Tato metoda je ideální pro anonymní CVS, naopak nezvyšuje zabezpečení vlastní síťové komunikace, proto vám zřejmě příliš nepomůže, pokud máte do repository právo zápisu (a nechcete ho dát volně k dispozici). Je tedy nejlepší obě metody kombinovat — pro anonymní CVS používat cvsd, zatímco po vývojářích vyžadovat komunikaci přes ssh.

bitcoin_skoleni


Příště vám prozradím zejména něco z tajů tagování a větvení, dostane se i na sledování cizích projektů ve vlastním repository. Poté se můžete těšit na poněkud důkladnější průlet konfigurací CVS, něco o administraci CVS repository, poslední článek této části našeho nekonečného seriálu pak budu věnovat přehledu různých praktických utilit, které vám dokáží značně zpříjemnit život. Pokud se už těšíte, až budeme mít CVS z krku a vrhneme se na zajímavější a progresivnější nástroje, pak vězte, že já také ;-).

Máte-li nějaký konkrétní návrh, co byste si přáli se o CVS dozvědět mimo rámec toho, co jsem právě nastínil, jen do toho! Svěřte se v diskusi pod článkem, pokud pěkně poprosíte a budete moje články hodně číst, budu o tom uvažovat.