Sửa lỗi AccessDeniedException trên AWS CloudWatch khi gọi PutLogEvents

intermediate☁️ AWS2026-03-31| AWS SDK (Python, Node.js, Go), AWS CLI, EC2, Lambda, hoặc ECS sử dụng IAM Roles.

Error Message

An error occurred (AccessDeniedException) when calling the PutLogEvents operation: User: arn:aws:sts::123456789012:assumed-role/MyAppRole is not authorized to perform: logs:PutLogEvents on resource: arn:aws:logs:us-east-1:123456789012:log-group:/aws/lambda/my-func:*
#aws#cloudwatch#iam#khắc phục lỗi#devops

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ụng DescribeLogStreams. 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 DescribeCreate 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) cho PutLogEvents trên mỗi stream.

Related Error Notes