在AWS Lambda容器中用Cloud Custodian标记RDS遇权限拒绝问题排查
问题
在容器化的AWS Lambda函数中使用Cloud Custodian为RDS集群和独立实例打标签时,触发权限拒绝错误:
custodian.actions:ERROR Exception with tags: {'CustodianStopped': 'True'} Resource Tag Errors {'arn:aws:rds:xxx-xxxx-xxxx:xxxxxxxx:cluster:my-rds-cluster': 'AccessDenied', 'arn:aws:rds:xxx-xxxx-xxxx:xxxxxxxx:cluster:my-rds-instance': 'AccessDenied'}
相关配置文件如下:
Dockerfile
FROM python:3.8-slim # Install custodian RUN pip install c7n # COPY your custodian policy COPY policy.yml /var/task/policy.yml COPY entrypoint.sh /var/task/entrypoint.sh RUN chmod +x /var/task/entrypoint.sh ENV AWS_DEFAULT_REGION=us-east-1 CMD ["/var/task/entrypoint.sh"]
entrypoint.sh
#!/bin/bash # Run the custodian command with the policy custodian run -s /tmp /var/task/policy.yml --verbose --cache-period 0 exit 0
Terraform IAM配置
resource "aws_iam_role" "custodian_lambda" { name = "CustodianLambdaRole" assume_role_policy = jsonencode({ Version = "2012-10-17", Statement = [ { Action = "sts:AssumeRole", Principal = { Service = "lambda.amazonaws.com" }, Effect = "Allow" Sid = "" } ] }) } resource "aws_iam_role_policy_attachment" "custodian_policy_attachment" { policy_arn = aws_iam_policy.custodian_lambda_policy.arn role = aws_iam_role.custodian_lambda.name } resource "aws_iam_policy" "custodian_lambda_policy" { name = "CustodianLambdaPolicy" description = "Policy for Cloud Custodian RDS Lambda Functions" policy = jsonencode({ Version = "2012-10-17" Statement = [ { Sid = "CloudWatchLogAccess" Effect = "Allow" Action = [ "logs:CreateLogGroup", "logs:CreateLogStream", "logs:PutLogEvents" ], Resource = "arn:aws:logs:*:*:*" }, { Sid = "RDSClusterAccess" Effect = "Allow", Action = [ "rds:DescribeDBClusterParameters", "rds:StartDBCluster", "rds:StopDBCluster", "rds:DescribeDBEngineVersions", "rds:DescribeGlobalClusters", "rds:DescribePendingMaintenanceActions", "rds:DescribeDBLogFiles", "rds:StopDBInstance", "rds:StartDBInstance", "rds:DescribeReservedDBInstancesOfferings", "rds:DescribeReservedDBInstances", "rds:ListTagsForResource", "rds:AddTagsToResources", "rds:RemoveTagsFromResources", "rds:DescribeValidDBInstanceModifications", "rds:DescribeDBInstances", "rds:DescribeSourceRegions", "rds:DescribeDBClusterEndpoints", "rds:DescribeDBClusters", "rds:DescribeDBClusterParameterGroups", "rds:DescribeOptionGroups" ], Resource = "*" }, { Sid = "CloudWatchMetricsAccess" Effect = "Allow" Action = [ "cloudwatch:GetMetricStatistics", "cloudwatch:ListMetrics" ], Resource = "*" }, { Sid = "TagResourcesPermission" Effect = "Allow" Action = [ "tag:TagResources", "tag:UntagResources", "lambda:TagResource", "lambda:ListTags", "lambda:UntagResource" ], Resource = "*" } ] }) } resource "aws_lambda_function" "lambda"{ function_name = "stop-inactive-rds-instances" role = aws_iam_role.custodian_lambda.arn image_uri = "xxxxxxxxxxx.yyy.ecr.us-east-1.amazonaws.com/custodian:0.9.44" timeout = 15 package_type = "Image" } ... # event rules and target + aws_lambda_permission
原因分析及解决方案
核心问题:RDS集群标签操作的权限差异
Cloud Custodian针对RDS集群打标签时,不会使用通用的tag:TagResources权限,也不支持批量操作的rds:AddTagsToResources(复数形式),而是依赖RDS专属的单数形式权限:rds:AddTagsToResource和rds:RemoveTagsFromResource。你当前配置的复数权限仅适用于批量操作普通RDS实例,无法作用于RDS集群。
修复步骤
更新IAM策略中的RDS权限:
在RDSClusterAccess语句的Action列表中,将rds:AddTagsToResources替换为rds:AddTagsToResource,同时把rds:RemoveTagsFromResources替换为rds:RemoveTagsFromResource:"Action": [ // 保留原有其他RDS权限... "rds:ListTagsForResource", "rds:AddTagsToResource", "rds:RemoveTagsFromResource" // 保留原有其他RDS权限... ]验证权限范围:
确保Resource字段为"*"或者明确包含目标RDS集群的ARN,避免资源范围限制导致权限失效。重新部署配置:
执行terraform apply更新IAM策略,之后重新触发Lambda函数测试标签操作。
额外检查点
- 确认Lambda角色已正确关联更新后的IAM策略,无策略未附加的情况。
- 检查Cloud Custodian的
policy.yml中,RDS集群的标签动作配置正确,未指定错误的资源类型。
内容的提问来源于stack exchange,提问作者basebandit
相关产品推荐
相关产品推荐

