Quick Answer
AWS IAM Access Control: Policies, Roles & Best Practices AWS Identity and Access Management (IAM) is the service that governs authentication and authorization...
Key Topics Covered
AWS IAM Access Control: Policies, Roles & Best Practices
AWS Identity and Access Management (IAM) is the service that governs authentication and authorization for every API call made to your AWS environment. It determines who can sign in, what actions they can perform, and on which resources — across every AWS service, in every region, for every account. Getting IAM right is not optional; according to AWS's own post-incident analyses, misconfigured IAM policies are involved in the majority of cloud security breaches that reach public disclosure. This article covers IAM's architecture, its policy evaluation logic, practical patterns for scaling access control, and the operational mistakes Opsio's SOC encounters repeatedly across hundreds of AWS accounts.
Key Takeaways
- AWS IAM is the foundational service for controlling who can do what across every AWS resource, and misconfiguring it is the most common root cause of cloud security incidents.
- Effective IAM requires layering identity policies, resource policies, permission boundaries, and Service Control Policies — not just attaching managed policies to users.
- Organizations operating under NIS2, GDPR, or DPDPA 2023 must treat IAM configuration as a compliance control, not just an operational convenience.
- ABAC (attribute-based access control) using tags is now the recommended scaling pattern for organizations with more than a handful of accounts, but most teams still default to RBAC.
- The biggest IAM failures Opsio's SOC investigates aren't permission escalations — they're stale credentials and over-permissioned service roles that nobody reviews.
How AWS IAM Works: The Core Model
IAM operates on a default-deny model. Every AWS API request is evaluated against a set of policies, and unless the evaluation produces an explicit Allow — with no Deny overriding it — the request is rejected. Understanding this evaluation chain is the single most important concept in AWS access control.
Principals, Actions, Resources, and Conditions
Every IAM policy statement has four components:
- Principal — the entity making the request (IAM user, IAM role, federated identity, AWS service)
- Action — the specific API operation (
s3:GetObject,ec2:RunInstances,iam:CreateUser) - Resource — the ARN(s) the action applies to
- Condition — optional constraints (source IP, MFA status, time of day, resource tags)
A policy is a JSON document containing one or more statements, each with an Effect of Allow or Deny. The power — and the complexity — comes from how multiple policies interact during evaluation.
The Policy Evaluation Chain
When a principal makes a request within an AWS Organization, the evaluation follows this order:
1. Service Control Policies (SCPs) — organization-level guardrails that set the maximum permissions for member accounts
2. Resource-based policies — attached to the resource itself (e.g., S3 bucket policies, KMS key policies)
3. IAM permission boundaries — the maximum permissions an IAM entity can have, regardless of its identity policies
4. Session policies — passed when assuming a role, further scoping the session
5. Identity-based policies — the policies attached to the IAM user, group, or role
An explicit Deny at any level overrides all Allow statements. This layered model means you can enforce organization-wide guardrails (via SCPs) even if individual account administrators try to grant broader access.
Understanding this chain is not academic — Opsio's NOC regularly traces access-denied errors to SCP restrictions that account-level admins didn't know existed. If you're troubleshooting a 403 on an API call where the identity policy clearly says Allow, check the SCPs first.
Need help with cloud?
Book a free 30-minute meeting with one of our cloud specialists. We'll analyse your situation and provide actionable recommendations — no obligation, no cost.
IAM Building Blocks in Practice
IAM Users vs. IAM Roles vs. Federated Identities
IAM users are long-lived identities with permanent credentials. They still exist and still work, but for human operators they should be considered legacy. AWS's current guidance — and Opsio's operational stance — is to federate human access through IAM Identity Center (formerly AWS SSO), which issues temporary credentials via SAML 2.0 or OIDC.
IAM roles are the workhorses of modern AWS IAM. A role has no permanent credentials; instead, principals assume the role and receive temporary security tokens (via AWS STS). Roles are used for:
- Cross-account access (Account A's workload assumes a role in Account B)
- Service-to-service access (an EC2 instance profile, a Lambda execution role)
- Human access via federation (assume a role after authenticating through your IdP)
Federated identities authenticate against an external identity provider (Okta, Azure AD / Entra ID, Google Workspace) and assume IAM roles. This is the pattern every organization with more than ten engineers should be using for console and CLI access.
| Approach | Credentials | Best For | Risk Profile |
|---|---|---|---|
| IAM Users | Long-lived access keys | Legacy systems, service accounts with no alternative | High — keys leak, rotate poorly |
| IAM Roles (assumed) | Temporary STS tokens | Cross-account, EC2/Lambda, CI/CD | Low — auto-expire, no keys to leak |
| IAM Identity Center | SAML/OIDC + temporary tokens | Human access across all accounts | Low — centralized, SSO-backed |
| Resource-based policies | N/A (grant access to external principals) | Cross-account S3, KMS, SQS | Medium — must be carefully scoped |
IAM Policies: Managed, Inline, and Custom
AWS managed policies (e.g., ReadOnlyAccess, PowerUserAccess) are maintained by AWS and cover common patterns. They're convenient but often too broad for production use. AdministratorAccess is the most commonly attached managed policy Opsio's SOC finds in audit findings — and it's almost never justified for day-to-day operations.
Customer managed policies are the right default. Write them yourself, scope them to your actual workloads, version-control them in Git, and deploy them via Infrastructure as Code (Terraform, CloudFormation, or CDK).
Inline policies are embedded directly in a user, group, or role. They have a strict 1:1 relationship. Use them only when a policy must not be accidentally attached to another entity — which is rare.
Service Control Policies (SCPs)
SCPs are the most powerful — and most misunderstood — layer in the IAM stack. They don't grant permissions; they define the maximum boundary of what any principal in a member account can do. An SCP that denies s3:DeleteBucket means no one in that account can delete a bucket, even if they have AdministratorAccess.
Practical SCP patterns Opsio deploys for clients:
- Region restriction — deny all actions outside
eu-north-1,eu-west-1, andap-south-1(enforcing data sovereignty for GDPR and DPDPA) - Guardrail SCPs — prevent disabling CloudTrail, deleting VPC flow logs, or modifying the audit IAM role
- Service deny-list — block services the organization doesn't use (e.g., Lightsail, GameLift) to reduce attack surface
RBAC vs. ABAC: Choosing the Right Model
RBAC (Role-Based Access Control)
RBAC in AWS means creating distinct IAM roles for each job function — DevOps-Engineer, Data-Analyst, Security-Auditor — and attaching policies to those roles. It's intuitive and works well when:
- You have fewer than ~20 distinct roles
- Teams are clearly separated
- Account sprawl is limited
The drawback is combinatorial explosion. If you have 5 job functions, 4 environments (dev/staging/prod/sandbox), and 3 projects, you could need 60 role definitions — each with separate policies.
ABAC (Attribute-Based Access Control)
ABAC uses tags on both principals and resources to make authorization decisions. Instead of 60 roles, you write a smaller set of policies with conditions like:
```json
"Condition": {
"StringEquals": {
"aws:ResourceTag/Project": "${aws:PrincipalTag/Project}",
"aws:ResourceTag/Environment": "${aws:PrincipalTag/Environment}"
}
}
```
This lets a developer tagged Project=payments, Environment=dev access only the resources tagged the same way — without creating project-specific or environment-specific roles.
AWS's IAM documentation explicitly recommends ABAC as the preferred model for scaling. In practice, most organizations Opsio manages use a hybrid: RBAC for broad job-function separation, ABAC for fine-grained resource scoping within those roles.
The operational catch: ABAC only works if your tagging is disciplined. If teams don't consistently tag resources, the conditions fail open or fail closed in unpredictable ways. Enforce tagging with SCPs and AWS Config rules before betting on ABAC.
IAM Best Practices: What Actually Matters
The AWS Well-Architected Framework's Security Pillar defines IAM best practices across five areas. Here's what we see matter most in production — not theory:
1. Eliminate Long-Lived Access Keys
Every access key is a credential that can be exfiltrated. Opsio's SOC has investigated incidents where access keys committed to public GitHub repos were exploited within minutes by automated scanners. The fix:
- Use IAM roles with temporary credentials for all workloads (EC2 instance profiles, ECS task roles, Lambda execution roles)
- Federate human access via IAM Identity Center
- For the rare cases where access keys are unavoidable (legacy integrations), enforce rotation via AWS Config rule
access-keys-rotatedwith a maximum age of 90 days
2. Enforce MFA — Everywhere That Matters
MFA on the root account is table stakes. But also enforce MFA for:
- All human IAM users (if you still have them)
- Role assumption for sensitive roles (
iam:AssumeRolewithCondition: { "Bool": { "aws:MultiFactorAuthPresent": "true" }}) - The IAM Identity Center authentication flow (push notification MFA, not SMS)
3. Apply Least Privilege Iteratively
Nobody gets least privilege right on the first try. The practical approach:
1. Start with AWS managed policies that are slightly broader than needed
2. Enable IAM Access Analyzer to monitor which permissions are actually used
3. After 30-90 days, generate a least-privilege policy based on CloudTrail access activity
4. Replace the broad policy with the generated one
5. Repeat quarterly
IAM Access Analyzer's policy generation feature is genuinely useful and underutilized. It reads CloudTrail logs and produces a scoped policy matching only the actions and resources actually invoked.
4. Use Permission Boundaries for Delegated Administration
If you allow developers or team leads to create IAM roles (e.g., for Lambda functions), set a permission boundary that caps what those created roles can do. Without this, a developer can create a role with AdministratorAccess — which is a privilege escalation path.
5. Audit Continuously, Not Annually
An annual IAM review is a checkbox exercise. Instead:
- Run IAM Access Analyzer continuously to detect external and unused access
- Monitor for anomalous IAM API calls via CloudTrail + Amazon GuardDuty
- Use AWS Config rules to flag non-compliant IAM configurations automatically
- Pipe findings into a centralized SIEM or your SOC's alerting pipeline
IAM in a Multi-Account AWS Organization
Single-account AWS environments are increasingly rare in production. AWS Organizations, combined with IAM Identity Center, is the standard pattern for managing access across tens or hundreds of accounts.
IAM Identity Center (Formerly AWS SSO)
IAM Identity Center provides a single place to manage human access across all accounts in your organization. Users authenticate once (through your corporate IdP or the built-in directory) and receive temporary credentials for whichever account and permission set they select.
Permission sets in IAM Identity Center are abstractions that create IAM roles in each target account. You define them once centrally and assign them to users or groups per account. This is drastically simpler than managing IAM roles independently in each account.
Cross-Account Role Assumption
For service-to-service access across accounts (e.g., a CI/CD pipeline in the tooling account deploying to production), the pattern is:
1. Create a role in the target account with a trust policy allowing the source account's role
2. The source workload calls sts:AssumeRole to get temporary credentials
3. Use external IDs to prevent confused-deputy attacks when third parties are involved
Opsio configures cross-account access using a hub-and-spoke model: a central security account holds audit roles that can read (but not write) into all member accounts. This design supports both SOC operations and compliance evidence collection.
Compliance Dimensions: NIS2, GDPR, and DPDPA 2023
IAM configuration is directly referenced in every major compliance framework Opsio encounters:
NIS2 Directive (EU) — Article 21 requires "policies on access control" including privileged access management. Organizations classified as essential or important entities must demonstrate that IAM controls are proportionate to risk, that privileged access is monitored, and that access reviews are conducted regularly. For AWS, this maps to SCPs, CloudTrail, IAM Access Analyzer, and documented access review procedures.
GDPR — Article 32 requires "the ability to ensure the ongoing confidentiality, integrity, availability and resilience of processing systems and services," which regulators interpret to include identity and access management. Data controllers must show that access to personal data is limited to personnel who need it — which means IAM policies scoped to specific DynamoDB tables, S3 prefixes, or RDS instances containing PII.
DPDPA 2023 (India) — Section 8 obligations on data fiduciaries include implementing "reasonable security safeguards." For Indian businesses running workloads in ap-south-1 (Mumbai) or ap-south-2 (Hyderabad), this means documented IAM controls, audit trails, and evidence of periodic review — similar in spirit to GDPR's Article 32 requirements.
The common thread: all three frameworks require not just that controls exist, but that they're monitored and reviewed. IAM configuration without CloudTrail logging and periodic access review doesn't satisfy any of them.
Common IAM Mistakes Opsio's SOC Encounters
Based on actual incidents and audit findings across our managed accounts:
1. Wildcard resource ARNs in production policies — "Resource": "*" is acceptable during prototyping. In production, it means a compromised principal can access every resource of that type in the account.
2. Service roles with AdministratorAccess — Lambda functions and ECS tasks should have narrowly scoped execution roles. Attaching admin access "because it's easier" turns every application vulnerability into a full account compromise.
3. No SCP guardrails on member accounts — Without SCPs, any account administrator can grant themselves anything. SCPs are the only mechanism that constrains even the account root user (in member accounts).
4. Stale IAM users and access keys — We routinely find IAM users for employees who left the organization months or years ago. Use AWS Config's iam-user-unused-credentials-check rule and set it to flag credentials unused for 45 days.
5. Ignoring resource-based policies — S3 bucket policies, KMS key policies, and SQS queue policies can grant access independently of identity policies. An S3 bucket with "Principal": "*" in its bucket policy is publicly accessible, regardless of how tight your IAM roles are.
Getting Started: A Practical Sequence
For organizations that haven't formalized IAM governance, here's the order that produces results fastest:
1. Enable CloudTrail in all accounts, all regions, logging to a centralized S3 bucket in a log archive account
2. Enable IAM Access Analyzer in every account (it's free)
3. Migrate human access from IAM users to IAM Identity Center with MFA
4. Deploy baseline SCPs — deny unused regions, protect audit infrastructure, require encryption
5. Audit existing IAM roles and policies — use Access Analyzer's findings to identify unused roles and over-permissioned policies
6. Implement Infrastructure as Code for all IAM resources — no more ClickOps in the IAM console
cloud migration and modernization
This sequence works whether you have 2 accounts or 200. The difference is how long step 5 takes.
Frequently Asked Questions
What are IAM access controls?
IAM access controls are the policies, roles, and mechanisms within AWS Identity and Access Management that determine which principals (users, roles, services) can perform which actions on which resources. They operate on a default-deny model: unless a policy explicitly allows an action, it is denied. Controls include identity-based policies, resource-based policies, permission boundaries, session policies, and Service Control Policies at the organization level.
Is IAM RBAC or ABAC?
AWS IAM supports both. Role-based access control (RBAC) is achieved by creating IAM roles with specific permission sets and assigning them to users or groups. Attribute-based access control (ABAC) uses tags on principals and resources to make dynamic authorization decisions. AWS recommends ABAC for scaling across many accounts because it reduces the number of distinct policies to manage. Most production environments use a hybrid of both.
What is IAM access in AWS?
IAM access in AWS refers to the authenticated and authorized ability for a principal — an IAM user, federated identity, or IAM role — to interact with AWS services and resources. Every API call to AWS is evaluated against IAM policies. Access is granted only when applicable policies produce an explicit Allow and no applicable policy produces an explicit Deny.
What are the 4 pillars of IAM?
The four pillars commonly referenced in identity management are: authentication (proving who you are), authorization (what you're allowed to do), administration (managing identities and policies at scale), and auditing (logging and reviewing access activity). In AWS terms, these map to IAM authentication mechanisms, IAM policies, AWS Organizations/IAM Identity Center, and AWS CloudTrail respectively.
How does AWS IAM relate to NIS2 compliance?
NIS2 requires essential and important entities to implement access control policies proportionate to risk, maintain incident response capabilities, and demonstrate accountability for privileged access. AWS IAM provides the technical controls — MFA, least-privilege policies, SCPs, CloudTrail logging — but compliance requires documented processes, periodic access reviews, and evidence that these controls are actively monitored. A managed SOC can bridge the gap between having the controls and proving they work.
Written By

Country Manager, Sweden at Opsio
Johan leads Opsio's Sweden operations, driving AI adoption, DevOps transformation, security strategy, and cloud solutioning for Nordic enterprises. With 12+ years in enterprise cloud infrastructure, he has delivered 200+ projects across AWS, Azure, and GCP — specialising in Well-Architected reviews, landing zone design, and multi-cloud strategy.
Editorial standards: This article was written by cloud practitioners and peer-reviewed by our engineering team. We update content quarterly for technical accuracy. Opsio maintains editorial independence.