-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
a223e4f
commit 1fc0e12
Showing
11 changed files
with
363 additions
and
9 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
module "api_gateway" { | ||
source = "../modules/api-gateway" | ||
name = "app-${local.prefix}-api-gateway" | ||
description = "API Gateway for ${local.prefix}" | ||
api_gateway_stage_name = var.api_gateway_stage_name | ||
lambda_role_arn = module.cognito.cognito_lambda_role_arn | ||
cognito_user_pool_arn = module.cognito.cognito_user_pool_arn | ||
region = local.region | ||
resource_path_part = "{proxy+}" | ||
lambda_invoke_arn = module.api_gateway.lambda_alias_arn | ||
lambda_function_arn = module.api_gateway.api_gateway_lambda_arn | ||
prefix = local.prefix | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
exports.handler = async (event) => { | ||
console.log("Received event:", JSON.stringify(event, null, 2)); | ||
|
||
return { | ||
statusCode: 200, | ||
body: JSON.stringify({ message: "Hello from API Gateway via Lambda!" }), | ||
headers: { | ||
"Content-Type": "application/json" | ||
} | ||
}; | ||
}; |
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,183 @@ | ||
data "aws_caller_identity" "current" {} | ||
|
||
resource "aws_lambda_function" "api_gateway_lambda" { | ||
function_name = "app-${var.prefix}-api-gateway-lambda" | ||
runtime = "nodejs18.x" | ||
role = var.lambda_role_arn | ||
handler = "index.handler" | ||
|
||
source_code_hash = filebase64sha256("${path.module}/api_gateway_lambda.zip") | ||
filename = "${path.module}/api_gateway_lambda.zip" | ||
timeout = 15 | ||
publish = true | ||
} | ||
|
||
resource "aws_lambda_alias" "live" { | ||
name = "live" | ||
description = "Alias pointing to the live version of the Lambda function" | ||
function_name = aws_lambda_function.api_gateway_lambda.arn | ||
function_version = "$LATEST" | ||
} | ||
|
||
resource "aws_lambda_alias" "dev" { | ||
name = "dev" | ||
description = "Alias pointing to the dev version of the Lambda function" | ||
function_name = aws_lambda_function.api_gateway_lambda.arn | ||
function_version = "$LATEST" | ||
} | ||
|
||
resource "aws_api_gateway_rest_api" "api_gateway" { | ||
name = var.name | ||
description = var.description | ||
} | ||
|
||
resource "aws_api_gateway_resource" "proxy" { | ||
rest_api_id = aws_api_gateway_rest_api.api_gateway.id | ||
parent_id = aws_api_gateway_rest_api.api_gateway.root_resource_id | ||
path_part = "{proxy+}" | ||
} | ||
|
||
resource "aws_api_gateway_method" "proxy" { | ||
rest_api_id = aws_api_gateway_rest_api.api_gateway.id | ||
resource_id = aws_api_gateway_resource.proxy.id | ||
http_method = "ANY" | ||
authorization = "COGNITO_USER_POOLS" | ||
authorizer_id = aws_api_gateway_authorizer.cognito.id | ||
} | ||
|
||
resource "aws_api_gateway_authorizer" "cognito" { | ||
name = "app-${var.prefix}-cognito-authorizer" | ||
rest_api_id = aws_api_gateway_rest_api.api_gateway.id | ||
type = "COGNITO_USER_POOLS" | ||
provider_arns = [var.cognito_user_pool_arn] | ||
} | ||
|
||
resource "aws_api_gateway_integration" "proxy_integration" { | ||
rest_api_id = aws_api_gateway_rest_api.api_gateway.id | ||
resource_id = aws_api_gateway_resource.proxy.id | ||
http_method = aws_api_gateway_method.proxy.http_method | ||
integration_http_method = "POST" | ||
type = "AWS_PROXY" | ||
uri = "arn:aws:apigateway:${var.region}:lambda:path/2015-03-31/functions/${lookup({ | ||
"live" = aws_lambda_alias.live.arn, | ||
"dev" = aws_lambda_alias.dev.arn | ||
}, var.lambda_alias, aws_lambda_alias.live.arn)}/invocations" | ||
} | ||
|
||
resource "aws_api_gateway_deployment" "deployment" { | ||
depends_on = [ | ||
aws_api_gateway_method.proxy, | ||
aws_api_gateway_integration.proxy_integration | ||
] | ||
rest_api_id = aws_api_gateway_rest_api.api_gateway.id | ||
|
||
triggers = { | ||
redeployment = timestamp() | ||
} | ||
|
||
lifecycle { | ||
create_before_destroy = true | ||
} | ||
} | ||
|
||
resource "aws_api_gateway_stage" "stage" { | ||
stage_name = var.api_gateway_stage_name | ||
rest_api_id = aws_api_gateway_rest_api.api_gateway.id | ||
deployment_id = aws_api_gateway_deployment.deployment.id | ||
|
||
description = "Stage for ${var.api_gateway_stage_name}" | ||
variables = { | ||
lambda_alias = var.lambda_alias | ||
} | ||
|
||
lifecycle { | ||
prevent_destroy = false | ||
} | ||
} | ||
|
||
resource "aws_api_gateway_account" "account" { | ||
cloudwatch_role_arn = aws_iam_role.api_gateway_cloudwatch_role.arn | ||
|
||
depends_on = [ | ||
aws_iam_role.api_gateway_cloudwatch_role, | ||
aws_iam_role_policy.api_gateway_cloudwatch_policy | ||
] | ||
} | ||
|
||
resource "aws_iam_role" "api_gateway_cloudwatch_role" { | ||
name = "app-${var.prefix}-api-gateway-cloudwatch-role" | ||
|
||
assume_role_policy = jsonencode({ | ||
Version = "2012-10-17", | ||
Statement = [ | ||
{ | ||
Effect = "Allow", | ||
Principal = { | ||
Service = "apigateway.amazonaws.com" | ||
}, | ||
Action = "sts:AssumeRole" | ||
} | ||
] | ||
}) | ||
} | ||
|
||
resource "aws_iam_role_policy" "api_gateway_cloudwatch_policy" { | ||
role = aws_iam_role.api_gateway_cloudwatch_role.id | ||
|
||
policy = jsonencode({ | ||
Version = "2012-10-17", | ||
Statement = [ | ||
{ | ||
Effect = "Allow", | ||
Action = [ | ||
"logs:CreateLogGroup", | ||
"logs:CreateLogStream", | ||
"logs:PutLogEvents", | ||
"logs:DescribeLogGroups", | ||
"logs:DescribeLogStreams", | ||
"logs:GetLogEvents", | ||
"logs:FilterLogEvents" | ||
], | ||
Resource = [ | ||
"arn:aws:logs:${var.region}:${data.aws_caller_identity.current.account_id}:log-group:/aws/apigateway/*" | ||
] | ||
}, | ||
{ | ||
Effect = "Allow", | ||
Action = [ | ||
"apigateway:GET", | ||
"apigateway:PUT", | ||
"apigateway:POST", | ||
"apigateway:DELETE", | ||
"apigateway:PATCH" | ||
], | ||
Resource = aws_api_gateway_rest_api.api_gateway.execution_arn | ||
} | ||
] | ||
}) | ||
} | ||
|
||
resource "aws_lambda_permission" "allow_api_gateway" { | ||
statement_id = "AllowAPIGatewayInvoke" | ||
action = "lambda:InvokeFunction" | ||
function_name = lookup({ | ||
"live" = aws_lambda_alias.live.arn, | ||
"dev" = aws_lambda_alias.dev.arn | ||
}, var.lambda_alias, aws_lambda_alias.live.arn) | ||
principal = "apigateway.amazonaws.com" | ||
source_arn = "arn:aws:execute-api:${var.region}:${data.aws_caller_identity.current.account_id}:${aws_api_gateway_rest_api.api_gateway.id}/*/*/*" | ||
} | ||
|
||
output "api_gateway_lambda_arn" { | ||
description = "The ARN of the API Gateway Lambda function" | ||
value = aws_lambda_function.api_gateway_lambda.arn | ||
} | ||
|
||
variable "prefix" { | ||
description = "Prefix for naming resources" | ||
type = string | ||
validation { | ||
condition = can(regex("^[a-zA-Z0-9_-]+$", var.prefix)) | ||
error_message = "Prefix must only contain letters, numbers, hyphens, or underscores." | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
output "api_gateway_id" { | ||
description = "The ID of the API Gateway" | ||
value = aws_api_gateway_rest_api.api_gateway.id | ||
} | ||
|
||
output "api_gateway_url" { | ||
description = "The invoke URL of the API Gateway" | ||
value = aws_api_gateway_deployment.deployment.invoke_url | ||
} | ||
|
||
output "api_gateway_stage_name" { | ||
description = "The stage name of the API Gateway deployment" | ||
value = aws_api_gateway_stage.stage.stage_name | ||
} | ||
|
||
output "api_gateway_lambda_invoke_arn" { | ||
description = "The invoke ARN for the API Gateway Lambda function alias" | ||
value = var.lambda_alias == "live" ? aws_lambda_alias.live.arn : aws_lambda_alias.dev.arn | ||
} | ||
|
||
output "lambda_alias_arn" { | ||
description = "The ARN of the selected Lambda alias" | ||
value = lookup({ | ||
"live" = aws_lambda_alias.live.arn, | ||
"dev" = aws_lambda_alias.dev.arn | ||
}, var.lambda_alias, aws_lambda_alias.live.arn) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,103 @@ | ||
variable "name" { | ||
description = "The name of the API Gateway" | ||
type = string | ||
|
||
validation { | ||
condition = length(var.name) > 0 | ||
error_message = "The 'name' variable must be a non-empty string." | ||
} | ||
} | ||
|
||
variable "description" { | ||
description = "The description of the API Gateway" | ||
type = string | ||
default = "API Gateway for the application" | ||
|
||
validation { | ||
condition = length(var.description) > 0 | ||
error_message = "The 'description' variable must be a non-empty string." | ||
} | ||
} | ||
|
||
variable "api_gateway_stage_name" { | ||
description = "The stage name for API Gateway (e.g. dev or live)" | ||
type = string | ||
default = "dev" | ||
|
||
validation { | ||
condition = can(regex("^[a-zA-Z0-9_-]+$", var.api_gateway_stage_name)) | ||
error_message = "The 'stage_name' variable must only contain alphanumeric characters, dashes, or underscores." | ||
} | ||
} | ||
|
||
variable "lambda_function_arn" { | ||
description = "The ARN of the Lambda function to integrate with API Gateway" | ||
type = string | ||
|
||
validation { | ||
condition = can(regex("^arn:aws:lambda:.*:.*:function:.*$", var.lambda_function_arn)) | ||
error_message = "The 'lambda_function_arn' must be a valid Lambda function ARN." | ||
} | ||
} | ||
|
||
variable "cognito_user_pool_arn" { | ||
description = "The ARN of the Cognito User Pool for authorizing requests" | ||
type = string | ||
|
||
validation { | ||
condition = can(regex("^arn:aws:cognito-idp:.*:.*:userpool/.*$", var.cognito_user_pool_arn)) | ||
error_message = "The 'cognito_user_pool_arn' must be a valid Cognito User Pool ARN." | ||
} | ||
} | ||
|
||
variable "region" { | ||
description = "The AWS region for resources" | ||
type = string | ||
|
||
validation { | ||
condition = can(regex("^[a-z]{2}-[a-z]+-[0-9]{1}$", var.region)) | ||
error_message = "The 'region' variable must be a valid AWS region string, e.g. 'eu-west-2'." | ||
} | ||
} | ||
|
||
variable "resource_path_part" { | ||
description = "The resource path part for API Gateway (e.g. 'data' or '{proxy+}')" | ||
type = string | ||
default = "{proxy+}" | ||
|
||
validation { | ||
condition = can(regex("^[a-zA-Z0-9/{}+_-]+$", var.resource_path_part)) | ||
error_message = "The 'resource_path_part' must be a valid path segment containing alphanumeric characters, slashes, curly braces, dashes, or underscores." | ||
} | ||
} | ||
|
||
variable "lambda_invoke_arn" { | ||
description = "The ARN of the Lambda function for API Gateway" | ||
type = string | ||
|
||
validation { | ||
condition = can(regex("^arn:aws:lambda:.*:.*:function:.*$", var.lambda_invoke_arn)) | ||
error_message = "The 'lambda_invoke_arn' must be a valid Lambda function ARN." | ||
} | ||
} | ||
|
||
variable "lambda_role_arn" { | ||
description = "IAM Role ARN for the Lambda function" | ||
type = string | ||
|
||
validation { | ||
condition = can(regex("^arn:aws:iam::\\d{12}:role/.+$", var.lambda_role_arn)) | ||
error_message = "The 'lambda_role_arn' must be a valid IAM Role ARN." | ||
} | ||
} | ||
|
||
variable "lambda_alias" { | ||
description = "The alias for the Lambda function (e.g. live, dev)" | ||
type = string | ||
default = "live" | ||
|
||
validation { | ||
condition = contains(["dev", "live"], var.lambda_alias) | ||
error_message = "Invalid alias provided. Allowed values are 'dev' or 'live'." | ||
} | ||
} |
Oops, something went wrong.