Cloud Certificate Manger による Wildcard Certificate を用いた Cloud Run の活用

2022-09-22

Overview

GCP の Cloud Certificate Manager では元々ロードバランサー(以下 LB) に付随していた SSL 証明書ではできなかったワイルドカード証明書の利用が可能になりました。

本記事では Cloud Certificate Manager の概要を説明後、実際の運用での活用例を Cloud Run の利用とともに紹介します。

Certificate Manager とは

Cloud Certificate Manager (以下 Certificate Manager) は 2022-08-25 に GA になりました。 Certificate Manager の登場により TLS 証明書の大規模取得や利用が可能になります。

元々 GCP では LB にセルフマネージド SSL 証明書と Google マネージド SSL 証明書を無料で設定できます (概要)。 しかし、LB に紐づく既存の証明書には制限事項に記述されているように以下のような制限がありました。

  • Wildcard Certificate が使えない
  • 各マネージド証明書でサポートされるドメインの数の上限
  • 各ターゲットプロキシでサポートされる SSL 証明書数の上限

Certificate Manager ではこれらの制限に囚われず、大量の証明書を一つのロードバランサーに集約したり、ワイルドカード証明書の利用が可能になります。

Certificate Manager 使い所

公式ページ では以下の場合は Certificate Manager ではなく既存の LB と紐づく証明書を用いたら十分だと書かれています。

  • ロードバランサーにつき 15 以下の証明書のみ必要
  • サードパーティのソリューションからの移行でダウンタイムがある
  • ワイルドカード証明書が必要ない

つまり、ダウンタイム無しで移行したい場合(証明書の場合プロビジョニングに時間がかかる)や、ワイルドカード証明書を利用したい場合などは Certificate Manager が良いということです。

Certificate Manager 使い方

Certificate Manager の使い方は公式のチュートリアルを参考にできます。 認証の方法として DNS AuthorizationLB Authorization がありますが、 LB Authorization の場合はワイルドカード証明書がサポートされない、設定には LB が事前に起動している必要があるという制限があります。 DNS Authorization はドメインのオーナーシップを証明するためのレコードを追加する必要がありますが、ダウンタイムなしの移行が可能であり、Certificate Manager の良さをフルに活かすことができます。 (参考)

この記事を書いている 2022-09 時点では Certificate Manager の設定はコンソールではできず、gcloud コマンドを用いる必要があります。

Certificate Manager の制限

Certificate Manager にも以下の例のような制限事項が存在します。

  • サポートしている LB は External HTTP(S) load balancer (Classic) と Global external HTTP(S) load balancer (Preview) のみ
  • 公開認証局のみ Google-managed として利用可能
  • Google CA と Let's Encrypt CA のみが Google-managed ではサポートされている

ワイルドカード証明書を用いた Cloud Run の活用

ここからは Certificate Manager により利用可能となったワイルドカード証明書を用いて Cloud Run をより柔軟に利用するアイディアを紹介します。

前提として、今回のアプローチは基本的に URL Mask を活用します。

URL Mask とは

URL Mask はカスタムドメインを利用しながら柔軟に Cloud Run のサービスにアクセスできる仕組みです。

Cloud Run で LB を利用する場合、 LB のバックエンドサービスとして Serverless NEG を紐付け、NEG に Cloud Run のサービスをバックエンドとして設定することでカスタムドメインを用いて Cloud Run のサービスに通信可能となります。

LB and Run https://cloud.google.com/load-balancing/docs/https/setup-global-ext-https-serverless#creating_the_load_balancer

URL Mask は特定の Cloud Run のサービスを LB と紐付けるのではなく、Cloud Run の service と tag をプレースホルダとして用いることで、 カスタムドメインを通してプレースホルダの条件と一致する Cloud Run のサービスに柔軟にアクセス可能となります。

例: <tag>.<service>.example.com

このとき、IAP は Backend Service に対して設定するため、Cloud Run のサービスに追加があったとしても IAP や LB の設定を変更することなく IAP 認証を適用してアクセス可能になるのが嬉しいポイントです。

