Skip to content

Commit 8334f18

Browse files
authored
feat: add support for custom Lambda@Edge policies (#333)
* feat: Add support for custom Lambda@Edge policies * docs: README and example update * chore: There's no need to provide a default value for an empty list of strings * fix: Init policy_documents with an empty array * feat: Simplify Lambda@Edge role policy handling Attribute renamed from `policy_documents` to `additional_policy`. Add `LambdaWriteCloudWatchLogs` SID to default CloudWatch policy to make overrrides possible. * fix: Remove .json reference from string object * docs: Update README file * docs: Remove '$${lambda_arn}' reference from the docs Dynamic Lambda ARN repalcements bring no value for Lambda IAM execution roles, as typically you'd like to list other AWS resources/services there, not the Lambda itself. * chore: README update
1 parent 8853705 commit 8334f18

File tree

4 files changed

+55
-21
lines changed

4 files changed

+55
-21
lines changed

examples/complete/lambda-at-edge.tf

Lines changed: 40 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,33 @@ provider "aws" {
33
alias = "us-east-1"
44
}
55

6+
data "aws_iam_policy_document" "s3_policy" {
7+
statement {
8+
sid = "AllowS3GetObjectFoo"
9+
effect = "Allow"
10+
11+
actions = [
12+
"s3:GetObject",
13+
]
14+
15+
resources = [
16+
"arn:aws:s3:::example-bucket-foo/*",
17+
]
18+
}
19+
statement {
20+
sid = "AllowS3PutObjectBar"
21+
effect = "Allow"
22+
23+
actions = [
24+
"s3:PutObject",
25+
]
26+
27+
resources = [
28+
"arn:aws:s3:::example-bucket-bar/*",
29+
]
30+
}
31+
}
32+
633
module "lambda_at_edge" {
734
source = "../../modules/lambda@edge"
835

@@ -48,13 +75,14 @@ module "lambda_at_edge" {
4875
include_body = false
4976
},
5077
origin_request = {
51-
source_zip = "origin-request.zip"
52-
runtime = "nodejs16.x"
53-
handler = "index.handler"
54-
memory_size = 128
55-
timeout = 3
56-
event_type = "origin-request"
57-
include_body = false
78+
source_zip = "origin-request.zip"
79+
runtime = "nodejs16.x"
80+
handler = "index.handler"
81+
memory_size = 128
82+
timeout = 3
83+
event_type = "origin-request"
84+
include_body = false
85+
additional_policy = data.aws_iam_policy_document.s3_policy.json
5886
},
5987
# Add security headers to the request from CF to the origin
6088
origin_response = {
@@ -83,10 +111,11 @@ module "lambda_at_edge" {
83111
EOT
84112
filename = "index.js"
85113
}]
86-
runtime = "nodejs16.x"
87-
handler = "index.handler"
88-
memory_size = 128
89-
timeout = 3
114+
runtime = "nodejs16.x"
115+
handler = "index.handler"
116+
memory_size = 128
117+
timeout = 3
118+
90119
event_type = "origin-response"
91120
include_body = false
92121
}

modules/lambda@edge/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ module "lambda_at_edge" {
7373
| <a name="input_destruction_delay"></a> [destruction\_delay](#input\_destruction\_delay) | The delay, in [Golang ParseDuration](https://pkg.go.dev/time#ParseDuration) format, to wait before destroying the Lambda@Edge<br>functions.<br><br>This delay is meant to circumvent Lambda@Edge functions not being immediately deletable following their dissociation from<br>a CloudFront distribution, since they are replicated to CloudFront Edge servers around the world.<br><br>If set to `null`, no delay will be introduced.<br><br>By default, the delay is 20 minutes. This is because it takes about 3 minutes to destroy a CloudFront distribution, and<br>around 15 minutes until the Lambda@Edge function is available for deletion, in most cases.<br><br>For more information, see: https://github.com/hashicorp/terraform-provider-aws/issues/1721. | `string` | `"20m"` | no |
7474
| <a name="input_enabled"></a> [enabled](#input\_enabled) | Set to false to prevent the module from creating any resources | `bool` | `null` | no |
7575
| <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 |
76-
| <a name="input_functions"></a> [functions](#input\_functions) | Lambda@Edge functions to create.<br><br>The key of this map is the name label of the Lambda@Edge function.<br><br>`source.filename` and `source.content` dictate the name and content of the files that will make up the Lambda function<br>source, respectively.<br><br>`runtime`, `handler`, `memory_size`, and `timeout` correspond to the attributes of the same name in the [lambda\_function](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/lambda_function)<br>resource.<br><br>`event_type` and `include_body` correspond to the attributes of the same name in the [Lambda Function association block<br>of the cloudfront\_distribution](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudfront_distribution#lambda-function-association)<br>resource. | <pre>map(object({<br> source = list(object({<br> filename = string<br> content = string<br> }))<br> runtime = string<br> handler = string<br> memory_size = number<br> timeout = number<br> event_type = string<br> include_body = bool<br> }))</pre> | n/a | yes |
76+
| <a name="input_functions"></a> [functions](#input\_functions) | Lambda@Edge functions to create.<br><br>The key of this map is the name label of the Lambda@Edge function.<br><br>One of `source`, `source_dir` or `source_zip` should be specified. These variables are mutually exclusive.<br><br>`source.filename` and `source.content` dictate the name and content of the files that will make up the Lambda function<br>source, respectively.<br><br>`source_dir` contains path to whole directory that has to be archived.<br><br>`source_zip` contains path to zip file with lambda source.<br><br>`runtime`, `handler`, `memory_size` and `timeout` correspond to the attributes of the same name in the [lambda\_function](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/lambda_function)<br>resource. See [here](https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/lambda-at-edge-function-restrictions.html) for Lambda@Edge function restrictions.<br><br>`additional_policy` contains additional IAM policies for Lambda@Edge function. It's possible to override default policy statement by providing your own statement with `LambdaWriteCloudWatchLogs` sid.<br><br>`event_type` and `include_body` correspond to the attributes of the same name in the [Lambda Function association block<br>of the cloudfront\_distribution](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudfront_distribution#lambda-function-association)<br>resource. | <pre>map(object({<br> source = optional(list(object({<br> filename = string<br> content = string<br> })))<br> source_dir = optional(string)<br> source_zip = optional(string)<br> runtime = string<br> handler = string<br> memory_size = optional(number, 128)<br> timeout = optional(number, 3)<br> additional_policy = optional(string, "{}")<br> event_type = string<br> include_body = bool<br> }))</pre> | n/a | yes |
7777
| <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 |
7878
| <a name="input_label_key_case"></a> [label\_key\_case](#input\_label\_key\_case) | Controls the letter case of the `tags` keys (label names) for tags generated by this module.<br>Does not affect keys of tags passed in via the `tags` input.<br>Possible values: `lower`, `title`, `upper`.<br>Default value: `title`. | `string` | `null` | no |
7979
| <a name="input_label_order"></a> [label\_order](#input\_label\_order) | The order in which the labels (ID elements) appear in the `id`.<br>Defaults to ["namespace", "environment", "stage", "name", "attributes"].<br>You can omit any of the 6 labels ("tenant" is the 6th), but at least one must be present. | `list(string)` | `null` | no |

modules/lambda@edge/main.tf

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ module "function_label" {
3232

3333
data "aws_iam_policy_document" "lambda_write_logs" {
3434
statement {
35+
sid = "LambdaWriteCloudWatchLogs"
3536
actions = [
3637
"logs:CreateLogGroup",
3738
"logs:CreateLogStream",
@@ -63,6 +64,7 @@ module "role" {
6364

6465
policy_documents = [
6566
data.aws_iam_policy_document.lambda_write_logs.json,
67+
each.value.additional_policy
6668
]
6769

6870
context = module.function_label[each.key].context

modules/lambda@edge/variables.tf

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ variable "functions" {
1616
`runtime`, `handler`, `memory_size` and `timeout` correspond to the attributes of the same name in the [lambda_function](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/lambda_function)
1717
resource. See [here](https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/lambda-at-edge-function-restrictions.html) for Lambda@Edge function restrictions.
1818
19+
`additional_policy` contains additional IAM policies for Lambda@Edge function. It's possible to override default policy statement by providing your own statement with `LambdaWriteCloudWatchLogs` sid.
20+
1921
`event_type` and `include_body` correspond to the attributes of the same name in the [Lambda Function association block
2022
of the cloudfront_distribution](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudfront_distribution#lambda-function-association)
2123
resource.
@@ -25,14 +27,15 @@ variable "functions" {
2527
filename = string
2628
content = string
2729
})))
28-
source_dir = optional(string)
29-
source_zip = optional(string)
30-
runtime = string
31-
handler = string
32-
memory_size = optional(number, 128)
33-
timeout = optional(number, 3)
34-
event_type = string
35-
include_body = bool
30+
source_dir = optional(string)
31+
source_zip = optional(string)
32+
runtime = string
33+
handler = string
34+
memory_size = optional(number, 128)
35+
timeout = optional(number, 3)
36+
additional_policy = optional(string, "{}")
37+
event_type = string
38+
include_body = bool
3639
}))
3740

3841
validation {
@@ -63,4 +66,4 @@ variable "destruction_delay" {
6366
For more information, see: https://github.com/hashicorp/terraform-provider-aws/issues/1721.
6467
EOT
6568
default = "20m"
66-
}
69+
}

0 commit comments

Comments
 (0)