This is who IAM
Posted on May 27, 2025 • 5 min read • 891 wordsAWS Identity and Access Management (IAM) is a core service that allows fine-grained access control to AWS resources. When properly configured, IAM ensures security, compliance, and productivity in cloud usage.

IAM is based on entities and policies.
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "s3:ListBucket",
"Resource": "arn:aws:s3:::example_bucket"
}
]
}This IAM policy allows an AWS entity (user, role, or group) to list the objects in a specific S3 bucket named example_bucket. It uses the standard IAM version format (2012-10-17) and allows the s3:ListBucket action on the resource identified by its ARN. It lets the entity see the list of objects (names, sizes, metadata), but not read or modify them—unless additional permissions are granted. This minimal policy is often used for inventory or bucket navigation via the AWS Console or API.
IAM relies on the Least Privilege Principle: each entity gets only the permissions strictly necessary.
Some AWS services allow fine-grained resource access control. Examples:
| Element | Global IAM Policy | Service-Level Control |
|---|---|---|
| S3 Bucket Policy | ❌ | ✅ |
| EC2 | ✅ | ❌ |
| Lambda | ✅ | ✅ |
| CloudWatch Logs | ✅ | ✅ |
Use Cognito to manage authentication, then IAM assigns temporary roles using JWTs to access S3 or DynamoDB.
In an EKS cluster, assign an IAM role to a Kubernetes service to limit access to only the necessary S3 buckets.
IAM integrates with AWS CloudTrail to log every API call—useful for:
Conditional IAM policies add dynamic and contextual rules to permissions. Useful for restricting access based on:
A Condition clause is added within a Statement block. Example:
{
"Effect": "Allow",
"Action": "s3:*",
"Resource": "*",
"Condition": {
"IpAddress": {
"aws:SourceIp": "203.0.113.0/24"
}
}
}This IAM policy allows all S3 actions ("s3:*") on all resources only if the request originates from an IP address within 203.0.113.0/24. The Condition clause restricts access based on the source IP (aws:SourceIp), reinforcing security by limiting permissions to a specific network—like a corporate office or VPN.
| Condition Type | Operator | Example (Key) |
|---|---|---|
| Source IP | IpAddress | aws:SourceIp |
| Time | DateLessThan / DateGreaterThan | aws:CurrentTime |
| MFA Enabled | Bool | aws:MultiFactorAuthPresent |
| Tags | StringEquals | aws:RequestTag/Project |
Case 1: Access only during business hours
"Condition": {
"DateGreaterThan": { "aws:CurrentTime": "2025-04-09T08:00:00Z" },
"DateLessThan": { "aws:CurrentTime": "2025-04-09T18:00:00Z" }
}Case 2: Deny access without MFA
"Condition": {
"BoolIfExists": {
"aws:MultiFactorAuthPresent": "true"
}
}Case 3: Permission based on tags
"Condition": {
"StringEquals": {
"aws:RequestTag/Environment": "prod"
}
}A multi-account structure offers:
However, it increases permission complexity—where AWS Organizations helps.
AWS Organizations lets you:
SCPs define what a member account is allowed to do, regardless of local IAM policies.
SCPs apply at the account or OU level, filtering effective permissions.
| Action | IAM Policy | SCP | Final Access |
|---|---|---|---|
| Allow EC2 Start | ✅ | ❌ | ❌ |
| Deny EC2 Stop | ✅ | ❌ | ✅ |
| Deny S3 Delete | ❌ | ❌ | ❌ |
🔐 Note: IAM policies can never override an SCP.
prod, dev, sandbox.sandbox:{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Deny",
"Action": "ec2:*",
"Resource": "*"
}
]
}dev.To allow an entity in Account A to access resources in Account B:
AssumeRole policy.Example in Account B:
{
"Effect": "Allow",
"Principal": { "AWS": "arn:aws:iam::123456789012:root" },
"Action": "sts:AssumeRole"
}AWS IAM is a foundational pillar of any cloud security strategy. Though initially complex, it’s essential for maintaining a secure, structured, and scalable AWS environment. Mastering IAM concepts and best practices ensures your cloud infrastructure is built on strong, flexible access controls.