I assume most of the readers are familiar with sudo. If not, sudo is a utility that runs on most of flavors of Unix, including Linux, and allows the user to elevate his privileges and run a particular program, even a login shell, as another user. Most of the time, the "another user" would be root and sudo would be used to get root privileges without knowing the root password. To learn more about sudo, visit its homepage and read the documentation
The later sections of the article are also assuming that the reader is familiar with LDAP, in particular adding entries to a directory.
In a single-machine environment, such as a personal laptop, the easiest way to configure sudo is to edit the /etc/sudoers file, preferably using a tool that double-checks the syntax, such as visudo.
Obviously, in a big corporate environment, the administrator faces a problem - how to distribute the file to all the machines he administers? One possible solution is to use tools such as puppet and directly copy the /etc/sudoers file. The other solution, which I will be focusing on in the rest of this article, is to store the rules in a centralized database, in particular LDAP.
Sudo itself has built-in support for processing rules stored in LDAP. Because the data is centralized, the administrator does not have to worry about distributing anything. He just needs to enter the rules into the LDAP server and all the clients, provided they are correctly configured, will be able to use them. There is another problem, though. Now that the data is stored on a server accessible over the network, what happens when the network is down, either because the server is down or simply because the user uses a laptop that is disconnected from the network?
Our solution is to cache the data retrieved from the central server on the client machine. We have developed a new SSSD service that caches the sudo rules much like SSSD is able to cache information about users including their credentials. Instead of sudo contacting the LDAP server directly, sudo queries SSSD. In this scenario, the SSSD acts as kind of a proxy between sudo and the LDAP server - the sudo utility has no idea whether the results came from the server itself or the on-disk cache.
There are several benefits to this approach, the most notable being the offline support and better performance. In a little more detail:
- offline support - the on-disk cache SSSD provides means that the sudo rules that were previously retrieved from the central server are available even if the client machine is not connected to the network or the server that contains the sudo rules is down.
- better performance - each invocation of sudo translates into one or more requests to the LDAP server over the network which might be slow and combined with other client requests affect the performance and load of the server itself. Consider a simple scenario where a user that is allowed to run some commands as root would like to edit a configuration file for a random service without knowing where exactly the file is. He might want to run sudo ls several times, then sudo vim some-service.conf and finally sudo service some-service restart. When sudo is configured to use SSSD as the information source, only the first request contacts the server by default and the successive requests are served from the cache for a configurable period of time to improve performance and reduce load. Another performance improvement is that the SSSD only keeps a single connection to the LDAP server open at a time. In comparison, multiple sudo users with the native LDAP back end would trigger multiple LDAP connections.
- unified configuration - instead of configuring the SSSD to perform account lookups and then configuring /etc/ldap.conf to perform sudo rules lookups, the user only configures one client piece - the SSSD. The SSSD also provides several advanced features that might not be available in other LDAP client packages, such as the support for server discovery using DNS SRV requests or advanced server fail over, which lets the admin define several servers that are tried in descending order of preference and then stick to the working server
- back end abstraction - while most of this article talks about LDAP, it would in theory be possible to store sudoers in another form of database
A hands-on exampleIn our model example, we are going to create two groups - readers and writers. Readers must be able to read and inspect all config files, writers must also be able to edit them. Our goal is to store the entries in LDAP so that they are centralized and access them using the SSSD to leverage caching and allow offline access. To simplify the matter, we are going to allow executing the commands on all hosts in the enterprise. A prerequisite to this example is a running LDAP server, such as OpenLDAP or 389 Directory Server. In the rest of this example I will be using the base DN of dc=example,dc=com.
I'm going to start by configuring sudo to use its native LDAP lookup capability. In the next section, we will be migrating the setup to SSSD.
The rules are referring two group stored in LDAP - I will skip adding the users and the groups, because this step might depend on the layout and schema your directory server uses. Depending on your directory server, you might also want to add the required SUDO schema. The Schema files for some of the most popular directory servers are part of the sudo distribution and are located in /usr/share/doc/sudo-$version/schema.* on my Fedora machine.
Below are the corresponding LDAP entries. Use a utility such as ldapadd to add them into your server. The first entry is simply a container the rules are stored in. The native sudo lookup mechanism uses a hardcoded container name ou=SUDOers. SSSD allows the user to configure a custom search base.
The next two objects are the two rules themselves. The readers_rule is referencing a group called readers with its sudoUser attribute. The sudoCommand attribute contains the command that we are allowing to be run, which is the "less" pager in particular.
The second object is very similar, just the group name and the command name are different.
The next step is to configure sudo to fetch user data from LDAP. This example assumes that you are already using the SSSD to retreive user and group data and will be only using the built in sudoers LDAP support to fetch sudo rules. First, you need to specify the LDAP server and sudoers search base in the /etc/ldap.conf config file:
See the sudoers.ldap(5) manual page for more options.
With the rule database populated, we can configure sudo to start using them now. Sudo uses the configuration file /etc/nsswitch.conf to specify the data sources, in particular it uses the "sudoers" line. That said, the glibc does not provide a sudoers map, such as it does for passwd or netgroups. If the directive is not specified, it defaults to "files", that is, only read sudo rules from the /etc/sudoers file.
And then configure the sudo utility itself to connect to LDAP for sudoers information:
sudoers: files ldap
Now simply log in as user who belongs to either readers or writers group - you can type id or groups to check group memberships for a user. And that's it, you should be able to list the commands the user is allowed to run with sudo -l and also execute them.
This setup obviously does the job but comes at the costs mentioned in the previous part of the article - every sudo command queries the LDAP server which might be slow. Also, if the network is unreachable for any reason, you're out of luck, which might be an important factor if the administrator is trying to fix network problems and his sudo data are stored in an LDAP server.
How to migrate to SSSDThis section will show you how to set up the SSSD as a proxy for storing sudoers. A prerequisite is a sudo binary with sss plugin support (sudo-1.8.1p2 or later). As of this writing, only the Fedora version of sudo contains the plugin, although the support should land in the sudo upstream soon.
In case you are already using the SSSD for user and group lookups, the configuration will be extremely easy:
- Create a new [sudo] section in the /etc/sssd/sssd.conf config file. You can leave it empty or fine-tune it with sudo specific configuration options. See man sssd.conf for a (currently quite short) list of available options:
- In the [sssd] section of the /etc/sssd/sssd.conf file, extend the services directive to also include sudo. If services originally included nss, pam which is the default, it would look like this:
services = nss,pam,sudo
- If your sudo rules are stored outside the ldap_search_base, you also need to set the ldap_sudo_search_base parameter to point to the LDAP subtree that contains the sudo rules.
ldap_sudo_search_base = ou=SUDOers,dc=example,dc=com
- The last step is to tell sudo to contact the SSSD for sudoers rules list. This is done in the /etc/nsswitch.conf config file:
sudoers: files sss
Whether to leave files in or not depends on your local configuration, but it might be prudent to retain the same order as the passwd and group NSS databases.
- Restart the SSSD.
service sssd restart
Sudo will now fetch data via the SSSD. You should be able to see increased performance, especially when multiple sudo commands are used. Sudo will also be able to answer requests from the central directory even if network was unreachable or the LDAP server was down.
The SSSD only stores the rules that were explicitly requested using the sudo utility. If you need to download all the rules, for example to protect against the situation where the network is down but you need to act as a user who never used sudo before, you can also use the "periodical download" feature. See the ldap_sudo_refresh_enabled and ldap_sudo_refresh_timeout options of sssd-ldap(5) manual page to learn more about this feature.
ConclusionThis article showed the benefits of using the sudo service of SSSD to fetch sudoers rules on behalf of sudo. There is not much more configuration right now - which is a good thing, because the sudo/SSSD integration should just run well out of the box.
That said, we are still targeting several improvements, mainly in the field of multi domain support.
Please also note that the feature is quite fresh, so there might be bugs here and there. We would very much appreciate bug reports, RFEs or general comments.