Privilege Separation & Security Validation

Overview

This document describes the zero-trust privilege separation model for Linux workstations integrated with Active Directory. The core principle:

"This computer is not to be trusted."

Domain users (researchers, end users) have no administrative privileges. System modifications require local administrator or InfoSec intervention.

Privilege Model

Role Example User Privileges sudo Access

Domain User

gabriel@inside.domusdigitalis.dev

Login, run applications, access authorized network resources

NO

Local Admin

evanusmodestus (local account)

Full system administration

YES

Root

root

Emergency break-glass access

N/A (is root)

The su vs su-l Distinction

Understanding the difference between su and su - is critical for PAM configuration.

Command Comparison

Command PAM Config Behavior

su username

/etc/pam.d/su

Switch user, keep current environment

su - username

/etc/pam.d/su-l

Switch user, login shell (fresh environment)

Why This Matters

# su (non-login) - inherits current shell environment
$ su gabriel
# Uses /etc/pam.d/su
# $HOME, $PATH, etc. may be inherited from original user

# su - (login shell) - simulates full login
$ su - gabriel
# Uses /etc/pam.d/su-l  <-- DIFFERENT FILE!
# Reads ~/.bash_profile, sets fresh $HOME, $PATH

Common Misconfiguration: Administrators often configure /etc/pam.d/su but forget /etc/pam.d/su-l. This causes su - to fail while su works, or vice versa.

PAM Configuration

Both files must include the SSSD authentication stack:

/etc/pam.d/su-l
#%PAM-1.0
auth            sufficient      pam_rootok.so
auth            include         system-auth
account         include         system-auth
session         include         system-auth
password        include         system-auth
/etc/pam.d/su
#%PAM-1.0
auth            sufficient      pam_rootok.so
auth            include         system-auth
account         include         system-auth
session         include         system-auth
password        include         system-auth

The pam_rootok.so line allows root to su to any user without password. The include system-auth pulls in the SSSD stack for AD authentication.

Sudoers Configuration

Zero-Trust Model

Domain users are explicitly denied sudo access:

/etc/sudoers.d/10-domain-users
# Zero-Trust: Domain users have NO sudo access
# Only local admins and designated AD groups can elevate

# Local administrator (break-glass)
evanusmodestus ALL=(ALL) ALL

# InfoSec team AD group (if applicable)
# %GRP-Linux-Admins@{domain} ALL=(ALL) ALL

# Explicitly deny all domain users
%domain\ users@{domain} ALL=(ALL) !ALL

Verification

Test that domain users cannot sudo:

# As domain user
$ su - gabriel@inside.domusdigitalis.dev
Password: ********

$ sudo whoami
[sudo] password for gabriel@inside.domusdigitalis.dev:
gabriel@inside.domusdigitalis.dev is not in the sudoers file.
This incident will be reported.    # <-- Expected behavior

Security Controls Validation

Validation Matrix

Control Validation Command Expected Actual (2026-01-22)

LUKS Encryption

lsblk -o NAME,FSTYPE,SIZE | grep crypt

All partitions encrypted

✓ cryptroot, cryptswap, crypthome

Host Firewall

sudo ufw status verbose

Status: active

✓ Active, deny incoming

Antivirus

systemctl status clamav-daemon

Active (running)

✓ Running, self-check every 600s

802.1X Auth

wpa_cli -i <iface> status

wpa_state=COMPLETED

✓ EAP-TLS SUCCESS

No sudo for domain users

sudo -l as domain user

"not in sudoers file"

✓ Confirmed

Full Validation Output

Domain User Perspective (gabriel)

[gabriel@inside.domusdigitalis.dev@modestus-p50 ~]$ echo "=== LUKS ===" && \
  lsblk -o NAME,FSTYPE,SIZE | grep -E "crypt|NAME"
=== LUKS ===
NAME          FSTYPE        SIZE
├─nvme0n1p3   crypto_LUKS   150G
│ └─cryptroot btrfs         150G
├─nvme0n1p4   crypto_LUKS    32G
│ └─cryptswap swap           32G
└─nvme0n1p5   crypto_LUKS   748G
  └─crypthome btrfs         748G

[gabriel@inside.domusdigitalis.dev@modestus-p50 ~]$ sudo ufw status
[sudo] password for gabriel@inside.domusdigitalis.dev:
gabriel@inside.domusdigitalis.dev is not in the sudoers file.  # <-- CORRECT!

[gabriel@inside.domusdigitalis.dev@modestus-p50 ~]$ systemctl status clamav-daemon --no-pager
● clamav-daemon.service - Clam AntiVirus userspace daemon
     Loaded: loaded (/usr/lib/systemd/system/clamav-daemon.service; enabled)
     Active: active (running) since Thu 2026-01-22 16:50:56 PST
   Main PID: 1370 (clamd)
     Memory: 1.1G

Administrator Perspective (evanusmodestus/root)

[root@modestus-p50 ~]# sudo ufw status verbose
Status: active
Logging: on (low)
Default: deny (incoming), allow (outgoing), disabled (routed)
New profiles: skip

To                         Action      From
--                         ------      ----
22                         ALLOW IN    Anywhere
22                         ALLOW IN    192.168.68.132
22 (v6)                    ALLOW IN    Anywhere (v6)

802.1X Authentication Status

$ wpa_cli -i enp0s31f6 status | grep -E "wpa_state|EAP|selectedMethod"
wpa_state=COMPLETED
EAP state=SUCCESS
selectedMethod=13 (EAP-TLS)
EAP TLS cipher=ECDHE-RSA-AES256-GCM-SHA384

Security Architecture Diagram

Zero-Trust Privilege Separation

Troubleshooting

su - fails but su works

Cause: /etc/pam.d/su-l missing or misconfigured.

# Check both files exist and have correct content
diff /etc/pam.d/su /etc/pam.d/su-l

# Both should include system-auth
grep "include.*system-auth" /etc/pam.d/su-l

Domain user can sudo (security issue!)

Cause: Missing deny rule or incorrect group mapping.

# Check sudoers
sudo visudo -c
sudo grep -r "domain" /etc/sudoers.d/

# Verify user's groups
id gabriel@inside.domusdigitalis.dev

PAM authentication fails silently

Cause: Leading whitespace in PAM config files (common with heredoc copy-paste).

# Check for hidden characters
cat /etc/pam.d/sssd-arch | od -c | head -5
# Should start: 0000000   a   u   t   h
# NOT:          0000000       a   u   t   h  (spaces!)

# Fix
sudo sed -i 's/^[[:space:]]*//' /etc/pam.d/sssd-arch