Skip to content

Commit e41af5e

Browse files
committed
refactor / clean terraform code for webhook
1 parent 9cff596 commit e41af5e

File tree

20 files changed

+216
-443
lines changed

20 files changed

+216
-443
lines changed

.terraform.lock.hcl

Lines changed: 21 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

lambdas/functions/webhook/src/ConfigLoader.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,15 @@ import { getParameter } from '@aws-github-runner/aws-ssm-util';
22
import { RunnerMatcherConfig } from './sqs';
33
import { logger } from '@aws-github-runner/aws-powertools-util';
44

5+
/**
6+
* Base class for loading configuration from environment variables and SSM parameters.
7+
*
8+
* @remarks
9+
* To avoid usages or checking values can be undefined we assume that configuration is
10+
* set to
11+
* - empty string if the property is not relevant
12+
* - empty list if the property is not relevant
13+
*/
514
abstract class BaseConfig {
615
static instance: BaseConfig | null = null;
716
configLoadingErrors: string[] = [];

modules/webhook/direct/main.tf

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
2+
resource "null_resource" "ssm_parameter_runner_matcher_config" {
3+
triggers = {
4+
version = var.config.ssm_parameter_runner_matcher_config.version
5+
}
6+
}

modules/webhook/webhook/outputs.tf renamed to modules/webhook/direct/outputs.tf

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,16 @@
1-
# output "gateway" {
2-
# value = aws_apigatewayv2_api.webhook
3-
# }
4-
51
output "webhook_lambda_function" {
62
value = aws_lambda_function.webhook
73
}
84

5+
6+
output "webhook" {
7+
value = {
8+
lambda = aws_lambda_function.webhook
9+
log_group = aws_cloudwatch_log_group.webhook
10+
role = aws_iam_role.webhook_lambda
11+
}
12+
}
13+
914
# output "lambda_log_group" {
1015
# value = aws_cloudwatch_log_group.webhook
1116
# }

modules/webhook/direct/variables.tf

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
variable "config" {
2+
description = "Configuration object for all variables."
3+
type = object({
4+
prefix = string
5+
archive = optional(object({
6+
enable = optional(bool, true)
7+
retention_days = optional(number, 7)
8+
}), {})
9+
tags = optional(map(string), {})
10+
11+
lambda_subnet_ids = optional(list(string), [])
12+
lambda_security_group_ids = optional(list(string), [])
13+
sqs_job_queues_arns = list(string)
14+
sqs_workflow_job_queue = optional(object({
15+
id = string
16+
arn = string
17+
}), null)
18+
lambda_zip = optional(string, null)
19+
lambda_memory_size = optional(number, 256)
20+
lambda_timeout = optional(number, 10)
21+
role_permissions_boundary = optional(string, null)
22+
role_path = optional(string, null)
23+
logging_retention_in_days = optional(number, 180)
24+
logging_kms_key_id = optional(string, null)
25+
lambda_s3_bucket = optional(string, null)
26+
lambda_s3_key = optional(string, null)
27+
lambda_s3_object_version = optional(string, null)
28+
lambda_apigateway_access_log_settings = optional(object({
29+
destination_arn = string
30+
format = string
31+
}), null)
32+
repository_white_list = optional(list(string), [])
33+
kms_key_arn = optional(string, null)
34+
log_level = optional(string, "info")
35+
lambda_runtime = optional(string, "nodejs20.x")
36+
aws_partition = optional(string, "aws")
37+
lambda_architecture = optional(string, "arm64")
38+
github_app_parameters = object({
39+
webhook_secret = map(string)
40+
})
41+
tracing_config = optional(object({
42+
mode = optional(string, null)
43+
capture_http_requests = optional(bool, false)
44+
capture_error = optional(bool, false)
45+
}), {})
46+
lambda_tags = optional(map(string), {})
47+
api_gw_source_arn = string
48+
ssm_parameter_runner_matcher_config = object({
49+
name = string
50+
arn = string
51+
version = string
52+
})
53+
})
54+
}

modules/webhook/webhook/webhook.tf renamed to modules/webhook/direct/webhook.tf

Lines changed: 7 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,7 @@
11
locals {
2-
# config with combined key and order
3-
runner_matcher_config = { for k, v in var.config.runner_matcher_config : format("%03d-%s", v.matcherConfig.priority, k) => merge(v, { key = k }) }
4-
5-
# sorted list
6-
runner_matcher_config_sorted = [for k in sort(keys(local.runner_matcher_config)) : local.runner_matcher_config[k]]
7-
8-
# handler
9-
lambda_handler_function = var.config.legacy_mode ? "index.githubWebhook" : "index.eventBridgeWebhook"
10-
112
lambda_zip = var.config.lambda_zip == null ? "${path.module}/../../../lambdas/functions/webhook/webhook.zip" : var.config.lambda_zip
12-
133
}
144

15-
resource "aws_ssm_parameter" "runner_matcher_config" {
16-
name = "${var.config.ssm_paths.root}/${var.config.ssm_paths.webhook}/runner-matcher-config"
17-
type = "String"
18-
value = jsonencode(local.runner_matcher_config_sorted)
19-
tier = var.config.matcher_config_parameter_store_tier
20-
}
21-
22-
235
resource "aws_lambda_function" "webhook" {
246
s3_bucket = var.config.lambda_s3_bucket != null ? var.config.lambda_s3_bucket : null
257
s3_key = var.config.lambda_s3_key != null ? var.config.lambda_s3_key : null
@@ -28,7 +10,7 @@ resource "aws_lambda_function" "webhook" {
2810
source_code_hash = var.config.lambda_s3_bucket == null ? filebase64sha256(local.lambda_zip) : null
2911
function_name = "${var.config.prefix}-webhook"
3012
role = aws_iam_role.webhook_lambda.arn
31-
handler = local.lambda_handler_function
13+
handler = "index.githubWebhook"
3214
runtime = var.config.lambda_runtime
3315
memory_size = var.config.lambda_memory_size
3416
timeout = var.config.lambda_timeout
@@ -45,7 +27,7 @@ resource "aws_lambda_function" "webhook" {
4527
PARAMETER_GITHUB_APP_WEBHOOK_SECRET = var.config.github_app_parameters.webhook_secret.name
4628
REPOSITORY_ALLOW_LIST = jsonencode(var.config.repository_white_list)
4729
SQS_WORKFLOW_JOB_QUEUE = try(var.config.sqs_workflow_job_queue.id, null)
48-
PARAMETER_RUNNER_MATCHER_CONFIG_PATH = aws_ssm_parameter.runner_matcher_config.name
30+
PARAMETER_RUNNER_MATCHER_CONFIG_PATH = var.config.ssm_parameter_runner_matcher_config.name
4931
} : k => v if v != null
5032
}
5133
}
@@ -68,12 +50,10 @@ resource "aws_lambda_function" "webhook" {
6850
}
6951

7052
lifecycle {
71-
replace_triggered_by = [aws_ssm_parameter.runner_matcher_config, null_resource.github_app_parameters]
53+
replace_triggered_by = [null_resource.ssm_parameter_runner_matcher_config, null_resource.github_app_parameters]
7254
}
7355
}
7456

