如何配置CloudWatch将CreateLogGroup消息发送至EventBridge?
问题:CloudTrail部署报错,无法转发CloudWatch CreateLogGroup事件到EventBridge
我需要让CloudWatch将CreateLogGroup事件发送至EventBridge,已知该需求需通过CloudTrail转发,但部署CloudFormation模板时持续报错:
AWS::CloudTrail::Trail - "Invalid request provided: Incorrect S3 bucket policy is detected for bucket"
原CloudFormation模板:
AWSTemplateFormatVersion: '2010-09-09' Outputs: HelloFunction: Value: Ref: HelloFunction WatcherFunction: Value: Ref: WatcherFunction WatcherTrailBucket: Value: Ref: WatcherTrailBucket Parameters: MemorySizeDefault: Default: '512' Type: String RuntimeVersion: Default: '3.8' Type: String TimeoutDefault: Default: '5' Type: String Resources: HelloFunction: Properties: Code: ZipFile: | def handler(event, context): print (event) Handler: index.handler MemorySize: Ref: MemorySizeDefault Role: Fn::GetAtt: - HelloFunctionRole - Arn Runtime: Fn::Sub: python${RuntimeVersion} Timeout: Ref: TimeoutDefault Type: AWS::Lambda::Function HelloFunctionRole: Properties: AssumeRolePolicyDocument: Statement: - Action: sts:AssumeRole Effect: Allow Principal: Service: lambda.amazonaws.com Version: '2012-10-17' Policies: - PolicyDocument: Statement: - Action: - logs:CreateLogGroup - logs:CreateLogStream - logs:PutLogEvents Effect: Allow Resource: '*' Version: '2012-10-17' PolicyName: Fn::Sub: hello-function-role-policy-${AWS::StackName} Type: AWS::IAM::Role WatcherFunction: Properties: Code: ZipFile: | def handler(event, context): print (event) Handler: index.handler MemorySize: Ref: MemorySizeDefault Role: Fn::GetAtt: - WatcherFunctionRole - Arn Runtime: Fn::Sub: python${RuntimeVersion} Timeout: Ref: TimeoutDefault Type: AWS::Lambda::Function WatcherFunctionRole: Properties: AssumeRolePolicyDocument: Statement: - Action: sts:AssumeRole Effect: Allow Principal: Service: lambda.amazonaws.com Version: '2012-10-17' Policies: - PolicyDocument: Statement: - Action: - logs:CreateLogGroup - logs:CreateLogStream - logs:PutLogEvents Effect: Allow Resource: '*' Version: '2012-10-17' PolicyName: Fn::Sub: watcher-function-role-policy-${AWS::StackName} Type: AWS::IAM::Role WatcherEventRule: Type: AWS::Events::Rule Properties: EventPattern: source: - aws.logs detail-type: - "AWS API Call via CloudTrail" detail: eventName: - CreateLogGroup Targets: - Id: Fn::Sub: watcher-event-rule-${AWS::StackName} Arn: Fn::GetAtt: - WatcherFunction - Arn State: ENABLED WatcherEventRulePermission: Type: AWS::Lambda::Permission Properties: Action: lambda:InvokeFunction Principal: events.amazonaws.com FunctionName: Ref: WatcherFunction SourceArn: Fn::GetAtt: - WatcherEventRule - Arn WatcherTrailBucket: Type: AWS::S3::Bucket WatcherTrailBucketPolicy: DependsOn: - WatcherTrailBucket Type: AWS::S3::BucketPolicy Properties: Bucket: Ref: WatcherTrailBucket PolicyDocument: Version: '2012-10-17' Statement: - Effect: Allow Principal: Service: cloudtrail.amazonaws.com Action: s3:GetBucketAcl Resource: "*" Condition: {} - Effect: Allow Principal: Service: cloudtrail.amazonaws.com Action: s3:PutObject Resource: "*" Condition: StringEquals: s3:x-amz-acl: bucket-owner-full-control WatcherTrail: Type: AWS::CloudTrail::Trail Properties: EventSelectors: - ReadWriteType: All IsLogging: true S3BucketName: Ref: WatcherTrailBucket IsLogging: true S3KeyPrefix: logs/
修复方案
问题点说明
- S3桶策略Resource通配符不合法:CloudTrail要求桶策略必须明确指定目标桶的ARN,不能使用
"*",否则会触发权限校验错误。 - Trail资源重复配置IsLogging:模板中
WatcherTrail资源里写了两次IsLogging: true,属于冗余配置,需要移除其中一个。 - 缺少账户ID验证条件:为了安全性,桶策略应添加条件限制只有当前AWS账户的CloudTrail能写入该桶。
修改后的完整模板
AWSTemplateFormatVersion: '2010-09-09' Outputs: HelloFunction: Value: Ref: HelloFunction WatcherFunction: Value: Ref: WatcherFunction WatcherTrailBucket: Value: Ref: WatcherTrailBucket Parameters: MemorySizeDefault: Default: '512' Type: String RuntimeVersion: Default: '3.8' Type: String TimeoutDefault: Default: '5' Type: String Resources: HelloFunction: Properties: Code: ZipFile: | def handler(event, context): print (event) Handler: index.handler MemorySize: Ref: MemorySizeDefault Role: Fn::GetAtt: - HelloFunctionRole - Arn Runtime: Fn::Sub: python${RuntimeVersion} Timeout: Ref: TimeoutDefault Type: AWS::Lambda::Function HelloFunctionRole: Properties: AssumeRolePolicyDocument: Statement: - Action: sts:AssumeRole Effect: Allow Principal: Service: lambda.amazonaws.com Version: '2012-10-17' Policies: - PolicyDocument: Statement: - Action: - logs:CreateLogGroup - logs:CreateLogStream - logs:PutLogEvents Effect: Allow Resource: '*' Version: '2012-10-17' PolicyName: Fn::Sub: hello-function-role-policy-${AWS::StackName} Type: AWS::IAM::Role WatcherFunction: Properties: Code: ZipFile: | def handler(event, context): print (event) Handler: index.handler MemorySize: Ref: MemorySizeDefault Role: Fn::GetAtt: - WatcherFunctionRole - Arn Runtime: Fn::Sub: python${RuntimeVersion} Timeout: Ref: TimeoutDefault Type: AWS::Lambda::Function WatcherFunctionRole: Properties: AssumeRolePolicyDocument: Statement: - Action: sts:AssumeRole Effect: Allow Principal: Service: lambda.amazonaws.com Version: '2012-10-17' Policies: - PolicyDocument: Statement: - Action: - logs:CreateLogGroup - logs:CreateLogStream - logs:PutLogEvents Effect: Allow Resource: '*' Version: '2012-10-17' PolicyName: Fn::Sub: watcher-function-role-policy-${AWS::StackName} Type: AWS::IAM::Role WatcherEventRule: Type: AWS::Events::Rule Properties: EventPattern: source: - aws.logs detail-type: - "AWS API Call via CloudTrail" detail: eventName: - CreateLogGroup Targets: - Id: Fn::Sub: watcher-event-rule-${AWS::StackName} Arn: Fn::GetAtt: - WatcherFunction - Arn State: ENABLED WatcherEventRulePermission: Type: AWS::Lambda::Permission Properties: Action: lambda:InvokeFunction Principal: events.amazonaws.com FunctionName: Ref: WatcherFunction SourceArn: Fn::GetAtt: - WatcherEventRule - Arn WatcherTrailBucket: Type: AWS::S3::Bucket WatcherTrailBucketPolicy: DependsOn: - WatcherTrailBucket Type: AWS::S3::BucketPolicy Properties: Bucket: Ref: WatcherTrailBucket PolicyDocument: Version: '2012-10-17' Statement: - Effect: Allow Principal: Service: cloudtrail.amazonaws.com Action: s3:GetBucketAcl Resource: !Sub "arn:aws:s3:::${WatcherTrailBucket}" Condition: StringEquals: aws:SourceAccount: !Ref AWS::AccountId - Effect: Allow Principal: Service: cloudtrail.amazonaws.com Action: s3:PutObject Resource: !Sub "arn:aws:s3:::${WatcherTrailBucket}/logs/*" Condition: StringEquals: s3:x-amz-acl: bucket-owner-full-control aws:SourceAccount: !Ref AWS::AccountId WatcherTrail: Type: AWS::CloudTrail::Trail Properties: EventSelectors: - ReadWriteType: All IncludeManagementEvents: true DataResources: [] IsLogging: true S3BucketName: Ref: WatcherTrailBucket S3KeyPrefix: logs/
关键修改说明
- 桶策略Resource:将
"*"替换为具体的桶ARN(!Sub "arn:aws:s3:::${WatcherTrailBucket}")和桶内路径ARN(!Sub "arn:aws:s3:::${WatcherTrailBucket}/logs/*")。 - 添加SourceAccount条件:通过
aws:SourceAccount: !Ref AWS::AccountId限制只有当前账户的CloudTrail能访问桶,提升安全性。 - 移除重复的IsLogging:删除Trail资源中重复的
IsLogging: true配置。 - 完善EventSelectors:显式添加
IncludeManagementEvents: true确保管理事件(如CreateLogGroup)被捕获。
内容的提问来源于stack exchange,提问作者Justin
相关产品推荐
相关产品推荐

