↓メインコンテンツへスキップ
  1. Blogs/

ドメイン認証がFAILEDになった9分後にAUTHORIZEDへ戻り、証明書はACTIVEになった

4 分
Terraform GoogleCloud LoadBalancing CertificateManager CloudDNS
0222-nnn
著者
0222-nnn
猫が好き
目次
Terraform-GoogleCloud - この記事は連載の一部です
パート 40: この記事

概要
#

リージョン外部 ALB で、公開の Google マネージド証明書を使うとします。選べるのは Certificate Manager の DNS 認証です。

Compute Engine のマネージド証明書は使えません。自己管理証明書なら別途使えます。

Compute Engine Google-managed SSL certificates aren’t supported for regional external Application Load Balancers, regional internal Application Load Balancers, or cross-region internal Application Load Balancers.

残るのは Certificate Manager です。認証方式は DNS認証とLB認証の2つで、どちらを選ぶかで証明書を用意できるタイミングが変わります。

ただしリージョン証明書で使えるのは DNS 認証だけです。 この記事では、比較のためにグローバル外部ALBで LB 認証も試します。

両方を同じプロジェクトに作り、発行までを実測しました。29分の時点では両方 FAILED でした。

対象読者
#

  • Terraform で Google Cloud のロードバランサを作ったことがある
  • terraform apply の出力を読める

扱わないもの
#

  • Terraform と Google Cloud の入門
  • 自己管理証明書、private PKI
  • Cloud Armor、URL マップの詳細

証明書の発行と、ロードバランサへの取り付けに絞ります。

検証すること
#

  • 発行が完了するまで実際にどれくらいかかるか
  • ロードバランサが無くても発行できるか
  • リージョンとグローバルで DNS 認証の中身は同じか
  • 証明書が ACTIVE になれば TLS は張れるのか
  • Cloud Logging に何が残るか

前提環境
#

  • Google Cloud CLI、Terraform
  • Billing が有効な検証用 Google Cloud Project
  • 親ドメインから、サブドメインを Cloud DNS へ委任できること
  • 検証時のバージョン:Terraform 1.14.3、google 7.x

委任しないと DNS 認証の CNAME が引けません。証明書は待っても発行されません。

使用するTerraformコード
#

2つの認証方式
#

flowchart TB
    subgraph DNS["DNS認証"]
        D1["DNS認証を作る"]
        D2["_acme-challenge の CNAME を置く"]
        D3["証明書が発行される"]
        D4["ロードバランサに付ける"]
        D1 --> D2 --> D3 --> D4
    end
    subgraph LB["LB認証"]
        L1["ロードバランサを作る"]
        L2["A レコードを LB の IP に向ける"]
        L3["証明書が発行される"]
        L1 --> L2 --> L3
    end

DNS認証は証明書が先、LB認証はロードバランサが先です。移行のときはこの順序が効きます。

構成
#

3つ並べます。

A. DNS認証 + リージョン証明書 -> リージョン外部ALB   regional.<domain>
B. LB 認証 + グローバル証明書 -> グローバル外部ALB   global.<domain>
C. DNS認証 + リージョン証明書 -> どこにも繋がない     nolb.<domain>

C は A レコードもロードバランサも作りません。DNS認証が配信経路と無関係かどうかを見るためです。

バックエンドは VM 1台で、ゾーン NEG を A と B で共用します。

認証方式の選び方は「何を用意できるか」で決まる
#

DNS認証 LB認証
必要なもの _acme-challenge の CNAME ドメインを配信するすべてのIPで同じ証明書に443で到達できること
SAN の上限 100 5
対応するLB グローバル / クラシック / リージョン / クロスリージョン グローバル / クラシックのみ

LB認証は「そのホスト名でロードバランサが応答していること」を認証条件にします。ロードバランサが先に要ります。

委任直後と委任済みで発行時間に差が出た
#

