An engineer assumes a role in an AWS member account.
The account sits beneath an organisational unit with the AWS-managed FullAWSAccess service control policy attached.
The engineer tries to list an S3 bucket.
AWS returns:
AccessDenied
The first reaction may be:
But S3 is allowed by the SCP.
That statement can be completely true.
The request can still be denied.
The misunderstanding comes from treating an SCP as a permission grant.
It is not one.
A service control policy defines the maximum permissions that may remain available to principals in affected AWS member accounts. It does not grant those permissions.
The request still needs an applicable grant path, such as an identity-based policy or resource-based policy. It must also survive every applicable limiting policy, explicit deny, request condition and service-specific rule.
“Allowed by the SCP” means the organisation has left the action inside the permitted ceiling. It does not mean the caller has been authorised to perform it.
An SCP answers:
May this action remain available
inside this organisational scope?
It does not answer:
May this principal perform
this action on this resource
under these conditions now?
That second question belongs to the complete AWS authorization system.
Authorization needs a grant path
AWS requests begin without permission.
Some applicable policy path must grant the requested action.
Possible grant sources include:
IDENTITY-BASED POLICY
permission granted to
a user, role or session
RESOURCE-BASED POLICY
permission granted by
the target resource
The request may then be restricted by:
PERMISSIONS BOUNDARY
maximum identity permission
SESSION POLICY
maximum permission for
this temporary session
SCP
maximum permission available
to affected member-account principals
RCP
maximum permission accepted
by supported resources
An explicit deny in any applicable policy overrides a matching allow.
The complete model is therefore not one fixed pipeline.
REQUEST CONTEXT
│
┌────────────────┼────────────────┐
│ │ │
▼ ▼ ▼
GRANT SOURCES LIMITERS EXPLICIT DENIES
│ │ │
├── identity ├── boundary ├── identity
└── resource ├── session ├── resource
├── SCP ├── boundary
└── RCP ├── session
├── SCP
└── RCP
│ │ │
└────────────────┼────────────────┘
▼
SERVICE-SPECIFIC EVALUATION
│
┌────────┴────────┐
▼ ▼
ALLOWED DENIED
The principal type, account relationship, resource and service determine exactly how these policy categories combine.
Identity and resource policies may form a grant path.
Limiting policies generally intersect with that path.
Explicit denies remain decisive.
No single green light necessarily represents the final decision.
An SCP is a filter, not a grant
Consider an SCP containing:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "s3:*",
"Resource": "*"
}
]
}
The policy leaves S3 actions available within its scope.
It does not give an IAM role permission to use S3.
Suppose the role has no identity-based S3 permission and no applicable resource-based grant.
SCP:
S3 remains available
Grant path:
no S3 permission
Result:
denied
The SCP does not fill the missing permission.
It merely refrains from removing it.
What the SCP layer actually decides
FullAWSAccess does not mean administrator access
When SCPs are enabled, AWS Organizations uses an AWS-managed policy named FullAWSAccess.
Its purpose is to leave services and actions available at the SCP layer until the organisation introduces narrower controls.
It does not mean:
Every principal has
full AWS access.
It means:
The SCP layer is not currently
filtering AWS actions out of
the maximum available set.
An IAM role with no policies still has no useful authority.
A role allowed only to read CloudWatch metrics remains limited to those actions.
A role with broad IAM permissions may exercise broad authority because the SCP is not narrowing it, but the authority comes from IAM.
| SCP | Grant path | Result |
|---|---|---|
FullAWSAccess |
No S3 grant | S3 request denied |
FullAWSAccess |
Allow s3:GetObject |
Request may proceed |
Deny s3:GetObject |
Allow s3:GetObject |
Request denied |
| Allow only S3 | Allow EC2 administration | EC2 request denied |
| Allow only S3 | Allow s3:GetObject |
S3 request may proceed |
“May proceed” matters.
Another boundary, resource condition, RCP or explicit deny may still block the request.
An explicit deny wins
Suppose a role has IAM permission to create an internet gateway.
{
"Effect": "Allow",
"Action": "ec2:CreateInternetGateway",
"Resource": "*"
}
The Production OU has an SCP denying the action.
{
"Effect": "Deny",
"Action": "ec2:CreateInternetGateway",
"Resource": "*"
}
The result is denial.
The account administrator cannot repair it by attaching a broader IAM policy.
They cannot grant authority beyond the organisational ceiling.
The deny belongs to a higher administrative boundary.
SCP allows must survive the hierarchy
SCPs may be attached to:
- the organisation root
- parent OUs
- child OUs
- an individual member account
Under an allow-list strategy, the action needs appropriate allow coverage throughout the applicable path.
Root:
allows S3
Workloads OU:
allows S3
Production OU:
does not allow S3
bfstore-prod:
allows S3
S3 remains unavailable in bfstore-prod.
The account-level allow cannot reopen an action filtered out by an ancestor.
For deny statements, one applicable deny along the path is enough to block the request.
The tree is part of permission evaluation.
Check whether the SCP applies
SCPs constrain principals in affected member accounts, including their root users.
They do not constrain users or roles in the management account.
They also do not restrict service-linked roles.
AWS documents a small number of additional exceptions for specific tasks.
A troubleshooting check should therefore begin with:
Is the principal in
an affected member account?
Is it using a
service-linked role?
Is this one of the documented
SCP exceptions?
A correct SCP cannot explain a request made by a principal outside its scope.
First obtain the session, then authorize the action
Role assumption and the eventual service request are separate authorization events.
Event one: obtain temporary credentials
AssumeRole
│
├── caller permission
├── target trust policy
├── request conditions
└── optional session policy
│
▼
temporary credentials
The caller may need permission to request the role.
The target role must trust the caller and request context.
If assumption succeeds, AWS issues a role session.
Event two: use the session
Service API request
│
├── session principal
├── identity or resource grant
├── permissions boundary
├── session limit
├── SCP and RCP
└── service-specific rules
The trust policy usually explains whether the session could be created.
It does not normally explain why a later S3, CloudWatch or EKS request failed after assumption succeeded.
Troubleshooting should ask two different questions:
Could the principal
obtain the session?
and:
Could that session
perform the action?
Why an SCP-allowed request still fails
The permission was never granted
The simplest case is a missing grant.
SCP:
action remains available
Identity or resource policy:
no applicable allow
Result:
denied
The SCP allow keeps permission possible.
It does not create it.
The permissions boundary is narrower
Suppose the role policy allows:
s3:GetObject
s3:PutObject
Its permissions boundary allows only:
s3:GetObject
The effective identity permission is narrower.
ROLE POLICY
GetObject
PutObject
BOUNDARY
GetObject
EFFECTIVE IDENTITY PERMISSION
GetObject
The SCP has not denied PutObject.
The role boundary has prevented the identity policy from granting it.
These layers solve different problems:
ORGANISATION CEILING
what affected principals
may ever be allowed to do
ROLE CEILING
what this IAM identity
may ever be allowed to do
IDENTITY POLICY
what the identity is
currently granted
The session is narrower
A role may support broad operations.
A particular temporary session may receive a session policy that narrows it.
ROLE
read and limited mutation
INVESTIGATION SESSION
read-only
The SCP may leave mutation available.
This session still cannot use it.
The resource rejects the request
A resource policy may grant or deny access directly on resources such as:
- S3 buckets
- KMS keys
- SQS queues
- Secrets Manager secrets
- IAM roles
A clear explicit-deny example is:
SCP:
S3 remains available
Identity policy:
GetObject allowed
Bucket policy:
explicitly denies requests
outside the approved VPC endpoint
Request:
uses another endpoint
Result:
denied
For cross-account access, the target resource may also need to grant the caller account or principal.
SCP:
S3 remains available
Caller policy:
GetObject allowed
Target bucket policy:
no cross-account grant
Result:
denied
The SCP does not certify that the resource accepts the caller.
An RCP limits the resource
A resource control policy can constrain access to supported resources in member accounts.
The caller may have an identity grant.
The SCP may leave the action available.
The resource may still sit beneath an RCP that does not allow the request.
The final result is denial.
A bfstore example
Mariam uses an IAM Identity Center permission set named:
ProductionInvestigator
The generated role in bfstore-prod has identity permissions allowing:
- CloudWatch log reads
- read-only EKS inspection
- deployment-history reads
- selected service descriptions
The role has a permissions boundary that leaves those investigation actions available but does not allow:
- secret-value retrieval
- IAM mutation
- infrastructure deletion
The Production OU has SCPs that leave the investigation services available but explicitly deny:
- disabling central logging
- leaving approved Regions
- changing organisation-managed security configuration
The session lasts one hour.
A request to view application logs can succeed because:
Identity policy:
allows log read
Permissions boundary:
leaves log read available
SCP:
leaves log read available
No applicable explicit deny:
found
A request to retrieve a production database password fails because the permissions boundary does not allow that action.
A request to disable central logging fails because the SCP explicitly denies it.
A request to delete an EKS cluster fails because no identity grant provides that permission.
DELETE CLUSTER
denied because no grant exists
READ DATABASE PASSWORD
denied because the boundary
does not leave it available
DISABLE CENTRAL LOGGING
denied by the SCP
The user sees three denials.
They come from three different policy layers.
Calling all three “an SCP problem” would send the investigation into the wrong cupboard.
Diagnose the failed request
When AWS returns AccessDenied, start with the complete error.
For many requests, AWS may provide additional context such as:
no identity-based policy allows
explicit deny in an SCP
no SCP allows
permissions-boundary denial
session-policy denial
RCP denial
Enhanced messages are useful evidence.
They are not universal. Some services and cross-account scenarios provide less detail.
Then follow the request.
Identify the authorization event
Did role assumption fail?
or
Did a later service action fail?
Identify the principal
- Which user, role or session made the request?
- Is it the expected identity?
- Which account owns it?
- Does an SCP apply to that principal category?
Identify the action and resource
- Which exact API action failed?
- Which resource was targeted?
- Which Region and request conditions applied?
Find the grant path
- Does an identity policy allow the action?
- Does a resource policy provide a required grant?
- For role assumption, does the trust policy accept the caller?
Check limiting layers
- Which permissions boundary applies?
- Was a session policy supplied?
- Which SCPs apply from root to account?
- Does an RCP affect the target resource?
Look for explicit denies
Check applicable:
- identity policies
- resource policies
- boundaries
- session policies
- SCPs
- RCPs
Check service-specific requirements
Some services require additional permissions, key policies, resource grants or conditions that are not obvious from the original API call.
WHICH EVENT FAILED?
│
▼
WHO CALLED?
│
▼
WHAT ACTION AND RESOURCE?
│
▼
WHERE IS THE GRANT?
│
▼
WHICH LIMITS APPLY?
│
▼
IS THERE AN EXPLICIT DENY?
This is slower than blaming the SCP immediately.
It is considerably faster than editing the wrong policy six times.
Prove the intended policy behaviour
Policy-analysis tools are useful.
They do not reproduce every AWS authorization path.
Simulation may have limitations involving:
- cross-account access
- resource-based role permissions
- SCP conditions
- RCPs
- service-specific authorization
- the real runtime and request context
SIMULATOR
useful for selected
policy reasoning
REPRESENTATIVE TEST
required for complete
authorization behaviour
An SCP test should define both:
EXPECTED SUCCESS
operation should remain possible
and:
EXPECTED DENIAL
operation must remain unavailable
A useful test records:
- principal
- account
- OU path
- action
- resource
- request context
- expected result
- observed result
- relevant grant
- relevant SCP or RCP
- other limiting policies
This separates two questions:
- Did the SCP leave or remove the action as intended?
- Did the complete authorization system produce the expected final decision?
A failed success test may indicate a missing identity grant rather than a broken SCP.
An unexpectedly successful denial test may indicate that the wrong principal, account, resource or condition was exercised.
Important policy changes should therefore move through:
STATIC ANALYSIS
│
▼
POLICY REASONING
│
▼
REPRESENTATIVE ACCOUNT TEST
│
▼
STAGED OU ROLLOUT
│
▼
PRODUCTION VERIFICATION
Questions I now ask
Principal
Which principal and session
made the request?
Request
Which action, resource and
context were evaluated?
Grant
Where does the applicable
permission grant come from?
Identity limits
Which permissions boundary
or session policy applies?
Organisation limits
Which SCPs apply along
the complete hierarchy path?
Resource limits
Does an RCP or resource policy
affect the target?
Denial
Is there an explicit deny
or service-specific requirement?
Test
Did the test isolate SCP behaviour
or only observe the final decision?
These questions replace one misleading binary:
SCP says allow,
therefore access should work.
The mental model I am keeping
My earlier model was:
SCP ALLOWS ACTION
│
▼
ACTION ALLOWED
The stronger model is:
AWS REQUEST
│
▼
REQUEST CONTEXT
│
┌───────────────┼───────────────┐
│ │ │
▼ ▼ ▼
GRANT PATH LIMITERS EXPLICIT DENIES
│ │ │
▼ ▼ ▼
identity or boundary, any applicable
resource policy session, deny statement
SCP or RCP
│ │ │
└───────────────┼───────────────┘
▼
SERVICE-SPECIFIC EVALUATION
│
┌────────────┴────────────┐
│ │
▼ ▼
ALLOWED DENIED
The grant path answers:
Where does the principal
receive authority?
The permissions boundary answers:
How far may this IAM identity's
permissions extend?
The session policy answers:
How much authority may
this temporary session use?
The SCP answers:
Which permissions may remain
available to affected principals
in this account or OU?
The RCP and resource policy answer:
Which requests may
this resource accept?
The request context answers:
Which principal, resource,
network, Region, tags
and conditions apply?
An SCP is powerful because it can prevent member-account administrators from granting selected authority.
It is not powerful because it grants authority itself.
An SCP allow keeps a permission inside the realm of possibility. A valid grant path must still turn that possibility into authority.
FullAWSAccess is not an administrator role.
An SCP allow is not an entitlement.
An AccessDenied response is a result, not a diagnosis.
“Allowed by the SCP” is useful evidence.
It is just not the verdict.
References and further reading
- AWS Organizations: Service control policies
- AWS Organizations: SCP evaluation
- AWS IAM: Policy evaluation logic
- AWS IAM: How AWS evaluates policies
- AWS IAM: Permissions boundaries
- AWS IAM: Troubleshooting access denied
- AWS IAM: Testing policies with the simulator
- AWS Organizations: SCP examples and testing guidance
- AWS Organizations: Resource control policies
- AWS IAM Identity Center: Permissions boundaries for permission sets