75-
76-
7757
resource "aws_cloudwatch_log_group" "webhook" {
7858
name = "/aws/lambda/${aws_lambda_function.webhook.function_name}"
7959
retention_in_days = var.config.logging_retention_in_days
@@ -88,7 +68,7 @@ resource "aws_lambda_permission" "webhook" {
8868
principal = "apigateway.amazonaws.com"
8969
source_arn = var.config.api_gw_source_arn
9070
lifecycle {
91-
replace_triggered_by = [aws_ssm_parameter.runner_matcher_config, null_resource.github_app_parameters]
71+
replace_triggered_by = [null_resource.ssm_parameter_runner_matcher_config, null_resource.github_app_parameters]
9272
}
9373
}
9474

@@ -110,7 +90,7 @@ data "aws_iam_policy_document" "lambda_assume_role_policy" {
11090
}
11191

11292
resource "aws_iam_role" "webhook_lambda" {
113-
name = "${var.config.prefix}-action-webhook-lambda-role"
93+
name = "${var.config.prefix}-direct-webhook-lambda-role"
11494
assume_role_policy = data.aws_iam_policy_document.lambda_assume_role_policy.json
11595
path = var.config.role_path
11696
permissions_boundary = var.config.role_permissions_boundary
@@ -136,7 +116,7 @@ resource "aws_iam_role_policy" "webhook_sqs" {
136116
role = aws_iam_role.webhook_lambda.name
137117

138118
policy = templatefile("${path.module}/../policies/lambda-publish-sqs-policy.json", {
139-
sqs_resource_arns = jsonencode([for k, v in var.config.runner_matcher_config : v.arn])
119+
sqs_resource_arns = jsonencode(var.config.sqs_job_queues_arns)
140120
kms_key_arn = var.config.kms_key_arn != null ? var.config.kms_key_arn : ""
141121
})
142122
}
@@ -158,7 +138,7 @@ resource "aws_iam_role_policy" "webhook_ssm" {
158138

159139
policy = templatefile("${path.module}/../policies/lambda-ssm.json", {
160140
github_app_webhook_secret_arn = var.config.github_app_parameters.webhook_secret.arn,
161-
parameter_runner_matcher_config_arn = aws_ssm_parameter.runner_matcher_config.arn
141+
parameter_runner_matcher_config_arn = var.config.ssm_parameter_runner_matcher_config.arn
162142
})
163143
}
164144

modules/webhook/eventbridge/dispatcher.tf

Lines changed: 4 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -1,43 +1,3 @@
1-
# locals {
2-
# # config with combined key and order
3-
# runner_matcher_config = { for k, v in var.config.runner_matcher_config : format("%03d-%s", v.matcherConfig.priority, k) => merge(v, { key = k }) }
4-
5-
# # sorted list
6-
# runner_matcher_config_sorted = [for k in sort(keys(local.runner_matcher_config)) : local.runner_matcher_config[k]]
7-
8-
# # handler
9-
# lambda_handler_function = var.config.legacy_mode ? "index.githubWebhook" : "index.eventBridgeWebhook"
10-
11-
# lambda_zip = var.config.lambda_zip == null ? "${path.module}/../../../lambdas/functions/webhook/webhook.zip" : var.config.lambda_zip
12-
13-
# }
14-
15-
# resource "aws_ssm_parameter" "runner_matcher_config" {
16-
# name = "${var.config.ssm_paths.root}/${var.config.ssm_paths.webhook}/runner-matcher-config"
17-
# type = "String"
18-
# value = jsonencode(local.runner_matcher_config_sorted)
19-
# tier = var.config.matcher_config_parameter_store_tier
20-
# }
21-
22-
# resource "aws_cloudwatch_event_rule" "workflow_job" {
23-
# name = "${var.config.prefix}-workflow_job"
24-
# description = "Workflow job event ruule for job queued."
25-
# event_bus_name = aws_cloudwatch_event_bus.main.name
26-
27-
# event_pattern = <<EOF
28-
# {
29-
# "detail-type": [
30-
# "workflow_job"
31-
# ],
32-
# "source": ["github"],
33-
# "detail": {
34-
# "action": ["queued"]
35-
# }
36-
# }
37-
# EOF
38-
# }
39-
40-
411
resource "aws_cloudwatch_event_rule" "workflow_job" {
422
name = "${var.config.prefix}-workflow_job"
433
description = "Workflow job event ruule for job queued."
@@ -87,7 +47,7 @@ resource "aws_lambda_function" "dispatcher" {
8747
REPOSITORY_ALLOW_LIST = jsonencode(var.config.repository_white_list)
8848
SQS_WORKFLOW_JOB_QUEUE = try(var.config.sqs_workflow_job_queue.id, null)
8949
PARAMETER_GITHUB_APP_WEBHOOK_SECRET = var.config.github_app_parameters.webhook_secret.name
90-
PARAMETER_RUNNER_MATCHER_CONFIG_PATH = aws_ssm_parameter.runner_matcher_config.name
50+
PARAMETER_RUNNER_MATCHER_CONFIG_PATH = var.config.ssm_parameter_runner_matcher_config.name
9151
} : k => v if v != null
9252
}
9353
}
@@ -110,7 +70,7 @@ resource "aws_lambda_function" "dispatcher" {
11070
}
11171

11272
lifecycle {
113-
replace_triggered_by = [aws_ssm_parameter.runner_matcher_config, null_resource.github_app_parameters]
73+
replace_triggered_by = [null_resource.ssm_parameter_runner_matcher_config, null_resource.github_app_parameters]
11474
}
11575
}
11676

