AWS Identity and Access Management (IAM) controls who can access AWS resources and what actions they can perform. This guide has AWS IAM explained through practical examples covering users, roles, policies, permission evaluation and least privilege.
What Is AWS IAM?
AWS IAM is the global AWS service used to manage identities and permissions within an AWS account. It authenticates principals such as users and roles, then authorises or denies their requests according to applicable policies.
IAM itself does not create application users for your website. It controls administrative and programmatic access to AWS services and resources.
Important IAM characteristics include:
- IAM is a global service, not a regional service.
- New AWS accounts include a root user with unrestricted account access.
- IAM permissions deny requests by default.
- An explicit
Denyoverrides anAllow. - IAM roles provide temporary credentials through AWS Security Token Service (STS).
- IAM policies are JSON documents describing allowed or denied actions.
Use the root user only for tasks that specifically require it. Protect it with multi-factor authentication (MFA), do not create root access keys, and use an administrative role or federated access for regular work.
IAM request flow: a diagram in words
Visualise IAM as a security checkpoint:
Person or workload
|
v
Authentication: Who are you?
|
v
Principal: IAM user, assumed role or AWS service
|
v
Authorisation: Which policies apply?
|
v
Decision: Explicit deny, allow or implicit deny
|
v
AWS resource: S3 bucket, EC2 instance, DynamoDB table, etc.Authentication establishes an identity. Authorisation evaluates whether that identity can perform a particular action on a particular resource under the request conditions.
What Is the Difference Between IAM Users and Roles?
An IAM user is a long-term identity in one AWS account, while an IAM role is an assumable identity that supplies temporary credentials. Roles are normally the safer choice for applications, AWS services, federation and cross-account access.
| Feature | IAM user | IAM role |
|---|---|---|
| Credential type | Password or long-term access keys | Temporary STS credentials |
| Typical use | Limited human or legacy access | Workloads, federation and cross-account access |
| Direct sign-in | Can have a console password | Assumed through a trusted identity or service |
| Credential rotation | Access keys require management | Credentials expire automatically |
| Trust policy | Not used | Required |
| Recommended for EC2 applications | No | Yes, through an instance profile |
When should an IAM user be used?
Use IAM users only when a workload or person cannot use federation or roles. For workforce access, AWS IAM Identity Center is generally preferable because it provides centrally managed access and temporary credentials.
An IAM user can have:
- A console password
- Up to two access keys, although unused keys should be removed
- MFA devices
- Identity-based policies attached directly or through groups
Do not place access keys inside source code, container images or public repositories. Where long-term keys are unavoidable, store them securely, monitor their use and rotate them according to your organisation's process.
When should an IAM role be used?
Use a role when an application, AWS service, federated user or another AWS account needs temporary access. A role has a trust policy defining who may assume it and permission policies defining what the resulting role session may do.
Examples include:
- An EC2 application reading an S3 bucket
- A Lambda function writing logs to CloudWatch Logs
- A deployment pipeline updating an ECS service
- An administrator accessing a production account from a central identity account
- A user signing in through IAM Identity Center
These patterns are covered through guided labs in the AWS Solutions Architect course, including role-based access for common AWS architectures.
How Do IAM Policies Work?
An IAM policy is a JSON document containing permission statements. Each statement normally specifies an effect, one or more actions, resources and optional conditions.
Consider this identity-based policy for an application that must read objects from one S3 prefix:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "ReadReportsPrefix",
"Effect": "Allow",
"Action": [
"s3:GetObject"
],
"Resource": "arn:aws:s3:::company-reports/monthly/*"
}
]
}This permits s3:GetObject only for objects below monthly/. It does not allow bucket listing, uploads, deletions or reads from another prefix.
To list that prefix, a separate bucket-level permission is required because s3:ListBucket applies to the bucket ARN:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "ListMonthlyReports",
"Effect": "Allow",
"Action": "s3:ListBucket",
"Resource": "arn:aws:s3:::company-reports",
"Condition": {
"StringLike": {
"s3:prefix": [
"monthly/*"
]
}
}
},
{
"Sid": "ReadMonthlyReports",
"Effect": "Allow",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::company-reports/monthly/*"
}
]
}What are the main types of IAM policies?
AWS evaluates several policy types depending on the identity, account structure, resource and request. Understanding their different purposes prevents incorrect assumptions about effective access.
| Policy type | Attached to or used by | Purpose |
|---|---|---|
| Identity-based policy | User, group or role | Grants permissions to an identity |
| Resource-based policy | Resource such as an S3 bucket or KMS key | Defines which principals can access the resource |
| Permissions boundary | User or role | Sets the maximum permissions an identity-based policy can grant |
| Service control policy | AWS Organizations account or organisational unit | Limits maximum permissions in member accounts |
| Session policy | Role or federated session | Further restricts a temporary session |
| Access control list | Supported resources such as S3 objects | Provides resource-level access in specific services |
AWS-managed policies are maintained by AWS. Customer-managed policies are created and managed within your account, while inline policies are embedded directly in one identity. Customer-managed policies are usually easier to review, version and reuse than inline policies.
How Does AWS Evaluate IAM Permissions?
AWS begins with an implicit deny, looks for applicable allows and then checks for explicit denies. An explicit deny in any applicable policy takes precedence over an allow.
A practical decision sequence is:
Request received
-> Is there an applicable explicit Deny? Yes: Deny
-> Is there an applicable Allow? No: Implicit Deny
-> Do boundaries, session policies or SCPs limit it? Yes: Deny
-> Do all required policy checks permit it? Yes: AllowFor permissions granted through identity-based policies, effective permissions are broadly the intersection of identity policies, permissions boundaries, session policies and applicable service control policies. Resource-based policies and role trust policies add further checks, especially for cross-account access.
A role's trust policy does not grant access to S3, EC2 or other services. It only defines which principal can call an operation such as sts:AssumeRole for that role.
How Do You Create and Assume an IAM Role?
Create a role by defining its trusted principal, attaching only the required permissions and assuming it through STS. The following lab creates a role trusted by a specific IAM user for demonstration purposes.
Create trust-policy.json:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::111122223333:user/lab-user"
},
"Action": "sts:AssumeRole"
}
]
}Create the role:
aws iam create-role \
--role-name ReportsReadRole \
--assume-role-policy-document file://trust-policy.jsonSave the S3 policy from the previous section as reports-read-policy.json, then create and attach it:
aws iam create-policy \
--policy-name ReportsReadPolicy \
--policy-document file://reports-read-policy.json
aws iam attach-role-policy \
--role-name ReportsReadRole \
--policy-arn arn:aws:iam::111122223333:policy/ReportsReadPolicyThe calling user also needs permission to run sts:AssumeRole against this role. After both sides are configured, assume it:
aws sts assume-role \
--role-arn arn:aws:iam::111122223333:role/ReportsReadRole \
--role-session-name reports-labThe output contains an access key, secret access key, session token and expiration time. Configure these as environment variables for the lab shell:
export AWS_ACCESS_KEY_ID="temporary-access-key"
export AWS_SECRET_ACCESS_KEY="temporary-secret-key"
export AWS_SESSION_TOKEN="temporary-session-token"
aws sts get-caller-identityExpected identity output includes an ARN similar to:
arn:aws:sts::111122223333:assumed-role/ReportsReadRole/reports-labThe assumed-role ARN confirms that the shell is using a role session rather than the original user. For production automation, use an AWS SDK credential provider instead of manually copying temporary credentials. Engineers building deployment systems can study related role and pipeline patterns in the AWS DevOps course.
What Does Least Privilege Mean in AWS IAM?
Least privilege means granting only the actions, resources and conditions required for a task. Permissions should be reviewed and reduced as actual usage becomes clear rather than remaining broad indefinitely.
A weak policy might use:
{
"Effect": "Allow",
"Action": "s3:*",
"Resource": "*"
}A least-privilege design asks four questions:
- Which exact API actions are required?
- Which resource ARNs should those actions target?
- Can conditions restrict location, network path, tags or identity context?
- How long is the access needed?
Useful controls include:
- Require MFA for sensitive human actions with
aws:MultiFactorAuthPresent. - Restrict access by resource tags using supported condition keys.
- Use
aws:SourceArnandaws:SourceAccountwhen an AWS service assumes or invokes access on behalf of a resource. - Use VPC endpoint conditions only after confirming the operational impact.
- Separate read, deploy and administrative roles.
- Remove permissions that IAM Access Analyzer identifies as unused after suitable observation and review.
- Use permissions boundaries for delegated IAM administration.
- Use SCPs as organisation-wide guardrails, not as permission grants.
Avoid blindly generating policies from console actions. The console may call supporting read and list APIs, while automation may need a smaller or different permission set.
Security teams also need to connect IAM activity with logs, alerts and incident response. These operational controls are introduced in the Cybersecurity & SOC course.
How Can You Validate and Test an IAM Policy?
Validate policy syntax before deployment, then test expected allowed and denied actions in a non-production environment. Policy simulation is helpful, but a real service call is still important because resource policies, service-specific behaviour and runtime context can affect the result.
Validate an identity policy with IAM Access Analyzer:
aws accessanalyzer validate-policy \
--policy-document file://reports-read-policy.json \
--policy-type IDENTITY_POLICYSimulate selected actions for an IAM role:
aws iam simulate-principal-policy \
--policy-source-arn arn:aws:iam::111122223333:role/ReportsReadRole \
--action-names s3:GetObject s3:DeleteObject \
--resource-arns arn:aws:s3:::company-reports/monthly/report.csvReview the EvalDecision field. In this example, s3:GetObject should be allowed and s3:DeleteObject should not be allowed, assuming no other relevant policies change the decision.
Then run a real test:
aws s3api get-object \
--bucket company-reports \
--key monthly/report.csv \
/tmp/report.csvAlso test a request that should fail. Negative tests confirm that the policy prevents unintended access rather than merely supporting the expected path.
How Do You Troubleshoot IAM Access Denied Errors?
Start by identifying the current principal, denied API action and target resource ARN. Then inspect every relevant policy layer instead of repeatedly adding broader permissions.
Step 1: Confirm the active identity
aws sts get-caller-identityA common problem is using an unexpected CLI profile, stale environment variables or an EC2 role different from the intended role.
Step 2: Capture the exact denied operation
Run the command with debug logging if necessary:
aws s3api get-object \
--bucket company-reports \
--key monthly/report.csv \
/tmp/report.csv \
--debugDebug output can be extensive and may contain request metadata. Store and share it carefully.
Step 3: Check action and resource matching
Confirm that the policy uses the correct API action and ARN format. For S3, bucket operations often require a bucket ARN, while object operations require an object ARN ending in /* or a narrower object path.
Step 4: Check every restricting policy layer
Review:
- Identity-based policies
- Resource-based policies
- Role trust policy for assumption failures
- Permissions boundaries
- Session policies
- AWS Organizations SCPs
- KMS key policies when encrypted data is involved
- VPC endpoint policies where applicable
An S3 policy may allow s3:GetObject, but an object encrypted with a customer-managed KMS key can also require kms:Decrypt and permission through the key policy.
Step 5: Inspect CloudTrail events
Search AWS CloudTrail event history or your CloudTrail Lake/event data store for the denied API request. Check userIdentity, eventSource, eventName, requestParameters and errorMessage to understand which principal made the request and what it attempted.
Common IAM problems
| Symptom | Likely cause | Practical check |
|---|---|---|
AccessDenied on AssumeRole | Caller permission or trust policy missing | Check both sides of role assumption |
| S3 list works but download fails | s3:GetObject missing | Check the object ARN and action |
| S3 download allowed but KMS denies | KMS permission or key policy missing | Review kms:Decrypt and the key policy |
| Policy says allow but request fails | Explicit deny, boundary or SCP | Inspect all applicable policy layers |
| CLI uses the wrong account | Wrong profile or environment credentials | Run aws sts get-caller-identity |
| Temporary credentials suddenly fail | STS session expired | Refresh or assume the role again |
Do not resolve access errors by attaching AdministratorAccess unless full administration is genuinely required. It can hide the original design problem and grant unrelated capabilities.
Summary
AWS IAM provides authentication and authorisation for AWS accounts through users, roles and policies. Prefer temporary role credentials, protect root access, test both allowed and denied actions, and reduce permissions to the minimum required actions and resources.
A reliable IAM workflow is: identify the principal, define the task, write a narrow policy, validate it, test it in a safe environment, inspect logs and review permissions regularly.
To practise IAM, STS, S3 permissions and secure architecture through guided labs, enquire about upcoming batch details for the AWS Solutions Architect course.
Reviewed by Network Rhinos AWS and cloud trainers.
Related reading: Terraform Basics for AWS: Build Your First Resource
