Skip to content

Instantly share code, notes, and snippets.

@NicholasLeader
Created September 3, 2019 15:58
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save NicholasLeader/b47a25dcb019ada85c3806f80fa8923c to your computer and use it in GitHub Desktop.
Save NicholasLeader/b47a25dcb019ada85c3806f80fa8923c to your computer and use it in GitHub Desktop.
Terraform PoC to deploy AWS Lamda Python function and API
### Nicholas Leader
### 8.21.2019
### Terraform AWS API config
###
### updates:
### 8.21.2019 fixed the wild card (removed '/' to make a valid matching rule for Lamda permission for source ARN)
resource "aws_api_gateway_rest_api" "example" {
name = "ServerlessExample"
description = "Terraform Serverless Application Example"
}
# lamda permission to the API gateway
resource "aws_lambda_permission" "apigw" {
statement_id = "AllowAPIGatewayInvoke"
action = "lambda:InvokeFunction"
function_name = "${aws_lambda_function.example.arn}"
principal = "apigateway.amazonaws.com"
# The /*/* portion grants access from any method on any resource
# within the API Gateway "REST API".
# where 'execution_arn' comes from (exported from resource declaration)
# https://www.terraform.io/docs/providers/aws/r/api_gateway_deployment.html#execution_arn
source_arn = "${aws_api_gateway_deployment.example.execution_arn}*/*"
}
### Nicholas Leader
### 8.19.2019
### Terraform main config for Lamda function with API
### see Python file for details on the actual function
### requires the API Terrform config as well.
### Terraform script expects Python file to be in S3 bucket
# Configure the AWS Provider
# credential reference https://www.terraform.io/docs/providers/aws/index.html#authentication
# API / Lamda reference https://learn.hashicorp.com/terraform/aws/lambda-api-gateway
# detail on adding URL parameter query string to API: https://www.terraform.io/docs/providers/aws/r/api_gateway_method.html
# Terraform 'resources' declaration: https://www.terraform.io/docs/configuration/resources.html
provider "aws" {
region = "us-east-1"
shared_credentials_file = "c:/users/user/.aws/credentials"
}
resource "aws_lambda_function" "example" {
function_name = "ServerlessExample_with_terraform_push"
# The bucket name as created earlier with "aws s3api create-bucket"
# houses previously uploaded Python script
s3_bucket = "lamda-api-example"
s3_key = "v1.0.0/HTTP-header-check-AWS-8-14-2019.zip"
# "main" is the filename within the zip file (main.js) and "handler"
# is the name of the property under which the handler function was
# exported in that file.
handler = "HTTP-header-check-AWS-8-14-2019.lambda_handler"
runtime = "python3.7"
role = "${aws_iam_role.lambda_exec.arn}"
}
# IAM role which dictates what other AWS services the Lambda function
# may access.
resource "aws_iam_role" "lambda_exec" {
name = "serverless_example_lambda"
assume_role_policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Action": "sts:AssumeRole",
"Principal": {
"Service": "lambda.amazonaws.com"
},
"Effect": "Allow",
"Sid": ""
}
]
}
EOF
}
resource "aws_api_gateway_resource" "proxy" {
rest_api_id = "${aws_api_gateway_rest_api.example.id}"
parent_id = "${aws_api_gateway_rest_api.example.root_resource_id}"
path_part = "{proxy+}"
}
resource "aws_api_gateway_method" "proxy" {
rest_api_id = "${aws_api_gateway_rest_api.example.id}"
resource_id = "${aws_api_gateway_resource.proxy.id}"
http_method = "ANY"
authorization = "NONE"
# adding URL parameter to API
request_parameters = { "method.request.querystring.URL" = true}
}
# route API requests to Lamda function
resource "aws_api_gateway_integration" "lambda" {
rest_api_id = "${aws_api_gateway_rest_api.example.id}"
resource_id = "${aws_api_gateway_method.proxy.resource_id}"
http_method = "${aws_api_gateway_method.proxy.http_method}"
integration_http_method = "POST"
type = "AWS_PROXY"
uri = "${aws_lambda_function.example.invoke_arn}"
}
# proxy resource cannot match an empty path at the root of the API.
# To handle that, a similar configuration must be applied to the root resource that is built in to the REST API object:
resource "aws_api_gateway_method" "proxy_root" {
rest_api_id = "${aws_api_gateway_rest_api.example.id}"
resource_id = "${aws_api_gateway_rest_api.example.root_resource_id}"
http_method = "ANY"
authorization = "NONE"
# adding URL parameter to API
request_parameters = { "method.request.querystring.URL" = true}
}
resource "aws_api_gateway_integration" "lambda_root" {
rest_api_id = "${aws_api_gateway_rest_api.example.id}"
resource_id = "${aws_api_gateway_method.proxy_root.resource_id}"
http_method = "${aws_api_gateway_method.proxy_root.http_method}"
integration_http_method = "POST"
type = "AWS_PROXY"
uri = "${aws_lambda_function.example.invoke_arn}"
}
# deploy API
# resources are the provider name + local script name in two arguments
# where 'execution_arn' comes from (exported from resource declaration)
# https://www.terraform.io/docs/providers/aws/r/api_gateway_deployment.html#execution_arn
resource "aws_api_gateway_deployment" "example" {
depends_on = [
"aws_api_gateway_integration.lambda",
"aws_api_gateway_integration.lambda_root",
]
rest_api_id = "${aws_api_gateway_rest_api.example.id}"
stage_name = "test"
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment