😃

2048bitのDKIMレコードに対応したterraform moduleを作る

2024/12/03に公開

はじめに

SRE Advent Calendar 2024 12/4(木)分の記事です。

SaaSサービスとの連携時にDKIMレコードの設定を求められることは多くあります。最近では2048bitの公開鍵を使用するケースが増えており、これらは単一のDNSレコードとして設定できないという課題があります。

なぜDKIMレコードの分割が必要か

RFC 1035より、1つのTXTレコードには255文字までしか格納できません。2048bitの公開鍵をBase64エンコードすると、この制限を超えてしまいます。

そのため、以下のような形で分割する必要があります:

sselector._domainkey IN TXT "v=DKIM1; k=rsa; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0..." "続きの文字列..."

Terraformでの実装

以下が具体的な実装例です。Google Cloud DNSのリソースを使用して、分割されたDKIMレコードを設定します。今回はmoduleでの使用を意識するためvariableでdkimレコードを受け取ります。

variable "dkim_text_record" {
  type = string
}

resource "google_dns_managed_zone" "example" {
  name        = "example-zone"
  dns_name    = "example.com."
  description = "Example DNS zone"
}

resource "google_dns_record_set" "dkim" {
  name         = "_domainkey.example.com."
  managed_zone = google_dns_managed_zone.example.name
  type         = "TXT"
  ttl          = 3600

  rrdatas = [
    join(" ", [
      for i in range(0, length(var.dkim_text_record), 255) :
      "\"${substr(var.dkim_text_record, i, min(255, length(var.dkim_text_record) - i))}\""
    ])
  ]
}

工夫した点としては

join(" ", [
      for i in range(0, length(var.dkim_text_record), 255) :
      "\"${substr(var.dkim_text_record.value, i, min(255, length(var.dkim_text_record) - i))}\""
    ])

ここで、文字列を255文字ごとに切り出し分割を行っています。
例えばlength(var.dkim_text_record)が360だとforは2巡します。
分かりやすいように処理を具体的に追ってみましょう。

for 1巡目

i=0
substr(var.dkim_text_record, 0, min(255, 360-0))}

for 2巡目

i=255
substr(var.dkim_text_record, 255, min(255, 360-255))}
join(" ", [
    "for 1巡目の255文字の文字列",
    "for 2巡目の105文字の文字列"
])

上記のように処理が行われ、txtレコードとして分割して反映されます。

まとめ

従来、2048bit DKIMレコードの実装では、DNSの255文字制限に対応するために手動でレコードを分割する必要がありました。しかし、Terraformでは文字列操作関数を効果的に活用することで、この課題を楽に解決出来ます。

Discussion