This is a +followup +on my +previous +work on +merging +all the computer related LDAP objects in Debian Edu.
+ +As a step to try to see if it possible to merge the DNS and DHCP +LDAP objects, I have had a look at how the packages pdns-backend-ldap +and dhcp3-server-ldap in Debian use the LDAP server. The two +implementations are quite different in how they use LDAP.
+ +To get this information, I started slapd with debugging enabled and +dumped the debug output to a file to get the LDAP searches performed +on a Debian Edu main-server. Here is a summary. + +powerdns
+ +Clues +on how to set up PowerDNS to use a LDAP backend is available on +the web. + +PowerDNS have two modes of operation using LDAP as its backend. +One "strict" mode where the forward and reverse DNS lookups are done +using the same LDAP objects, and a "tree" mode where the forward and +reverse entries are in two different subtrees in LDAP with a structure +based on the DNS names, as in tjener.intern and +2.2.0.10.in-addr.arpa.
+ +In tree mode, the server is set up to use a LDAP subtree as its +base, and uses a "base" scoped search for the DNS name by adding +"dc=tjener,dc=intern," to the base with a filter for +"(associateddomain=tjener.intern)" for the forward entry and +"dc=2,dc=2,dc=0,dc=10,dc=in-addr,dc=arpa," with a filter for +"(associateddomain=2.2.0.10.in-addr.arpa)" for the reverse entry. For +forward entries, it is looking for attributes named dnsttl, arecord, +nsrecord, cnamerecord, soarecord, ptrrecord, hinforecord, mxrecord, +txtrecord, rprecord, afsdbrecord, keyrecord, aaaarecord, locrecord, +srvrecord, naptrrecord, kxrecord, certrecord, dsrecord, sshfprecord, +ipseckeyrecord, rrsigrecord, nsecrecord, dnskeyrecord, dhcidrecord, +spfrecord and modifytimestamp. For reverse entries it is looking for +the attributes dnsttl, arecord, nsrecord, cnamerecord, soarecord, +ptrrecord, hinforecord, mxrecord, txtrecord, rprecord, aaaarecord, +locrecord, srvrecord, naptrrecord and modifytimestamp. The equivalent +ldapsearch commands could look like this:
+ ++ ++ldapsearch -h ldap \ + -b dc=tjener,dc=intern,ou=hosts,dc=skole,dc=skolelinux,dc=no \ + -s base -x '(associateddomain=tjener.intern)' dNSTTL aRecord nSRecord \ + cNAMERecord sOARecord pTRRecord hInfoRecord mXRecord tXTRecord \ + rPRecord aFSDBRecord KeyRecord aAAARecord lOCRecord sRVRecord \ + nAPTRRecord kXRecord certRecord dSRecord sSHFPRecord iPSecKeyRecord \ + rRSIGRecord nSECRecord dNSKeyRecord dHCIDRecord sPFRecord modifyTimestamp + +ldapsearch -h ldap \ + -b dc=2,dc=2,dc=0,dc=10,dc=in-addr,dc=arpa,ou=hosts,dc=skole,dc=skolelinux,dc=no \ + -s base -x '(associateddomain=2.2.0.10.in-addr.arpa)' + dnsttl, arecord, nsrecord, cnamerecord soarecord ptrrecord \ + hinforecord mxrecord txtrecord rprecord aaaarecord locrecord \ + srvrecord naptrrecord modifytimestamp +
In Debian Edu/Lenny, the PowerDNS tree mode is used with +ou=hosts,dc=skole,dc=skolelinux,dc=no as the base, and these are two +example LDAP objects used there. In addition to these objects, the +parent objects all th way up to ou=hosts,dc=skole,dc=skolelinux,dc=no +also exist.
+ ++ ++dn: dc=tjener,dc=intern,ou=hosts,dc=skole,dc=skolelinux,dc=no +objectclass: top +objectclass: dnsdomain +objectclass: domainrelatedobject +dc: tjener +arecord: 10.0.2.2 +associateddomain: tjener.intern + +dn: dc=2,dc=2,dc=0,dc=10,dc=in-addr,dc=arpa,ou=hosts,dc=skole,dc=skolelinux,dc=no +objectclass: top +objectclass: dnsdomain2 +objectclass: domainrelatedobject +dc: 2 +ptrrecord: tjener.intern +associateddomain: 2.2.0.10.in-addr.arpa +
In strict mode, the server behaves differently. When looking for +forward DNS entries, it is doing a "subtree" scoped search with the +same base as in the tree mode for a object with filter +"(associateddomain=tjener.intern)" and requests the attributes dnsttl, +arecord, nsrecord, cnamerecord, soarecord, ptrrecord, hinforecord, +mxrecord, txtrecord, rprecord, aaaarecord, locrecord, srvrecord, +naptrrecord and modifytimestamp. For reverse entires it also do a +subtree scoped search but this time the filter is "(arecord=10.0.2.2)" +and the requested attributes are associateddomain, dnsttl and +modifytimestamp. In short, in strict mode the objects with ptrrecord +go away, and the arecord attribute in the forward object is used +instead.
+ +The forward and reverse searches can be simulated using ldapsearch +like this:
+ ++ ++ldapsearch -h ldap -b ou=hosts,dc=skole,dc=skolelinux,dc=no -s sub -x \ + '(associateddomain=tjener.intern)' dNSTTL aRecord nSRecord \ + cNAMERecord sOARecord pTRRecord hInfoRecord mXRecord tXTRecord \ + rPRecord aFSDBRecord KeyRecord aAAARecord lOCRecord sRVRecord \ + nAPTRRecord kXRecord certRecord dSRecord sSHFPRecord iPSecKeyRecord \ + rRSIGRecord nSECRecord dNSKeyRecord dHCIDRecord sPFRecord modifyTimestamp + +ldapsearch -h ldap -b ou=hosts,dc=skole,dc=skolelinux,dc=no -s sub -x \ + '(arecord=10.0.2.2)' associateddomain dnsttl modifytimestamp +
In addition to the forward and reverse searches , there is also a +search for SOA records, which behave similar to the forward and +reverse lookups.
+ +A thing to note with the PowerDNS behaviour is that it do not +specify any objectclass names, and instead look for the attributes it +need to generate a DNS reply. This make it able to work with any +objectclass that provide the needed attributes.
+ +The attributes are normally provided in the cosine (RFC 1274) and +dnsdomain2 schemas. The latter is used for reverse entries like +ptrrecord and recent DNS additions like aaaarecord and srvrecord.
+ +In Debian Edu, we have created DNS objects using the object classes +dcobject (for dc), dnsdomain or dnsdomain2 (structural, for the DNS +attributes) and domainrelatedobject (for associatedDomain). The use +of structural object classes make it impossible to combine these +classes with the object classes used by DHCP.
+ +There are other schemas that could be used too, for example the +dnszone structural object class used by Gosa and bind-sdb for the DNS +attributes combined with the domainrelatedobject object class, but in +this case some unused attributes would have to be included as well +(zonename and relativedomainname).
+ +My proposal for Debian Edu would be to switch PowerDNS to strict +mode and not use any of the existing objectclasses (dnsdomain, +dnsdomain2 and dnszone) when one want to combine the DNS information +with DHCP information, and instead create a auxiliary object class +defined something like this (using the attributes defined for +dnsdomain and dnsdomain2 or dnszone):
+ ++ ++objectclass ( some-oid NAME 'dnsDomainAux' + SUP top + AUXILIARY + MAY ( ARecord $ MDRecord $ MXRecord $ NSRecord $ SOARecord $ CNAMERecord $ + DNSTTL $ DNSClass $ PTRRecord $ HINFORecord $ MINFORecord $ + TXTRecord $ SIGRecord $ KEYRecord $ AAAARecord $ LOCRecord $ + NXTRecord $ SRVRecord $ NAPTRRecord $ KXRecord $ CERTRecord $ + A6Record $ DNAMERecord + )) +
This will allow any object to become a DNS entry when combined with +the domainrelatedobject object class, and allow any entity to include +all the attributes PowerDNS wants. I've sent an email to the PowerDNS +developers asking for their view on this schema and if they are +interested in providing such schema with PowerDNS, and I hope my +message will be accepted into their mailing list soon.
+ +ISC dhcp
+ +The DHCP server searches for specific objectclass and requests all +the object attributes, and then uses the attributes it want. This +make it harder to figure out exactly what attributes are used, but +thanks to the working example in Debian Edu I can at least get an idea +what is needed without having to read the source code.
+ +In the DHCP server configuration, the LDAP base to use and the +search filter to use to locate the correct dhcpServer entity is +stored. These are the relevant entries from +/etc/dhcp3/dhcpd.conf:
+ ++ ++ldap-base-dn "dc=skole,dc=skolelinux,dc=no"; +ldap-dhcp-server-cn "dhcp"; +
The DHCP server uses this information to nest all the DHCP +configuration it need. The cn "dhcp" is located using the given LDAP +base and the filter "(&(objectClass=dhcpServer)(cn=dhcp))". The +search result is this entry:
+ ++ ++dn: cn=dhcp,dc=skole,dc=skolelinux,dc=no +cn: dhcp +objectClass: top +objectClass: dhcpServer +dhcpServiceDN: cn=DHCP Config,dc=skole,dc=skolelinux,dc=no +
The content of the dhcpServiceDN attribute is next used to locate the +subtree with DHCP configuration. The DHCP configuration subtree base +is located using a base scope search with base "cn=DHCP +Config,dc=skole,dc=skolelinux,dc=no" and filter +"(&(objectClass=dhcpService)(|(dhcpPrimaryDN=cn=dhcp,dc=skole,dc=skolelinux,dc=no)(dhcpSecondaryDN=cn=dhcp,dc=skole,dc=skolelinux,dc=no)))". +The search result is this entry:
+ ++ ++dn: cn=DHCP Config,dc=skole,dc=skolelinux,dc=no +cn: DHCP Config +objectClass: top +objectClass: dhcpService +objectClass: dhcpOptions +dhcpPrimaryDN: cn=dhcp, dc=skole,dc=skolelinux,dc=no +dhcpStatements: ddns-update-style none +dhcpStatements: authoritative +dhcpOption: smtp-server code 69 = array of ip-address +dhcpOption: www-server code 72 = array of ip-address +dhcpOption: wpad-url code 252 = text +
Next, the entire subtree is processed, one level at the time. When +all the DHCP configuration is loaded, it is ready to receive requests. +The subtree in Debian Edu contain objects with object classes +top/dhcpService/dhcpOptions, top/dhcpSharedNetwork/dhcpOptions, +top/dhcpSubnet, top/dhcpGroup and top/dhcpHost. These provide options +and information about netmasks, dynamic range etc. Leaving out the +details here because it is not relevant for the focus of my +investigation, which is to see if it is possible to merge dns and dhcp +related computer objects.
+ +When a DHCP request come in, LDAP is searched for the MAC address +of the client (00:00:00:00:00:00 in this example), using a subtree +scoped search with "cn=DHCP Config,dc=skole,dc=skolelinux,dc=no" as +the base and "(&(objectClass=dhcpHost)(dhcpHWAddress=ethernet +00:00:00:00:00:00))" as the filter. This is what a host object look +like:
+ ++ ++dn: cn=hostname,cn=group1,cn=THINCLIENTS,cn=DHCP Config,dc=skole,dc=skolelinux,dc=no +cn: hostname +objectClass: top +objectClass: dhcpHost +dhcpHWAddress: ethernet 00:00:00:00:00:00 +dhcpStatements: fixed-address hostname +
There is less flexiblity in the way LDAP searches are done here. +The object classes need to have fixed names, and the configuration +need to be stored in a fairly specific LDAP structure. On the +positive side, the invidiual dhcpHost entires can be anywhere without +the DN pointed to by the dhcpServer entries. The latter should make +it possible to group all host entries in a subtree next to the +configuration entries, and this subtree can also be shared with the +DNS server if the schema proposed above is combined with the dhcpHost +structural object class. + +
Conclusion
+ +The PowerDNS implementation seem to be very flexible when it come +to which LDAP schemas to use. While its "tree" mode is rigid when it +come to the the LDAP structure, the "strict" mode is very flexible, +allowing DNS objects to be stored anywhere under the base cn specified +in the configuration.
+ +The DHCP implementation on the other hand is very inflexible, both +regarding which LDAP schemas to use and which LDAP structure to use. +I guess one could implement ones own schema, as long as the +objectclasses and attributes have the names used, but this do not +really help when the DHCP subtree need to have a fairly fixed +structure.
+ +Based on the observed behaviour, I suspect a LDAP structure like +this might work for Debian Edu:
+ ++ ++ou=services + cn=machine-info (dhcpService) - dhcpServiceDN points here + cn=dhcp (dhcpServer) + cn=dhcp-internal (dhcpSharedNetwork/dhcpOptions) + cn=10.0.2.0 (dhcpSubnet) + cn=group1 (dhcpGroup/dhcpOptions) + cn=dhcp-thinclients (dhcpSharedNetwork/dhcpOptions) + cn=192.168.0.0 (dhcpSubnet) + cn=group1 (dhcpGroup/dhcpOptions) + ou=machines - PowerDNS base points here + cn=hostname (dhcpHost/domainrelatedobject/dnsDomainAux) +
This is not tested yet. If the DHCP server require the dhcpHost +entries to be in the dhcpGroup subtrees, the entries can be stored +there instead of a common machines subtree, and the PowerDNS base +would have to be moved one level up to the machine-info subtree.
+ +The combined object under the machines subtree would look something +like this:
+ ++ +One could even add the LTSP configuration associated with a given +machine, as long as the required attributes are available in a +auxiliary object class. + ++dn: dc=hostname,ou=machines,cn=machine-info,dc=skole,dc=skolelinux,dc=no +dc: hostname +objectClass: top +objectClass: dhcpHost +objectclass: domainrelatedobject +objectclass: dnsDomainAux +associateddomain: hostname.intern +arecord: 10.11.12.13 +dhcpHWAddress: ethernet 00:00:00:00:00:00 +dhcpStatements: fixed-address hostname.intern +