A と B を作り、親ドメインから委任した直後の記録です。

    0秒          regional=AUTHORIZING      global=AUTHORIZING
 29分20秒        regional=FAILED           global=FAILED
 38分20秒        regional=AUTHORIZED       global=FAILED
 38分53秒        regional=ACTIVE           global=FAILED
 40分35秒        regional=ACTIVE           global=ACTIVE

29分20秒の時点で両方 FAILED になっています。 ここで見ていたら、設定を疑って作り直していたはずです。

これはドメイン認証の状態(authorizationAttemptInfo[].state)です。証明書そのものの managed.state が FAILED になった場合は発行を諦めた状態で、作り直しが要ります。同じ FAILED でも意味が違います。

そのあと C を、同じゾーンに追加しました。

      0秒  PROVISIONING/AUTHORIZING
    220秒  PROVISIONING/AUTHORIZED
    252秒  ACTIVE/AUTHORIZED

4分12秒です。同じプロジェクト、同じゾーン、同じ手順で9倍以上の差が出ました。

違いは、委任してからの経過時間だけです。1回目は委任した直後で、権威ネームサーバの切り替わりを待っていました。2回目はすでに引ける状態でした。

「証明書の発行には最大24時間」という記述を見かけます。ただしこの測定では、DNS の伝播と Certificate Manager・CA 側の処理を切り分けていません。 どちらがどれだけ効いたかは言えないので、発行処理単体の所要時間や上限についてはここでは結論を出しません。

ロードバランサが無くても発行できる
#

C は A レコードもロードバランサも作っていません。

$ dig +short A nolb.<domain>
(何も返らない)

$ gcloud compute forwarding-rules list --format="value(name)"
tf-adv-cm27-global-fr
tf-adv-cm27-regional-fr

それでも 4分12秒で ACTIVE になりました。DNS認証は配信経路と無関係に発行できます。

LB認証では原理的にできません。認証の条件は、証明書を関連付けたロードバランサの構成が済んでいて、そのホスト名の A / AAAA が返すすべての IP でポート 443 からその証明書を使えることだからです。AAAA の取り違え、証明書の未関連付け、443 の未開放は、いずれも失敗の原因になります。

この違いは移行のときに効きます。既存サイトをロードバランサへ載せ替える場合、DNS認証なら切り替え前に証明書を用意できます。

LB認証だと、ロードバランサを立てて DNS を向けるまで証明書が発行されません。切り替えと証明書の準備を同時にやることになります。

リージョンとグローバルでCNAMEの名前が違う
#

同じ「DNS認証」でも中身が違いました。

global(今回) リージョン
種別 FIXED_RECORD PER_PROJECT_RECORD
CNAME _acme-challenge.<domain> _acme-challenge_<接尾辞>.<domain>

CNAME の名前は location ではなく種別で決まります。 global では PER_PROJECT_RECORD も選べます。今回 global に FIXED_RECORD を使ったので、この組み合わせになりました。

一方、リージョンで FIXED_RECORD を指定すると弾かれます。

description: FIXED_RECORD type is not supported in this environment
subject: FIXED_RECORD
type: DATA_INVALID

公式にも書かれています。

For regional Google-managed certificates, you can create only the PER_PROJECT_RECORD type of DNS authorization.

_acme-challenge を決め打ちで書いたコードは、リージョンでは動きません。 認証リソースの出力から取れば、どちらでも動きます。

resource "google_dns_record_set" "acme_challenge_regional" {
  name         = google_certificate_manager_dns_authorization.regional.dns_resource_record[0].name
  type         = google_certificate_manager_dns_authorization.regional.dns_resource_record[0].type
  ttl          = 300
  managed_zone = google_dns_managed_zone.delegated.name

  rrdatas = [google_certificate_manager_dns_authorization.regional.dns_resource_record[0].data]
}

エラー文言が原因を指していない
#

「存在しない」と言われるが、存在する
#

global に作った DNS 認証を、リージョン証明書に渡してみました。

ERROR: INVALID_ARGUMENT: dns authorization doesn't exist
- field: managed.dns_authorizations[0]

