terraform-aws-modules/terraform-aws-lambda

Example of how to attach policy statements using for_each

wonboyn opened this issue · 8 comments

Description

I need to create a number of functions. I have configured a map(object) variable with the various values for each function (description, handler, runtime etc) and then use for_each within the module. I have the basic build working and am now attempting to add custom policies to some of the functions but am struggling to figure out how to define the appropriate statement object or policy as part of the variable I'm using.

  • ✋ I have searched the open/closed issues and my issue is not listed.

Versions

  • Module version [Required]: 4.9.0
  • Terraform version: v1.3.7
  • Provider version(s):
  • provider registry.terraform.io/hashicorp/aws v4.53.0
  • provider registry.terraform.io/hashicorp/external v2.2.3
  • provider registry.terraform.io/hashicorp/local v2.3.0
  • provider registry.terraform.io/hashicorp/null v3.2.1

Reproduction Code [Required]

module "lambda_function" {
   source = "terraform-aws-modules/lambda/aws"
   version = "4.9.0"

   for_each = var.lambda

   function_name = each.key
   description  = each.value["description"]
   environment_variables    = each.value["vars"]
   handler = each.value["handler"]
   runtime = each.value["runtime"]
   memory_size = each.value["memory"]
   source_path  = each.value["source"]
   tags  = merge(
            var.aws_resource_tags,
            each.value["tags"],
            tomap({"environment" = var.aws_environment}))
   timeout = each.value["timeout"]

   attach_policy_statements = each.value["policy_attach"]
   policy_statements        = each.value["policy"]
}
`

`
variable "lambda" {
  description = "The lambda functions that are required"
  type  = map(object({
         description   = string
         handler       = string
         memory        = number
         policies      = string
         policy_attach = bool
         runtime       = string
         source        = string
         tags          = map(string)
         timeout       = number
         vars          = map(string)
     }))
}

lambda = {
    child = {
        description   = "Child1"
        handler       = "lambda_function.lambda_handler"
        memory        = 128
        policies      = {}
        policy_attach = false
        runtime       = "python3.9"
        source        = "../services/src/child1/lambda_function.py"
        timeout       = 10
        tags          = {}
        vars          = {}
    },
    main = {
        description   = "Parent"
        handler       = "lambda_function.lambda_handler"
        memory        = 128
        policies      = "{ lambda = { effect = \"Allow\", actions = \"lambda:InvokeFunction\", resources = \"*\" }}"
        policy_attach = true
        runtime       = "python3.9"
        source        = "../services/src/main/lambda_function.py"
        timeout       = 5
        tags          = {}
        vars          = { fred = "somevalue" }
    }
}

Steps to reproduce the behavior:

No

Yes

Followed the simple example, then attempted to add policy_statements as shown in the complete example.

Expected behavior

A way to pass in a policy statement (or json) conditionally for each iteration of the for_each loop.

This issue has been automatically marked as stale because it has been open 30 days
with no activity. Remove stale label or comment or this issue will be closed in 10 days

Any assistance on this would be greatly appreciated

This issue has been automatically marked as stale because it has been open 30 days
with no activity. Remove stale label or comment or this issue will be closed in 10 days

Any assistance on this would be greatly appreciated

You've accomplished almost everything correctly, but you should pass policy_statements as map or any (not string).

Please check out the code in examples/complete:

attach_policy_statements = true
policy_statements = {
dynamodb = {
effect = "Allow",
actions = ["dynamodb:BatchWriteItem"],
resources = ["arn:aws:dynamodb:eu-west-1:052212379155:table/Test"]
},
s3_read = {
effect = "Deny",
actions = ["s3:HeadObject", "s3:GetObject"],
resources = ["arn:aws:s3:::my-bucket/*"]
}
}

So, the changes to your code should look something like this:

module "lambda_function" {
   source = "terraform-aws-modules/lambda/aws"
   version = "4.9.0"

   for_each = var.lambda

# omitted ...

   attach_policy_statements = each.value["policy_attach"]
   policy_statements        = each.value["policy"]
}
`

`
variable "lambda" {
  description = "The lambda functions that are required"
  type  = map(object({
# omitted ...
         policies      = any # not `string`
     }))
}

lambda = {
    main = {
        policies      = {
    dynamodb = {
      effect    = "Allow",
      actions   = ["dynamodb:BatchWriteItem"],
      resources = ["arn:aws:dynamodb:eu-west-1:052212379155:table/Test"]
    },
    s3_read = {
      effect    = "Deny",
      actions   = ["s3:HeadObject", "s3:GetObject"],
      resources = ["arn:aws:s3:::my-bucket/*"]
    }
  }
        policy_attach = true
    }
}

Please note that there are 6 distinct ways to attach IAM policies for Lambda functions described here - https://github.com/terraform-aws-modules/terraform-aws-lambda#additional-iam-policies-for-lambda-functions

This issue has been automatically marked as stale because it has been open 30 days
with no activity. Remove stale label or comment or this issue will be closed in 10 days

This issue was automatically closed because of stale in 10 days

I'm going to lock this issue because it has been closed for 30 days ⏳. This helps our maintainers find and focus on the active issues. If you have found a problem that seems similar to this, please open a new issue and complete the issue template so we can capture all the details necessary to investigate further.