terraform { required_providers { aws = { source = "hashicorp/aws" version = "~> 5.0" } } } # Configure the AWS Provider provider "aws" { region = var.region profile = "StandOut_Terraform" } # Create a VPC resource "aws_vpc" "vpc_standout" { cidr_block = var.env == "dev" ? "10.0.0.0/16" : "10.10.0.0/16" } # create an s3 bucket for config resource "aws_s3_bucket" "s3_standout_config" { bucket = "standout-config-${var.env}" force_destroy = false } # create an s3 bucket for data resource "aws_s3_bucket" "s3_standout" { bucket = "standout-data-${var.env}" force_destroy = true } resource "aws_s3_bucket_ownership_controls" "s3_standout_ownership" { bucket = aws_s3_bucket.s3_standout.id rule { object_ownership = "BucketOwnerPreferred" } } resource "aws_s3_bucket_ownership_controls" "s3_standout_config_ownership" { bucket = aws_s3_bucket.s3_standout_config.id rule { object_ownership = "BucketOwnerPreferred" } } resource "aws_s3_bucket_public_access_block" "s3_standout_public_access" { bucket = aws_s3_bucket.s3_standout.id block_public_acls = false block_public_policy = false ignore_public_acls = true restrict_public_buckets = true } resource "aws_s3_bucket_public_access_block" "s3_standout_config_public_access" { bucket = aws_s3_bucket.s3_standout_config.id block_public_acls = false block_public_policy = false ignore_public_acls = true restrict_public_buckets = true } resource "aws_s3_bucket_acl" "s3_standout_public_acl" { depends_on = [ aws_s3_bucket_ownership_controls.s3_standout_ownership, aws_s3_bucket_public_access_block.s3_standout_public_access, ] bucket = aws_s3_bucket.s3_standout.id acl = "public-read" } resource "aws_s3_bucket_policy" "s3_standout_policy" { bucket = aws_s3_bucket.s3_standout.id policy = data.aws_iam_policy_document.s3_standout_allow_lambda.json } resource "aws_s3_bucket_policy" "s3_standout_config_policy" { bucket = aws_s3_bucket.s3_standout_config.id policy = data.aws_iam_policy_document.s3_standout_config_allow_lambda.json } data "aws_iam_policy_document" "s3_standout_config_allow_lambda" { statement { principals { type = "AWS" identifiers = ["*"] } actions = [ "s3:Get*", "s3:List*", "s3:Put*", ] resources = [ "${aws_s3_bucket.s3_standout_config.arn}/*", ] } } data "aws_iam_policy_document" "s3_standout_allow_lambda" { statement { principals { type = "AWS" identifiers = ["*"] } actions = [ "s3:Get*", "s3:List*", "s3:Put*", ] resources = [ "${aws_s3_bucket.s3_standout.arn}/*", ] } } # create a redirect lambda function data "aws_iam_policy_document" "lambda_role" { statement { effect = "Allow" principals { type = "Service" identifiers = ["lambda.amazonaws.com"] } actions = ["sts:AssumeRole"] } } resource "aws_iam_role" "iam_for_lambda" { name = "iam_for_lambda-${var.env}" assume_role_policy = data.aws_iam_policy_document.lambda_role.json } resource "aws_iam_role_policy_attachment" "iam_for_lambda_allow_logs" { role = aws_iam_role.iam_for_lambda.name policy_arn = "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" } data "archive_file" "lambda_standout_redirect_code" { type = "zip" source_dir = "./lambda_redirect" output_path = "./lambda_zip/standout_lambda_redirect-${var.env}.zip" } data "archive_file" "lambda_standout_config_code" { type = "zip" source_dir = "./lambda_config" output_path = "./lambda_zip/standout_lambda_config-${var.env}.zip" } data "archive_file" "lambda_layer_deps" { type = "zip" source_dir = "./lambda_layer" output_path = "./lambda_zip/lambda_layer-${var.env}.zip" } resource "aws_lambda_layer_version" "lambda_layer" { filename = "./lambda_zip/lambda_layer-${var.env}.zip" layer_name = "lambda_deps" compatible_runtimes = ["python3.12"] } resource "aws_lambda_function" "lambda_standout_redirect" { # If the file is not in the current working directory you will need to include a # path.module in the filename. filename = "./lambda_zip/standout_lambda_redirect-${var.env}.zip" function_name = "standout-redirect-${var.env}" role = aws_iam_role.iam_for_lambda.arn handler = "lambda_redirect.lambda_handler" source_code_hash = data.archive_file.lambda_standout_redirect_code.output_base64sha256 runtime = "python3.12" layers = [aws_lambda_layer_version.lambda_layer.arn] timeout = 10 environment { variables = { BUCKET_CONFIG = aws_s3_bucket.s3_standout_config.bucket, BUCKET_DATA = aws_s3_bucket.s3_standout.bucket } } } resource "aws_lambda_function" "lambda_standout_config" { # If the file is not in the current working directory you will need to include a # path.module in the filename. filename = "./lambda_zip/standout_lambda_config-${var.env}.zip" function_name = "standout-config-${var.env}" role = aws_iam_role.iam_for_lambda.arn handler = "lambda_config.lambda_handler" source_code_hash = data.archive_file.lambda_standout_config_code.output_base64sha256 runtime = "python3.12" layers = [aws_lambda_layer_version.lambda_layer.arn] timeout = 10 environment { variables = { BUCKET_CONFIG = aws_s3_bucket.s3_standout_config.bucket, BUCKET_DATA = aws_s3_bucket.s3_standout.bucket FUNCTION_URL = aws_apigatewayv2_stage.api_standout_lambda_stage.invoke_url } } } # Add S3 trigger to config lambda resource "aws_lambda_permission" "lambda_config_s3_trigger_allow" { statement_id = "AllowExecutionFromS3Bucket" action = "lambda:InvokeFunction" function_name = aws_lambda_function.lambda_standout_config.arn principal = "s3.amazonaws.com" source_arn = aws_s3_bucket.s3_standout.arn } resource "aws_s3_bucket_notification" "bucket_notification" { bucket = aws_s3_bucket.s3_standout.id lambda_function { lambda_function_arn = aws_lambda_function.lambda_standout_config.arn events = ["s3:ObjectCreated:*", "s3:ObjectRemoved:*"] } } # create API gateway for lambda triger and connect resource "aws_apigatewayv2_api" "api_standout_gateway" { name = "standout-api-${var.env}" protocol_type = "HTTP" } resource "aws_apigatewayv2_integration" "api_standout_integration" { api_id = aws_apigatewayv2_api.api_standout_gateway.id integration_type = "AWS_PROXY" connection_type = "INTERNET" description = "Lambda example" integration_method = "POST" integration_uri = aws_lambda_function.lambda_standout_redirect.invoke_arn passthrough_behavior = "WHEN_NO_MATCH" } resource "aws_apigatewayv2_stage" "api_standout_lambda_stage" { api_id = aws_apigatewayv2_api.api_standout_gateway.id name = var.env auto_deploy = true } resource "aws_apigatewayv2_route" "api_standout_route" { api_id = aws_apigatewayv2_api.api_standout_gateway.id route_key = "GET /api" target = "integrations/${aws_apigatewayv2_integration.api_standout_integration.id}" } resource "aws_lambda_permission" "api_lambda_permission" { statement_id = "AllowExecutionFromAPIGateway" action = "lambda:InvokeFunction" function_name = aws_lambda_function.lambda_standout_redirect.function_name principal = "apigateway.amazonaws.com" source_arn = "${aws_apigatewayv2_api.api_standout_gateway.execution_arn}/*/*" } # create a route 53 configuration