Coder Social home page Coder Social logo

jimeh / terraform-cloudflare-email Goto Github PK

View Code? Open in Web Editor NEW
1.0 2.0 0.0 22 KB

Terraform module to configure various email related DNS records on Cloudflare.

Home Page: https://registry.terraform.io/modules/jimeh/email/cloudflare

License: MIT License

Makefile 0.56% HCL 94.59% JavaScript 3.91% Smarty 0.94%
cloudflare dmarc dmarc-record domainkeys email mta-sts mx mx-record spf terraform

terraform-cloudflare-email's Introduction

terraform-cloudflare-email

Terraform module to configure various email related DNS records on Cloudflare.

GitHub tag (latest SemVer) GitHub issues GitHub pull requests License Status

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.<your-domain>/.well-known/mta-sts.txt.
  • Configure domain key records (<selector>._domainkey.<your-domain>).

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 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 obviously

Also make sure you generate your own domain key from under Apps > Google Workspace > Gmail > Authenticate Email.

main.tf
module "email" {
  source  = "jimeh/email/cloudflare"
  version = "0.0.2"

  account_id = var.cloudflare_account_id
  zone_id    = var.cloudflare_zone_id

  mx = {
    "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 help article.

main.tf
module "email" {
  source  = "jimeh/email/cloudflare"
  version = "0.0.2"

  account_id = var.cloudflare_account_id
  zone_id    = var.cloudflare_zone_id

  mx = {
    "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 >= 3.0, < 5.0

Providers

Name Version
cloudflare >= 3.0, < 5.0

Modules

No modules.

Resources

Name Type
cloudflare_record.dmarc resource
cloudflare_record.domainkeys resource
cloudflare_record.mta-sts-a resource
cloudflare_record.mta-sts-aaaa resource
cloudflare_record.mta_sts resource
cloudflare_record.mx resource
cloudflare_record.smtp_tls resource
cloudflare_record.spf resource
cloudflare_worker_route.mta_sts_route resource
cloudflare_worker_script.mta_sts resource
cloudflare_workers_kv.mta_sts resource
cloudflare_workers_kv_namespace.mta_sts resource
cloudflare_zone.zone data source

Inputs

Name Description Type Default Required
account_id Cloudflare Account ID string n/a yes
dmarc_dkim_mode The DMARC DKIM mode for alignment (options: relaxed, strict). string "relaxed" no
dmarc_fo Failure reporting options for DMARC (characters: 0, 1, d, s, separated by :). string "1:d:s" no
dmarc_percent Percentage of messages to apply the DMARC policy to (0-100). number 100 no
dmarc_policy The DMARC policy to apply (options: none, quarantine, reject). string "none" no
dmarc_rua Where aggregate DMARC reports about policy violations should be sent. list(string) n/a yes
dmarc_ruf Where failure/forensic DMARC reports about policy violations should be sent. list(string) [] no
dmarc_spf_mode The DMARC SPF mode for alignment (options: relaxed, strict). string "relaxed" no
dmarc_ttl TTL for _dmarc DNS record. 1 is auto. Default is 1. number 1 no
domainkeys Map of domain keys with name, record type (TXT or CNAME), and value.
map(object({
type = string
value = string
}))
{} no
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 MTA policy mode, https://tools.ietf.org/html/rfc8461#section-5 string "testing" no
mta_sts_mx Additional permitted MX hosts for the MTA STS policy. list(string) [] no
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 List of sub-domains to also apply MX records to. list(string) [] no
record_ttl TTL for DNS records. 1 is auto. Default is 1. number 1 no
spf_terms List of SPF terms that should be included in the SPF TXT record. list(string)
[
"mx",
"a",
"~all"
]
no
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 Cloudflare Zone ID string n/a yes

Outputs

Name Description
mta_sts_policy_url URL to the MTA-STS policy file.

terraform-cloudflare-email's People

Contributors

github-actions[bot] avatar jimeh avatar

Stargazers

 avatar

Watchers

 avatar  avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.