forked from ChelseaKR/gtfs-scorecard
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmain.tf
More file actions
161 lines (139 loc) · 4.64 KB
/
Copy pathmain.tf
File metadata and controls
161 lines (139 loc) · 4.64 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
# Self-serve submission: a Lambda behind an HTTP API Gateway that opens a PR
# adding an agency to registry/intake.yaml (docs/roadmap.md, Year 1). The web form
# POSTs here.
#
# Uses API Gateway (not a Lambda function URL) because this account blocks public
# (auth NONE) Lambda function URLs — the same reason infra/alerts uses API GW.
# The handler reads the standard v2 payload shape that both emit.
#
# Build the deployment package before applying:
# pip install ../../pipeline -t build && cp handler.py build/
# terraform init && terraform apply
terraform {
required_version = ">= 1.5"
required_providers {
aws = { source = "hashicorp/aws", version = "~> 5.0" }
archive = { source = "hashicorp/archive", version = "~> 2.0" }
}
}
# Cost allocation: see the note in infra/artifacts/main.tf. `project` is the
# activated cost-allocation tag key, so untagged resources are invisible to the
# per-project budget; declaring it here covers every taggable resource in this
# module.
locals {
default_tags = {
project = var.project
component = "submit"
managed-by = "terraform"
}
}
provider "aws" {
region = var.region
default_tags {
tags = local.default_tags
}
}
variable "project" {
type = string
default = "gtfs-scorecard"
}
variable "region" {
type = string
default = "us-west-2"
}
variable "github_repo" {
description = "owner/name of the scorecard repo the PR is opened against."
type = string
}
variable "github_token" {
description = "Fine-scoped token with contents + pull_requests write."
type = string
sensitive = true
}
variable "allow_origin" {
description = "CORS origin of the deployed web form. Never '*' for a state-changing, token-backed endpoint."
type = string
default = "https://gtfsscorecard.org"
}
variable "submit_shared_secret" {
description = "If set, the form must send a matching X-Submit-Token header. A weak (client-visible) guard against trivial abuse; pair with a captcha for real protection."
type = string
default = ""
sensitive = true
}
data "archive_file" "submit" {
type = "zip"
source_dir = "${path.module}/build"
output_path = "${path.module}/submit.zip"
}
resource "aws_iam_role" "submit" {
name = "${var.project}-submit"
assume_role_policy = jsonencode({
Version = "2012-10-17"
Statement = [{
Action = "sts:AssumeRole"
Effect = "Allow"
Principal = { Service = "lambda.amazonaws.com" }
}]
})
}
resource "aws_iam_role_policy_attachment" "logs" {
role = aws_iam_role.submit.name
policy_arn = "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"
}
resource "aws_lambda_function" "submit" {
function_name = "${var.project}-submit"
role = aws_iam_role.submit.arn
runtime = "python3.12"
handler = "handler.handler"
filename = data.archive_file.submit.output_path
source_code_hash = data.archive_file.submit.output_base64sha256
timeout = 20
memory_size = 256
environment {
variables = {
GITHUB_REPO = var.github_repo
GITHUB_TOKEN = var.github_token
ALLOW_ORIGIN = var.allow_origin
BASE_BRANCH = "main"
SUBMIT_SHARED_SECRET = var.submit_shared_secret
}
}
}
# Public front door via API Gateway — the same workaround as infra/alerts for
# the account-level block on public Lambda function URLs.
resource "aws_apigatewayv2_api" "submit" {
name = "${var.project}-submit"
protocol_type = "HTTP"
}
resource "aws_apigatewayv2_integration" "submit" {
api_id = aws_apigatewayv2_api.submit.id
integration_type = "AWS_PROXY"
integration_uri = aws_lambda_function.submit.invoke_arn
payload_format_version = "2.0"
}
resource "aws_apigatewayv2_route" "default" {
api_id = aws_apigatewayv2_api.submit.id
route_key = "$default"
target = "integrations/${aws_apigatewayv2_integration.submit.id}"
}
resource "aws_apigatewayv2_stage" "default" {
api_id = aws_apigatewayv2_api.submit.id
name = "$default"
auto_deploy = true
default_route_settings {
throttling_rate_limit = 5
throttling_burst_limit = 10
}
}
resource "aws_lambda_permission" "apigw" {
statement_id = "AllowApiGatewayInvoke"
action = "lambda:InvokeFunction"
function_name = aws_lambda_function.submit.function_name
principal = "apigateway.amazonaws.com"
source_arn = "${aws_apigatewayv2_api.submit.execution_arn}/*/*"
}
output "submit_url" {
description = "Set this as SCORECARD_SUBMIT_URL in web/src/config.js."
value = aws_apigatewayv2_stage.default.invoke_url
}