What Is IAM Least-Privilege?
The principle of least privilege means giving any user, service, or system only the minimum permissions required to do its job — nothing more. In AWS, this is enforced through IAM (Identity and Access Management) policies that explicitly allow or deny specific actions on specific resources.
It sounds simple. In practice, most people skip it — especially when getting started. I was one of them.
The Mistake I Almost Made
When I first set up my CI/CD pipeline to deploy this portfolio to AWS S3 + CloudFront,
the path of least resistance was to use my personal IAM user's access keys — the one
with AdministratorAccess. It would have worked instantly.
I caught myself before doing it. Here's what I did instead.
Step 1 — Create a Dedicated Deploy User
The first step is creating a separate IAM user whose only purpose is to run deployments. This user should have no AWS Console access — only programmatic access (access key + secret key).
- Go to IAM → Users → Create user
- Name it something descriptive:
portfolio-deploy - Select Programmatic access only — no Console login
- Skip adding any policies for now — we'll do that next
- Generate and save the access key ID and secret key
Step 2 — Write a Scoped IAM Policy
Instead of attaching a managed policy like AmazonS3FullAccess,
write a custom policy that grants only what the deploy pipeline actually needs:
- Read and write objects in one specific S3 bucket
- Create CloudFront cache invalidations for one specific distribution
Attach this policy directly to the portfolio-deploy user.
That's it. Nothing else.
What This Policy Allows vs. What It Blocks
| Action | Allowed? | Why |
|---|---|---|
| Upload files to S3 bucket | ✅ Yes | Needed for deployment |
| Delete stale files from S3 | ✅ Yes | Needed for --delete flag |
| Invalidate CloudFront cache | ✅ Yes | Needed post-deploy |
| Access other S3 buckets | ❌ No | Not in Resource ARN |
| Delete the S3 bucket itself | ❌ No | Not in Action list |
| Access EC2, RDS, Lambda, etc. | ❌ No | Not in policy at all |
| Create or delete IAM users | ❌ No | Not in policy at all |
| Access AWS Console | ❌ No | Programmatic access only |
Step 3 — Store Credentials in GitHub Secrets
Never put AWS credentials in your code, workflow files, or environment variables that get committed. GitHub Secrets are the right place — they're encrypted at rest and are masked in all logs.
Go to your repo → Settings → Secrets and variables → Actions → New repository secret:
Step 4 — Reference Secrets in Your Workflow
Your GitHub Actions workflow never sees the actual values — it references them by name:
*** in all output.
What Happens If the Credentials Leak?
This is the key question — and the whole point of least-privilege.
With admin credentials leaked:
An attacker can spin up EC2 instances for crypto mining, exfiltrate data from every S3 bucket, delete your entire infrastructure, create new IAM users with full access, and rack up a bill worth thousands of dollars — all before you notice.
With least-privilege deploy credentials leaked:
An attacker can upload files to one specific S3 bucket and invalidate one CloudFront distribution. That's it. You rotate the key, the damage is contained, and you move on.
How to Rotate a Compromised Key
If you ever suspect your credentials are exposed:
- Go to IAM → Users → portfolio-deploy → Security credentials
- Click Deactivate on the compromised key immediately
- Create a new access key
- Update the new values in GitHub Secrets
- Delete the old deactivated key
- Review CloudTrail logs to audit what the compromised key was used for
Lessons Learned
- Never use root or admin credentials in CI/CD — the blast radius is your entire AWS account
- Scope policies to specific resource ARNs —
Resource: "*"is almost always wrong - Programmatic-only access for deploy users — no Console login needed, ever
- GitHub Secrets over environment variables — secrets are masked in logs automatically
- Rotate keys regularly — even unexposed keys should be rotated every 90 days as a habit
- Use CloudTrail to audit key usage — always know what your credentials are doing