Even root's all-powerful access can be limited.  In some cases, it's worth preventing root from using the su command to assume the identity of another user on the system.  Although Linux audit maintains a user's original auid (audit ID) throughout the login session, preventing an unauthorized su can keep all logs intact with the correct identity. Coupled with other mechanisms, this can also be used to limit root's access to another user's home directory either locally or over NFS.

In Linux, PAM (pluggable authentication module) governs operating system access.  In particular, the file /etc/pam.d/su is responsible for authentication when su is executed.  This line is configured by default on most systems and allows root to execute su to assume any other user's identity:

            auth    sufficient      pam_rootok.so

The pam_rootok modules checks if the current user is root and if so, allows the su command to proceed.  Removing or commenting this line eliminates this behaviour and causes the su command to request the target user's password, even when the calling user is root.

Unfortunately, it's rarely that simple.  In many cases, root needs to be able to assume some identities, usually for generic system accounts as needed for troubleshooting.  To accomplish this first create a new group - we'll call it gensys in our example.  Any users for which root is permitted to impersonate are added to this group.  We then modify /etc/pam/su as follows:

            auth    [default=1 success=ignore] pam_succeed_if.so user ingroup gensys
            auth    sufficient      pam_rootok.so

The second field of a PAM configuration is the control. Most often, the value will be required, requisite, or sufficient, but in this case a less common but more granular control field is what's needed.  In the line we added, we are telling PAM what to do if the current module is successful (success=) and what to do in any other case (default =), i.e. a failure.  We call the pam_succeed_if module, kind of like an if-then statement for PAM. With the ingroup directive we evaluate if the target user is a member of the group gensys.

The module will succeed if the target user is in group gensys. When that happens, PAM will ignore this line and move on to the next one, which we know will let root successfully authenticate to any other user. However, if the target user is not in the gensys group, the module fails and the default action occurs.  In this case, the default action is 1, which PAM translates as "skip the next 1 line." The pam_rootok module is never loaded and root cannot assume the identity without a password.

Wait, but this is root we're talking about!

What's the point of all this, if root can just modify the PAM file, add the target user to a group, or change the user's password?  Of course anyone with root access can circumvent this control, but hopefully there are other mechanisms in place to detect and alert on changes to configuration files and unauthorized password changes. With secure configuration management, the changes can even be reverted instantly unless pre-approved.  The idea is to make this part a defense in depth strategy.

Going Enterprise

With centralized authentication and authorization, invoking PAM to assume the identity of other users - as well as the initial root login and any other support or maintenance tasks - can be tied back to change management and ticketing systems.  This ensures that all privileged work has been authorized, and can alert the Security team to investigate if any break-glass access is invoked.

For a full list of directives that can be used with pam_succeed_if, check the man pages for your Linux distribution.