mirror of
https://github.com/jimeh/terraform-cloudflare-email.git
synced 2026-02-19 01:46:40 +00:00
feat!: upgrade to Cloudflare provider v5
The Cloudflare Terraform provider v5 is a ground-up rewrite with renamed resources, changed attributes, and a new worker deployment model. This is a breaking change requiring provider v5.x. Resource migrations: - cloudflare_record → cloudflare_dns_record (all 8 DNS records) - value → content on all DNS records - cloudflare_worker_script → cloudflare_worker + cloudflare_worker_version + cloudflare_workers_deployment (new 3-resource pattern) - cloudflare_worker_route → cloudflare_workers_route, script_name → script - cloudflare_workers_kv key → key_name - data.cloudflare_zone: dropped account_id (no longer top-level in v5) - smtp_tls record: added required ttl attribute - mta-sts.js: converted from Service Worker to ES module format State migration: - moved blocks handle DNS record and route renames automatically - Worker script (1→3 resources) requires manual state rm of the old cloudflare_worker_script resource BREAKING CHANGE: Requires Cloudflare provider >= 5.0, < 6.0 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
26
README.md
26
README.md
@@ -282,13 +282,13 @@ resource "cloudflare_record" "srv" {
|
||||
| Name | Version |
|
||||
|------|---------|
|
||||
| <a name="requirement_terraform"></a> [terraform](#requirement\_terraform) | >= 1.1 |
|
||||
| <a name="requirement_cloudflare"></a> [cloudflare](#requirement\_cloudflare) | >= 3.0, < 5.0 |
|
||||
| <a name="requirement_cloudflare"></a> [cloudflare](#requirement\_cloudflare) | >= 5.0, < 6.0 |
|
||||
|
||||
## Providers
|
||||
|
||||
| Name | Version |
|
||||
|------|---------|
|
||||
| <a name="provider_cloudflare"></a> [cloudflare](#provider\_cloudflare) | >= 3.0, < 5.0 |
|
||||
| <a name="provider_cloudflare"></a> [cloudflare](#provider\_cloudflare) | >= 5.0, < 6.0 |
|
||||
|
||||
## Modules
|
||||
|
||||
@@ -298,18 +298,20 @@ No modules.
|
||||
|
||||
| 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_dns_record.dmarc](https://registry.terraform.io/providers/cloudflare/cloudflare/latest/docs/resources/dns_record) | resource |
|
||||
| [cloudflare_dns_record.domainkeys](https://registry.terraform.io/providers/cloudflare/cloudflare/latest/docs/resources/dns_record) | resource |
|
||||
| [cloudflare_dns_record.mta-sts-a](https://registry.terraform.io/providers/cloudflare/cloudflare/latest/docs/resources/dns_record) | resource |
|
||||
| [cloudflare_dns_record.mta-sts-aaaa](https://registry.terraform.io/providers/cloudflare/cloudflare/latest/docs/resources/dns_record) | resource |
|
||||
| [cloudflare_dns_record.mta_sts](https://registry.terraform.io/providers/cloudflare/cloudflare/latest/docs/resources/dns_record) | resource |
|
||||
| [cloudflare_dns_record.mx](https://registry.terraform.io/providers/cloudflare/cloudflare/latest/docs/resources/dns_record) | resource |
|
||||
| [cloudflare_dns_record.smtp_tls](https://registry.terraform.io/providers/cloudflare/cloudflare/latest/docs/resources/dns_record) | resource |
|
||||
| [cloudflare_dns_record.spf](https://registry.terraform.io/providers/cloudflare/cloudflare/latest/docs/resources/dns_record) | resource |
|
||||
| [cloudflare_worker.mta_sts](https://registry.terraform.io/providers/cloudflare/cloudflare/latest/docs/resources/worker) | resource |
|
||||
| [cloudflare_worker_version.mta_sts](https://registry.terraform.io/providers/cloudflare/cloudflare/latest/docs/resources/worker_version) | resource |
|
||||
| [cloudflare_workers_deployment.mta_sts](https://registry.terraform.io/providers/cloudflare/cloudflare/latest/docs/resources/workers_deployment) | 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_workers_route.mta_sts_route](https://registry.terraform.io/providers/cloudflare/cloudflare/latest/docs/resources/workers_route) | resource |
|
||||
| [cloudflare_zone.zone](https://registry.terraform.io/providers/cloudflare/cloudflare/latest/docs/data-sources/zone) | data source |
|
||||
|
||||
## Inputs
|
||||
|
||||
88
main.tf
88
main.tf
@@ -3,8 +3,7 @@
|
||||
#
|
||||
|
||||
data "cloudflare_zone" "zone" {
|
||||
account_id = var.account_id
|
||||
zone_id = var.zone_id
|
||||
zone_id = var.zone_id
|
||||
}
|
||||
|
||||
locals {
|
||||
@@ -31,7 +30,7 @@ locals {
|
||||
}
|
||||
}
|
||||
|
||||
resource "cloudflare_record" "mx" {
|
||||
resource "cloudflare_dns_record" "mx" {
|
||||
for_each = local.mx_records
|
||||
|
||||
name = each.value.name
|
||||
@@ -39,7 +38,7 @@ resource "cloudflare_record" "mx" {
|
||||
proxied = false
|
||||
ttl = var.record_ttl
|
||||
type = "MX"
|
||||
value = each.value.mx
|
||||
content = each.value.mx
|
||||
zone_id = var.zone_id
|
||||
}
|
||||
|
||||
@@ -47,12 +46,12 @@ resource "cloudflare_record" "mx" {
|
||||
# SPF
|
||||
#
|
||||
|
||||
resource "cloudflare_record" "spf" {
|
||||
resource "cloudflare_dns_record" "spf" {
|
||||
name = local.zone_name
|
||||
proxied = false
|
||||
ttl = var.record_ttl
|
||||
type = "TXT"
|
||||
value = join(" ", concat(["v=spf1"], var.spf_terms))
|
||||
content = join(" ", concat(["v=spf1"], var.spf_terms))
|
||||
zone_id = var.zone_id
|
||||
}
|
||||
|
||||
@@ -60,10 +59,11 @@ resource "cloudflare_record" "spf" {
|
||||
# TLS SMTP
|
||||
#
|
||||
|
||||
resource "cloudflare_record" "smtp_tls" {
|
||||
resource "cloudflare_dns_record" "smtp_tls" {
|
||||
name = "_smtp._tls"
|
||||
ttl = var.record_ttl
|
||||
type = "TXT"
|
||||
value = "v=TLSRPTv1; rua=${join(",", var.tlsrpt_rua)}"
|
||||
content = "v=TLSRPTv1; rua=${join(",", var.tlsrpt_rua)}"
|
||||
zone_id = var.zone_id
|
||||
}
|
||||
|
||||
@@ -77,32 +77,33 @@ locals {
|
||||
max_age = var.mta_sts_max_age
|
||||
mx = sort(distinct(concat(keys(var.mx), var.mta_sts_mx)))
|
||||
})
|
||||
policy_sha = sha1(local.policy)
|
||||
policy_sha = sha1(local.policy)
|
||||
worker_name = "mta-sts-${replace(local.zone_name, "/[^A-Za-z0-9-]/", "-")}"
|
||||
}
|
||||
|
||||
resource "cloudflare_record" "mta-sts-a" {
|
||||
resource "cloudflare_dns_record" "mta-sts-a" {
|
||||
name = "mta-sts"
|
||||
proxied = true
|
||||
ttl = var.record_ttl
|
||||
type = "A"
|
||||
value = "192.0.2.1"
|
||||
content = "192.0.2.1"
|
||||
zone_id = var.zone_id
|
||||
}
|
||||
|
||||
resource "cloudflare_record" "mta-sts-aaaa" {
|
||||
resource "cloudflare_dns_record" "mta-sts-aaaa" {
|
||||
name = "mta-sts"
|
||||
proxied = true
|
||||
ttl = var.record_ttl
|
||||
type = "AAAA"
|
||||
value = "100::"
|
||||
content = "100::"
|
||||
zone_id = var.zone_id
|
||||
}
|
||||
|
||||
resource "cloudflare_record" "mta_sts" {
|
||||
resource "cloudflare_dns_record" "mta_sts" {
|
||||
name = "_mta-sts"
|
||||
ttl = var.record_ttl
|
||||
type = "TXT"
|
||||
value = "v=STSv1; id=${local.policy_sha}"
|
||||
content = "v=STSv1; id=${local.policy_sha}"
|
||||
zone_id = var.zone_id
|
||||
}
|
||||
|
||||
@@ -113,26 +114,49 @@ resource "cloudflare_workers_kv_namespace" "mta_sts" {
|
||||
|
||||
resource "cloudflare_workers_kv" "mta_sts" {
|
||||
namespace_id = cloudflare_workers_kv_namespace.mta_sts.id
|
||||
key = "mta-sts.txt"
|
||||
key_name = "mta-sts.txt"
|
||||
value = local.policy
|
||||
account_id = var.account_id
|
||||
}
|
||||
|
||||
resource "cloudflare_worker_script" "mta_sts" {
|
||||
name = "mta-sts-${replace(local.zone_name, "/[^A-Za-z0-9-]/", "-")}"
|
||||
content = file("${path.module}/mta-sts.js")
|
||||
resource "cloudflare_worker" "mta_sts" {
|
||||
account_id = var.account_id
|
||||
|
||||
kv_namespace_binding {
|
||||
name = "FILES"
|
||||
namespace_id = cloudflare_workers_kv_namespace.mta_sts.id
|
||||
}
|
||||
name = local.worker_name
|
||||
}
|
||||
|
||||
resource "cloudflare_worker_route" "mta_sts_route" {
|
||||
pattern = "mta-sts.${local.zone_name}/*"
|
||||
script_name = cloudflare_worker_script.mta_sts.name
|
||||
zone_id = var.zone_id
|
||||
resource "cloudflare_worker_version" "mta_sts" {
|
||||
account_id = var.account_id
|
||||
worker_id = cloudflare_worker.mta_sts.name
|
||||
|
||||
main_module = "mta-sts.js"
|
||||
modules = [{
|
||||
name = "mta-sts.js"
|
||||
content_file = "${path.module}/mta-sts.js"
|
||||
content_type = "application/javascript+module"
|
||||
}]
|
||||
|
||||
bindings = [{
|
||||
name = "FILES"
|
||||
type = "kv_namespace"
|
||||
namespace_id = cloudflare_workers_kv_namespace.mta_sts.id
|
||||
}]
|
||||
}
|
||||
|
||||
resource "cloudflare_workers_deployment" "mta_sts" {
|
||||
account_id = var.account_id
|
||||
script_name = cloudflare_worker.mta_sts.name
|
||||
strategy = "percentage"
|
||||
|
||||
versions = [{
|
||||
percentage = 100
|
||||
version_id = cloudflare_worker_version.mta_sts.id
|
||||
}]
|
||||
}
|
||||
|
||||
resource "cloudflare_workers_route" "mta_sts_route" {
|
||||
pattern = "mta-sts.${local.zone_name}/*"
|
||||
script = cloudflare_worker.mta_sts.name
|
||||
zone_id = var.zone_id
|
||||
}
|
||||
|
||||
#
|
||||
@@ -150,12 +174,12 @@ locals {
|
||||
}
|
||||
}
|
||||
|
||||
resource "cloudflare_record" "dmarc" {
|
||||
resource "cloudflare_dns_record" "dmarc" {
|
||||
name = "_dmarc"
|
||||
proxied = false
|
||||
ttl = floor(var.dmarc_ttl)
|
||||
type = "TXT"
|
||||
value = join(" ", flatten([
|
||||
content = join(" ", flatten([
|
||||
"v=DMARC1;",
|
||||
"p=${var.dmarc_policy};",
|
||||
"pct=${floor(var.dmarc_percent)};",
|
||||
@@ -177,13 +201,13 @@ resource "cloudflare_record" "dmarc" {
|
||||
# Domain Keys (DKIM)
|
||||
#
|
||||
|
||||
resource "cloudflare_record" "domainkeys" {
|
||||
resource "cloudflare_dns_record" "domainkeys" {
|
||||
for_each = var.domainkeys
|
||||
|
||||
name = "${each.key}._domainkey"
|
||||
proxied = false
|
||||
ttl = var.record_ttl
|
||||
type = upper(each.value.type)
|
||||
value = each.value.value
|
||||
content = each.value.value
|
||||
zone_id = var.zone_id
|
||||
}
|
||||
|
||||
54
moved.tf
Normal file
54
moved.tf
Normal file
@@ -0,0 +1,54 @@
|
||||
# State migration helpers for Cloudflare provider v4 → v5 upgrade.
|
||||
# These allow existing users to upgrade without manual state manipulation
|
||||
# for renamed resources. Can be removed in a future major release.
|
||||
|
||||
# MX
|
||||
moved {
|
||||
from = cloudflare_record.mx
|
||||
to = cloudflare_dns_record.mx
|
||||
}
|
||||
|
||||
# SPF
|
||||
moved {
|
||||
from = cloudflare_record.spf
|
||||
to = cloudflare_dns_record.spf
|
||||
}
|
||||
|
||||
# TLS SMTP
|
||||
moved {
|
||||
from = cloudflare_record.smtp_tls
|
||||
to = cloudflare_dns_record.smtp_tls
|
||||
}
|
||||
|
||||
# MTA-STS
|
||||
moved {
|
||||
from = cloudflare_record.mta-sts-a
|
||||
to = cloudflare_dns_record.mta-sts-a
|
||||
}
|
||||
|
||||
moved {
|
||||
from = cloudflare_record.mta-sts-aaaa
|
||||
to = cloudflare_dns_record.mta-sts-aaaa
|
||||
}
|
||||
|
||||
moved {
|
||||
from = cloudflare_record.mta_sts
|
||||
to = cloudflare_dns_record.mta_sts
|
||||
}
|
||||
|
||||
moved {
|
||||
from = cloudflare_worker_route.mta_sts_route
|
||||
to = cloudflare_workers_route.mta_sts_route
|
||||
}
|
||||
|
||||
# DMARC
|
||||
moved {
|
||||
from = cloudflare_record.dmarc
|
||||
to = cloudflare_dns_record.dmarc
|
||||
}
|
||||
|
||||
# Domain Keys (DKIM)
|
||||
moved {
|
||||
from = cloudflare_record.domainkeys
|
||||
to = cloudflare_dns_record.domainkeys
|
||||
}
|
||||
24
mta-sts.js
24
mta-sts.js
@@ -1,17 +1,15 @@
|
||||
addEventListener('fetch', (event) => {
|
||||
event.respondWith(handleRequest(event.request));
|
||||
});
|
||||
export default {
|
||||
async fetch(request, env) {
|
||||
const url = new URL(request.url);
|
||||
|
||||
async function handleRequest(request) {
|
||||
const url = new URL(request.url);
|
||||
if (url.pathname === '/.well-known/mta-sts.txt') {
|
||||
const response = await env.FILES.get('mta-sts.txt');
|
||||
|
||||
if (url.pathname === '/.well-known/mta-sts.txt') {
|
||||
const response = await FILES.get('mta-sts.txt');
|
||||
|
||||
if (response) {
|
||||
return new Response(response, { status: 200 });
|
||||
if (response) {
|
||||
return new Response(response, { status: 200 });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return new Response('Not found', { status: 404 });
|
||||
}
|
||||
return new Response('Not found', { status: 404 });
|
||||
},
|
||||
};
|
||||
|
||||
@@ -4,7 +4,7 @@ terraform {
|
||||
required_providers {
|
||||
cloudflare = {
|
||||
source = "cloudflare/cloudflare"
|
||||
version = ">= 3.0, < 5.0"
|
||||
version = ">= 5.0, < 6.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user