diff --git a/.github/workflows/tf-checks.yml b/.github/workflows/tf-checks.yml index 561d5c6..b8e595f 100644 --- a/.github/workflows/tf-checks.yml +++ b/.github/workflows/tf-checks.yml @@ -9,7 +9,7 @@ jobs: tf-checks-complete-example: uses: clouddrove/github-shared-workflows/.github/workflows/tf-checks.yml@master with: - working_directory: './examples/complete/' + working_directory: './examples/' tf-checks-basic-example: uses: clouddrove/github-shared-workflows/.github/workflows/tf-checks.yml@master with: diff --git a/examples/http-api-gateway/example.tf b/examples/http-api-gateway/example.tf new file mode 100644 index 0000000..6a7f3d8 --- /dev/null +++ b/examples/http-api-gateway/example.tf @@ -0,0 +1,112 @@ +####---------------------------------------------------------------------------------- +## PROVIDER +####---------------------------------------------------------------------------------- +provider "aws" { + region = local.region +} + +####---------------------------------------------------------------------------------- +## LOCALS +####---------------------------------------------------------------------------------- + +locals { + name = "api" + environment = "test" + region = "us-east-1" + domain_name = "clouddrove.ca" + hosted_zone_id = "Z0xxxxxxxxxxxxxxEP" +} +####---------------------------------------------------------------------------------- +## ACM +####---------------------------------------------------------------------------------- +module "acm" { + source = "clouddrove/acm/aws" + version = "1.4.1" + + name = local.name + environment = local.environment + enable_aws_certificate = true + domain_name = local.domain_name + subject_alternative_names = ["*.${local.domain_name}"] + validation_method = "DNS" + enable_dns_validation = false +} + +####---------------------------------------------------------------------------------- +## LAMBDA +####---------------------------------------------------------------------------------- +module "lambda" { + source = "clouddrove/lambda/aws" + version = "1.3.1" + + name = local.name + environment = local.environment + enable = true + timeout = 60 + filename = "../lambda_packages/index.zip" + handler = "index.lambda_handler" + runtime = "python3.8" + iam_actions = [ + "logs:CreateLogStream", + "logs:CreateLogGroup", + "logs:PutLogEvents" + ] + names = [ + "python_layer" + ] + compatible_runtimes = [ + ["python3.8"] + ] + statement_ids = [ + "AllowExecutionFromApiGateway" + ] + actions = [ + "lambda:InvokeFunction" + ] + principals = [ + "apigateway.amazonaws.com" + ] + variables = { + foo = "bar" + } +} + +####---------------------------------------------------------------------------------- +## API GATEWAY +####---------------------------------------------------------------------------------- +module "api_gateway" { + source = "../../." + + name = local.name + environment = local.environment + domain_name = "api.${local.domain_name}" + domain_name_certificate_arn = module.acm.arn + integration_uri = module.lambda.invoke_arn + zone_id = local.hosted_zone_id + auto_deploy = true + stage_name = "$default" + create_vpc_link_enabled = false + create_http_api = true + cors_configuration = { + allow_credentials = true + allow_methods = ["GET", "OPTIONS", "POST"] + max_age = 5 + } + integrations = { + "ANY /" = { + lambda_arn = module.lambda.arn + payload_format_version = "2.0" + timeout_milliseconds = 30000 + } + "GET /some-route-with-authorizer" = { + lambda_arn = module.lambda.arn + payload_format_version = "1.0" + authorizer_key = "cognito" + } + "POST /start-step-function" = { + lambda_arn = module.lambda.arn + payload_format_version = "1.0" + authorizer_key = "cognito" + } + } +} \ No newline at end of file diff --git a/examples/http-api-gateway/outputs.tf b/examples/http-api-gateway/outputs.tf new file mode 100644 index 0000000..7025048 --- /dev/null +++ b/examples/http-api-gateway/outputs.tf @@ -0,0 +1,19 @@ +output "api_id" { + value = module.api_gateway.api_id + description = "The API identifier." +} + +output "api_arn" { + value = module.api_gateway.api_arn + description = "The API arn." +} + +output "api_endpoint" { + value = module.api_gateway.api_endpoint + description = "The URI of the API, of the form {api-id}.execute-api.{region}.amazonaws.com." +} + +output "invoke_url" { + value = module.api_gateway.invoke_url + description = "URL to invoke the API pointing to the stage" +} diff --git a/examples/http-api-gateway/version.tf b/examples/http-api-gateway/version.tf new file mode 100644 index 0000000..3f60246 --- /dev/null +++ b/examples/http-api-gateway/version.tf @@ -0,0 +1,11 @@ +# Terraform version +terraform { + required_version = ">= 1.6.1" + + required_providers { + aws = { + source = "hashicorp/aws" + version = ">= 5.20.0" + } + } +} \ No newline at end of file diff --git a/examples/lambda_packages/index.py b/examples/lambda_packages/index.py new file mode 100644 index 0000000..a0f3277 --- /dev/null +++ b/examples/lambda_packages/index.py @@ -0,0 +1,7 @@ +import json +def lambda_handler(event, context): + print('Lambda function with Python!|') + return { + 'statusCode': 200, + 'body': json.dumps('Hello from Lambda!') + } diff --git a/examples/lambda_packages/index.zip b/examples/lambda_packages/index.zip new file mode 100644 index 0000000..f7f278d Binary files /dev/null and b/examples/lambda_packages/index.zip differ diff --git a/examples/private-rest-api-gateway/example.tf b/examples/private-rest-api-gateway/example.tf new file mode 100644 index 0000000..1eb70b9 --- /dev/null +++ b/examples/private-rest-api-gateway/example.tf @@ -0,0 +1,225 @@ +####---------------------------------------------------------------------------------- +## PROVIDER +####---------------------------------------------------------------------------------- + +provider "aws" { + region = local.region +} +####---------------------------------------------------------------------------------- +## LOCALS +####---------------------------------------------------------------------------------- + +locals { + name = "api" + environment = "test" + region = "us-east-1" + domain_name = "clouddrove.ca" + hosted_zone_id = "Z015XXXXXXXXXXXXXXIEP" +} +####---------------------------------------------------------------------------------- +## ACM +####---------------------------------------------------------------------------------- + +module "acm" { + source = "clouddrove/acm/aws" + version = "1.4.1" + + name = local.name + environment = local.environment + enable_aws_certificate = true + domain_name = local.domain_name + subject_alternative_names = ["*.${local.domain_name}"] + validation_method = "DNS" + enable_dns_validation = false +} + +####---------------------------------------------------------------------------------- +## LAMBDA +####---------------------------------------------------------------------------------- + +module "lambda" { + source = "clouddrove/lambda/aws" + version = "1.3.1" + + name = local.name + environment = local.environment + enable = true + timeout = 60 + filename = "../lambda_packages/index.zip" + handler = "index.lambda_handler" + runtime = "python3.8" + iam_actions = [ + "logs:CreateLogStream", + "logs:CreateLogGroup", + "logs:PutLogEvents" + ] + names = [ + "python_layer" + ] + compatible_runtimes = [ + ["python3.8"] + ] + statement_ids = [ + "AllowExecutionFromApiGateway" + ] + actions = [ + "lambda:InvokeFunction" + ] + principals = [ + "apigateway.amazonaws.com" + ] + variables = { + foo = "bar" + } +} + + +####---------------------------------------------------------------------------------- +## VPC +####---------------------------------------------------------------------------------- + +module "vpc" { + source = "clouddrove/vpc/aws" + version = "2.0.0" + + name = "${local.name}-rest-api-private" + environment = local.environment + enable = true + cidr_block = "10.0.0.0/16" + +} + +####---------------------------------------------------------------------------------- +## SUBNETS +####---------------------------------------------------------------------------------- +#tfsec:ignore:aws-ec2-no-excessive-port-access +#tfsec:ignore:aws-ec2-no-public-ingress-acl +module "subnets" { + source = "clouddrove/subnet/aws" + version = "2.0.1" + + name = "${local.name}-rest-api-private" + environment = local.environment + + nat_gateway_enabled = true + single_nat_gateway = true + availability_zones = ["${local.region}a", "${local.region}b", "${local.region}c"] + vpc_id = module.vpc.vpc_id + type = "public-private" + igw_id = module.vpc.igw_id + cidr_block = module.vpc.vpc_cidr_block + ipv6_cidr_block = module.vpc.ipv6_cidr_block + enable_ipv6 = true + private_inbound_acl_rules = [ + { + rule_number = 100 + rule_action = "allow" + from_port = 0 + to_port = 0 + protocol = "-1" + cidr_block = module.vpc.vpc_cidr_block + } + ] + private_outbound_acl_rules = [ + { + rule_number = 100 + rule_action = "allow" + from_port = 0 + to_port = 0 + protocol = "-1" + cidr_block = module.vpc.vpc_cidr_block + } + ] + public_inbound_acl_rules = [ + { + rule_number = 100 + rule_action = "allow" + from_port = 0 + to_port = 0 + protocol = "-1" + cidr_block = "0.0.0.0/0" + } + ] + public_outbound_acl_rules = [ + { + rule_number = 100 + rule_action = "allow" + from_port = 0 + to_port = 0 + protocol = "-1" + cidr_block = "0.0.0.0/0" + } + ] + +} + +####---------------------------------------------------------------------------------- +## SECURITY GROUP +####---------------------------------------------------------------------------------- + +module "security_group" { + source = "clouddrove/security-group/aws" + version = "2.0.0" + + name = "${local.name}-rest-api-private" + environment = local.environment + + vpc_id = module.vpc.vpc_id + new_sg_ingress_rules_with_cidr_blocks = [ + { + rule_count = 1 + from_port = 0 + protocol = "-1" + to_port = 0 + cidr_blocks = [module.vpc.vpc_cidr_block] + description = "Allow all traffic from ${local.environment} VPC." + } + ] + new_sg_egress_rules_with_cidr_blocks = [ + { + rule_count = 1 + from_port = 0 + protocol = "-1" + to_port = 0 + cidr_blocks = [module.vpc.vpc_cidr_block] + description = "Allow all outbound traffic." + } + ] +} + + +####---------------------------------------------------------------------------------- +## REST API PRIVATE +####---------------------------------------------------------------------------------- + +module "rest_api_private" { + source = "../../." + + name = "${local.name}-rest-api-private" + environment = local.environment + enabled = true + create_rest_api = true + rest_api_endpoint_type = "PRIVATE" + rest_api_description = "Private REST API for ${module.lambda.name} lambda function" + integration_uri = module.lambda.invoke_arn + rest_api_stage_name = "default" + auto_deploy = true + rest_api_base_path = "test" + domain_name = "api.${local.domain_name}" + zone_id = local.hosted_zone_id + + # -- VPC Endpoint configuration + vpc_id = module.vpc.vpc_id + subnet_ids = module.subnets.private_subnet_id + security_group_ids = [module.security_group.security_group_id] + service_name = "com.amazonaws.${local.region}.execute-api" + vpc_endpoint_type = "Interface" + private_dns_enabled = true + domain_name_certificate_arn = module.acm.arn + + #---access log---- + enable_access_logs = true + retention_in_days = 7 +} + + diff --git a/examples/private-rest-api-gateway/outputs.tf b/examples/private-rest-api-gateway/outputs.tf new file mode 100644 index 0000000..289a67a --- /dev/null +++ b/examples/private-rest-api-gateway/outputs.tf @@ -0,0 +1,21 @@ +##------------------------------------------------------------- +# REST API PRIVATE +##------------------------------------------------------------- + +output "private_rest_api_id" { + value = module.rest_api_private.rest_api_id + description = " The ID of the REST API" + +} + +output "private_rest_api_arn" { + value = module.rest_api_private.rest_api_arn + description = "The Rest api arn" + +} + +output "private_rest_api_invoke_url" { + value = module.rest_api_private.rest_api_invoke_url + description = "The URL to invoke the API pointing to the stage" + +} \ No newline at end of file diff --git a/examples/private-rest-api-gateway/versions.tf b/examples/private-rest-api-gateway/versions.tf new file mode 100644 index 0000000..3f60246 --- /dev/null +++ b/examples/private-rest-api-gateway/versions.tf @@ -0,0 +1,11 @@ +# Terraform version +terraform { + required_version = ">= 1.6.1" + + required_providers { + aws = { + source = "hashicorp/aws" + version = ">= 5.20.0" + } + } +} \ No newline at end of file diff --git a/examples/rest-api-gateway/example.tf b/examples/rest-api-gateway/example.tf new file mode 100644 index 0000000..d63d7be --- /dev/null +++ b/examples/rest-api-gateway/example.tf @@ -0,0 +1,115 @@ +####---------------------------------------------------------------------------------- +## PROVIDER +####---------------------------------------------------------------------------------- +provider "aws" { + region = local.region +} + +####---------------------------------------------------------------------------------- +## LOCALS +####---------------------------------------------------------------------------------- + +locals { + name = "api" + environment = "test" + region = "us-east-1" + domain_name = "clouddrove.ca" + hosted_zone_id = "Z015XXXXXXXXXXXXXXIEP" +} +####---------------------------------------------------------------------------------- +## ACM +####---------------------------------------------------------------------------------- +module "acm" { + source = "clouddrove/acm/aws" + version = "1.4.1" + + name = local.name + environment = local.environment + enable_aws_certificate = true + domain_name = local.domain_name + subject_alternative_names = ["*.${local.domain_name}"] + validation_method = "DNS" + enable_dns_validation = false +} + +####---------------------------------------------------------------------------------- +## LAMBDA +####---------------------------------------------------------------------------------- +module "lambda" { + source = "clouddrove/lambda/aws" + version = "1.3.1" + + name = local.name + environment = local.environment + enable = true + timeout = 60 + filename = "../lambda_packages/index.zip" + handler = "index.lambda_handler" + runtime = "python3.8" + iam_actions = [ + "logs:CreateLogStream", + "logs:CreateLogGroup", + "logs:PutLogEvents" + ] + names = [ + "python_layer" + ] + compatible_runtimes = [ + ["python3.8"] + ] + statement_ids = [ + "AllowExecutionFromApiGateway" + ] + actions = [ + "lambda:InvokeFunction" + ] + principals = [ + "apigateway.amazonaws.com" + ] + variables = { + foo = "bar" + } +} + + +####---------------------------------------------------------------------------------- +## REST API +####---------------------------------------------------------------------------------- + +module "rest_api" { + source = "../../." + + name = "${local.name}-rest-api" + environment = local.environment + create_rest_api = true + domain_name_certificate_arn = module.acm.arn + domain_name = "api.${local.domain_name}" + zone_id = local.hosted_zone_id + rest_api_description = "REST API for ${module.lambda.name} lambda function" + rest_api_endpoint_type = "REGIONAL" + integration_uri = module.lambda.invoke_arn + rest_api_stage_name = "default" + api_resources = { + users = { + path_part = "users" + http_method = "ANY" + uri = module.lambda.invoke_arn + + }, + cards = { + path_part = "cards" + http_method = "ANY" + uri = module.lambda.invoke_arn + } + } + + #---access log---- + enable_access_logs = true + retention_in_days = 7 +} + + + + + + diff --git a/examples/rest-api-gateway/outputs.tf b/examples/rest-api-gateway/outputs.tf new file mode 100644 index 0000000..a0b81f7 --- /dev/null +++ b/examples/rest-api-gateway/outputs.tf @@ -0,0 +1,22 @@ +##------------------------------------------------------------- +# REST API +##------------------------------------------------------------- + +output "rest_api_id" { + value = module.rest_api.rest_api_id + description = " The ID of the REST API" + +} + +output "rest_api_arn" { + value = module.rest_api.rest_api_arn + description = "The Rest api arn" +} + +output "rest_api_invoke_url" { + value = module.rest_api.rest_api_invoke_url + description = "The URL to invoke the API pointing to the stage" + +} + + diff --git a/examples/rest-api-gateway/versions.tf b/examples/rest-api-gateway/versions.tf new file mode 100644 index 0000000..3f60246 --- /dev/null +++ b/examples/rest-api-gateway/versions.tf @@ -0,0 +1,11 @@ +# Terraform version +terraform { + required_version = ">= 1.6.1" + + required_providers { + aws = { + source = "hashicorp/aws" + version = ">= 5.20.0" + } + } +} \ No newline at end of file diff --git a/main.tf b/main.tf index e24f286..0561bcc 100644 --- a/main.tf +++ b/main.tf @@ -536,13 +536,14 @@ module "kms_key" { source = "clouddrove/kms/aws" version = "1.3.1" - enabled = var.enabled && var.create_rest_api && var.enable_access_logs && var.create_kms_key ? true : false + enabled = var.enabled && var.enable_access_logs && var.create_kms_key ? true : false name = module.labels.id enable_key_rotation = var.enable_key_rotation multi_region = var.multi_region policy = data.aws_iam_policy_document.cloudwatch[0].json } + ##---------------------------------------------------------------------------------- ## Below resource will Manages an Kms key JSON POlicy. ##---------------------------------------------------------------------------------- @@ -551,7 +552,7 @@ data "aws_partition" "current" {} data "aws_region" "current" {} data "aws_iam_policy_document" "cloudwatch" { - count = var.enabled && var.create_rest_api && var.enable_access_logs && var.create_kms_key ? 1 : 0 + count = var.enabled && var.enable_access_logs && var.create_kms_key ? 1 : 0 policy_id = "key-policy-cloudwatch" statement { sid = "Enable IAM User Permissions" diff --git a/variables.tf b/variables.tf index ddbd9fd..6e4bc92 100644 --- a/variables.tf +++ b/variables.tf @@ -306,8 +306,8 @@ variable "xray_tracing_enabled" { } variable "vpc_endpoint_id" { - type = string - default = "" + type = set(string) + default = [""] description = "ID of the vpc endpoint. Only applicable when " }