Search code examples
aws-lambdacloudcustodian

Containerize cloud custodian lambda in AWS to tag RDS instance


I am trying to tag RDS Clusters and Standalone instances as well using cloud custodian in a AWS lambda function within a container. However I am getting this error.

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'}

Below is my 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

And below is my terraform code for IAM role and policy for use with the lambda

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

What could I be possibly missing?


Solution

  • Found out I had a typo in "rds:AddTagsToResources", action, correcting it to "rds:AddTagsToResource", worked.