Adresář je speciální databáze optimalizovaná pro čtení, procházení a vyhledávání dat. Běžným příkladem takového adresáře může být například katalog knih nebo telefonní seznam. Předpokládá se, že telefonní čísla se nemění příliš často a stejně tak seznam knih v knihovně. Obecněji se takový adresář skládá z jednoznačně identifikovatelných položek, každá položka se pak skládá z atributů (přičemž u každé položky musí být alespoň jeden atribut). Atributy jsou různých typů určujících možné hodnoty atributu. Cílem takto zavedené architektury je usnadnit maximálně rychlý a jednoduchý přístup k informacím.
Práce s adresářem je postavena na modelu klient-server. Klientská aplikace pro přístup k adresáři pošle požadavek na adresářový server, ten ho vyhodnotí a posílá zpátky.
Rodina standardů definujících adresářové služby, práci s nimi, jejich chování a další. Vše je definováno nad referenčním síťovým modelem ISO.OSI (klasických 7 vrstev, viz. přednášky doc. Staudka :-)). Konkrétně se jedná o dokumenty X.500 až X.521. Definují nad klasickou architekturou klient-server protokol DAP (Directory access protocol). Protože model ISO.OSI je zbytečně složitý a v podobě, jak byl navržen, se prakticky neimplementuje, vznikl "odlehčený" protokol tzv. LDAP (Lightweight DAP).
Verze 1 protokolu je definována v RFC 1478 a je skutečně postavena na DAP jen s tím rozdílem, že je jednodušší - komunikace však musí stále probíhat s plnohodnotným X.500 serverem. Následující verze 2 a 3 se protokol se plně osamostatnili a již nevyžadují podporu DAP podle X.500. Rozdíly mezi verzemi 2 a 3 budou popsány dále. Verze 2 je popsána v v následujících RFC: 1777-1779, 1959, 1960. Verze 3 pak v RFC 2251-2256.
LDAP je definován nad TCP/IP (na rozdíl od ISO.OSI DAPu). Dále oproti DAPu vypustil několik specializovaných operací a některé operace sloučil do jedné a pro reprezentaci jmen používá textové řetězce (X.500 definuje složité struktury pro totéž).
Interakce mezi klientem a serverem probíhá v několika krocích. Klient naváže spojení se serverem (binding), v této fázi probíhá autentizace. Následně může klient provádět různé operace nad adresářem. Nakonec proběhne ukončení spojení (unbinding).
Protokol definuje typy atributů, typ určuje jaká syntax je pro zapsání hodnoty použita, jak se bude atribut při různých operacích chovat a podobně. Atributy mohou mít pro přehlednost aliasy. Atribut může být binárního typu (bin), řetězec znaků (cis je non-case sensitive a ces je case sensitive), typ rozlišovací jméno (dn) nebo třeba typ telefonní číslo (tel). Toto jsou některé vybrané základní typy. Běžně užívanými atributy jsou pak například commonName alias cn je typu cis (jméno například zaměstnance), owner je typu dn (rozlišovací jméno osoby vlastnící položku) a další.
Schema je množina pravidel nad adresářem - rozhoduje o počtech, typech, významem a jiných vlastnostech položek a atributů v adresáři. Především definuje třídy objektů (object classes), určující jaké položky (objekty) mohou být uloženy v adresáři. Třída určuje počet a typ atributů, které se mohou v položce nacházet (kontrola probíhá procesem zvaným schema-checking). Každá položka (objekt) pak má povinný atribut objectClass, určující v jaké třídě se položka nachází. Třídy mohou samozřejmě dědit od jiných tříd (objektový model), přičemž je definována nejvyšší třída, která má jediný atribut a tím je právě objectClass, od této třídy (nazývané top) pak musí být odvozeny všechny třídy ostatní. Aby byla možná spolupráce mezi LDAP servery (každý z nich může mít nadefinováno vlastní schéma) existuje několik standardizovaných schemat. Pokud klient schema adresáře nezná, dotazuje se na speciální položku.
LDIF je textový formát pro výměnu dat mezi LDAPím adresářem a čímkoli jiným. Aneb jakákoli data lze převést do LDIFu a následně pomocí standardních klientů vložit do LDAPího adresáře.
Položky jsou organizovány ve stromové struktuře zvané Direct Information Tree (DIT). Každá položka je identifikována svým jednoznačným rozlišovacím jménem (distinguished name - DN). Rozlišovací jméno se tvoří hierarchicky podobným procesem jako třeba IP adresy, jen syntaxe je jiná. Typicky <atribut1>=<hodnota1>, <atribut2>=<hodnota2>, ..., přičemž každá dvojice atribut-hodnota se nazývá Relative DN (RDN). Suffixem se pak nazývá jméno nejvýše umístěné položky na daném serveru. Existuje i speciální položka zvaná referral, která může fungovat jako odkaz na DIT v jiném adresáři - tím to způsobem se spravují distribuované LDAP servery (mohu například odkazovat na nejvyšší položku v nějakém vzdáleném adresáři).
Můžeme získávat operace z adresářového stromu (operace search a compare) a měnit položky ve stromě (add, delete, modify a modify RDN). Speciálními operacemi jsou pak autentizační služby (bind, unbind a abandon).
Operace search dovoluje prohledávat určité podstromy DIT do dané hloubky. Jejím výsledkem je vrácení nalezených dat (neexistuje něco jako operace read, vše je zakomponováno do search). Lze samozřejmě určit, které z atributů se mají vracet. Vyhledávací výraz (filtr) lze konstruovat pomocí obvyklých booleovských operátorů plus některých speciálních relací (například ~= znamená "přibližně stejná hodnota"). Operace compare je naproti tomu jednodušší, pouze porovná zadanou hodnotu s hodnotou nějakého atributu. Ostatní výše uvedené operace mají obvyklou sémantiku.
Protokol není omezen na jmenované operace. Lze vytvářet nové operace, popř. měnit ty stávající (seznam dostupných operací vypíše LDAP server při dotazu na speciální položku nazývanou root DSE).
LDAP podporuje komunikaci klasicky na úrovni TCP/IP přes SSL. Autentizace buď není žádná (obvykle jsou-li položky adresáře přístupné všem), nebo probíhá na úrovni ověřování DN vlastníka položky a jeho hesla (zahashovaného) a nebo proběhne pomocí SASL (Simple Authentication and Security Layer, RFC2222).
Proč se ovšem tím vším okolo LDAPu zaobírat? Vtip je v tom, že pomocí LDAPu lze autentizovaně spravovat jakékoli informace. A také lze pomocí něj řešit centrální správu uživatelů v unixových systémech. V principu nejsou informace o uživatelích a skupinách v /etc/passwd (/etc/shadow) a /etc/group, ale nacházejí se na nějakém LDAP serveru. Při přihlašování na daný unixový stroj je pak uživatel kontrolován nikoli s /etc/passwd, ale s informacemi na LDAP serveru. Odpadá tak práce s uživatelskými účty rozstrkanými po všech stanicích a vše je uloženo pouze na jednom (popř. několika) místech. Tutéž srandu můžete udělat s /etc/services, /etc/limits etc. etc. :-)
V adresáři budeme mít položky s atributy jako uid, uidNumber, gidNumber, loginshell a další, které se uživatelského účtu týkají. To vše je určeno schematem nis, které bývá dodáváno s implementací LDAPu. V tomto schématu jsou již definovány příslušné třídy, které strukturu uživatelského účtu v LDAP adresáři definují (např. posixAccount, shadowAccount).
V současnosti je k dispozici několik implementací LDAPu, zejména komerčních (od oblíbeného Microsoftu, přes Sun a IBM až po třeba Novell). Stačí si jen vybrat - nutnou a netriviální podmínkou je být v balíku. Pro nás zajímavější je však OpenLDAP, který je zadarmo, a kterému se budu nadále věnovat.
OpenLDAP je projekt na vytvoření open source balíku implementujícího vše potřebné pro provoz LDAP serverů, který by se vyrovnal dostupným komerčním řešením. Je dostupný zdarma na http://www.openldap.org/ a obsahuje vše potřebné (knihovny, servery, klientské aplikace).
Instalace asi záleží na distribuci. Já mám lehce masochistickou "distribuci" LFS, takže jsem překládal a dělal všechno ručně. Proto popíšu, jak tímhle univerzálním způsobem na to a to pro verzi 2.2.6. Hodit se vám budou knihovny OpenSSL, SASL, BerkeleyDB (pozor, u poslední verze jsou dva patche, já je raději použil) nebo GDBM a v neposlední řadě to chce mít nějakou podporu vláken (to už je dneska snad v každé distribuci). Podrobnosti najdete na stránkách OpenLDAPu. Rozhodně to není úplný výčet toho, co je potřeba, spíš to berte tak, že konkrétně tyhle věci jsem musel doinstalovat já.
Kvůli autentizaci uživatele budete potřebovat knihovnu PAM a pro získávání informací o uživateli (jeho login, home adresář atd.) budete potřebovat NSS pro LDAP. Ve skutečnosti by vám k centrální správě stačil jen ten NSS (Name Service Switch), ale pak by chodily po síti i hesla v otevřené podobě, což není zrovna bezpečné.
Nepříjemné může být to, že nemáte přeloženy programy jako login a passwd s podporou PAMu. Pak vám nezbude než znovu přeložit balík Shadow.
Zmíním některé zajímavé parametry, které je dobré předhodit ./configure skriptu a které jsou defaultně nastaveny jinak, než je pro nás zdrávo. Doporučuji:
--enable-crypt - umožňuje hashovat hesla pomocí klasické funkce crypt(3)
--enable-slurpd - replikační démon, potřeba pro sdílení účtů více LDAP servery, defaultně se nepřekládá
--libexecdir=PATH - spíš jen informačně, pokud to nezadáte, tak se vám přeložené binárky nacpou někam do $PREFIX/etc/...
--enable-syslog - přeloží podporu syslogu
Kromě několik zajímavých prográmků se přeloží hlavně démon slapd (defaultně pak běží na portu 389).
Zmíním zde příklad konfiguračního souboru, který se týká centrální správy uživatelů. V LDAPím adresáři lze skladovat prakticky cokoli, takže můžete narazit na spoustu jiných konfiguračních souborů, které budou fungovat. Tohle je jen jedna z možností.
Podle toho, jaký jste zadali při konfiguraci před překladem $PREFIX (nebo hodnotu parametru --sysconfdir, naleznete konfigurační soubor pro OpenLDAP démona, který se jmenuje slapd. Konfigurační soubor je obvykle v $PREFIX/etc/openldap a jmenuje se slapd.conf. Může vypadat takto:
database ldbm suffix "dc=mylan,dc=net" rootdn "cn=root,dc=mylan,dc=net" rootpw {MD5}nejaky_hash_hesla index objectClass,uid,uidNumber,gidNumber eq index cn,mail,surname,givenname eq,subinitial password-hash {crypt} password-crypt-salt-format "$1$%.8s"
Po řadě definuje použitou backend databázi, suffix, rozlišovací jméno kořene (tedy v tomto případě jde o uživatele root), dále heslo pro root-a (použitý je hash MD5). index říká, které atributy se budou indexovat (pro rychlejší přístup), dále se určuje, hashování a formát hesla (hesla se budou kryptovat stejně jako v unixu, čili pomocí crypt(3)). Podrobnosti se dozvíte na stránkách OpenLDAPu.
Hash hesla můžete získat pomocí programu slappasswd. Parametrem určíte hashovací funkci. Program vás vyzve k vložení hesla, jeho potvrzení a výstupem je příslušný hash hesla. Například:
# slappasswd -h {MD5}
vyhodí na výstup MD5 hash vloženého hesla. Více viz. manové stránky.
Dále je potřeba nastavit ACLs (Acces Control Lists), kterými určíme politiku přístupu uživatelů k účtům (uživatel si může měnit heslo, uživatel nesmí vidět účtu jiných uživatelů atd.). Nejdřív do slapd.conf přidáte řádek určující, kde se bude hledat soubor s politikami. Může to vypadat takto:
include /etc/openldap/slapd.access.conf
V daném adresáři pak vytvoříte soubor slapd.access.conf. Jeho obsah může vypadat následovně:
access to dn.regex=".*,dc=mylan,dc=net" attr=userPassword by dn="cn=root,dc=mylan,dc=net" write by self write by * auth access to dn.regex=".*,dc=mylan,dc=net" attr=mail by dn="cn=root,dc=mylan,dc=net" write by self write by * read access to dn.regex=".*,ou=People,dc=mylan,dc=net" by * read access to dn.regex=".*,dc=mylan,dc=net" by self write by * read
Nejdřív omezíme přístup k atributu uchovávajícímu hash hesla (userPassword). Čili zapisovat hesla může root (druhý řádek) a jejich vlastník (vlastník dané položky ~ účtu viz. třetí řádek). Hesla mohou být samozřejmě použita pro autentizaci všemi (by * auth). Další část se týká nastavení poštovních účtů, v následující části omezujeme uživatele, tak aby si nemohli měnit home adresář, login shell, uid a další. V poslední části pak nastavujeme, že si uživatel jinde v LDAPu může posloužit na svých záznamech jak je mu libo a ostatní může číst. Základní nastavení LDAP serveru tím máte dokončeno. Nyní můžete spustit slapd, popř. si připravit startovací skripty. Pro logování používá server syslog démona, defaultně je typ zprávy nastaven na local4, takže si nějak rozumně nastavte /etc/syslog.conf (popravdě řečeno, mně se to logování nějak nedařilo rozjet).
Předchozí část se týkala nastavení serveru. Nyní je nutné nastavit i klientskou stranu (kde běží LDAP server zajišťující autentizaci a další). V souboru /etc/ldap.conf by mělo být asi toto:
host 127.0.0.1 base dc=mylan,dc=net rootbinddn cn=root,dc=mylan,dc=net scope one pam_filter objectclass=posixaccount pam_login_attribute uid pam_member_attribute gid pam_password md5 nss_base_passwd ou=People,dc=mylan,dc=net?one nss_base_shadow ou=People,dc=mylan,dc=net?one nss_base_group ou=Group,dc=mylan,dc=net?one
Položka host udává IP, kde běží LDAP server, dané nastavení je pro počítač, který je zároveň serverem i klientem, v opačném případě musí být na daném místě plná IP (nebo FQDN). Hodnota položky base musí odpovídat suffixu, který je nastaven v konfiguračním souboru serveru /etc/openldap/slapd.conf. Ostatní položky musí korespondovat taktéž. Položka rootbinddn říká, kdo bude navazovat spojení s LDAP serverem (bind). Heslo musí být uloženo v /etc/ldap.secret, tento soubor musí být uložen s vlastníkem a skupinou root a musí mu být nastavena práva na 0600 (pouze rw pro roota). Heslo je tam uloženo přímo nezahashované a odpovídá tomu, jehož hash je uložen v konfiguračním souboru OpenLDAP serveru. POZOR, tento soubor musí končit až na druhém řádku (čili za heslem ještě <Enter>).
Nejdříve NSS. Předpokládá se samozřejmě nainstalování nss_ldap knihovny (jinak se k LDAPu nedostanete). V souboru /etc/nsswitch.conf nastavíte pořadí místa, kde se postupně budou informace o uživatelských účtech hledat (kromě toho jsou tam i další věci, které nás momentálně nemusí trápit). Protože chceme, aby se informace o uživatelských účtech hledali nejdřív lokálně a pak v LDAPu, tak může konfigurace u příslušných položek vypadat třeba takto:
passwd: files ldap shadow: files ldap group: files ldap
Nyní konfigurace PAMu. Konfigurační soubory se nachází obvykle v /etc/pam.d/. Zbytek už se hodně liší distribuci od distribuce. Konfigurace a spol. byla probrána v jiném referátu, takže se tím nebudu nijak podrobně zabývat. Nicméně letecky například login:
auth required pam_nologin.so auth sufficient pam_ldap.so auth sufficient pam_unix.so shadow use_first_pass auth required pam_deny.so account sufficient pam_unix.so account sufficient pam_ldap.so account required pam_deny.soa passwd:
password required pam_cracklib.so password sufficient pam_ldap.so password sufficient pam_unix.so password required pam_deny.so
Příklady těchto konfiguračních souborů naleznete v adresáři pam.d po přeložení balíku pam_ldap. Klidně je můžete použít.
Chcete-li používat LDAP například i se Sambou a s SSL/TLS, doporučuji podívat se na tutoriál od Mandraků.
Jak na účty? Pro začátek je dobré použít pro migraci nějaký šikovný nástroj. Aplikaci, která dovede přečíst /etc/passwd, /etc/shadow a /etc/group, vytáhnout odtamtud údaje a převést je do LDIFu. Takové záznamy už můžete snadno importovat do LDAP databáze. Pravděpodobně naleznete na webu celou řadu nástrojů (hlavně různých perl skriptů je mnoho), které tohle umí. Například yap2lc (Yet Another Passwd 2 LDIF Converter), ten je napsaný v Céčku nebo perlovské Migration Tools. Zkoušel jsem druhý jmenovaný, je v něm k dispozici spousta skriptů na migraci všeho možného (shadow, networks, hosts, ...). Je potřeba nastavit nějaké údaje v konfiguračním souboru migrate_common.ph. Důležité je:
$DEFAULT_MAIL_DOMAIN = "mylan.net"; $DEFAULT_BASE = "dc=mylan,dc=net"; $DEFAULT_MAIL_HOST = "mail.mylan.net"; $EXTENDED_SCHEMA = 1;
Tyto hodnoty je třeba nastavit podle hodnot v konfiguračním souboru OpenLDAP serveru. Jednotlivé skripty dávají na výstup LDIF soubory, které pak za pomoci programu ldapadd vložíte do adresáře. Dále uvedu příklad, podrobnosti si můžete posléze nastudovat sami na příslušných stránkách (doporučuji v odkazech Tutoriál od Mandraků). Příprava adresáře a migrace shadow a group:
# ./migrate_base.pl >base.ldif # ldapadd -x -D "cn=root,dc=mylan,dc=net" -W -f base.ldif # ETC_SHADOW=/etc/shadow ./migrate_passwd.pl /etc/passwd passwd.ldif # ldapadd -x -D "cn=root,dc=mylan,dc=net" -W -f passwd.ldif # ./migrate_group.pl /etc/group group.ldif # ldapadd -x -D "cn=cn=root,dc=mylan,dc=net" -W -f group.ldif
Výše zmíněné perlovské migrační skripty mají jednu nevýhodu - počítají i s tím, že máte nějaká schemata, která ovšem nejsou obsažena přímo v balíku s OpenLDAPem. Pak se připravte na to, že výsledné LDIF soubory budou chtít nějaké to SEDování. Ale záleží to asi distribuci od distribuce.
Spolu s OpenLDAP balíkem jsou dodávány programy ldapadd, ldapdelete a ldapsearch. Jsou to klasičtí řádkový klienti a práce s nimi není příliš pohodlná. Kromě toho existuje řada GUI klientů. Níže uvádím pár odkazů na ty použitelné. První dva jsem rozjel, třetí se mi nedařilo přeložit (něco se mu nelíbilo na mojí iconv knihovně), pokud máte distribuci s podporou rpm nebo deb, tak asi nebudete mít problém. Konkrétně ten java klient vypadá docela dobře, odzkoušel jsem ho, jde pěkně editovat položky, jednotlivé atributy, včetně nastavení a verifikace hesla.
gq - GTK klient pro práci s adresářem
LDAP Browser/Editor - Java klient
Pokud máte všechny uživatele pěkně na jedno místě, hrozí riziko, že zrovna daný počítač s ldap serverem nebude přístupný a tudíž se nikdo nenaloguje. Proto můžete používat sekundární LDAP servery. Kvůli uchování konzistence je nutno obsah serverů synchronizovat. K tomu slouží speciální démon zvaný slurpd. V praxi to vypadá tak, že tenhle démon jen čeká na změny (které čte ze speciálního souboru, do kterého ukládá informace o provedených operacích slapd), když nějakou změnu zjistí, přečte si, jaké operace byly provedeny a pošle požadavek na jejich provedení sekundárnímu LDAP serveru.
Především je nutné v konfiguračním souboru LDAP serveru nastavit jestli se jedná o master nebo slave. U masteru to znamená přidat položky replica s příslušnými adresami sekundární LDAP serverů. Například:
replica uri=ldaps://slave.example.com:636 binddn="cn=Replicator,dc=example,dc=com" bindmethod=simple credentials=secret
V konfiguračním souboru slave serveru nesmíte hlavně nastavovat žádné položky replica a replogfile. Dále musíte nastavit vazbu na primární server pomocí položky uptdatedn (odpovídá příslušnému binddn= v položce replica na straně masteru). Konečným krokem je nakopírování databáze primárního serveru na sekundární (záleží na použitém backendu).
Závěrem nutno říct, že jsem se na tomhle tématu docela vydusil, protože jsem o něm nevěděl téměř nic (zapsal jsem si to, abych se to dobře naučil). Záměrně jsem volil poměrně dlouhý úvod do adresářových služeb, protože mám pocit, že se to v žádném předmětu neprobírá a neprobíralo ani ve Správě UNIXu II. (cca 2 roky zpět). Nicméně všechno jsem si vyzkoušel, na vlastním počítači (pro velký provoz a neustálé štěstí na HW krach počítačů jsem to nezkoušel v laborce) nakonfiguroval a popřekládal. Jen nevím proč mi nefunguje logování, takže nevím proč se mi nechce uživatel autentizovat. Možná něco z toho vyřeším ještě po odevzdání referátu. Ale jak jsem již zmínil i výše - všechno je to hodně závislé na distribuci Linuxu jakou používáte a jaký máte základ, proto při instalaci hodně doporučuji konzultovat stránky vaší distribuce. Výše zmíněné rady se týkají LFS 4.0. Spoustu problémů si hlavně ušetříte, pokud máte většinu věcí přeloženou už s PAMem. Každopádně instalaci na LFS like systémech doporučuji jen skalním, protože se nadřete jak koně (o to ovšem jde, že :-)).
Většinu odkazů uvádím u příslušných témat přímo v textu ...
OpenLDAP - kromě jiného je tam hlavně ten administrátorův průvodce
Další tutoriálek - docela stručný, ale není dělaný na konkrétní distribuci
Beyond LFS - aneb jak přeložit správně v referátu zmiňované programy a knihovny