AWS IAM Least-Privilege — Role, Permission Boundary và Access Analyzer
🎯 Mục tiêu: Tạo IAM Role cho EC2 chỉ có quyền đọc một S3 bucket cụ thể; gắn Permission Boundary ngăn escalate; chạy IAM Access Analyzer phát hiện public access.
🧰 Công cụ / nền tảng: AWS CLI (đã config aws configure), AWS Console, tài khoản AWS (free tier đủ).
📦 Chuẩn bị: AWS CLI ≥ 2.x; IAM permission để tạo role và bucket.
▶️ Các bước:
# 1. Tạo S3 bucket test (tên phải unique toàn cầu)
BUCKET="sec-lab-$(date +%s)"
aws s3 mb s3://$BUCKET --region ap-southeast-1
aws s3 cp /etc/hostname s3://$BUCKET/test.txt
echo "Bucket: $BUCKET"
# 2. Tạo Permission Boundary policy — giới hạn trên cùng
cat > boundary.json <<'EOF'
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowS3ReadOnly",
"Effect": "Allow",
"Action": ["s3:Get*", "s3:List*"],
"Resource": "*"
},
{
"Sid": "DenyEverythingElse",
"Effect": "Deny",
"NotAction": ["s3:Get*", "s3:List*"],
"Resource": "*"
}
]
}
EOF
BOUNDARY_ARN=$(aws iam create-policy \
--policy-name S3ReadOnlyBoundary \
--policy-document file://boundary.json \
--query 'Policy.Arn' --output text)
echo "Boundary ARN: $BOUNDARY_ARN"
# 3. Tạo Trust Policy cho EC2
cat > trust.json <<'EOF'
{
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Principal": {"Service": "ec2.amazonaws.com"},
"Action": "sts:AssumeRole"
}]
}
EOF
# 4. Tạo IAM Role với Permission Boundary gắn sẵn
ROLE_ARN=$(aws iam create-role \
--role-name ec2-s3-reader \
--assume-role-policy-document file://trust.json \
--permissions-boundary $BOUNDARY_ARN \
--query 'Role.Arn' --output text)
echo "Role ARN: $ROLE_ARN"
# 5. Tạo inline policy chỉ cho phép đọc bucket cụ thể
cat > s3-policy.json <<EOF
{
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Action": ["s3:GetObject", "s3:ListBucket"],
"Resource": [
"arn:aws:s3:::$BUCKET",
"arn:aws:s3:::$BUCKET/*"
]
}]
}
EOF
aws iam put-role-policy \
--role-name ec2-s3-reader \
--policy-name allow-specific-bucket \
--policy-document file://s3-policy.json
# 6. Kiểm tra effective permission
aws iam simulate-principal-policy \
--policy-source-arn $ROLE_ARN \
--action-names s3:GetObject \
--resource-arns arn:aws:s3:::$BUCKET/test.txt \
--query 'EvaluationResults[0].EvalDecision'
# Expected: "allowed"
aws iam simulate-principal-policy \
--policy-source-arn $ROLE_ARN \
--action-names s3:DeleteObject \
--resource-arns arn:aws:s3:::$BUCKET/test.txt \
--query 'EvaluationResults[0].EvalDecision'
# Expected: "explicitDeny" (bị Permission Boundary chặn)
# 7. Bật IAM Access Analyzer (region-scoped)
aws accessanalyzer create-analyzer \
--analyzer-name sec-lab-analyzer \
--type ACCOUNT \
--region ap-southeast-1
# 8. Xem findings (S3 bucket public, IAM role cross-account, etc.)
sleep 10
aws accessanalyzer list-findings \
--analyzer-name sec-lab-analyzer \
--region ap-southeast-1 \
--query 'findings[*].{Type:findingType,Resource:resource,Status:status}' \
--output table
✅ Kết quả mong đợi: simulate-principal-policy trả về allowed cho GetObject và explicitDeny cho DeleteObject. Access Analyzer tạo thành công; nếu bucket có public access sẽ hiện finding. Role không thể leo thang do Permission Boundary.
🧹 Cleanup:
aws s3 rb s3://$BUCKET --force
aws iam delete-role-policy --role-name ec2-s3-reader --policy-name allow-specific-bucket
aws iam delete-role --role-name ec2-s3-reader
aws iam delete-policy --policy-arn $BOUNDARY_ARN
aws accessanalyzer delete-analyzer --analyzer-name sec-lab-analyzer --region ap-southeast-1
rm -f boundary.json trust.json s3-policy.json