オンライン通信のセキュリティとプライバシーを守ることが、これまで以上に重要になっています。SSL証明書は、安全な接続の確立、機密データの保護、そしてユーザーとWebサイト間の信頼構築において欠かせない役割を果たします。
Google Cloud Platform(GCP)のロードバランサー向けにSSL証明書を設定する際、ドメイン所有権の検証は重要なステップです。これまでは、ロードバランサーベースの認可が一般的な方法でした。Googleマネージドの SSL証明書をロードバランサーにマウントし、AレコードでドメインをロードバランサーのIPに紐付ける方式です。
しかし、ロードバランサーベースの認可によるマネージドSSL証明書の設定は、手間がかかり、ミスも起きやすいのが難点です。まず、TLS(SSL)証明書をプロビジョニングする前に、すべての設定を完了しておく必要があります。設定ミスや手順漏れがあれば、その分プロビジョニングが遅れます。さらに、グローバルなDNSレコードの伝播には最大48時間かかることもあり、SSL証明書のドメインにアクセスできない時間帯が通常10〜15分ほど発生します。そのため、この方式は本番トラフィックのない新規環境の構築に向いています。
こうした課題を解消し、ロードバランサーの構築や他社からGoogle Cloudへの移行に先立ってGoogleマネージド証明書を準備しておくための代替手段が、Domain authorizationです。Domain authorizationでは、ドメイン所有権を検証するための専用DNSレコードを別途設定します。これにより、ターゲットプロキシがネットワークトラフィックを処理できる状態になる前から、証明書を先行してプロビジョニング可能です。サードパーティ製ソリューションからGoogle Cloudへのダウンタイムゼロの移行も実現でき、よりスムーズな移行が可能になります。
ロードバランサー認可とDomain authorizationの違いは、以下の表を参照してください。

本記事では、Domain authorizationを設定し、Certificate Managerで新しい証明書を作成する手順を解説します。
**前提条件**
- Cloud DNSにパブリックDNSゾーンがあること
Domain authorizationは他のDNSプロバイダでも利用できます。
- GCPプロジェクトでCertificate Manager APIが有効化されていること
- gcloud CLI
本記事では、Cloud DNS上のパブリックゾーンchimbuc.dns.doit-playground.comを利用します。

**DNS authorizationの設定**
- 必要な環境変数を設定します。
export PROJECT_ID="your-project-id"
export REGION="your-region" # ex: us-central1
export DOMAIN_NAME="domain-name-for-the-certificate" # ex: example.chimbuc.dns.doit-playground.com
export DOMAIN_AUTHORIZATION_NAME="dns-authorization-resource-name" # ex: dns-authorization-example
export CLOUD_DNS_ZONE_NAME="your-cloud-dns-zone" # ex: chimbuc.dns.doit-playground.com.
export CERTIFICATE_NAME="certificate-manager-cert-name" # ex: example-chimbuc-dns-doit-playground-com
export CERTIFICATE_MAP_NAME="certificate-map-name" # ex: example-dns-authorization-cert-map
export CERTIFICATE_MAP_ENTRY_NAME="certificate-map-entry" # ex: example-dns-authorization-cert-map-entry
- ドメイン用のDNS authorizationを作成します。1つのDNS authorizationでカバーできるホスト名は1つだけなので、対象の証明書で使いたいホスト名ごとにDNS authorizationを作成してください。
*.example.comのようなワイルドカード証明書のDNS authorizationを作成する場合は、親ドメイン(例:example.com)に対して設定します。
gcloud certificate-manager dns-authorizations create $DOMAIN_AUTHORIZATION_NAME \
--domain="${DOMAIN_NAME}" \
--project $PROJECT_ID

example.chimbuc.dns.doit-playground.comのDNS authorization
- DNSに追加するCNAMEレコードの情報を取得します。
gcloud certificate-manager dns-authorizations describe $DOMAIN_AUTHORIZATION_NAME \
--project $PROJECT_ID

example.chimbuc.dns.doit-playground.comのDNS authorization詳細
- CNAMEレコードをDNSに追加します。Google CloudでDNSを管理している場合は本セクションの手順を実施し、それ以外の場合はお使いのサードパーティ製DNSのドキュメントを参照してください。
#DNSレコードのトランザクションを開始
gcloud dns record-sets transaction start --zone="${CLOUD_DNS_ZONE_NAME}" \
--project $PROJECT_ID
#対象のDNSゾーンにCNAMEレコードを追加
gcloud dns record-sets transaction add CNAME_RECORD_DATA \
--name="_acme-challenge.${DOMAIN_NAME}." \
--ttl="30" \
--type="CNAME" \
--zone="${CLOUD_DNS_ZONE_NAME}" \
--project $PROJECT_ID
#トランザクションを実行して変更を保存
gcloud dns record-sets transaction execute --zone="${CLOUD_DNS_ZONE_NAME}" \
--project $PROJECT_ID

DNS設定
DNS authorizationでGoogleマネージド証明書を作成する
- DNS authorizationを設定したドメイン用の証明書を作成します。Googleマネージド証明書は
globalロケーションにのみ作成できます。
gcloud certificate-manager certificates create $CERTIFICATE_NAME \
--domains="${DOMAIN_NAME}" \
--dns-authorizations="${DOMAIN_AUTHORIZATION_NAME}" \
--project $PROJECT_ID


