# Password Policies and User Privileges

> Chapter 8 of the Courseiva LF-LFCS curriculum — https://courseiva.com/learn/lf-lfcs/password-policies-and-user-privileges

**Official objective:** 3.2 — Configure password aging and manage user privileges

## Introduction

The Linux Foundation Certified System Administrator exam objective 3.2—'Configure password aging and manage user privileges'—solves a critical security problem: how to stop attackers from using stolen or forgotten passwords, and how to give people exactly the right level of system access without giving them too much. When you manage a Linux server, you are responsible for making sure every user’s password changes regularly and that no one has permissions they don’t need, which directly prevents data breaches and accidental damage.

## The Night Security Guard Analogy

A night security guard at a gated community is the central figure. Their job is to enforce the community’s rules for who gets in, how often keys must be changed, and what privileges residents have. The property manager sets a policy: every resident must change their gate code every 90 days, otherwise their key fob expires. This is like password aging. The guard checks the fob’s expiration date; if it’s overdue, the resident must visit the office to get a new code before entering. Similarly, a Linux system forces users to update passwords after a set period to prevent stale credentials from being stolen. 

 Now, consider privileges. Some residents have master keys that open the pool, gym, and parking garage. Others only have a key to their front door. The guard maintains a log: who has which key and for how long. If a contractor finishes a renovation job, the guard revokes their temporary access immediately. This maps to user privilege management in Linux. The root user (the property manager) grants specific permissions—like reading files, running programs, or changing system settings—using tools like `chage` for password aging and `usermod` or `groupmod` for group memberships. The guard doesn’t just let everyone in; they enforce the policies set by the manager. On a Linux server, the system administrator (the guard) configures password expiration intervals, minimum days between changes, and warning periods, then assigns users to groups like `sudo` (which gives admin power) or `webdev` (which gives write access to a specific folder). The goal is the same: keep the community secure while letting authorised people do their jobs without hassle.

## Core explanation

Password aging is a set of rules that force users to change their passwords after a certain amount of time. On a Linux system, every user account has an entry in the `/etc/shadow` file, which stores the encrypted password and several date-related fields. The `chage` command (short for 'change age') lets an administrator view or modify these fields. The key parameters are: `-M` sets the maximum number of days a password is valid (e.g., `-M 90` means the password expires after 90 days), `-m` sets the minimum number of days before a user can change it again (to stop users from cycling back to the same password too fast), `-W` sets the number of days before expiry that a warning is shown, and `-I` sets the number of days after expiry that the account is locked if the password is not changed. For example, `sudo chage -M 90 -m 7 -W 14 -I 30 username` forces the user to change their password at least every 90 days, wait 7 days before changing it again, see a warning 14 days before it expires, and get locked out after 30 days of inactivity. This replaces the old method of doing nothing—leaving passwords unchanged for years, which is a huge security risk because leaked passwords from other sites can be used to break in. 

 When you run `chage -l username`, you see the current aging information: Last password change, Password expires, Password inactive, Account expires, and Minimum number of days between password changes. Aging policies are often set system-wide in `/etc/login.defs` with variables like `PASS_MAX_DAYS`, `PASS_MIN_DAYS`, and `PASS_WARN_AGE`. These defaults apply to all new users unless overridden per user. For existing users, you must run `chage` or edit their shadow entry manually. 

 Now, user privileges. Every action on a Linux system is controlled by permissions. Files and directories have three permission sets: owner (u), group (g), and others (o). These are read (r=4), write (w=2), and execute (x=1). For example, `-rwxr-xr--` means the owner can read, write, and execute; the group can read and execute; everyone else can only read. This is called discretionary access control (DAC) because the file owner decides who gets access. But managing privileges for dozens of users on a server requires more control. 

 The `sudo` command lets authorised users run commands as another user (usually root). Sudo privileges are defined in the `/etc/sudoers` file, which should be edited with `visudo` to prevent syntax errors. A typical entry is `username ALL=(ALL:ALL) ALL`, which gives that user full root access. More granular entries like `username ALL=(ALL:ALL) /usr/bin/apt, /usr/bin/systemctl` only allow specific commands. Groups can be used: `%admin ALL=(ALL:ALL) ALL` gives all members of the admin group sudo access. 

 User groups simplify permission management. Instead of setting privileges for each user individually, you create a group (e.g., `webdev`), add users to it with `usermod -aG groupname username`, then set file permissions for the group. For example, `chown :webdev /var/www` changes the group ownership of the directory, and `chmod 2775 /var/www` gives the group write access (the 2 sets the setgid bit, so new files in that directory inherit the group). This approach scales: when a user leaves, you remove them from the group instead of hunting down every file they owned. 

 Password aging and privilege management together form the basis of system hardening. Without aging, a stolen password gives indefinite access. Without privilege control, a compromised user can delete critical files or install malware. The LFCS exam tests your ability to set these policies using command-line tools like `chage`, `usermod`, `groupadd`, `gpasswd`, and the `sudoers` configuration.

