AWS CDK创建CloudWatch日志订阅过滤器至KinesisStream失败排查
问题:CloudWatch日志流转至S3时订阅过滤器创建失败
我通过AWS CDK搭建CloudWatch日志转S3的流程,涉及Kinesis的代码如下:
const rootStream = new Stream(this, 'Root', { streamName: `stream-name` }); const firehoseRole = new Role(this, `some-id`, { assumedBy: new ServicePrincipal('firehose.amazonaws.com'), roleName: `some-role-name` }); rootStream.grantRead(firehoseRole); rootStream.grant(firehoseRole, 'kinesis:DescribeStream'); const firehoseStreamToS3 = new CfnDeliveryStream(...);// 省略大量配置 const subFilterDestination = new KinesisDestination(rootStream); const subFilter = new SubscriptionFilter(this, 'xyz', { destination: subFilterDestination, filterPattern: FilterPattern.literal('some=pattern'), logGroup: myLogGroup }); subFilter.node.addDependency(myLogGroup);
部署时触发如下错误:
X:XX:XX PM | CREATE_FAILED | AWS::Logs::SubscriptionFilter | LogProcessingFilterXYZABC Resource handler returned message: "Could not deliver test message to specified Kinesis stream. Check if the given kinesis strea m is in ACTIVE state. (Service: CloudWatchLogs, Status Code: 400, Request ID: abcdef-bbbb-cccc-dddd-xxxxxxxxx)" (RequestTok en: xxxxxxxxxxxxxxxx, HandlerErrorCode: InternalFailure)
当前Kinesis Stream对应的IAM角色包含以下策略,并且通过AWS控制台创建订阅过滤器时也会报同样错误:
{ "Version": "2012-10-17", "Statement": [ { "Action": "kinesis:*", "Resource": "arn:aws:kinesis:xxxxxxxxx", "Effect": "Allow" }, { "Action": "lambda:InvokeFunction", "Resource": [ "arn:aws:lambda:lambda-to-be-invoked-by-stream", "arn:aws:lambda:lambda-to-be-invoked-by-stream:*" ], "Effect": "Allow" }, { "Action": [ "glue:BatchGetPartition", "glue:GetPartition", "glue:GetPartitions", "glue:GetTable", "glue:GetTables", "glue:GetTableVersion", "glue:GetTableVersions", "glue:BatchCreatePartition", "glue:BatchDeletePartition", "glue:CreatePartition", "glue:DeletePartition", "glue:UpdatePartition" ], "Resource": "arn:aws:glue:xxxxxxxxx", "Effect": "Allow" }, { "Action": [ "s3:GetObject*", "s3:GetBucket*", "s3:List*", "s3:DeleteObject*", "s3:PutObject*", "s3:Abort*" ], "Resource": [ "arn:aws:s3:::bucket-where-streamed-data-is-saved", "arn:aws:s3:::bucket-where-streamed-data-is-saved/*" ], "Effect": "Allow" }, { "Action": "logs:*", "Resource": "arn:aws:logs:source-log-group-from-where-I-want-to-stream:*:*", "Effect": "Allow" } ] }
原因分析与解决方法
核心原因
- Kinesis资源策略缺失CloudWatch Logs写入权限:订阅过滤器是由CloudWatch Logs服务直接向Kinesis Stream写入日志数据,当前仅配置了Firehose角色的读权限,未给CloudWatch Logs服务授予写入Kinesis的权限。
- IAM策略中Kinesis资源ARN不完整:策略里的Kinesis资源ARN仅写了
arn:aws:kinesis:xxxxxxxxx,缺少账号ID、Stream名称等关键部分,导致权限范围无效。
解决步骤
1. 给Kinesis Stream添加资源策略,允许CloudWatch Logs写入
通过CDK代码给Kinesis Stream添加资源策略,允许logs.amazonaws.com执行写入操作:
rootStream.addToResourcePolicy(new PolicyStatement({ actions: ['kinesis:PutRecord', 'kinesis:PutRecords'], principals: [new ServicePrincipal('logs.amazonaws.com')], resources: [rootStream.streamArn], // 可选:限制仅指定日志组可以写入 conditions: { 'StringEquals': { 'aws:SourceAccount': Stack.of(this).account }, 'ArnLike': { 'aws:SourceArn': myLogGroup.logGroupArn } } }));
2. 修正IAM角色中的Kinesis资源ARN
将策略中Kinesis的Resource字段修改为完整的Stream ARN,格式为:arn:aws:kinesis:区域ID:账号ID:stream/stream-name
示例修正后片段:
{ "Action": "kinesis:*", "Resource": "arn:aws:kinesis:us-east-1:123456789012:stream/stream-name", "Effect": "Allow" }
3. 确认Kinesis Stream状态(可选)
如果上述步骤执行后仍报错,进入AWS控制台检查Kinesis Stream的状态是否为ACTIVE,若为其他状态需等待其正常激活或重建Stream。
内容的提问来源于stack exchange,提问作者Akshay
相关产品推荐
相关产品推荐

