This case study demonstrates the implementation of least privilege access controls across a three-tier web application architecture (Web → Application → Database) using AWS IAM. Building on a previously secured account foundation (Lab 1 case study), this project created human IAM groups and service roles that strictly limit each tier and team persona to only the permissions they need to function, while explicitly blocking cross-tier privilege escalation paths.
Key Outcomes:
-
WebOps users can manage web servers but cannot touch databases or IAM
-
AppDev users can deploy application code but lack infrastructure-wide permissions
-
DbAdmin users can manage RDS but cannot modify web/app resources
-
Service roles (WebTierRole, AppTierRole, DbTierRole) follow identical least-privilege boundaries
-
CloudTrail audit logs prove both successful operations and denied unauthorized attempts
2. Problem Statement & Architecture Context
2.1 The Risk of Broad Permissions
In typical cloud environments, development and operations teams often receive overly broad IAM permissions (AdministratorAccess, PowerUserAccess), creating significant privilege escalation risks. A compromised web server with broad EC2 permissions could delete production databases. An application developer with RDS admin rights could access customer PII inappropriately.
2.2 Three-Tier Reference Architecture
Internet → Web Tier (EC2, ALB, S3 static) → App Tier (EC2, SQS) → DB Tier (RDS)
Persona Requirements Mapping:
| Tier/Persona | Allowed Actions | Prohibited Actions |
|---|---|---|
| WebOps | EC2 web server mgmt, S3 static deploy, CloudWatch logs | RDS access, IAM changes, network config |
| AppDev | App server deploy, SQS queue mgmt, app metrics | EC2 infra mgmt, RDS control plane, IAM |
| DbAdmin | RDS backups/parameters, DB monitoring | EC2/S3 access, IAM policy changes |

3. Technical Implementation
3.1 IAM Groups for Human Users
Created three dedicated IAM groups:
-
WebOpsGrouptextUsers: webops-user1, webops-user2
Policies: EC2ReadOnlyAccess + custom WebTierPolicy
-
AppDevGrouptextUsers: appdev-user1, appdev-user2
Policies: Custom AppTierPolicy + CloudWatchReadOnlyAccess
-
DbAdminGrouptextUsers: dbadmin-user1
Policies: AmazonRDSReadOnlyAccess + custom DbTierPolicy

3.2 Service Roles for Application Tiers
EC2 instance roles with strict trust relationships:
WebTierRole → Trusted: EC2 instances in web subnet only
AppTierRole → Trusted: EC2 instances in app subnet only
DbTierRole → Trusted: EC2 instances in DB subnet only
Sample WebTierRole Policy (abbreviated):
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:GetObject",
"logs:PutLogEvents",
"elasticloadbalancing:Describe*"
],
"Resource": [
"arn:aws:s3:::web-static-bucket/*",
"arn:aws:logs:*:*:log-group:/aws/ec2/web*"
]
}
]
}
3.3 Key Design Principles Applied
-
Separation of Duties – No single identity can perform web + app + DB operations
-
Explicit Deny Patterns – Missing permissions = automatic denial
-
Resource-Level Specificity – Permissions scoped to specific ARNs, not
"*" -
Audit Everything – CloudTrail captures both allowed and denied actions
4. Validation & Test Results
4.1 Positive Test Cases (Expected Success)
| Persona | Test Action | Result |
|---|---|---|
| WebOps | StopInstances on web EC2 |
✅ Success |
| WebOps | PutObject to web S3 bucket |
✅ Success |
| AppDev | UpdateCodeDeployment app server |
✅ Success |
| DbAdmin | ModifyDBInstance RDS backup |
✅ Success |
4.2 Negative Test Cases (Expected Failure)
| Persona | Unauthorized Action | Result |
|---|---|---|
| WebOps | DeleteDBInstance RDS |
❌ AccessDenied |
| AppDev | StopInstances web EC2 |
❌ AccessDenied |
| DbAdmin | PutBucketPolicy S3 |
❌ AccessDenied |

4.3 CloudTrail Audit Evidence
All actions (successful + denied) were captured in CloudTrail with:
-
UserIdentity → Correct IAM user/group
-
EventName → Specific API call attempted
-
AccessDenied → Policy evaluation details for failures
-
SourceIPAddress → Test workstation IP

5. Architecture Visualization
┌─────────────────┐ IAM Groups & Roles
│ WebOps User │──┐
└──────────┬──────┘ │ WebTierRole (EC2)
│ │
┌─────▼─────┐ │
│ Web Tier │◄───┘ [EC2, ALB, S3 static]
│ SG │
└─────┬─────┘
│
┌─────▼─────┐
│ App Tier │◄── AppTierRole (EC2)
│ SG │ AppDev Group
└─────┬─────┘
│
┌─────▼─────┐
│ DB Tier │◄── DbTierRole (RDS)
│ SG │ DbAdmin Group
└───────────┘
│
┌────▼────┐
│CloudTrail│← Audit Trail (Success + Denied)
└─────────┘

6. Business Impact & Risk Reduction
6.1 Attack Surface Reduction
BEFORE: Single admin user → Full account access
AFTER: 9 identities (3 groups × 3 users) → Tier-specific access only
Quantified improvements:
-
Privilege escalation paths: Reduced from “anyone → everything” to “tier → adjacent tier only”
-
Compromise blast radius: Web server breach cannot reach production database
-
Audit granularity: Every action traceable to specific user + role + tier
6.2 Compliance Alignment
-
CIS AWS Benchmarks: 1.1, 1.2, 2.1 (least privilege, RBAC)
-
NIST 800-53: AC-6 (Least Privilege), AU-2 (Audit Events)
-
SOC 2: CC6.1 (Access Control), CC7.2 (Monitoring)
7. Lessons Learned & Recommendations
7.1 Key Takeaways
-
Start with personas, not technology – Define “what does WebOps actually need to do daily?” before writing policies
-
Test both allow AND deny – Policy validation requires proving what users cannot do
-
CloudTrail is your proof – Screenshots of denied actions + matching audit logs = ironclad evidence
7.2 Production Enhancements
Phase 2 Roadmap:
□ Just-in-Time (JIT) elevation via IAM Access Analyzer
□ Policy as Code (OPA/Terraform Sentinel) validation
□ Automated permission boundary enforcement
□ Cross-account role federation
8. Technical Skills Demonstrated
✅ AWS IAM Advanced
-
Custom policy authoring with resource-level granularity
-
Group-based RBAC implementation
-
Cross-service permission boundaries
✅ Security Testing Methodology
-
Positive/negative test case design
-
Policy validation via denied actions
-
Audit log correlation
✅ Architecture Design
-
Multi-tier least privilege modeling
-
Service role trust relationships
-
Separation of duties mapping