terraform { required_providers { aws = { source = "hashicorp/aws" version = "~> 4.0.0" } random = { source = "hashicorp/random" version = "~> 3.1.0" } archive = { source = "hashicorp/archive" version = "~> 2.2.0" } } required_version = "~> 1.0" } provider "aws" { profile = "default" region = var.aws_region } resource "aws_s3_bucket" "lambda_bucket" { bucket_prefix = var.s3_bucket_prefix force_destroy = true } resource "aws_s3_bucket_acl" "private_bucket" { bucket = aws_s3_bucket.lambda_bucket.id acl = "private" } data "archive_file" "lambda_zip" { type = "zip" source_dir = "${path.module}/src" output_path = "${path.module}/src.zip" } resource "aws_s3_object" "lambda_app" { bucket = aws_s3_bucket.lambda_bucket.id key = "source.zip" source = data.archive_file.lambda_zip.output_path etag = filemd5(data.archive_file.lambda_zip.output_path) } //Define lambda function resource "aws_lambda_function" "app" { function_name = var.lambda_name description = "apigwy-http-api serverlessland pattern" s3_bucket = aws_s3_bucket.lambda_bucket.id s3_key = aws_s3_object.lambda_app.key runtime = "python3.8" handler = "app.lambda_handler" source_code_hash = data.archive_file.lambda_zip.output_base64sha256 role = aws_iam_role.lambda_exec.arn depends_on = [aws_cloudwatch_log_group.lambda_log] } resource "aws_cloudwatch_log_group" "lambda_log" { name = "/aws/lambda/${var.lambda_name}" retention_in_days = var.lambda_log_retention } resource "aws_iam_role" "lambda_exec" { name = "serverless_lambda" assume_role_policy = jsonencode({ Version = "2012-10-17" Statement = [{ Action = "sts:AssumeRole" Effect = "Allow" Sid = "" Principal = { Service = "lambda.amazonaws.com" } } ] }) } resource "aws_iam_role_policy_attachment" "lambda_policy" { role = aws_iam_role.lambda_exec.name policy_arn = "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" } // API Gateway stuff resource "aws_apigatewayv2_api" "lambda" { name = "apigw-http-lambda" protocol_type = "HTTP" description = "Serverlessland API Gwy HTTP API and AWS Lambda function" cors_configuration { allow_credentials = false allow_headers = [] allow_methods = [ "GET", "HEAD", "OPTIONS", "POST", ] allow_origins = [ "*", ] expose_headers = [] max_age = 0 } } resource "aws_apigatewayv2_stage" "default" { api_id = aws_apigatewayv2_api.lambda.id name = "$default" auto_deploy = true access_log_settings { destination_arn = aws_cloudwatch_log_group.api_gw.arn format = jsonencode({ requestId = "$context.requestId" sourceIp = "$context.identity.sourceIp" requestTime = "$context.requestTime" protocol = "$context.protocol" httpMethod = "$context.httpMethod" resourcePath = "$context.resourcePath" routeKey = "$context.routeKey" status = "$context.status" responseLength = "$context.responseLength" integrationErrorMessage = "$context.integrationErrorMessage" } ) } depends_on = [aws_cloudwatch_log_group.api_gw] } resource "aws_apigatewayv2_integration" "app" { api_id = aws_apigatewayv2_api.lambda.id integration_uri = aws_lambda_function.app.invoke_arn integration_type = "AWS_PROXY" } resource "aws_apigatewayv2_route" "any" { api_id = aws_apigatewayv2_api.lambda.id route_key = "$default" target = "integrations/${aws_apigatewayv2_integration.app.id}" } resource "aws_cloudwatch_log_group" "api_gw" { name = "/aws/api_gw/${aws_apigatewayv2_api.lambda.name}" retention_in_days = var.apigw_log_retention } resource "aws_lambda_permission" "api_gw" { statement_id = "AllowExecutionFromAPIGateway" action = "lambda:InvokeFunction" function_name = aws_lambda_function.app.function_name principal = "apigateway.amazonaws.com" source_arn = "${aws_apigatewayv2_api.lambda.execution_arn}/*/*" }