This lab trains the muscle memory of safe service-account creation and identity-policy enforcement. Every command in this lab has a production counterpart, and every audit has a finding.
Objective
By the end of this lab, you can create a hardened service account, set a password aging policy, add an existing user to a supplementary group safely, and audit the host for common identity misconfigurations.
Architecture
flowchart LR
CR["useradd / usermod<br/>account creation"]
AG["chage<br/>password aging"]
AUDIT["awk / getent<br/>identity audit"]
HOMES["find<br/>home-dir audit"]
LOCK["passwd -l<br/>lock the password"]
Requirements
- A Linux host (Ubuntu 24.04 LTS or Debian 12 preferred).
- Root or sudo access.
- An existing test user you can modify safely (do not use root or any account you cannot recreate).
Scenario
Your team is preparing a new application deployment. You need to:
- Create a
myappservice account for the application daemon. - Set the
myappaccount’s password aging policy. - Add an existing user (
alice) to adockersupplementary group to allow her to use Docker without sudo. - Audit the host for identity drift.
Tasks
Task 1: Create the service account
sudo useradd -r -m -d /opt/myapp -s /usr/sbin/nologin -c 'MyApp service account' myapp
sudo passwd -l myapp
getent passwd myapp
Verify:
- UID is below 1000 (because of
-r). - Home directory exists at
/opt/myapp. - Login shell is
/usr/sbin/nologin. - Password is locked (
!prefix in /etc/shadow).
Task 2: Set the aging policy
sudo chage -M 90 -m 7 -W 14 myapp
sudo chage -l myapp
Verify the aging fields are set. Note: service accounts typically
should not have passwords that expire in the traditional sense, but
aging fields are still useful for EXPIRED account handling if the
account is ever unlocked.
Task 3: Safely add alice to a supplementary group
Before:
id alice
groups alice
Append to the docker group (not replace):
sudo usermod -aG docker alice
id alice
Verify alice retains her existing memberships AND has docker.
Task 4: Audit UID 0 accounts
awk -F: '$3 == 0 { print $1 }' /etc/passwd
The expected output is exactly one line: root. Any other line is
a finding.
Task 5: Audit system account shells
awk -F: '$3 < 1000 && $3 > 0 && $7 !~ /nologin/ { print $1, $7 }' /etc/passwd
The output should be empty or contain only the special-cased
accounts (sync, halt, shutdown). Anything else is a finding.
Task 6: Audit world-readable home directories
sudo find /home -type d -perm -o+r 2>/dev/null
ls -ld /home/*/
Each home directory should be drwx------ (0700) or
drwxr-x--- (0750). World-readable home directories leak the
contents of .ssh/, .bash_history, and similar sensitive files.
Task 7: Audit the new account
getent passwd myapp
getent shadow myapp
ls -ld /opt/myapp
Verify the account is correctly hardened.
Validation
The lab is complete when:
myappexists, UID below 1000, locked password, no interactive shell.myapphas aging fields set to 90 max / 7 min / 14 warn.aliceretains her original memberships and hasdockeradded.- The UID 0 audit returns only
root. - The system-account-shell audit returns no surprises.
- No world-readable home directories exist (or all findings are documented).
Expected outcome
A hardened service account ready for an application deployment, and evidence that the host’s identity database is in a known-good state.
Troubleshooting
- “useradd: UID 999 is already in use” — pick a different UID in the system range or check for stale packages.
- alice lost her memberships in Task 3 —
usermod -aGwas not used. Restore withusermod -aG <list of groups> alicebased on the originalidoutput. - “chage: permission denied” — running as non-root. Use sudo.
myapphome directory missing —-mwas not passed. Remove the account withuserdel -r myappand recreate with-m.
Cleanup
Remove the test account:
sudo userdel -r myapp
Verify removal:
getent passwd myapp
ls /opt/myapp
The lab host should be in the same state as before the lab.
What you learned
You can now create production-grade service accounts, set aging policies without locking humans out, and audit the identity database for the most common production misconfigurations.