A permission gets added during an incident. A wildcard sneaks in during a rushed deploy. A role is copied “just to get things working.” Nobody comes back to clean it up. Six months later, the policy is twice as big, nobody remembers why half of it exists, and the next audit turns into a week-long fire drill. Cloud Iam Cleanup: Removing Unused Permissions With Audit Logs
I’ve lived through this more times than I’d like. IAM cleanup isn’t about heroics or perfect least privilege. It’s about safe, boring, repeatable reduction of risk without breaking production at 2am. This post is about how unused permissions actually get identified in the real world, how to remove them without outages, and how to stop the mess from rebuilding itself.
Why unused permissions are dangerous
Unused permissions don’t feel dangerous because nothing is actively using them. That’s exactly why they’re dangerous.
Every extra permission increases blast radius. If a workload is compromised, the attacker doesn’t care what permissions you intended to use they care what’s available. That old permission added during a migration? That’s now a data exfiltration path. That forgotten That’s privilege escalation waiting to happen.
I’ve seen roles that technically “only read from DynamoDB” but also had leftover permissions for ECS, SSM, and KMS from experiments years ago. Nobody noticed because nothing broke. Auditors noticed immediately.
Unused permissions also widen audit scope. The more permissions attached to a role, the more questions you have to answer. “Why does this Lambda need EC2 access?” turns into a half-day archaeology dig through commit history and Slack threads.
And then there’s the human factor. Wildcards and broad permissions normalize laziness. Once a role is already over-privileged, it becomes the dumping ground for the next exception. Permission creep accelerates quietly.
Unused permissions aren’t harmless. They’re latent risk.
What “unused permissions” actually means in practice
Here’s the first uncomfortable truth: “not seen in audit logs” does not automatically mean “safe to delete.”
In practice, unused permissions fall into a few categories:
-
Truly dead permissions
Services you no longer use. APIs that were enabled for a proof-of-concept and never touched again. These are the easy wins.
-
Rare but valid permissions
Quarterly jobs. Annual certificate rotations. Disaster recovery workflows. These might not show up in a 30-day window, but deleting them will hurt just not today.
-
Deploy-time or break-glass permissions
Permissions only used by CI/CD, migrations, or incident response. They’re quiet most of the time and absolutely critical when needed.
-
Permissions that were never used correctly
I’ve seen policies with actions that were intended to be used but never actually worked. They’re dead, but nobody knows they’re dead.
This is where IAM cleanup becomes judgment, not math. Audit logs are evidence, not truth. They tell you what happened, not what might need to happen later. Treat them as a signal, not a deletion list.
How to find unused permissions using audit logs
Audit logs are where IAM cleanup becomes real work instead of theory.
In AWS, that’s CloudTrail. In GCP, Cloud Audit Logs. In Azure, Activity Logs and Sign-In Logs. Different names, same pain.
Start with a realistic time window
In most environments, 30–90 days is the practical range. Less than 30 days misses normal operational variance. More than 90 days increases noise and slows analysis.
I usually start with 60 days and adjust if I know there are quarterly or monthly jobs involved.
Map logs back to policies
This part is tedious and unavoidable.
-
Identify the role or principal
-
List all allowed actions from attached policies
-
Compare against observed actions in logs
-
Flag actions never seen
Cloud-native tools can help here:
-
AWS IAM Access Analyzer
-
GCP Policy Analyzer
-
Azure Entra permissions reports
They save time, but they don’t replace thinking. I’ve seen these tools confidently mark permissions as “unused” that were required during deploys or DR tests that simply hadn’t run recently.
Watch for false negatives
Common reasons logs lie to you:
- Logging wasn’t enabled early enough
- AssumeRole chains hide the true caller
- Some services don’t emit detailed logs
- Permissions are used by third-party integrations
If a permission feels suspicious but also important, assume the logs are incomplete not the other way around.
Keep a “maybe” bucket
Not everything needs an immediate decision. I always maintain three lists:
-
Safe to remove
-
Definitely required
-
Unclear / needs validation
Rushing the unclear ones is how outages happen.
The safest way to remove permissions without outages
This is where most cleanup projects fail. Not because people didn’t analyze enough but because they removed permissions too aggressively.
Here’s the process that has kept me out of trouble.
Remove actions, not roles
Never start by deleting roles or detaching entire policies. Start by removing specific actions.
Going from to a smaller set is safer than deleting the policy entirely. Smaller diffs are easier to reason about and easier to roll back.
Make one change at a time
Batch removals feel efficient. They’re also impossible to debug.
I limit changes to:
-
One role
-
One policy
-
One set of related actions
Yes, it’s slower. It’s also survivable.
Deploy with heightened monitoring
After removal:
-
Watch
-
Monitor application error rates
-
Check CI/CD pipelines
Most breakages show up fast within minutes or hours if you’re looking.
Log denials aggressively
Denied actions are gold during cleanup. They tell you exactly what you missed.
In AWS, this means paying attention to CloudTrail events. In GCP and Azure, similar signals exist but you often need to explicitly query for them.
Roll back without shame
If something breaks, roll back immediately. Don’t argue with production.
IAM cleanup is about reducing risk over time, not winning arguments about theoretical least privilege.
Wait before the next cut
I usually wait a few days between changes for production roles. Long enough to catch delayed jobs and background workflows.
The biggest mistake I see is engineers doing “one big cleanup PR.” It looks great. It also guarantees a long night.
How to prevent permission creep long-term
Cleanup without prevention is just future work.
Policy-as-code helps if you use it honestly
Policy-as-code doesn’t magically solve IAM. What it does is:
-
Make changes visible
-
Enable review
-
Create an audit trail
The value isn’t the tool. It’s the friction. IAM should be slightly annoying to change.
Time-bound access is non-negotiable
Temporary permissions must actually expire. If your system can’t enforce this automatically, people won’t remember.
I’ve never seen “we’ll remove it later” work reliably.
Design roles for change, not perfection
Roles that try to cover everything are impossible to clean. Smaller, purpose-built roles are easier to reason about and safer to modify.
Yes, it means more roles. That’s fine. Humans reason better about small objects.
“Just trust engineers” doesn’t scale
Good engineers still take shortcuts under pressure. IAM systems need guardrails because production incidents don’t care about intentions.
Trust people. Verify permissions.
Practical checklist
-
Enable and retain audit logs long enough to matter
-
Start with one role, not the whole account
-
Classify permissions: used, unused, unclear
-
Remove actions incrementally
-
Monitor denials and application errors
-
Roll back fast if needed
-
Document why remaining permissions exist
-
Enforce expiration on temporary access
Common pitfalls and lessons learned
The most common mistake is treating IAM cleanup like refactoring code. It’s not. You don’t have tests that cover every path.
Another mistake is over-trusting tools. They’re helpful, but they don’t understand your business cycles or incident workflows.
I’ve also seen teams clean up service roles while ignoring human users. Long-lived users with broad permissions are often the worst offenders and the hardest politically.
Finally, don’t wait for audits. Audits punish delay, not risk. Cleanup should happen on your schedule, not theirs.
You Might Be Interested In
- Multi-tenant Saas Isolation: Patterns For Data, Compute, And Queues
- Api Rate Limits And Scaling Basics
- Best Cloud Gpu Options For Beginners
- Admission Controllers 101: How To Block Risky Deploys Before They Run
- Kubernetes Rbac Explained: Roles, Bindings, And Least Privilege
Conclusion
IAM cleanup isn’t a milestone you cross and forget about. It’s ongoing maintenance, like patching systems or rotating secrets. Permissions naturally expand as systems grow, incidents happen, and teams move fast. If nobody intentionally pulls them back, risk quietly accumulates until an audit, breach, or outage forces the issue.
The good news is that IAM cleanup doesn’t have to be scary or disruptive. When you use audit logs as evidence not absolute truth remove permissions incrementally, and watch production closely, cleanup becomes a routine engineering task instead of a high-risk event. The goal isn’t perfect least privilege. It’s smaller blast radius, clearer intent, and systems you actually understand. If you treat IAM cleanup as continuous, boring, and deliberate work, it will quietly pay you back when things go wrong.
FAQs about Cloud Iam Cleanup: Removing Unused Permissions With Audit Logs
How long should audit logs be reviewed before removing permissions?
In most production environments, I’ve found that 30–90 days is the realistic window where audit logs are actually useful. Thirty days is often enough to catch day-to-day application behavior, background jobs, and normal operational noise. Ninety days helps surface slower cycles like monthly billing jobs, scheduled cleanups, or infrequent integrations. Anything shorter than that tends to create false confidence, and anything much longer usually adds more data than insight.
That said, log windows should be informed by how your systems actually run. If you know you have quarterly processes, annual rotations, or disaster recovery drills, you need to explicitly account for them. Audit logs don’t understand your business calendar you do. When in doubt, extend the window or treat the permission as “unclear” instead of rushing removal.
What’s the safest way to remove permissions without breaking prod?
The safest approach is incremental removal paired with active monitoring. Instead of deleting entire roles or policies, remove specific actions that appear unused, deploy the change, and watch closely for errors or application failures. Most real breakages show up quickly if you’re paying attention, especially in systems with steady traffic.
Equally important is having an easy rollback path. You should be able to re-add a permission within minutes without debate or blame. IAM cleanup is not the time to prove a point. If production disagrees with your assumptions, production wins, and you adjust based on what you learned.
Why do some unused permissions still matter?
Some permissions are quiet by design. They only show up during deploys, migrations, incident response, or disaster recovery. These events might not happen for months, but when they do, missing permissions can turn a bad day into a catastrophic one. Audit logs will happily tell you those permissions were “unused” right up until you need them most.
I’ve also seen permissions that were added for future work that never happened, and permissions that were supposed to be used but never actually were due to bugs or misconfigurations. The hard part is telling these apart. This is why IAM cleanup requires context and conversations, not just log analysis.
How do you stop permission creep from coming back?
You don’t stop permission creep by telling people to be careful. You stop it by designing systems where permissions naturally expire, changes are visible, and adding access requires a small amount of friction. Time-bound access, reviewable policy changes, and clear ownership all help slow the drift.
At scale, good intentions aren’t enough. Engineers under pressure will always choose speed over precision if the system allows it. The goal isn’t to block work it’s to make the easy path also the safe one. If cleanup feels optional, it won’t happen.
Should you clean up users or roles first?
In most environments, cleaning up roles first gives you the biggest risk reduction for the least political pain. Roles tend to have larger blast radius and affect more systems, so tightening them pays off quickly. Service roles are also easier to reason about because their usage patterns are more predictable than human behavior.
Long-lived users, however, are often where the worst permission sprawl lives. They’re harder to clean up because they involve trust, habit, and sometimes ego. I usually tackle roles first to stabilize the environment, then move on to users with clearer data and stronger justification.

