irongit

intitial commit

huncholanehuncholaneauthored
commit 6291be08ef868ef435e4a4f4db27822465dee208Browse files

10 files changed, +2122 -0

+31-0apigateway.tf
@@ -0,0 +1,31 @@
1+resource "aws_apigatewayv2_api" "http_api" {
2+ name = "${var.function_name}-gateway"
3+ protocol_type = "HTTP"
4+}
5+
6+resource "aws_lambda_permission" "allow_apigw" {
7+ statement_id = "AllowExecutionFromAPIGateway"
8+ action = "lambda:InvokeFunction"
9+ function_name = aws_lambda_function.api.function_name
10+ principal = "apigateway.amazonaws.com"
11+ source_arn = "${aws_apigatewayv2_api.http_api.execution_arn}/*/*"
12+}
13+
14+resource "aws_apigatewayv2_integration" "lambda_integration" {
15+ api_id = aws_apigatewayv2_api.http_api.id
16+ integration_type = "AWS_PROXY"
17+ integration_uri = aws_lambda_function.api.invoke_arn
18+ payload_format_version = "2.0"
19+}
20+
21+resource "aws_apigatewayv2_route" "default_route" {
22+ api_id = aws_apigatewayv2_api.http_api.id
23+ route_key = "ANY /{proxy+}"
24+ target = "integrations/${aws_apigatewayv2_integration.lambda_integration.id}"
25+}
26+
27+resource "aws_apigatewayv2_stage" "default_stage" {
28+ api_id = aws_apigatewayv2_api.http_api.id
29+ name = "$default"
30+ auto_deploy = true
31+}
+101-0cloudfront.tf
@@ -0,0 +1,101 @@
1+resource "aws_cloudfront_origin_access_control" "default" {
2+ name = "default-oac"
3+ origin_access_control_origin_type = "s3"
4+ signing_behavior = "always"
5+ signing_protocol = "sigv4"
6+}
7+
8+resource "aws_cloudfront_distribution" "cdn" {
9+ origin {
10+ domain_name = aws_s3_bucket_website_configuration.frontend.website_endpoint
11+ # origin_access_control_id = aws_cloudfront_origin_access_control.default.id
12+ origin_id = local.s3_origin_id
13+ custom_origin_config {
14+ http_port = 80
15+ https_port = 443
16+ origin_protocol_policy = "http-only"
17+ origin_ssl_protocols = ["TLSv1.2"]
18+ }
19+ }
20+
21+ origin {
22+ domain_name = replace(aws_apigatewayv2_api.http_api.api_endpoint, "https://", "")
23+ origin_id = "api-origin"
24+
25+ custom_origin_config {
26+ origin_protocol_policy = "https-only"
27+ http_port = 80
28+ https_port = 443
29+ origin_ssl_protocols = ["TLSv1.2"]
30+ }
31+ }
32+
33+ enabled = true
34+ is_ipv6_enabled = true
35+ comment = "ReadFasterLabs CDN"
36+ default_root_object = "index.html"
37+ aliases = ["readfasterlabs.com", "www.readfasterlabs.com"]
38+
39+ default_cache_behavior {
40+ allowed_methods = ["DELETE", "GET", "HEAD", "OPTIONS", "PATCH", "POST", "PUT"]
41+ cached_methods = ["GET", "HEAD"]
42+ target_origin_id = local.s3_origin_id
43+ viewer_protocol_policy = "redirect-to-https"
44+
45+ forwarded_values {
46+ query_string = true
47+ headers = ["Authorization"]
48+
49+ cookies {
50+ forward = "none"
51+ }
52+ }
53+
54+ min_ttl = 0
55+ default_ttl = 3600
56+ max_ttl = 86400
57+ }
58+
59+ # Cache behavior with precedence 0
60+ ordered_cache_behavior {
61+ path_pattern = "/api/*"
62+ allowed_methods = ["GET", "HEAD", "OPTIONS", "POST", "PUT", "PATCH", "DELETE"]
63+ cached_methods = ["GET", "HEAD"]
64+ target_origin_id = "api-origin"
65+
66+ forwarded_values {
67+ query_string = true
68+ headers=["Authorization"]
69+
70+ cookies {
71+ forward = "none"
72+ }
73+ }
74+
75+ min_ttl = 0
76+ default_ttl = 3600
77+ max_ttl = 86400
78+ compress = true
79+ viewer_protocol_policy = "redirect-to-https"
80+ }
81+
82+ price_class = "PriceClass_200"
83+
84+ restrictions {
85+ geo_restriction {
86+ restriction_type = "whitelist"
87+ locations = ["US", "CA", "GB", "DE"]
88+ }
89+ }
90+
91+ tags = {
92+ Environment = "production"
93+ }
94+
95+ viewer_certificate {
96+ acm_certificate_arn = "arn:aws:acm:us-east-1:036487096349:certificate/dc4f8dcc-9809-4d6d-8258-362cf5e19244"
97+ ssl_support_method = "sni-only"
98+ minimum_protocol_version = "TLSv1.2_2021"
99+ }
100+}
101+
+58-0lambda.tf
@@ -0,0 +1,58 @@
1+resource "aws_iam_role" "lambda_role" {
2+ name = "${var.function_name}-role"
3+
4+ assume_role_policy = jsonencode({
5+ Version = "2012-10-17",
6+ Statement = [{
7+ Action = "sts:AssumeRole",
8+ Effect = "Allow",
9+ Principal = { Service = "lambda.amazonaws.com" }
10+ }]
11+ })
12+}
13+
14+resource "aws_iam_role_policy_attachment" "lambda_logging" {
15+ role = aws_iam_role.lambda_role.name
16+ policy_arn = "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"
17+}
18+
19+resource "aws_iam_policy" "lambda_secret_access" {
20+ name = "lambda-secret-access"
21+ policy = jsonencode({
22+ Version = "2012-10-17",
23+ Statement = [
24+ {
25+ Effect = "Allow",
26+ Action = [
27+ "secretsmanager:GetSecretValue"
28+ ],
29+ Resource = [
30+ "arn:aws:secretsmanager:us-west-1:036487096349:secret:rfl-secrets-ztW9tp"
31+ ]
32+ }
33+ ]
34+ })
35+}
36+
37+resource "aws_iam_role_policy_attachment" "lambda_secret_access" {
38+ role = aws_iam_role.lambda_role.name
39+ policy_arn = aws_iam_policy.lambda_secret_access.arn
40+}
41+
42+
43+resource "aws_lambda_function" "api" {
44+ function_name = var.function_name
45+ role = aws_iam_role.lambda_role.arn
46+ handler = "bootstrap" # Rust binary handler
47+ runtime = "provided.al2023" # custom runtime for Rust
48+ filename = var.lambda_zip
49+ source_code_hash = filebase64sha256(var.lambda_zip)
50+ memory_size = 128
51+ timeout = 30
52+
53+ environment {
54+ variables = {
55+ RUST_LOG = "info"
56+ }
57+ }
58+}
+15-0main.tf
@@ -0,0 +1,15 @@
1+terraform {
2+ required_providers {
3+ aws = {
4+ source = "hashicorp/aws"
5+ version = "~> 5.0"
6+ }
7+ }
8+
9+ required_version = ">= 1.7.0"
10+}
11+
12+provider "aws" {
13+ region = var.region
14+ profile = var.aws_profile
15+}
+17-0outputs.tf
@@ -0,0 +1,17 @@
1+output "lambda_name" {
2+ value = aws_lambda_function.api.function_name
3+}
4+
5+output "lambda_arn" {
6+ value = aws_lambda_function.api.arn
7+}
8+
9+output "cloudfront_url" {
10+ description = "Public CloudFront domain for the app"
11+ value = aws_cloudfront_distribution.cdn.domain_name
12+}
13+
14+output "cloudfront_distribution_id" {
15+ value = aws_cloudfront_distribution.cdn.id
16+}
17+
+58-0s3.tf
@@ -0,0 +1,58 @@
1+resource "aws_s3_bucket" "frontend" {
2+ bucket = var.s3_bucket
3+
4+ tags = {
5+ Name = "ReadFasterLabs"
6+ }
7+}
8+
9+resource "aws_s3_bucket_website_configuration" "frontend" {
10+ bucket = aws_s3_bucket.frontend.id
11+
12+ index_document {
13+ suffix = "index.html"
14+ }
15+}
16+
17+data "aws_iam_policy_document" "origin_bucket_policy" {
18+ statement {
19+ sid = "PublicRead"
20+ effect = "Allow"
21+
22+ principals {
23+ type = "*"
24+ identifiers = ["*"]
25+ }
26+
27+ actions = ["s3:GetObject"]
28+ resources = ["${aws_s3_bucket.frontend.arn}/*"]
29+ }
30+
31+ statement {
32+ sid = "AllowCloudFrontServicePrincipal"
33+ effect = "Allow"
34+
35+ principals {
36+ type = "Service"
37+ identifiers = ["cloudfront.amazonaws.com"]
38+ }
39+
40+ actions = ["s3:GetObject"]
41+ resources = ["${aws_s3_bucket.frontend.arn}/*"]
42+
43+ condition {
44+ test = "ArnLike"
45+ variable = "AWS:SourceArn"
46+ values = [aws_cloudfront_distribution.cdn.arn]
47+ }
48+ }
49+}
50+
51+resource "aws_s3_bucket_policy" "frontend" {
52+ bucket = aws_s3_bucket.frontend.bucket
53+ policy = data.aws_iam_policy_document.origin_bucket_policy.json
54+}
55+
56+locals {
57+ s3_origin_id = "myS3Origin"
58+}
+901-0terraform.tfstate
@@ -0,0 +1,901 @@
1+{
2+ "version": 4,
3+ "terraform_version": "1.13.3",
4+ "serial": 210,
5+ "lineage": "0f9ff0dd-e8f8-bd72-d551-f6a84fdbea86",
6+ "outputs": {
7+ "cloudfront_distribution_id": {
8+ "value": "E3QQ8AY9QCV40V",
9+ "type": "string"
10+ },
11+ "cloudfront_url": {
12+ "value": "d3u6qxzv4zlkzy.cloudfront.net",
13+ "type": "string"
14+ },
15+ "lambda_arn": {
16+ "value": "arn:aws:lambda:us-west-1:036487096349:function:rfl-rust-api",
17+ "type": "string"
18+ },
19+ "lambda_name": {
20+ "value": "rfl-rust-api",
21+ "type": "string"
22+ }
23+ },
24+ "resources": [
25+ {
26+ "mode": "data",
27+ "type": "aws_iam_policy_document",
28+ "name": "origin_bucket_policy",
29+ "provider": "provider[\"registry.terraform.io/hashicorp/aws\"]",
30+ "instances": [
31+ {
32+ "schema_version": 0,
33+ "attributes": {
34+ "id": "3485735718",
35+ "json": "{\n \"Version\": \"2012-10-17\",\n \"Statement\": [\n {\n \"Sid\": \"PublicRead\",\n \"Effect\": \"Allow\",\n \"Action\": \"s3:GetObject\",\n \"Resource\": \"arn:aws:s3:::rfl-frontend.hygo/*\",\n \"Principal\": \"*\"\n },\n {\n \"Sid\": \"AllowCloudFrontServicePrincipal\",\n \"Effect\": \"Allow\",\n \"Action\": \"s3:GetObject\",\n \"Resource\": \"arn:aws:s3:::rfl-frontend.hygo/*\",\n \"Principal\": {\n \"Service\": \"cloudfront.amazonaws.com\"\n },\n \"Condition\": {\n \"ArnLike\": {\n \"AWS:SourceArn\": \"arn:aws:cloudfront::036487096349:distribution/E3QQ8AY9QCV40V\"\n }\n }\n }\n ]\n}",
36+ "minified_json": "{\"Version\":\"2012-10-17\",\"Statement\":[{\"Sid\":\"PublicRead\",\"Effect\":\"Allow\",\"Action\":\"s3:GetObject\",\"Resource\":\"arn:aws:s3:::rfl-frontend.hygo/*\",\"Principal\":\"*\"},{\"Sid\":\"AllowCloudFrontServicePrincipal\",\"Effect\":\"Allow\",\"Action\":\"s3:GetObject\",\"Resource\":\"arn:aws:s3:::rfl-frontend.hygo/*\",\"Principal\":{\"Service\":\"cloudfront.amazonaws.com\"},\"Condition\":{\"ArnLike\":{\"AWS:SourceArn\":\"arn:aws:cloudfront::036487096349:distribution/E3QQ8AY9QCV40V\"}}}]}",
37+ "override_json": null,
38+ "override_policy_documents": null,
39+ "policy_id": null,
40+ "source_json": null,
41+ "source_policy_documents": null,
42+ "statement": [
43+ {
44+ "actions": [
45+ "s3:GetObject"
46+ ],
47+ "condition": [],
48+ "effect": "Allow",
49+ "not_actions": [],
50+ "not_principals": [],
51+ "not_resources": [],
52+ "principals": [
53+ {
54+ "identifiers": [
55+ "*"
56+ ],
57+ "type": "*"
58+ }
59+ ],
60+ "resources": [
61+ "arn:aws:s3:::rfl-frontend.hygo/*"
62+ ],
63+ "sid": "PublicRead"
64+ },
65+ {
66+ "actions": [
67+ "s3:GetObject"
68+ ],
69+ "condition": [
70+ {
71+ "test": "ArnLike",
72+ "values": [
73+ "arn:aws:cloudfront::036487096349:distribution/E3QQ8AY9QCV40V"
74+ ],
75+ "variable": "AWS:SourceArn"
76+ }
77+ ],
78+ "effect": "Allow",
79+ "not_actions": [],
80+ "not_principals": [],
81+ "not_resources": [],
82+ "principals": [
83+ {
84+ "identifiers": [
85+ "cloudfront.amazonaws.com"
86+ ],
87+ "type": "Service"
88+ }
89+ ],
90+ "resources": [
91+ "arn:aws:s3:::rfl-frontend.hygo/*"
92+ ],
93+ "sid": "AllowCloudFrontServicePrincipal"
94+ }
95+ ],
96+ "version": "2012-10-17"
97+ },
98+ "sensitive_attributes": [],
99+ "identity_schema_version": 0
100+ }
101+ ]
102+ },
103+ {
104+ "mode": "managed",
105+ "type": "aws_apigatewayv2_api",
106+ "name": "http_api",
107+ "provider": "provider[\"registry.terraform.io/hashicorp/aws\"]",
108+ "instances": [
109+ {
110+ "schema_version": 0,
111+ "attributes": {
112+ "api_endpoint": "https://teopf75zy7.execute-api.us-west-1.amazonaws.com",
113+ "api_key_selection_expression": "$request.header.x-api-key",
114+ "arn": "arn:aws:apigateway:us-west-1::/apis/teopf75zy7",
115+ "body": null,
116+ "cors_configuration": [],
117+ "credentials_arn": null,
118+ "description": "",
119+ "disable_execute_api_endpoint": false,
120+ "execution_arn": "arn:aws:execute-api:us-west-1:036487096349:teopf75zy7",
121+ "fail_on_warnings": null,
122+ "id": "teopf75zy7",
123+ "ip_address_type": "ipv4",
124+ "name": "rfl-rust-api-gateway",
125+ "protocol_type": "HTTP",
126+ "route_key": null,
127+ "route_selection_expression": "$request.method $request.path",
128+ "tags": {},
129+ "tags_all": {},
130+ "target": null,
131+ "version": ""
132+ },
133+ "sensitive_attributes": [],
134+ "identity_schema_version": 0,
135+ "private": "bnVsbA=="
136+ }
137+ ]
138+ },
139+ {
140+ "mode": "managed",
141+ "type": "aws_apigatewayv2_integration",
142+ "name": "lambda_integration",
143+ "provider": "provider[\"registry.terraform.io/hashicorp/aws\"]",
144+ "instances": [
145+ {
146+ "schema_version": 0,
147+ "attributes": {
148+ "api_id": "teopf75zy7",
149+ "connection_id": "",
150+ "connection_type": "INTERNET",
151+ "content_handling_strategy": "",
152+ "credentials_arn": "",
153+ "description": "",
154+ "id": "wqvnwt6",
155+ "integration_method": "POST",
156+ "integration_response_selection_expression": "",
157+ "integration_subtype": "",
158+ "integration_type": "AWS_PROXY",
159+ "integration_uri": "arn:aws:apigateway:us-west-1:lambda:path/2015-03-31/functions/arn:aws:lambda:us-west-1:036487096349:function:rfl-rust-api/invocations",
160+ "passthrough_behavior": "",
161+ "payload_format_version": "2.0",
162+ "request_parameters": {},
163+ "request_templates": {},
164+ "response_parameters": [],
165+ "template_selection_expression": "",
166+ "timeout_milliseconds": 30000,
167+ "tls_config": []
168+ },
169+ "sensitive_attributes": [],
170+ "identity_schema_version": 0,
171+ "private": "bnVsbA==",
172+ "dependencies": [
173+ "aws_apigatewayv2_api.http_api",
174+ "aws_iam_role.lambda_role",
175+ "aws_lambda_function.api"
176+ ]
177+ }
178+ ]
179+ },
180+ {
181+ "mode": "managed",
182+ "type": "aws_apigatewayv2_route",
183+ "name": "default_route",
184+ "provider": "provider[\"registry.terraform.io/hashicorp/aws\"]",
185+ "instances": [
186+ {
187+ "schema_version": 0,
188+ "attributes": {
189+ "api_id": "teopf75zy7",
190+ "api_key_required": false,
191+ "authorization_scopes": [],
192+ "authorization_type": "NONE",
193+ "authorizer_id": "",
194+ "id": "cybly2s",
195+ "model_selection_expression": "",
196+ "operation_name": "",
197+ "request_models": {},
198+ "request_parameter": [],
199+ "route_key": "ANY /{proxy+}",
200+ "route_response_selection_expression": "",
201+ "target": "integrations/wqvnwt6"
202+ },
203+ "sensitive_attributes": [],
204+ "identity_schema_version": 0,
205+ "private": "bnVsbA==",
206+ "dependencies": [
207+ "aws_apigatewayv2_api.http_api",
208+ "aws_apigatewayv2_integration.lambda_integration",
209+ "aws_iam_role.lambda_role",
210+ "aws_lambda_function.api"
211+ ]
212+ }
213+ ]
214+ },
215+ {
216+ "mode": "managed",
217+ "type": "aws_apigatewayv2_stage",
218+ "name": "default_stage",
219+ "provider": "provider[\"registry.terraform.io/hashicorp/aws\"]",
220+ "instances": [
221+ {
222+ "schema_version": 0,
223+ "attributes": {
224+ "access_log_settings": [],
225+ "api_id": "teopf75zy7",
226+ "arn": "arn:aws:apigateway:us-west-1::/apis/teopf75zy7/stages/$default",
227+ "auto_deploy": true,
228+ "client_certificate_id": "",
229+ "default_route_settings": [
230+ {
231+ "data_trace_enabled": false,
232+ "detailed_metrics_enabled": false,
233+ "logging_level": "",
234+ "throttling_burst_limit": 0,
235+ "throttling_rate_limit": 0
236+ }
237+ ],
238+ "deployment_id": "lm0u9y",
239+ "description": "",
240+ "execution_arn": "arn:aws:execute-api:us-west-1:036487096349:teopf75zy7/$default",
241+ "id": "$default",
242+ "invoke_url": "https://teopf75zy7.execute-api.us-west-1.amazonaws.com/",
243+ "name": "$default",
244+ "route_settings": [],
245+ "stage_variables": {},
246+ "tags": {},
247+ "tags_all": {}
248+ },
249+ "sensitive_attributes": [],
250+ "identity_schema_version": 0,
251+ "private": "bnVsbA==",
252+ "dependencies": [
253+ "aws_apigatewayv2_api.http_api"
254+ ]
255+ }
256+ ]
257+ },
258+ {
259+ "mode": "managed",
260+ "type": "aws_cloudfront_distribution",
261+ "name": "cdn",
262+ "provider": "provider[\"registry.terraform.io/hashicorp/aws\"]",
263+ "instances": [
264+ {
265+ "schema_version": 1,
266+ "attributes": {
267+ "aliases": [
268+ "readfasterlabs.com",
269+ "www.readfasterlabs.com"
270+ ],
271+ "arn": "arn:aws:cloudfront::036487096349:distribution/E3QQ8AY9QCV40V",
272+ "caller_reference": "terraform-20251021151303194400000001",
273+ "comment": "ReadFasterLabs CDN",
274+ "continuous_deployment_policy_id": "",
275+ "custom_error_response": [],
276+ "default_cache_behavior": [
277+ {
278+ "allowed_methods": [
279+ "DELETE",
280+ "GET",
281+ "HEAD",
282+ "OPTIONS",
283+ "PATCH",
284+ "POST",
285+ "PUT"
286+ ],
287+ "cache_policy_id": "",
288+ "cached_methods": [
289+ "GET",
290+ "HEAD"
291+ ],
292+ "compress": false,
293+ "default_ttl": 3600,
294+ "field_level_encryption_id": "",
295+ "forwarded_values": [
296+ {
297+ "cookies": [
298+ {
299+ "forward": "none",
300+ "whitelisted_names": []
301+ }
302+ ],
303+ "headers": [
304+ "Authorization"
305+ ],
306+ "query_string": true,
307+ "query_string_cache_keys": []
308+ }
309+ ],
310+ "function_association": [],
311+ "grpc_config": [
312+ {
313+ "enabled": false
314+ }
315+ ],
316+ "lambda_function_association": [],
317+ "max_ttl": 86400,
318+ "min_ttl": 0,
319+ "origin_request_policy_id": "",
320+ "realtime_log_config_arn": "",
321+ "response_headers_policy_id": "",
322+ "smooth_streaming": false,
323+ "target_origin_id": "myS3Origin",
324+ "trusted_key_groups": [],
325+ "trusted_signers": [],
326+ "viewer_protocol_policy": "redirect-to-https"
327+ }
328+ ],
329+ "default_root_object": "index.html",
330+ "domain_name": "d3u6qxzv4zlkzy.cloudfront.net",
331+ "enabled": true,
332+ "etag": "EOE7YQ3FGLFQT",
333+ "hosted_zone_id": "Z2FDTNDATAQYW2",
334+ "http_version": "http2",
335+ "id": "E3QQ8AY9QCV40V",
336+ "in_progress_validation_batches": 0,
337+ "is_ipv6_enabled": true,
338+ "last_modified_time": "2025-10-22 01:58:02.776 +0000 UTC",
339+ "logging_config": [],
340+ "ordered_cache_behavior": [
341+ {
342+ "allowed_methods": [
343+ "DELETE",
344+ "GET",
345+ "HEAD",
346+ "OPTIONS",
347+ "PATCH",
348+ "POST",
349+ "PUT"
350+ ],
351+ "cache_policy_id": "",
352+ "cached_methods": [
353+ "GET",
354+ "HEAD"
355+ ],
356+ "compress": true,
357+ "default_ttl": 3600,
358+ "field_level_encryption_id": "",
359+ "forwarded_values": [
360+ {
361+ "cookies": [
362+ {
363+ "forward": "none",
364+ "whitelisted_names": []
365+ }
366+ ],
367+ "headers": [
368+ "Authorization"
369+ ],
370+ "query_string": true,
371+ "query_string_cache_keys": []
372+ }
373+ ],
374+ "function_association": [],
375+ "grpc_config": [
376+ {
377+ "enabled": false
378+ }
379+ ],
380+ "lambda_function_association": [],
381+ "max_ttl": 86400,
382+ "min_ttl": 0,
383+ "origin_request_policy_id": "",
384+ "path_pattern": "/api/*",
385+ "realtime_log_config_arn": "",
386+ "response_headers_policy_id": "",
387+ "smooth_streaming": false,
388+ "target_origin_id": "api-origin",
389+ "trusted_key_groups": [],
390+ "trusted_signers": [],
391+ "viewer_protocol_policy": "redirect-to-https"
392+ }
393+ ],
394+ "origin": [
395+ {
396+ "connection_attempts": 3,
397+ "connection_timeout": 10,
398+ "custom_header": [],
399+ "custom_origin_config": [
400+ {
401+ "http_port": 80,
402+ "https_port": 443,
403+ "origin_keepalive_timeout": 5,
404+ "origin_protocol_policy": "http-only",
405+ "origin_read_timeout": 30,
406+ "origin_ssl_protocols": [
407+ "TLSv1.2"
408+ ]
409+ }
410+ ],
411+ "domain_name": "rfl-frontend.hygo.s3-website-us-west-1.amazonaws.com",
412+ "origin_access_control_id": "",
413+ "origin_id": "myS3Origin",
414+ "origin_path": "",
415+ "origin_shield": [],
416+ "s3_origin_config": [],
417+ "vpc_origin_config": []
418+ },
419+ {
420+ "connection_attempts": 3,
421+ "connection_timeout": 10,
422+ "custom_header": [],
423+ "custom_origin_config": [
424+ {
425+ "http_port": 80,
426+ "https_port": 443,
427+ "origin_keepalive_timeout": 5,
428+ "origin_protocol_policy": "https-only",
429+ "origin_read_timeout": 30,
430+ "origin_ssl_protocols": [
431+ "TLSv1.2"
432+ ]
433+ }
434+ ],
435+ "domain_name": "teopf75zy7.execute-api.us-west-1.amazonaws.com",
436+ "origin_access_control_id": "",
437+ "origin_id": "api-origin",
438+ "origin_path": "",
439+ "origin_shield": [],
440+ "s3_origin_config": [],
441+ "vpc_origin_config": []
442+ }
443+ ],
444+ "origin_group": [],
445+ "price_class": "PriceClass_200",
446+ "restrictions": [
447+ {
448+ "geo_restriction": [
449+ {
450+ "locations": [
451+ "CA",
452+ "DE",
453+ "GB",
454+ "US"
455+ ],
456+ "restriction_type": "whitelist"
457+ }
458+ ]
459+ }
460+ ],
461+ "retain_on_delete": false,
462+ "staging": false,
463+ "status": "Deployed",
464+ "tags": {
465+ "Environment": "production"
466+ },
467+ "tags_all": {
468+ "Environment": "production"
469+ },
470+ "trusted_key_groups": [
471+ {
472+ "enabled": false,
473+ "items": []
474+ }
475+ ],
476+ "trusted_signers": [
477+ {
478+ "enabled": false,
479+ "items": []
480+ }
481+ ],
482+ "viewer_certificate": [
483+ {
484+ "acm_certificate_arn": "arn:aws:acm:us-east-1:036487096349:certificate/dc4f8dcc-9809-4d6d-8258-362cf5e19244",
485+ "cloudfront_default_certificate": false,
486+ "iam_certificate_id": "",
487+ "minimum_protocol_version": "TLSv1.2_2021",
488+ "ssl_support_method": "sni-only"
489+ }
490+ ],
491+ "wait_for_deployment": true,
492+ "web_acl_id": ""
493+ },
494+ "sensitive_attributes": [],
495+ "identity_schema_version": 0,
496+ "private": "eyJzY2hlbWFfdmVyc2lvbiI6IjEifQ==",
497+ "dependencies": [
498+ "aws_apigatewayv2_api.http_api",
499+ "aws_s3_bucket.frontend",
500+ "aws_s3_bucket_website_configuration.frontend"
501+ ]
502+ }
503+ ]
504+ },
505+ {
506+ "mode": "managed",
507+ "type": "aws_cloudfront_origin_access_control",
508+ "name": "default",
509+ "provider": "provider[\"registry.terraform.io/hashicorp/aws\"]",
510+ "instances": [
511+ {
512+ "schema_version": 0,
513+ "attributes": {
514+ "arn": "arn:aws:cloudfront::036487096349:origin-access-control/E6YQTL8HZQZGN",
515+ "description": "Managed by Terraform",
516+ "etag": "ETVPDKIKX0DER",
517+ "id": "E6YQTL8HZQZGN",
518+ "name": "default-oac",
519+ "origin_access_control_origin_type": "s3",
520+ "signing_behavior": "always",
521+ "signing_protocol": "sigv4"
522+ },
523+ "sensitive_attributes": [],
524+ "identity_schema_version": 0,
525+ "private": "bnVsbA=="
526+ }
527+ ]
528+ },
529+ {
530+ "mode": "managed",
531+ "type": "aws_iam_policy",
532+ "name": "lambda_secret_access",
533+ "provider": "provider[\"registry.terraform.io/hashicorp/aws\"]",
534+ "instances": [
535+ {
536+ "schema_version": 0,
537+ "attributes": {
538+ "arn": "arn:aws:iam::036487096349:policy/lambda-secret-access",
539+ "attachment_count": 1,
540+ "description": "",
541+ "id": "arn:aws:iam::036487096349:policy/lambda-secret-access",
542+ "name": "lambda-secret-access",
543+ "name_prefix": "",
544+ "path": "/",
545+ "policy": "{\"Statement\":[{\"Action\":[\"secretsmanager:GetSecretValue\"],\"Effect\":\"Allow\",\"Resource\":[\"arn:aws:secretsmanager:us-west-1:036487096349:secret:rfl-secrets-ztW9tp\"]}],\"Version\":\"2012-10-17\"}",
546+ "policy_id": "ANPAQQ7WM5AOYLJGC2FKW",
547+ "tags": {},
548+ "tags_all": {}
549+ },
550+ "sensitive_attributes": [],
551+ "identity_schema_version": 0,
552+ "private": "bnVsbA=="
553+ }
554+ ]
555+ },
556+ {
557+ "mode": "managed",
558+ "type": "aws_iam_role",
559+ "name": "lambda_role",
560+ "provider": "provider[\"registry.terraform.io/hashicorp/aws\"]",
561+ "instances": [
562+ {
563+ "schema_version": 0,
564+ "attributes": {
565+ "arn": "arn:aws:iam::036487096349:role/rfl-rust-api-role",
566+ "assume_role_policy": "{\"Statement\":[{\"Action\":\"sts:AssumeRole\",\"Effect\":\"Allow\",\"Principal\":{\"Service\":\"lambda.amazonaws.com\"}}],\"Version\":\"2012-10-17\"}",
567+ "create_date": "2025-10-21T14:31:41Z",
568+ "description": "",
569+ "force_detach_policies": false,
570+ "id": "rfl-rust-api-role",
571+ "inline_policy": [],
572+ "managed_policy_arns": [
573+ "arn:aws:iam::036487096349:policy/lambda-secret-access",
574+ "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"
575+ ],
576+ "max_session_duration": 3600,
577+ "name": "rfl-rust-api-role",
578+ "name_prefix": "",
579+ "path": "/",
580+ "permissions_boundary": "",
581+ "tags": {},
582+ "tags_all": {},
583+ "unique_id": "AROAQQ7WM5AOS7MVIC5QD"
584+ },
585+ "sensitive_attributes": [],
586+ "identity_schema_version": 0,
587+ "private": "bnVsbA=="
588+ }
589+ ]
590+ },
591+ {
592+ "mode": "managed",
593+ "type": "aws_iam_role_policy_attachment",
594+ "name": "lambda_logging",
595+ "provider": "provider[\"registry.terraform.io/hashicorp/aws\"]",
596+ "instances": [
597+ {
598+ "schema_version": 0,
599+ "attributes": {
600+ "id": "rfl-rust-api-role-20251021143142048400000001",
601+ "policy_arn": "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole",
602+ "role": "rfl-rust-api-role"
603+ },
604+ "sensitive_attributes": [],
605+ "identity_schema_version": 0,
606+ "private": "bnVsbA==",
607+ "dependencies": [
608+ "aws_iam_role.lambda_role"
609+ ]
610+ }
611+ ]
612+ },
613+ {
614+ "mode": "managed",
615+ "type": "aws_iam_role_policy_attachment",
616+ "name": "lambda_secret_access",
617+ "provider": "provider[\"registry.terraform.io/hashicorp/aws\"]",
618+ "instances": [
619+ {
620+ "schema_version": 0,
621+ "attributes": {
622+ "id": "rfl-rust-api-role-20251021172419743600000002",
623+ "policy_arn": "arn:aws:iam::036487096349:policy/lambda-secret-access",
624+ "role": "rfl-rust-api-role"
625+ },
626+ "sensitive_attributes": [],
627+ "identity_schema_version": 0,
628+ "private": "bnVsbA==",
629+ "dependencies": [
630+ "aws_iam_policy.lambda_secret_access",
631+ "aws_iam_role.lambda_role"
632+ ]
633+ }
634+ ]
635+ },
636+ {
637+ "mode": "managed",
638+ "type": "aws_lambda_function",
639+ "name": "api",
640+ "provider": "provider[\"registry.terraform.io/hashicorp/aws\"]",
641+ "instances": [
642+ {
643+ "schema_version": 0,
644+ "attributes": {
645+ "architectures": [
646+ "x86_64"
647+ ],
648+ "arn": "arn:aws:lambda:us-west-1:036487096349:function:rfl-rust-api",
649+ "code_sha256": "FP9XNG0JJ+HA1lEG0xdZ71O3xKEbd+jGrM2MiCtAPMg=",
650+ "code_signing_config_arn": "",
651+ "dead_letter_config": [],
652+ "description": "",
653+ "environment": [
654+ {
655+ "variables": {
656+ "RUST_LOG": "info"
657+ }
658+ }
659+ ],
660+ "ephemeral_storage": [
661+ {
662+ "size": 512
663+ }
664+ ],
665+ "file_system_config": [],
666+ "filename": "../lambda.zip",
667+ "function_name": "rfl-rust-api",
668+ "handler": "bootstrap",
669+ "id": "rfl-rust-api",
670+ "image_config": [],
671+ "image_uri": "",
672+ "invoke_arn": "arn:aws:apigateway:us-west-1:lambda:path/2015-03-31/functions/arn:aws:lambda:us-west-1:036487096349:function:rfl-rust-api/invocations",
673+ "kms_key_arn": "",
674+ "last_modified": "2025-10-22T19:14:13.000+0000",
675+ "layers": [],
676+ "logging_config": [
677+ {
678+ "application_log_level": "",
679+ "log_format": "Text",
680+ "log_group": "/aws/lambda/rfl-rust-api",
681+ "system_log_level": ""
682+ }
683+ ],
684+ "memory_size": 128,
685+ "package_type": "Zip",
686+ "publish": false,
687+ "qualified_arn": "arn:aws:lambda:us-west-1:036487096349:function:rfl-rust-api:$LATEST",
688+ "qualified_invoke_arn": "arn:aws:apigateway:us-west-1:lambda:path/2015-03-31/functions/arn:aws:lambda:us-west-1:036487096349:function:rfl-rust-api:$LATEST/invocations",
689+ "replace_security_groups_on_destroy": null,
690+ "replacement_security_group_ids": null,
691+ "reserved_concurrent_executions": -1,
692+ "role": "arn:aws:iam::036487096349:role/rfl-rust-api-role",
693+ "runtime": "provided.al2023",
694+ "s3_bucket": null,
695+ "s3_key": null,
696+ "s3_object_version": null,
697+ "signing_job_arn": "",
698+ "signing_profile_version_arn": "",
699+ "skip_destroy": false,
700+ "snap_start": [],
701+ "source_code_hash": "FP9XNG0JJ+HA1lEG0xdZ71O3xKEbd+jGrM2MiCtAPMg=",
702+ "source_code_size": 13841914,
703+ "tags": {},
704+ "tags_all": {},
705+ "timeout": 30,
706+ "timeouts": null,
707+ "tracing_config": [
708+ {
709+ "mode": "PassThrough"
710+ }
711+ ],
712+ "version": "$LATEST",
713+ "vpc_config": []
714+ },
715+ "sensitive_attributes": [],
716+ "identity_schema_version": 0,
717+ "private": "eyJlMmJmYjczMC1lY2FhLTExZTYtOGY4OC0zNDM2M2JjN2M0YzAiOnsiY3JlYXRlIjo2MDAwMDAwMDAwMDAsImRlbGV0ZSI6NjAwMDAwMDAwMDAwLCJ1cGRhdGUiOjYwMDAwMDAwMDAwMH19",
718+ "dependencies": [
719+ "aws_iam_role.lambda_role"
720+ ]
721+ }
722+ ]
723+ },
724+ {
725+ "mode": "managed",
726+ "type": "aws_lambda_permission",
727+ "name": "allow_apigw",
728+ "provider": "provider[\"registry.terraform.io/hashicorp/aws\"]",
729+ "instances": [
730+ {
731+ "schema_version": 0,
732+ "attributes": {
733+ "action": "lambda:InvokeFunction",
734+ "event_source_token": null,
735+ "function_name": "rfl-rust-api",
736+ "function_url_auth_type": null,
737+ "id": "AllowExecutionFromAPIGateway",
738+ "principal": "apigateway.amazonaws.com",
739+ "principal_org_id": null,
740+ "qualifier": "",
741+ "source_account": null,
742+ "source_arn": "arn:aws:execute-api:us-west-1:036487096349:teopf75zy7/*/*",
743+ "statement_id": "AllowExecutionFromAPIGateway",
744+ "statement_id_prefix": ""
745+ },
746+ "sensitive_attributes": [],
747+ "identity_schema_version": 0,
748+ "private": "bnVsbA==",
749+ "dependencies": [
750+ "aws_apigatewayv2_api.http_api",
751+ "aws_iam_role.lambda_role",
752+ "aws_lambda_function.api"
753+ ]
754+ }
755+ ]
756+ },
757+ {
758+ "mode": "managed",
759+ "type": "aws_s3_bucket",
760+ "name": "frontend",
761+ "provider": "provider[\"registry.terraform.io/hashicorp/aws\"]",
762+ "instances": [
763+ {
764+ "schema_version": 0,
765+ "attributes": {
766+ "acceleration_status": "",
767+ "acl": null,
768+ "arn": "arn:aws:s3:::rfl-frontend.hygo",
769+ "bucket": "rfl-frontend.hygo",
770+ "bucket_domain_name": "rfl-frontend.hygo.s3.amazonaws.com",
771+ "bucket_prefix": "",
772+ "bucket_regional_domain_name": "rfl-frontend.hygo.s3.us-west-1.amazonaws.com",
773+ "cors_rule": [],
774+ "force_destroy": false,
775+ "grant": [
776+ {
777+ "id": "1b184376d6e0b905901383d861912c4a020d8db220e2b6ac41c8318df695d62b",
778+ "permissions": [
779+ "FULL_CONTROL"
780+ ],
781+ "type": "CanonicalUser",
782+ "uri": ""
783+ }
784+ ],
785+ "hosted_zone_id": "Z2F56UZL2M1ACD",
786+ "id": "rfl-frontend.hygo",
787+ "lifecycle_rule": [],
788+ "logging": [],
789+ "object_lock_configuration": [],
790+ "object_lock_enabled": false,
791+ "policy": "{\"Statement\":[{\"Action\":\"s3:GetObject\",\"Effect\":\"Allow\",\"Principal\":\"*\",\"Resource\":\"arn:aws:s3:::rfl-frontend.hygo/*\",\"Sid\":\"PublicRead\"},{\"Action\":\"s3:GetObject\",\"Condition\":{\"ArnLike\":{\"AWS:SourceArn\":\"arn:aws:cloudfront::036487096349:distribution/E3QQ8AY9QCV40V\"}},\"Effect\":\"Allow\",\"Principal\":{\"Service\":\"cloudfront.amazonaws.com\"},\"Resource\":\"arn:aws:s3:::rfl-frontend.hygo/*\",\"Sid\":\"AllowCloudFrontServicePrincipal\"}],\"Version\":\"2012-10-17\"}",
792+ "region": "us-west-1",
793+ "replication_configuration": [],
794+ "request_payer": "BucketOwner",
795+ "server_side_encryption_configuration": [
796+ {
797+ "rule": [
798+ {
799+ "apply_server_side_encryption_by_default": [
800+ {
801+ "kms_master_key_id": "",
802+ "sse_algorithm": "AES256"
803+ }
804+ ],
805+ "bucket_key_enabled": false
806+ }
807+ ]
808+ }
809+ ],
810+ "tags": {
811+ "Name": "ReadFasterLabs"
812+ },
813+ "tags_all": {
814+ "Name": "ReadFasterLabs"
815+ },
816+ "timeouts": null,
817+ "versioning": [
818+ {
819+ "enabled": false,
820+ "mfa_delete": false
821+ }
822+ ],
823+ "website": [
824+ {
825+ "error_document": "",
826+ "index_document": "index.html",
827+ "redirect_all_requests_to": "",
828+ "routing_rules": ""
829+ }
830+ ],
831+ "website_domain": "s3-website-us-west-1.amazonaws.com",
832+ "website_endpoint": "rfl-frontend.hygo.s3-website-us-west-1.amazonaws.com"
833+ },
834+ "sensitive_attributes": [],
835+ "identity_schema_version": 0,
836+ "private": "eyJlMmJmYjczMC1lY2FhLTExZTYtOGY4OC0zNDM2M2JjN2M0YzAiOnsiY3JlYXRlIjoxMjAwMDAwMDAwMDAwLCJkZWxldGUiOjM2MDAwMDAwMDAwMDAsInJlYWQiOjEyMDAwMDAwMDAwMDAsInVwZGF0ZSI6MTIwMDAwMDAwMDAwMH19"
837+ }
838+ ]
839+ },
840+ {
841+ "mode": "managed",
842+ "type": "aws_s3_bucket_policy",
843+ "name": "frontend",
844+ "provider": "provider[\"registry.terraform.io/hashicorp/aws\"]",
845+ "instances": [
846+ {
847+ "schema_version": 0,
848+ "attributes": {
849+ "bucket": "rfl-frontend.hygo",
850+ "id": "rfl-frontend.hygo",
851+ "policy": "{\"Statement\":[{\"Action\":\"s3:GetObject\",\"Effect\":\"Allow\",\"Principal\":\"*\",\"Resource\":\"arn:aws:s3:::rfl-frontend.hygo/*\",\"Sid\":\"PublicRead\"},{\"Action\":\"s3:GetObject\",\"Condition\":{\"ArnLike\":{\"AWS:SourceArn\":\"arn:aws:cloudfront::036487096349:distribution/E3QQ8AY9QCV40V\"}},\"Effect\":\"Allow\",\"Principal\":{\"Service\":\"cloudfront.amazonaws.com\"},\"Resource\":\"arn:aws:s3:::rfl-frontend.hygo/*\",\"Sid\":\"AllowCloudFrontServicePrincipal\"}],\"Version\":\"2012-10-17\"}"
852+ },
853+ "sensitive_attributes": [],
854+ "identity_schema_version": 0,
855+ "private": "bnVsbA==",
856+ "dependencies": [
857+ "aws_apigatewayv2_api.http_api",
858+ "aws_cloudfront_distribution.cdn",
859+ "aws_s3_bucket.frontend",
860+ "aws_s3_bucket_website_configuration.frontend",
861+ "data.aws_iam_policy_document.origin_bucket_policy"
862+ ]
863+ }
864+ ]
865+ },
866+ {
867+ "mode": "managed",
868+ "type": "aws_s3_bucket_website_configuration",
869+ "name": "frontend",
870+ "provider": "provider[\"registry.terraform.io/hashicorp/aws\"]",
871+ "instances": [
872+ {
873+ "schema_version": 0,
874+ "attributes": {
875+ "bucket": "rfl-frontend.hygo",
876+ "error_document": [],
877+ "expected_bucket_owner": "",
878+ "id": "rfl-frontend.hygo",
879+ "index_document": [
880+ {
881+ "suffix": "index.html"
882+ }
883+ ],
884+ "redirect_all_requests_to": [],
885+ "routing_rule": [],
886+ "routing_rules": "",
887+ "website_domain": "s3-website-us-west-1.amazonaws.com",
888+ "website_endpoint": "rfl-frontend.hygo.s3-website-us-west-1.amazonaws.com"
889+ },
890+ "sensitive_attributes": [],
891+ "identity_schema_version": 0,
892+ "private": "bnVsbA==",
893+ "dependencies": [
894+ "aws_s3_bucket.frontend"
895+ ]
896+ }
897+ ]
898+ }
899+ ],
900+ "check_results": null
901+}
+901-0terraform.tfstate.backup
@@ -0,0 +1,901 @@
1+{
2+ "version": 4,
3+ "terraform_version": "1.13.3",
4+ "serial": 208,
5+ "lineage": "0f9ff0dd-e8f8-bd72-d551-f6a84fdbea86",
6+ "outputs": {
7+ "cloudfront_distribution_id": {
8+ "value": "E3QQ8AY9QCV40V",
9+ "type": "string"
10+ },
11+ "cloudfront_url": {
12+ "value": "d3u6qxzv4zlkzy.cloudfront.net",
13+ "type": "string"
14+ },
15+ "lambda_arn": {
16+ "value": "arn:aws:lambda:us-west-1:036487096349:function:rfl-rust-api",
17+ "type": "string"
18+ },
19+ "lambda_name": {
20+ "value": "rfl-rust-api",
21+ "type": "string"
22+ }
23+ },
24+ "resources": [
25+ {
26+ "mode": "data",
27+ "type": "aws_iam_policy_document",
28+ "name": "origin_bucket_policy",
29+ "provider": "provider[\"registry.terraform.io/hashicorp/aws\"]",
30+ "instances": [
31+ {
32+ "schema_version": 0,
33+ "attributes": {
34+ "id": "3485735718",
35+ "json": "{\n \"Version\": \"2012-10-17\",\n \"Statement\": [\n {\n \"Sid\": \"PublicRead\",\n \"Effect\": \"Allow\",\n \"Action\": \"s3:GetObject\",\n \"Resource\": \"arn:aws:s3:::rfl-frontend.hygo/*\",\n \"Principal\": \"*\"\n },\n {\n \"Sid\": \"AllowCloudFrontServicePrincipal\",\n \"Effect\": \"Allow\",\n \"Action\": \"s3:GetObject\",\n \"Resource\": \"arn:aws:s3:::rfl-frontend.hygo/*\",\n \"Principal\": {\n \"Service\": \"cloudfront.amazonaws.com\"\n },\n \"Condition\": {\n \"ArnLike\": {\n \"AWS:SourceArn\": \"arn:aws:cloudfront::036487096349:distribution/E3QQ8AY9QCV40V\"\n }\n }\n }\n ]\n}",
36+ "minified_json": "{\"Version\":\"2012-10-17\",\"Statement\":[{\"Sid\":\"PublicRead\",\"Effect\":\"Allow\",\"Action\":\"s3:GetObject\",\"Resource\":\"arn:aws:s3:::rfl-frontend.hygo/*\",\"Principal\":\"*\"},{\"Sid\":\"AllowCloudFrontServicePrincipal\",\"Effect\":\"Allow\",\"Action\":\"s3:GetObject\",\"Resource\":\"arn:aws:s3:::rfl-frontend.hygo/*\",\"Principal\":{\"Service\":\"cloudfront.amazonaws.com\"},\"Condition\":{\"ArnLike\":{\"AWS:SourceArn\":\"arn:aws:cloudfront::036487096349:distribution/E3QQ8AY9QCV40V\"}}}]}",
37+ "override_json": null,
38+ "override_policy_documents": null,
39+ "policy_id": null,
40+ "source_json": null,
41+ "source_policy_documents": null,
42+ "statement": [
43+ {
44+ "actions": [
45+ "s3:GetObject"
46+ ],
47+ "condition": [],
48+ "effect": "Allow",
49+ "not_actions": [],
50+ "not_principals": [],
51+ "not_resources": [],
52+ "principals": [
53+ {
54+ "identifiers": [
55+ "*"
56+ ],
57+ "type": "*"
58+ }
59+ ],
60+ "resources": [
61+ "arn:aws:s3:::rfl-frontend.hygo/*"
62+ ],
63+ "sid": "PublicRead"
64+ },
65+ {
66+ "actions": [
67+ "s3:GetObject"
68+ ],
69+ "condition": [
70+ {
71+ "test": "ArnLike",
72+ "values": [
73+ "arn:aws:cloudfront::036487096349:distribution/E3QQ8AY9QCV40V"
74+ ],
75+ "variable": "AWS:SourceArn"
76+ }
77+ ],
78+ "effect": "Allow",
79+ "not_actions": [],
80+ "not_principals": [],
81+ "not_resources": [],
82+ "principals": [
83+ {
84+ "identifiers": [
85+ "cloudfront.amazonaws.com"
86+ ],
87+ "type": "Service"
88+ }
89+ ],
90+ "resources": [
91+ "arn:aws:s3:::rfl-frontend.hygo/*"
92+ ],
93+ "sid": "AllowCloudFrontServicePrincipal"
94+ }
95+ ],
96+ "version": "2012-10-17"
97+ },
98+ "sensitive_attributes": [],
99+ "identity_schema_version": 0
100+ }
101+ ]
102+ },
103+ {
104+ "mode": "managed",
105+ "type": "aws_apigatewayv2_api",
106+ "name": "http_api",
107+ "provider": "provider[\"registry.terraform.io/hashicorp/aws\"]",
108+ "instances": [
109+ {
110+ "schema_version": 0,
111+ "attributes": {
112+ "api_endpoint": "https://teopf75zy7.execute-api.us-west-1.amazonaws.com",
113+ "api_key_selection_expression": "$request.header.x-api-key",
114+ "arn": "arn:aws:apigateway:us-west-1::/apis/teopf75zy7",
115+ "body": null,
116+ "cors_configuration": [],
117+ "credentials_arn": null,
118+ "description": "",
119+ "disable_execute_api_endpoint": false,
120+ "execution_arn": "arn:aws:execute-api:us-west-1:036487096349:teopf75zy7",
121+ "fail_on_warnings": null,
122+ "id": "teopf75zy7",
123+ "ip_address_type": "ipv4",
124+ "name": "rfl-rust-api-gateway",
125+ "protocol_type": "HTTP",
126+ "route_key": null,
127+ "route_selection_expression": "$request.method $request.path",
128+ "tags": {},
129+ "tags_all": {},
130+ "target": null,
131+ "version": ""
132+ },
133+ "sensitive_attributes": [],
134+ "identity_schema_version": 0,
135+ "private": "bnVsbA=="
136+ }
137+ ]
138+ },
139+ {
140+ "mode": "managed",
141+ "type": "aws_apigatewayv2_integration",
142+ "name": "lambda_integration",
143+ "provider": "provider[\"registry.terraform.io/hashicorp/aws\"]",
144+ "instances": [
145+ {
146+ "schema_version": 0,
147+ "attributes": {
148+ "api_id": "teopf75zy7",
149+ "connection_id": "",
150+ "connection_type": "INTERNET",
151+ "content_handling_strategy": "",
152+ "credentials_arn": "",
153+ "description": "",
154+ "id": "wqvnwt6",
155+ "integration_method": "POST",
156+ "integration_response_selection_expression": "",
157+ "integration_subtype": "",
158+ "integration_type": "AWS_PROXY",
159+ "integration_uri": "arn:aws:apigateway:us-west-1:lambda:path/2015-03-31/functions/arn:aws:lambda:us-west-1:036487096349:function:rfl-rust-api/invocations",
160+ "passthrough_behavior": "",
161+ "payload_format_version": "2.0",
162+ "request_parameters": {},
163+ "request_templates": {},
164+ "response_parameters": [],
165+ "template_selection_expression": "",
166+ "timeout_milliseconds": 30000,
167+ "tls_config": []
168+ },
169+ "sensitive_attributes": [],
170+ "identity_schema_version": 0,
171+ "private": "bnVsbA==",
172+ "dependencies": [
173+ "aws_apigatewayv2_api.http_api",
174+ "aws_iam_role.lambda_role",
175+ "aws_lambda_function.api"
176+ ]
177+ }
178+ ]
179+ },
180+ {
181+ "mode": "managed",
182+ "type": "aws_apigatewayv2_route",
183+ "name": "default_route",
184+ "provider": "provider[\"registry.terraform.io/hashicorp/aws\"]",
185+ "instances": [
186+ {
187+ "schema_version": 0,
188+ "attributes": {
189+ "api_id": "teopf75zy7",
190+ "api_key_required": false,
191+ "authorization_scopes": [],
192+ "authorization_type": "NONE",
193+ "authorizer_id": "",
194+ "id": "cybly2s",
195+ "model_selection_expression": "",
196+ "operation_name": "",
197+ "request_models": {},
198+ "request_parameter": [],
199+ "route_key": "ANY /{proxy+}",
200+ "route_response_selection_expression": "",
201+ "target": "integrations/wqvnwt6"
202+ },
203+ "sensitive_attributes": [],
204+ "identity_schema_version": 0,
205+ "private": "bnVsbA==",
206+ "dependencies": [
207+ "aws_apigatewayv2_api.http_api",
208+ "aws_apigatewayv2_integration.lambda_integration",
209+ "aws_iam_role.lambda_role",
210+ "aws_lambda_function.api"
211+ ]
212+ }
213+ ]
214+ },
215+ {
216+ "mode": "managed",
217+ "type": "aws_apigatewayv2_stage",
218+ "name": "default_stage",
219+ "provider": "provider[\"registry.terraform.io/hashicorp/aws\"]",
220+ "instances": [
221+ {
222+ "schema_version": 0,
223+ "attributes": {
224+ "access_log_settings": [],
225+ "api_id": "teopf75zy7",
226+ "arn": "arn:aws:apigateway:us-west-1::/apis/teopf75zy7/stages/$default",
227+ "auto_deploy": true,
228+ "client_certificate_id": "",
229+ "default_route_settings": [
230+ {
231+ "data_trace_enabled": false,
232+ "detailed_metrics_enabled": false,
233+ "logging_level": "",
234+ "throttling_burst_limit": 0,
235+ "throttling_rate_limit": 0
236+ }
237+ ],
238+ "deployment_id": "lm0u9y",
239+ "description": "",
240+ "execution_arn": "arn:aws:execute-api:us-west-1:036487096349:teopf75zy7/$default",
241+ "id": "$default",
242+ "invoke_url": "https://teopf75zy7.execute-api.us-west-1.amazonaws.com/",
243+ "name": "$default",
244+ "route_settings": [],
245+ "stage_variables": {},
246+ "tags": {},
247+ "tags_all": {}
248+ },
249+ "sensitive_attributes": [],
250+ "identity_schema_version": 0,
251+ "private": "bnVsbA==",
252+ "dependencies": [
253+ "aws_apigatewayv2_api.http_api"
254+ ]
255+ }
256+ ]
257+ },
258+ {
259+ "mode": "managed",
260+ "type": "aws_cloudfront_distribution",
261+ "name": "cdn",
262+ "provider": "provider[\"registry.terraform.io/hashicorp/aws\"]",
263+ "instances": [
264+ {
265+ "schema_version": 1,
266+ "attributes": {
267+ "aliases": [
268+ "readfasterlabs.com",
269+ "www.readfasterlabs.com"
270+ ],
271+ "arn": "arn:aws:cloudfront::036487096349:distribution/E3QQ8AY9QCV40V",
272+ "caller_reference": "terraform-20251021151303194400000001",
273+ "comment": "ReadFasterLabs CDN",
274+ "continuous_deployment_policy_id": "",
275+ "custom_error_response": [],
276+ "default_cache_behavior": [
277+ {
278+ "allowed_methods": [
279+ "DELETE",
280+ "GET",
281+ "HEAD",
282+ "OPTIONS",
283+ "PATCH",
284+ "POST",
285+ "PUT"
286+ ],
287+ "cache_policy_id": "",
288+ "cached_methods": [
289+ "GET",
290+ "HEAD"
291+ ],
292+ "compress": false,
293+ "default_ttl": 3600,
294+ "field_level_encryption_id": "",
295+ "forwarded_values": [
296+ {
297+ "cookies": [
298+ {
299+ "forward": "none",
300+ "whitelisted_names": []
301+ }
302+ ],
303+ "headers": [
304+ "Authorization"
305+ ],
306+ "query_string": true,
307+ "query_string_cache_keys": []
308+ }
309+ ],
310+ "function_association": [],
311+ "grpc_config": [
312+ {
313+ "enabled": false
314+ }
315+ ],
316+ "lambda_function_association": [],
317+ "max_ttl": 86400,
318+ "min_ttl": 0,
319+ "origin_request_policy_id": "",
320+ "realtime_log_config_arn": "",
321+ "response_headers_policy_id": "",
322+ "smooth_streaming": false,
323+ "target_origin_id": "myS3Origin",
324+ "trusted_key_groups": [],
325+ "trusted_signers": [],
326+ "viewer_protocol_policy": "redirect-to-https"
327+ }
328+ ],
329+ "default_root_object": "index.html",
330+ "domain_name": "d3u6qxzv4zlkzy.cloudfront.net",
331+ "enabled": true,
332+ "etag": "EOE7YQ3FGLFQT",
333+ "hosted_zone_id": "Z2FDTNDATAQYW2",
334+ "http_version": "http2",
335+ "id": "E3QQ8AY9QCV40V",
336+ "in_progress_validation_batches": 0,
337+ "is_ipv6_enabled": true,
338+ "last_modified_time": "2025-10-22 01:58:02.776 +0000 UTC",
339+ "logging_config": [],
340+ "ordered_cache_behavior": [
341+ {
342+ "allowed_methods": [
343+ "DELETE",
344+ "GET",
345+ "HEAD",
346+ "OPTIONS",
347+ "PATCH",
348+ "POST",
349+ "PUT"
350+ ],
351+ "cache_policy_id": "",
352+ "cached_methods": [
353+ "GET",
354+ "HEAD"
355+ ],
356+ "compress": true,
357+ "default_ttl": 3600,
358+ "field_level_encryption_id": "",
359+ "forwarded_values": [
360+ {
361+ "cookies": [
362+ {
363+ "forward": "none",
364+ "whitelisted_names": []
365+ }
366+ ],
367+ "headers": [
368+ "Authorization"
369+ ],
370+ "query_string": true,
371+ "query_string_cache_keys": []
372+ }
373+ ],
374+ "function_association": [],
375+ "grpc_config": [
376+ {
377+ "enabled": false
378+ }
379+ ],
380+ "lambda_function_association": [],
381+ "max_ttl": 86400,
382+ "min_ttl": 0,
383+ "origin_request_policy_id": "",
384+ "path_pattern": "/api/*",
385+ "realtime_log_config_arn": "",
386+ "response_headers_policy_id": "",
387+ "smooth_streaming": false,
388+ "target_origin_id": "api-origin",
389+ "trusted_key_groups": [],
390+ "trusted_signers": [],
391+ "viewer_protocol_policy": "redirect-to-https"
392+ }
393+ ],
394+ "origin": [
395+ {
396+ "connection_attempts": 3,
397+ "connection_timeout": 10,
398+ "custom_header": [],
399+ "custom_origin_config": [
400+ {
401+ "http_port": 80,
402+ "https_port": 443,
403+ "origin_keepalive_timeout": 5,
404+ "origin_protocol_policy": "http-only",
405+ "origin_read_timeout": 30,
406+ "origin_ssl_protocols": [
407+ "TLSv1.2"
408+ ]
409+ }
410+ ],
411+ "domain_name": "rfl-frontend.hygo.s3-website-us-west-1.amazonaws.com",
412+ "origin_access_control_id": "",
413+ "origin_id": "myS3Origin",
414+ "origin_path": "",
415+ "origin_shield": [],
416+ "s3_origin_config": [],
417+ "vpc_origin_config": []
418+ },
419+ {
420+ "connection_attempts": 3,
421+ "connection_timeout": 10,
422+ "custom_header": [],
423+ "custom_origin_config": [
424+ {
425+ "http_port": 80,
426+ "https_port": 443,
427+ "origin_keepalive_timeout": 5,
428+ "origin_protocol_policy": "https-only",
429+ "origin_read_timeout": 30,
430+ "origin_ssl_protocols": [
431+ "TLSv1.2"
432+ ]
433+ }
434+ ],
435+ "domain_name": "teopf75zy7.execute-api.us-west-1.amazonaws.com",
436+ "origin_access_control_id": "",
437+ "origin_id": "api-origin",
438+ "origin_path": "",
439+ "origin_shield": [],
440+ "s3_origin_config": [],
441+ "vpc_origin_config": []
442+ }
443+ ],
444+ "origin_group": [],
445+ "price_class": "PriceClass_200",
446+ "restrictions": [
447+ {
448+ "geo_restriction": [
449+ {
450+ "locations": [
451+ "CA",
452+ "DE",
453+ "GB",
454+ "US"
455+ ],
456+ "restriction_type": "whitelist"
457+ }
458+ ]
459+ }
460+ ],
461+ "retain_on_delete": false,
462+ "staging": false,
463+ "status": "Deployed",
464+ "tags": {
465+ "Environment": "production"
466+ },
467+ "tags_all": {
468+ "Environment": "production"
469+ },
470+ "trusted_key_groups": [
471+ {
472+ "enabled": false,
473+ "items": []
474+ }
475+ ],
476+ "trusted_signers": [
477+ {
478+ "enabled": false,
479+ "items": []
480+ }
481+ ],
482+ "viewer_certificate": [
483+ {
484+ "acm_certificate_arn": "arn:aws:acm:us-east-1:036487096349:certificate/dc4f8dcc-9809-4d6d-8258-362cf5e19244",
485+ "cloudfront_default_certificate": false,
486+ "iam_certificate_id": "",
487+ "minimum_protocol_version": "TLSv1.2_2021",
488+ "ssl_support_method": "sni-only"
489+ }
490+ ],
491+ "wait_for_deployment": true,
492+ "web_acl_id": ""
493+ },
494+ "sensitive_attributes": [],
495+ "identity_schema_version": 0,
496+ "private": "eyJzY2hlbWFfdmVyc2lvbiI6IjEifQ==",
497+ "dependencies": [
498+ "aws_apigatewayv2_api.http_api",
499+ "aws_s3_bucket.frontend",
500+ "aws_s3_bucket_website_configuration.frontend"
501+ ]
502+ }
503+ ]
504+ },
505+ {
506+ "mode": "managed",
507+ "type": "aws_cloudfront_origin_access_control",
508+ "name": "default",
509+ "provider": "provider[\"registry.terraform.io/hashicorp/aws\"]",
510+ "instances": [
511+ {
512+ "schema_version": 0,
513+ "attributes": {
514+ "arn": "arn:aws:cloudfront::036487096349:origin-access-control/E6YQTL8HZQZGN",
515+ "description": "Managed by Terraform",
516+ "etag": "ETVPDKIKX0DER",
517+ "id": "E6YQTL8HZQZGN",
518+ "name": "default-oac",
519+ "origin_access_control_origin_type": "s3",
520+ "signing_behavior": "always",
521+ "signing_protocol": "sigv4"
522+ },
523+ "sensitive_attributes": [],
524+ "identity_schema_version": 0,
525+ "private": "bnVsbA=="
526+ }
527+ ]
528+ },
529+ {
530+ "mode": "managed",
531+ "type": "aws_iam_policy",
532+ "name": "lambda_secret_access",
533+ "provider": "provider[\"registry.terraform.io/hashicorp/aws\"]",
534+ "instances": [
535+ {
536+ "schema_version": 0,
537+ "attributes": {
538+ "arn": "arn:aws:iam::036487096349:policy/lambda-secret-access",
539+ "attachment_count": 1,
540+ "description": "",
541+ "id": "arn:aws:iam::036487096349:policy/lambda-secret-access",
542+ "name": "lambda-secret-access",
543+ "name_prefix": "",
544+ "path": "/",
545+ "policy": "{\"Statement\":[{\"Action\":[\"secretsmanager:GetSecretValue\"],\"Effect\":\"Allow\",\"Resource\":[\"arn:aws:secretsmanager:us-west-1:036487096349:secret:rfl-secrets-ztW9tp\"]}],\"Version\":\"2012-10-17\"}",
546+ "policy_id": "ANPAQQ7WM5AOYLJGC2FKW",
547+ "tags": {},
548+ "tags_all": {}
549+ },
550+ "sensitive_attributes": [],
551+ "identity_schema_version": 0,
552+ "private": "bnVsbA=="
553+ }
554+ ]
555+ },
556+ {
557+ "mode": "managed",
558+ "type": "aws_iam_role",
559+ "name": "lambda_role",
560+ "provider": "provider[\"registry.terraform.io/hashicorp/aws\"]",
561+ "instances": [
562+ {
563+ "schema_version": 0,
564+ "attributes": {
565+ "arn": "arn:aws:iam::036487096349:role/rfl-rust-api-role",
566+ "assume_role_policy": "{\"Statement\":[{\"Action\":\"sts:AssumeRole\",\"Effect\":\"Allow\",\"Principal\":{\"Service\":\"lambda.amazonaws.com\"}}],\"Version\":\"2012-10-17\"}",
567+ "create_date": "2025-10-21T14:31:41Z",
568+ "description": "",
569+ "force_detach_policies": false,
570+ "id": "rfl-rust-api-role",
571+ "inline_policy": [],
572+ "managed_policy_arns": [
573+ "arn:aws:iam::036487096349:policy/lambda-secret-access",
574+ "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"
575+ ],
576+ "max_session_duration": 3600,
577+ "name": "rfl-rust-api-role",
578+ "name_prefix": "",
579+ "path": "/",
580+ "permissions_boundary": "",
581+ "tags": {},
582+ "tags_all": {},
583+ "unique_id": "AROAQQ7WM5AOS7MVIC5QD"
584+ },
585+ "sensitive_attributes": [],
586+ "identity_schema_version": 0,
587+ "private": "bnVsbA=="
588+ }
589+ ]
590+ },
591+ {
592+ "mode": "managed",
593+ "type": "aws_iam_role_policy_attachment",
594+ "name": "lambda_logging",
595+ "provider": "provider[\"registry.terraform.io/hashicorp/aws\"]",
596+ "instances": [
597+ {
598+ "schema_version": 0,
599+ "attributes": {
600+ "id": "rfl-rust-api-role-20251021143142048400000001",
601+ "policy_arn": "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole",
602+ "role": "rfl-rust-api-role"
603+ },
604+ "sensitive_attributes": [],
605+ "identity_schema_version": 0,
606+ "private": "bnVsbA==",
607+ "dependencies": [
608+ "aws_iam_role.lambda_role"
609+ ]
610+ }
611+ ]
612+ },
613+ {
614+ "mode": "managed",
615+ "type": "aws_iam_role_policy_attachment",
616+ "name": "lambda_secret_access",
617+ "provider": "provider[\"registry.terraform.io/hashicorp/aws\"]",
618+ "instances": [
619+ {
620+ "schema_version": 0,
621+ "attributes": {
622+ "id": "rfl-rust-api-role-20251021172419743600000002",
623+ "policy_arn": "arn:aws:iam::036487096349:policy/lambda-secret-access",
624+ "role": "rfl-rust-api-role"
625+ },
626+ "sensitive_attributes": [],
627+ "identity_schema_version": 0,
628+ "private": "bnVsbA==",
629+ "dependencies": [
630+ "aws_iam_policy.lambda_secret_access",
631+ "aws_iam_role.lambda_role"
632+ ]
633+ }
634+ ]
635+ },
636+ {
637+ "mode": "managed",
638+ "type": "aws_lambda_function",
639+ "name": "api",
640+ "provider": "provider[\"registry.terraform.io/hashicorp/aws\"]",
641+ "instances": [
642+ {
643+ "schema_version": 0,
644+ "attributes": {
645+ "architectures": [
646+ "x86_64"
647+ ],
648+ "arn": "arn:aws:lambda:us-west-1:036487096349:function:rfl-rust-api",
649+ "code_sha256": "NHgFZmvpEPkVenG3QDQAJRFYiOXuR99pA8uWMyK/3hQ=",
650+ "code_signing_config_arn": "",
651+ "dead_letter_config": [],
652+ "description": "",
653+ "environment": [
654+ {
655+ "variables": {
656+ "ENV_FILE": ".env"
657+ }
658+ }
659+ ],
660+ "ephemeral_storage": [
661+ {
662+ "size": 512
663+ }
664+ ],
665+ "file_system_config": [],
666+ "filename": "../lambda.zip",
667+ "function_name": "rfl-rust-api",
668+ "handler": "bootstrap",
669+ "id": "rfl-rust-api",
670+ "image_config": [],
671+ "image_uri": "",
672+ "invoke_arn": "arn:aws:apigateway:us-west-1:lambda:path/2015-03-31/functions/arn:aws:lambda:us-west-1:036487096349:function:rfl-rust-api/invocations",
673+ "kms_key_arn": "",
674+ "last_modified": "2025-10-22T19:08:29.000+0000",
675+ "layers": [],
676+ "logging_config": [
677+ {
678+ "application_log_level": "",
679+ "log_format": "Text",
680+ "log_group": "/aws/lambda/rfl-rust-api",
681+ "system_log_level": ""
682+ }
683+ ],
684+ "memory_size": 128,
685+ "package_type": "Zip",
686+ "publish": false,
687+ "qualified_arn": "arn:aws:lambda:us-west-1:036487096349:function:rfl-rust-api:$LATEST",
688+ "qualified_invoke_arn": "arn:aws:apigateway:us-west-1:lambda:path/2015-03-31/functions/arn:aws:lambda:us-west-1:036487096349:function:rfl-rust-api:$LATEST/invocations",
689+ "replace_security_groups_on_destroy": null,
690+ "replacement_security_group_ids": null,
691+ "reserved_concurrent_executions": -1,
692+ "role": "arn:aws:iam::036487096349:role/rfl-rust-api-role",
693+ "runtime": "provided.al2023",
694+ "s3_bucket": null,
695+ "s3_key": null,
696+ "s3_object_version": null,
697+ "signing_job_arn": "",
698+ "signing_profile_version_arn": "",
699+ "skip_destroy": false,
700+ "snap_start": [],
701+ "source_code_hash": "NHgFZmvpEPkVenG3QDQAJRFYiOXuR99pA8uWMyK/3hQ=",
702+ "source_code_size": 13841914,
703+ "tags": {},
704+ "tags_all": {},
705+ "timeout": 3,
706+ "timeouts": null,
707+ "tracing_config": [
708+ {
709+ "mode": "PassThrough"
710+ }
711+ ],
712+ "version": "$LATEST",
713+ "vpc_config": []
714+ },
715+ "sensitive_attributes": [],
716+ "identity_schema_version": 0,
717+ "private": "eyJlMmJmYjczMC1lY2FhLTExZTYtOGY4OC0zNDM2M2JjN2M0YzAiOnsiY3JlYXRlIjo2MDAwMDAwMDAwMDAsImRlbGV0ZSI6NjAwMDAwMDAwMDAwLCJ1cGRhdGUiOjYwMDAwMDAwMDAwMH19",
718+ "dependencies": [
719+ "aws_iam_role.lambda_role"
720+ ]
721+ }
722+ ]
723+ },
724+ {
725+ "mode": "managed",
726+ "type": "aws_lambda_permission",
727+ "name": "allow_apigw",
728+ "provider": "provider[\"registry.terraform.io/hashicorp/aws\"]",
729+ "instances": [
730+ {
731+ "schema_version": 0,
732+ "attributes": {
733+ "action": "lambda:InvokeFunction",
734+ "event_source_token": null,
735+ "function_name": "rfl-rust-api",
736+ "function_url_auth_type": null,
737+ "id": "AllowExecutionFromAPIGateway",
738+ "principal": "apigateway.amazonaws.com",
739+ "principal_org_id": null,
740+ "qualifier": "",
741+ "source_account": null,
742+ "source_arn": "arn:aws:execute-api:us-west-1:036487096349:teopf75zy7/*/*",
743+ "statement_id": "AllowExecutionFromAPIGateway",
744+ "statement_id_prefix": ""
745+ },
746+ "sensitive_attributes": [],
747+ "identity_schema_version": 0,
748+ "private": "bnVsbA==",
749+ "dependencies": [
750+ "aws_apigatewayv2_api.http_api",
751+ "aws_iam_role.lambda_role",
752+ "aws_lambda_function.api"
753+ ]
754+ }
755+ ]
756+ },
757+ {
758+ "mode": "managed",
759+ "type": "aws_s3_bucket",
760+ "name": "frontend",
761+ "provider": "provider[\"registry.terraform.io/hashicorp/aws\"]",
762+ "instances": [
763+ {
764+ "schema_version": 0,
765+ "attributes": {
766+ "acceleration_status": "",
767+ "acl": null,
768+ "arn": "arn:aws:s3:::rfl-frontend.hygo",
769+ "bucket": "rfl-frontend.hygo",
770+ "bucket_domain_name": "rfl-frontend.hygo.s3.amazonaws.com",
771+ "bucket_prefix": "",
772+ "bucket_regional_domain_name": "rfl-frontend.hygo.s3.us-west-1.amazonaws.com",
773+ "cors_rule": [],
774+ "force_destroy": false,
775+ "grant": [
776+ {
777+ "id": "1b184376d6e0b905901383d861912c4a020d8db220e2b6ac41c8318df695d62b",
778+ "permissions": [
779+ "FULL_CONTROL"
780+ ],
781+ "type": "CanonicalUser",
782+ "uri": ""
783+ }
784+ ],
785+ "hosted_zone_id": "Z2F56UZL2M1ACD",
786+ "id": "rfl-frontend.hygo",
787+ "lifecycle_rule": [],
788+ "logging": [],
789+ "object_lock_configuration": [],
790+ "object_lock_enabled": false,
791+ "policy": "{\"Statement\":[{\"Action\":\"s3:GetObject\",\"Effect\":\"Allow\",\"Principal\":\"*\",\"Resource\":\"arn:aws:s3:::rfl-frontend.hygo/*\",\"Sid\":\"PublicRead\"},{\"Action\":\"s3:GetObject\",\"Condition\":{\"ArnLike\":{\"AWS:SourceArn\":\"arn:aws:cloudfront::036487096349:distribution/E3QQ8AY9QCV40V\"}},\"Effect\":\"Allow\",\"Principal\":{\"Service\":\"cloudfront.amazonaws.com\"},\"Resource\":\"arn:aws:s3:::rfl-frontend.hygo/*\",\"Sid\":\"AllowCloudFrontServicePrincipal\"}],\"Version\":\"2012-10-17\"}",
792+ "region": "us-west-1",
793+ "replication_configuration": [],
794+ "request_payer": "BucketOwner",
795+ "server_side_encryption_configuration": [
796+ {
797+ "rule": [
798+ {
799+ "apply_server_side_encryption_by_default": [
800+ {
801+ "kms_master_key_id": "",
802+ "sse_algorithm": "AES256"
803+ }
804+ ],
805+ "bucket_key_enabled": false
806+ }
807+ ]
808+ }
809+ ],
810+ "tags": {
811+ "Name": "ReadFasterLabs"
812+ },
813+ "tags_all": {
814+ "Name": "ReadFasterLabs"
815+ },
816+ "timeouts": null,
817+ "versioning": [
818+ {
819+ "enabled": false,
820+ "mfa_delete": false
821+ }
822+ ],
823+ "website": [
824+ {
825+ "error_document": "",
826+ "index_document": "index.html",
827+ "redirect_all_requests_to": "",
828+ "routing_rules": ""
829+ }
830+ ],
831+ "website_domain": "s3-website-us-west-1.amazonaws.com",
832+ "website_endpoint": "rfl-frontend.hygo.s3-website-us-west-1.amazonaws.com"
833+ },
834+ "sensitive_attributes": [],
835+ "identity_schema_version": 0,
836+ "private": "eyJlMmJmYjczMC1lY2FhLTExZTYtOGY4OC0zNDM2M2JjN2M0YzAiOnsiY3JlYXRlIjoxMjAwMDAwMDAwMDAwLCJkZWxldGUiOjM2MDAwMDAwMDAwMDAsInJlYWQiOjEyMDAwMDAwMDAwMDAsInVwZGF0ZSI6MTIwMDAwMDAwMDAwMH19"
837+ }
838+ ]
839+ },
840+ {
841+ "mode": "managed",
842+ "type": "aws_s3_bucket_policy",
843+ "name": "frontend",
844+ "provider": "provider[\"registry.terraform.io/hashicorp/aws\"]",
845+ "instances": [
846+ {
847+ "schema_version": 0,
848+ "attributes": {
849+ "bucket": "rfl-frontend.hygo",
850+ "id": "rfl-frontend.hygo",
851+ "policy": "{\"Statement\":[{\"Action\":\"s3:GetObject\",\"Effect\":\"Allow\",\"Principal\":\"*\",\"Resource\":\"arn:aws:s3:::rfl-frontend.hygo/*\",\"Sid\":\"PublicRead\"},{\"Action\":\"s3:GetObject\",\"Condition\":{\"ArnLike\":{\"AWS:SourceArn\":\"arn:aws:cloudfront::036487096349:distribution/E3QQ8AY9QCV40V\"}},\"Effect\":\"Allow\",\"Principal\":{\"Service\":\"cloudfront.amazonaws.com\"},\"Resource\":\"arn:aws:s3:::rfl-frontend.hygo/*\",\"Sid\":\"AllowCloudFrontServicePrincipal\"}],\"Version\":\"2012-10-17\"}"
852+ },
853+ "sensitive_attributes": [],
854+ "identity_schema_version": 0,
855+ "private": "bnVsbA==",
856+ "dependencies": [
857+ "aws_apigatewayv2_api.http_api",
858+ "aws_cloudfront_distribution.cdn",
859+ "aws_s3_bucket.frontend",
860+ "aws_s3_bucket_website_configuration.frontend",
861+ "data.aws_iam_policy_document.origin_bucket_policy"
862+ ]
863+ }
864+ ]
865+ },
866+ {
867+ "mode": "managed",
868+ "type": "aws_s3_bucket_website_configuration",
869+ "name": "frontend",
870+ "provider": "provider[\"registry.terraform.io/hashicorp/aws\"]",
871+ "instances": [
872+ {
873+ "schema_version": 0,
874+ "attributes": {
875+ "bucket": "rfl-frontend.hygo",
876+ "error_document": [],
877+ "expected_bucket_owner": "",
878+ "id": "rfl-frontend.hygo",
879+ "index_document": [
880+ {
881+ "suffix": "index.html"
882+ }
883+ ],
884+ "redirect_all_requests_to": [],
885+ "routing_rule": [],
886+ "routing_rules": "",
887+ "website_domain": "s3-website-us-west-1.amazonaws.com",
888+ "website_endpoint": "rfl-frontend.hygo.s3-website-us-west-1.amazonaws.com"
889+ },
890+ "sensitive_attributes": [],
891+ "identity_schema_version": 0,
892+ "private": "bnVsbA==",
893+ "dependencies": [
894+ "aws_s3_bucket.frontend"
895+ ]
896+ }
897+ ]
898+ }
899+ ],
900+ "check_results": null
901+}
+11-0upload_env_to_secrets.sh
@@ -0,0 +1,11 @@
1+#!/bin/bash
2+val=$(cat "$1" | grep '^\w' | awk -F'=' '{print "\""$1"\":\""$2"\","}')
3+val="{${val%?}}"
4+echo "${val%?}}" >/tmp/env.json
5+cat /tmp/env.json | jq
6+aws secretsmanager put-secret-value \
7+ --secret-id rfl-secrets \
8+ --secret-string file:///tmp/env.json >/dev/null 2>&1 ||
9+ aws secretsmanager create-secret \
10+ --name rfl-secrets \
11+ --secret-string file:///tmp/env.json
+29-0variables.tf
@@ -0,0 +1,29 @@
1+variable "region" {
2+ description = "AWS region to deploy to"
3+ default = "us-west-1"
4+}
5+
6+variable "aws_profile" {
7+ description = "AWS CLI profile name to use"
8+ default = "hygo"
9+}
10+
11+variable "function_name" {
12+ description = "Lambda function name"
13+ default = "rfl-rust-api"
14+}
15+
16+variable "lambda_zip" {
17+ description = "Path to compiled Lambda ZIP"
18+ default = "../lambda.zip"
19+}
20+
21+variable "s3_bucket" {
22+ description = "AWS S3 bucket for frontend Next.js"
23+ default = "rfl-frontend.hygo"
24+}
25+
26+variable "s3_zip" {
27+ description = "Path to compiled Next.js"
28+ default = "frontend.zip"
29+}