URL Mask https://cloud.google.com/load-balancing/docs/negs/serverless-neg-concepts#url_masks

コードレビュー時点でブランチ単位でデプロイし内容を確認

開発中の機能を実環境にデプロイし挙動を確認したい場面があると思います。 ワイルドカード証明書と URL Mask を組み合わせると任意のバージョンの Cloud Run のサービスにアクセスすることが簡単になり、この実現が簡単になります。

やりたいことの例

例えば開発中の Cloud Run サービス device の新機能を main ブランチマージ前のコードレビュー時点で確認したい場面があります。
開発中の機能は ticket-123ticket-456 があり、同時期にコードレビューが作られました。 開発者は新機能を実環境で確認するために IAP で守られたサービスにデプロイすると、2 つのリビジョンが Cloud Run では作られます。 これらの状態を確認するためチケット名(or ブランチ名の一部) を tag に設定したら、 URL Mask を利用すると以下の URL で確認可能になります。

  • https://ticket-123.device.myservice.com
  • https://ticket-456.device.myservice.com

これまでの方法

これまで、 LB の証明書を利用する方法の場合は利用したいこの各 URL のドメインを証明書と紐付ける必要がありました。 しかし、この方法だと長期的に開発をすると LB をの証明書の上限に引っかかるため頻繁にクリーンアップが必要になります。
クリーンアップの手間を抑えるには URL Mask を使わず、https://device.myservice.com という URL を用いる前提でデプロイしたものを順番に トラフィック移行して確認するという選択肢も考えられます。 その場合、ticket-123ticket-456 のどちらに先にトラフィックを流して確認するなどの調整が必要になります。

ワイルドカード証明書による改善された方法

Certificate Manager を用いてワイルドカード証明書を導入するとドメイン毎に証明書を用意する必要がなくなります。 具体的には、*.device.myservice.com というサブドメインに対応した証明書を作成し、LB と紐付けます。
こうすることで、動的に変わるチケット番号を気にする必要なく、任意のリビジョンが確認可能になります。

Tag Base Routing

Certificate Manager の LB への設定サンプル


# Create DNS authorization.
% gcloud certificate-manager dns-authorizations describe device-domain-authorization

# Get DNS authorization data to set to the DNS.
% gcloud certificate-manager dns-authorizations describe device-domain-authorization

createTime: '2019-02-22T00:00:00.000000000Z'
dnsResourceRecord:
  data: YOUR_AUTHZ_DATA
  name: _acme-challenge.myservice.com.
  type: CNAME
domain: myservice.com
name: projects/myProject/locations/global/dnsAuthorizations/myAuthorization
updateTime: '2019-02-22T00:00:00.000000000Z'

# Start transaction for DNS manipulation.
% gcloud dns record-sets transaction start --zone="myservice-one-zone"

% gcloud dns record-sets transaction add  {YOUR_AUTHZ_DATA} \
   --name="_acme-challenge.myservice.one." \
   --ttl="30" \
   --type="CNAME" \
   --zone="myservice-one-zone"

% gcloud dns record-sets transaction execute --zone="myservice-one-zone"

# Create certificate.
% gcloud certificate-manager certificates create device-wildcard-certificate \
    --domains="device.myservice.com,*.device.myservice.com" --dns-authorizations=device-domain-authorization

# Create a cert-map.
% gcloud certificate-manager maps create device-cert-map

# Create an entry for cert-map.
% gcloud certificate-manager maps entries create wildcard-entry \
    --map="device-cert-map" \
    --certificates="device-wildcard-certificate" \
    --hostname="*.device.myservice.com"

# Update LB's target proxy.
gcloud compute target-https-proxies update device-lb-target-proxy \
   --certificate-map="device-cert-map"

本番サービスのリビジョンごとの確認