認証は存在します。location が違うだけです。

$ gcloud certificate-manager dns-authorizations describe ... --location=global
projects/.../locations/global/dnsAuthorizations/...   FIXED_RECORD

公式の記述と対応しています。

You can’t use global DNS authorizations with regional certificates.

「使えない」ではなく「無い」と出るので、リソース名の打ち間違いを疑ってしまいます。

「非対応」ではなく「見つからない」と出る
#

Compute Engine のマネージド証明書をリージョン ALB に付けようとした結果です。

ERROR: Could not fetch resource:
 - The resource 'projects/.../regions/asia-northeast1/sslCertificates/...' was not found

作成自体はできます。グローバル資源だからです。付けようとすると regions/<region>/sslCertificates/ を探しに行き、そこには無い、という順で失敗します。

この出力が直接示すのは「そのリージョンパスに資源が無い」ことだけです。 リージョン SSL 証明書が Google-managed に非対応であること自体は仕様で確かめます。観測と仕様は分けて読みます。

冒頭の「リージョンALBでは非対応」を知らないと、この文面からはたどり着けません。

証明書がACTIVEでも、まだTLSは張れない
#

リージョン側は、ACTIVE の直後から通りました。

$ curl -o /dev/null -w '%{http_code} %{ssl_verify_result}\n' https://regional.<domain>/
200 0

subject=CN = regional.<domain>
issuer=C = US, O = Google Trust Services, CN = WR3
notBefore=Sep  5 23:52:56 2026 GMT
notAfter=Dec  5 00:48:52 2026 GMT

ssl_verify_result が 0 なので、検証も通っています。有効期間は90日です。

グローバル側は違いました。

$ curl https://global.<domain>/
curl: (35) error:0A000126:SSL routines::unexpected eof while reading

証明書は ACTIVE です。それでも TLS が張れません。さらに121秒待つと 200 になりました。

似た記述がCompute Engine のマネージド SSL 証明書のページにあります。

After the certificate and domain statuses are active, it can take up to 30 minutes for your load balancer to begin using your Google-managed SSL certificate.

ただしこれは Certificate Manager の証明書についての記述ではありません。 121秒は今回の観測値で、上限を示すものでもありません。

いずれにせよ、「証明書ができた」と「繋がる」は別です。

取り付け方がリージョンとグローバルで違う
#

取り付け先
リージョン ターゲットプロキシに直接(certificate_manager_certificates)
グローバル 証明書マップ経由(certificate_map)

リージョン側はこう書きます。

resource "google_compute_region_target_https_proxy" "regional" {
  name                             = "tf-adv-cm27-regional-proxy"
  region                           = var.region
  url_map                          = google_compute_region_url_map.regional.id
  certificate_manager_certificates = [google_certificate_manager_certificate.regional.id]
}

併用の可否は上下で違います。 リージョン側の certificate_manager_certificates は ssl_certificates と同時に指定できません。

sslCertificates and certificateManagerCertificates can’t be defined together.

グローバル側の certificate_map は ssl_certificates と同時に設定できます。その場合はマップが優先され、Compute Engine の証明書は無視されます。

今回の検索では発行の経過を確認できなかった
#

管理操作は残ります。

$ gcloud logging read 'protoPayload.serviceName="certificatemanager.googleapis.com"' --freshness=4h
CreateDnsAuthorization  projects/.../dnsAuthorizations/tf-adv-cm27-dnsauth-regional
CreateCertificate       projects/.../certificates/tf-adv-cm27-cert-nolb
...
→ 18 件

発行の経過は、今回の検索では見つかりませんでした。

$ gcloud logging read 'textPayload=~"ACTIVE|AUTHORIZ|PROVISION"' --freshness=3h
→ 0 件

この条件は textPayload しか見ていません。 jsonPayload や protoPayload は別のフィールドなので、この検索だけでは経過ログが存在しないとは言い切れません。

今回は describe を定期的に呼び出して状態を追いました。

