The IAM policy controls access — the document controls how people feel about it
I tightened a teammate’s AWS permissions last night. Added an inline deny policy to block three categories of CloudWatch log groups — WorkSpaces OS logs, VPC flow logs, WAF request data. Five minutes of IAM work. Then I spent twenty minutes writing a document explaining every boundary, what’s accessible, what’s denied, what’s coming next, and what I haven’t designed yet.
The document mattered more than the policy.
The default is silence
Most companies handle access control the same way. Someone asks for access. An admin creates a policy. The requester gets a login link. Nobody explains what they can and can’t do, or why.
The requester discovers their boundaries by hitting access denied errors in the console. The reasoning lives in the admin’s head, or nowhere. The policy feels arbitrary because, from the requester’s perspective, it is.
I’ve been on both sides of this. As the person hitting unexplained access denied errors, I’ve wondered whether asking about it signals that I’m trying to access something I shouldn’t. As the admin applying policies, I’ve told myself the restrictions are obvious and don’t need explanation. They aren’t, and they do.
Boundaries without explanation feel like distrust
The teammate whose access I tightened is a senior engineer. He has broad impact across the platform. When you restrict a senior person’s access without telling them why, they have two options: assume you have good reasons, or assume you don’t trust them. The more senior the person, the more the second interpretation stings — and the more corrosive it is to the working relationship.
An access control document converts “you can’t do this” into “this data is security telemetry and isn’t relevant to your work.” One is a wall. The other is a map.
What I wrote
The document covered four things. What’s accessible and why — app logs, infrastructure logs, metrics, dashboards, the full debugging surface, because the goal is autonomous debugging without waiting on someone else to run commands. What’s denied and why — three log group prefixes containing endpoint OS event logs, VPC flow logs, and WAF request data, denied because of what the data contains, not because of who’s asking. What’s coming next — a Kubernetes RBAC viewer role so he can see pod events and deployment status directly instead of asking me to run kubectl. And what’s not designed yet — an honest statement that the GovCloud access model is acknowledged debt, not an oversight.
I shared it with the whole team, not just the person whose access changed.
Deny categories, not individuals
The document made a principle explicit that I hadn’t articulated before writing it down: deny based on what the data contains, not who’s asking. The same policy applies to anyone in the same role. VPC flow logs are network forensics data and nobody in a developer role needs them. WAF logs contain full HTTP request bodies and headers. WorkSpaces OS logs are endpoint management telemetry.
This depersonalizes the restriction. It’s not “we don’t trust you with VPC flow logs.” It’s “VPC flow logs are a data category that doesn’t belong in a debugging permission set.” If the data classification changes, the policy changes. If the role changes, the policy changes. Neither change is about the person.
I didn’t fully understand this principle until I had to write it down for someone else. The act of documenting forced me to distinguish between “I don’t want this person reading WAF logs” and “WAF logs are a different data classification than app logs.” The first is a trust judgment. The second is an architecture decision. They feel similar from the admin’s chair. They land very differently on the other side.
Visible but inaccessible beats invisible
A small design choice in the IAM policy that the document explained: the developer can see that the denied log groups exist in the CloudWatch console. He just can’t read their contents. Clicking into one shows access denied.
This is better than hiding the log groups entirely, and I almost did the opposite. Hidden resources create confusion — “I thought we had WAF logs?” Visible-but-denied resources create clarity — “I can see WAF logs exist, I don’t have access, and the doc tells me why.” The document turns the access denied error from a dead end into a cross-reference.
The document outlives the conversation
Six months from now, when someone new joins the team or when we revisit the access model, the reasoning is written down. Nobody has to reconstruct why those three log group prefixes were denied. Nobody has to ask whether the restriction was deliberate or accidental. The document captures the decision and the thinking, not just the outcome.
This matters more than it seems. I’ve inherited IAM policies in every job I’ve had. The policies are always there. The reasoning never is. You’re left reverse-engineering intent from resource ARNs and action lists, hoping the person who wrote it was being principled and not just reactive. A one-page document eliminates that archaeology.
Twenty minutes
The IAM policy took 5 minutes. The document took 20. The document was 4x the effort of the technical work, and it was the part that changed how the team received the change.
Access control is a team concern, not a private transaction between an admin and a user. The policy enforces the boundary. The document earns it.