@@ -121,17 +81,6 @@ resource "aws_cloudwatch_log_group" "dispatcher" {
12181
tags = var.config.tags
12282
}
12383

124-
# resource "aws_lambda_permission" "dispatcher" {
125-
# statement_id = "AllowExecutionFromAPIGateway"
126-
# action = "lambda:InvokeFunction"
127-
# function_name = aws_lambda_function.dispatcher.function_name
128-
# principal = "apigateway.amazonaws.com"
129-
# source_arn = var.config.api_gw_source_arn
130-
# lifecycle {
131-
# replace_triggered_by = [aws_ssm_parameter.runner_matcher_config, null_resource.github_app_parameters]
132-
# }
133-
# }
134-
13584
resource "aws_lambda_permission" "allow_cloudwatch_to_call_lambda" {
13685
statement_id = "AllowExecutionFromCloudWatch"
13786
action = "lambda:InvokeFunction"
@@ -140,18 +89,6 @@ resource "aws_lambda_permission" "allow_cloudwatch_to_call_lambda" {
14089
source_arn = aws_cloudwatch_event_rule.workflow_job.arn
14190
}
14291

143-
144-
# data "aws_iam_policy_document" "lambda_assume_role_policy" {
145-
# statement {
146-
# actions = ["sts:AssumeRole"]
147-
148-
# principals {
149-
# type = "Service"
150-
# identifiers = ["lambda.amazonaws.com"]
151-
# }
152-
# }
153-
# }
154-
15592
resource "aws_iam_role" "dispatcher_lambda" {
15693
name = "${var.config.prefix}-dispatcher-lambda-role"
15794
assume_role_policy = data.aws_iam_policy_document.lambda_assume_role_policy.json
@@ -179,7 +116,7 @@ resource "aws_iam_role_policy" "dispatcher_sqs" {
179116
role = aws_iam_role.dispatcher_lambda.name
180117

181118
policy = templatefile("${path.module}/../policies/lambda-publish-sqs-policy.json", {
182-
sqs_resource_arns = jsonencode([for k, v in var.config.runner_matcher_config : v.arn])
119+
sqs_resource_arns = jsonencode(var.config.sqs_job_queues_arns)
183120
kms_key_arn = var.config.kms_key_arn != null ? var.config.kms_key_arn : ""
184121
})
185122
}
@@ -190,7 +127,7 @@ resource "aws_iam_role_policy" "dispatcher_ssm" {
190127

191128
policy = templatefile("${path.module}/../policies/lambda-ssm.json", {
192129
github_app_webhook_secret_arn = var.config.github_app_parameters.webhook_secret.arn,
193-
parameter_runner_matcher_config_arn = aws_ssm_parameter.runner_matcher_config.arn
130+
parameter_runner_matcher_config_arn = var.config.ssm_parameter_runner_matcher_config.arn
194131
})
195132
}
196133

modules/webhook/eventbridge/main.tf

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
locals {
2-
name = "${var.config.prefix}-runners"
2+
name = "${var.config.prefix}-runners"
3+
lambda_zip = var.config.lambda_zip == null ? "${path.module}/../../../lambdas/functions/webhook/webhook.zip" : var.config.lambda_zip
34
}
45

56
resource "aws_cloudwatch_event_bus" "main" {
@@ -12,3 +13,9 @@ resource "aws_cloudwatch_event_archive" "main" {
1213
event_source_arn = aws_cloudwatch_event_bus.main.arn
1314
retention_days = var.config.archive.retention_days
1415
}
16+
17+
resource "null_resource" "ssm_parameter_runner_matcher_config" {
18+
triggers = {
19+
version = var.config.ssm_parameter_runner_matcher_config.version
20+
}
21+
}
Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,22 @@
11
output "eventbridge" {
2-
value = aws_cloudwatch_event_bus.main
2+
value = {
3+
event_but = aws_cloudwatch_event_bus.main
4+
archive = aws_cloudwatch_event_archive.main
5+
}
36
}
47

5-
output "achive" {
6-
value = var.config.archive.enable ? aws_cloudwatch_event_archive.main : null
8+
output "webhook" {
9+
value = {
10+
lambda = aws_lambda_function.webhook
11+
log_group = aws_cloudwatch_log_group.webhook
12+
role = aws_iam_role.webhook_lambda
13+
}
714
}
815

9-
output "webhook_lambda_function" {
10-
value = aws_lambda_function.webhook
16+
output "dispatcher" {
17+
value = {
18+
lambda = aws_lambda_function.dispatcher
19+
log_group = aws_cloudwatch_log_group.dispatcher
20+
role = aws_iam_role.dispatcher_lambda
21+
}
1122
}

0 commit comments

Comments
 (0)