Skip to content

Commit

Permalink
Merge pull request #355 from dasmeta/DMVP-5969
Browse files Browse the repository at this point in the history
feat(DMVP-5969): Add SES module
  • Loading branch information
aghamyan44 authored Nov 7, 2024
2 parents 44825ff + b7296eb commit 630e8e1
Show file tree
Hide file tree
Showing 12 changed files with 323 additions and 4 deletions.
6 changes: 3 additions & 3 deletions modules/efs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -101,17 +101,17 @@ resource "aws_kms_key" "key" {
| <a name="input_availability_zone_prefix"></a> [availability\_zone\_prefix](#input\_availability\_zone\_prefix) | Availability zone prefix, concat later to region code | `string` | `""` | no |
| <a name="input_creation_token"></a> [creation\_token](#input\_creation\_token) | Creation token, same as unique name | `string` | `"EFS-creation-token"` | no |
| <a name="input_egress_with_cidr_blocks"></a> [egress\_with\_cidr\_blocks](#input\_egress\_with\_cidr\_blocks) | Additional CIDR blocks for egress | `list(map(string))` | `[]` | no |
| <a name="input_encrypted"></a> [encrypted](#input\_encrypted) | Weather make encrypted or not | `bool` | `false` | no |
| <a name="input_encrypted"></a> [encrypted](#input\_encrypted) | Weather make encrypted or not | `bool` | `true` | no |
| <a name="input_ingress_with_cidr_blocks"></a> [ingress\_with\_cidr\_blocks](#input\_ingress\_with\_cidr\_blocks) | Additional CIDR blocks for ingress | `list(map(string))` | `[]` | no |
| <a name="input_kms_key_id"></a> [kms\_key\_id](#input\_kms\_key\_id) | AWS kms key arn | `string` | `null` | no |
| <a name="input_lifecycle_policy"></a> [lifecycle\_policy](#input\_lifecycle\_policy) | A block representing the lifecycle policy for the file system. | `any` | <pre>{<br/> "transition_to_archive": "AFTER_60_DAYS",<br/> "transition_to_ia": "AFTER_30_DAYS",<br/> "transition_to_primary_storage_class": null<br/>}</pre> | no |
| <a name="input_lifecycle_policy"></a> [lifecycle\_policy](#input\_lifecycle\_policy) | A block representing the lifecycle policy for the file system. | `any` | <pre>{<br> "transition_to_archive": "AFTER_60_DAYS",<br> "transition_to_ia": "AFTER_30_DAYS",<br> "transition_to_primary_storage_class": null<br>}</pre> | no |
| <a name="input_mount_target_subnets"></a> [mount\_target\_subnets](#input\_mount\_target\_subnets) | Subnet in which to create mount target | `list(string)` | `[]` | no |
| <a name="input_name"></a> [name](#input\_name) | EFS name | `string` | `"EFS"` | no |
| <a name="input_performance_mode"></a> [performance\_mode](#input\_performance\_mode) | Performance mode for EFS | `string` | `null` | no |
| <a name="input_provisioned_throughput_in_mibps"></a> [provisioned\_throughput\_in\_mibps](#input\_provisioned\_throughput\_in\_mibps) | Throughput mibps for EFS, Only compliant when throughput mode is set to provisioned | `string` | `null` | no |
| <a name="input_security_group_description"></a> [security\_group\_description](#input\_security\_group\_description) | Security group description for EFS | `string` | `""` | no |
| <a name="input_security_group_name"></a> [security\_group\_name](#input\_security\_group\_name) | Security group name for EFS | `string` | `""` | no |
| <a name="input_tags"></a> [tags](#input\_tags) | n/a | `map(any)` | <pre>{<br/> "Provisioner": "DasMeta"<br/>}</pre> | no |
| <a name="input_tags"></a> [tags](#input\_tags) | n/a | `map(any)` | <pre>{<br> "Provisioner": "DasMeta"<br>}</pre> | no |
| <a name="input_throughput_mode"></a> [throughput\_mode](#input\_throughput\_mode) | Throughput mode for the file system. Valid values: bursting, provisioned, or elastic. When using 'provisioned', also set 'provisioned\_throughput\_in\_mibps'. | `string` | `"elastic"` | no |
| <a name="input_vpc_id"></a> [vpc\_id](#input\_vpc\_id) | VPC ID to which EFS will have access | `string` | `""` | no |

Expand Down
2 changes: 1 addition & 1 deletion modules/efs/variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ variable "availability_zone_prefix" {
variable "encrypted" {
description = "Weather make encrypted or not"
type = bool
default = false
default = true
}

variable "kms_key_id" {
Expand Down
58 changes: 58 additions & 0 deletions modules/ses/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
# ses

<!-- BEGINNING OF PRE-COMMIT-TERRAFORM DOCS HOOK -->
## Requirements

No requirements.

## Providers

| Name | Version |
|------|---------|
| <a name="provider_aws"></a> [aws](#provider\_aws) | n/a |

## Modules

No modules.

## Resources

| Name | Type |
|------|------|
| [aws_iam_access_key.ses_user](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_access_key) | resource |
| [aws_iam_group.ses_group](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_group) | resource |
| [aws_iam_group_membership.ses_user_group](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_group_membership) | resource |
| [aws_iam_group_policy.ses_group_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_group_policy) | resource |
| [aws_iam_user.ses_user](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_user) | resource |
| [aws_route53_record.dkim](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/route53_record) | resource |
| [aws_route53_record.spf](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/route53_record) | resource |
| [aws_ses_domain_dkim.ses_domain](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ses_domain_dkim) | resource |
| [aws_ses_domain_identity.ses_domain](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ses_domain_identity) | resource |
| [aws_ses_domain_identity.verified_domains](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ses_domain_identity) | resource |
| [aws_ses_email_identity.verified_email](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ses_email_identity) | resource |
| [aws_caller_identity.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/caller_identity) | data source |
| [aws_iam_policy_document.ses_policy](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.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/route53_zone) | data source |

## Inputs

| Name | Description | Type | Default | Required |
|------|-------------|------|---------|:--------:|
| <a name="input_create_dkim_route53"></a> [create\_dkim\_route53](#input\_create\_dkim\_route53) | If DKIM records should be created in Route 53 | `bool` | `false` | no |
| <a name="input_create_spf_route53"></a> [create\_spf\_route53](#input\_create\_spf\_route53) | If TXT record for SPF should be created in Route 53 | `bool` | `false` | no |
| <a name="input_email_domain"></a> [email\_domain](#input\_email\_domain) | For which sender domain SES should be configured. | `string` | n/a | yes |
| <a name="input_mail_users"></a> [mail\_users](#input\_mail\_users) | User names for mail to create. | `list(string)` | n/a | yes |
| <a name="input_prefix"></a> [prefix](#input\_prefix) | Prefix for ses greoup be unique. | `string` | `""` | no |
| <a name="input_region"></a> [region](#input\_region) | The region where ressources should be managed. | `string` | `null` | no |
| <a name="input_verified_domains"></a> [verified\_domains](#input\_verified\_domains) | The domain name to assign to SES. | `list(string)` | `[]` | no |
| <a name="input_verified_email_users"></a> [verified\_email\_users](#input\_verified\_email\_users) | The emails address to assign to SES. | `list(string)` | `[]` | no |

## Outputs

| Name | Description |
|------|-------------|
| <a name="output_dkim_records"></a> [dkim\_records](#output\_dkim\_records) | DNS records for DKIM |
| <a name="output_secret_keys"></a> [secret\_keys](#output\_secret\_keys) | IAM Access Key ID and Secret |
| <a name="output_smtp_credentials"></a> [smtp\_credentials](#output\_smtp\_credentials) | SMTP Username and Passwort |
<!-- END OF PRE-COMMIT-TERRAFORM DOCS HOOK -->
40 changes: 40 additions & 0 deletions modules/ses/iam.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
data "aws_caller_identity" "current" {}
data "aws_region" "current" {}

data "aws_iam_policy_document" "ses_policy" {
statement {
actions = ["ses:SendEmail", "ses:SendRawEmail"]
effect = "Allow"
resources = [
"arn:aws:ses:${local.region}:${data.aws_caller_identity.current.account_id}:identity/*"
]
}
}

resource "aws_iam_group" "ses_group" {
name = "${var.prefix}ses_users"
path = "/"
}

resource "aws_iam_user" "ses_user" {
count = length(var.mail_users)
name = "ses_${var.mail_users[count.index]}"
path = "/"
}

resource "aws_iam_group_membership" "ses_user_group" {
name = "SES users"
users = aws_iam_user.ses_user[*].name
group = aws_iam_group.ses_group.name
}

resource "aws_iam_group_policy" "ses_group_policy" {
name = "sendMailSES"
group = aws_iam_group.ses_group.name
policy = data.aws_iam_policy_document.ses_policy.json
}

resource "aws_iam_access_key" "ses_user" {
count = length(var.mail_users)
user = aws_iam_user.ses_user[count.index].name
}
24 changes: 24 additions & 0 deletions modules/ses/locals.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
locals {
dkim_record_0 = {
name : "${aws_ses_domain_dkim.ses_domain.dkim_tokens[0]}._domainkey.${var.email_domain}."
record : "${aws_ses_domain_dkim.ses_domain.dkim_tokens[0]}.dkim.amazonses.com."
type : "CNAME"
}
dkim_record_1 = {
name : "${aws_ses_domain_dkim.ses_domain.dkim_tokens[1]}._domainkey.${var.email_domain}."
record : "${aws_ses_domain_dkim.ses_domain.dkim_tokens[1]}.dkim.amazonses.com."
type : "CNAME"
}
dkim_record_2 = {
name : "${aws_ses_domain_dkim.ses_domain.dkim_tokens[2]}._domainkey.${var.email_domain}."
record : "${aws_ses_domain_dkim.ses_domain.dkim_tokens[2]}.dkim.amazonses.com."
type : "CNAME"
}

region = var.region == null ? data.aws_region.current.name : var.region
}

data "aws_route53_zone" "this" {
count = anytrue([var.create_spf_route53, var.create_dkim_route53]) ? 1 : 0
name = var.email_domain
}
35 changes: 35 additions & 0 deletions modules/ses/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
resource "aws_ses_email_identity" "verified_email" {
for_each = { for value in var.verified_email_users : value => value }
email = each.value
}

resource "aws_ses_domain_identity" "verified_domains" {
for_each = { for value in var.verified_domains : value => value }
domain = each.value
}

resource "aws_ses_domain_identity" "ses_domain" {
domain = var.email_domain
}

resource "aws_ses_domain_dkim" "ses_domain" {
domain = var.email_domain
}

resource "aws_route53_record" "spf" {
count = var.create_spf_route53 ? 1 : 0
zone_id = data.aws_route53_zone.this[0].zone_id
name = ""
type = "TXT"
records = ["v=spf1 include:amazonses.com ~all"]
ttl = 600
}

resource "aws_route53_record" "dkim" {
count = var.create_dkim_route53 ? 3 : 0
zone_id = data.aws_route53_zone.this[0].zone_id
name = "${element(aws_ses_domain_dkim.ses_domain.dkim_tokens, count.index)}._domainkey.${var.email_domain}"
type = "CNAME"
ttl = 600
records = ["${element(aws_ses_domain_dkim.ses_domain.dkim_tokens, count.index)}.dkim.amazonses.com"]
}
27 changes: 27 additions & 0 deletions modules/ses/ouputs.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
output "dkim_records" {
description = "DNS records for DKIM"
value = [local.dkim_record_0, local.dkim_record_1, local.dkim_record_2]
}

output "smtp_credentials" {
value = { for k, v in aws_iam_access_key.ses_user : k =>
{
user = v.user,
password = v.ses_smtp_password_v4
}
}
description = "SMTP Username and Passwort"
sensitive = true
}

output "secret_keys" {
value = { for v in aws_iam_access_key.ses_user : v.user =>
{
user = v.user,
id = v.id
secret = v.secret
}
}
description = "IAM Access Key ID and Secret"
sensitive = true
}
29 changes: 29 additions & 0 deletions modules/ses/tests/basic/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# basic

<!-- BEGINNING OF PRE-COMMIT-TERRAFORM DOCS HOOK -->
## Requirements

No requirements.

## Providers

No providers.

## Modules

| Name | Source | Version |
|------|--------|---------|
| <a name="module_ses"></a> [ses](#module\_ses) | ../../ | n/a |

## Resources

No resources.

## Inputs

No inputs.

## Outputs

No outputs.
<!-- END OF PRE-COMMIT-TERRAFORM DOCS HOOK -->
6 changes: 6 additions & 0 deletions modules/ses/tests/basic/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
module "ses" {
source = "../../"
email_domain = "devops.dasmeta.com"
mail_users = ["prod"]
verified_domains = ["devops.dasmeta.com"]
}
30 changes: 30 additions & 0 deletions modules/ses/tests/multiple/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# multiple

<!-- BEGINNING OF PRE-COMMIT-TERRAFORM DOCS HOOK -->
## Requirements

No requirements.

## Providers

No providers.

## Modules

| Name | Source | Version |
|------|--------|---------|
| <a name="module_ses"></a> [ses](#module\_ses) | ../../ | n/a |
| <a name="module_ses-virginia"></a> [ses-virginia](#module\_ses-virginia) | ../../ | n/a |

## Resources

No resources.

## Inputs

No inputs.

## Outputs

No outputs.
<!-- END OF PRE-COMMIT-TERRAFORM DOCS HOOK -->
25 changes: 25 additions & 0 deletions modules/ses/tests/multiple/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
module "ses" {
source = "../../"
email_domain = "devops.dasmeta.com"
mail_users = ["prod"]
verified_domains = ["devops.dasmeta.com"]
}

module "ses-virginia" {
source = "../../"
email_domain = "devops.dasmeta.com"
mail_users = ["prod-virginia"]
verified_domains = ["devops.dasmeta.com"]
region = "us-east-1"
prefix = "virginia"

providers = {
aws = aws.virginia # Explicitly pass the AWS provider
}
}


provider "aws" {
region = "us-east-1" # Specify the desired AWS region here
alias = "virginia"
}
45 changes: 45 additions & 0 deletions modules/ses/variables.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
variable "region" {
type = string
description = "The region where ressources should be managed."
default = null
}

variable "email_domain" {
type = string
description = "For which sender domain SES should be configured."
}

variable "prefix" {
type = string
description = "Prefix for ses greoup be unique."
default = ""
}

variable "mail_users" {
type = list(string)
description = "User names for mail to create."
}

variable "create_dkim_route53" {
type = bool
description = "If DKIM records should be created in Route 53"
default = false
}

variable "create_spf_route53" {
type = bool
description = "If TXT record for SPF should be created in Route 53"
default = false
}

variable "verified_email_users" {
type = list(string)
default = []
description = "The emails address to assign to SES."
}

variable "verified_domains" {
type = list(string)
default = []
description = "The domain name to assign to SES."
}

0 comments on commit 630e8e1

Please sign in to comment.