Least Privilege Practice
Practice the principle of least privilege in this hands-on lesson — step-by-step guidance, troubleshooting, and next steps in the Security foundations track.
Focus: practice the principle of least privilege
You've been handed admin credentials to a production database, and every deployment script runs as root. Sound familiar? That's the security equivalent of leaving your house keys under the mat — and telling everyone where they are. The principle of least privilege (PoLP) is the one security control that can stop a whole class of breaches before they start, and in this lesson you'll learn exactly how to practice it — from theory to hands-on code. We'll turn a vague best practice into something you can implement today, then point you to the next step in your Security foundations journey. Let's lock down those permissions.
The problem this lesson solves
Every day, teams get breached not because attackers are geniuses, but because far too many accounts hold far too much power. A single leaked application token with full root access can let an attacker drop a database, mine cryptocurrency, or pivot to your entire network. The pain is real: over-privileged access is the #1 enabler of data breaches. You might think, "We're a small team, nothing will happen," but attackers scan for open doors 24/7, and one overgranted permission is an open door.
The deeper problem is that permissions tend to accumulate. A developer asks for elevated rights to debug an issue, and nobody removes them after. A cron job gets sudo access for a one-off task and keeps it forever. Before long, you have dozens of accounts that can do far more than their job requires. Worse, those accounts are often shared and never audited. The result? An incident that should have been a minor blip becomes a catastrophe.
Core concept / mental model
Think of least privilege like the principle of a librarian's key ring. The librarian doesn't carry keys to every office in the building — just the ones they need: the front door, the book stacks, and maybe the supply closet. They don't have the key to the server room because that's not part of their job. If a thief steals the librarian's keys, they can only get into the library, not the whole building. That's the idea: give every user, program, and process only the permissions it needs to do its job — and nothing more.
In technical terms, least privilege means configuring access controls so that each subject (user, service account, or application) has the minimal set of privileges required to perform its function. It applies across the whole stack: operating system users, file permissions, database roles, cloud IAM policies, API keys, network rules, and even human roles.
A useful mental model is the need-to-know basis. Just as a spy only gets information relevant to their mission, a service account should only be able to read the tables it processes, and a human operator should only have write access to the environments they manage. The goal is to minimize the blast radius: if one account is compromised, the damage stays contained.
How it works step by step
Practicing least privilege isn't a single action; it's a continuous process. Here's a logical flow to follow:
- Inventory — List every user, service account, API key, and process in your system. You can't manage what you don't know.
- Define job functions — Write down exactly what each subject needs to do. For example, a web server needs to read static files, write to a log directory, and connect to a database — nothing more.
- Assign minimal permissions — Start with no permissions, then grant only what's needed. Use role-based access control (RBAC) or fine-grained IAM policies.
- Use time-limited or elevated access — When someone truly needs more power, grant it temporarily (e.g., a
sudosession for 10 minutes, or a time-bound cloud role). This is called just-in-time privilege. - Review and audit — Regularly check permissions. Remove stale accounts, revoke unused keys, and rotate credentials.
- Automate enforcement — Use infrastructure-as-code tools to detect and auto-remediate over-permissions (e.g., AWS Config rules, Terraform policies).
Pro tip: The phrase "deny by default" is your mantra. Always assume no access unless explicitly allowed — that's the core of least privilege.
Hands-on walkthrough
Let's put least privilege into practice with concrete examples. We'll work through three common scenarios: Linux file permissions, a Python script that reads a config file, and a cloud IAM policy.
1. Linux file permissions
A common mistake is running a web server as root. Instead, create a dedicated service user with only read access to the web directory. Here's how:
# Create a dedicated user for the web service
sudo useradd -r web_service
# Set ownership: root owns the directory, but the service user can read files
sudo chown -R root:www-data /var/www/html
sudo chmod -R 755 /var/www/html
# Grant write only to the specific log directory
sudo mkdir -p /var/log/webapp
sudo chown web_service:web_service /var/log/webapp
sudo chmod 700 /var/log/webapp
Now the web service user can serve files (read) but can't modify the code, and it can write only to its log directory. If the service is compromised, the attacker can't change the website or read system secrets.
2. Python script with minimal access
Suppose your Python application needs to read a database password from a config file. Instead of giving the script root access, lock down the file so only the application's service account can read it.
import os
from pathlib import Path
# Assume the script runs as 'app_user' — no sudo needed
config_path = Path('/etc/myapp/.db_secret')
try:
secret = config_path.read_text().strip()
except PermissionError:
print("ERROR: Cannot read config. Check file permissions.")
raise
# Use the secret to connect (example only)
print(f"Config read successfully — secret length: {len(secret)}")
To lock it down:
sudo chown app_user:app_user /etc/myapp/.db_secret
sudo chmod 600 /etc/myapp/.db_secret
Now only app_user can read that file — not other users, not the root-cron jobs. If the script is ever exploited, the attacker can't read system credentials.
3. Cloud IAM (AWS example)
Cloud providers make it easy to grant broad permissions like AdministratorAccess, but that's a worst practice. Instead, attach a minimally scoped policy:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:GetObject",
"s3:ListBucket"
],
"Resource": [
"arn:aws:s3:::my-app-assets/*",
"arn:aws:s3:::my-app-assets"
]
}
]
}
This policy lets the EC2 instance only read from a specific S3 bucket — no list-all-buckets, no write, no other services. You can attach this policy to an IAM role and assume it from your code.
Expected output: If you run the Python script as app_user, it prints Config read successfully — secret length: 24. If you run it as another user, you'll get a PermissionError.
Compare options / when to choose what
There are several tools and approaches to enforce least privilege. Here's a comparison to guide your choice:
| Approach | Strengths | Weaknesses | Best for |
|---|---|---|---|
POSIX file permissions (chmod/chown) |
Simple, built-in, fast | Coarse-grained; no per-app isolation | Single-host apps, Linux services |
| Role-based access control (RBAC) | Centralized, easy to manage, auditable | Needs IAM infrastructure | Cloud platforms, multi-user systems |
| Container security contexts | Isolates processes with non-root users & read-only filesystems | Container-specific; learning curve | Microservices, Kubernetes |
Just-in-time elevation (e.g., sudo with timeout, AWS STS) |
Reduces standing privileges, great for audits | Requires trust in the elevation mechanism | Admin tasks, break-glass scenarios |
| Infrastructure-as-code policy (Terraform, CloudFormation) | Reproducible, auto-enforced, reviewable | Needs CI/CD integration | Large cloud estates |
When to choose what?
- For a single server or simple app, start with POSIX permissions — they're quick and effective.
- For cloud-native systems, use RBAC + IAM policies with specific resources.
- For containerized workloads, combine security contexts (run as non-root, read-only root filesystem) with RBAC in Kubernetes.
- For admin tasks, use just-in-time elevation instead of always-on sudo.
Troubleshooting & edge cases
Practicing least privilege can introduce friction. Here are common issues and how to fix them:
- "The app broke after locking permissions" — Usually you revoked something needed. Check logs for permission errors (
PermissionError,EACCES). Re-grant only the missing resource, and test incrementally. - "A service needs to write to a directory, but I gave read-only" — That's by design; you must scope the write to the exact path, not the whole tree. Use separate write-directories.
- "I have too many users and can't manage them manually" — Automate with infrastructure-as-code and use groups/roles instead of individual permissions.
- "Root can still read everything" — True, but root access should be reserved for emergencies with
sudoaudit logs. Usesudo -lto list allowed commands. - "Running containers as non-root is hard" — Many base images require a root to install packages. Build a custom image with a non-root user (
USER appuserin Dockerfile) and use read-only volumes.
Edge case: Environment variables can leak secrets. If your script reads config from /etc/myapp/.db_secret, don't echo it to stdout or logs. Also, never put secrets in code.
Pro tip: When you hit a permission issue, don't just chmod 777 — solve the root cause. That's a classic over-privilege mistake.
What you learned & what's next
You now understand the core idea behind the principle of least privilege: grant every user and process only the permissions it absolutely needs. You've seen how to apply it in a practical exercise — from Linux file permissions to Python scripts and cloud IAM policies. You can explain why it's critical, and you have a mental model and a troubleshooting toolkit to keep your systems resilient.
Here's your quick recap of what you mastered:
- The problem: over-privileged accounts multiply breach impact.
- The mental model: think in terms of a librarian's key ring — minimal keys.
- The process: inventory, define, assign, review, automate.
- Hands-on: you created a service user, locked file permissions, and wrote a minimal IAM policy.
- Comparison: you know when to use chmod, RBAC, containers, or just-in-time elevation.
- Troubleshooting: you can fix permission errors without resorting to 777.
Next step: Head to the next lesson in the Security foundations track, where you'll build on this foundation to handle secrets management and access control at scale. Keep practicing least privilege — it's a habit that will pay off many times over.
Now, go ahead and review the permissions on one of your own projects. Identify at least one account that has more access than it needs and tighten it. That's the practical takeaway you can implement right now.
Practice recap
Hands-on exercise: Pick a small project (or a server you manage) and audit the top 5 most privileged accounts or service users. For each, write down the exact job function and then tighten permissions to match. Use ls -l to verify file permissions, and if any tool needs more access, grant it precisely. This practice will cement the principle of least privilege in your daily workflow.
Common mistakes
- Running all processes as root or Administrator "to keep things simple" — this defeats least privilege and amplifies any compromise.
- Granting write access to an entire directory when only one file needs it; instead, scope permissions to the exact path.
- Creating a service account with long-lived credentials and unlimited permissions — always prefer time-limited roles and rotate secrets.
- Using chmod 777 to fix a permission error — this opens the door to everyone and is the opposite of least privilege.
Variations
- Use container security contexts (Kubernetes: runAsNonRoot, readOnlyRootFilesystem) alongside RBAC to enforce least privilege at the container level.
- Implement just-in-time access for admin tasks using tools like Teleport, AWS SSO, or sudo with timeouts instead of standing root access.
- Apply policy-as-code with Open Policy Agent (OPA) or Sentinel to automatically validate and block over-privileged IAM policies in CI/CD.
Real-world use cases
- A backend service on AWS only needs to read a specific S3 bucket; a scoped IAM role prevents it from deleting data if compromised.
- A CI/CD pipeline uses a short-lived token with permissions to push to one repository only, reducing the blast radius of a leaked secret.
- A customer support team has read-only access to customer records; write access is granted temporarily via a just-in-time flow for specific actions.
Key takeaways
- Least privilege means granting only the permissions each user or process needs — nothing more.
- Follow a step-by-step process: inventory accounts, define job functions, assign minimal access, review regularly, and automate enforcement.
- In Linux, use dedicated service users, directories with 700/600 permissions, and avoid running apps as root.
- In the cloud, replace AdministratorAccess with scoped IAM policies that specify exact actions and resource ARNs.
- Use just-in-time elevation and role-based access control to minimize standing privileges.
- Always test after tightening permissions — start with minimal access and incrementally grant only what breaks.
Keep learning
Related tutorials, quizzes, and articles for this topic.
Discussion
Questions, corrections, and tips help everyone reading this page.
0 comments
Add a comment
No comments yet — start the thread.