IAM, KMS và Cognito: phân quyền và mã hoá
Mục tiêu bài học
Sau bài này, bạn sẽ:
- Đọc được một IAM policy JSON và xác định ai được làm gì, trên tài nguyên nào, trong điều kiện nào.
- Nắm thứ tự đánh giá policy và biết vì sao "Deny luôn thắng".
- Chọn đúng loại KMS key (AWS owned, AWS managed, customer managed) và hiểu envelope encryption.
- Phân biệt Cognito User Pool (authentication) với Identity Pool (authorization, cấp AWS credentials) trong đề thi.
- Nhận ra các bẫy câu hỏi tình huống hay gặp về cross-account access và mã hoá dữ liệu.
Ôn tập nhanh
Ở bài trước, bạn đã thấy S3 và DynamoDB đều hỗ trợ mã hoá at rest, và S3 bucket policy chính là một dạng resource-based policy. Bài này nối tiếp đúng chỗ đó: bucket policy, KMS key policy và IAM identity policy đều dùng chung một ngôn ngữ JSON, và chúng được đánh giá cùng nhau theo một thứ tự cố định.
[!NOTE] Nếu bạn còn nhớ ARN có dạng
arn:aws:service:region:account-id:resource, bạn đã có đủ nền để đọc mọi policy trong bài này.
Lý thuyết
1. IAM: hai loại policy và một thứ tự đánh giá
Mọi policy IAM đều có cấu trúc gần giống nhau:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowReadOwnBucket",
"Effect": "Allow",
"Action": ["s3:GetObject", "s3:ListBucket"],
"Resource": [
"arn:aws:s3:::my-app-bucket",
"arn:aws:s3:::my-app-bucket/*"
],
"Condition": {
"StringEquals": { "aws:PrincipalTag/team": "backend" }
}
}
]
}
Các trường cần đọc theo thứ tự: Effect (Allow/Deny), Action (được làm gì), Resource (trên cái gì), Condition (khi nào). Trong đề thi, phần lớn câu hỏi sai nằm ở Resource thiếu dấu /* hoặc Condition không khớp.
Có hai loại policy gắn ở hai phía:
| Loại | Gắn vào đâu | Ví dụ |
|---|---|---|
| Identity-based | User, group, role | Policy cho role mà Lambda assume |
| Resource-based | Chính tài nguyên | S3 bucket policy, KMS key policy, SQS queue policy |
Thứ tự đánh giá rút gọn: explicit Deny, rồi SCP, rồi permissions boundary, rồi session policy, cuối cùng mới xét Allow từ identity policy hoặc resource policy. ==Explicit Deny luôn thắng mọi Allow.==
flowchart TD
Req["📨 Yêu cầu API"] --> Deny["🚫 Có explicit Deny?"]
Deny -->|Có| Blocked["❌ Từ chối ngay"]
Deny -->|Không| Allow["✅ Có Allow ở identity hoặc resource policy?"]
Allow -->|Không| Blocked
Allow -->|Có| Granted["🎫 Cho phép, nếu qua boundary và SCP"]
Một điểm cực hay thi: IAM role không có mật khẩu. Khi EC2, Lambda hay container assume role, chúng nhận credential tạm thời từ AWS STS. Đó là lý do bạn không bao giờ hard-code access key trong code.
2. KMS: ba loại key và envelope encryption
KMS key (CMK) có ba nhóm chính:
- AWS owned key: bạn không thấy, không quản lý, miễn phí, dùng cho mã hoá mặc định của nhiều dịch vụ.
- AWS managed key: hiện trong console với tên dạng
aws/s3,aws/lambda. Bạn dùng được nhưng không sửa key policy, không tự cấu hình rotation. - Customer managed key: bạn tạo, kiểm soát key policy, bật rotation, dùng cho yêu cầu compliance.
Trong đề thi, cụm "cần kiểm soát key policy và audit việc dùng key" nghĩa là phải chọn customer managed key.
Về mã hoá: kms:Encrypt chỉ nhận tối đa 4 KB dữ liệu. Với dữ liệu lớn hơn, dùng envelope encryption:
1. Gọi `GenerateDataKey` với KMS key gốc, nhận về `Plaintext` (data key) và `CiphertextBlob` (data key đã mã hoá).
2. Dùng `Plaintext` mã hoá dữ liệu lớn ở local bằng AES.
3. Lưu `CiphertextBlob` bên cạnh dữ liệu, xoá `Plaintext` khỏi bộ nhớ.
4. Khi cần đọc, gọi `kms:Decrypt` trên `CiphertextBlob` để lấy lại data key rồi giải mã.
Hai công cụ phụ cần nhớ: key policy là cách chính để cấp quyền (cross-account bắt buộc phải sửa key policy), còn grant là cách cấp quyền tạm thời cho một principal mà không cần sửa key policy.
Về rotation: automatic rotation chỉ áp dụng cho symmetric customer managed key, chu kỳ một năm, và phải bật. Asymmetric key và HMAC key không hỗ trợ automatic rotation.
3. Cognito: User Pool và Identity Pool
Đây là cặp khái niệm gây lẫn nhiều nhất trong DVA-C02.
| Tiêu chí | User Pool | Identity Pool |
|---|---|---|
| Vai trò | Authentication (bạn là ai) | Authorization (bạn được dùng gì) |
| Đầu ra | JWT: ID token, access token, refresh token | AWS credentials tạm thời từ STS |
| Dùng cho | Đăng ký, đăng nhập, MFA, hosted UI, federation | Gọi trực tiếp S3, DynamoDB từ mobile/web app |
| IAM role | Không cấp trực tiếp | Gán IAM role cho authenticated và unauthenticated identity |
Cách nhớ nhanh: User Pool phát token, Identity Pool phát credentials. Trong đề, nếu câu hỏi nói "người dùng đăng nhập bằng Google/Facebook rồi cần upload file lên S3", đáp án gần như luôn là User Pool federation, sau đó đổi token ở Identity Pool để lấy AWS credentials.
Ví dụ minh hoạ
Ví dụ 1: Policy này có cho phép không?
Một Lambda chạy với role chỉ có policy s3:GetObject trên arn:aws:s3:::data-bucket/*. Bucket data-bucket có bucket policy:
{ "Effect": "Deny", "Principal": "*", "Action": "s3:*",
"Resource": "arn:aws:s3:::data-bucket/*",
"Condition": { "Bool": { "aws:SecureTransport": "false" } } }
Câu hỏi: Lambda gọi GetObject qua HTTP thường, kết quả ra sao?
Bước 1: role có Allow cho GetObject. Bước 2: bucket policy có Deny khi không dùng TLS. Bước 3: điều kiện SecureTransport = false đúng, nên Deny kích hoạt. Kết quả: bị từ chối. Đây là bẫy kinh điển: Allow đúng vẫn thua explicit Deny.
Ví dụ 2: Chọn loại KMS key
Đề cho: "Công ty cần mã hoá dữ liệu trong S3, phải tự quản lý vòng đời key, bật rotation và chứng minh với auditor rằng chỉ một số role cụ thể được dùng key." Bạn chọn customer managed key, vì chỉ loại này cho phép sửa key policy và bật rotation theo ý mình.
Ví dụ 3: User Pool hay Identity Pool?
Một app React cần cho người dùng đăng nhập bằng email/mật khẩu và sau đó đọc dữ liệu từ DynamoDB, mỗi người chỉ thấy dòng của mình. Luồng đúng: User Pool xác thực và trả ID token; app gửi token đến Identity Pool; Identity Pool đổi lấy AWS credentials tạm thời qua STS; phía DynamoDB dùng dynamodb:LeadingKeys với ${cognito-identity.amazonaws.com:sub} trong condition để giới hạn dữ liệu.
Cloze ôn nhanh:
- Trong IAM, {{c1::explicit Deny}} luôn thắng mọi Allow.
- IAM role cấp credential tạm thời thông qua {{c2::AWS STS}}.
kms:Encryptchỉ nhận trực tiếp tối đa {{c3::4 KB}} dữ liệu.- Để lấy AWS credentials cho app, dùng Cognito {{c4::Identity Pool}}.
- Automatic rotation của KMS chỉ áp dụng cho {{c5::symmetric customer managed key}}.
Thảo luận và phản tư
- Trong hệ thống bạn từng làm, có chỗ nào hard-code access key không? Nếu chuyển sang IAM role cho Lambda, bạn cần sửa những gì?
- Vì sao AWS khuyến nghị envelope encryption thay vì gọi KMS cho từng object nhỏ? Nghĩ về chi phí và độ trễ.
- Nếu sản phẩm của bạn cần cho phép người dùng chưa đăng nhập vẫn xem dữ liệu công khai, bạn cấu hình Identity Pool thế nào?
Góc chuyên gia
- Bẫy "IAM policy đủ rồi": với KMS, IAM policy một mình thường không đủ. Key policy phải cho phép, hoặc phải uỷ quyền cho IAM qua principal của account gốc. Cross-account mà quên key policy là câu hỏi sai phổ biến nhất.
- Bẫy "root user": principal
arn:aws:iam::123456789012:roottrong key policy nghĩa là "giao lại cho IAM trong account đó", không phải "chỉ root user dùng được". - Bẫy "Identity Pool xác thực": Identity Pool không xác thực người dùng. Nó chỉ đổi token hợp lệ lấy credentials.
- Rule of thumb: câu hỏi có chữ "temporary credentials" thì nghĩ ngay đến STS và IAM role; có chữ "JWT" thì nghĩ User Pool; có chữ "AWS credentials cho app" thì nghĩ Identity Pool.
- Đừng học thuộc đáp án. Hãy đọc kỹ chủ thể (Principal), hành động (Action) và tài nguyên (Resource) trong từng phương án, vì đề thường đổi đúng một trong ba thứ đó.
Tóm tắt và bước tiếp theo
Tóm lại ba trục: IAM quyết định ai được gọi API gì (và Deny luôn thắng), KMS quyết định ai được dùng key nào (key policy là trung tâm, envelope encryption cho dữ liệu lớn), Cognito chia làm hai nửa rất rõ: User Pool xác thực và phát JWT, Identity Pool đổi token thành AWS credentials.
[
{ "front": "Khi một policy cho Allow và một policy khác cho Deny, kết quả là gì?", "back": "Explicit Deny luôn thắng, request bị từ chối." },
{ "front": "IAM role cấp credential tạm thời thông qua dịch vụ nào?", "back": "AWS STS." },
{ "front": "Bốn trường quan trọng nhất trong một IAM Statement?", "back": "Effect, Action, Resource, Condition." },
{ "front": "Loại policy nào gắn trực tiếp vào tài nguyên như S3 bucket hay KMS key?", "back": "Resource-based policy." },
{ "front": "Permission boundary giới hạn điều gì?", "back": "Mức quyền tối đa của user hoặc role, nó không cấp thêm quyền." },
{ "front": "Muốn cross-account dùng được KMS key thì bắt buộc phải sửa gì?", "back": "Key policy của KMS key, cho phép principal ở account kia." },
{ "front": "GenerateDataKey trả về hai thứ gì?", "back": "Plaintext data key và CiphertextBlob (data key đã mã hoá)." },
{ "front": "Khi nào phải dùng envelope encryption?", "back": "Khi dữ liệu lớn hơn giới hạn 4 KB của kms:Encrypt." },
{ "front": "KMS grants khác key policy ở điểm nào?", "back": "Grant cấp quyền tạm thời cho principal mà không cần sửa key policy." },
{ "front": "Loại KMS key nào hỗ trợ automatic rotation?", "back": "Symmetric customer managed key, chu kỳ một năm, phải bật." },
{ "front": "Cognito User Pool làm gì?", "back": "Xác thực người dùng và trả về JWT (ID token, access token, refresh token)." },
{ "front": "Cognito Identity Pool làm gì?", "back": "Đổi token hợp lệ lấy AWS credentials tạm thời qua STS." },
{ "front": "Identity Pool có hỗ trợ người dùng chưa đăng nhập không?", "back": "Có, qua unauthenticated identity gắn với một IAM role riêng." }
]
Bài tiếp theo là Checkpoint: Compute, storage và bảo mật, nơi bạn sẽ ghép Lambda/ECS/Beanstalk, S3/DynamoDB và IAM/KMS/Cognito vào các câu hỏi tình huống tổng hợp theo đúng kiểu đề DVA-C02.