## Real-world context

You are the sole IT administrator for a small tech startup with 50 employees. The company uses a single Linux server to host its internal web application, customer database, and source code repository. Your manager asks you to 'secure the system' because a competitor recently had a data breach from an old password. Here is what you actually do, step by step. 

 First, you audit current user accounts. You run `cat /etc/passwd | grep /home` to list real users, then `chage -l username` for each one. You discover that most employees have never changed their passwords—some accounts are two years old. The CEO’s password is set to never expire (chage shows `Password expires : never`). You run `sudo chage -M 90 -m 7 -W 14 -I 30 *`? No—that wildcard doesn't work. Instead, you write a small loop script or use a for loop in bash: `for user in $(ls /home); do sudo chage -M 90 -m 7 -W 14 -I 30 $user; done`. This ensures everyone must change their password within 90 days, with a 7-day minimum between changes. 

 Next, you set system-wide defaults by editing `/etc/login.defs`. You change PASS_MAX_DAYS to 90, PASS_MIN_DAYS to 7, and PASS_WARN_AGE to 14. Adding `ENCRYPT_METHOD SHA512` ensures passwords are hashed securely (SHA-512 is a one-way cryptographic function). You test the policy by creating a new user: `sudo useradd -m -s /bin/bash testuser && sudo passwd testuser`. Then `chage -l testuser` shows the defaults applied. 

 Now for privileges. The web application team needs write access to `/var/www/html` and the database dump directory `/backups/db`. You create a group called `webdev`: `sudo groupadd webdev`. Then you add the five developers: `sudo usermod -aG webdev alice`, `sudo usermod -aG webdev bob`, and so on. You set the directory permissions: `sudo chown -R root:webdev /var/www/html` and `sudo chmod -R 2775 /var/www/html`. The 2 sets the setgid bit so new files inherit the group. For backups, you do the same with `/backups/db`. 

 The junior sysadmin needs to restart the web server and view logs but should not have full root. You add a sudoers entry: `%webdev ALL=(ALL:ALL) /usr/bin/systemctl restart apache2, /usr/bin/journalctl`—this lets any member of webdev run only these two commands as root. You use `visudo` to edit safely. You also set up a `sudo` log via `Defaults logfile=/var/log/sudo.log` in `/etc/sudoers` so you can track who ran which command. 

 Finally, you automate user expiry for contractors. You create a user for a freelancer with an account expiry: `sudo useradd -e 2025-12-31 -m freelancer`. The `-e` date sets the account to expire on that day. After the project ends, the account locks automatically. You also set `sudo chage -E 2025-12-31 freelancer` as a backup. 

 This whole process—auditing, setting password aging, creating groups, assigning privileges, and automating expiry—is exactly what a real IT professional does. It prevents unauthorised access, contains damage if an account is compromised, and simplifies audits because you can show clear policies and logs. The LFCS exam expects you to know these exact commands and their options.

## Exam focus

The LFCS exam tests password aging and user privileges in several distinct ways. Expect multiple-choice questions where you must choose the correct `chage` option or the correct `/etc/sudoers` syntax. They love to set traps with similar-looking flags. For example, `-M` (maximum days) vs `-m` (minimum days) is a common confusion. Another trap: `chage -l` lists current settings, but the exam might ask you to interpret the output to find when a password expires. 

 Key topics that appear regularly: 
