Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/jimeh/terraform-cloudflare-email
Terraform module to configure various email related DNS records on Cloudflare.
https://github.com/jimeh/terraform-cloudflare-email
cloudflare dmarc dmarc-record domainkeys email mta-sts mx mx-record spf terraform terraform-module
Last synced: 6 days ago
JSON representation
Terraform module to configure various email related DNS records on Cloudflare.
- Host: GitHub
- URL: https://github.com/jimeh/terraform-cloudflare-email
- Owner: jimeh
- License: mit
- Created: 2023-04-25T23:59:37.000Z (over 1 year ago)
- Default Branch: main
- Last Pushed: 2023-04-26T01:48:47.000Z (over 1 year ago)
- Last Synced: 2024-12-09T10:48:27.778Z (13 days ago)
- Topics: cloudflare, dmarc, dmarc-record, domainkeys, email, mta-sts, mx, mx-record, spf, terraform, terraform-module
- Language: HCL
- Homepage: https://registry.terraform.io/modules/jimeh/email/cloudflare
- Size: 21.5 KB
- Stars: 2
- Watchers: 3
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- License: LICENSE
Awesome Lists containing this project
README
terraform-cloudflare-email
Terraform module to configure various email related DNS records on
Cloudflare.
Module that configures various email related DNS records on Cloudflare,
including serving a MTA-STS policy text file via Cloudflare Workers.## Features
- Configure MX records.
- Configure SPF record.
- Configure DMARC record.
- Configure SMTP TLS reporting record.
- Configure MTA-STS record, generate `mta-sts.txt` policy file and serve it with
a Cloudflare Worker on
`https://mta-sts./.well-known/mta-sts.txt`.
- Configure domain key records (`._domainkey.`).## Example Usage
Examples assume that you have the following variables setup:
- `cloudflare_account_id` — Your Account ID.
- `cloudflare_zone_id` — ID of the Zone (domain name).
- `cloudflare_zone_name` — Domain name, e.g. `foobar.com`.Adjust examples as needed to fit your setup.
### Google Workspace
Below example is based on the
[DNS Basics](https://support.google.com/a/answer/48090?hl=en) support article.
When going through the domain setup wizard within the Google Workspace Admin,
you are likely to be given a slightly different list of MX records, and
obviouslyAlso make sure you generate your own domain key from under Apps > Google
Workspace > Gmail > Authenticate Email.
main.tf
```terraform
module "email" {
source = "jimeh/email/cloudflare"
version = "0.0.2"account_id = var.cloudflare_account_id
zone_id = var.cloudflare_zone_idmx = {
"aspmx.l.google.com" = 1
"alt1.aspmx.l.google.com" = 5
"alt2.aspmx.l.google.com" = 5
"aspmx2.googlemail.com" = 10
"aspmx3.googlemail.com" = 10
}spf_terms = [
"include:_spf.google.com",
"~all",
]mta_sts_mode = "enforce"
mta_sts_max_age = 86400
mta_sts_mx = [
"*.aspmx.l.google.com",
"*.googlemail.com",
"aspmx.l.google.com",
]tlsrpt_rua = [
"mailto:tls-report@${var.cloudflare_zone_name}",
]dmarc_policy = "reject"
dmarc_rua = [
"mailto:dmarc-report@${var.cloudflare_zone_name}",
]domainkeys = {
"google" = {
type = "TXT"
value = join("", [
# TODO: Replace this example key with a real one.
"v=DKIM1; k=rsa; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEApAVNwJ9",
"+6ArXN23ZaR8SFSYxVEEbbHRZplZqHVt6uEpcirY+jxHOqV2bvqAY3BHZQs/KoHnFSWUf",
"6zv6ajZgUxvU65UhCbrQ7CwrJCjU8sQFDk+CpbvmXyJIe9G470HuGEs4NmQDoddJZr09V",
"7d3anX8n7ePSCsIxwGi53DMhwijQXqHYMFALml+QIMZ/03ydL6/B3EwDNDFSBSEqzt2QS",
"N43EYb3FlUiGu5NGHl3gibEsbywTmGtN3kmkp/rxqaJPLv16NVpTe+0lAqPiq/pgJT4pp",
"ACz2ENh6BD0H+hDiCKBiw+gyAeDbOn1c5yslENSEyDxqpn17tnxo+O/ZFmwIDAQAB"
])
}
}
}resource "cloudflare_record" "cname" {
for_each = {
"mail" = { value = "ghs.googlehosted.com", proxied = false }
}name = lookup(each.value, "name", each.key)
proxied = lookup(each.value, "proxied", false)
ttl = lookup(each.value, "ttl", 1)
type = "CNAME"
value = each.value.value
zone_id = var.cloudflare_zone_id
}resource "cloudflare_record" "txt" {
for_each = {
"google" = {
value = (
"google-site-verification=__REPLACE_ME_WITH_A_REAL_VALUE__"
)
}
}name = lookup(each.value, "name", local.zone_name)
proxied = lookup(each.value, "proxied", false)
ttl = lookup(each.value, "ttl", 1)
type = "TXT"
value = each.value.value
zone_id = var.cloudflare_zone_id
}
```### Fastmail
The below example is based on Fastmail's
[Manual DNS configuration](https://www.fastmail.help/hc/en-us/articles/360060591153-Manual-DNS-configuration)
help article.
main.tf
```terraform
module "email" {
source = "jimeh/email/cloudflare"
version = "0.0.2"account_id = var.cloudflare_account_id
zone_id = var.cloudflare_zone_idmx = {
"in1-smtp.messagingengine.com" = 10
"in2-smtp.messagingengine.com" = 20
}
mx_subdomains = ["*"]spf_terms = [
"include:spf.messagingengine.com",
"?all"
]mta_sts_mode = "enforce"
mta_sts_max_age = 86400
mta_sts_mx = [
"in1-smtp.messagingengine.com",
"in2-smtp.messagingengine.com",
]tlsrpt_rua = [
"mailto:tls-report@${var.cloudflare_zone_name}",
]dmarc_policy = "reject"
dmarc_rua = [
"mailto:dmarc-report@${var.cloudflare_zone_name}",
]domainkeys = {
"fm1" = {
type = "CNAME"
value = "fm1.${var.cloudflare_zone_name}.dkim.fmhosted.com"
}
"fm2" = {
type = "CNAME"
value = "fm2.${var.cloudflare_zone_name}.dkim.fmhosted.com"
}
"fm3" = {
type = "CNAME"
value = "fm3.${var.cloudflare_zone_name}.dkim.fmhosted.com"
}
"mesmtp" = {
type = "CNAME"
value = "mesmtp.${var.cloudflare_zone_name}.dkim.fmhosted.com"
}
}
}resource "cloudflare_record" "srv" {
for_each = {
"_caldav._tcp" = {}
"_caldavs._tcp" = {
port = 433
target = "caldav.fastmail.com"
weight = 1
}
"_carddav._tcp" = {}
"_carddavs._tcp" = {
port = 443
target = "carddav.fastmail.com"
weight = 1
}
"_imap._tcp" = {}
"_imaps._tcp" = {
port = 993
target = "imap.fastmail.com"
weight = 1
}
"_jmap._tcp" = {
port = 443
target = "jmap.fastmail.com"
weight = 1
}
"_pop3._tcp" = {}
"_pop3s._tcp" = {
port = 995
priority = 10
target = "pop.fastmail.com"
weight = 1
}
"_submission._tcp" = {
port = 587
target = "smtp.fastmail.com"
weight = 1
}
}name = lookup(each.value, "name", each.key)
proxied = lookup(each.value, "proxied", false)
ttl = lookup(each.value, "ttl", 1)
type = "SRV"
zone_id = var.cloudflare_zone_id
data {
name = var.cloudflare_zone_name
port = lookup(each.value, "port", 0)
priority = lookup(each.value, "priority", 0)
proto = split(".", each.key)[1]
service = split(".", each.key)[0]
target = lookup(each.value, "target", ".")
weight = lookup(each.value, "weight", 0)
}
}
```## Requirements
| Name | Version |
| --------------------------------------------------------------------------- | ------------- |
| [cloudflare](#requirement_cloudflare) | >= 3.0, < 5.0 |## Providers
| Name | Version |
| --------------------------------------------------------------------- | ------------- |
| [cloudflare](#provider_cloudflare) | >= 3.0, < 5.0 |## Modules
No modules.
## Resources
| Name | Type |
| --------------------------------------------------------------------------------------------------------------------------------------------------- | ----------- |
| [cloudflare_record.dmarc](https://registry.terraform.io/providers/cloudflare/cloudflare/latest/docs/resources/record) | resource |
| [cloudflare_record.domainkeys](https://registry.terraform.io/providers/cloudflare/cloudflare/latest/docs/resources/record) | resource |
| [cloudflare_record.mta-sts-a](https://registry.terraform.io/providers/cloudflare/cloudflare/latest/docs/resources/record) | resource |
| [cloudflare_record.mta-sts-aaaa](https://registry.terraform.io/providers/cloudflare/cloudflare/latest/docs/resources/record) | resource |
| [cloudflare_record.mta_sts](https://registry.terraform.io/providers/cloudflare/cloudflare/latest/docs/resources/record) | resource |
| [cloudflare_record.mx](https://registry.terraform.io/providers/cloudflare/cloudflare/latest/docs/resources/record) | resource |
| [cloudflare_record.smtp_tls](https://registry.terraform.io/providers/cloudflare/cloudflare/latest/docs/resources/record) | resource |
| [cloudflare_record.spf](https://registry.terraform.io/providers/cloudflare/cloudflare/latest/docs/resources/record) | resource |
| [cloudflare_worker_route.mta_sts_route](https://registry.terraform.io/providers/cloudflare/cloudflare/latest/docs/resources/worker_route) | resource |
| [cloudflare_worker_script.mta_sts](https://registry.terraform.io/providers/cloudflare/cloudflare/latest/docs/resources/worker_script) | resource |
| [cloudflare_workers_kv.mta_sts](https://registry.terraform.io/providers/cloudflare/cloudflare/latest/docs/resources/workers_kv) | resource |
| [cloudflare_workers_kv_namespace.mta_sts](https://registry.terraform.io/providers/cloudflare/cloudflare/latest/docs/resources/workers_kv_namespace) | resource |
| [cloudflare_zone.zone](https://registry.terraform.io/providers/cloudflare/cloudflare/latest/docs/data-sources/zone) | data source |## Inputs
| Name | Description | Type | Default | Required |
| ------------------------------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------- | ----------------------------------------------- | :------: |
| [account_id](#input_account_id) | Cloudflare Account ID | `string` | n/a | yes |
| [dmarc_dkim_mode](#input_dmarc_dkim_mode) | The DMARC DKIM mode for alignment (options: `relaxed`, `strict`). | `string` | `"relaxed"` | no |
| [dmarc_fo](#input_dmarc_fo) | Failure reporting options for DMARC (characters: `0`, `1`, `d`, `s`, separated by `:`). | `string` | `"1:d:s"` | no |
| [dmarc_percent](#input_dmarc_percent) | Percentage of messages to apply the DMARC policy to (0-100). | `number` | `100` | no |
| [dmarc_policy](#input_dmarc_policy) | The DMARC policy to apply (options: `none`, `quarantine`, `reject`). | `string` | `"none"` | no |
| [dmarc_rua](#input_dmarc_rua) | Where aggregate DMARC reports about policy violations should be sent. | `list(string)` | n/a | yes |
| [dmarc_ruf](#input_dmarc_ruf) | Where failure/forensic DMARC reports about policy violations should be sent. | `list(string)` | `[]` | no |
| [dmarc_spf_mode](#input_dmarc_spf_mode) | The DMARC SPF mode for alignment (options: `relaxed`, `strict`). | `string` | `"relaxed"` | no |
| [dmarc_ttl](#input_dmarc_ttl) | TTL for `_dmarc` DNS record. `1` is auto. Default is `1`. | `number` | `1` | no |
| [domainkeys](#input_domainkeys) | Map of domain keys with name, record type (`TXT` or `CNAME`), and value. |map(object({| `{}` | no |
type = string
value = string
}))
| [mta_sts_max_age](#input_mta_sts_max_age) | Maximum lifetime of the policy in seconds, up to 31557600, defaults to 604800 (1 week) | `number` | `604800` | no |
| [mta_sts_mode](#input_mta_sts_mode) | MTA policy mode, https://tools.ietf.org/html/rfc8461#section-5 | `string` | `"testing"` | no |
| [mta_sts_mx](#input_mta_sts_mx) | Additional permitted MX hosts for the MTA STS policy. | `list(string)` | `[]` | no |
| [mx](#input_mx) | A map representing the MX records. Key is the mail server hostname and value is the priority. | `map(number)` | n/a | yes |
| [mx_subdomains](#input_mx_subdomains) | List of sub-domains to also apply MX records to. | `list(string)` | `[]` | no |
| [record_ttl](#input_record_ttl) | TTL for DNS records. `1` is auto. Default is `1`. | `number` | `1` | no |
| [spf_terms](#input_spf_terms) | List of SPF terms that should be included in the SPF TXT record. | `list(string)` |[| no |
"mx",
"a",
"~all"
]
| [tlsrpt_rua](#input_tlsrpt_rua) | Locations to which aggregate TLS SMTP reports about policy violations should be sent, either `mailto:` or `https:` schema. | `list(string)` | n/a | yes |
| [zone_id](#input_zone_id) | Cloudflare Zone ID | `string` | n/a | yes |## Outputs
| Name | Description |
| ----------------------------------------------------------------------------------------- | ------------------------------- |
| [mta_sts_policy_url](#output_mta_sts_policy_url) | URL to the MTA-STS policy file. |