本番サービスの場合も、本番環境にデプロイした後トラフィック移行前に一度自身の目で確認した後に公開したい場合があると思います。 このような場合にも、ワイルドカード証明書と URL Mask を組み合わせると容易に実現できます。

やりたいことの例

Cloud Run サービス device のデプロイをし、新しい機能を公開したいと考えています。 しかし、公開前に開発者は本番の実環境でも外部との連携も含めて期待通りに動くことを確認したいです。

このようなシナリオの場合、前提として、本番の外部公開サービスの場合サービスの URL は容易に変更できません。 また、内部で確認するリビジョンは外部から見えて欲しくないため、外部公開用の LB と IAP 認証を利用した内部確認用の LB を用意することになると思います。

これまでの方法

外部公開用の LB (PLB) は特別な要件が無い限り公式ページで例として提示されるような形で基本的に問題ないです。

内部確認用のサービスリビジョンは外部に見せたくたいため、内部確認用の LB (ILB) を作成し、ILB のバックエンドサービスに IAP 認証を設定します。 Cloud Run のトラフィック自体は現在公開中のリビジョンに流したいため、トラフィック移行せずとも新機能を含むリビジョンにアクセスするために URL Mask を用いて最新のリビジョンにアクセスします。
リリースバージョンをタグとして付けそれを参照したいところですが、リリースバージョンが変わる毎に証明書を用意する必要があるため、ここでは latest タグをこのユースケースのものとして固定で用います。

想定内部確認用 URL: https://latest.device.myservice.com

ワイルドカード証明書による改善された方法

これまでの方法でも「公開前に状態を確認する」という目的は達成できますが、ワイルドカード証明書を用いると最新でなくともアクセスし状態を確認することができます。 ワイルドカード証明書を用いる場合、各リビジョンにリリースバージョンのタグを付けておくと最新のもののみでなく過去の特定の時点のサービスの状態も確認しやすくなります。

想定内部確認用 URL:

  • https://v010.device.myservice.com
  • https://v100.device.myservice.com
  • https://latest.device.myservice.com, https://v110.device.myservice.com

Tag Base Routing

注意点

今回紹介した Certificate Manager と URL Mask を組合わせた方法は便利ですが、同時に気を付けないといけない点もあります。

URL Mask によりプロジェクト内のどのサービスでもアクセス可能になる

URL Mask と IAP を用いると、別途認証の条件などを設けていないとプロジェクト内のどの Run のサービスへもアクセスができます。 意図せずアクセスするべきでないサービスが閲覧可能にならないかは気をつける必要があります。

Minimum Instance が設定され tag 付けされていると課金される

Cloud Run では Minimum Instance が設定されるとアクセスがない場合は Idle 状態になります。 このとき、トラフィックが完全に到達可能でない場合はインスタンスはシャットダウンされるのですが、 tag 付けされた場合はアクセス可能なインスタンスとなるため Idle 状態で待機することになり課金対象になります。

今回紹介したソリューションは tag を活用した方法であるため、Cloud Run に今まで行っていなかった tag 付けを始めて意図せず課金されてしまったということにならないよう気をつけてください。

おわりに

本記事では最近 GA になった Cloud Certificate Manager の紹介と、Cloud Run を利用して活用する例を紹介しました。 Certificate Manager の利用によってダウンタイム無しの移行が可能になったり、ワイルドカード証明書が可能になるといった利点が生まれます。 また、URL Mask と組み合わせて Cloud Run を用いるとより発展的なソリューションを構築できることにも触れました。 本記事では挙げられなかった活用方法もたくさんあると思うので、何かの機会に共有していただき、GCP のユーザーコミュニティ等で広めていただけたら嬉しく思います。

最後に、Belong ではエンジニアを募集しています。Belong では GCP のプロダクトをうまく使いたい方、とにかくプログラムを書きたい方など様々な方にフィットするポジションがあります。 本記事で Belong に興味を持っていただけたらぜひエンジニアリングチーム紹介ページを確認していただき、カジュアル面談等お声がけいただけたら嬉しく思います。