The Non-complexity of /etc/nsswitch.conf
In most glibc-based operating systems, there’s a file /etc/nsswitch.conf that most people ignore, few people understand, but all people generally rely on. This file determines where the system finds things like host names, passwords, and protocol numbers. Does your company use LDAP? NIS? Plain files? The nsswitch file (it stands for “name services switch”) tells the system what service to use for each type of name lookup.
Here’s a snippet from a sample /etc/nsswitch.conf file:
passwd: files nis group: files nis hosts: files dns myhostname
In this example, user information (the passwd and group services) come first from “files” (like /etc/passwd or /etc/group), and if no entries are found there, a query to an NIS server (configured elsewhere) will be used. Host information first comes from /etc/hosts (files), then a DNS server (dns), and if neither of those work, at least a fallback of “myhostname” so that the local machine has some name.
The non-complexity comes in the “and if that doesn’t work” rule. When multiple services are listed, they’re tried in order, and a sevice either succeeds or fails. If it fails, the next is tried, etc. There’s a way to check for a few other cases (entry not found, or service temporarily unavailable) but the only thing you can do based on those is either try the next service, or don’t.
This simplicity has already led to one drawback, which is the handling of a user’s groups when there are both local groups and global (LDAP for example) groups. You wouldn’t want to have to choose between the two, you’d rather be allowed into the union of the two sets of groups. The nsswitch.conf syntax has a special case for that:
groups: files [SUCCESS=merge] ldap
Normally, a successful lookup would terminate the lookup and return a value. This special case says that even if the “files” lookup worked, try the “ldap” service also and merge the two lists of groups together. Another special case has come up recently, with systemd providing some services for the local machine. The problem here is “local machine” – it doesn’t provide global services, but the nsswitch syntax doesn’t allow for “delegation”. If the systemd service doesn’t find a record, is that “not found” authoritative?
And what if you wanted different services for different domains? Currently, your only option is to configure a local DNS server that has all the logic for domain delegation, and refer to that in nsswitch.conf. That only works if the DNS server is running, which may not be the case when the machine is first booting, and may not be easy to configure when you change networks (wifi? vpn?).
So what’s the point of this article? I’ve been contemplating the non-complexity of this file, and wondering what its future might contain. What if you could select services based on a pattern match of the search string? What if it could test for outside conditions like time of day, or VPNs? What if your corporate security rules required a more deterministic failure mode? I’m not suggesting nsswitch.conf become some full programming language (nsswitch.py anyone? 😉 but if it had some decision-making syntax beyond what it already has, what would it look like? What kinds of problems would it solve? Do you have any problems that could be solved by a more flexible nsswitch.conf? If so, share them in the comments below!