Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[lambda] feat: allows to use YAML instead of JSON for IAM policy #692

Merged
merged 12 commits into from
Jun 21, 2023
Merged
33 changes: 26 additions & 7 deletions modules/lambda/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,27 @@ components:
# https://docs.aws.amazon.com/lambda/latest/dg/lambda-runtimes.html
runtime: python3.9
package_type: Zip # `Zip` or `Image`
policy_json: null

policy_json: |
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "ListAllBuckets",
"Effect": "Allow",
"Action": "s3:ListAllMyBuckets",
"Resource": "*"
}
]
}
iam_policy:
statements:
- sid: AllowSQSWorkerWriteAccess
effect: Allow
actions:
- sqs:SendMessage
- sqs:SendMessageBatch
resources:
- arn:aws:sqs:*:111111111111:worker-queue
# Filename example
filename: lambdas/hello-world-python/output.zip # generated by zip variable.
zip:
Expand All @@ -53,7 +72,6 @@ components:
# S3 Source Example
# s3_bucket_name: lambda-source # lambda main.tf calculates the rest of the bucket_name
# s3_key: hello-world-go.zip

```


Expand All @@ -62,7 +80,7 @@ components:

| Name | Version |
|------|---------|
| <a name="requirement_terraform"></a> [terraform](#requirement\_terraform) | >= 1.0 |
| <a name="requirement_terraform"></a> [terraform](#requirement\_terraform) | >= 1.3.0 |
| <a name="requirement_archive"></a> [archive](#requirement\_archive) | >= 2.3.0 |
| <a name="requirement_aws"></a> [aws](#requirement\_aws) | >= 4.9.0 |

Expand All @@ -77,6 +95,7 @@ components:

| Name | Source | Version |
|------|--------|---------|
| <a name="module_iam_policy"></a> [iam\_policy](#module\_iam\_policy) | cloudposse/iam-policy/aws | 1.0.1 |
| <a name="module_iam_roles"></a> [iam\_roles](#module\_iam\_roles) | ../account-map/modules/iam-roles | n/a |
| <a name="module_label"></a> [label](#module\_label) | cloudposse/label/null | 0.25.0 |
| <a name="module_lambda"></a> [lambda](#module\_lambda) | cloudposse/lambda-function/aws | 0.4.1 |
Expand All @@ -86,7 +105,6 @@ components:

| Name | Type |
|------|------|
| [aws_iam_policy.default](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_policy) | resource |
| [aws_iam_role_policy_attachment.default](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource |
| [archive_file.lambdazip](https://registry.terraform.io/providers/hashicorp/archive/latest/docs/data-sources/file) | data source |

Expand All @@ -112,8 +130,9 @@ components:
| <a name="input_environment"></a> [environment](#input\_environment) | ID element. Usually used for region e.g. 'uw2', 'us-west-2', OR role 'prod', 'staging', 'dev', 'UAT' | `string` | `null` | no |
| <a name="input_event_source_mappings"></a> [event\_source\_mappings](#input\_event\_source\_mappings) | Creates event source mappings to allow the Lambda function to get events from Kinesis, DynamoDB and SQS. The IAM role<br> of this Lambda function will be enhanced with necessary minimum permissions to get those events. | `any` | `{}` | no |
| <a name="input_filename"></a> [filename](#input\_filename) | The path to the function's deployment package within the local filesystem. If defined, The s3\_-prefixed options and image\_uri cannot be used. | `string` | `null` | no |
| <a name="input_function_name"></a> [function\_name](#input\_function\_name) | Unique name for the Lambda Function. | `string` | n/a | yes |
| <a name="input_function_name"></a> [function\_name](#input\_function\_name) | Unique name for the Lambda Function. | `string` | `null` | no |
| <a name="input_handler"></a> [handler](#input\_handler) | The function entrypoint in your code. | `string` | `null` | no |
| <a name="input_iam_policy"></a> [iam\_policy](#input\_iam\_policy) | IAM policy as Terraform object. This can be used with or instead of the `var.policy_json`. | <pre>object({<br> policy_id = optional(string, null)<br> version = optional(string, null)<br> statements = list(object({<br> sid = optional(string, null)<br> effect = optional(string, null)<br> actions = optional(list(string), null)<br> not_actions = optional(list(string), null)<br> resources = optional(list(string), null)<br> not_resources = optional(list(string), null)<br> conditions = optional(list(object({<br> test = string<br> variable = string<br> values = list(string)<br> })), [])<br> principals = optional(list(object({<br> type = string<br> identifiers = list(string)<br> })), [])<br> not_principals = optional(list(object({<br> type = string<br> identifiers = list(string)<br> })), [])<br> }))<br> })</pre> | `null` | no |
| <a name="input_iam_policy_description"></a> [iam\_policy\_description](#input\_iam\_policy\_description) | Description of the IAM policy for the Lambda IAM role | `string` | `"Minimum SSM read permissions for Lambda IAM Role"` | no |
| <a name="input_id_length_limit"></a> [id\_length\_limit](#input\_id\_length\_limit) | Limit `id` to this many characters (minimum 6).<br>Set to `0` for unlimited length.<br>Set to `null` for keep the existing setting, which defaults to `0`.<br>Does not affect `id_full`. | `number` | `null` | no |
| <a name="input_ignore_external_function_updates"></a> [ignore\_external\_function\_updates](#input\_ignore\_external\_function\_updates) | Ignore updates to the Lambda Function executed externally to the Terraform lifecycle. Set this to `true` if you're<br> using CodeDeploy, aws CLI or other external tools to update the Lambda Function code." | `bool` | `false` | no |
Expand All @@ -132,7 +151,7 @@ components:
| <a name="input_namespace"></a> [namespace](#input\_namespace) | ID element. Usually an abbreviation of your organization name, e.g. 'eg' or 'cp', to help ensure generated IDs are globally unique | `string` | `null` | no |
| <a name="input_package_type"></a> [package\_type](#input\_package\_type) | The Lambda deployment package type. Valid values are `Zip` and `Image`. | `string` | `"Zip"` | no |
| <a name="input_permissions_boundary"></a> [permissions\_boundary](#input\_permissions\_boundary) | ARN of the policy that is used to set the permissions boundary for the role | `string` | `""` | no |
| <a name="input_policy_json"></a> [policy\_json](#input\_policy\_json) | IAM policy to attach to the Lambda IAM role | `string` | `null` | no |
| <a name="input_policy_json"></a> [policy\_json](#input\_policy\_json) | IAM policy to attach to the Lambda IAM role. This can be used with or instead of the `var.iam_policy`. | `string` | `null` | no |
| <a name="input_publish"></a> [publish](#input\_publish) | Whether to publish creation/change as new Lambda Function Version. | `bool` | `false` | no |
| <a name="input_regex_replace_chars"></a> [regex\_replace\_chars](#input\_regex\_replace\_chars) | Terraform regular expression (regex) string.<br>Characters matching the regex will be removed from the ID elements.<br>If not set, `"/[^a-zA-Z0-9-]/"` is used to remove all characters other than hyphens, letters and digits. | `string` | `null` | no |
| <a name="input_region"></a> [region](#input\_region) | AWS Region | `string` | n/a | yes |
Expand Down
26 changes: 12 additions & 14 deletions modules/lambda/main.tf
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
locals {
enabled = module.this.enabled
iam_policy_enabled = local.enabled && var.policy_json != null
iam_policy_enabled = local.enabled && (try(length(var.iam_policy), 0) > 0 || var.policy_json != null)
s3_bucket_full_name = var.s3_bucket_name != null ? format("%s-%s-%s-%s-%s", module.this.namespace, module.this.tenant, module.this.environment, module.this.stage, var.s3_bucket_name) : null
}



module "label" {
source = "cloudposse/label/null"
version = "0.25.0"
Expand All @@ -15,37 +13,37 @@ module "label" {
context = module.this.context
}

resource "aws_iam_policy" "default" {
count = local.iam_policy_enabled ? 1 : 0
module "iam_policy" {
count = local.iam_policy_enabled ? 1 : 0
source = "cloudposse/iam-policy/aws"
version = "1.0.1"

name = module.label.id
path = "/"
description = format("%s Lambda policy", module.label.id)
policy = var.policy_json
iam_policy_enabled = true
iam_policy = var.iam_policy
iam_source_policy_documents = [var.policy_json]
gberenice marked this conversation as resolved.
Show resolved Hide resolved

tags = module.this.tags
context = module.this.context
}

resource "aws_iam_role_policy_attachment" "default" {
count = local.iam_policy_enabled ? 1 : 0

role = module.lambda.role_name
policy_arn = aws_iam_policy.default[0].arn
policy_arn = module.iam_policy[0].policy_arn
}

data "archive_file" "lambdazip" {
count = var.zip.enabled ? 1 : 0
type = "zip"
output_path = "${path.module}/lambdas/${var.zip.output}"

source_dir = "${path.module}/lambdas/${var.zip.input_dir}"
source_dir = "${path.module}/lambdas/${var.zip.input_dir}"
}

module "lambda" {
source = "cloudposse/lambda-function/aws"
version = "0.4.1"

function_name = module.label.id
function_name = coalesce(var.function_name, module.label.id)
gberenice marked this conversation as resolved.
Show resolved Hide resolved
description = var.description
handler = var.handler
lambda_environment = var.lambda_environment
Expand Down
33 changes: 32 additions & 1 deletion modules/lambda/variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ variable "region" {
variable "function_name" {
type = string
description = "Unique name for the Lambda Function."
default = null
}

variable "architectures" {
Expand Down Expand Up @@ -268,7 +269,37 @@ variable "iam_policy_description" {

variable "policy_json" {
type = string
description = "IAM policy to attach to the Lambda IAM role"
description = "IAM policy to attach to the Lambda IAM role. This can be used with or instead of the `var.iam_policy`."
gberenice marked this conversation as resolved.
Show resolved Hide resolved
default = null
}

variable "iam_policy" {
type = object({
policy_id = optional(string, null)
version = optional(string, null)
statements = list(object({
sid = optional(string, null)
effect = optional(string, null)
actions = optional(list(string), null)
not_actions = optional(list(string), null)
resources = optional(list(string), null)
not_resources = optional(list(string), null)
conditions = optional(list(object({
test = string
variable = string
values = list(string)
})), [])
principals = optional(list(object({
type = string
identifiers = list(string)
})), [])
not_principals = optional(list(object({
type = string
identifiers = list(string)
})), [])
}))
})
description = "IAM policy as Terraform object. This can be used with or instead of the `var.policy_json`."
gberenice marked this conversation as resolved.
Show resolved Hide resolved
default = null
}

Expand Down
2 changes: 1 addition & 1 deletion modules/lambda/versions.tf
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
terraform {
required_version = ">= 1.0"
required_version = ">= 1.3.0"

required_providers {
aws = {
Expand Down