- `chage` command flags: `-M` (max days), `-m` (min days), `-W` (warning days), `-I` (inactive days), `-E` (account expiry date), `-l` (list current values). 
- `/etc/shadow` format: fields like `last_change`, `min_days`, `max_days`, `warn_days`, `inactive_days`, `expire_date`. The exam might show a shadow line and ask which field corresponds to, say, the maximum password age. 
- `/etc/login.defs` defaults: `PASS_MAX_DAYS`, `PASS_MIN_DAYS`, `PASS_WARN_AGE`. 
- `/etc/sudoers` rules: user/group specification, host aliases, command lists. Common syntax: `username host=(runas:runas_group) commands`. The trap is missing the `%` for groups or forgetting the comma between commands. 
- Group management commands: `groupadd`, `groupmod`, `groupdel`, `gpasswd`, `usermod -aG` (append to group—the `-a` flag is crucial because without it, the user is removed from all other groups). 
- File permission concepts: `chmod`, `chown`, setgid bit (2775), and the difference between owner, group, and others. The exam often asks how to grant group write access without changing other permissions. 
- Account expiry with `useradd -e` or `usermod -e` or `chage -E`. The date must be in YYYY-MM-DD format. 

 Traps to watch for: 
- The `-a` flag in `usermod -aG`. If you write `usermod -G webdev alice` without `-a`, Alice will be removed from all other groups. This is a classic gotcha. 
- In `/etc/sudoers`, the order of entries matters—the last match wins, so if you have both `%admin ALL=(ALL:ALL) ALL` and `alice ALL=(ALL:ALL) /usr/bin/cat`, Alice could still run anything because the group rule comes after. The exam might present two rules and ask what command Alice can run. 
- Password aging defaults from `/etc/login.defs` apply only to new users, not existing ones. The exam might ask how to apply a global policy to existing users—the answer is to use a loop with `chage`. 
- The difference between account lock (via `passwd -l` or `usermod -L`) and password expiry. A locked account cannot log in at all; an expired password only forces a change at next login. 
- The `ALL` keyword in sudoers can be ambiguous. `ALL=(ALL:ALL) ALL` means all hosts, all run-as users and groups, all commands. The exam might ask what `username ALL=(root) /usr/bin/top` means (only run as root, only the top command). 

 The best way to prepare is to practise these commands in a virtual machine. Run `chage -l` on your own user, create test users, set up groups, and edit sudoers (but be careful not to lock yourself out—always keep a root shell open). The exam expects you to know the exact flag syntax, not just the concept.

## Step by step

1. **Audit Current Users** — List all user accounts with `cat /etc/passwd` and check their password aging status using `chage -l username`. This identifies accounts with no expiration, stale passwords, or disabled aging. It is the baseline for deciding what policies to implement.
2. **Set System-Wide Defaults in /etc/login.defs** — Edit the `/etc/login.defs` file to set `PASS_MAX_DAYS 90`, `PASS_MIN_DAYS 7`, and `PASS_WARN_AGE 14`. These defaults will apply to all new users. This step ensures consistency and reduces future manual work.
3. **Apply Password Aging to Existing Users** — Use a loop like `for user in $(ls /home); do sudo chage -M 90 -m 7 -W 14 -I 30 $user; done` to enforce the same aging rules on all current accounts. Without this step, the defaults only affect new users, leaving existing accounts unprotected.
4. **Create Groups and Add Users** — Create groups with `sudo groupadd webdev` and add users with `sudo usermod -aG webdev username`. Using groups allows you to assign file permissions to the group rather than each individual user, simplifying management when people join or leave teams.
5. **Set File Permissions with setgid** — Change group ownership of directories (e.g., `sudo chown -R root:webdev /var/www/html`) and set permissions to 2775 (`sudo chmod -R 2775 /var/www/html`). The 2 sets the setgid bit so new files created inside inherit the group, ensuring consistent access.
6. **Configure Sudoers for Controlled Privilege Elevation** — Edit `/etc/sudoers` with `visudo` to grant specific commands to specific users or groups (e.g., `%webdev ALL=(ALL:ALL) /usr/bin/systemctl restart apache2`). This replaces giving full root access and limits the risk of accidental or malicious damage.
7. **Set Account Expiry for Temporary Users** — Use `sudo useradd -e YYYY-MM-DD -m username` or `sudo chage -E YYYY-MM-DD username` to automatically lock accounts after a project ends. This prevents forgotten accounts from becoming security holes.

