diff --git a/modules/cloudfront-with-s3-as-public-storage/README.md b/modules/cloudfront-with-s3-as-public-storage/README.md index 3fbdd55..9bf4cac 100644 --- a/modules/cloudfront-with-s3-as-public-storage/README.md +++ b/modules/cloudfront-with-s3-as-public-storage/README.md @@ -48,6 +48,7 @@ | Name | Description | |------|-------------| | [arn](#output\_arn) | CDN distribution ARN. | +| [bucket\_name](#output\_bucket\_name) | Name of the storage S3 bucket. | | [deployment\_group](#output\_deployment\_group) | Deployment group name | | [deployment\_group\_arn](#output\_deployment\_group\_arn) | Deployment group ARN | | [deployment\_policy\_id](#output\_deployment\_policy\_id) | IAM policy for deploying CloudFront distribution. | diff --git a/modules/iam/smtp-user/README.md b/modules/iam/smtp-user/README.md new file mode 100644 index 0000000..6c04204 --- /dev/null +++ b/modules/iam/smtp-user/README.md @@ -0,0 +1,40 @@ + +## Requirements + +| Name | Version | +|------|---------| +| [terraform](#requirement\_terraform) | ~> 1.0 | +| [aws](#requirement\_aws) | ~> 5.0 | + +## Providers + +| Name | Version | +|------|---------| +| [aws](#provider\_aws) | ~> 5.0 | + +## Resources + +| Name | Type | +|------|------| +| [aws_iam_access_key.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_access_key) | resource | +| [aws_iam_policy.ses_sender](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_policy) | resource | +| [aws_iam_user.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_user) | resource | +| [aws_iam_user_policy_attachment.ses_sender](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_user_policy_attachment) | resource | +| [aws_iam_policy_document.ses_sender](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | + +## Inputs + +| Name | Description | Type | Default | Required | +|------|-------------|------|---------|:--------:| +| [name](#input\_name) | User name | `string` | n/a | yes | + +## Outputs + +| Name | Description | +|------|-------------| +| [access\_key\_as\_envs](#output\_access\_key\_as\_envs) | User access key map containing AWS\_ACCESS\_KEY\_ID and AWS\_SECRET\_ACCESS\_KEY. | +| [arn](#output\_arn) | User ARN. | +| [key\_id](#output\_key\_id) | Access key ID. | +| [key\_secret](#output\_key\_secret) | Access secret access key. | +| [name](#output\_name) | User name. | + \ No newline at end of file diff --git a/modules/iam/smtp-user/main.tf b/modules/iam/smtp-user/main.tf new file mode 100644 index 0000000..28587e9 --- /dev/null +++ b/modules/iam/smtp-user/main.tf @@ -0,0 +1,25 @@ +resource "aws_iam_user" "this" { + name = var.name +} + +resource "aws_iam_access_key" "this" { + user = aws_iam_user.this.name +} + +data "aws_iam_policy_document" "ses_sender" { + statement { + actions = ["ses:SendRawEmail"] + resources = ["*"] + } +} + +resource "aws_iam_policy" "ses_sender" { + name = "ses_sender" + description = "Allows sending of e-mails via Simple Email Service" + policy = data.aws_iam_policy_document.ses_sender.json +} + +resource "aws_iam_user_policy_attachment" "ses_sender" { + user = aws_iam_user.this.name + policy_arn = aws_iam_policy.ses_sender.arn +} \ No newline at end of file diff --git a/modules/iam/smtp-user/outputs.tf b/modules/iam/smtp-user/outputs.tf new file mode 100644 index 0000000..c65dcb0 --- /dev/null +++ b/modules/iam/smtp-user/outputs.tf @@ -0,0 +1,30 @@ +output "name" { + description = "User name." + value = aws_iam_user.this.name +} + +output "arn" { + description = "User ARN." + value = aws_iam_user.this.arn +} + +output "access_key_as_envs" { + description = "User access key map containing AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY." + value = { + AWS_ACCESS_KEY_ID = aws_iam_access_key.this.id + AWS_SECRET_ACCESS_KEY = aws_iam_access_key.this.ses_smtp_password_v4 + } + sensitive = true +} + +output "key_id" { + description = "Access key ID." + value = aws_iam_access_key.this.id + sensitive = true +} + +output "key_secret" { + description = "Access secret access key." + value = aws_iam_access_key.this.ses_smtp_password_v4 + sensitive = true +} diff --git a/modules/iam/smtp-user/variables.tf b/modules/iam/smtp-user/variables.tf new file mode 100644 index 0000000..2b7ef4e --- /dev/null +++ b/modules/iam/smtp-user/variables.tf @@ -0,0 +1,4 @@ +variable "name" { + type = string + description = "User name" +} \ No newline at end of file diff --git a/modules/iam/smtp-user/versions.tf b/modules/iam/smtp-user/versions.tf new file mode 100644 index 0000000..d50a6bd --- /dev/null +++ b/modules/iam/smtp-user/versions.tf @@ -0,0 +1,10 @@ +terraform { + required_version = "~> 1.0" + + required_providers { + aws = { + source = "hashicorp/aws" + version = "~> 5.0" + } + } +} diff --git a/templates/production/README.md b/templates/production/README.md index b5e84c2..4e30e94 100644 --- a/templates/production/README.md +++ b/templates/production/README.md @@ -12,38 +12,54 @@ | Name | Version | |------|---------| | [aws](#provider\_aws) | 5.68.0 | +| [aws.global](#provider\_aws.global) | 5.68.0 | +| [random](#provider\_random) | 3.6.3 | ## Modules | Name | Source | Version | |------|--------|---------| +| [app\_storage\_s3\_read\_write](#module\_app\_storage\_s3\_read\_write) | ../../modules/iam/s3-read-write | n/a | +| [cert](#module\_cert) | ../../modules/acm-wildcard | n/a | | [ci\_iam](#module\_ci\_iam) | ../../modules/iam/user-with-access-key | n/a | | [cloudfront\_app](#module\_cloudfront\_app) | ../../modules/cloudfront-app | n/a | | [cloudfront\_bucket\_policy](#module\_cloudfront\_bucket\_policy) | ../../modules/cloudfront-s3-origin-bucket-policy | n/a | | [cloudfront\_deployment\_policy](#module\_cloudfront\_deployment\_policy) | ../../modules/cloudfront-deployment-policy | n/a | +| [cloudfront\_dns](#module\_cloudfront\_dns) | ../../modules/route53/cloudfront-record | n/a | | [cluster](#module\_cluster) | ../../modules/ecs-cluster | n/a | | [database\_subnet](#module\_database\_subnet) | ../../modules/vpc-private-subnet | n/a | | [db](#module\_db) | ../../modules/postgres | n/a | | [ecr](#module\_ecr) | ../../modules/ecr-repository | n/a | +| [iam\_app](#module\_iam\_app) | ../../modules/iam/user-with-access-key | n/a | | [lb](#module\_lb) | ../../modules/lb/alb | n/a | | [private\_subnet](#module\_private\_subnet) | ../../modules/vpc-private-subnet | n/a | | [public\_subnet](#module\_public\_subnet) | ../../modules/vpc-public-subnet | n/a | +| [secrets](#module\_secrets) | ../../modules/ssm/parameters | n/a | | [secrets\_ci](#module\_secrets\_ci) | ../../modules/ssm/parameters | n/a | -| [service](#module\_service) | ../../modules/ecs-service | n/a | +| [service](#module\_service) | ../../modules/route53/load-balancer-record | n/a | +| [ses](#module\_ses) | ../../modules/ses | n/a | | [vpc](#module\_vpc) | ../../modules/vpc | n/a | ## Resources | Name | Type | |------|------| +| [aws_alb_listener.default](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/alb_listener) | resource | | [aws_iam_policy.ci_user](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_policy) | resource | +| [aws_iam_user_policy_attachment.allow_sending_email](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_user_policy_attachment) | resource | | [aws_iam_user_policy_attachment.ci_user](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_user_policy_attachment) | resource | +| [aws_lb_listener_rule.service](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/lb_listener_rule) | resource | +| [aws_s3_bucket.app_storage](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket) | resource | | [aws_s3_bucket.apps_storage](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket) | resource | +| [aws_s3_bucket.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket) | resource | | [aws_s3_bucket_public_access_block.apps_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_public_access_block) | resource | +| [aws_s3_bucket_public_access_block.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_public_access_block) | resource | +| [random_id.example](https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/id) | resource | | [aws_caller_identity.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/caller_identity) | data source | | [aws_iam_policy_document.ci_user](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_route53_zone.domain](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/route53_zone) | data source | +| [aws_route53_zone.name](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/route53_zone) | data source | ## Inputs diff --git a/templates/production/acm.tf b/templates/production/acm.tf new file mode 100644 index 0000000..461bf0a --- /dev/null +++ b/templates/production/acm.tf @@ -0,0 +1,23 @@ +data "aws_route53_zone" "name" { # TODO adjust name to your project + provider = aws.global + name = "example.com" # TODO adjust name to your project +} + +module "cert" { + providers = { + aws = aws.global + } + + source = "../../modules/acm-wildcard" + + domain = "example.com" # TODO adjust name to your project + validation_zone = "example.com" # TODO adjust name to your project + wildcard = true + validate = true + + context = { + namespace = "name" # TODO adjust name to your project + stage = "production" + name = "acm" + } +} \ No newline at end of file diff --git a/templates/production/ecr.tf b/templates/production/ecr.tf index 40057a9..7d7a092 100644 --- a/templates/production/ecr.tf +++ b/templates/production/ecr.tf @@ -10,5 +10,4 @@ module "ecr" { output "url" { value = module.ecr.url - } diff --git a/templates/production/ecs.tf b/templates/production/ecs.tf index 59986a8..6ff1138 100644 --- a/templates/production/ecs.tf +++ b/templates/production/ecs.tf @@ -31,6 +31,8 @@ module "service" { cluster_id = module.cluster.id desired_count = 1 + secrets = ["/name/production/service/terraform", "/name/production/service/editable"] + tcp_ports = [{ name = "http" host = 0 @@ -43,3 +45,11 @@ module "service" { name = "ecs" } } + +# TODO Optional variable to create SSM parameter for private key +# resource "aws_ssm_parameter" "private_key" { +# name = "/ecs/config/PRIVATE_KEY_PEM" +# description = "Private key for EC2 instance" +# type = "SecureString" +# value = module.cluster.private_key_pem +# } \ No newline at end of file diff --git a/templates/production/iam.tf b/templates/production/iam.tf index e69de29..4412cb0 100644 --- a/templates/production/iam.tf +++ b/templates/production/iam.tf @@ -0,0 +1,10 @@ +module "iam_app" { + source = "../../modules/iam/user-with-access-key" + + name = "name-production" # TODO adjust name to your project +} + +resource "aws_iam_user_policy_attachment" "allow_sending_email" { + user = module.iam_app.name # TODO adjust name to your project + policy_arn = module.ses.send_email_policy_arn +} diff --git a/templates/production/networking.tf b/templates/production/networking.tf index 875d2db..9c25e82 100644 --- a/templates/production/networking.tf +++ b/templates/production/networking.tf @@ -71,4 +71,45 @@ module "lb" { force_https = true context = local.context +} + +resource "aws_alb_listener" "default" { + load_balancer_arn = module.lb.id + port = 443 + protocol = "HTTPS" + certificate_arn = module.cert.arn + ssl_policy = "ELBSecurityPolicy-TLS-1-2-2017-01" # https://docs.aws.amazon.com/elasticloadbalancing/latest/application/create-https-listener.html + + default_action { + type = "fixed-response" + + fixed_response { + content_type = "text/plain" + message_body = "Hello there! Load balancer works." + status_code = "200" + } + } +} + + +resource "aws_lb_listener_rule" "service" { + listener_arn = aws_alb_listener.default.arn + priority = 60 + + action { + type = "forward" + target_group_arn = module.service.lb_target_group_id # TODO adjust name to your project + } + + condition { + host_header { + values = ["api.example.com"] # TODO adjust name to your project + } + } + + condition { + path_pattern { + values = ["/*"] + } + } } \ No newline at end of file diff --git a/templates/production/rds.tf b/templates/production/rds.tf index 6a0d41c..0347f39 100644 --- a/templates/production/rds.tf +++ b/templates/production/rds.tf @@ -23,5 +23,4 @@ module "db" { parameter_group_family = "postgres16" engine_version = "16.1" instance_class = "db.t4g.small" - } diff --git a/templates/production/route53.tf b/templates/production/route53.tf index bddcff6..cc46d60 100644 --- a/templates/production/route53.tf +++ b/templates/production/route53.tf @@ -1,3 +1,19 @@ data "aws_route53_zone" "domain" { name = "your-domain.com" # TODO adjust name to your project +} + +module "cloudfront_dns" { + source = "../../modules/route53/cloudfront-record" + + name = "" + zone_id = data.aws_route53_zone.example_com.zone_id # TODO adjust name to your project + distribution_id = module.cloudfront_app.id +} + +module "service" { + source = "../../modules/route53/load-balancer-record" + + lb_arn = module.lb.id + name = "service" + zone_id = data.aws_route53_zone.example_com.zone_id # TODO adjust name to your project } \ No newline at end of file diff --git a/templates/production/s3.tf b/templates/production/s3.tf new file mode 100644 index 0000000..1ce8d46 --- /dev/null +++ b/templates/production/s3.tf @@ -0,0 +1,29 @@ +resource "random_id" "example" { + byte_length = 4 + prefix = "web-" +} + +resource "aws_s3_bucket" "this" { + bucket = "apps-${random_id.example.hex}" +} + +resource "aws_s3_bucket_public_access_block" "this" { + bucket = aws_s3_bucket.this.id + + block_public_acls = true + block_public_policy = true + ignore_public_acls = true + restrict_public_buckets = true +} + +resource "aws_s3_bucket" "app_storage" { + bucket = "production-name-app-storage" # TODO adjust name to your project +} + +module "app_storage_s3_read_write" { + source = "../../modules/iam/s3-read-write" + + name_prefix = "name-storage" # TODO adjust name to your project + bucket_arn = aws_s3_bucket.app_storage.arn + users = [module.iam_app.name] # TODO adjust name to your project +} diff --git a/templates/production/secrets.tf b/templates/production/secrets.tf new file mode 100644 index 0000000..03741df --- /dev/null +++ b/templates/production/secrets.tf @@ -0,0 +1,20 @@ +module "secrets" { + source = "../../modules/ssm/parameters" + + context = { + namespace = "name" # TODO adjust name to your project + stage = "production" + name = "service" # TODO adjust name to your project + } + + secrets = { + NODE_ENV = "production" + DATABASE_URL = module.db.url + AWS_REGION = var.region + } + + editable_secrets = { + CORS_ORIGIN = "Edit in AWS Console" + ENVIRONMENT = "Edit in AWS Console" + } +} \ No newline at end of file diff --git a/templates/production/ses.tf b/templates/production/ses.tf new file mode 100644 index 0000000..86ccdd3 --- /dev/null +++ b/templates/production/ses.tf @@ -0,0 +1,13 @@ +module "ses" { + source = "../../modules/ses" + + name_prefix = "name-production" # TODO adjust name to your project + domain_name = "example.com" + zone_id = data.aws_route53_zone.example_com.id # TODO adjust name to your project + verify_dkim = true + dmarc_enabled = true + spf_enabled = true + email_addresses = [ + "your.name@example.com" # TODO adjust name to your project + ] +} diff --git a/templates/production/versions.tf b/templates/production/versions.tf index cbdeb05..b95610f 100644 --- a/templates/production/versions.tf +++ b/templates/production/versions.tf @@ -1,13 +1,13 @@ terraform { required_version = "~> 1.0" - # cloud { - # organization = "organization" # TODO adjust name to your project - - # workspaces { - # name = "workspace" # TODO adjust name to your project - # } - # } + backend "s3" { + key = "production/terraform.tfstate" + bucket = "name-production-tf-state" # TODO adjust name to your project + region = var.region + encrypt = true + use_lockfile = true + } required_providers { aws = { diff --git a/templates/staging/README.md b/templates/staging/README.md index 00f1411..463c324 100644 --- a/templates/staging/README.md +++ b/templates/staging/README.md @@ -12,38 +12,53 @@ | Name | Version | |------|---------| | [aws](#provider\_aws) | ~> 5.0 | +| [aws.global](#provider\_aws.global) | ~> 5.0 | +| [random](#provider\_random) | ~> 3.0 | ## Modules | Name | Source | Version | |------|--------|---------| +| [app\_storage\_s3\_read\_write](#module\_app\_storage\_s3\_read\_write) | ../../modules/iam/s3-read-write | n/a | +| [cert](#module\_cert) | ../../modules/acm-wildcard | n/a | | [ci\_iam](#module\_ci\_iam) | ../../modules/iam/user-with-access-key | n/a | | [cloudfront\_app](#module\_cloudfront\_app) | ../../modules/cloudfront-app | n/a | | [cloudfront\_bucket\_policy](#module\_cloudfront\_bucket\_policy) | ../../modules/cloudfront-s3-origin-bucket-policy | n/a | | [cloudfront\_deployment\_policy](#module\_cloudfront\_deployment\_policy) | ../../modules/cloudfront-deployment-policy | n/a | +| [cloudfront\_dns](#module\_cloudfront\_dns) | ../../modules/route53/cloudfront-record | n/a | | [cluster](#module\_cluster) | ../../modules/ecs-cluster | n/a | | [database\_subnet](#module\_database\_subnet) | ../../modules/vpc-private-subnet | n/a | | [db](#module\_db) | ../../modules/postgres | n/a | | [ecr](#module\_ecr) | ../../modules/ecr-repository | n/a | +| [iam\_app](#module\_iam\_app) | ../../modules/iam/user-with-access-key | n/a | | [lb](#module\_lb) | ../../modules/lb/alb | n/a | | [private\_subnet](#module\_private\_subnet) | ../../modules/vpc-private-subnet | n/a | | [public\_subnet](#module\_public\_subnet) | ../../modules/vpc-public-subnet | n/a | +| [secrets](#module\_secrets) | ../../modules/ssm/parameters | n/a | | [secrets\_ci](#module\_secrets\_ci) | ../../modules/ssm/parameters | n/a | -| [service](#module\_service) | ../../modules/ecs-service | n/a | +| [service](#module\_service) | ../../modules/route53/load-balancer-record | n/a | +| [ses](#module\_ses) | ../../modules/ses | n/a | | [vpc](#module\_vpc) | ../../modules/vpc | n/a | ## Resources | Name | Type | |------|------| +| [aws_alb_listener.default](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/alb_listener) | resource | | [aws_iam_policy.ci_user](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_policy) | resource | +| [aws_iam_user_policy_attachment.allow_sending_email](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_user_policy_attachment) | resource | | [aws_iam_user_policy_attachment.ci_user](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_user_policy_attachment) | resource | +| [aws_lb_listener_rule.service](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/lb_listener_rule) | resource | +| [aws_s3_bucket.app_storage](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket) | resource | | [aws_s3_bucket.apps_storage](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket) | resource | +| [aws_s3_bucket.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket) | resource | | [aws_s3_bucket_public_access_block.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_public_access_block) | resource | +| [random_id.example](https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/id) | resource | | [aws_caller_identity.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/caller_identity) | data source | | [aws_iam_policy_document.ci_user](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_route53_zone.domain](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/route53_zone) | data source | +| [aws_route53_zone.name](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/route53_zone) | data source | ## Inputs diff --git a/templates/staging/acm.tf b/templates/staging/acm.tf new file mode 100644 index 0000000..0978f28 --- /dev/null +++ b/templates/staging/acm.tf @@ -0,0 +1,23 @@ +data "aws_route53_zone" "name" { # TODO adjust name to your project + provider = aws.global + name = "example.com" # TODO adjust name to your project +} + +module "cert" { + providers = { + aws = aws.global + } + + source = "../../modules/acm-wildcard" + + domain = "example.com" # TODO adjust name to your project + validation_zone = "example.com" # TODO adjust name to your project + wildcard = true + validate = true + + context = { + namespace = "name" # TODO adjust name to your project + stage = "staging" + name = "acm" + } +} \ No newline at end of file diff --git a/templates/staging/ecr.tf b/templates/staging/ecr.tf index 40057a9..a0c6773 100644 --- a/templates/staging/ecr.tf +++ b/templates/staging/ecr.tf @@ -3,12 +3,11 @@ module "ecr" { context = { namespace = "name" # TODO adjust name to your project - stage = "production" + stage = "staging" name = "api" } } output "url" { value = module.ecr.url - } diff --git a/templates/staging/ecs.tf b/templates/staging/ecs.tf index 479997b..2f8872b 100644 --- a/templates/staging/ecs.tf +++ b/templates/staging/ecs.tf @@ -31,6 +31,8 @@ module "service" { cluster_id = module.cluster.id desired_count = 1 + secrets = ["/name/staging/service/terraform", "/name/staging/service/editable"] + tcp_ports = [{ name = "http" host = 0 @@ -43,3 +45,11 @@ module "service" { name = "ecs" } } + +# TODO Optional variable to create SSM parameter for private key +# resource "aws_ssm_parameter" "private_key" { +# name = "/ecs/config/PRIVATE_KEY_PEM" +# description = "Private key for EC2 instance" +# type = "SecureString" +# value = module.cluster.private_key_pem +# } \ No newline at end of file diff --git a/templates/staging/iam.tf b/templates/staging/iam.tf index e69de29..2b7d230 100644 --- a/templates/staging/iam.tf +++ b/templates/staging/iam.tf @@ -0,0 +1,10 @@ +module "iam_app" { + source = "../../modules/iam/user-with-access-key" + + name = "name-staging" # TODO adjust name to your project +} + +resource "aws_iam_user_policy_attachment" "allow_sending_email" { + user = module.iam_app.name # TODO adjust name to your project + policy_arn = module.ses.send_email_policy_arn +} diff --git a/templates/staging/networking.tf b/templates/staging/networking.tf index 482b29f..bb47c3d 100644 --- a/templates/staging/networking.tf +++ b/templates/staging/networking.tf @@ -71,4 +71,45 @@ module "lb" { force_https = true context = local.context +} + +resource "aws_alb_listener" "default" { + load_balancer_arn = module.lb.id + port = 443 + protocol = "HTTPS" + certificate_arn = module.cert.arn + ssl_policy = "ELBSecurityPolicy-TLS-1-2-2017-01" # https://docs.aws.amazon.com/elasticloadbalancing/latest/application/create-https-listener.html + + default_action { + type = "fixed-response" + + fixed_response { + content_type = "text/plain" + message_body = "Hello there! Load balancer works." + status_code = "200" + } + } +} + + +resource "aws_lb_listener_rule" "service" { + listener_arn = aws_alb_listener.default.arn + priority = 60 + + action { + type = "forward" + target_group_arn = module.service.lb_target_group_id # TODO adjust name to your project + } + + condition { + host_header { + values = ["api.example.com"] # TODO adjust name to your project + } + } + + condition { + path_pattern { + values = ["/*"] + } + } } \ No newline at end of file diff --git a/templates/staging/route53.tf b/templates/staging/route53.tf index 305f220..635430f 100644 --- a/templates/staging/route53.tf +++ b/templates/staging/route53.tf @@ -1,3 +1,19 @@ data "aws_route53_zone" "domain" { name = "staging.your-domain.com" # TODO adjust name to your project +} + +module "cloudfront_dns" { + source = "../../modules/route53/cloudfront-record" + + name = "" + zone_id = data.aws_route53_zone.example_com.zone_id # TODO adjust name to your project + distribution_id = module.cloudfront_app.id +} + +module "service" { + source = "../../modules/route53/load-balancer-record" + + lb_arn = module.lb.id + name = "service" + zone_id = data.aws_route53_zone.example_com.zone_id # TODO adjust name to your project } \ No newline at end of file diff --git a/templates/staging/s3.tf b/templates/staging/s3.tf new file mode 100644 index 0000000..0189e8b --- /dev/null +++ b/templates/staging/s3.tf @@ -0,0 +1,29 @@ +resource "random_id" "example" { + byte_length = 4 + prefix = "web-" +} + +resource "aws_s3_bucket" "this" { + bucket = "apps-${random_id.example.hex}" +} + +resource "aws_s3_bucket_public_access_block" "this" { + bucket = aws_s3_bucket.this.id + + block_public_acls = true + block_public_policy = true + ignore_public_acls = true + restrict_public_buckets = true +} + +resource "aws_s3_bucket" "app_storage" { + bucket = "staging-name-app-storage" # TODO adjust name to your project +} + +module "app_storage_s3_read_write" { + source = "../../modules/iam/s3-read-write" + + name_prefix = "name-storage" # TODO adjust name to your project + bucket_arn = aws_s3_bucket.app_storage.arn + users = [module.iam_app.name] # TODO adjust name to your project +} diff --git a/templates/staging/secrets.tf b/templates/staging/secrets.tf new file mode 100644 index 0000000..898a5b2 --- /dev/null +++ b/templates/staging/secrets.tf @@ -0,0 +1,20 @@ +module "secrets" { + source = "../../modules/ssm/parameters" + + context = { + namespace = "name" # TODO adjust name to your project + stage = "staging" + name = "service" # TODO adjust name to your project + } + + secrets = { + NODE_ENV = "staging" + DATABASE_URL = module.db.url + AWS_REGION = var.region + } + + editable_secrets = { + CORS_ORIGIN = "Edit in AWS Console" + ENVIRONMENT = "Edit in AWS Console" + } +} \ No newline at end of file diff --git a/templates/staging/ses.tf b/templates/staging/ses.tf new file mode 100644 index 0000000..b4c2e9d --- /dev/null +++ b/templates/staging/ses.tf @@ -0,0 +1,13 @@ +module "ses" { + source = "../../modules/ses" + + name_prefix = "name-staging" # TODO adjust name to your project + domain_name = "example.com" + zone_id = data.aws_route53_zone.example_com.id # TODO adjust name to your project + verify_dkim = true + dmarc_enabled = true + spf_enabled = true + email_addresses = [ + "your.name@example.com" # TODO adjust name to your project + ] +} diff --git a/templates/staging/versions.tf b/templates/staging/versions.tf index cbdeb05..729b871 100644 --- a/templates/staging/versions.tf +++ b/templates/staging/versions.tf @@ -1,13 +1,13 @@ terraform { required_version = "~> 1.0" - # cloud { - # organization = "organization" # TODO adjust name to your project - - # workspaces { - # name = "workspace" # TODO adjust name to your project - # } - # } + backend "s3" { + key = "staging/terraform.tfstate" + bucket = "name-staging-tf-state" # TODO adjust name to your project + region = var.region + encrypt = true + use_lockfile = true + } required_providers { aws = {