証明書のプロビジョニングには数分かかります。完了するとステータスがactiveに変わります。Pendingのまま長時間変わらない場合は、証明書名をクリックして失敗の原因を確認してください。
- 証明書のステータスを確認します。
gcloud certificate-manager certificates describe $CERTIFICATE_NAME --project $PROJECT_ID


作成した証明書をロードバランサーにデプロイするには、特定の証明書を特定のホスト名に割り当てる証明書マップエントリを1つ以上参照する証明書マップが必要です。詳しくはHow Certificate Manager Worksを参照してください。
- 証明書マップを作成します。
gcloud certificate-manager maps create $CERTIFICATE_MAP_NAME --project $PROJECT_ID

証明書マップ
- ドメイン用の証明書マップエントリを作成します。
gcloud certificate-manager maps entries create $CERTIFICATE_MAP_ENTRY_NAME \
--map="${CERTIFICATE_MAP_NAME}" \
--certificates="${CERTIFICATE_NAME}" \
--hostname="${DOMAIN_NAME}" \
--project $PROJECT_ID

証明書マップエントリ
証明書マップエントリのプロビジョニングが完了し、ステータスがactiveになるまで数分待ちます。
gcloud certificate-manager maps entries describe $CERTIFICATE_MAP_ENTRY_NAME \
--map="${CERTIFICATE_MAP_NAME}" \
--project $PROJECT_ID

サンプルアプリケーションをデプロイする
- マネージドインスタンスグループを作成し、Apacheをインストールします。
#インスタンステンプレートを作成
gcloud compute instance-templates create web-app-instance-template \
--region=$REGION \
--project $PROJECT_ID \
--network=default \
--subnet=default \
--tags=allow-health-check \
--image-family=debian-10 \
--image-project=debian-cloud \
--metadata=startup-script='#! /bin/bash
apt-get update
apt-get install apache2 -y
a2ensite default-ssl
a2enmod ssl
vm_hostname="$(curl -H "Metadata-Flavor:Google" \
http://metadata.google.internal/computeMetadata/v1/instance/name)"
echo "Page served from: $vm_hostname" | \
tee /var/www/html/index.html
systemctl restart apache2'
#テンプレートからマネージドインスタンスグループを作成
gcloud compute instance-groups managed create web-app-instance-group \
--template=web-app-instance-template \
--size=1 \
--zone="${REGION}"-b \
--project $PROJECT_ID
#インスタンスグループに名前付きポートを追加
gcloud compute instance-groups set-named-ports web-app-instance-group \
--named-ports http:80 \
--zone "${REGION}"-b \
--project $PROJECT_ID
- Google Cloudのヘルスチェックシステムからのトラフィックを許可するファイアウォールルールを作成します。
gcloud compute firewall-rules create fw-allow-health-check \
--network=default \
--action=allow \
--direction=ingress \
--source-ranges=130.211.0.0/22,35.191.0.0/16 \
--target-tags=allow-health-check \
--rules=tcp:80 \
--project $PROJECT_ID

サンプルインスタンス
証明書をロードバランサーにデプロイする
- ロードバランサーのリソースを作成します。
#外部IPを予約
gcloud compute addresses create external-lb-ipv4 \
--ip-version=IPV4 \
--network-tier=PREMIUM \
--global \
--project $PROJECT_ID
#ヘルスチェックを作成
gcloud compute health-checks create http http-basic-check \
--port 80 \
--project $PROJECT_ID
#バックエンドサービスを作成
gcloud compute backend-services create web-app-backend-service \
--load-balancing-scheme=EXTERNAL \
--protocol=HTTP \
--port-name=http \
--health-checks=http-basic-check \
--global \
--project $PROJECT_ID
#インスタンスグループをバックエンドサービスのバックエンドとして追加
gcloud compute backend-services add-backend web-app-backend-service \
--instance-group=web-app-instance-group \
--instance-group-zone="${REGION}"-b \
--global \
--project $PROJECT_ID
#受信リクエストをデフォルトのバックエンドサービスにルーティングするURLマップを作成
gcloud compute url-maps create web-app-url-map-https \
--default-service web-app-backend-service \
--project $PROJECT_ID
- URLマップへリクエストをルーティングするターゲットHTTPSプロキシを作成し、証明書マップを紐付けます。
gcloud compute target-https-proxies create https-lb-proxy \
--url-map=web-app-url-map-https \
--certificate-map="${CERTIFICATE_MAP_NAME}" \
--project $PROJECT_ID

ターゲットHTTPSプロキシに証明書が紐付いた状態
- 受信リクエストをプロキシへルーティングするグローバル転送ルールを作成します。
gcloud compute forwarding-rules create web-app-https-fw-rule \
--load-balancing-scheme=EXTERNAL \
--network-tier=PREMIUM \
--address=external-lb-ipv4 \
--global \
--target-https-proxy=https-lb-proxy \
--ports=443 \
--project $PROJECT_ID

外部ロードバランサーの構成
- Cloud DNSにドメイン用のレコードセットを作成し、エンドポイントへアクセスします。

example.chimbuc.dns.doit-playground.comのAレコード

**まとめ**
Google Cloud Platform(GCP)のDomain authorizationを活用すれば、従来のロードバランサーベースの認可と比べて、SSL証明書のプロビジョニングを大幅にスピードアップできます。本記事の手順に沿って進めれば、Domain authorizationを効率的に設定し、新しいTLS証明書を発行して、GCP環境のセキュリティを強化できます。ダウンタイムを最小限に抑え、よりスムーズな移行を実現する手段として、ぜひ活用してみてください。