From 5e156df110f5abb8ebbd69410e108d9412bfacdd Mon Sep 17 00:00:00 2001 From: "Anastasia D." Date: Wed, 16 Oct 2024 17:31:12 +0200 Subject: [PATCH] Added possibility to deploy sample example with terraform --- .env.example | 3 + .gitignore | 27 +- Makefile | 34 ++ README.md | 47 ++- bin/build_lambdas.sh | 28 ++ bin/deploy.sh | 26 +- deployment/policies/lambda.json | 12 + deployment/policies/lambda_ssm.json | 14 + .../policies/list_lambda_s3_buckets.json.tpl | 18 + .../presign_lambda_s3_buckets.json.tpl | 17 + .../resize_lambda_s3_buckets.json.tpl | 17 + .../policies/resize_lambda_sns.json.tpl | 17 + .../policies/website_bucket_policy.json.tpl | 13 + deployment/terraform/main.tf | 356 ++++++++++++++++++ 14 files changed, 588 insertions(+), 41 deletions(-) create mode 100644 .env.example create mode 100644 Makefile create mode 100755 bin/build_lambdas.sh create mode 100644 deployment/policies/lambda.json create mode 100644 deployment/policies/lambda_ssm.json create mode 100644 deployment/policies/list_lambda_s3_buckets.json.tpl create mode 100644 deployment/policies/presign_lambda_s3_buckets.json.tpl create mode 100644 deployment/policies/resize_lambda_s3_buckets.json.tpl create mode 100644 deployment/policies/resize_lambda_sns.json.tpl create mode 100644 deployment/policies/website_bucket_policy.json.tpl create mode 100644 deployment/terraform/main.tf diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..0249c39 --- /dev/null +++ b/.env.example @@ -0,0 +1,3 @@ +LOCALSTACK_AUTH_TOKEN=YOUR_TOKEN +AWS_DEFAULT_REGION=us-east-1 +# LOCAL_RUN=false # Default is true \ No newline at end of file diff --git a/.gitignore b/.gitignore index 7419686..5471905 100644 --- a/.gitignore +++ b/.gitignore @@ -59,4 +59,29 @@ volume/ # lambda packages lambdas/*/package/ -lambdas/*/lambda.zip \ No newline at end of file +lambdas/*/lambda.zip +terraform/*/*.zip + +# Local .terraform directories +**/.terraform/* + +# .tfstate files +*.tfstate +*.tfstate.* + +# Crash log files +crash.log +crash.*.log + +*.tfvars +*.tfvars.json + +override.tf +override.tf.json +*_override.tf +*_override.tf.json + +.terraform.tfstate.lock.info + +.terraformrc +terraform.rc \ No newline at end of file diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..1731e05 --- /dev/null +++ b/Makefile @@ -0,0 +1,34 @@ +export AWS_DEFAULT_REGION=us-east-1 +export AWS_ACCESS_KEY_ID ?= test +export AWS_SECRET_ACCESS_KEY ?= test +export LOCAL_RUN ?= true +SHELL := /bin/bash + +include .env + +build: + bin/build_lambdas.sh; + +awslocal-setup: + bin/deploy.sh + +terraform-setup: + $(MAKE) build + cd deployment/terraform; \ + tflocal init; \ + echo "Deploying Terraform configuration 🚀"; \ + tflocal apply --auto-approve -var="local_run=${LOCAL_RUN}"; \ + echo "Paste the function URLs above to the WebApp 🎉"; + +terraform-destroy: + cd deployment/terraform; \ + tflocal destroy --auto-approve; + +start: + LOCALSTACK_AUTH_TOKEN=$(LOCALSTACK_AUTH_TOKEN) localstack start -d + +stop: + @echo + localstack stop + +.PHONY: build awslocal-setup terraform-setup terraform-destroy start stop diff --git a/README.md b/README.md index aa18679..f7a0965 100644 --- a/README.md +++ b/README.md @@ -69,22 +69,37 @@ source .venv/bin/activate pip install -r requirements-dev.txt ``` +## Instructions + +You can set up and deploy the sample application on LocalStack by executing the commands in our Makefile. First, create a `.env` file using the provided `.env.example` file as a template, and include your LocalStack token in it. Then, run `make -s start` to initiate LocalStack on your machine. + +Next, execute `make -s terraform-setup` to provision the infrastructure on LocalStack using Terraform CLI and its scripts. Alternatively, run `make -s awslocal-setup` to set up the infrastructure with the local AWS CLI. + +If you prefer, you can also follow these step-by-step instructions for a manual deployment. + ### LocalStack -Start LocalStack Pro with the appropriate CORS configuration for the S3 Website: +Start LocalStack Pro with Auth Token: ```bash -LOCALSTACK_AUTH_TOKEN=... localstack start +LOCALSTACK_AUTH_TOKEN=... localstack start (-d) ``` -## Instructions +### Terraform + +To create the infrastructure using Terraform, run the following commands: + +```shell +cd deployment/terraform +tflocal init +tflocal apply --auto-approve +``` -You can create the AWS infrastructure on LocalStack by running `bin/deploy.sh`. -Make sure you have Python 3.11 activated before running the script. +We are using the `tflocal` wrapper to configure the local service endpoints, and send the API requests to LocalStack, instead of AWS. -Here are instructions to deploy it manually step-by-step. +### AWS CLI -### Create the buckets +#### Create the buckets The names are completely configurable via SSM: @@ -93,14 +108,14 @@ awslocal s3 mb s3://localstack-thumbnails-app-images awslocal s3 mb s3://localstack-thumbnails-app-resized ``` -### Put the bucket names into the parameter store +#### Put the bucket names into the parameter store ```bash awslocal ssm put-parameter --name /localstack-thumbnail-app/buckets/images --type "String" --value "localstack-thumbnails-app-images" awslocal ssm put-parameter --name /localstack-thumbnail-app/buckets/resized --type "String" --value "localstack-thumbnails-app-resized" ``` -### Create the DLQ Topic for failed lambda invokes +#### Create the DLQ Topic for failed lambda invokes ```bash awslocal sns create-topic --name failed-resize-topic @@ -115,9 +130,9 @@ awslocal sns subscribe \ --notification-endpoint my-email@example.com ``` -### Create the lambdas +#### Create the lambdas -#### S3 pre-signed POST URL generator +##### S3 pre-signed POST URL generator This Lambda is responsible for generating pre-signed POST URLs to upload files to an S3 bucket. @@ -143,7 +158,7 @@ awslocal lambda create-function-url-config \ Copy the `FunctionUrl` from the response, you will need it later to make the app work. -### Image lister lambda +#### Image lister lambda The `list` Lambda is very similar: @@ -166,7 +181,7 @@ awslocal lambda create-function-url-config \ --auth-type NONE ``` -### Resizer Lambda +#### Resizer Lambda ```bash ( @@ -189,7 +204,7 @@ awslocal lambda create-function \ --environment Variables="{STAGE=local}" ``` -### Connect the S3 bucket to the resizer lambda +#### Connect the S3 bucket to the resizer lambda ```bash awslocal s3api put-bucket-notification-configuration \ @@ -197,7 +212,7 @@ awslocal s3api put-bucket-notification-configuration \ --notification-configuration "{\"LambdaFunctionConfigurations\": [{\"LambdaFunctionArn\": \"$(awslocal lambda get-function --function-name resize | jq -r .Configuration.FunctionArn)\", \"Events\": [\"s3:ObjectCreated:*\"]}]}" ``` -### Create the static s3 webapp +#### Create the static s3 webapp ```bash awslocal s3 mb s3://webapp @@ -205,7 +220,7 @@ awslocal s3 sync --delete ./website s3://webapp awslocal s3 website s3://webapp --index-document index.html ``` -### Using the application +#### Using the application Once deployed, visit http://webapp.s3-website.localhost.localstack.cloud:4566 diff --git a/bin/build_lambdas.sh b/bin/build_lambdas.sh new file mode 100755 index 0000000..5dc6c45 --- /dev/null +++ b/bin/build_lambdas.sh @@ -0,0 +1,28 @@ +#!/bin/bash + +(cd lambdas/presign; rm -f lambda.zip; zip lambda.zip handler.py) + +(cd lambdas/list; rm -f lambda.zip; zip lambda.zip handler.py) + +os=$(uname -s) +if [ "$os" == "Darwin" ]; then + ( + cd lambdas/resize + rm -rf libs lambda.zip + docker run --platform linux/x86_64 --rm -v "$PWD":/var/task "public.ecr.aws/sam/build-python3.11" /bin/sh -c "pip3 install -r requirements.txt -t libs; exit" + + cd libs && zip -r ../lambda.zip . && cd .. + zip lambda.zip handler.py + rm -rf libs + ) +else + ( + cd lambdas/resize + rm -rf package lambda.zip + mkdir package + pip3 install -r requirements.txt --platform manylinux2014_x86_64 --only-binary=:all: -t package + zip lambda.zip handler.py + cd package + zip -r ../lambda.zip *; + ) +fi \ No newline at end of file diff --git a/bin/deploy.sh b/bin/deploy.sh index 37e146b..b2555bd 100755 --- a/bin/deploy.sh +++ b/bin/deploy.sh @@ -2,6 +2,8 @@ export AWS_DEFAULT_REGION=us-east-1 +bin/build_lambdas.sh + awslocal s3 mb s3://localstack-thumbnails-app-images awslocal s3 mb s3://localstack-thumbnails-app-resized @@ -14,7 +16,6 @@ awslocal sns subscribe \ --protocol email \ --notification-endpoint my-email@example.com -(cd lambdas/presign; rm -f lambda.zip; zip lambda.zip handler.py) awslocal lambda create-function \ --function-name presign \ --runtime python3.11 \ @@ -30,7 +31,6 @@ awslocal lambda create-function-url-config \ --function-name presign \ --auth-type NONE -(cd lambdas/list; rm -f lambda.zip; zip lambda.zip handler.py) awslocal lambda create-function \ --function-name list \ --runtime python3.11 \ @@ -46,28 +46,6 @@ awslocal lambda create-function-url-config \ --function-name list \ --auth-type NONE -os=$(uname -s) -if [ "$os" == "Darwin" ]; then - ( - cd lambdas/resize - rm -rf libs lambda.zip - docker run --platform linux/x86_64 --rm -v "$PWD":/var/task "public.ecr.aws/sam/build-python3.11" /bin/sh -c "pip3 install -r requirements.txt -t libs; exit" - - cd libs && zip -r ../lambda.zip . && cd .. - zip lambda.zip handler.py - rm -rf libs - ) -else - ( - cd lambdas/resize - rm -rf package lambda.zip - mkdir package - pip3 install -r requirements.txt --platform manylinux2014_x86_64 --only-binary=:all: -t package - zip lambda.zip handler.py - cd package - zip -r ../lambda.zip *; - ) -fi awslocal lambda create-function \ --function-name resize \ diff --git a/deployment/policies/lambda.json b/deployment/policies/lambda.json new file mode 100644 index 0000000..b531d5d --- /dev/null +++ b/deployment/policies/lambda.json @@ -0,0 +1,12 @@ +{ + "Version": "2012-10-17", + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "lambda.amazonaws.com" + } + } + ] + } \ No newline at end of file diff --git a/deployment/policies/lambda_ssm.json b/deployment/policies/lambda_ssm.json new file mode 100644 index 0000000..d4c8ee0 --- /dev/null +++ b/deployment/policies/lambda_ssm.json @@ -0,0 +1,14 @@ +{ + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Action": [ + "ssm:GetParameters" + ], + "Resource": [ + "arn:aws:ssm:::parameter/localstack-thumbnail-app/*" + ] + } + ] +} \ No newline at end of file diff --git a/deployment/policies/list_lambda_s3_buckets.json.tpl b/deployment/policies/list_lambda_s3_buckets.json.tpl new file mode 100644 index 0000000..0278bf1 --- /dev/null +++ b/deployment/policies/list_lambda_s3_buckets.json.tpl @@ -0,0 +1,18 @@ +{ + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Action": [ + "s3:ListBucket", + "s3:GetObject" + ], + "Resource": [ + "arn:aws:s3:::${images_bucket}", + "arn:aws:s3:::${images_bucket}/*", + "arn:aws:s3:::${images_resized_bucket}", + "arn:aws:s3:::${images_resized_bucket}/*" + ] + } + ] +} \ No newline at end of file diff --git a/deployment/policies/presign_lambda_s3_buckets.json.tpl b/deployment/policies/presign_lambda_s3_buckets.json.tpl new file mode 100644 index 0000000..1788bf1 --- /dev/null +++ b/deployment/policies/presign_lambda_s3_buckets.json.tpl @@ -0,0 +1,17 @@ +{ + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Action": [ + "s3:ListBucket", + "s3:GetObject", + "s3:PutObject" + ], + "Resource": [ + "arn:aws:s3:::${images_bucket}", + "arn:aws:s3:::${images_bucket}/*" + ] + } + ] +} \ No newline at end of file diff --git a/deployment/policies/resize_lambda_s3_buckets.json.tpl b/deployment/policies/resize_lambda_s3_buckets.json.tpl new file mode 100644 index 0000000..c21fcfe --- /dev/null +++ b/deployment/policies/resize_lambda_s3_buckets.json.tpl @@ -0,0 +1,17 @@ +{ + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Action": [ + "s3:ListBucket", + "s3:GetObject", + "s3:PutObject" + ], + "Resource": [ + "arn:aws:s3:::${images_resized_bucket}", + "arn:aws:s3:::${images_resized_bucket}/*" + ] + } + ] +} \ No newline at end of file diff --git a/deployment/policies/resize_lambda_sns.json.tpl b/deployment/policies/resize_lambda_sns.json.tpl new file mode 100644 index 0000000..34a7540 --- /dev/null +++ b/deployment/policies/resize_lambda_sns.json.tpl @@ -0,0 +1,17 @@ +{ + "Version": "2012-10-17", + "Statement": [ + { + "Action": [ + "sns:Publish" + ], + "Effect": "Allow", + "Resource": "${failure_notifications_topic_arn}" + }, + { + "Action": "lambda:InvokeFunction", + "Effect": "Allow", + "Resource": "${resize_lambda_arn}" + } + ] +} \ No newline at end of file diff --git a/deployment/policies/website_bucket_policy.json.tpl b/deployment/policies/website_bucket_policy.json.tpl new file mode 100644 index 0000000..0e11a91 --- /dev/null +++ b/deployment/policies/website_bucket_policy.json.tpl @@ -0,0 +1,13 @@ +{ + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Principal": { + "AWS": "${cdn_identity_arn}" + }, + "Action": "s3:GetObject", + "Resource": "${website_bucket_arn}/*" + } + ] +} \ No newline at end of file diff --git a/deployment/terraform/main.tf b/deployment/terraform/main.tf new file mode 100644 index 0000000..4797619 --- /dev/null +++ b/deployment/terraform/main.tf @@ -0,0 +1,356 @@ +terraform { + required_providers { + aws = { + source = "hashicorp/aws" + version = "<= 5.72.1" + } + } +} + +provider "aws" { + region = "us-east-1" + skip_requesting_account_id = var.local_run +} + +variable "local_run" { + description = "Flag to determine if running locally using LocalStack" + type = bool +} + +resource "random_integer" "images_bucket_id" { + min = 0 + max = 10000 +} + +resource "random_integer" "image_resized_bucket_id" { + min = 0 + max = 10000 +} + +resource "random_integer" "website_bucket_id" { + min = 0 + max = 10000 +} + +locals { + env_variables = var.local_run ? { STAGE = "local" } : {} + root_dir = "${path.module}/../.." + images_bucket = "localstack-thumbnails-app-images${var.local_run ? "" : "-${random_integer.images_bucket_id.result}"}" + image_resized_bucket = "localstack-thumbnails-app-resized${var.local_run ? "" : "-${random_integer.image_resized_bucket_id.result}"}" + website_bucket = "localstack-website${var.local_run ? "" : "-${random_integer.website_bucket_id.result}"}" + failure_notifications_email = "my-email@example.com" +} + +# S3 +resource "aws_s3_bucket" "images_bucket" { + bucket = local.images_bucket +} + +resource "aws_s3_bucket" "image_resized_bucket" { + bucket = local.image_resized_bucket +} + +# SSM + +resource "aws_ssm_parameter" "images_bucket_ssm" { + name = "/localstack-thumbnail-app/buckets/images" + type = "String" + value = aws_s3_bucket.images_bucket.bucket +} + +resource "aws_ssm_parameter" "images_resized_bucket_ssm" { + name = "/localstack-thumbnail-app/buckets/resized" + type = "String" + value = aws_s3_bucket.image_resized_bucket.bucket +} + +## Lambdas + +# IAM SSM Policy + +resource "aws_iam_policy" "lambdas_ssm" { + name = "LambdasAccessSsm" + policy = file("../policies/lambda_ssm.json") +} + +# Presign Lambda + +resource "aws_iam_role" "presign_lambda_role" { + name = "PresignLambdaRole" + assume_role_policy = file("../policies/lambda.json") +} + +resource "aws_iam_policy" "presign_lambda_s3_buckets" { + name = "PresignLambdaS3AccessPolicy" + policy = templatefile("../policies/presign_lambda_s3_buckets.json.tpl", { + images_bucket = aws_s3_bucket.images_bucket.bucket + }) +} + +resource "aws_iam_role_policy_attachment" "presign_lambda_s3_buckets" { + role = aws_iam_role.presign_lambda_role.name + policy_arn = aws_iam_policy.presign_lambda_s3_buckets.arn +} + +resource "aws_iam_role_policy_attachment" "presign_lambda_ssm" { + role = aws_iam_role.presign_lambda_role.name + policy_arn = aws_iam_policy.lambdas_ssm.arn +} + +resource "aws_lambda_function" "presign_lambda" { + function_name = "presign" + filename = "${local.root_dir}/lambdas/presign/lambda.zip" + handler = "handler.handler" + runtime = "python3.11" + timeout = 10 + role = aws_iam_role.presign_lambda_role.arn + source_code_hash = filebase64sha256("${local.root_dir}/lambdas/presign/lambda.zip") + + environment { + variables = local.env_variables + } +} + +resource "aws_lambda_function_url" "presign_lambda_function" { + function_name = aws_lambda_function.presign_lambda.function_name + authorization_type = "NONE" +} + +# List images lambda + +resource "aws_iam_role" "list_lambda_role" { + name = "ListLambdaRole" + assume_role_policy = file("../policies/lambda.json") +} + +resource "aws_iam_policy" "list_lambda_s3_buckets" { + name = "ListLambdaS3AccessPolicy" + policy = templatefile("../policies/list_lambda_s3_buckets.json.tpl", { + images_bucket = aws_s3_bucket.images_bucket.bucket, + images_resized_bucket = aws_s3_bucket.image_resized_bucket.bucket + }) +} + +resource "aws_iam_role_policy_attachment" "list_lambda_s3_buckets" { + role = aws_iam_role.list_lambda_role.name + policy_arn = aws_iam_policy.list_lambda_s3_buckets.arn +} + +resource "aws_iam_role_policy_attachment" "list_lambda_ssm" { + role = aws_iam_role.list_lambda_role.name + policy_arn = aws_iam_policy.lambdas_ssm.arn +} + +resource "aws_lambda_function" "list_lambda" { + function_name = "list" + filename = "${local.root_dir}/lambdas/list/lambda.zip" + handler = "handler.handler" + runtime = "python3.11" + timeout = 10 + role = aws_iam_role.list_lambda_role.arn + source_code_hash = filebase64sha256("${local.root_dir}/lambdas/list/lambda.zip") + + environment { + variables = local.env_variables + } +} + +resource "aws_lambda_function_url" "list_lambda_function" { + function_name = aws_lambda_function.list_lambda.function_name + authorization_type = "NONE" +} + +# Resize lambda + +resource "aws_iam_role" "resize_lambda_role" { + name = "ResizeLambdaRole" + assume_role_policy = file("../policies/lambda.json") +} + +resource "aws_iam_policy" "resize_lambda_s3_buckets" { + name = "ResizeLambdaS3Buckets" + policy = templatefile("../policies/resize_lambda_s3_buckets.json.tpl", { + images_resized_bucket = aws_s3_bucket.image_resized_bucket.bucket + }) +} + +resource "aws_iam_role_policy_attachment" "resize_lambda_s3_buckets" { + role = aws_iam_role.resize_lambda_role.name + policy_arn = aws_iam_policy.resize_lambda_s3_buckets.arn +} + +resource "aws_iam_policy" "resize_lambda_sns" { + name = "ResizeLambdaSNS" + policy = templatefile("../policies/resize_lambda_sns.json.tpl", { + failure_notifications_topic_arn = aws_sns_topic.failure_notifications.arn, + resize_lambda_arn = aws_lambda_function.resize_lambda.arn + }) +} + +resource "aws_iam_role_policy_attachment" "resize_lambda_sns" { + role = aws_iam_role.resize_lambda_role.name + policy_arn = aws_iam_policy.resize_lambda_sns.arn +} + +resource "aws_iam_role_policy_attachment" "resize_lambda_ssm" { + role = aws_iam_role.resize_lambda_role.name + policy_arn = aws_iam_policy.lambdas_ssm.arn +} + +resource "aws_lambda_function" "resize_lambda" { + function_name = "resize" + filename = "${local.root_dir}/lambdas/resize/lambda.zip" + handler = "handler.handler" + runtime = "python3.11" + role = aws_iam_role.resize_lambda_role.arn + source_code_hash = filebase64sha256("${local.root_dir}/lambdas/resize/lambda.zip") + + environment { + variables = local.env_variables + } + + dead_letter_config { + target_arn = aws_sns_topic.failure_notifications.arn + } +} + +# SNS Topic for failure notifications +resource "aws_sns_topic" "failure_notifications" { + name = "image_resize_failures" +} + +resource "aws_sns_topic_subscription" "email_sub" { + topic_arn = aws_sns_topic.failure_notifications.arn + protocol = "email" + endpoint = local.failure_notifications_email +} + +# S3 Bucket Notification for Lambda trigger +resource "aws_s3_bucket_notification" "bucket_notification" { + bucket = aws_s3_bucket.images_bucket.id + + lambda_function { + lambda_function_arn = aws_lambda_function.resize_lambda.arn + events = ["s3:ObjectCreated:*"] + } +} + +resource "aws_lambda_permission" "s3_invoke_resize_lambda" { + statement_id = "AllowS3InvokeLambda" + action = "lambda:InvokeFunction" + function_name = aws_lambda_function.resize_lambda.function_name + principal = "s3.amazonaws.com" + source_arn = aws_s3_bucket.images_bucket.arn +} + +# CloudFront + +resource "aws_s3_bucket" "website_bucket" { + bucket = local.website_bucket +} + +resource "aws_s3_bucket_website_configuration" "website_configuration" { + bucket = aws_s3_bucket.website_bucket.bucket + index_document { + suffix = "index.html" + } +} + +resource "aws_s3_object" "website_file_index" { + bucket = aws_s3_bucket.website_bucket.bucket + key = "index.html" + source = "${local.root_dir}/website/index.html" + etag = filemd5("${local.root_dir}/website/index.html") + content_type = "text/html" + acl = "public-read" +} + +resource "aws_s3_object" "website_file_js" { + bucket = aws_s3_bucket.website_bucket.bucket + key = "app.js" + source = "${local.root_dir}/website/app.js" + etag = filemd5("${local.root_dir}/website/app.js") + content_type = "application/javascript" + acl = "public-read" +} + +resource "aws_s3_object" "website_file_icon" { + bucket = aws_s3_bucket.website_bucket.bucket + key = "favicon.ico" + source = "${local.root_dir}/website/favicon.ico" + etag = filemd5("${local.root_dir}/website/favicon.ico") + content_type = "image/x-icon" + acl = "public-read" +} + +resource "aws_cloudfront_origin_access_identity" "cdn_identity" { + comment = "OAI for CloudFront to access S3 bucket" +} + +resource "aws_s3_bucket_policy" "website_bucket_policy" { + bucket = aws_s3_bucket.website_bucket.bucket + policy = templatefile("../policies/website_bucket_policy.json.tpl", { + cdn_identity_arn = aws_cloudfront_origin_access_identity.cdn_identity.iam_arn + website_bucket_arn = aws_s3_bucket.website_bucket.arn + }) +} + +resource "aws_cloudfront_distribution" "cdn" { + origin { + domain_name = aws_s3_bucket.website_bucket.bucket_regional_domain_name + origin_id = aws_s3_bucket.website_bucket.bucket + + s3_origin_config { + origin_access_identity = aws_cloudfront_origin_access_identity.cdn_identity.cloudfront_access_identity_path + } + } + + enabled = true + is_ipv6_enabled = true + default_root_object = "index.html" + + viewer_certificate { + cloudfront_default_certificate = true + } + + default_cache_behavior { + target_origin_id = aws_s3_bucket.website_bucket.bucket + + allowed_methods = ["GET", "HEAD"] + cached_methods = ["GET", "HEAD"] + + viewer_protocol_policy = "redirect-to-https" + min_ttl = 0 + default_ttl = 86400 + max_ttl = 31536000 + } + + restrictions { + geo_restriction { + restriction_type = "none" + } + } +} + +resource "aws_s3_bucket_public_access_block" "website_block_public_access" { + bucket = aws_s3_bucket.website_bucket.bucket + + block_public_acls = true + block_public_policy = true + ignore_public_acls = true + restrict_public_buckets = true +} + +# Outputs + +output "presign_lambda_function_url" { + value = aws_lambda_function_url.presign_lambda_function.function_url +} + +output "list_lambda_function_url" { + value = aws_lambda_function_url.list_lambda_function.function_url +} + +output "cloudfront_url" { + value = "Now open the Web app under: http://${aws_cloudfront_distribution.cdn.domain_name}" +} \ No newline at end of file