IAM Best Practices & Least Privilege
Overview
The principle of least privilege is the foundation of AWS security. It states that identities should only be permitted to perform the smallest set of actions necessary to fulfill a specific task - nothing more, nothing less.
Implementing IAM best practices is essential for passing the SAA-C03 exam and building secure AWS architectures. AWS continuously updates its security recommendations, and understanding how to apply least privilege effectively distinguishes competent architects from those who create security vulnerabilities.
Core Principle
Least Privilege = Minimum Permissions Required. Start with zero permissions and add only what's needed. When in doubt, deny access and wait for specific requests to grant permissions.
Expect questions asking you to identify the 'most secure' or 'best practice' approach. The answer almost always involves least privilege, temporary credentials, and avoiding long-term access keys.
Architecture Diagram
The following diagram illustrates the IAM security layers and how best practices apply at each level:

Key Concepts
The Principle of Least Privilege
Least Privilege
Least privilege means granting only the minimum permissions required to perform a task. This principle:
- Reduces blast radius - If credentials are compromised, damage is limited
- Simplifies auditing - Easier to understand who can do what
- Improves compliance - Meets regulatory requirements (SOC 2, HIPAA, PCI-DSS)
- Enables accountability - Clear ownership of permissions
Implementation Strategy:
- Start with an empty policy (deny all)
- Add permissions as needed based on actual requirements
- Use IAM Access Analyzer to identify unused permissions
- Regularly review and remove unnecessary access
Temporary Credentials vs Long-Term Credentials
Credential Types
AWS supports two types of credentials:
Temporary Credentials (Preferred):
- Automatically expire after a set time (15 minutes to 12 hours)
- Automatically rotated by AWS
- Cannot be embedded in code
- Provided via IAM roles and STS
Long-Term Credentials (Avoid When Possible):
- Access keys that never expire unless rotated manually
- Passwords for console access
- Must be manually rotated and managed
- Higher risk if compromised
Credential Comparison
| Aspect | Temporary Credentials | Long-Term Credentials |
|---|---|---|
| Expiration | Automatic (configurable) | Never (manual rotation) |
| Rotation | Automatic by AWS | Manual process required |
| Storage Risk | Never stored | Can be leaked in code/logs |
| Use Case | AWS workloads, federation | External systems, CLI users |
| Security Level | High | Lower |
| Recommended | Yes - preferred approach | Only when necessary |
IAM Access Analyzer
IAM Access Analyzer
IAM Access Analyzer is a powerful tool for implementing least privilege. It provides:
Policy Generation:
- Analyzes CloudTrail logs to see what actions were actually used
- Generates least-privilege policies based on real access patterns
- Eliminates guesswork in policy creation
Access Analysis:
- Identifies resources shared with external entities
- Detects public access to S3 buckets, KMS keys, etc.
- Continuous monitoring for permission changes
Policy Validation:
- Validates policy grammar and syntax
- Checks against 100+ security best practices
- Provides actionable recommendations
How It Works
Implementing Least Privilege Step-by-Step

