Access your remote SUDO rules offline with SSSD
jhrozek
This blog post is intended as both advertisement and documentation for a nice feature of SSSD 1.8 and later - integration with the sudo utility. It is also a featured Fedora 17 Feature.

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
Now that we know what we can accomplish with sudo and SSSD integrated, let's show a more practical example.

A hands-on example

In 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.

dn: ou=SUDOers,dc=example,dc=com
objectClass: top
objectClass: nsContainer
ou: SUDOers


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.

dn: cn=readers_rule,ou=SUDOers,dc=example,dc=com
objectClass: top
objectClass: sudoRole
cn: readers_rule
sudoUser: %readers
sudoHost: ALL
sudoCommand: /usr/bin/less


The second object is very similar, just the group name and the command name are different.

dn: cn=writers_rule,ou=SUDOers,dc=example,dc=com
objectClass: top
objectClass: sudoRole
cn: writers_rule
sudoUser: %writers
sudoHost: ALL
sudoCommand: /usr/bin/vim


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:

uri ldap://ldap.example.com
sudoers_base ou=SUDOers,dc=example,dc=com


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 SSSD

This 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:

  1. 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:

    [sudo]
  2. 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

  3. 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

  4. 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.

  5. 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.

Conclusion

This 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.
Tags: , ,

Analysing the SSSD source code with clang
jhrozek
The bottom line is that the static analyser that comes with LLVM's clang is awesome and you really should be using it. (I'm certainly not the first one to say so.)

Recently, I ran the clang static analyser against SSSD code. The run showed up a number of bugs.

None of the bugs is critical, that is, no bufer overruns or crashes under normal circumstances, but it should be noted that SSSD code was checked using a different static analyser not very long ago. Some of the bugs are very important to get fixed, though, such as this one - if a Host Based Access Control Rule in a FreeIPA server was malformed, the value returned would indicated success parsing and evaluating the rule (not granting access, though).

Most of the bugs are pretty easy to fix. For instance, take a look at one of the two I fixed today via fedorahosted's github.
The code should speak for itself for the most part..the next couple of lines of the function just clean up and return whatever is in ret. Most of the bugs are very easy to fix, so if you would like to contribute to SSSD, just pick one of those assigned to "somebody" and send a patch.

The instructions on running clang with your favorite project follow and should be very similar for just about any autotools-driven package.


  1. yum install clang-analyzer

    • installs the static analyser

  2. export CC=/usr/bin/clang

    • sets clang as your compiler of choice

  3. scan-build -o clang make

    • perform build and scan it for errors. The output will be stored in the clang directory.



As you may have figured, the scan involves compiling your code with the clang compiler..which is not necessarily a bad thing as most packages are compiled with gcc most of the time and using a different compiler may show poor coding practice in your project.

MALLOC_PERTURB_ helps find real bugs
jhrozek
I admit I had no idea about the existence of MALLOC_PERTURB_ until a recent post on fedora-devel list by Jim Meyering.

The feature is simple yet effective. It makes glibc return malloc(3)-ated memory initialized to the value of the environment variable MALLOC_PERTURB_ and clear free(3)-d memory to the bitwise inverse of MALLOC_PERTURB_'s value. This way you can easily spot places in your code which use memory before it is initialized or reuses freed memory.

I decided to give it a try and run the test suite of SSSD. Guess what - I got an instant crash. It turned out that we reused already freed memory in our program, but since we reused it almost instantly, the contents were still there and we never saw the bug during our testing.

I highly recommend using MALLOC_PERTURB_ during development of your software as it can help find bugs that would otherwise manifest themselves only sometimes making it very hard to debug (and ultimately fix!) them.

For more information, refer to the thread on fedora-devel or read some more on Ulrich Drepper's journal.

SSSD is worth a million
jhrozek
OK, a little childish, but anyway.. The project I've been working on for the past 7 months has now topped $1.000.000 in "Project Cost" estimate on Ohloh.

It is probably quite inaccurate for our project, though, as in the beginning of the development we used to import some libraries from Samba directly until they were ready as a separate package. Still, it shows that there's lot of progress going on in SSSD land as we're getting ready for the 1.0RC release. In the meantime, check out what we can already do.

nmon - distributing open source software done wrong
jhrozek

Recently, IBM have open sourced a Linux version of their ncurses-based performance monitor called nmon. Seeing the screeshots, I thought I might take a look..but I guess nmon is a nice example on how to not release an open source project.

Take a look:

  • there is no VCS
  • there are no tarballs. You have to download one huge source file and makefile separately
  • typing "make" results in building binary named nmon_power_rhel3
  • the makefile does not honor CFLAGS and since there is no configure, you have no way to tell what packages are you missing
  • there is a bunch of makefile targets in the form of:
    nmon_x86_64_opensuse11: $(FILE)
          cc -o nmon_x86_64_opensuse11 $(FILE) $(CFLAGS) $(LDFLAGS)
    nmon_x86_sles9: $(FILE)
          cc -o nmon_x86_sles9 $(FILE) $(CFLAGS) $(LDFLAGS)
    nmon_x86_rhel45: $(FILE)
          cc -o nmon_x86_rhel45 $(FILE) $(CFLAGS) $(LDFLAGS)
    nmon_x86_rhel52: $(FILE)
          cc -o nmon_x86_rhel52 $(FILE) $(CFLAGS) $(LDFLAGS)
  • makefile expects nmon.c but the file is actually called nmon-${version}.c, you have to manually rename it
  • bullet point No. 6 of their How to compile says "Yes, it's that easy"

FAIL.

I don't want to bash them for doing the right thing (kudos for opensourcing the tool!) but there's certainly room for improvement...and I think one can see the closed source past of the project, where the project was not distributed in source form but rather binaries only.

Tags:

The rumors of FreeIPA's death have been greatly exaggerated
jhrozek

I'm not sure where this rumor came from but it keeps popping up on various message boards, mailing lists and IRC..people would ask why Red Hat stopped supporting the FreeIPA project.

But it never did. Version 2 is still under heavy development (look at the volume of patches on freeipa-devel mailing list). That said, we had expected to have released v2 sooner and probably with more features, it just became evident that in order to release the project in time, we had to make changes. Dmitri explained them all nicely in his post on freeipa-users

To make it short, FreeIPA rocks on :-) Hang on on #freeipa at irc.freenode.net, join our mailing lists to watch the progress we make and provide feedback.

(Full disclosure: I am a Red Hat employee working on IPA full time)
Tags:

test post
jhrozek
Ignore this, please.

Apparently, I have a blog. Yay for me.

?

Log in