initial commit
This commit is contained in:
@@ -0,0 +1,77 @@
|
||||
<!-- This readme file is generated with terraform-docs -->
|
||||
## Requirements
|
||||
|
||||
| Name | Version |
|
||||
|------|---------|
|
||||
| terraform | >= 1.3.0 |
|
||||
| aws | >= 5.0 |
|
||||
|
||||
## Providers
|
||||
|
||||
| Name | Version |
|
||||
|------|---------|
|
||||
| aws | >= 5.0 |
|
||||
| random | n/a |
|
||||
|
||||
## Modules
|
||||
|
||||
No modules.
|
||||
|
||||
## Resources
|
||||
|
||||
| Name | Type |
|
||||
|------|------|
|
||||
| [aws_api_gateway_deployment.apigw-deployment](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/api_gateway_deployment) | resource |
|
||||
| [aws_api_gateway_integration.api-integration](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/api_gateway_integration) | resource |
|
||||
| [aws_api_gateway_integration_response.integration-response](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/api_gateway_integration_response) | resource |
|
||||
| [aws_api_gateway_method.api-method](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/api_gateway_method) | resource |
|
||||
| [aws_api_gateway_method_response.response_200](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/api_gateway_method_response) | resource |
|
||||
| [aws_api_gateway_method_settings.apigw-method-settings](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/api_gateway_method_settings) | resource |
|
||||
| [aws_api_gateway_resource.api-res](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/api_gateway_resource) | resource |
|
||||
| [aws_api_gateway_rest_api.api](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/api_gateway_rest_api) | resource |
|
||||
| [aws_api_gateway_rest_api_policy.api-policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/api_gateway_rest_api_policy) | resource |
|
||||
| [aws_api_gateway_stage.apigw-stage](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/api_gateway_stage) | resource |
|
||||
| [aws_api_gateway_vpc_link.api-vpc-link](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/api_gateway_vpc_link) | resource |
|
||||
| [aws_cloudwatch_log_group.lambda-logs](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudwatch_log_group) | resource |
|
||||
| [aws_cloudwatch_log_group.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudwatch_log_group) | resource |
|
||||
| [aws_iam_role.lambda-exec-role](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource |
|
||||
| [aws_iam_role_policy.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy) | resource |
|
||||
| [aws_lambda_function.function](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/lambda_function) | resource |
|
||||
| [aws_lambda_permission.allow_api_gateway](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/lambda_permission) | resource |
|
||||
| [aws_vpc_endpoint.apigw-vpcep](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/vpc_endpoint) | resource |
|
||||
| [random_id.this](https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/id) | resource |
|
||||
| [aws_caller_identity.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/caller_identity) | data source |
|
||||
| [aws_iam_policy_document.api-policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source |
|
||||
| [aws_region.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/region) | data source |
|
||||
| [aws_vpc.vpc](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/vpc) | data source |
|
||||
|
||||
## Inputs
|
||||
|
||||
| Name | Description | Type | Default | Required |
|
||||
|------|-------------|------|---------|:--------:|
|
||||
| apigw-security-group-id | Security group id of apigateway | `string` | n/a | yes |
|
||||
| apigw-subnet-ids | Subnet IDs of apigateway | `list(string)` | n/a | yes |
|
||||
| apigw-type | Type of apigateway: private or regional | `string` | n/a | yes |
|
||||
| apigw-vpc-id | VPC id of apigateway | `string` | n/a | yes |
|
||||
| apigw-vpc-link-target-arns | Target arns for apigateway VPC link | `list(string)` | `[]` | no |
|
||||
| cloudwatchlog-retention | Cloudwatch log group retention days | `number` | `14` | no |
|
||||
| create-vpc-link | Set true to create vpc link for outbound access to specific targets | `bool` | n/a | yes |
|
||||
| cwl-cmk-key-id | CMK arn for cloudwatch logs encryption | `string` | `null` | no |
|
||||
| description | Description of apigateway | `string` | n/a | yes |
|
||||
| lambda-archive-file | Path to lambda zip archive | `string` | n/a | yes |
|
||||
| lambda-main-function-name | Main python file without the .py extension | `string` | n/a | yes |
|
||||
| lambda-runtime-version | Lambda runtime version | `string` | `"python3.12"` | no |
|
||||
| name | Name of apigateway | `string` | n/a | yes |
|
||||
| resources | Apigateway resources (path\_part) | <pre>map(object({<br> method = string<br> authorization = string<br> integration_type = string<br> content_handling = string<br> }))</pre> | n/a | yes |
|
||||
| stages | apigateway stages | <pre>map(object({<br> description = string<br> variables = map(string)<br> }))</pre> | n/a | yes |
|
||||
|
||||
## Outputs
|
||||
|
||||
| Name | Description |
|
||||
|------|-------------|
|
||||
| apigw-id | n/a |
|
||||
| apigw-vpc-endpoints | n/a |
|
||||
|
||||
---
|
||||
## Authorship
|
||||
This module was developed by UPDATE_THIS.
|
||||
@@ -0,0 +1,256 @@
|
||||
resource "aws_api_gateway_rest_api" "api" {
|
||||
name = var.name
|
||||
description = var.description
|
||||
|
||||
dynamic "endpoint_configuration" {
|
||||
for_each = [1]
|
||||
content {
|
||||
types = var.apigw-type == "private" ? ["PRIVATE"] : ["REGIONAL"]
|
||||
vpc_endpoint_ids = var.apigw-type == "private" ? [aws_vpc_endpoint.apigw-vpcep[0].id] : null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# private endpoint for inbound access
|
||||
# to connect to the private api gateway, provide the header x-apigw-api-id
|
||||
# curl -IX GET -H 'x-apigw-api-id:<YOUR_API_ID>' https://<YOUR_VPCE_HOSTNAME>/<STAGE>
|
||||
data "aws_region" "current" {}
|
||||
|
||||
resource "aws_vpc_endpoint" "apigw-vpcep" {
|
||||
count = var.apigw-type == "private" ? 1 : 0
|
||||
private_dns_enabled = false
|
||||
security_group_ids = [var.apigw-security-group-id]
|
||||
service_name = "com.amazonaws.${data.aws_region.current.name}.execute-api"
|
||||
subnet_ids = var.apigw-subnet-ids
|
||||
vpc_endpoint_type = "Interface"
|
||||
vpc_id = var.apigw-vpc-id
|
||||
}
|
||||
|
||||
# vpc link for outbound access
|
||||
resource "aws_api_gateway_vpc_link" "api-vpc-link" {
|
||||
count = var.create-vpc-link ? 1 : 0
|
||||
name = "${var.name}-vpclink"
|
||||
description = "VPC link for apigateway ${var.name}"
|
||||
target_arns = var.apigw-vpc-link-target-arns
|
||||
}
|
||||
|
||||
# Apigw resources, integration, method, responses
|
||||
resource "aws_api_gateway_resource" "api-res" {
|
||||
depends_on = [aws_api_gateway_rest_api_policy.api-policy]
|
||||
for_each = var.resources
|
||||
path_part = each.key
|
||||
parent_id = aws_api_gateway_rest_api.api.root_resource_id
|
||||
rest_api_id = aws_api_gateway_rest_api.api.id
|
||||
}
|
||||
|
||||
resource "aws_api_gateway_method" "api-method" {
|
||||
depends_on = [aws_api_gateway_resource.api-res]
|
||||
for_each = var.resources
|
||||
rest_api_id = aws_api_gateway_rest_api.api.id
|
||||
resource_id = aws_api_gateway_resource.api-res[each.key].id
|
||||
http_method = each.value["method"]
|
||||
authorization = each.value["authorization"]
|
||||
}
|
||||
|
||||
# non-proxy integration
|
||||
resource "aws_api_gateway_integration" "api-integration" {
|
||||
depends_on = [aws_api_gateway_method.api-method]
|
||||
for_each = var.resources
|
||||
rest_api_id = aws_api_gateway_rest_api.api.id
|
||||
resource_id = aws_api_gateway_resource.api-res[each.key].id
|
||||
http_method = aws_api_gateway_method.api-method[each.key].http_method
|
||||
integration_http_method = each.value["method"]
|
||||
type = each.value["integration-type"]
|
||||
content_handling = each.value["content-handling"]
|
||||
uri = aws_lambda_function.function.invoke_arn
|
||||
}
|
||||
|
||||
resource "aws_api_gateway_method_response" "response_200" {
|
||||
depends_on = [aws_api_gateway_method.api-method]
|
||||
for_each = var.resources
|
||||
rest_api_id = aws_api_gateway_rest_api.api.id
|
||||
resource_id = aws_api_gateway_resource.api-res[each.key].id
|
||||
http_method = aws_api_gateway_method.api-method[each.key].http_method
|
||||
status_code = "200"
|
||||
}
|
||||
|
||||
resource "aws_api_gateway_integration_response" "integration-response" {
|
||||
depends_on = [aws_api_gateway_integration.api-integration]
|
||||
for_each = var.resources
|
||||
rest_api_id = aws_api_gateway_rest_api.api.id
|
||||
resource_id = aws_api_gateway_resource.api-res[each.key].id
|
||||
http_method = aws_api_gateway_method.api-method[each.key].http_method
|
||||
status_code = aws_api_gateway_method_response.response_200[each.key].status_code
|
||||
}
|
||||
|
||||
# apigw deployment and stage
|
||||
resource "aws_api_gateway_deployment" "apigw-deployment" {
|
||||
depends_on = [aws_api_gateway_integration.api-integration]
|
||||
rest_api_id = aws_api_gateway_rest_api.api.id
|
||||
|
||||
triggers = {
|
||||
redeployment = sha1(jsonencode(aws_api_gateway_rest_api.api.body))
|
||||
}
|
||||
|
||||
lifecycle {
|
||||
create_before_destroy = true
|
||||
}
|
||||
}
|
||||
|
||||
resource "aws_api_gateway_stage" "apigw-stage" {
|
||||
for_each = var.stages
|
||||
depends_on = [aws_api_gateway_rest_api_policy.api-policy, aws_cloudwatch_log_group.this]
|
||||
deployment_id = aws_api_gateway_deployment.apigw-deployment.id
|
||||
rest_api_id = aws_api_gateway_rest_api.api.id
|
||||
stage_name = each.key
|
||||
description = each.value["description"]
|
||||
variables = each.value["variables"]
|
||||
|
||||
access_log_settings {
|
||||
destination_arn = aws_cloudwatch_log_group.this[each.key].arn
|
||||
# https://docs.aws.amazon.com/apigateway/latest/developerguide/set-up-logging.html
|
||||
format = jsonencode({
|
||||
"requestId" : "$context.requestId",
|
||||
"extendedRequestId" : "$context.extendedRequestId",
|
||||
"ip" : "$context.identity.sourceIp",
|
||||
"caller" : "$context.identity.caller",
|
||||
"user" : "$context.identity.user",
|
||||
"requestTime" : "$context.requestTime",
|
||||
"httpMethod" : "$context.httpMethod",
|
||||
"resourcePath" : "$context.resourcePath",
|
||||
"status" : "$context.status",
|
||||
"protocol" : "$context.protocol",
|
||||
"responseLength" : "$context.responseLength"
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
resource "aws_api_gateway_method_settings" "apigw-method-settings" {
|
||||
depends_on = [aws_api_gateway_rest_api_policy.api-policy]
|
||||
for_each = aws_api_gateway_stage.apigw-stage
|
||||
rest_api_id = aws_api_gateway_rest_api.api.id
|
||||
stage_name = each.value.stage_name
|
||||
method_path = "*/*"
|
||||
|
||||
settings {
|
||||
metrics_enabled = true
|
||||
logging_level = "INFO"
|
||||
}
|
||||
}
|
||||
|
||||
# Cloudwatch log group path: API-Gateway-Execution-Logs_{rest-api-id}/{stage_name}
|
||||
resource "aws_cloudwatch_log_group" "this" {
|
||||
for_each = var.stages
|
||||
name = "API-Gateway-Execution-Logs_${aws_api_gateway_rest_api.api.id}/${each.key}"
|
||||
retention_in_days = var.cloudwatchlog-retention
|
||||
kms_key_id = var.cwl-cmk-key-id
|
||||
}
|
||||
|
||||
# lambda function
|
||||
resource "aws_cloudwatch_log_group" "lambda-logs" {
|
||||
name = "/aws/lambda/${var.name}-lambda-function"
|
||||
retention_in_days = var.cloudwatchlog-retention
|
||||
kms_key_id = var.cwl-cmk-key-id
|
||||
}
|
||||
|
||||
resource "aws_lambda_function" "function" {
|
||||
filename = var.lambda-archive-file
|
||||
function_name = "${var.name}-lambda-function"
|
||||
handler = "main.lambda_handler"
|
||||
role = aws_iam_role.lambda-exec-role.arn
|
||||
runtime = var.lambda-runtime-version
|
||||
# source_code_hash = local.source_code_hash
|
||||
}
|
||||
|
||||
resource "aws_lambda_permission" "allow_api_gateway" {
|
||||
action = "lambda:InvokeFunction"
|
||||
function_name = aws_lambda_function.function.function_name
|
||||
principal = "apigateway.amazonaws.com"
|
||||
}
|
||||
|
||||
# Lambda execution role
|
||||
data "aws_caller_identity" "this" {}
|
||||
|
||||
resource "random_id" "this" {
|
||||
byte_length = 4
|
||||
}
|
||||
|
||||
resource "aws_iam_role" "lambda-exec-role" {
|
||||
name = "lambda-apigw-${var.name}-${random_id.this.dec}"
|
||||
|
||||
assume_role_policy = jsonencode(
|
||||
{
|
||||
"Version" : "2012-10-17",
|
||||
"Statement" : [
|
||||
{
|
||||
"Effect" : "Allow",
|
||||
"Principal" : {
|
||||
"Service" : "lambda.amazonaws.com"
|
||||
},
|
||||
"Action" : "sts:AssumeRole"
|
||||
}
|
||||
]
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
resource "aws_iam_role_policy" "this" {
|
||||
policy = jsonencode(
|
||||
{
|
||||
"Version" : "2012-10-17",
|
||||
"Statement" : [
|
||||
{
|
||||
"Sid" : "AllowCreationOfCloudwatchLogGroup",
|
||||
"Effect" : "Allow",
|
||||
"Action" : "logs:CreateLogGroup",
|
||||
"Resource" : "arn:aws:logs:ap-east-1:${data.aws_caller_identity.this.account_id}:*"
|
||||
},
|
||||
{
|
||||
"Sid" : "AllowWritingToCloudwatchLogGroup",
|
||||
"Effect" : "Allow",
|
||||
"Action" : [
|
||||
"logs:CreateLogStream",
|
||||
"logs:PutLogEvents"
|
||||
],
|
||||
"Resource" : [
|
||||
"arn:aws:logs:ap-east-1:${data.aws_caller_identity.this.account_id}:log-group:/aws/lambda/*"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
)
|
||||
role = aws_iam_role.lambda-exec-role.id
|
||||
name = "LambdaExecutionPolicy"
|
||||
}
|
||||
|
||||
# apigateway policy
|
||||
data "aws_iam_policy_document" "api-policy" {
|
||||
statement {
|
||||
effect = "Allow"
|
||||
|
||||
principals {
|
||||
type = "AWS"
|
||||
identifiers = ["*"]
|
||||
}
|
||||
|
||||
actions = ["execute-api:Invoke"]
|
||||
resources = [aws_api_gateway_rest_api.api.execution_arn]
|
||||
|
||||
condition {
|
||||
test = "IpAddress"
|
||||
variable = "aws:SourceIp"
|
||||
values = [data.aws_vpc.vpc.cidr_block]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
data "aws_vpc" "vpc" {
|
||||
id = var.apigw-vpc-id
|
||||
}
|
||||
resource "aws_api_gateway_rest_api_policy" "api-policy" {
|
||||
rest_api_id = aws_api_gateway_rest_api.api.id
|
||||
policy = data.aws_iam_policy_document.api-policy.json
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
output "apigw-id" {
|
||||
value = aws_api_gateway_rest_api.api.id
|
||||
}
|
||||
|
||||
output "apigw-vpc-endpoints" {
|
||||
value = try(aws_vpc_endpoint.apigw-vpcep.*.dns_entry[0].*.dns_name, null)
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
variable "name" {
|
||||
type = string
|
||||
description = "Name of apigateway"
|
||||
}
|
||||
|
||||
variable "description" {
|
||||
type = string
|
||||
description = "Description of apigateway"
|
||||
}
|
||||
|
||||
variable "apigw-type" {
|
||||
type = string
|
||||
description = "Type of apigateway: private or regional"
|
||||
validation {
|
||||
condition = can(regex("^(private|regional)$", var.apigw-type))
|
||||
error_message = "Invalid apigw type, only allowed types are: 'private', 'regional'"
|
||||
}
|
||||
}
|
||||
|
||||
variable "resources" {
|
||||
type = map(object({
|
||||
method = string
|
||||
authorization = string
|
||||
integration_type = string
|
||||
content_handling = string
|
||||
}))
|
||||
description = "Apigateway resources (path_part)"
|
||||
}
|
||||
|
||||
variable "stages" {
|
||||
type = map(object({
|
||||
description = string
|
||||
variables = map(string)
|
||||
}))
|
||||
description = "apigateway stages"
|
||||
}
|
||||
|
||||
variable "lambda-archive-file" {
|
||||
type = string
|
||||
description = "Path to lambda zip archive"
|
||||
}
|
||||
|
||||
variable "lambda-runtime-version" {
|
||||
type = string
|
||||
description = "Lambda runtime version"
|
||||
default = "python3.12"
|
||||
}
|
||||
|
||||
variable "lambda-main-function-name" {
|
||||
type = string
|
||||
description = "Main python file without the .py extension"
|
||||
}
|
||||
|
||||
variable "apigw-vpc-id" {
|
||||
type = string
|
||||
description = "VPC id of apigateway"
|
||||
}
|
||||
|
||||
variable "apigw-subnet-ids" {
|
||||
type = list(string)
|
||||
description = "Subnet IDs of apigateway"
|
||||
}
|
||||
|
||||
variable "apigw-security-group-id" {
|
||||
type = string
|
||||
description = "Security group id of apigateway"
|
||||
}
|
||||
|
||||
variable "create-vpc-link" {
|
||||
type = bool
|
||||
description = "Set true to create vpc link for outbound access to specific targets"
|
||||
}
|
||||
|
||||
variable "apigw-vpc-link-target-arns" {
|
||||
type = list(string)
|
||||
description = "Target arns for apigateway VPC link"
|
||||
default = []
|
||||
}
|
||||
|
||||
variable "cloudwatchlog-retention" {
|
||||
type = number
|
||||
description = "Cloudwatch log group retention days"
|
||||
default = 14
|
||||
}
|
||||
|
||||
variable "cwl-cmk-key-id" {
|
||||
type = string
|
||||
description = "CMK arn for cloudwatch logs encryption"
|
||||
default = null
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
terraform {
|
||||
required_version = ">= 1.3.0"
|
||||
required_providers {
|
||||
aws = {
|
||||
source = "hashicorp/aws"
|
||||
version = ">= 5.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user