NIS to LDAP: Making the Leap
If it's time to trade in your aging NIS installation for LDAP, our roadmap will point out the potholes you can expect.
Considering a conversion from NIS to LDAP? It may be more difficult than you plan. NIS, designed by Sun Microsystems and sometimes called a Yellow Pages directory, is a mechanism to centrally manage machine configuration data. For many reasons, LDAP is a better alternative, but switching non-trivial configurations from NIS to LDAP isn't straightforward. This isn't an LDAP tutorial; assuming basic LDAP knowledge, we'll talk about some of the common issues encountered in an NIS conversion.
A NIS master can centrally manage e-mail aliases, users, passwords, netgroups, automounter maps and more. Clients "bind" to a NIS domain, and /etc/nsswitch.conf allows the clients to access the information. A file called securenets, which lists networks that are "secure" and therefore trusted, controls access to the domain's information. Anyone on those networks can connect to a NIS server. NIS+ was invented to introduce more security, but was widely shunned due to its completely redone and complex architecture.
So why don't we want to use NIS any more? It isn't very manageable, nor is it secure. Anyone on a client machine can run 'ypcat passwd' and get all users' password hashes in NIS. There's a special mode called c2secure that implements shadow files so that password hashes are hidden to all but the root user. This is great, but breaks many things. If a program doesn't have access to the password hashes, it can't authenticate users. For example, if you're using Apache, running as user www, and use PAM authentication, that can't work with c2security. Workarounds exist, but involve calling a setuid program to run as root and perform the authentication.
In LDAP, authentication of users and machine access is very secure. For machines, the LDAP client can be configured to need a certificate before it's allowed access. User authentication is done by binding to the LDAP server as the user, over SSL. If the bind succeeds, the user's password was good, and he is authenticated. The great news is that most applications support LDAP authentication mechanisms.
Manageability is the main reason to switch. In NIS, if you have multiple domains, every time a change is made to a file, the changes must propagate to each domain. This is done with Makefiles, and every time a change is needed, for example to a password file, it gets rebuilt in every domain, and then clients will soon see the changes. Adding new files to NIS means that you must engineer a method to replicate the file every time a change is made. It's a lot of work to maintain a changing NIS environment. Aside from creating sane configurations on the master server, you also have to worry about slave server propagation. LDAP replication is more efficient and reliable than NIS's map transfer mechanism.
In LDAP, changes are made by directly editing the database. If all clients are configured to use the same password information, then changes never need to "propogate," instead you can simply edit the entry and immediately affect all client machines.
Depending on the number of NIS clients, and your NIS domain structure, converting to LDAP may be troublesome. Many environments will have the following properties:
- Global user accounts (i.e. one password everywhere)
- Sets of machines that only some users can login to
- Groups of machines with "different" information, such as automounter maps
- Netgroups used to limit NFS shares and user access
If your environment is flat, the same configurations for all machines, then converting is simple. When you need to keep groups of machines, with similar information but with some variances, that's where LDAP is not easy. NIS wasn't easy either, unless you wanted to completely isolate domains and not share any information. The same problem exists in LDAP.
Some Scenarios to Consider
Say we have a Solaris and Linux mixed environment, where home directories are obviously going to be different. In NIS, we simply engineer the building of the auto.homedirs (or whatever you call it) map to generate different entries for the Linux domain's automounter maps, so that home directories are in different locations.
In LDAP we have a few way to go about this. The client can bind to a different place in the tree, so that its searches for information start in a Linux-centric location. To accomplish this, other information like People (password information) needs to exist in each sub tree as well. So we're back to having to engineer a way to manage duplicate information, and propagate it when changes occur. Alternatively, we could implement this Linux branch of the tree to use referrals for all "global" information.
An LDAP referral is pointer to another place, put simply. Referrals can be used to make this sort of LDAP design feasible: Linux automounter entries are unique, but People refers to a global one.
Another issue arises with netgroups and limiting access to certain machines. In Linux and Solaris, you can limit password entries by using a "+@netgroup" in the /etc/passwd or shadow file instead of just allowing everyone to exist with a "+" at the end of the file. OpenLDAP, by default, does not have a notion of netgroups, but the Sun LDAP server does have an object type: nisNetgroupTriple. If netgroups are used, you'll either be importing foreign schemas into OpenLDAP or you'll need to run Sun's LDAP server. The Fedora Directory Server is based on Sun's, so that's another viable option.
The LDAP client configuration file controls essentially everything. You will define the LDAP server, where the base DN is located, SSL information, and optionally search filters. In the NIS example we gave, separate domains had different password files, built (trimmed) from a global password file of all users. Concocting this sort of environment isn't straightforward in LDAP, if you want to avoid duplicating information.
This line in ldap_client_file (Solaris) or ldap.conf (Linux) specifies how nsswitch passwd entries are found:
NS_LDAP_SERVICE_SEARCH_DESC= passwd: ou=People,dc=example,dc=com?one
We can specify that ou=People is actually someplace different, if we were duplicating information or had completely separate People in each container. But to use a global People entry, allowing one password for all types of machines, something else has to happen. People frequently ask how something like this is possible, and the answer is actually simple: add an attribute to each Person, and check that attribute as a search filter in the client configuration.
An example is that different departments in a company or university have Unix machines, and cross-departmental logins aren't allowed. Using a university example, let's say we want CS users to login to a group of machines, but not ECE users. In the People attribute, the schema can be extended to have a 'dept' field. The LDAP client file's service search description uses a search filter to check that the user has this attribute:
If the user who attempts to login doesn't have the attribute dept=CS, they won't exist, since the search would fail.
These are a few of the major high-level issues I've personally experienced with a NIS to LDAP conversion. All in all, the work put into LDAP pays off tremendously. Linux clients are happier, it's easier to manage, and it's secure. LDAP authentication is possible directly from PHP, Ruby, Perl and pretty much all other languages and applications in existence. The LDAP learning curve shouldn't be a deterrent.