Skip to content
This repository was archived by the owner on Feb 6, 2024. It is now read-only.

Commit 4f18d27

Browse files
authored
Merge pull request #76 from deckgo/nm-infra
infra: fix lambda permissions and CORS
2 parents 630d6b6 + 0d7755d commit 4f18d27

File tree

4 files changed

+129
-59
lines changed

4 files changed

+129
-59
lines changed

infra/api_gateway.tf

Lines changed: 78 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,59 +1,109 @@
1-
resource "aws_api_gateway_rest_api" "example" {
2-
name = "ServerlessExample"
3-
description = "Terraform Serverless Application Example"
1+
resource "aws_api_gateway_rest_api" "lambda-api" {
2+
name = "deckdeckgo-handler-rest-api"
43
}
54

65
resource "aws_api_gateway_resource" "proxy" {
7-
rest_api_id = "${aws_api_gateway_rest_api.example.id}"
8-
parent_id = "${aws_api_gateway_rest_api.example.root_resource_id}"
6+
rest_api_id = "${aws_api_gateway_rest_api.lambda-api.id}"
7+
parent_id = "${aws_api_gateway_rest_api.lambda-api.root_resource_id}"
98
path_part = "{proxy+}"
109
}
1110

1211
resource "aws_api_gateway_method" "proxy" {
13-
rest_api_id = "${aws_api_gateway_rest_api.example.id}"
12+
rest_api_id = "${aws_api_gateway_rest_api.lambda-api.id}"
1413
resource_id = "${aws_api_gateway_resource.proxy.id}"
1514
http_method = "ANY"
1615
authorization = "NONE"
1716
}
1817

19-
resource "aws_api_gateway_integration" "lambda" {
20-
rest_api_id = "${aws_api_gateway_rest_api.example.id}"
18+
resource "aws_api_gateway_integration" "lambda-api" {
19+
rest_api_id = "${aws_api_gateway_rest_api.lambda-api.id}"
2120
resource_id = "${aws_api_gateway_method.proxy.resource_id}"
2221
http_method = "${aws_api_gateway_method.proxy.http_method}"
2322

2423
integration_http_method = "POST"
2524
type = "AWS_PROXY"
26-
uri = "${aws_lambda_function.example.invoke_arn}"
25+
uri = "${aws_lambda_function.api.invoke_arn}"
2726
}
2827

29-
resource "aws_api_gateway_method" "proxy_root" {
30-
rest_api_id = "${aws_api_gateway_rest_api.example.id}"
31-
resource_id = "${aws_api_gateway_rest_api.example.root_resource_id}"
32-
http_method = "ANY"
28+
resource "aws_api_gateway_deployment" "lambda-api" {
29+
depends_on = [
30+
"aws_api_gateway_integration.lambda-api",
31+
]
32+
33+
rest_api_id = "${aws_api_gateway_rest_api.lambda-api.id}"
34+
stage_name = "beta"
35+
}
36+
37+
resource "aws_lambda_permission" "lambda_permission" {
38+
action = "lambda:InvokeFunction"
39+
function_name = "${aws_lambda_function.api.function_name}"
40+
principal = "apigateway.amazonaws.com"
41+
source_arn = "${aws_api_gateway_rest_api.lambda-api.execution_arn}/*/*/*"
42+
43+
depends_on = [
44+
"aws_lambda_function.api",
45+
]
46+
}
47+
48+
###############
49+
# Enable CORS #
50+
###############
51+
# https://medium.com/@MrPonath/terraform-and-aws-api-gateway-a137ee48a8ac
52+
resource "aws_api_gateway_method" "options_method" {
53+
rest_api_id = "${aws_api_gateway_rest_api.lambda-api.id}"
54+
resource_id = "${aws_api_gateway_resource.proxy.id}"
55+
http_method = "OPTIONS"
3356
authorization = "NONE"
3457
}
3558

36-
resource "aws_api_gateway_integration" "lambda_root" {
37-
rest_api_id = "${aws_api_gateway_rest_api.example.id}"
38-
resource_id = "${aws_api_gateway_method.proxy_root.resource_id}"
39-
http_method = "${aws_api_gateway_method.proxy_root.http_method}"
59+
resource "aws_api_gateway_method_response" "options_200" {
60+
rest_api_id = "${aws_api_gateway_rest_api.lambda-api.id}"
61+
resource_id = "${aws_api_gateway_resource.proxy.id}"
62+
http_method = "${aws_api_gateway_method.options_method.http_method}"
63+
status_code = 200
4064

41-
integration_http_method = "POST"
42-
type = "AWS_PROXY"
43-
uri = "${aws_lambda_function.example.invoke_arn}"
65+
response_models {
66+
"application/json" = "Empty"
67+
}
68+
69+
response_parameters {
70+
"method.response.header.Access-Control-Allow-Headers" = true
71+
"method.response.header.Access-Control-Allow-Methods" = true
72+
"method.response.header.Access-Control-Allow-Origin" = true
73+
}
4474
}
4575

46-
resource "aws_api_gateway_deployment" "example" {
47-
depends_on = [
48-
"aws_api_gateway_integration.lambda",
49-
"aws_api_gateway_integration.lambda_root",
50-
]
76+
resource "aws_api_gateway_integration" "options_integration" {
77+
rest_api_id = "${aws_api_gateway_rest_api.lambda-api.id}"
78+
resource_id = "${aws_api_gateway_resource.proxy.id}"
79+
http_method = "${aws_api_gateway_method.options_method.http_method}"
80+
type = "MOCK"
5181

52-
rest_api_id = "${aws_api_gateway_rest_api.example.id}"
53-
stage_name = "test"
82+
# https://stackoverflow.com/questions/43990464/api-gateway-mock-integration-fails-with-500/44013347#44013347
83+
request_templates {
84+
"application/json" = <<EOF
85+
{
86+
"statusCode": 200
5487
}
88+
EOF
89+
}
90+
}
91+
92+
resource "aws_api_gateway_integration_response" "options_integration_response" {
93+
rest_api_id = "${aws_api_gateway_rest_api.lambda-api.id}"
94+
resource_id = "${aws_api_gateway_resource.proxy.id}"
95+
http_method = "${aws_api_gateway_method.options_method.http_method}"
96+
status_code = "${aws_api_gateway_method_response.options_200.status_code}"
5597

98+
response_parameters = {
99+
"method.response.header.Access-Control-Allow-Headers" = "'Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token'"
100+
"method.response.header.Access-Control-Allow-Methods" = "'DELETE,GET,HEAD,OPTIONS,PATCH,POST,PUT'"
101+
"method.response.header.Access-Control-Allow-Origin" = "'*'"
102+
}
103+
}
56104

57105
output "base_url" {
58-
value = "${aws_api_gateway_deployment.example.invoke_url}"
106+
107+
value = "${aws_api_gateway_deployment.lambda-api.invoke_url}"
108+
59109
}

infra/lambda.tf

Lines changed: 47 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,15 @@
1-
provider "aws" {
2-
region = "us-east-1"
3-
}
4-
5-
resource "aws_lambda_function" "example" {
6-
function_name = "ServerlessExample"
1+
resource "aws_lambda_function" "api" {
2+
function_name = "deckdeckgo-handler-lambda"
3+
filename = "${data.external.build-function.result.build_function_zip_path}"
4+
handler = "main.handler"
5+
runtime = "nodejs8.10"
76

8-
# The lambda function
9-
filename = "${data.external.build-function.result.build_function_zip_path}"
7+
role = "${aws_iam_role.iam_for_lambda.arn}"
108

11-
# "main" is the filename within the zip file (main.js) and "handler"
12-
# is the name of the property under which the handler function was
13-
# exported in that file.
14-
handler = "main.handler"
15-
runtime = "nodejs8.10"
16-
17-
role = "${aws_iam_role.lambda_exec.arn}"
189
}
1910

20-
# IAM role which dictates what other AWS services the Lambda function
21-
# may access.
22-
resource "aws_iam_role" "lambda_exec" {
23-
name = "serverless_example_lambda"
11+
resource "aws_iam_role" "iam_for_lambda" {
12+
name = "deckdeckgo-handler-lambda-iam"
2413

2514
assume_role_policy = <<EOF
2615
{
@@ -39,25 +28,52 @@ resource "aws_iam_role" "lambda_exec" {
3928
EOF
4029
}
4130

42-
data "external" "build-function" {
4331

32+
data "external" "build-function" {
4433
program = [
4534
"${path.module}/script/build-function"
4635
]
47-
4836
}
4937

50-
resource "aws_lambda_permission" "apigw" {
51-
statement_id = "AllowAPIGatewayInvoke"
52-
action = "lambda:InvokeFunction"
53-
function_name = "${aws_lambda_function.example.arn}"
54-
principal = "apigateway.amazonaws.com"
38+
data "aws_iam_policy_document" "policy_for_lambda" {
39+
40+
# Give access to CloudWatch
41+
statement {
42+
actions = [
43+
"logs:CreateLogStream",
44+
"logs:PutLogEvents",
45+
]
46+
47+
resources = ["${aws_cloudwatch_log_group.lambda-api.arn}"]
48+
}
49+
50+
# Give access to DynamoDB
51+
statement {
52+
actions = [
53+
"dynamodb:BatchGetItem",
54+
"dynamodb:GetItem",
55+
"dynamodb:Query",
56+
"dynamodb:Scan",
57+
"dynamodb:BatchWriteItem",
58+
"dynamodb:PutItem",
59+
"dynamodb:UpdateItem",
60+
]
61+
62+
resources = [
63+
"${aws_dynamodb_table.deckdeckgo-test-dynamodb-table.arn}",
64+
"${aws_dynamodb_table.deckdeckgo-test-dynamodb-table-slides.arn}",
65+
]
66+
}
67+
68+
}
5569

56-
# The /*/* portion grants access from any method on any resource
57-
# within the API Gateway "REST API".
58-
source_arn = "${aws_api_gateway_deployment.example.execution_arn}/*/*"
70+
resource "aws_iam_role_policy" "policy_for_lambda" {
71+
name = "deckdeckgo-handler-lambda-policy"
72+
role = "${aws_iam_role.iam_for_lambda.id}"
73+
policy = "${data.aws_iam_policy_document.policy_for_lambda.json}"
5974
}
6075

61-
output "function_zip" {
62-
value = "${data.external.build-function.result.build_function_zip_path}"
76+
resource "aws_cloudwatch_log_group" "lambda-api" {
77+
name = "/aws/lambda/${aws_lambda_function.api.function_name}"
78+
retention_in_days = "7"
6379
}

infra/main.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ let child = null;
1212
function getHaskellProcess() {
1313

1414
if (child == null) {
15+
1516
child = execFile(path.join(process.env['LAMBDA_TASK_ROOT'],'main_hs'));
1617

1718
console.log('Exec-ed child');

infra/main.tf

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
provider "aws" {
2+
region = "us-east-1"
3+
}

0 commit comments

Comments
 (0)