Logging In Does Not Grant You Permission
In one line
Authentication is "who are you," and authorization is "what can you do." The cloud keeps the two completely separate, so being able to log in successfully and still not be able to do anything is the normal state.
Why it was needed
If you can't tell 401 from 403, debugging takes twice as long.
| Response | Meaning | Where to fix |
|---|---|---|
| 401 Unauthorized | I don't know who you are | Credentials, token, signature |
| 403 Forbidden | I know who you are, but no | Policy, permissions |
The names are confusingly assigned — 401 is actually an authentication failure and 403 is an authorization failure. If you get AccessDenied from a cloud API, it is in the 403 family, and it means the credentials are fine. Reissuing the key does no good.
How it works
Kinds of principals
Permissions are not attached only to "people."
| Principal | Example | Characteristics |
|---|---|---|
| User | A staff account | Long-term credentials. A person logs in |
| Group | developers |
A collection of users. Gathers permissions together |
| Role | ec2-app-role |
Anyone can assume it. Temporary credentials |
| Service | A Lambda function, an EC2 instance | Runs by assuming a role |
| External identity | Google or GitHub OIDC | Assumes a role through federation |
The key concept here is the role. It is not a person but a "bundle of permissions," and a principal that meets the conditions borrows it for a while. We cover it in detail in a later module.
Evaluation order — an explicit deny wins
When several policies are attached to one principal, the result is decided like this.
1. 명시적 Deny 가 하나라도 있으면 → 거부 (무엇도 이를 뒤집지 못한다)
2. 명시적 Allow 가 하나라도 있으면 → 허용
3. 아무것도 없으면 → 거부 (기본 거부)
Two things matter.
- The default is deny. Permissions arise only when added. It is a safe default.
- Deny always takes priority. Even with administrator permissions, a single organization-level Deny blocks you. This is how you build guardrails.
The two places a policy attaches
You can produce the same result from two directions.
- Identity-based — attached to the principal. "This person can read that bucket"
- Resource-based — attached to the resource. "This bucket can be read by that person"
Within an account, you usually use only identity-based. Across accounts, you need both — for a principal in someone else's account to read our bucket, their identity policy must have an allow and our bucket policy must also have an allow. This is why cross-account access often fails.
What it looks like in the field
- Got
AccessDeniedand reissued the key → it is an authorization problem, so no effect at all. - An administrator is blocked only on a specific action → a Deny in a higher-level organization policy.
- Cross-account access does not work → an allow was put on only one side.
What to look at when you are denied
To avoid digging around anywhere when you receive AccessDenied, you need to fix an order of checks. This is because a single request has to pass several gates before it is allowed in the cloud.
- Who am I right now. First check whether the principal is the one you think it is. Code running on an instance usually runs as the attached role, but people test with their own personal credentials and say "it works for me." Every cloud has a command that prints the current principal, so print that first.
- At which gate was it blocked. The organization-level policy, the identity policy, the resource policy, and the scope narrowed when temporary credentials were issued. If any one of these does not allow it, it is a denial.
- Are the action name and resource name exact. A typo in an action name written in a policy does not cause an error; it just becomes a rule that does not match. The same goes for the resource notation: the bucket itself and the objects inside it are different resources, and it is common to need both.
- Is there a condition attached. If a condition such as source IP, time of day, tag or multi-factor authentication is attached, it works normally and is blocked only in a particular situation. Many of the reports that say "it worked yesterday" come from here.
And the habit of asking a tool for the verdict instead of guessing is important. The major clouds offer a feature that actually evaluates "can this principal perform this action on this resource," and it even tells you which policy made the decision. It is several times faster than reading policy documents by eye and reasoning, and it answers including the higher-level organization policies that people easily miss.
Finally, look at the logs. A denied request is left in the audit log, and it contains the principal, action, resource and time. This one line is far more accurate than a symptom relayed in words by a developer, so the starting point of the investigation should always be this record.
What to look at next
We take that policy document apart line by line to see what it really looks like.