Step 1: Start with AWS Managed Policies
Begin with AWS managed policies for common use cases, then refine:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:*"
],
"Resource": "*"
}
]
}Step 2: Analyze and Reduce
Use IAM Access Analyzer to see actual usage, then create a refined policy:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowSpecificS3Actions",
"Effect": "Allow",
"Action": [
"s3:GetObject",
"s3:PutObject",
"s3:ListBucket"
],
"Resource": [
"arn:aws:s3:::my-app-bucket",
"arn:aws:s3:::my-app-bucket/*"
],
"Condition": {
"StringEquals": {
"aws:RequestedRegion": "us-east-1"
}
}
}
]
}Step 3: Add Conditions for Extra Security
Conditions provide granular control over when policies apply:
Common IAM Conditions
| Condition Key | Use Case | Example |
|---|---|---|
| aws:SourceIp | Restrict to corporate IP range | Only allow from 10.0.0.0/8 |
| aws:RequestedRegion | Limit to specific regions | Only allow us-east-1, us-west-2 |
| aws:PrincipalTag | Attribute-based access control | Allow if department=engineering |
| aws:MultiFactorAuthPresent | Require MFA for sensitive actions | Only allow if MFA authenticated |
| aws:SecureTransport | Require HTTPS | Deny if request not over TLS |
| s3:x-amz-acl | Prevent public objects | Deny if ACL is public-read |
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "SecureS3Access",
"Effect": "Allow",
"Action": "s3:*",
"Resource": "arn:aws:s3:::sensitive-data/*",
"Condition": {
"Bool": {
"aws:MultiFactorAuthPresent": "true",
"aws:SecureTransport": "true"
},
"IpAddress": {
"aws:SourceIp": "10.0.0.0/8"
}
}
}
]
}Best Practices Checklist
1. Use Federation and IAM Identity Center
Human User Access
Do: Use IAM Identity Center (formerly AWS SSO) for human users
- Centralized access across multiple AWS accounts
- Integrates with corporate identity providers (Okta, Azure AD, etc.)
- Provides temporary credentials automatically
Don't: Create individual IAM users for each person
- Hard to manage at scale
- Long-term credentials increase risk
- No centralized visibility
2. Use IAM Roles for Workloads
Workload Access
For AWS Compute (EC2, Lambda, ECS):
- Attach IAM roles directly to compute resources
- AWS delivers temporary credentials automatically
- Credentials rotate automatically every few hours
For External Workloads:
- Use IAM Roles Anywhere with X.509 certificates
- Use OIDC federation for Kubernetes workloads
- Use SAML federation for enterprise applications
3. Require MFA for Privileged Access
MFA Implementation
| User Type | MFA Requirement | Implementation |
|---|---|---|
| Root Account | Required - Highest Priority | Hardware MFA device or passkey |
| Admin Users | Required for console and API | Virtual MFA or passkey |
| Power Users | Required for sensitive operations | Conditional MFA policy |
| Read-Only Users | Recommended | Virtual MFA app |
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowAllActionsWithMFA",
"Effect": "Allow",
"Action": "*",
"Resource": "*",
"Condition": {
"Bool": {
"aws:MultiFactorAuthPresent": "true"
}
}
},
{
"Sid": "AllowBasicActionsWithoutMFA",
"Effect": "Allow",
"Action": [
"iam:GetAccountPasswordPolicy",
"iam:ListMFADevices"
],
"Resource": "*"
}
]
}4. Regular Access Reviews
Continuous Improvement
Review Frequency:
- Quarterly: Review all IAM users, roles, and policies
- After org changes: Review when employees join, leave, or change roles
- Continuously: Monitor IAM Access Analyzer findings
What to Review:
- Last accessed information for users and roles
- Unused permissions that can be removed
- External access to resources
- Credential age and rotation status
5. Use Permissions Boundaries
Permissions Boundaries
Permissions boundaries set the maximum permissions that identity-based policies can grant. They act as a "ceiling" on permissions.
Use Cases:
- Allow developers to create IAM roles without granting admin access
- Delegate IAM administration safely
- Prevent privilege escalation
Key Point: Permissions boundaries don't grant permissions - they only limit them. The effective permissions are the intersection of the identity policy AND the boundary.
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowedServices",
"Effect": "Allow",
"Action": [
"s3:*",
"dynamodb:*",
"lambda:*",
"logs:*"
],
"Resource": "*"
},
{
"Sid": "DenyIAMChanges",
"Effect": "Deny",
"Action": [
"iam:*",
"organizations:*"
],
"Resource": "*"
}
]
}Common Exam Scenarios
Exam Scenarios and Solutions
| Scenario | Best Practice Solution | Why |
|---|---|---|
| Company wants to grant AWS access to employees using corporate credentials | Use IAM Identity Center with SAML federation | Centralized management, temporary credentials, no IAM users needed |
| Application on EC2 needs to access multiple AWS services | Create IAM role with specific permissions, attach to EC2 | Temporary credentials, automatic rotation, no access keys |
| Developer needs to create IAM roles for Lambda functions | Grant iam:CreateRole with permissions boundary | Allows delegation while preventing privilege escalation |
| Audit reveals unused permissions in IAM policies | Use IAM Access Analyzer to generate least-privilege policies | Reduces attack surface, improves compliance |
| External vendor needs temporary access to S3 bucket | Create cross-account role with time-limited trust policy | Temporary access, auditable, can be revoked instantly |
| Prevent any IAM user from accessing production without MFA | Add MFA condition to all production resource policies | Defense in depth, protects sensitive resources |
Common Pitfalls
Pitfall 1: Starting with Broad Permissions
Mistake: Creating policies with "Action": "*" or "Resource": "*" to "get things working" and planning to restrict later.
Why it's dangerous:
- Rarely gets restricted (technical debt)
- Creates significant security exposure
- May violate compliance requirements
Correct Approach:
- Start with zero permissions
- Add specific actions and resources as needed
- Use IAM Access Analyzer to identify exact requirements
Pitfall 2: Not Using Conditions
Mistake: Granting permissions without conditions when conditions would add security.
Why it matters:
- Conditions are free additional security
- Can prevent entire classes of attacks
- Show security maturity to auditors
Correct Approach:
- Always consider: source IP, MFA, secure transport, regions
- Add conditions even if they seem redundant
- Review AWS global condition keys for applicable options
Pitfall 3: Ignoring Resource-Level Permissions
Mistake: Using "Resource": "*" when the action supports resource-level permissions.
Why it matters:
- Many actions support specific resource ARNs
- Using
*grants access to ALL resources of that type - Significantly increases blast radius
Correct Approach:
- Check AWS documentation for resource-level permission support
- Use specific ARNs whenever possible
- Use wildcards only for the specific part that varies (e.g.,
arn:aws:s3:::bucket/*)
Pitfall 4: Not Reviewing Access Regularly
Mistake: Setting up permissions once and never reviewing them.
Why it matters:
- Permissions accumulate over time
- Employee roles change but permissions don't
- Unused access increases risk without benefit
Correct Approach:
- Schedule quarterly access reviews
- Use last accessed information to identify stale permissions
- Remove access immediately when no longer needed
Test Your Knowledge
What is the FIRST step in implementing least privilege?
Which AWS service helps generate least-privilege policies based on actual usage?
A company wants to allow developers to create IAM roles but prevent them from creating admin-level roles. What should they use?
Which credential type should be used for an application running on EC2?
Related Services
Quick Reference
IAM Best Practices Summary
Best Practices Quick Reference
| Practice | Priority | Implementation |
|---|---|---|
| Use federation for humans | Critical | IAM Identity Center + IdP integration |
| Use roles for workloads | Critical | Attach roles to EC2, Lambda, ECS |
| Require MFA | Critical | Enable for all console users |
| Apply least privilege | Critical | Start with zero, add as needed |
| Use conditions | High | IP, MFA, region, secure transport |
| Regular access reviews | High | Quarterly + after org changes |
| Remove unused access | High | Use last accessed information |
| Use permissions boundaries | Medium | For delegated IAM administration |
Common Condition Keys
aws:SourceIp - Restrict by IP address/range
aws:MultiFactorAuthPresent - Require MFA
aws:SecureTransport - Require HTTPS
aws:RequestedRegion - Limit to specific regions
aws:PrincipalTag/* - Attribute-based access control
aws:CurrentTime - Time-based restrictions
aws:TokenIssueTime - Credential age checks