## Comparisons

### chage -M (Maximum days) vs chage -m (Minimum days)

**chage -M (Maximum days):**
- Sets the maximum number of days before a password expires
- After this many days, the user is forced to change the password
- Default from /etc/login.defs is often 99999 (no expiry)

**chage -m (Minimum days):**
- Sets the minimum number of days before a user can change their password again
- Prevents users from cycling through old passwords quickly
- Default from /etc/login.defs is often 0 (no minimum)

### usermod -aG (Append to group) vs usermod -G (Set groups, without -a)

**usermod -aG (Append to group):**
- Adds the user to the specified group without affecting other group memberships
- Safe to use for adding a user to an additional group
- Syntax: usermod -aG groupname username

**usermod -G (Set groups, without -a):**
- Replaces the user's entire group membership list with only the specified groups
- Removes the user from any groups not listed
- Syntax: usermod -G group1,group2 username (dangerous if unintentional)

### Account expiry (chage -E) vs Password expiry (chage -M)

**Account expiry (chage -E):**
- Locks the entire account on a specific date regardless of password state
- Persists even if password is changed before the date
- Syntax: chage -E YYYY-MM-DD username

**Password expiry (chage -M):**
- Only forces a password change after the maximum days
- If password expires but account is not locked, user can still log in and change password
- Syntax: chage -M 90 username

### Direct file permissions (chmod ugo) vs Group-based permissions via setgid

**Direct file permissions (chmod ugo):**
- Grant access based on individual user ownership and world permissions
- Each file must be explicitly set for each user or group
- Does not propagate to new files created inside directories unless manually set

**Group-based permissions via setgid:**
- Define group ownership on a directory and use setgid so new files inherit the group
- Simplifies management for teams: add/remove users from one group
- Use chmod 2775 dir to enable setgid with group write

### Editing sudoers with visudo vs Editing sudoers with a text editor like vim

**Editing sudoers with visudo:**
- Locks the file to prevent concurrent edits
- Validates syntax before saving
- If syntax is wrong, offers to re-edit or abort

**Editing sudoers with a text editor like vim:**
- No file locking—risk of corrupting the file if two people edit
- No syntax validation—a single error can break sudo entirely
- Not recommended; visudo is the only safe method

## Diagram

_Flowchart showing the relationships between an administrator, password aging settings, user accounts, groups, file permissions, and sudo access._

```mermaid
flowchart TD
    A[System Administrator] -->|sets defaults in| B[/etc/login.defs]
    A -->|applies per-user with| C[chage command]
    B -->|affects new users| D[User Accounts]
    C -->|affects existing users| D
    A -->|creates groups| E[groupadd]
    A -->|adds users to groups| F[usermod -aG]
    E -->|defines| G[Groups]
    F -->|populates| G
    G -->|owns files/directories| H[/var/www/html]
    A -->|sets sudo rules via| I[visudo edits /etc/sudoers]
    I -->|grants limited root| J[Sudo Access]
    J -->|allows running commands as| K[Root]
    D -->|has password aging| L[Password must change every 90 days]
    D -->|belongs to groups| G
    D -->|can use sudo if allowed| J
    K -->|manages system| A
```

## Common misconceptions

