How many IAM layers exist when accessing an S3 object from within an AWS VPC using an AWS principal? In AWS, even if an identity has the required permissions to access a resource, that does not guarantee the resource will be accessible.
There are generally three IAM layers: identity, network (VPC), and resource.
The rule of thumb of AWS IAM evaluation logic is that as long as there isn't an explicit deny, but there is an explicit allow, access will be granted. If we think of the journey from identity to resource, we can build a very approximate mental model of how to think about AWS IAM1. You should now print the AWS IAM evaluation reference logic, get a pen and write “VPC endpoint policies” above “Evaluate all applicable policies” to reflect how VPC endpoints factor into the process.
When you make a request from within a VPC - targeting a VPC endpoint - the request, carrying its SigV4, is sent to the AWS service's respective VPC endpoint. The VPC endpoint evaluates the identity's permissions against the resource it's trying to access and either forwards (allows) or rejects the request to the resource. The other policy evaluations follow after that. This isn't applicable if the request isn't reaching the VPC endpoint and it's reaching the public endpoint of the AWS service. Access points are on a similar level. The first core point is that if the request never reaches the service's endpoint, because a proxy or VPC endpoint decide not to forward it, the rest of the evaluation stops early.
We still need to understand the interactions between all of these IAM constructs.
Here's a diagram to help us build our reasoning.2
Does a session policy that allows s3:GetObject
, automatically enable to access the S3 object? No. Not if the identity didn't allow it in the first place. What's the relationship between a permissions boundary, a session policy, and an identity policy. Identity policies are directly attached to your user or role. I'm going to hand-wave and pretend that only roles and users exist in AWS as principals. This isn't the case, but it simplifies stuff.
Back to identity policies.
You'll use permission boundaries as a guardrail to enforce boundaries on roles whose policies you cannot control. For example the app team can manage a role and you want to try to stop the role from creating VPCs. You'll use session policies when assuming a role and want to drop permissions. For example the app team has built an S3 router. The role has access to the whole of the bucket but the session only allows access to a specific key of the bucket. You'll use a Service Control Policy to as a guardrail against account level access. For example, allowlisting AWS services altogether.
Use the diagram above to help you with the applicability and associations of policies against AWS principals, VPCs, and resources. If you're making a request to an AWS service that uses the public endpoint, remove the VPC endpoint policy.
A few cautionary notes:
Not all identities have the same IAM resource constructs. IAM users can be part of groups which have their own policies.3
Not all AWS resources have the same IAM resource constructs, not all AWS resources support policies, not all AWS services have VPC endpoints and not all VPC endpoint support policies.
Part of the perceived AWS IAM complexity stems from inconsistency.4
For instance, Amazon EFS has similar IAM constructs to S3, Amazon OpenSearch Service has Fine-grained-access controls, a different IAM construct. Even S3 has Access Control Lists, another IAM construct, which I'm going to pretend they don't exist in this primer, and so should you.
In most cases, the AWS services that work with IAM page offers the de facto reference. However, don't lean too heavy against it. As I mentioned earlier, what constitutes a "resource-based policy" varies. Take for example Amazon CloudSearch, which isn't listed as having one, but it does.5
The policy evaluation within an account goes like this - "if an action is allowed by an identity-based policy, a resource-based policy, or both, then AWS allows the action." Next time you see an empty S3 bucket policy, but the identity allows access and they're both in the same account, you now know why access will be granted. This is true for the majority of the cases that support resource-based policies - they don't require an explicit allow.
A lesser known corollary is that if a resource allows access to the role (session) then neither the permissions boundary or the session policy are evaluated. Access is granted. This is quite problematic in cases where you can explicitly control the identity-policies but cannot control the resource policies. This is where Resource Control Policies (RCPs) can shine. More on that later.
There are certain conditions on which the above diagram is not true. For example when dealing with cross account access, things are different. When an identity from another AWS account is making requests to our resources, either via public or VPC endpoints. Remember that all IAM policies apply to your AWS accounts' identities and resources only. If an attacker lands on your VPC they can use their identity and only the VPC policies would apply.
The take away is that an AWS account is the logical access container.
Before we move on, let's recap on our IAM components.
- Identity policies – The policies directly attached to your user or role
- Permissions boundary - An allowlist that is always attached to your role
- Session policy - A subset of permissions attached when you assume a role
- Service control policy - An SCP is an AWS organisation wide policy and is the ultimate allow or block list against services and identities
- Resource-based policies - Depends on the service, for example an S3 bucket policy
- Resource control policy - An RCP is an AWS organisation wide policy and is the ultimate allow or block list against services and resources
- VPC endpoint policy - When inside a VPC these policies allow or deny access to service requests.
Now, how can we determine which permissions affect our role trying to access an S3 object via a VPC endpoint ?6
The ultimate answer, is via automation and tooling. Look at AWS IAM Access Analyzer, aws-lint-iam-policies, cloudpilot.io, AWSXenos, among many others.
The check marks denote effective permissions. In other words where you see a check mark on the intersection of policies and none of the policies involved explicitly deny access, then access will be granted.
Reminder An SCP or RCP on their own cannot grant permissions. An IAM role needs to have permissions to access a resource. As long as the SCP doesn't deny access to the identity or specific resource, then the identity can access the resource. If there's a resource policy in place7
The red check marks effective permissions are only true when an identity outside of the organisation is inside the VPC. The service control policy wouldn't be applied to that identity. If you're inside a VPC owned by AWS account A and organisation A, and use credentials from AWS account B in organisation B, the service control policy of organisation A will not apply to your credentials from organisation B. Service Control Policies only apply to identities in the same organisation.
You can bring your own credentials to a compute resource and as long as the VPC endpoint policy allows your principal then you can access a resource. The same applies if you're trying to access a resource via the service's public endpoint and not via the VPC endpoint. Account B's principal won't be able to access account A' S3 bucket by default, as AWS resources are account bound8, but they would be able to access Account's B resources, which can lead to data exfiltration if this wasn't intended.
This is where RCPs come in. In the event that you have a leaky S3 resource policy, your RCP can blanket deny access to all principals outside the organisation. In general for a data perimeter, i.e. for establishing a baseline in keeping your AWS data to your AWS organisation, you'd need to sprinkle aws:Principal* and the aws:Resource* IAM conditions.
These conditions, prevent your AWS Principals from reaching to other account's resources. They would also prevent other AWS principals, outside of your AWS organisation, from reaching in to your resources. Things get tricky when AWS services get involved or when you're hitting public endpoints because reasons but the principles remain the same.
While you could establish high-level guardrails for your AWS Principals, you couldn't do the same with your resources, until RCPs were introduced.
Finally, it’s important to remember that IAM in AWS is constantly evolving and each service may bring its own nuances or additional policy constructs. By layering identity, VPC endpoint, and resource policies, plus leveraging organization-wide guardrails like SCPs and RCPs, you can build a robust data perimeter that keeps your accounts more secure.
As always, though, real-world scenarios often blur these clean lines—especially once you factor in cross-account access, public endpoints, or specialized service features. That’s why having a solid mental model of the evaluation flow can help you troubleshoot and refine your security posture when it feels like the policies are all stacked on top of each other.
It's not meant to represent how AWS IAM actually works. If you want to know more about how IAM actually works perhaps start with a gentle intro to Automated Reasoning or a not so gentle intro to Zelkova
Trying excalidraw because I don't want to admit that PowerPoint is the best diagramming tool. That goes for you Phil H.
I won't go into IAM Identity Center because there is a great overlap of terminology with completely different meaning.
Perhaps all
I've reported the issue to the good folks as AWS
Ultimately via automation and tooling. Look at AWS IAM Access Analyzer, aws-lint-iam-policies, cloudpilot.io, AWSXenos, among many others.
This is an Euler diagram and not a Venn diagram
Most of them