describe を繰り返して authorizationAttemptInfo を見るしかありません。

$ gcloud certificate-manager certificates describe <NAME> --location=<REGION> --format="yaml(managed)"
managed:
  authorizationAttemptInfo:
  - attemptTime: '2026-09-06T00:48:54Z'
    domain: regional.<domain>
    state: AUTHORIZED
  state: ACTIVE

つまずいたところ
#

API有効化の直後は失敗する
#

google_project_service で Certificate Manager API を有効化し、同じ apply で証明書を作ろうとして落ちました。

Certificate Manager API has not been used in project ... before or it is disabled.
"reason": "SERVICE_DISABLED"

google_project_service は、有効化オペレーションの完了と、Service Usage 上で ENABLED になるまでは待ちます。ただしそれは、そのサービスで実際に操作できるようになったことの確認ではありません。 depends_on は作成順序を決めるだけで、利用可能になるまでを保証しません。

今回はもう一度 apply すれば通りました。ただし1回の観測なので、必ず再 apply で通るとまでは言えません。

capacity_scaler を省くとplanが落ちる(リージョン版)
#

Error: managed backend service must have at least one non-zero capacity_scaler for backends

google_compute_region_backend_service で EXTERNAL_MANAGED を使うと、plan の検証に引っかかりました。

API の省略時の既定は 1 です。 明示を求めているのは provider 側の検証で、グローバル版の google_compute_backend_service には既定値があります。

backend {
  group                 = google_compute_network_endpoint_group.backend.id
  balancing_mode        = "RATE"
  max_rate_per_endpoint = 100
  capacity_scaler       = 1.0
}

まとめ
#

実測した結果を並べます。

項目 結果
発行までの時間(委任直後) 38分53秒
発行までの時間(委任済み) 4分12秒
途中の FAILED あり。29分20秒から9分間
LB無しでの発行 できる(DNS認証)
リージョンのDNS認証 PER_PROJECT_RECORD 強制
証明書ACTIVE後のTLS グローバルはさらに121秒
発行経過のログ 0件

時間がかかるのは DNS の伝播でした。 2回目が4分で終わったことが、それを示しています。委任を先に済ませておけば、証明書の発行自体は待つほどのものではありません。

FAILED という表示だけで再作成を判断しないことが、この検証で一番の収穫でした。29分で諦めていたら、原因のない作り直しをしていたはずです。

ただし待てば直るとは限りません。 公式のトラブルシューティングは、認証の失敗理由として CNAME の不一致やロードバランサの設定不備を挙げています。failureReason と details を見て、設定に問題があれば直します。

どのフィールドが失敗したのかも確かめます。managed.state の FAILED は作り直しが要ります。

認証方式は、証明書をいつ用意したいかで決まります。ロードバランサを立てる前に用意しておきたいなら DNS認証しかありません。リージョンALBを使う場合は、そもそも Certificate Manager 一択です。

参考資料
#

Terraform-GoogleCloud - この記事は連載の一部です
パート 40: この記事

関連記事

TerraformでGKEのスタンドアロンNEGを消したらLBのバックエンドが戻らなかった話
3 分
Terraform GoogleCloud GKE LoadBalancing
TerraformでGKEのPodをInternal HTTP LB(NEG)でポート別に振り分けてみた
3 分
Terraform GoogleCloud GKE LoadBalancing
TerraformでGoogle Cloudの予算アラートを作り、Pub/Sub通知の中身まで確かめた
4 分
Terraform GoogleCloud CloudBilling PubSub
terraform applyが成功してもVMの中は設定されていなかった話
4 分
Terraform GoogleCloud Ansible ComputeEngine CloudLogging
標準出力に1行JSONを書くだけなら、GKEではFluentdサイドカーが要らなかった
2 分
Terraform GoogleCloud GKE CloudLogging Fluentd
GKEのdefault_compute_class_enabledを有効にしても何も起きなかったので調べた
3 分
Terraform GoogleCloud GKE