Dans mon précédent article, nous avions vu comment utiliser le serveur d'annuaire 389 Directory Server (389DS) pour stocker les données d'un serveur DNS. Nous gérons aussi nos comptes utilisateurs dans cet annuaire LDAP. Nous disposons donc d'une infrastructure dont une part non négligeable des données administratives sont stockées dans un annuaire. Et nous pouvons aller au-delà : stockons nos données DHCP dans un annuaire. Cet article se propose donc de vous montrer la marche à suivre pour le faire avec 389DS, dans la foulée du serveur DNS.
Dans un article sur Cobbler [1], j'avais abordé le fait que nous construisions une CMDB (Configuration Management DataBase) en stockant les informations des machines dans Cobbler. Il est tout à fait envisageable d'imaginer que Cobbler « sérialise » ses données dans un annuaire (l'API permet d'ailleurs d'écrire un « sérialiseur »). Dès lors, Cobbler n'aurait plus besoin d'utiliser son mécanisme de templates pour gérer les services DHCP et DNS. Au passage, la sauvegarde des données de l'annuaire sauvegarderait aussi les données des services DNS, DHCP et Cobbler (pour partie), simplifiant la politique de sauvegarde. Nous retrouverions d'ailleurs un comportement assez proche... d'Active Directory, les outils de manipulation en moins.
Mais trêve de divagations... Je pars du principe que vous savez configurer le service DHCP via ses fichiers de configuration habituels. Nous partirons donc d'un exemple de configuration classique que nous migrerons dans l'annuaire LDAP.
Pour cet article, je ne repasserai pas sur la configuration de 389DS puisque nous l'avons réalisée dans l'article précédent sur le DNS. Je rappelle juste quelques points utiles. Le serveur d'annuaire écoute à l'adresse 10.0.2.101 et son suffixe LDAP est dc=localdomain. Ceux qui viennent de lire l'article précédent auront une impression de déjà vu : c'est normal, c'est du copier/coller ; ne réinventons pas la roue ! ;)
1. Configuration de base de ISC DHCP
Dans un premier temps, nous installons le package dhcp (yum install dhcp), nous configurons le serveur DHCP de manière classique, via le fichier /etc/dhcp/dhcpd.conf ci-dessous.
authoritative;
ddns-update-style none;
default-lease-time 259200;
max-lease-time 259200;
subnet 10.0.2.0 netmask 255.255.255.0 {
option broadcast-address 10.0.2.255;
option routers 10.0.2.2;
option domain-name "localdomain";
option domain-name-servers ns.localdomain;
deny unknown-clients;
host client01 {
hardware ethernet 08:00:27:d5:08:08;
fixed-address 10.0.2.201;
}
}
J'ai volontairement pris un exemple particulièrement simple :
- Un seul réseau 10.0.2.0/24 dont l'adresse de broadcast est 10.0.2.255, le routeur 10.0.2.2, le nom de domaine localdomain et le serveur DNS ns.localdomain. Les informations DNS correspondent au service que nous avons configuré dans le précédent article.
- Les clients non renseignés dans la configuration ne recevront pas de bail DHCP (deny unknown-clients).
- Un seul client dont l'adresse MAC est 08:00:27:d5:08:08 et auquel nous attribuons l'adresse IP 10.0.2.201.
Il suffit de démarrer et d'activer le service comme suit :
service dhcpd start
chkconfig dhcpd on
Voici la règle à ajouter dans /etc/sysconfig/iptables pour que le firewall accepte les requêtes :
# DHCP Server
-A INPUT -p udp --dport 67 -j ACCEPT
Pour valider le fonctionnement du serveur DHCP, il faut vérifier dans /var/log/messages que le client se voit bien offrir un bail et sur le client que la configuration réseau s'effectue bien.
2. Migration des données dans l'annuaire LDAP
Maintenant que notre service est fonctionnel, je vous propose d'entrer dans le vif du sujet.
2.1 Intégration du schéma et arborescence de base
Pour que l'annuaire puisse accueillir nos données, nous devons lui en fournir la description au travers d'un schéma spécifique. Nous commençons donc par télécharger et installer ce schéma.
root# service dirsrv stop localdomain
root# urlgrabber http://www.lunytune.net/old/dhcp.schema.gz
root# urlgrabber http://directory.fedoraproject.org/download/ol-schema-migrate.pl
root# gunzip dhcp.schema.gz
root# chmod u+x /root/ol-schema-migrate.pl
root# /root/ol-schema-migrate.pl -b /root/dhcp.schema > /etc/dirsrv/slapd-localdomain/schema/60dhcp.ldif
root# service dirsrv start localdomain
Nous avons arrêté le service d’annuaire, puis téléchargé le schéma (dhcp.schema) et le script de conversion (ol-schema-migrate.pl), installé la version convertie du schéma dans le répertoire où sont installés les schémas de notre instance d’annuaire (/etc/dirsrv/slapd-localdomain/schema), et nous avons redémarré le service. Notre instance d’annuaire sait maintenant traiter des données DHCP.
Nous créons une arborescence spécifique pour stocker les données DHCP, directement sous la racine de l’annuaire, ainsi qu’un utilisateur spécifique au service DHCP. Nous souhaitons limiter les droits sur la consultation des données : nous ajoutons donc une ACI (Access Control Instruction) à l’annuaire pour que seul l’utilisateur cn=dhcpadmin,ou=Special Users,dc=localdomain puisse consulter les données. Cet utilisateur sera utilisé par dhcpd pour obtenir les données DHCP. Nous créons donc le fichier LDIF /root/389ds/389ds-dhcp_base.ldif comme suit :
# /root/389ds/389ds-dhcp_base.ldif
dn: ou=dhcp,dc=localdomain
objectClass: top
objectClass: organizationalUnit
ou: dhcp
description: All informations about DHCP
aci: (target="ldap:///ou=dhcp,dc=localdomain")(version 3.0; acl "DHCP Administrator"; deny(all) userdn!="ldap:///cn=dhcpadmin,ou=Special Users,dc=localdomain";)
dn: cn=dhcpadmin,ou=Special Users,dc=localdomain
objectClass: top
objectClass: person
cn: dhcpadmin
sn: DHCP Administrator
Nous ajoutons ces données à l’annuaire et positionnons le mot de passe pour l’utilisateur qui gère les données DHCP :
root# /usr/lib/mozldap/ldapmodify -a -h ldap.localdomain \
-D "cn=Directory Manager" -w - \
-f /root/389ds/389ds-dhcp_base.ldif
root# /usr/lib/mozldap/ldappasswd -Z -h ldap.localdomain -p 636 \
-P /etc/dirsrv/slapd-localdomain/cert8.db \
-D "cn=Directory Manager" -w - \
-s "dhcpPassword" "cn=dhcpadmin,ou=Special Users,dc=localdomain"
2.2 Déclaration du service
Le début du fichier /etc/dhcp/dhcpd.conf contient les options du service DHCP, précisant entre autres choses la durée des baux... Nous reprenons donc ces informations et les transformons en attributs d'un objet de classe dhcpService. Cet objet référence le serveur DHCP via l'attribut dhcpPrimaryDN, serveur qui est ensuite déclaré sous la forme d'un objet de classe dhcpServer référençant à son tour le service associé (je sais, c'est un peu redondant...). Notez cependant que le nom du serveur doit être celui renvoyé par hostname (ici lilith.localdomain), sans quoi le service ne démarrera pas.
# /root/389ds/389ds-dhcp_structure.ldif
dn: cn=localdomain,ou=dhcp,dc=localdomain
cn: localdomain
objectClass: top
objectClass: dhcpService
dhcpPrimaryDN: cn=lilith.localdomain,ou=dhcp,dc=localdomain
dhcpStatements: ddns-update-style none
dhcpStatements: default-lease-time 14400
dhcpStatements: max-lease-time 14400
dhcpStatements: authoritative
dn: cn=lilith.localdomain,ou=dhcp,dc=localdomain
cn: lilith.localdomain
objectClass: top
objectClass: dhcpServer
dhcpServiceDN: cn=localdomain,ou=dhcp,dc=localdomain
L'injection se fait toujours via ldapmodify :
/usr/lib/mozldap/ldapmodify -a -h ldap.localdomain \
-D "cn=Directory Manager" -w - \
-f /root/389ds/389ds-dhcp_structure.ldif
2.3 Déclaration du réseau 10.0.2.0/24
Pour pouvoir déclarer des hôtes, nous devons les associer à un sous-réseau. Pour cela, nous créons une entrée de classe dhcpSubnet et qui reprend les attributs du sous-réseau que nous avons déclaré en début d'article :
- le masque de sous-réseau est 255.255.255.0 (attribut dhcpNetMask sous sa forme abrégée) ;
- l'adresse de broadcast (10.0.2.255), l'adresse IP du routeur par défaut (10.0.2.2), le nom de domaine (localdomain) et le serveur DNS (ns.localdomain) sous la forme d'attribut dhcpOption.
Cela donne le fichier LDIF /root/389ds/389ds-dhcp_10.0.2.0.ldif qui suit :
# /root/389ds/389ds-dhcp_10.0.2.0.ldif
dn: cn=10.0.2.0,cn=networks,cn=localdomain,ou=dhcp,dc=localdomain
cn: 10.0.2.0
objectClass: top
objectClass: dhcpSubnet
objectClass: dhcpOptions
dhcpNetMask: 24
dhcpOption: broadcast-address 10.0.2.255
dhcpOption: routers 10.0.2.2
dhcpOption: domain-name "localdomain"
dhcpOption: domain-name-servers ns.localdomain
L'injection se fait toujours via ldapmodify :
/usr/lib/mozldap/ldapmodify -a -h ldap.localdomain \
-D "cn=Directory Manager" -w - \
-f /root/389ds/389ds-dhcp_10.0.2.0.ldif
2.4 Déclaration du client
Nous voici maintenant à l'essentiel : la déclaration de l'hôte ! Nous créons là aussi un fichier LDIF qui déclare une entrée de classe dhcpHost, dont l'adresse MAC est 08:00:27:d5:08:08 (attribut dhcpHWAddress) et l'adresse IP 10.0.2.201 (attribut de type dhcpStatements).
# /root/389ds/389ds-dhcp_client01.ldif
dn: cn=client01,cn=networks,cn=localdomain,ou=dhcp,dc=localdomain
cn: client01
objectClass: top
objectClass: dhcpHost
dhcpHWAddress: ethernet 08:00:27:d5:08:08
dhcpStatements: fixed-address 10.0.2.201
Nous l'injectons avec l'inépuisable ldapmodify
/usr/lib/mozldap/ldapmodify -a -h ldap.localdomain \
-D "cn=Directory Manager" -w - \
-f /root/389ds/389ds-dhcp_client01.ldif
Nous allons pouvoir passer à la configuration du service dhcpd.
3. Bascule du service DHCP sur le backend LDAP
Et comme d'habitude, la dernière étape est la plus simple. Nous devons indiquer au serveur DHCP où trouver sa configuration et ses données. Le fichier /etc/dhcp/dhcpd.conf devient donc :
ldap-server "ldap.localdomain";
ldap-port 389;
ldap-username "cn=dhcpadmin,ou=Special Users,dc=localdomain";
ldap-password "dhcpPassword";
ldap-base-dn "ou=dhcp,dc=localdomain";
ldap-method dynamic;
Le serveur LDAP écoute à l'adresse ldap.localdomain (ldap-server) sur le port 389 (ldap-port). Pour se connecter à l'annuaire, le serveur DHCP utilise le compte cn=dhcpadmin,ou=Special Users,dc=localdomain (ldap-username) avec le mot de passe défini précédemment (ldap-password). Les données sont stockées dans la branche ou=dhcp,dc=localdomain (ldap-base-dn). Ce qui est important ici est que nous utilisons la méthode dynamic qui lit les données dans l'annuaire à chaque requête, évitant ainsi de redémarrer le service DHCP pour prendre en compte les modifications ; la méthode static réduit la charge sur le serveur LDAP, mais réduit aussi l'intérêt d'utiliser un annuaire.
Le redémarrage du service (service dhcpd restart) permet d'utiliser les nouveaux paramètres. Et c'est le dernier redémarrage que vous aurez à faire, grâce à l'utilisation de la méthode dynamic.
Vous disposez donc maintenant d'une solution centralisée pour gérer l'Identité au sein de votre organisation. Vos utilisateurs sont authentifiés via PAM/LDAP, leurs certificats sont exportés dans l'annuaire si vous avez une PKI. Vos machines sont renseignées dans les services DNS et DHCP avec le backend LDAP, et elles sont déployées et configurées grâce à Cobbler et Puppet. Bien entendu, maintenir tout ceci à jour nécessite du travail, mais vous écrirez rapidement vos propres outils. Vous pouvez aussi regarder du côté de produits libres tels que FreeIPA [2] qui s'occupe de toutes ces fonctions de manière totalement intégrée.
Références
[1] GNU/Linux Magazine France, Juillet-Août 2009
[2] http://freeipa.org/page/Main_Page
[3] http://directory.fedoraproject.org/