Dịch vụ bảo mật: WAF, Shield, GuardDuty, Inspector, Macie, Security Hub, Cognito, IAM Identity Center
Tiếp đi: các dịch vụ bảo mật. Sáng nay log của shop-alb có hàng nghìn request /login từ cùng một dải IP trong vài phút, kèm vài request kiểu ?id=1' OR 1=1. IAM và Security Group mình đã làm kỹ rồi, nhưng chuyện này nằm ở tầng HTTP. AWS có gì để chặn và để phát hiện sớm những thứ như vậy?
Bạn vừa gặp hai loại việc khác nhau: chặn ở biên (brute force, SQL injection đi vào qua ALB) và phát hiện (có ai đang làm gì lạ trong tài khoản không). Bài này gom các dịch vụ bảo mật "có tên riêng" của AWS mà Domain 3 SAA-C03 (Design Secure Architectures, 30% đề, lớn nhất) hay hỏi, chia theo đúng câu hỏi chúng trả lời. IAM, KMS, VPC đã học ở 22.2, 22.3, 22.14; bài này không lặp.
1. Bài toán: shop-app lộ ra Internet qua ALB và CloudFront
Internet ──► CloudFront (assets) ──► S3 shop-app-assets
Internet ──► shop-alb :443 ──► shop-asg :8080 ──► shop-db / shop-cache
Những gì shop-alb-sg cho qua: TCP 80/443 từ 0.0.0.0/0. Nghĩa là:
- brute force /login : hợp lệ về mạng, SG không chặn
- SQL injection trong query string : hợp lệ về mạng
- bot cào giá sản phẩm 1000 req/s : hợp lệ về mạng
- DDoS SYN flood : AWS tự chặn phần lớn (Shield Standard)
- DDoS Layer 7 (HTTP flood) : ALB vẫn nhận, EC2 vẫn tốn CPU
Và ở phía trong: access key bị lộ lên GitHub, ai đó gọi API từ IP lạ, EC2 bị cài crypto miner, bucket S3 có file chứa số thẻ. IAM và SG đúng vẫn không nói cho bạn biết việc đó đang diễn ra.
2. Vấn đề: SG/NACL làm việc ở Layer 3–4, còn tấn công ở Layer 7 và ở hành vi
- Security Group chỉ biết IP, port, protocol. Không đọc được URL, header, body.
- Rate limit viết trong Spring (bucket4j, Redis) chỉ bảo vệ sau khi request đã tới EC2, đã tốn CPU và kết nối.
- CloudTrail ghi lại mọi API call (22.15) nhưng không ai đọc hàng triệu dòng để tìm cái bất thường.
- Vulnerability trong AMI, trong jar (log4j kiểu cũ) không ai quét định kỳ.
- Dữ liệu nhạy cảm trong S3 không ai biết nằm ở đâu.
- Tự xây đăng nhập người dùng (user/pass, social login, MFA) là việc tốn công và dễ sai.
3. Giải pháp: bản đồ dịch vụ bảo mật theo câu hỏi chúng trả lời
| Câu hỏi | Dịch vụ | Một dòng mô tả | Từ khóa đề thi |
|---|---|---|---|
| Chặn request HTTP xấu? | AWS WAF | Web ACL gồm rule, gắn vào CloudFront, ALB, API Gateway, AppSync, Cognito; managed rule group (SQLi, XSS, bot), rate-based rule, geo match, IP set | "SQL injection", "cross-site scripting", "rate limit per IP", "block country", "Layer 7" |
| Chống DDoS? | Shield Standard / Advanced | Standard: miễn phí, tự động, Layer 3/4. Advanced: trả phí tháng, Layer 7, DDoS Response Team 24/7, bảo hiểm chi phí scale do tấn công, WAF free | "DDoS protection", "cost protection", "24/7 response team" |
| Có ai làm gì lạ trong account? | GuardDuty | Threat detection: phân tích CloudTrail, VPC Flow Logs, DNS logs, EKS audit, S3 data events, RDS login, Lambda network bằng ML + threat intel; không cần cài agent (có agent tùy chọn cho Runtime Monitoring) | "detect compromised credentials", "crypto mining", "unusual API calls", "intelligent threat detection" |
| EC2/container/Lambda có lỗ hổng? | Inspector | Quét CVE và network reachability trên EC2 (qua SSM agent), image ECR, Lambda function; liên tục, có điểm risk | "software vulnerabilities", "CVE", "unintended network exposure", "scan ECR images" |
| S3 có dữ liệu nhạy cảm không? | Macie | ML phát hiện PII, thẻ tín dụng, credential trong S3; báo bucket public, không encrypt | "PII in S3", "sensitive data discovery", "credit card numbers" |
| Gom hết finding một chỗ? | Security Hub | Tập hợp finding từ GuardDuty, Inspector, Macie, Config, IAM Access Analyzer, Firewall Manager, partner; chấm điểm theo standard (AWS Foundational Security Best Practices, CIS, PCI DSS); format ASFF; automation với EventBridge | "central view of security posture", "compliance standards", "aggregate findings across accounts" |
| Điều tra sâu finding? | Detective | Xây graph hành vi từ CloudTrail/Flow Logs/GuardDuty để điều tra nguyên nhân gốc | "root cause analysis", "investigate security findings" |
| Đăng nhập cho người dùng cuối (customer)? | Cognito | User pool = user directory + OIDC/OAuth2 server (sign-up, MFA, social login, hosted UI, JWT). Identity pool = đổi token thành credential AWS tạm thời để gọi S3/DynamoDB trực tiếp | "mobile/web app users", "social identity providers", "temporary AWS credentials for app users" |
| Đăng nhập cho nhân viên vào AWS Console / CLI? | IAM Identity Center (SSO) | Một cổng SSO cho nhiều account trong Organizations; permission set; kết nối Entra ID, Okta, Directory Service | "workforce access to multiple accounts", "single sign-on", "existing corporate IdP" |
| Cần Active Directory trên AWS? | Directory Service | AWS Managed Microsoft AD (AD thật, trust với on-prem), AD Connector (proxy về AD on-prem), Simple AD (Samba, nhỏ) | "Active Directory", "trust relationship", "on-premises AD without caching credentials" |
| WAF/Shield/SG cho hàng chục account? | Firewall Manager | Áp chính sách WAF, Shield Advanced, SG, Network Firewall, Route 53 DNS Firewall cho toàn Organization | "centrally manage WAF rules across accounts" |
| Firewall tầng mạng trong VPC? | Network Firewall | Stateful/stateless rule, IDS/IPS (Suricata rule), domain filtering cho egress | "inspect traffic between VPCs", "egress domain filtering", "intrusion prevention" |
| Ai có quyền truy cập tài nguyên từ bên ngoài account? | IAM Access Analyzer | Phân tích resource policy (S3, KMS, IAM role, SQS…) chỉ ra truy cập từ account/public ngoài zone of trust; sinh policy từ CloudTrail | "identify resources shared externally", "generate least-privilege policy" |
| Chứng chỉ, bằng chứng audit? | Artifact / Audit Manager | Artifact: tải báo cáo compliance của AWS (SOC, PCI). Audit Manager: tự thu evidence cho framework | "download AWS compliance reports", "collect audit evidence" |
3.1 WAF: cấu trúc
Web ACL (gắn vào 1 ALB / CloudFront / API Gateway stage)
├─ Default action: Allow (hoặc Block)
├─ Rule 0 : AWSManagedRulesCommonRuleSet (OWASP top 10 cơ bản, XSS)
├─ Rule 1 : AWSManagedRulesSQLiRuleSet (SQL injection)
├─ Rule 2 : AWSManagedRulesKnownBadInputsRuleSet (log4j JNDI, path traversal)
├─ Rule 3 : AWSManagedRulesAmazonIpReputationList (IP xấu theo threat intel)
├─ Rule 4 : rate-based rule: > 300 req / 5 phút cùng IP tới /login → Block
├─ Rule 5 : geo match: country not in [VN, SG] → Count (chỉ đếm để quan sát)
└─ Rule 6 : custom: header User-Agent chứa "python-requests" → CAPTCHA / Challenge
Mỗi rule có action: Allow / Block / Count / CAPTCHA / Challenge; có "capacity" (WCU), ACL tối đa 5.000 WCU
Log: ra CloudWatch Logs (log group bắt đầu bằng aws-waf-logs-), S3, hoặc Firehose
- Rate-based rule: cửa sổ đánh giá 1, 2, 5 hoặc 10 phút, ngưỡng tối thiểu theo cửa sổ (từ vài chục request); aggregate theo IP, forwarded IP (sau CloudFront), header, cookie, query… Đây là câu trả lời đề thi cho "limit requests per IP", "protect login from brute force".
- Managed rule group: do AWS hoặc Marketplace vendor duy trì, tự cập nhật. Có Bot Control (trả phí thêm) và Account Takeover Prevention cho trang login.
- Scope:
REGIONAL(ALB, API Gateway, Cognito, AppSync trong region) hoặcCLOUDFRONT(phải tạo ở us-east-1). - WAF không gắn được vào NLB hay EC2 trực tiếp. Đề cho NLB mà hỏi WAF → sai, phải đổi sang ALB hoặc đặt CloudFront phía trước.
3.2 Shield
| Shield Standard | Shield Advanced | |
|---|---|---|
| Giá | Miễn phí, tự bật cho mọi account | Phí tháng cố định (khoảng vài nghìn USD) + cam kết 1 năm, kiểm tra pricing page |
| Bảo vệ | Layer 3/4: SYN/UDP flood, reflection | Thêm Layer 7, phát hiện theo ứng dụng, health-based detection |
| Tài nguyên | Mọi thứ | CloudFront, Route 53, Global Accelerator, ALB/CLB, NLB, Elastic IP |
| Thêm | — | Shield Response Team (SRT) 24/7, DDoS cost protection (hoàn phí scale do tấn công), WAF & Firewall Manager không tính phí, Proactive engagement |
3.3 GuardDuty: bật một nút, không agent (trừ Runtime Monitoring tùy chọn). Nguồn: CloudTrail management events, S3 data events, VPC Flow Logs, Route 53 DNS logs, EKS audit logs, RDS login activity, Lambda network, Malware Protection cho EBS/S3. Finding có severity Low/Medium/High và loại như UnauthorizedAccess:IAMUser/InstanceCredentialExfiltration.OutsideAWS, CryptoCurrency:EC2/BitcoinTool.B!DNS. Có 30 ngày trial miễn phí, sau đó tính theo lượng log phân tích. Multi-account: delegated administrator trong Organizations.
3.4 Cognito user pool vs identity pool (bẫy kinh điển)
User Pool (Authentication: "bạn là ai") Identity Pool (Authorization vào AWS: "bạn được gọi gì")
─────────────────────────────────────────── ────────────────────────────────────────────────
- Lưu user, password, attribute - KHÔNG lưu user
- Sign-up, sign-in, MFA, forgot password - Nhận token từ: Cognito user pool, Google,
- Hosted UI, OAuth2/OIDC server Facebook, Apple, SAML, OIDC, hoặc guest (unauth)
- Federation: Google, Facebook, Apple, SAML - Đổi token → STS AssumeRoleWithWebIdentity
- Trả JWT: id_token, access_token, refresh - Trả credential AWS tạm (AccessKey/Secret/Session)
- App/Spring dùng như một OIDC provider - App gọi S3/DynamoDB trực tiếp, phân quyền bằng
(resource server validate JWT) IAM role + policy variable ${cognito-identity.amazonaws.com:sub}
So với Keycloak (chương 12): user pool làm việc của Keycloak realm (IdP, OIDC, MFA, social login) nhưng do AWS quản lý, ít tùy biến flow hơn; Spring Boot cấu hình spring.security.oauth2.resourceserver.jwt.issuer-uri trỏ sang Cognito giống hệt cách trỏ sang Keycloak (spring-security 08). Identity pool thì Keycloak không có tương đương: nó là cầu nối sang IAM.
3.5 IAM Identity Center vs Cognito vs IAM user
| Ai đăng nhập | Dùng | Ghi chú |
|---|---|---|
| Nhân viên vào Console/CLI nhiều account | IAM Identity Center | Permission set → tạo role ở account thành viên; nguồn user: built-in, Entra ID, Okta, AD |
| Khách hàng vào app shop-app | Cognito user pool | Hàng triệu user, social login, hosted UI |
| Khách hàng cần upload thẳng lên S3 | Cognito identity pool (+ user pool) | Credential tạm theo role |
| App/CI cần gọi AWS | IAM role (EC2/ECS/IRSA, OIDC GitHub Actions) | Không IAM user + access key dài hạn |
| Legacy app cần Kerberos/LDAP, Windows domain join | Directory Service (Managed AD) | Trust với AD on-prem; AD Connector nếu không muốn AD trên cloud |
4. Cấu hình từng bước: WAF trước shop-alb
Bước 1: IP set (danh sách IP cần block hẳn, ví dụ dải đang brute force):
aws wafv2 create-ip-set --name shop-blocklist --scope REGIONAL \
--ip-address-version IPV4 --addresses 203.0.113.0/24 \
--tags Key=Project,Value=shop-app Key=Env,Value=lab \
--region $AWS_REGION --profile shop-lab
Bước 2: Web ACL với managed rule + rate-based rule (file JSON ở lab bên dưới).
Bước 3: Gắn vào ALB:
aws wafv2 associate-web-acl --web-acl-arn $WEB_ACL_ARN \
--resource-arn $ALB_ARN --region $AWS_REGION --profile shop-lab
Bước 4 (Java): đọc đúng IP client sau WAF/ALB. WAF rate-limit theo IP nguồn tới ALB; nếu còn CloudFront phía trước thì dùng forwarded IP (header X-Forwarded-For). Spring Boot cũng nên hiểu header này để log và rate limit tầng app nhất quán:
# application.yml
server:
forward-headers-strategy: framework # tin X-Forwarded-* từ ALB
tomcat:
remoteip:
internal-proxies: 10\.0\.\d{1,3}\.\d{1,3} # chỉ tin proxy trong VPC
// Khi WAF block, client nhận 403 từ WAF, request không tới app.
// Khi WAF ở chế độ Count, app vẫn nhận; có thể đọc header để biết:
@GetMapping("/login")
public ResponseEntity<?> login(HttpServletRequest req) {
String clientIp = req.getRemoteAddr(); // đã được RemoteIpValve chỉnh
log.info("login from ip={} ua={}", clientIp, req.getHeader("User-Agent"));
...
}
Bước 5 (Java): Cognito làm IdP cho shop-app thay hoặc song song Keycloak:
spring:
security:
oauth2:
resourceserver:
jwt:
issuer-uri: https://cognito-idp.${AWS_REGION}.amazonaws.com/${COGNITO_USER_POOL_ID}
# jwk-set-uri tự suy ra: {issuer}/.well-known/jwks.json
// Cognito đặt group vào claim "cognito:groups", map sang ROLE_
@Bean
JwtAuthenticationConverter jwtAuthenticationConverter() {
JwtGrantedAuthoritiesConverter groups = new JwtGrantedAuthoritiesConverter();
groups.setAuthoritiesClaimName("cognito:groups");
groups.setAuthorityPrefix("ROLE_");
JwtAuthenticationConverter c = new JwtAuthenticationConverter();
c.setJwtGrantedAuthoritiesConverter(groups);
return c;
}
Chú ý: access token của Cognito không có claim aud (chỉ id token có), nên nếu bật kiểm tra audience phải dùng claim client_id.
5. Cách hoạt động: request đi qua lớp nào, finding chảy về đâu
Internet
│
Shield Standard (L3/4, luôn bật) ──── Shield Advanced (L7, SRT, cost protection)
│
CloudFront ── WAF (scope CLOUDFRONT) ← assets, có thể cả API
│
shop-alb ──── WAF (scope REGIONAL) ← web ACL shop-waf
│ ├─ managed: SQLi, XSS, bad inputs, IP reputation
│ ├─ rate-based: 300 req/5min/IP trên /login → Block
│ └─ log → CloudWatch Logs aws-waf-logs-shop
▼
shop-asg (EC2) ◄── Inspector quét CVE qua SSM agent
│ ◄── GuardDuty Runtime Monitoring (tùy chọn)
▼
shop-db / shop-cache / S3 shop-app-assets ◄── Macie quét PII trong S3
Nguồn log Phát hiện Gom & hành động
CloudTrail ─┐ GuardDuty ──┐ Security Hub
VPC Flow ───┼───────────► (ML/intel) ├────────► (ASFF, score, standards)
DNS logs ───┘ Inspector ──┤ │ EventBridge rule
EKS audit Macie ──────┤ ▼
S3 data events Config ─────┘ SNS shop-security-alerts
Access Analyzer Lambda tự động remediate
(vd: tắt public bucket)
Detective: điều tra sâu
Thứ tự "đọc" sơ đồ này trong đề: chặn ở WAF/Shield; phát hiện ở GuardDuty/Inspector/Macie; tổng hợp ở Security Hub; điều tra ở Detective; tự động xử lý qua EventBridge + Lambda/SSM Automation.
6. So sánh kiểu đề thi
| Cặp hay nhầm | Khác nhau |
|---|---|
| WAF vs Shield | WAF: luật HTTP do bạn/AWS viết, chặn request xấu cụ thể. Shield: chống DDoS theo lượng, Standard tự động L3/4, Advanced thêm L7 + người + tiền. |
| WAF vs Security Group | WAF Layer 7 (URL, header, body, rate), gắn vào ALB/CloudFront/API GW. SG Layer 3/4 (IP, port), gắn vào ENI. |
| WAF vs Network Firewall | WAF bảo vệ HTTP endpoint public. Network Firewall kiểm tra traffic mạng trong/ra VPC (IDS/IPS, domain filtering egress). |
| GuardDuty vs Inspector | GuardDuty: hành vi bất thường, log-based, không agent, "ai đang tấn công". Inspector: lỗ hổng phần mềm/CVE và network exposure trên EC2/ECR/Lambda, "chỗ nào có thể bị tấn công". |
| GuardDuty vs Macie | GuardDuty: threat. Macie: dữ liệu nhạy cảm trong S3. |
| Security Hub vs Detective | Security Hub: gom và chấm điểm. Detective: điều tra nguyên nhân với graph. |
| Security Hub vs AWS Config | Config: ghi cấu hình và đánh giá rule riêng lẻ. Security Hub: dùng Config rule và các dịch vụ khác để chấm theo standard, gom cross-account. |
| Cognito user pool vs identity pool | User pool: xác thực, trả JWT. Identity pool: đổi token lấy credential AWS tạm thời (kể cả guest). |
| Cognito vs IAM Identity Center | Cognito: khách hàng của app. Identity Center: nhân viên vào AWS account/ứng dụng SaaS. |
| Managed AD vs AD Connector vs Simple AD | Managed AD: AD thật trên AWS, trust với on-prem, cho app cần domain join/Kerberos. AD Connector: proxy về AD on-prem, không lưu credential trên cloud. Simple AD: Samba, nhỏ, không trust, không MFA. |
| Access Analyzer vs Trusted Advisor security | Access Analyzer: phân tích policy để tìm chia sẻ ra ngoài và sinh least-privilege. Trusted Advisor: checklist (S3 public, MFA root, SG mở). |
7. Khi nào dùng / không
- WAF: bật managed Common + SQLi + Known Bad Inputs cho mọi ALB/CloudFront public; thêm rate-based cho
/login,/api/checkout. Chạy Count 1–2 tuần trước khi Block để tránh chặn khách thật. Không dùng WAF thay validation trong code. - Shield Advanced: chỉ khi doanh thu phụ thuộc uptime và chịu được phí tháng; shop-app giai đoạn này dùng Standard + WAF rate limit + CloudFront là đủ.
- GuardDuty: bật ở mọi account, mọi region (kể cả region không dùng: kẻ tấn công thích region vắng). Rẻ so với giá trị.
- Inspector: bật khi có EC2/ECR; cho pipeline fail nếu image shop-app có CVE Critical (xem 22.13, ECR enhanced scanning chính là Inspector).
- Macie: khi S3 chứa dữ liệu khách hàng (hồ sơ, hóa đơn); không cần cho bucket chỉ có ảnh sản phẩm.
- Security Hub: khi có từ 2 account hoặc cần báo cáo compliance; một account lab cũng dùng để học cách đọc finding.
- Cognito: khi muốn bỏ tự vận hành Keycloak và chấp nhận ít tùy biến; không hợp khi cần flow phức tạp, theme sâu, hoặc chạy on-prem.
shop-app đã có rate limit bằng bucket4j và Redis (bài system-design) rồi. Thêm WAF rate-based rule thì có thừa không? Nếu dùng cả hai, ngưỡng nên đặt thế nào để không chặn nhầm khách thật đi qua cùng một NAT công ty?
Không thừa, vì hai cái bảo vệ hai thứ khác nhau. Bạn đang có "rate limit nghiệp vụ" ở tầng app; WAF là "rate limit sinh tồn" ở biên.
1. Hai lớp, hai mục đích
WAF rate-based rule bucket4j + Redis trong app
Chỗ đứng trước ALB, request bị chặn không tới EC2 trong EC2, request đã tốn CPU/thread
Đơn vị IP (hoặc forwarded IP, header, cookie) user id, API key, tenant
Ngưỡng cao, thô: 300–2000 req/5 phút thấp, tinh: 10 req/giây/user
Mục đích chống flood, brute force, bot cào công bằng giữa user, bảo vệ DB
Phản hồi 403 từ WAF (hoặc CAPTCHA/Challenge) 429 + Retry-After từ app
Khi EC2 chết vẫn chặn không còn ai chặn
Rate limit trong app không bảo vệ bạn khi 10.000 req/s đổ vào: mỗi request vẫn mở connection, chạy filter chain, hỏi Redis. WAF chặn ở biên nên EC2 không thấy gì. Ngược lại WAF không biết user A đang lạm dụng API bằng 50 IP khác nhau; bucket4j theo user id mới bắt được. Xem lại thiết kế rate limiting ở system-design 04.
2. Đặt ngưỡng để không chặn NAT công ty
- Scope down rule: rate-based rule chỉ áp cho path nhạy cảm (
/login,/api/auth/*,/api/checkout) thay vì toàn site. Khách thật không đăng nhập 300 lần trong 5 phút, kể cả cả văn phòng chung một IP. - Aggregate key tinh hơn IP: WAF cho phép gộp theo IP + header (vd
X-Device-Id) hoặc theo cookie session. Cùng NAT nhưng khác cookie thì tính riêng. - Action CAPTCHA/Challenge thay Block cho path trang web: người thật giải được, bot dừng. API thuần thì Block hoặc trả custom response 429 với body JSON.
- Chạy Count trước: để rule ở Count 1–2 tuần, xem log
aws-waf-logs-shopbằng Logs Insights đếm có IP thật nào vượt ngưỡng, rồi mới đổi Block. - Allowlist IP set cho IP văn phòng, đối tác, health checker, đặt rule Allow này ở priority trước rate rule.
# Logs Insights trên log group aws-waf-logs-shop: IP nào bị rule rate-login đánh dấu
fields @timestamp, httpRequest.clientIp, httpRequest.uri, terminatingRuleId, action
| filter terminatingRuleId = "rate-login" or ispresent(nonTerminatingMatchingRules.0.ruleId)
| stats count(*) as hits by httpRequest.clientIp
| sort hits desc | limit 20
3. Phía CloudFront
Nếu đặt CloudFront trước ALB, IP tới ALB là IP edge của CloudFront. Rate rule ở ALB phải dùng ForwardedIPConfig (header X-Forwarded-For), hoặc tốt hơn là gắn WAF vào CloudFront. Và khóa ALB chỉ nhận từ CloudFront: SG của ALB dùng managed prefix list com.amazonaws.global.cloudfront.origin-facing cộng custom header bí mật mà CloudFront thêm vào, ALB listener rule kiểm tra header đó.
Mình bật GuardDuty thử và nó báo finding UnauthorizedAccess:IAMUser/InstanceCredentialExfiltration.OutsideAWS mức High trên shop-app-ec2-role. Nghĩa là gì, mình phải làm gì ngay, và GuardDuty biết chuyện này bằng cách nào khi mình chẳng cài gì?
Finding này nghĩa đen là: credential của role EC2 shop-app-ec2-role (vốn chỉ được dùng từ instance) đang được dùng từ một IP ngoài AWS. Thường là ai đó đã lấy được credential tạm từ instance (SSRF vào 169.254.169.254, hoặc dump từ máy bị xâm nhập) và mang về máy họ gọi API. Đây là một trong những finding nghiêm trọng nhất.
1. GuardDuty biết bằng cách nào
CloudTrail ghi: API call X, bởi role session của shop-app-ec2-role,
từ source IP 198.51.100.7
GuardDuty so: 198.51.100.7 không phải IP của AWS; role này là instance profile role
→ credential đang chạy ngoài EC2 → finding High
GuardDuty đọc thẳng CloudTrail, VPC Flow Logs, DNS logs từ bên trong AWS (không cần bạn bật Flow Logs hay tạo trail; nó dùng nguồn độc lập), nên "không cài gì" vẫn thấy. Phiên bản .InsideAWS là credential bị dùng từ account AWS khác.
2. Xử lý ngay (runbook ngắn)
- Cô lập instance bị nghi: đổi SG của nó sang SG "quarantine" không cho inbound/outbound, không terminate (giữ bằng chứng), snapshot EBS.
- Thu hồi credential: IAM → role
shop-app-ec2-role→ Revoke sessions. Nó thêm inline policy deny mọi call cóaws:TokenIssueTimetrước thời điểm đó. Instance khỏe mạnh sẽ tự lấy credential mới qua IMDS.aws iam put-role-policy --role-name shop-app-ec2-role --policy-name AWSRevokeOlderSessions \ --policy-document '{"Version":"2012-10-17","Statement":[{"Effect":"Deny","Action":"*","Resource":"*", "Condition":{"DateLessThan":{"aws:TokenIssueTime":"'$(date -u +%Y-%m-%dT%H:%M:%SZ)'"}}}]}' \ --profile shop-lab - Xem kẻ đó đã làm gì: CloudTrail Lake / Athena lọc theo
userIdentity.sessionContext.sessionIssuer.userName = shop-app-ec2-rolevàsourceIPAddresslạ. Detective dựng graph nhanh hơn nếu đã bật. - Bịt lỗ: bắt buộc IMDSv2 (
HttpTokens=required) trên launch templateshop-lt, SSRF kiểu GET đơn giản không lấy được token; giới hạnHttpPutResponseHopLimit=1để container không với tới. Sửa code nếu có SSRF. - Tự động hóa: EventBridge rule bắt finding GuardDuty severity ≥ 7 → Lambda gắn SG quarantine + SNS
shop-security-alerts. Security Hub có custom action gửi sang SSM Automation runbook.
aws ec2 modify-launch-template ... # hoặc sửa trực tiếp instance đang chạy:
aws ec2 modify-instance-metadata-options --instance-id $INSTANCE_ID \
--http-tokens required --http-put-response-hop-limit 1 --http-endpoint enabled \
--region $AWS_REGION --profile shop-lab
3. Trong đề thi
"GuardDuty finding shows EC2 credentials used from outside AWS, what should SA do FIRST?" → cô lập instance và revoke session/rotate credential; đáp án bẫy thường là "terminate instance" (mất bằng chứng) hoặc "disable GuardDuty". "Prevent SSRF from stealing instance credentials" → IMDSv2 required.
shop-app đang xác thực bằng Keycloak chạy trên ECS. Nếu đổi sang Cognito thì mình được gì, mất gì? Và mình chưa hiểu khi nào cần thêm identity pool, vì backend Spring của mình chỉ cần validate JWT thôi mà.
Bạn hiểu đúng ở điểm quan trọng nhất: nếu backend chỉ validate JWT thì user pool là đủ, không cần identity pool. Identity pool chỉ xuất hiện khi frontend/mobile cần gọi dịch vụ AWS trực tiếp.
1. Keycloak → Cognito user pool: được và mất
| Keycloak trên ECS (hiện tại) | Cognito user pool | |
|---|---|---|
| Vận hành | Tự chạy container, DB Postgres riêng, patch, HA (keycloak 06) | AWS quản lý, SLA, scale tự động |
| Giá | Fargate + RDS 24/7 (không Free Tier) | Theo MAU; có bậc miễn phí hàng tháng cho tier Essentials/Lite, kiểm tra pricing page |
| Chuẩn | OIDC, OAuth2, SAML đầy đủ, nhiều flow | OIDC/OAuth2 (code, implicit, client credentials), SAML chỉ ở vai IdP federation vào |
| Tùy biến | Theme, custom authenticator SPI, flow phức tạp, user federation LDAP | Hosted UI (managed login) tùy biến hạn chế; Lambda trigger (pre-signup, pre-token, custom auth challenge) |
| Token | Bạn kiểm soát claim, mapper, lifetime | Claim cố định + custom qua Pre Token Generation Lambda; access token không có aud |
| Bảo mật nâng cao | Tự cấu hình brute force detection | Advanced security (Plus tier): adaptive auth, compromised credential check; tích hợp WAF |
| Portability | Chạy ở đâu cũng được (on-prem, cloud khác) | Khóa vào AWS; export user không kèm password hash (phải migrate bằng Lambda trigger khi user đăng nhập lần đầu) |
Đáng đổi khi: team nhỏ không muốn vận hành IdP, cần social login/MFA nhanh, chạy toàn bộ trên AWS. Không đáng khi: đã có flow phức tạp trên Keycloak, cần SAML IdP cho đối tác, hoặc cần multi-cloud. Với Spring, phần resource server gần như không đổi: chỉ đổi issuer-uri và tên claim group (cognito:groups thay realm_access.roles).
2. Khi nào thêm identity pool
Trường hợp A: Web/mobile ──JWT──► Spring Boot ──SDK──► S3 (presigned URL, upload qua backend)
→ chỉ cần user pool. Backend dùng role ECS/EC2 để gọi S3.
Trường hợp B: Mobile app upload ảnh 50 MB thẳng lên S3, không muốn đi qua backend
Mobile ──id_token──► Identity pool ──AssumeRoleWithWebIdentity──► credential tạm 1 giờ
──credential──► S3 PutObject s3://shop-app-assets-123/users/${sub}/avatar.jpg
IAM policy của role "authenticated":
Resource: arn:aws:s3:::shop-app-assets-${ACCOUNT_ID}/users/${cognito-identity.amazonaws.com:sub}/*
→ mỗi user chỉ ghi được thư mục của mình, không cần backend trung gian.
Trường hợp C: Khách chưa đăng nhập xem catalog trong DynamoDB qua AppSync/API trực tiếp
→ identity pool với "unauthenticated identities" (guest role chỉ có quyền đọc).
Với shop-app hiện tại, upload ảnh đi qua presigned URL do backend cấp (22.6) là đủ và kiểm soát tốt hơn; identity pool để khi làm mobile app nặng offline/direct-to-AWS. Đề thi: cứ thấy "mobile users need temporary AWS credentials to access S3/DynamoDB directly" là identity pool; "sign-up/sign-in, MFA, social login" là user pool.
Cho mình bài lab để tự tay làm phần này nhé: WAF rate limit lên shop-alb, bật GuardDuty và gom finding vào Security Hub.
Lab 22.20: WAF trước shop-alb, GuardDuty và Security Hub
Mục tiêu
- Web ACL
shop-wafgắn vàoshop-albvới 2 managed rule group và 1 rate-based rule trên/login; bắn 400 request trong 1 phút từ một IP thì bắt đầu nhận 403. - WAF log ghi vào CloudWatch Logs group
aws-waf-logs-shop; Logs Insights đếm được số request bị block theo IP. - GuardDuty bật (trial 30 ngày), sinh sample findings và thấy ít nhất 1 finding High.
- Security Hub bật với standard AWS Foundational Security Best Practices, nhận finding từ GuardDuty; EventBridge rule đẩy finding High về SNS email.
Chi phí & thời gian
- WAF: không Free Tier. Web ACL tính theo tháng (khoảng vài USD/tháng, prorate theo giờ), mỗi rule/rule group tính thêm theo tháng, và tính theo triệu request. Lab vài giờ chỉ tốn cent.
- ALB shop-alb và EC2 phải chạy: ALB không Free Tier (theo giờ + LCU).
- GuardDuty: 30 ngày trial miễn phí lần đầu bật trong account/region; sau đó tính theo GB log. Security Hub: 30 ngày trial; sau đó theo số security check và finding ingest. Inspector (thử thêm): 15 ngày trial.
- Thời gian: 60–75 phút.
Chuẩn bị
- ALB
shop-alb+ target groupshop-tg+ ASGshop-asgđang chạy từ 22.5; app trả 200 ở/actuator/healthvà có endpoint/login(trả 401 hoặc 200 đều được, miễn ALB forward). - Profile
shop-lab;jqvàheyhoặcab(ApacheBench) để bắn tải.
export AWS_REGION=ap-southeast-1
export ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text --profile shop-lab)
export MY_EMAIL=you@example.com
export ALB_ARN=$(aws elbv2 describe-load-balancers --names shop-alb \
--query 'LoadBalancers[0].LoadBalancerArn' --output text --region $AWS_REGION --profile shop-lab)
export ALB_DNS=$(aws elbv2 describe-load-balancers --names shop-alb \
--query 'LoadBalancers[0].DNSName' --output text --region $AWS_REGION --profile shop-lab)
curl -s -o /dev/null -w "%{http_code}\n" http://$ALB_DNS/actuator/health # 200
Các bước
Bước 1. Tạo Web ACL với managed rules + rate-based rule.
cat > shop-waf-rules.json <<'EOF'
[
{
"Name": "aws-common",
"Priority": 0,
"OverrideAction": {"None": {}},
"Statement": {"ManagedRuleGroupStatement": {
"VendorName": "AWS", "Name": "AWSManagedRulesCommonRuleSet"}},
"VisibilityConfig": {"SampledRequestsEnabled": true, "CloudWatchMetricsEnabled": true,
"MetricName": "aws-common"}
},
{
"Name": "aws-sqli",
"Priority": 1,
"OverrideAction": {"None": {}},
"Statement": {"ManagedRuleGroupStatement": {
"VendorName": "AWS", "Name": "AWSManagedRulesSQLiRuleSet"}},
"VisibilityConfig": {"SampledRequestsEnabled": true, "CloudWatchMetricsEnabled": true,
"MetricName": "aws-sqli"}
},
{
"Name": "rate-login",
"Priority": 2,
"Action": {"Block": {"CustomResponse": {"ResponseCode": 429}}},
"Statement": {"RateBasedStatement": {
"Limit": 300,
"EvaluationWindowSec": 60,
"AggregateKeyType": "IP",
"ScopeDownStatement": {"ByteMatchStatement": {
"FieldToMatch": {"UriPath": {}},
"PositionalConstraint": "STARTS_WITH",
"SearchString": "/login",
"TextTransformations": [{"Priority": 0, "Type": "LOWERCASE"}]}}}},
"VisibilityConfig": {"SampledRequestsEnabled": true, "CloudWatchMetricsEnabled": true,
"MetricName": "rate-login"}
}
]
EOF
aws wafv2 create-web-acl --name shop-waf --scope REGIONAL \
--default-action Allow={} \
--rules file://shop-waf-rules.json \
--visibility-config SampledRequestsEnabled=true,CloudWatchMetricsEnabled=true,MetricName=shop-waf \
--tags Key=Project,Value=shop-app Key=Env,Value=lab \
--region $AWS_REGION --profile shop-lab
export WEB_ACL_ARN=$(aws wafv2 list-web-acls --scope REGIONAL \
--query "WebACLs[?Name=='shop-waf'].ARN" --output text --region $AWS_REGION --profile shop-lab)
export WEB_ACL_ID=$(aws wafv2 list-web-acls --scope REGIONAL \
--query "WebACLs[?Name=='shop-waf'].Id" --output text --region $AWS_REGION --profile shop-lab)
Console: WAF & Shield → Web ACLs → Region: Asia Pacific (Singapore) → Create web ACL → Name shop-waf, Resource type: Regional → Add rules: Add managed rule groups (Core rule set, SQL database) → Add my own rules: Rule builder → Rate-based rule, limit 300, window 1 minute, Only consider requests that match: URI path starts with /login → Action Block, custom response 429.
Ghi chú: ngưỡng tối thiểu của rate-based rule phụ thuộc cửa sổ (1 phút: tối thiểu khoảng vài chục request); nếu API báo lỗi ngưỡng, tăng Limit lên theo thông báo.
Bước 2. Gắn Web ACL vào ALB.
aws wafv2 associate-web-acl --web-acl-arn $WEB_ACL_ARN --resource-arn $ALB_ARN \
--region $AWS_REGION --profile shop-lab
aws wafv2 get-web-acl-for-resource --resource-arn $ALB_ARN \
--query 'WebACL.Name' --region $AWS_REGION --profile shop-lab # "shop-waf"
Console: Web ACL shop-waf → Associated AWS resources → Add AWS resources → Application Load Balancer → shop-alb.
Bước 3. Bật WAF logging ra CloudWatch Logs. Tên log group bắt buộc bắt đầu bằng aws-waf-logs-.
aws logs create-log-group --log-group-name aws-waf-logs-shop \
--tags Project=shop-app,Env=lab --region $AWS_REGION --profile shop-lab
aws logs put-retention-policy --log-group-name aws-waf-logs-shop --retention-in-days 7 \
--region $AWS_REGION --profile shop-lab
aws wafv2 put-logging-configuration --logging-configuration "{
\"ResourceArn\": \"$WEB_ACL_ARN\",
\"LogDestinationConfigs\": [\"arn:aws:logs:$AWS_REGION:$ACCOUNT_ID:log-group:aws-waf-logs-shop\"]
}" --region $AWS_REGION --profile shop-lab
Console: Web ACL shop-waf → Logging and metrics → Enable → CloudWatch Logs log group → aws-waf-logs-shop.
Bước 4. Thử SQL injection và brute force.
# SQLi: mong đợi 403 (managed rule SQLi block)
curl -s -o /dev/null -w "%{http_code}\n" "http://$ALB_DNS/api/products?id=1'%20OR%201=1--"
# Request bình thường: 200
curl -s -o /dev/null -w "%{http_code}\n" "http://$ALB_DNS/api/products?id=1"
# Brute force /login: 400 request trong ~60 giây từ 1 IP
hey -n 400 -c 10 -q 7 http://$ALB_DNS/login
# hoặc: ab -n 400 -c 10 http://$ALB_DNS/login
# Sau đó:
for i in $(seq 1 5); do curl -s -o /dev/null -w "%{http_code} " http://$ALB_DNS/login; done; echo
# Mong đợi: 429 429 429 429 429 (rate rule cần ~30–60 giây để kích hoạt sau khi vượt ngưỡng)
Bước 5. Bật GuardDuty và sinh sample findings.
DETECTOR_ID=$(aws guardduty create-detector --enable \
--finding-publishing-frequency FIFTEEN_MINUTES \
--tags Project=shop-app,Env=lab \
--query DetectorId --output text --region $AWS_REGION --profile shop-lab)
echo $DETECTOR_ID
# Sinh finding mẫu (không có tấn công thật, chỉ để học cách đọc)
aws guardduty create-sample-findings --detector-id $DETECTOR_ID \
--finding-types UnauthorizedAccess:IAMUser/InstanceCredentialExfiltration.OutsideAWS \
CryptoCurrency:EC2/BitcoinTool.B!DNS \
Recon:EC2/PortProbeUnprotectedPort \
--region $AWS_REGION --profile shop-lab
aws guardduty list-findings --detector-id $DETECTOR_ID \
--finding-criteria '{"Criterion":{"severity":{"Gte":7}}}' \
--region $AWS_REGION --profile shop-lab
Console: GuardDuty → Get Started → Enable GuardDuty (30-day free trial) → Settings → Sample findings → Generate sample findings → Findings (lọc "[SAMPLE]").
Bước 6. Bật Security Hub và standard.
aws securityhub enable-security-hub --enable-default-standards \
--tags Project=shop-app,Env=lab --region $AWS_REGION --profile shop-lab
aws securityhub get-enabled-standards --query 'StandardsSubscriptions[].StandardsArn' \
--region $AWS_REGION --profile shop-lab
# Mong đợi có aws-foundational-security-best-practices và cis-aws-foundations-benchmark
# GuardDuty tự tích hợp; kiểm tra:
aws securityhub list-enabled-products-for-import --region $AWS_REGION --profile shop-lab | grep -i guardduty
Console: Security Hub → Go to Security Hub → Enable AWS Foundational Security Best Practices → Enable Security Hub. Sau 15–30 phút: Findings → filter Product name = GuardDuty.
Bước 7. EventBridge: finding High → SNS email.
TOPIC_ARN=$(aws sns create-topic --name shop-security-alerts \
--tags Key=Project,Value=shop-app Key=Env,Value=lab \
--query TopicArn --output text --region $AWS_REGION --profile shop-lab)
aws sns subscribe --topic-arn $TOPIC_ARN --protocol email --notification-endpoint $MY_EMAIL \
--region $AWS_REGION --profile shop-lab # confirm trong email
aws events put-rule --name shop-sechub-high \
--event-pattern '{
"source": ["aws.securityhub"],
"detail-type": ["Security Hub Findings - Imported"],
"detail": {"findings": {"Severity": {"Label": ["HIGH","CRITICAL"]},
"RecordState": ["ACTIVE"]}}
}' --tags Key=Project,Value=shop-app Key=Env,Value=lab \
--region $AWS_REGION --profile shop-lab
aws events put-targets --rule shop-sechub-high \
--targets "Id=sns,Arn=$TOPIC_ARN,InputTransformer={InputPathsMap={title=\$.detail.findings[0].Title,sev=\$.detail.findings[0].Severity.Label,res=\$.detail.findings[0].Resources[0].Id},InputTemplate='\"[] on \"'}" \
--region $AWS_REGION --profile shop-lab
# Cho EventBridge publish vào topic
aws sns set-topic-attributes --topic-arn $TOPIC_ARN --attribute-name Policy --attribute-value "{
\"Version\":\"2012-10-17\",\"Statement\":[{\"Effect\":\"Allow\",
\"Principal\":{\"Service\":\"events.amazonaws.com\"},\"Action\":\"SNS:Publish\",\"Resource\":\"$TOPIC_ARN\"}]}" \
--region $AWS_REGION --profile shop-lab
# Sinh thêm sample finding để kích rule
aws guardduty create-sample-findings --detector-id $DETECTOR_ID \
--finding-types Backdoor:EC2/C&CActivity.B!DNS --region $AWS_REGION --profile shop-lab
Console: EventBridge → Rules → Create rule → Event pattern: AWS services → Security Hub → Security Hub Findings - Imported → chỉnh JSON thêm Severity → Target: SNS topic shop-security-alerts.
Kiểm tra kết quả
# 1. WAF: số request bị block theo rule trong 15 phút qua
aws cloudwatch get-metric-statistics --namespace AWS/WAFV2 --metric-name BlockedRequests \
--dimensions Name=WebACL,Value=shop-waf Name=Region,Value=$AWS_REGION Name=Rule,Value=rate-login \
--start-time $(date -u -d '-15 min' +%FT%TZ 2>/dev/null || date -u -v-15M +%FT%TZ) \
--end-time $(date -u +%FT%TZ) --period 300 --statistics Sum \
--region $AWS_REGION --profile shop-lab
# Datapoints Sum > 0
# 2. WAF log qua Logs Insights
QID=$(aws logs start-query --log-group-name aws-waf-logs-shop \
--start-time $(($(date +%s)-1800)) --end-time $(date +%s) \
--query-string 'fields httpRequest.clientIp, terminatingRuleId, action | filter action="BLOCK" | stats count(*) as hits by httpRequest.clientIp, terminatingRuleId' \
--query queryId --output text --region $AWS_REGION --profile shop-lab)
sleep 5; aws logs get-query-results --query-id $QID --region $AWS_REGION --profile shop-lab
# 3. GuardDuty có finding severity >= 7
aws guardduty get-findings --detector-id $DETECTOR_ID \
--finding-ids $(aws guardduty list-findings --detector-id $DETECTOR_ID --query 'FindingIds[0]' --output text --region $AWS_REGION --profile shop-lab) \
--query 'Findings[0].[Type,Severity,Resource.ResourceType]' --region $AWS_REGION --profile shop-lab
# 4. Security Hub nhận finding từ GuardDuty
aws securityhub get-findings --filters '{"ProductName":[{"Value":"GuardDuty","Comparison":"EQUALS"}]}' \
--max-items 3 --query 'Findings[].[Title,Severity.Label]' --region $AWS_REGION --profile shop-lab
# 5. Email: nhận được "[HIGH] ... on arn:aws:ec2:..."
Thử thêm
- Chuyển rate rule sang Count rồi bắn lại: request đi qua (200/401) nhưng log vẫn ghi
nonTerminatingMatchingRulesvớirate-login. Đây là cách "chạy thử" rule trước khi Block:aws wafv2 update-web-aclvới"Action": {"Count": {}}(cần--lock-tokentừget-web-acl). - Geo block: thêm rule
GeoMatchStatementvớiCountryCodes: ["XX"]action Block, kiểm tra bằng VPN hoặc đổi sang Count và xem log fieldhttpRequest.country. - Inspector:
aws inspector2 enable --resource-types EC2 ECR --region $AWS_REGION --profile shop-lab(15 ngày trial); sau ~1 giờ xemaws inspector2 list-findingscho EC2 của shop-asg (cần SSM agent, Amazon Linux 2023 có sẵn). Finding cũng chảy vào Security Hub. - Bắt buộc IMDSv2 trên launch template shop-lt, xem Security Hub control
EC2.8chuyển từ FAILED sang PASSED ở lần đánh giá sau. - Cognito nhanh:
aws cognito-idp create-user-pool --pool-name shop-users, tạo app client, lấy issuerhttps://cognito-idp.$AWS_REGION.amazonaws.com/<poolId>, trỏissuer-uricủa shop-app sang và đăng nhập bằng hosted UI. User pool không có phí nếu dưới bậc miễn phí; xóa bằngdelete-user-pool.
Dọn tài nguyên
# 1. EventBridge rule + SNS
aws events remove-targets --rule shop-sechub-high --ids sns --region $AWS_REGION --profile shop-lab
aws events delete-rule --name shop-sechub-high --region $AWS_REGION --profile shop-lab
aws sns delete-topic --topic-arn $TOPIC_ARN --region $AWS_REGION --profile shop-lab
# 2. Security Hub (tắt để không bị tính sau trial)
aws securityhub disable-security-hub --region $AWS_REGION --profile shop-lab
# 3. GuardDuty (xóa detector = tắt; trial còn lại không được cộng dồn lần sau)
aws guardduty delete-detector --detector-id $DETECTOR_ID --region $AWS_REGION --profile shop-lab
# 4. Inspector nếu đã bật
aws inspector2 disable --resource-types EC2 ECR --region $AWS_REGION --profile shop-lab
# 5. WAF: gỡ khỏi ALB → tắt log → xóa ACL (cần lock token)
aws wafv2 disassociate-web-acl --resource-arn $ALB_ARN --region $AWS_REGION --profile shop-lab
aws wafv2 delete-logging-configuration --resource-arn $WEB_ACL_ARN --region $AWS_REGION --profile shop-lab
LOCK=$(aws wafv2 get-web-acl --name shop-waf --scope REGIONAL --id $WEB_ACL_ID \
--query LockToken --output text --region $AWS_REGION --profile shop-lab)
aws wafv2 delete-web-acl --name shop-waf --scope REGIONAL --id $WEB_ACL_ID --lock-token $LOCK \
--region $AWS_REGION --profile shop-lab
aws logs delete-log-group --log-group-name aws-waf-logs-shop --region $AWS_REGION --profile shop-lab
# 6. ALB/ASG/EC2: dọn theo lab 22.5 nếu không làm tiếp bài 22.21
Không nằm trong Free Tier nếu quên: Web ACL (theo tháng, prorate), ALB (giờ + LCU), GuardDuty và Security Hub sau khi hết 30 ngày trial, Inspector sau 15 ngày.
Phỏng vấn và đề thi SAA hỏi về WAF, GuardDuty, Cognito và các dịch vụ bảo mật thì sao? Nhiều tên quá, mình sợ nhầm.
Q1. Bạn bảo vệ một web app public trên ALB trước SQL injection, brute force và DDoS như thế nào?
🇻🇳 Tiếng Việt:
Em đặt AWS WAF lên ALB hoặc CloudFront: bật managed rule group Common và SQLi để chặn injection và XSS, thêm rate-based rule giới hạn request mỗi IP trên đường dẫn login để chặn brute force, chạy Count trước rồi mới Block. DDoS tầng mạng đã có Shield Standard miễn phí; nếu doanh thu phụ thuộc uptime thì cân nhắc Shield Advanced để có bảo vệ Layer 7, đội phản ứng và bảo hiểm chi phí. Trong app vẫn giữ validation và rate limit theo user, vì WAF chỉ thấy IP và nội dung HTTP.
🇬🇧 English:
I put AWS WAF in front of the ALB or CloudFront: enable the Common and SQLi managed rule groups to block injection and XSS, add a rate-based rule that limits requests per IP on the login path to stop brute force, and run it in Count mode before switching to Block. Network-layer DDoS is already covered by the free Shield Standard; if revenue depends on uptime I would consider Shield Advanced for Layer 7 protection, the response team and cost protection. The application keeps its own validation and per-user rate limiting, because WAF only sees IPs and HTTP content.
Q2. GuardDuty, Inspector, Macie, Security Hub: cái nào làm gì?
🇻🇳 Tiếng Việt:
GuardDuty phát hiện hành vi đe dọa bằng cách phân tích CloudTrail, VPC Flow Logs và DNS logs, không cần agent, ví dụ credential bị dùng từ ngoài AWS hay EC2 đào coin. Inspector quét lỗ hổng CVE và network exposure trên EC2, image ECR và Lambda. Macie tìm dữ liệu nhạy cảm như PII, số thẻ trong S3. Security Hub gom finding của cả ba cộng Config và Access Analyzer về một chỗ, chấm điểm theo standard như CIS, và cho phép tự động xử lý qua EventBridge.
🇬🇧 English:
GuardDuty detects threats by analyzing CloudTrail, VPC Flow Logs and DNS logs without agents, for example credentials used from outside AWS or an EC2 instance mining crypto. Inspector scans for CVEs and network exposure on EC2, ECR images and Lambda. Macie discovers sensitive data such as PII and card numbers in S3. Security Hub aggregates findings from all of them plus Config and Access Analyzer, scores them against standards like CIS, and enables automated response through EventBridge.
Q3. Cognito user pool khác identity pool chỗ nào? Khi nào bạn chọn Cognito thay Keycloak?
🇻🇳 Tiếng Việt:
User pool là user directory và OIDC provider: đăng ký, đăng nhập, MFA, social login, trả JWT để backend validate. Identity pool không lưu user, nó đổi token từ user pool hoặc Google, Facebook, SAML thành credential AWS tạm thời để app gọi S3, DynamoDB trực tiếp, có cả chế độ guest. Em chọn Cognito khi muốn bỏ vận hành IdP và chạy toàn bộ trên AWS; giữ Keycloak khi cần flow tùy biến sâu, SAML IdP cho đối tác, hoặc multi-cloud. Với Spring resource server, chỉ đổi issuer-uri và tên claim.
🇬🇧 English:
A user pool is a user directory and OIDC provider: sign-up, sign-in, MFA, social login, and it issues JWTs for the backend to validate. An identity pool stores no users; it exchanges tokens from a user pool or Google, Facebook or SAML for temporary AWS credentials so the app can call S3 or DynamoDB directly, including a guest mode. I choose Cognito when we want to stop operating an IdP and stay fully on AWS; I keep Keycloak when we need deeply customized flows, a SAML IdP for partners, or multi-cloud. For a Spring resource server only the issuer-uri and claim names change.
Q4. Nhân viên cần vào 20 AWS account bằng tài khoản công ty, bạn thiết kế thế nào?
🇻🇳 Tiếng Việt:
Em dùng IAM Identity Center trong Organizations, kết nối với IdP công ty như Entra ID hoặc Okta qua SAML và SCIM để đồng bộ user, group. Tạo permission set như ReadOnly, Developer, Admin rồi gán nhóm cho từng account. Nhân viên đăng nhập một cổng, chọn account và role, CLI dùng aws sso login nên không có access key dài hạn. Không tạo IAM user trong từng account.
🇬🇧 English:
I use IAM Identity Center in Organizations, connected to the corporate IdP such as Entra ID or Okta through SAML and SCIM for user and group sync. I define permission sets like ReadOnly, Developer and Admin and assign groups to each account. Employees log in through one portal, pick an account and role, and the CLI uses aws sso login, so there are no long-lived access keys. No IAM users are created in individual accounts.
Góc thi SAA-C03
Câu 1: Một ứng dụng web chạy sau Application Load Balancer bị tấn công brute force vào trang login từ nhiều IP, mỗi IP gửi hàng nghìn request mỗi phút. Giải pháp nào chặn hiệu quả với LEAST operational overhead?
A. Thêm rule Network ACL deny các IP tấn công
B. Tạo AWS WAF web ACL có rate-based rule gắn vào ALB
C. Chuyển sang Network Load Balancer và bật Shield Advanced
D. Viết rate limiting trong code ứng dụng và scale thêm EC2
Đáp án: B. Rate-based rule tự động chặn IP vượt ngưỡng trong cửa sổ thời gian, không cần biết trước IP, gắn vào ALB. A phải cập nhật tay IP, NACL giới hạn số rule và không hiểu URL. C: WAF không gắn vào NLB; Shield Advanced đắt và không phải công cụ rate limit per path. D tốn chi phí và request vẫn tới EC2.
Câu 2: Một công ty muốn phát hiện account bị xâm nhập, ví dụ access key bị dùng từ IP lạ hoặc EC2 liên lạc với máy chủ đào coin, trên toàn bộ account trong Organization mà không cài agent. Dịch vụ nào phù hợp?
A. Amazon Inspector
B. Amazon Macie
C. Amazon GuardDuty với delegated administrator
D. AWS Config với conformance pack
Đáp án: C. GuardDuty là threat detection dựa trên CloudTrail, Flow Logs, DNS logs, không agent, hỗ trợ multi-account qua delegated administrator. A quét lỗ hổng phần mềm, không phát hiện hành vi. B tìm dữ liệu nhạy cảm trong S3. D kiểm tra cấu hình, không phân tích hành vi.
Câu 3: Mobile app cho phép người dùng đăng nhập bằng Google hoặc email, sau đó upload ảnh trực tiếp lên S3 vào thư mục riêng của mình mà không đi qua backend. Giải pháp nào đúng?
A. Cognito user pool, backend cấp presigned URL
B. Cognito user pool kết hợp Cognito identity pool với IAM role dùng policy variable theo identity
C. Tạo IAM user cho mỗi người dùng và nhúng access key vào app
D. IAM Identity Center với permission set cho người dùng app
Đáp án: B. User pool xác thực (Google/email), identity pool đổi token lấy credential AWS tạm thời, IAM role với ${cognito-identity.amazonaws.com:sub} giới hạn mỗi user vào thư mục riêng; "trực tiếp lên S3" là dấu hiệu identity pool. A đi qua backend, trái yêu cầu. C là anti-pattern nghiêm trọng. D dành cho nhân viên, không cho khách hàng.
Cách nhớ ngắn gọn
- Chặn: WAF (HTTP rule, rate) · Shield (DDoS) · Network Firewall (trong VPC). Phát hiện: GuardDuty (hành vi) · Inspector (CVE) · Macie (PII S3). Gom: Security Hub. Điều tra: Detective.
- Cognito user pool = ai là ai (JWT); identity pool = credential AWS tạm (kể cả guest).
- Khách hàng → Cognito; nhân viên → IAM Identity Center; app → IAM role; Windows/Kerberos → Directory Service.
- WAF không gắn NLB. GuardDuty không cần agent. Shield Standard miễn phí và luôn bật.
| Từ khóa trong đề | Dịch vụ |
|---|---|
| "SQL injection", "XSS", "block requests by country", "rate limit per IP" | WAF |
| "DDoS", "cost protection", "24/7 response team" | Shield Advanced |
| "compromised credentials", "crypto mining", "malicious IP", "no agent" | GuardDuty |
| "CVE", "software vulnerabilities", "ECR image scan", "network reachability" | Inspector |
| "PII", "sensitive data in S3", "credit card numbers" | Macie |
| "single pane", "security posture", "CIS benchmark", "aggregate findings" | Security Hub |
| "investigate root cause of finding" | Detective |
| "sign-up/sign-in for app users", "social login", "MFA for customers" | Cognito user pool |
| "temporary AWS credentials for mobile users", "unauthenticated guest access" | Cognito identity pool |
| "workforce SSO to multiple accounts", "corporate IdP" | IAM Identity Center |
| "Active Directory trust", "domain join" | AWS Managed Microsoft AD |
| "use on-prem AD without storing credentials in cloud" | AD Connector |
| "WAF rules across all accounts" | Firewall Manager |
| "IDS/IPS", "egress domain filtering for VPC" | Network Firewall |
| "resources shared with external accounts", "generate least-privilege policy" | IAM Access Analyzer |
| "download SOC/PCI report of AWS" | AWS Artifact |
Tự kiểm tra
WAF gắn được vào tài nguyên nào, không gắn được vào đâu?
Gắn: CloudFront, ALB, API Gateway (REST), AppSync, Cognito user pool, App Runner, Verified Access. Không gắn: NLB, EC2 trực tiếp, Classic LB. Scope CLOUDFRONT phải tạo ở us-east-1.
Shield Standard và Advanced khác nhau ở ba điểm nào?
Giá (miễn phí vs phí tháng + cam kết 1 năm), tầng bảo vệ (L3/4 vs thêm L7), và dịch vụ kèm theo (Advanced có Shield Response Team, DDoS cost protection, WAF/Firewall Manager không tính phí).
GuardDuty dùng những nguồn dữ liệu nào và có cần bật CloudTrail/Flow Logs trước không?
CloudTrail management và S3 data events, VPC Flow Logs, Route 53 DNS logs, EKS audit logs, RDS login, Lambda network, cộng malware protection. Không cần bật trước: GuardDuty đọc nguồn độc lập bên trong AWS.
Khi backend Spring chỉ validate JWT, có cần Cognito identity pool không?
Không. User pool đủ: nó là OIDC provider, Spring trỏ issuer-uri tới nó. Identity pool chỉ cần khi client phải gọi dịch vụ AWS trực tiếp bằng credential tạm.
Finding "InstanceCredentialExfiltration.OutsideAWS" xử lý theo thứ tự nào?
Cô lập instance bằng SG quarantine (không terminate), revoke session của role, điều tra CloudTrail/Detective, bắt buộc IMDSv2 và sửa SSRF, rồi tự động hóa phản ứng bằng EventBridge + Lambda.