How to Log All Sudo Commands with SUDO_USER Context in Linux Production Environments


8 views

In enterprise Linux environments, tracking command execution is critical for security audits and compliance. The common practice of admins using sudo -i creates a logging gap where commands run as root lose the original user context. While the SUDO_USER environment variable exists, most logging solutions don't capture this metadata.

We'll implement a comprehensive logging solution that captures:

1. Original username (SUDO_USER)
2. Effective username (who actually executed the command)
3. Full command with arguments
4. Precise timestamp
5. Hostname context

Method 1: Enhanced auditd Configuration

Modify /etc/audit/audit.rules:

-a exit,always -F arch=b64 -F euid=0 -S execve -k ROOT_CMDS
-a exit,always -F arch=b32 -F euid=0 -S execve -k ROOT_CMDS

Then create a custom format in /etc/audit/auditd.conf:

log_format = ENHANCED
name_format = HOSTNAME

Method 2: Bash History Injection

Add to /etc/bash.bashrc or user profiles:

function log_command {
    local real_user=$(whoami)
    local sudo_user=${SUDO_USER:-$real_user}
    logger -p local6.notice -t "CMD_AUDIT" "[$real_user|$sudo_user] $BASH_COMMAND"
}
trap log_command DEBUG

Method 3: Sudoers Logging Enhancement

Add to /etc/sudoers:

Defaults log_host, log_year, logfile="/var/log/sudo.log"
Defaults log_input, log_output
Defaults iolog_dir="/var/log/sudo-io/%{user}"

For centralized logging, configure rsyslog to forward logs:

template(name="CmdAudit" type="string"
         string="%timegenerated% %HOSTNAME% [%syslogtag%] %msg%\n")

if $syslogtag == 'CMD_AUDIT' then {
    action(type="omfile" file="/var/log/cmd_audit.log" template="CmdAudit")
    stop
}

For containerized environments, add this to your Dockerfile:

RUN echo 'export PROMPT_COMMAND=\'history -a >(tee -a ~/.bash_history | logger -t "$(whoami)[$SUDO_USER]")'\'' >> /etc/profile

Example log output would appear as:

Jan 19 22:28:46 prod-server01 CMD_AUDIT: [root|ksoviero] yum install random-pkg

In enterprise Linux environments where admins routinely use sudo -i to gain root access, traditional logging solutions often fail to capture the crucial link between elevated privileges and the original user. The SUDO_USER environment variable holds this relationship, but most logging mechanisms don't preserve it.

The most reliable approach combines bash history enhancements with syslog forwarding. Create a custom bashrc snippet for root:

# /root/.bashrc addition
function log_command {
    if [ -n "$SUDO_USER" ]; then
        logger -p local6.notice -t SUDO_CMDS "[$(whoami)|$SUDO_USER] $BASH_COMMAND"
    else
        logger -p local6.notice -t DIRECT_CMDS "[$(whoami)] $BASH_COMMAND"
    fi
}
trap log_command DEBUG

Configure rsyslog to handle these messages by adding to /etc/rsyslog.d/command-audit.conf:

# Command audit rules
local6.notice /var/log/command-audit.log
& stop

For enterprise-grade auditing, combine with auditd rules:

# /etc/audit/rules.d/command-logging.rules
-a always,exit -F arch=b64 -F euid=0 -S execve -k root_cmds
-a always,exit -F arch=b32 -F euid=0 -S execve -k root_cmds

After implementation, test with:

sudo -i
echo "Test command"
exit
tail -n 10 /var/log/command-audit.log

Expected output should resemble:

Jan 19 22:28:46 hostname SUDO_CMDS: [root|username] echo "Test command"

For high-traffic environments, consider:

  • Log rotation policies
  • Centralized log collection
  • Rate limiting to prevent DoS
  • Filesystem partitioning for audit logs

If you prefer using Snoopy, modify the source to include SUDO_USER:

// In snoopy.c, modify the output format
if (getenv("SUDO_USER") != NULL) {
    snprintf(message, sizeof(message), "[%s|%s] %s",
        username, getenv("SUDO_USER"), cmd);
} else {
    snprintf(message, sizeof(message), "[%s] %s",
        username, cmd);
}