Kịch bản
Bạn vừa mới triển khai một microservice hoặc Lambda function mới. Mọi thứ có vẻ ổn cho đến khi bạn kiểm tra nhật ký (logs). Thay vì thấy dữ liệu ứng dụng, bạn lại gặp một loạt lỗi AccessDeniedException. Ứng dụng của bạn đang cố gắng đẩy dữ liệu lên CloudWatch, nhưng AWS đang từ chối truy cập.
An error occurred (AccessDeniedException) when calling the PutLogEvents operation: User: arn:aws:sts::123456789012:assumed-role/MyRole is not authorized to perform: logs:PutLogEvents on resource
Sự cố này rất gây ức chế vì nó thường xảy ra ngay cả khi bạn nghĩ rằng mình đã cấp đủ quyền. Ngay cả khi bạn đã đính kèm CloudWatchLogsFullAccess, một hạn chế nhỏ ở cấp tài nguyên (resource-level) hoặc thiếu quyền KMS vẫn có thể làm gián đoạn luồng ghi nhật ký của bạn.
Tại sao điều này lại xảy ra?
Hành động PutLogEvents khắt khe hơn hầu hết các thao tác khác trên AWS. Dưới đây là những nguyên nhân phổ biến nhất:
- Thiếu các hành động hỗ trợ (Helper Actions): Nhiều SDK, chẳng hạn như Boto3 cho Python, không chỉ gọi mỗi
PutLogEvents. Chúng thường kiểm tra sự tồn tại của stream trước bằng cách sử dụngDescribeLogStreams. Nếu thiếu hành động đó, toàn bộ quá trình sẽ thất bại. - Ký tự đại diện (Wildcard) ở cuối: Một sai lầm phổ biến là trỏ chính sách IAM của bạn vào Log Group ARN mà không thêm
:*. Nếu không có ký tự đại diện đó, chính sách chỉ cấp quyền cho nhóm (group), chứ không phải các streams bên trong nó. - Mã hóa KMS: Nếu bạn đã mã hóa nhật ký của mình bằng Customer Managed Key (CMK), vai trò IAM của bạn cần nhiều hơn là chỉ quyền Log. Nó cần quyền để sử dụng khóa cụ thể đó.
- Rào chắn tổ chức (Organization Guardrails): Trong nhiều tài khoản AWS doanh nghiệp, Service Control Policies (SCPs) đóng vai trò là lớp ghi đè chính. Nếu một SCP từ chối
logs:*, chính sách IAM cục bộ của bạn sẽ không có tác dụng.
Các bước khắc phục
1. Xác định chính xác ARN của tài nguyên
Xác định Log Group cụ thể đang gây ra vấn đề. Mở CloudWatch Console và đi tới Log Groups. Lấy ARN từ tab Log group details. Nó sẽ trông như thế này:
arn:aws:logs:us-east-1:123456789012:log-group:my-app-logs
2. Tinh chỉnh chính sách IAM
Mở vai trò IAM được đề cập trong thông báo lỗi của bạn. Thay vì sử dụng các quyền rộng, hãy áp dụng chính sách có mục tiêu này. Nó bao gồm các hành động Describe và Create mà các SDK hiện đại yêu cầu để hoạt động trơn tru.
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"logs:CreateLogStream",
"logs:DescribeLogStreams",
"logs:PutLogEvents"
],
"Resource": [
"arn:aws:logs:us-east-1:123456789012:log-group:my-app-logs:*"
]
}
]
}
Mẹo nhỏ: Lưu ý ký tự :* ở cuối chuỗi Resource. Điều này là bắt buộc đối với PutLogEvents vì về mặt kỹ thuật, hành động này xảy ra trên log stream, vốn là một thành phần con của log group.
3. Kiểm tra quyền của khóa KMS
Nhật ký của bạn có được mã hóa bằng một khóa tùy chỉnh không? Nếu có, vai trò IAM của bạn cần phải là một "Key User". Thêm câu lệnh này vào chính sách của vai trò để cho phép nó mã hóa dữ liệu nhật ký ngay tức thì:
{
"Effect": "Allow",
"Action": [
"kms:Decrypt",
"kms:GenerateDataKey*"
],
"Resource": "arn:aws:kms:us-east-1:123456789012:key/your-key-id"
}
Kiểm tra kết quả
Các thay đổi IAM thường có hiệu lực sau vài giây, mặc dù đôi khi có thể mất tới một phút để lan truyền. Bạn có thể kiểm tra kết nối ngay lập tức bằng AWS CLI từ máy cục bộ của mình (giả sử bạn có cùng các quyền tương đương):
1. Tạo một stream thử nghiệm:
aws logs create-log-stream --log-group-name my-app-logs --log-stream-name manual-test
2. Gửi một sự kiện giả:
aws logs put-log-events \
--log-group-name my-app-logs \
--log-stream-name manual-test \
--log-events timestamp=$(date +%s000),message="Permission test success"
Nếu CLI trả về một nextSequenceToken, nghĩa là mọi thứ đã hoạt động trở lại.
Tóm tắt các thực hành tốt nhất
- Sử dụng quyền tối thiểu (Least Privilege): Đừng sử dụng
Resource: "*". Đó là một rủi ro bảo mật. Hãy giới hạn quyền truy cập vào các Log Group cụ thể mà ứng dụng của bạn thực sự sử dụng. - Hạ tầng dưới dạng mã (Infrastructure as Code): Định nghĩa các quyền này trong Terraform hoặc AWS CDK. Các thay đổi thủ công trên console rất khó theo dõi và thậm chí còn khó tái lập hơn khi bạn chuyển từ môi trường Staging sang Production.
- Theo dõi điều tiết (Throttling): Nếu bạn đã sửa quyền nhưng nhật ký vẫn bị thiếu, hãy kiểm tra lỗi
ThrottlingException. Bạn có thể đang chạm giới hạn 5 giao dịch mỗi giây (TPS) choPutLogEventstrên mỗi stream.

