Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions modules/cloudfront-with-s3-as-public-storage/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@
| Name | Description |
|------|-------------|
| <a name="output_arn"></a> [arn](#output\_arn) | CDN distribution ARN. |
| <a name="output_bucket_name"></a> [bucket\_name](#output\_bucket\_name) | Name of the storage S3 bucket. |
| <a name="output_deployment_group"></a> [deployment\_group](#output\_deployment\_group) | Deployment group name |
| <a name="output_deployment_group_arn"></a> [deployment\_group\_arn](#output\_deployment\_group\_arn) | Deployment group ARN |
| <a name="output_deployment_policy_id"></a> [deployment\_policy\_id](#output\_deployment\_policy\_id) | IAM policy for deploying CloudFront distribution. |
Expand Down
40 changes: 40 additions & 0 deletions modules/iam/smtp-user/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
<!-- BEGIN_TF_DOCS -->
## Requirements

| Name | Version |
|------|---------|
| <a name="requirement_terraform"></a> [terraform](#requirement\_terraform) | ~> 1.0 |
| <a name="requirement_aws"></a> [aws](#requirement\_aws) | ~> 5.0 |

## Providers

| Name | Version |
|------|---------|
| <a name="provider_aws"></a> [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 |
|------|-------------|------|---------|:--------:|
| <a name="input_name"></a> [name](#input\_name) | User name | `string` | n/a | yes |

## Outputs

| Name | Description |
|------|-------------|
| <a name="output_access_key_as_envs"></a> [access\_key\_as\_envs](#output\_access\_key\_as\_envs) | User access key map containing AWS\_ACCESS\_KEY\_ID and AWS\_SECRET\_ACCESS\_KEY. |
| <a name="output_arn"></a> [arn](#output\_arn) | User ARN. |
| <a name="output_key_id"></a> [key\_id](#output\_key\_id) | Access key ID. |
| <a name="output_key_secret"></a> [key\_secret](#output\_key\_secret) | Access secret access key. |
| <a name="output_name"></a> [name](#output\_name) | User name. |
<!-- END_TF_DOCS -->
25 changes: 25 additions & 0 deletions modules/iam/smtp-user/main.tf
Original file line number Diff line number Diff line change
@@ -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"]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you also need ses:SendEmail

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
}
30 changes: 30 additions & 0 deletions modules/iam/smtp-user/outputs.tf
Original file line number Diff line number Diff line change
@@ -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
}
4 changes: 4 additions & 0 deletions modules/iam/smtp-user/variables.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
variable "name" {
type = string
description = "User name"
}
10 changes: 10 additions & 0 deletions modules/iam/smtp-user/versions.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
terraform {
required_version = "~> 1.0"

required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
}
}
18 changes: 17 additions & 1 deletion templates/production/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,38 +12,54 @@
| Name | Version |
|------|---------|
| <a name="provider_aws"></a> [aws](#provider\_aws) | 5.68.0 |
| <a name="provider_aws.global"></a> [aws.global](#provider\_aws.global) | 5.68.0 |
| <a name="provider_random"></a> [random](#provider\_random) | 3.6.3 |

## Modules

| Name | Source | Version |
|------|--------|---------|
| <a name="module_app_storage_s3_read_write"></a> [app\_storage\_s3\_read\_write](#module\_app\_storage\_s3\_read\_write) | ../../modules/iam/s3-read-write | n/a |
| <a name="module_cert"></a> [cert](#module\_cert) | ../../modules/acm-wildcard | n/a |
| <a name="module_ci_iam"></a> [ci\_iam](#module\_ci\_iam) | ../../modules/iam/user-with-access-key | n/a |
| <a name="module_cloudfront_app"></a> [cloudfront\_app](#module\_cloudfront\_app) | ../../modules/cloudfront-app | n/a |
| <a name="module_cloudfront_bucket_policy"></a> [cloudfront\_bucket\_policy](#module\_cloudfront\_bucket\_policy) | ../../modules/cloudfront-s3-origin-bucket-policy | n/a |
| <a name="module_cloudfront_deployment_policy"></a> [cloudfront\_deployment\_policy](#module\_cloudfront\_deployment\_policy) | ../../modules/cloudfront-deployment-policy | n/a |
| <a name="module_cloudfront_dns"></a> [cloudfront\_dns](#module\_cloudfront\_dns) | ../../modules/route53/cloudfront-record | n/a |
| <a name="module_cluster"></a> [cluster](#module\_cluster) | ../../modules/ecs-cluster | n/a |
| <a name="module_database_subnet"></a> [database\_subnet](#module\_database\_subnet) | ../../modules/vpc-private-subnet | n/a |
| <a name="module_db"></a> [db](#module\_db) | ../../modules/postgres | n/a |
| <a name="module_ecr"></a> [ecr](#module\_ecr) | ../../modules/ecr-repository | n/a |
| <a name="module_iam_app"></a> [iam\_app](#module\_iam\_app) | ../../modules/iam/user-with-access-key | n/a |
| <a name="module_lb"></a> [lb](#module\_lb) | ../../modules/lb/alb | n/a |
| <a name="module_private_subnet"></a> [private\_subnet](#module\_private\_subnet) | ../../modules/vpc-private-subnet | n/a |
| <a name="module_public_subnet"></a> [public\_subnet](#module\_public\_subnet) | ../../modules/vpc-public-subnet | n/a |
| <a name="module_secrets"></a> [secrets](#module\_secrets) | ../../modules/ssm/parameters | n/a |
| <a name="module_secrets_ci"></a> [secrets\_ci](#module\_secrets\_ci) | ../../modules/ssm/parameters | n/a |
| <a name="module_service"></a> [service](#module\_service) | ../../modules/ecs-service | n/a |
| <a name="module_service"></a> [service](#module\_service) | ../../modules/route53/load-balancer-record | n/a |
| <a name="module_ses"></a> [ses](#module\_ses) | ../../modules/ses | n/a |
| <a name="module_vpc"></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

Expand Down
23 changes: 23 additions & 0 deletions templates/production/acm.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
data "aws_route53_zone" "name" { # TODO adjust name to your project
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

in this case i think it is fine to call it "main"

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"
}
}
1 change: 0 additions & 1 deletion templates/production/ecr.tf
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,4 @@ module "ecr" {

output "url" {
value = module.ecr.url

}
10 changes: 10 additions & 0 deletions templates/production/ecs.tf
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
# }
10 changes: 10 additions & 0 deletions templates/production/iam.tf
Original file line number Diff line number Diff line change
@@ -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
}
41 changes: 41 additions & 0 deletions templates/production/networking.tf
Original file line number Diff line number Diff line change
Expand Up @@ -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 = ["/*"]
}
}
}
1 change: 0 additions & 1 deletion templates/production/rds.tf
Original file line number Diff line number Diff line change
Expand Up @@ -23,5 +23,4 @@ module "db" {
parameter_group_family = "postgres16"
engine_version = "16.1"
instance_class = "db.t4g.small"

}
16 changes: 16 additions & 0 deletions templates/production/route53.tf
Original file line number Diff line number Diff line change
@@ -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
}
29 changes: 29 additions & 0 deletions templates/production/s3.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
resource "random_id" "example" {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

change "example" to sth valid

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
}
20 changes: 20 additions & 0 deletions templates/production/secrets.tf
Original file line number Diff line number Diff line change
@@ -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"
}
Comment on lines +16 to +19
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove editables everywhere, let people mange via UI only

}
13 changes: 13 additions & 0 deletions templates/production/ses.tf
Original file line number Diff line number Diff line change
@@ -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 = [
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

production ses, should not have emails as a whitelist anyumore (staging should)

"your.name@example.com" # TODO adjust name to your project
]
}
Loading