- **Misconception:** Password aging is only about setting an expiration date, and once the date passes, the user is locked out completely. **Reality:** Password aging sets multiple parameters: maximum days (expiry), minimum days before rechange, warning period before expiry, and inactive days after expiry before the account is disabled. A user can still log in after the password expires (they are forced to change it at login), but if the inactive days pass without a change, then the account becomes locked. (Beginners often see only the 'expiry date' field from tools like `chage` and assume it works like a credit card expiry rather than a soft deadline with a grace period.)
- **Misconception:** Editing `/etc/sudoers` directly with a text editor like vim is the standard method. **Reality:** You must use the `visudo` command, which locks the file against simultaneous edits and checks syntax before saving. A syntax error in sudoers can lock out all sudo access, so `visudo` is mandatory. (Many newcomers come from a Windows background where editing config files directly is common, and they don't know the risk of breaking sudo.)
- **Misconception:** Setting a password aging policy in `/etc/login.defs` immediately applies to all existing users. **Reality:** Changes to `/etc/login.defs` only affect new user accounts created after the change. To apply the policy to existing users, you must run `chage` commands individually or via a script/loop. (It is intuitive to think a configuration file change globally updates everything, but Linux often treats defaults as template settings for new objects only.)
- **Misconception:** Removing a user from a group (e.g., with `gpasswd -d`) automatically removes their access to files that belonged to that group. **Reality:** Removing a user from a group only prevents future access to files that require group membership. It does not change the ownership or group of existing files. The user may still access files if they have direct ownership or 'others' permissions. (People confuse group membership with file ownership. Group membership grants permission to access based on the file's group permission bits; it does not remove the file or change its ACL.)

## Key takeaways

- The `chage -M` flag sets the maximum number of days a password is valid before the user must change it.
- Always use `visudo` to edit the `/etc/sudoers` file to prevent syntax errors that could lock you out of root access.
- The `-a` flag with `usermod -aG` appends a user to a group without removing them from other groups; omitting `-a` replaces all group memberships.
- Password aging policies set in `/etc/login.defs` only apply to new users, not existing accounts.
- The `sudo` command allows authorised users to run commands as another user, typically root, with permissions defined in `/etc/sudoers`.
- Group-based permission management (using groups like `webdev`) scales better than assigning per-user permissions, especially on servers with many users.
- An expired password does not lock the account; the system only forces a password change at next login. Account lock occurs after the inactive period set with `-I` in `chage`.

## FAQ

**What is the difference between password expiry and account lock in Linux?**

Password expiry means the user must change their password at next login, but they can still log in. Account lock (via `passwd -l` or `usermod -L`) prevents login entirely, even with the correct password. Both are used together for security.

**How do I force a user to change their password on next login in Linux?**

Run `sudo chage -d 0 username`. Setting the last password change date to 0 (epoch) forces the user to change their password immediately upon next login.

**What does the '2' in file permission 2775 mean?**

The leading '2' sets the setgid bit. When set on a directory, new files and subdirectories created inside it inherit the group ownership of the directory, not the primary group of the creator.

**Can I use wildcards in chage to apply to all users at once?**

No, `chage` does not accept wildcards for usernames. You must use a for loop or a script to apply changes to multiple users, like `for user in alice bob charlie; do sudo chage -M 90 $user; done`.

**What happens if I edit /etc/sudoers directly and make a syntax error?**

A syntax error can break sudo, potentially locking you out of root access. Always use `visudo`, which validates syntax before saving and offers to re-edit if an error is found.

**How do I see what sudo commands a user can run?**

Run `sudo -lU username` as root or use `sudo -l` while logged in as that user to list permitted commands defined in `/etc/sudoers`.

**What is the /etc/shadow file and how is it related to password aging?**

`/etc/shadow` stores encrypted passwords and aging data (last change, min/max days, warn, inactive, expire). Each field corresponds to a column; `chage` reads and modifies these values.

## Check your understanding

1. **Which `chage` flag sets the maximum number of days a password is valid before the user must change it?**

   Answer: The `-M` flag (e.g., `chage -M 90 username`).

2. **What command should you always use to edit the `/etc/sudoers` file, and why?**

   Answer: `visudo`—it locks the file for editing and checks syntax before saving to prevent breaking sudo access.

3. **If you run `usermod -G webdev alice` (without `-a`), what happens to Alice's other group memberships?**

   Answer: Alice is removed from all groups except `webdev`, because `-G` without `-a` replaces her entire group list.

4. **What is the difference between setting `PASS_MAX_DAYS` in `/etc/login.defs` and using `chage -M` on an existing user?**

   Answer: `/etc/login.defs` only affects new users created after the change, while `chage -M` applies to the specific existing user immediately.

5. **A user's password has expired. Can they still log in?**

   Answer: Yes, they can log in but will be forced to change their password immediately. The account is not locked unless the inactive period (set with `chage -I`) has been exceeded.

---

Interactive version with quiz and diagrams: https://courseiva.com/learn/lf-lfcs/password-policies-and-user-privileges
