Adresář by měla být specializovaná databáze určená pro čtení, procházení a vyhledávání. Adresáře by my měly poskytovat dostatečně popisné informace členěné podle různých kritérií (atributů). Adresářové služby běžně neposkytují služby obvyklé u větších databází, jako například transakční zpracování, a místo toho se soustřeďují na rychlé vyhledání požadovaných dat. Více na http://www.openldap.org/doc/admin22/intro.html#What is a directory service
LDAP je zkratka z "Lightweight Directory Access Protocol". Již z názvu je patrné, že je to odlehčená verze DAP, který se však v praxi snad nikde pořádně nepoužívá kvůli jeho příliš velké složitosti a s tím souvisejícími implementačními problémy. V současné době se používá třetí verze protokolu.
Adresář v LDAP tvoří zpravidla stromovou strukturu, jak ukazují diagramy na výše zmíněném URL. Identifikátor záznamu složíme jednoduše tak, že jdeme od vybraného záznamu a zřetězíme za sebe jeho identifikátor a identifikátory všech nadřazených uzlů. Výsledku se říká Distiguished name (DN).
OpenLDAP lze stahnout na stránkách http://www.openldap.org/. K instalaci je nejjednodušší postupovat podle quickstart guide, která je k dispozici na http://www.openldap.org/doc/admin22/quickstart.html. Naštěstí většina nových distribucí obsahuje OpenLDAP server již ve své standardní výbavě.
Po stažení a instalaci (více k instalaci na http://www.openldap.org/doc/admin22/install.html ) je třeba server nakonfigurovat.
Hlavní konfigurační soubor je obvykle v /etc/openldap/slapd.conf. S distribucí je dodáván ukázkový konfigurační soubor a nejrychlejší cesta k funkční konfiguraci vede přes úpravu tohoto souboru.
Nejprve nastavíme úložiště pro databázi objektů: database ldbm
suffix "dc=example,dc=com" rootdn "cn=Manager,dc=example,dc=com" rootpw neco directory /var/lib/example.com index objectClass eqStručné vysvětlení:
Dále je třeba server spustit (buď přímo slapd z příkazového řádku nebo příslušné startup skripty z distribuce) a naplnit iniciálními daty.
K plněni adresáře se běžně používaji tzv. LDIF soubory. Jsou to obyčejné textové (ascii) soubory, ve kterých se nacházejí LDAP záznamy oddělené prázdným řádkem. Poněkud přesnější definici nalezneme na URL http://www.openldap.org/doc/admin22/dbtools.html#The LDIF text entry format Základní tvar vypadá takto:
# comment dn: <distinguished name> <attrdesc>: <attrvalue> <attrdesc>: <attrvalue>První řádek je komentář. Druhý řádek udává atribut se jménem "dn", což je zkratka z Distinguished name. Každý záznam musí mít unikátní DN. Následují řádky, které udávají vždy jeden atribut a po dvojtečce jeho hodnotu. Nezapomínejme, že se jedná opravdu o ASCII soubory, takže například české znaky nemůžeme jednoduše zapisovat ani v názvech atributů a ani v jejich hodnotách.
V našem oblíbeném editoru vytvoříme nový textový LDIF soubor (třeba init.ldif) a do něj zadefinujeme pro začátek dva objekty. První je samotný kořen databáze (ten samý jako v slapd.conf) a správce databáze (opět ten samý jako v slapd.conf).
Náš první LDIF soubor bude vypadat takto:
dn: dc=example,dc=com objectclass: dcObject objectclass: organization o: Nazev organizace dc: example dn: cn=Manager,dc=,dc= objectclass: organizationalRole cn: Manager
Máme tedy data v textovém souboru a musíme je ještě dostat do samotného adresáře v LDAPu. K tomu poslouží například příkaz ldapadd.
ldapadd -x -D "cn=Manager,dc=example,dc=com" -W -f init.ldif
(parametry popořadě: jednodnuchá autentizace, identifikovat se jako "cn=...", zeptat se na heslo, použít data ze souboru init.ldif)
V případě, že jsme se někde nepřeklepnuli, příkaz skončí bez výpisu. Data jsou v databázi a můžeme začít pracovat. Doteď jsme tam však neuložili vlastně žádná pro nás hodnotná data.
Pro jistotu jednoduché ověření pomocí příkazu:
ldapsearch -x -b 'dc=example,dc=com' '(objectclass=*)'(jednoduchá autentizace, prohledávat pod "dc=...", hledat všechno).
Poznámka: V dokumentaci se lze dočíst, že po použití příkazu ldapadd bychom měli server zrestartovat, aby správně poznal všechny změny a dokonce se vyskytuje i doporučení, že před použítim ldapadd by neměl vůbec běžet, jinak se za nic neručí :). Je tedy dobré vyhnout se současnému plnění pomocí ldapadd a případných soubežných modifikací např. z již běžících systémů.
Doposud jsme absolvovali spíše cvičení kopírování a vkládání do shellu. Jednoduše zde byly nějaké atributy, pak něco jako objectclass a když jsme to nakopírovali do shellu, tak nám vzniknul funkční LDAP.
Jenže v LDAPu (alespoň v tomhle) platí, že nic nedefinovaného z nebe nespadlo. A všechno máme definované v tzv. schématech. Standardní distribuce již obsahuje několik užitečných a obsáhlých schémat. Která ze schémat použijeme záleží na nás a určujeme to použitím direktiv "include" v konfiguračním souboru (slapd.conf).
Pro naše potřeby použijeme:
include /etc/openldap/schema/core.schema include /etc/openldap/schema/cosine.schema include /etc/openldap/schema/nis.schema include /etc/openldap/schema/inetorgperson.schema
Každý objekt definovaný ve schématech má své jméno a jednoznačný identifikátor, tzv. OID (Object identifier, podobné najdeme třeba v SNMP). Tato čísla si sice můžeme vymýšlet dle libosti, ale dřív nebo později bychom se tak dostali do problémů. Lepší je využít standardních objektů a tříd a vlastní výplody číslovat do segmentu začínajícího 1.1. (experimentální "dead" namespace).
I v definici schemat se logicky odráží stromová struktura, tedy dědičnost. Základem všeho je třída (objectClass) jménem "top". Protože ji musí obsahovat (dědit z ní) každý objekt, není při psaní LDIF záznamů povinná (nahoře byla vynechána). Ostatní třídy jsme již museli explicitně uvést. V definici schémat je použit podobný princip a dědí se z ní standardně.
Každá třída může definovat kromě jména třídy i atributy, které s sebou objekty z ní vytvořené ponesou. Může rovněž určit, které atributy budou povinné a které pouze volitelné. Při definici objektů v LDAP tedy specifikujeme všechny objectClass, které bude objekt používat a poté všechny atributy, které chceme nebo musíme vyplnit.
V definicích můžeme najít tři typy tříd: "ABSTRACT", "STRUCTURAL", "AUXILIARY". Důležité je, že pokud chceme definovat objekt v LDAP, musí obsahovat právě jednu STRUCTURAL objectClass. Pokud tomu bude jinak, bude si slapd stěžovat a záznam neprovede.
Stručná charakteristika:
ABSTRACT - slouží pouze jako šablona pro ostatní
STRUCTURAL - definuje třídu s jistou specifickou množinou vlastností (např.
člověk, auto, počítač,...)
AUXILIARY - doplňuje většinou STRUCTURAL třídy dalšími atributy
Tomuto chování lze snadno zabránit volbou "schemacheck off" v konfiguračním souboru slapd.conf. Potom můžeme skutečně do LDAPu vnutit cokoliv, ale samozřejmě to není ta správná cesta řešení problémů ;). Starší verze OpenLDAP nebyly tak striktní, ale novější verze mají standardně tuto kontrolu zapnutou.
Příklad definice:
objectclass ( 1.3.6.1.1.1.2.0 NAME 'posixAccount' SUP top AUXILIARY DESC 'Abstraction of an account with POSIX attributes' MUST ( cn $ uid $ uidNumber $ gidNumber $ homeDirectory ) MAY ( userPassword $ loginShell $ gecos $ description ) )
Příhlášení se do LDAPu se běžně označuje jako "bind". Důležité je vědět, že pro přístup do LDAPu nedefinujeme nikde externě uživatele nebo účty, ale rovnou ukážeme na libovolný záznam v LDAP a řekneme, že to jsme my. Server nás následně požádá o heslo a porovná s heslem pro daný záznam.
Autorizaci musíme vyřešit v konfiguračním souboru serveru (slapd.conf). Podrobnější popis na: http://www.openldap.org/doc/admin22/slapdconfig.html#Access Control
Příklad:
access to * by self write by anonymous auth by * read
Dává přístup ke všem objektům tak, že:
"záznam sám" se může zapsat (pokud jsme se jako on přihlásili, můžeme v sobě
měnit data)
anonymní uživatel se může jako záznam přihlásit (nic jiného)
a ostatní (přihlášení) uživatelé mohou záznam číst
Důležité je pořadí vyhodnocování takovýchto deklarací. Nejprve se vyhodnocují deklarace u příslušných databázi v konfiguračním souboru a poté globální. V rámci těchto dvou kategorií se hledá první shoda pro zkoumaný objekt a část za "access to". Pokud se najde, prochází se pravidla pod ní uvedená opět postupně a zastaví se na první shodě na parametru za slovem "by". Pokud se našla shoda, srovná se požadovaná uroveň oprávnění (read,write,...) s úrovní definovanou v konfiguračním souboru. Pokud je shoda i tam, je požadovaný přistup povolen, jinak se zamítá. Je vidět, že pořadí deklarací v konfiguračním souboru je v každém kroku velmi důležité.
Z uvedeného například plyne, že pokud bychom přesunuli pravidlo "by self write" na konec, nemohl by nikdo svůj záznam měnit.
Nyní máme funkční LDAP (kostru) a připravená potřebná schémata. Zbývá takový server ještě rozumně využít, třeba na autentizaci uživatelů do linuxu. Hlavní výhodou pro nás bude, že budeme mít centrální správu uživatelů. Celý problém rozdělíme na dvě části. První bude část autentizace uživatele do systému a druhou zjišťování informací o uživatelích.
Pro uživatelské účty se typicky používá objectClass posixAccount doplněná o shadowAccount, pro skupiny objectClass posixGroup.
Pro tyto potřeby využijeme PAM autentizačního systému a jeho modulu pam_ldap.so ( http://www.padl.com/OSS/pam_ldap.html ), běžně součástí distribucí. Upravíme konfigurační soubor PAMu (například /etc/pam.d/sshd pro ssh daemona) a přidáme záznamy pro LDAP:
auth sufficient /lib/security/pam_ldap.so account sufficient /lib/security/pam_ldap.so password sufficient /lib/security/pam_ldap.so
Tyto řádky musí příjít na vhodné místo tak, aby PAM dělal to, co si přejete ;). K určení tohoto místa (většinou před autentizací krz shadow) nejlépe použít minulý referát k PAMu.
To by však bylo příliš málo. Pokračujeme úpravou konfiguračního souboru pro pam_ldap, který se většinou nachází v /etc/ldap.conf.
Vyplníme nezbytné minimum:
# IP Adresa LDAP serveru (může být i hostname) host 127.0.0.1 # Větev v LDAPu, pod kterou budeme hledat účty base dc=example,dc=com # Verze LDAP protokolu, kterou budeme mluvit ldap_version 3 # Účet, pod kterým se budeme do LDAPu hlásit binddn uid=validator,dc=example,dc=com # Heslo k účtu bindpw validator
Nyní by mělo být možné se do systému přihlásit účty z LDAP. Pokud ale uživatel vlastní nějaký soubor, příkaz ls -la by nám ukazoval pouze číslo. To je třeba ještě změnit.
K tomuto účelu použijeme knihovnu nss_ldap ( http://www.padl.com/OSS/nss_ldap.html ), která potřebné informace vyhledá v LDAP. Opět bývá standardní součástí distribucí.
Konfigurace NSS spočívá v úpravě souboru /etc/nsswitch.conf a přípsání "ldap" všude tam, kde chceme, aby se LDAP používal. V našem případě to bude vypadat například takto (po úpravě):
passwd: files nisplus ldap shadow: files nisplus ldap group: files nisplus ldap
Tím doplníme údaje z /etc/passwd, /etc/shadow a /etc/group z LDAP.
Doteď jsme systém nastavili tak, že pro každou požadovanou informaci (např. převod uid čísla na jméno uživatele) se dotazoval LDAP serveru. To samozřejmě (i přes vhodné indexy) generuje na straně LDAP serveru značnou zátěž. Vhodným kešováním již na lokálním stroji by tato zátěž výrazně klesla.
K odstranění této zátěže můžeme použít nscd, konfigurační soubor je obvykle /etc/nscd.conf. Bližsí info viz man nscd.conf.
(kopie z dokumentace)
dn:dc=yourorg, dc=com objectclass: top objectclass: organizationalUnit dn:ou=groups, dc=yourorg, dc=com objectclass: top objectclass: organizationalUnit ou: groups dn:ou=people, dc=yourorg, dc=com objectclass: top objectclass: organizationalUnit ou: people dn: cn=Giuseppe LoBiondo, ou=people, dc=yourorg, dc=com cn: Giuseppe Lo Biondo sn: Lo Biondo objectclass: top objectclass: person objectclass: posixAccount objectclass: shadowAccount uid:giuseppe userpassword:{crypt}$1$ss2ii(0$gbs*do&@=)eksd uidnumber:104 gidnumber:100 gecos:Giuseppe Lo Biondo loginShell:/bin/zsh homeDirectory: /home/giuseppe shadowLastChange:10877 shadowMin: 0 shadowMax: 999999 shadowWarning: 7 shadowInactive: -1 shadowExpire: -1 shadowFlag: 0 dn: cn=mygroup, ou=groups, dc=yourorg, dc=com objectclass: top objectclass: posixGroup cn: mygroup gidnumber: 100 memberuid: giuseppe memberuid: anotheruser
http://www.openldap.org/doc/admin22/quickstart.html
http://www.openldap.org/
RFC2253, "Lightweight Directory Access Protocol (v3): UTF-8 String Representation of Distinguished Names."
http://www.rfc-editor.org/rfc/rfc2253.txt
RFC2251 "The Lightweight Directory Access Protocol (v3)"
ftp://kalamazoolinux.org/pub/pdf/ldapv3.pdf
http://en.tldp.org/HOWTO/LDAP-HOWTO/
http://www.tldp.org/HOWTO/LDAP-Implementation-HOWTO/pamnss.html
GQ LDAP klient
http://biot.com/gq/