App Service のカスタムドメインと App Service 証明書の覚え書き


App Service のカスタムドメインと App Service 証明書の覚え書き

# はじめに
App Service と App Service 証明書は同じ文脈で語られることがありますが、実際には独立した別のサービスになります。

どのようなサービスなのか、登録や発行の手順をメモとして残します。
個々で記載する例は全て contso.com という会社のドメインを登録する際のシナリオとします。

# App Service カスタムドメインについて
[App Service カスタムドメイン](https://learn.microsoft.com/ja-jp/azure/app-service/app-service-web-tutorial-custom-domain?tabs=root%2Cazurecli)は、App Service に対して既定で付与される *.azurewebsites.net 以外の FQDN でのアクセス出来るようにする機能です。

例えば Web サイトや REST API を App Service 上に実装して、www.contso.com, api.contso.com のようなユーザーの所有するドメインでのアクセスを可能にします。
[既存のドメインの移行](https://learn.microsoft.com/ja-jp/azure/app-service/manage-custom-dns-migrate-domain) のシナリオをちゃんと読んでみると分かるのですが、カスタムドメインの登録では、(1) 該当ドメインの所有権の検証、(2) ルーティングの開始、の 2 段階が存在します。


## App Service がアクセスを受け付ける、そもそもの仕組み
App Service はアプリケーションが実行されている仮想マシンが直接インターネット上に露出しているわけではなく、各アプリはスケールユニットに格納されており、各アプリへのアクセスのためにはフロントエンドと呼ばれる負荷分散装置を経由する必要があります。

スケールユニット毎に各負荷分散装置は代表となる受信 IP を 1 つ持っており、この IP に対してホスト名やホストヘッダーを指定してアクセスすることで、各アプリケーションへのルーティングを行います。
カスタムドメインは、このルーティングの経路を追加する作業を意味しており、登録が完了すると、指定したドメインへのアクセスが登録先の App Service にルーティングされるようになります。

言い換えれば、アプリケーションにアクセスするためには、リバースプロキシを経由する必要があるが、どのアプリへのアクセスなのかの識別が必要。既定で提供される FQDN 以外でのアクセスを登録するのがカスタムドメインです。


## ドメインの所有権の検証
App Service に対するカスタムドメインの登録に先立ち、該当のドメインの所有権を確認する必要があり、具体的には、登録しようとしているユーザーが contso.com など、登録しようとしているドメインの DNS レコードの管理権限を持っているかを確認しています。

これはサブドメインテイクオーバーなどの、無関係の第三者が当該企業のドメインを名乗るアクセスを許可するような構成を回避するために行われており、検証を回避することは出来ません (*.microsoft.com や *.google.com を名乗るサイトが勝手に作られたらおかしいですよね)。
ここでのドメインへのアクセス権限は、"asuid.~~" という名前の TXT レコードを作成し、値として予め指定された英数字を DNS レコードに登録し、パブリックなインターネットから DNS クライアントから取得できるか確認することで実現されます。

インターネット上から確認する方法はいくつかありますが、```nslookup contoso.com 8.8.8.8``` のように nslookup でパブリック DNS サーバーを指定する、[Dig web interface](https://www.digwebinterface.com/) のようなサービスを使用して外部の DNS 情報を参照する方法があります。
![無題1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/349915/bd56cf05-de12-374f-76d3-47b946e86f43.jpeg)

1度カスタムドメインの登録が完了した場合、asuid.~~ の TXT レコードは削除して問題ありません。


## DNS への登録
上記のドメインの所有権の検証が成功すると、App Service はカスタムドメイン (contoso.com) でのアクセスを受け付けられるようになりました。
でも、この時点での contoso.com に対するアクセスは App Service には向かいません。
これは、DNS の A レコードまたは CNAME レコードはまだ App Service を示しておらず、既存のサイトを指定、または未登録になっているためです。

App Service に対するアクセスを有効にするタイミングで DNS の A レコードまたは CNAME レコードを該当ドメインの DNS サーバーに登録します。

## App Service カスタムドメインの注意点
- ルートドメイン (contoso.com) を使用する場合とサブドメイン (www.contoso.com) を使用する場合で A レコードまたは CNAME レコードの使用可否が異なります。使い分けについては [ドキュメントを確認してください](https://learn.microsoft.com/ja-jp/azure/app-service/app-service-web-tutorial-custom-domain?tabs=root%2Cazurecli)。
- 
- 既存の環境からドメイン名を移行する場合、新旧どちらにアクセスするかを制御するために、DNS の TTL を短くすることが推奨されます。DNS クライアントは TTL に基づいてキャッシュを管理しており、キャッシュの有効期限を短くすることで IP アドレスの変更などへの追従を早くすることが出来ます。
通常 IP アドレスは変わらないため 1時間 (3600 秒) など長めに設定されていることが多いですが、移行前後では計画的に数秒程度にしておくと切り戻しなども行いやすくなります。

- 複数のサイトで同じカスタムドメインは設定できるのか？
カスタムドメインはスケールユニット単位で管理されているため、仕組みの観点からは「別のスケールユニットに配置されていれば可能」が答えです (同じスケールユニットの場合、既に登録済であるとして拒否されます)。
ただ一方で、「同じ URL のサイトが 2 つある」と言うことを意味しているので、移行やマルチリージョンといった要件以外では使わない方が良いでしょう。

# App Service 証明書について
App Service 証明書は、主に App Service 向けにサーバー証明書を発行するサービスですが、用途は App Service に限定されず Azure VM などの任意のサービスでも使用は可能です。
また、エクスポートして、Azure 外で使用する事も出来ます。

証明書は Microsoft が発行しているわけではなく、Go Daddy 社により発行されます。また、発行手順に関しては Azure が制御できるわけではなく、CA Forum などの業界団体が定める手順に基づいて行う必要があります。

証明書を発行するためにはいくつかの手順を踏む必要があります。また、証明書の課金は発行されたタイミングで行われるため、検証などを行わない限り課金されません。
公開ドキュメントは [こちら](https://learn.microsoft.com/ja-jp/azure/app-service/configure-ssl-app-service-certificate?tabs=portal#buy-and-configure-an-app-service-certificate) になりますので、こちらに関してもご確認ください。

![無題3.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/349915/27c73c53-37f5-1803-ade4-8b052fdba694.jpeg)


## 手順1. 構成
App Service 証明書は証明書の管理情報だけを扱うリソースになり、実際の証明書は、Key Vault のシークレットに格納されます。
そのため、格納先の Key Vault を用意する必要があります。

Key Vault がアクセスの構成方法として、[Azure ロールベースのアクセス制御] を推奨していますが、App Service 証明書は、従来通りの [アクセス ポリシー] を必要とします。
![無題2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/349915/2600f1ba-57fc-ccf2-6de3-eef6eb7bebcb.jpeg)


ただし、Key Vault 作成直後に変更しようとすると、以下のエラーが出力される場合があるため注意が必要です。
```
コード
InsufficientPermissions

メッセージ

未処理エラー
呼び出し元は、アクセス許可モデルの変更を許可されていません。アクセス許可モデルの変更方法について詳しくは、https://go.microsoft.com/fwlink/?linkid=2155160 のリンクをご覧ください。詳細: name=****; oid=d89527bc-2a93-49bf-968e-e87a0384793a; action=Microsoft.Authorization/roleAssignments/write; resource=/subscriptions/********-****-****-****-************/resourcegroups/****/providers/Microsoft.KeyVault/vaults/****; decision=NotAllowed; 
```

分かりにくいですが Key Vault の [アクセス構成] を変更するためには、action=Microsoft.Authorization/roleAssignments/write の権限が必要になります。
ただし、これはサブスクリプション管理者 ("サービス管理者" や "共同管理者") が持っている Microsoft.Authorization/roleAssignments/write は無視されるため、カスタムロールなどを使用して別途付与することが必要です。
探してみると [ロール ベースのアクセスの制御の管理者(Role Based Access Control Administrator)]((https://learn.microsoft.com/ja-jp/azure/role-based-access-control/built-in-roles#role-based-access-control-administrator)) という組み込みロールがこの権限を持っているため、操作を行うユーザーに付与します。
![無題4.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/349915/09c3c637-a966-4348-38f8-7e92bcc7b913.jpeg)


こうすることで [アクセス構成] のアクセス許可モデルを変更できるようになります。

あとは [アクセス構成] で「コンテナーのアクセス ポリシー」に変更して [適用] します。これで、Key Vault 側の準備は完了です。

App Service 証明書側からは保管先の Key Vault を選択するだけです。
![無題5.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/349915/c63ff007-2121-1e07-9caa-548cdd6117a0.jpeg)
![無題6.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/349915/031ab5ed-54ed-8dc0-494f-e8fd0533a5cc.jpeg)


この際、Key Vault のアクセスポリシーに、Microsoft Azure App Service と Microsoft.Azure.CertificateRegistration という 2 つのアプリケーションが追加されます。
これは、App Service から証明書を取得する (App Service にインポートする) 仕組みと、App Service 証明書が証明書の更新を行うための仕組みで使用されます (それぞれ Microsoft Azure App Service: 62853731-8d6b-4288-82ae-43ae121c2a48, Microsoft.Azure.CertificateRegistration: fd0204e6-e4d7-4b11-acba-716d7fe1063e という Azure 組み込みのサービスプリンシパルが使用しています)。

![無題7.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/349915/04db61ba-bc72-aa05-8f05-6372300e1091.jpeg)


## 手順2. 確認
この手順では、証明書の発行先となるドメインにおいて、お客様が適切な管理権限を持っているか確認されます。

ポータル上では 全部で 5 つの方法が示されますが、基本的にはメールによる確認、手動での DNS による方法、HTML Web ページによる方法の 3 つです。App Service 上で証明書と同じカスタムドメインのアプリをホストしている場合や App Service ドメインを使用している場合は一部が代行されるためショートカットが出来ます (内部的には、HTML の方法や DNS の方法を行っているだけで基本は変わりません)。

### (1) メールによる確認
証明書の発行元 (GoDaddy の API) から、証明書の発行先の特定のメールアドレスに対してメールによる通知が行われます。
contoso.com にたいして発行を行う場合、以下の 5 つのメールアドレスにのみ通知が行われます。
- admin@contoso.com
- administrator@contoso.com
- hostmaster@contoso.com
- postmaster@contoso.com
- webmaster@contoso.com

![無題9.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/349915/f4505d2e-d537-e792-19d1-cd9c451c57e4.jpeg)

それぞれのメールアドレスに「このリンクをクリックして、証明書の発行可否を判断してください」という内容のメールが届きます。
```
Dear Azure Customer,

We have received a certificate signing request for the following domain(s): 
*.contoso.com 

Our query of the Whois database returned your name as the administrator for the
domain in the certificate request.

In order to verify the validity of this request and that it was submitted by the
entity to which the domain in the request is registered, please signify your final
approval or disapproval of the certificate request by clicking the link below.

https://certs.godaddy.com/anonymous/domainapproval.pki?vk=CERC********&locale=en-US

Approval of the request will enable us to continue processing your request. Failure
to approve the certificate request will lead to denial of the request.

If the above address does not appear as a clickable link, cut/copy and paste it into
your browser's address bar.

If the Verification Page requests it, please use the following Verification Key: 
CERC******** 
This part of our authentication process serves to ensure that only the
entity/individual that controls the domain in the request can obtain a certificate
for that domain.

After completing the verification, please return to Azure Portal at
https://portal.azure.com and complete the remaining steps outlined here.

If you have any trouble or questions, contact us and let us know. We are available
to help around-the-clock, seven days a week.

For Customer Support, please visit https://azure.microsoft.com/en-us/support/options/.

For further information, log in to your account at https://portal.azure.com
```
![無題8.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/349915/1a3773c1-d0ce-da16-61c8-36383e70e716.jpeg)


よく聞くのが (ドメインは本社の IT 部門が管理しており登録手続きが必要、時間がかかるので)「別のメールアドレスで受取りたい」「[電子メールの指示] で受取ったメールで確認できない」という話を聞きますが、こちらでは出来ません。
まず、このメールが送信されるのは「ドメイン管理者に対して、このドメインの証明書を発行して良いか」の確認であるため、該当ドメインのユーザーの判断ではなく、組織の管理者に対する確認が必要となります。
Microsoft や Google の社員でもないのに、outlook.com や gmail.com の証明書を持っているのは変 (何に使うの？) ですよね。そうした事象を防ぐために、メールの送信先は上記の 5 つのアドレスに限定されています。

また、[電子メールの指示] からは、参照されているポータルに記載されている内容がそのまま送られるだけで、ドメインの検証で使用されるわけではありません。


### (2) DNS による手動検証
DNS による検証手順は、TXT レコードに指定された値を登録して、外部から取得できるかを確認することで、ドメインの所有権の検証を行います。 
contoso.com に対する証明書でも、sub.www.contoso.com の場合でも手順は同じであり、contoso.com の @ と言う名前の TXT レコードで指定された値を登録するだけです。

![無題10.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/349915/e10ab396-fba2-a66b-6d02-920f34cf32b3.jpeg)
```
手動の検証では、TXT レコードを追加して、DNS の構成でドメインの所有権を確認することができます。
    ルート ドメイン に TXT レコードを追加するためのアクセス許可を使用して、ドメイン ネーム サービス (DNS) プロバイダーにアクセスします。
    名前 @、値 o9ar69cbdvmiuhnorbn4cfqom1 の TXT レコードを追加します
    注意: サブドメイン 'subdomain.yoursite.com' のドメイン検証の場合は、サブドメインではなく、ルート ドメイン 'yoursite.com' に TXT レコードを追加する必要があります。

    例 1: ドメイン subdomain1.subdomain2.yoursite.com について、TXT レコードを yoursite.com に追加
    例 2: ドメイン subdomain.yoursite.com.in について、TXT レコードを yoursite.com.in に追加
    例 3: ドメイン subdomain1.subdomain2.subdomain3.yoursite.com.in について、TXT レコードを yoursite.com.in に追加
```

名前で @ は、一般的にそのホストゾーン名 (ここでは contoso.com) のレコードを意味しますが、AWS Route53 では @ は記号として扱われます。[特に記述しない場合はホストゾーン名として扱われるようです](https://docs.aws.amazon.com/ja_jp/Route53/latest/DeveloperGuide/resource-record-sets-values-shared.html#rrsets-values-common-name)。
使用する DNS サービスの使用に合わせてご対応ください。

外部から確認できるかは、カスタムドメインの設定と同じように ```nslookup -q=TXT contoso.com 8.8.8.8``` のように nslookup でパブリック DNS サーバーを指定する、[Dig web interface](https://www.digwebinterface.com/) のようなサービスを使用して外部から DNS 情報を参照する方法があります。

ここで登録した TXT レコードは、証明書発行後は不要ですので削除して問題ありません。


### (3) HTML Web ページによる方法
この方法は、Azure 外のクライアントが http で指定された URL にアクセスし、指定されて文字列が応答されるか確認するものです。
該当のドメインで応答するサーバーを予め用意しておき、指定された URL でアクセスした場合に、指定された文字列が応答されるように構成する必要があります。

![無題11.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/349915/eee788fb-2bb0-e377-d817-ac258c5db4a6.jpeg)

```
重要な更新: 2021 年 11 月 30 日から、App Service の検証を使用する場合、新規、更新済み、キー更新済みの証明書は、追加の 'www' ドメインで発行されません。ただし、DNS 手動検証を使用して証明書を検証する場合 (手動検証を参照)、証明書は引き続き追加の 'www' ドメインで発行されます。詳細情報

注: App Service 証明書を使用する 'www' ドメインの Web アプリに SSL バインドがある場合、SSL バインドでは更新済みの App Service 証明書を使用できず、古い証明書を引き続き使用するため、古い証明書の有効期限が切れたときに Web アプリにダウンタイムが発生する可能性があります。この変更により、問題を回避するために、手動検証からの DNS 手動検証の手順に従うことをお勧めします。

    1. 次の名前の HTML ファイルを作成します: godaddy.html。

    2. このファイルのコンテンツは、ドメイン確認トークンの値でなければなりません: o9ar69cbdvmiuhnorbn4cfqom1

    3. ご使用のサイトの URL: http://contoso.com/.well-known/pki-validation/godaddy.html から HTML ファイルをパブリック インターネットで使用できるようにします

    4. このファイルを次の場所から参照できることを検証します: http://contoso.com/.well-known/pki-validation/godaddy.html。応答は、ドメイン確認 o9ar69cbdvmiuhnorbn4cfqom1 が含まれるテキスト ファイルでなければなりません

    5. [更新] ボタンをクリックして、証明書の状態を確認します。証明書の確認が完了するまでに、数分かかることがあります。

証明書の発行者は、URL: http://contoso.com/.well-known/pki-validation/godaddy.html に ping を実行し、ドメイン確認トークンが使用可能かどうかを確認します。ご使用のドメインで、アプリ内のドメイン確認トークンをホストする動作によって、証明書発行者に対する所有権が証明されます。対象アプリに対する認証が存在したり、対象アプリに対するトラフィックをフィルター処理する他の手段が講じられていたりする場合、証明書の発行者が証明書を確認できなくなる可能性があります。証明書発行者が確認 URL に関してインターネット接続できる必要があるのは、ドメイン確認プロセス時のみです。証明書によってトークン ファイルが発行されたら、他の変更を削除できます。
```

この手続きは、サーバー証明書の発行のために行われるため、サーバーに対するアクセスも http のみになります。インターネットからのアクセス拒否や https でのアクセスが強制になっている場合は動作しません。

個々で作成した "/.well-known/pki-validation/godaddy.html" のファイルは、証明書発行後は不要ですので、削除して問題ありません。


## App Service 証明書の注意点

- 証明書は自動更新が有効になっている場合、有効期限切れが近くなると手続きは自動的に開始されます。ただし、前回の確認から 395 日経過など、再度ドメインの所有権の検証が必要な場合は保留になります。速やかに検証を実施してください。[ドキュメント](https://learn.microsoft.com/ja-jp/azure/app-service/configure-ssl-app-service-certificate?tabs=portal#renew-an-app-service-certificate)
- 証明書の有効期限が切れた場合、更新することは出来ません。更新した場合も再発行した場合も別の証明書が発行されるだけなので、有効期限の切れた App Service 証明書を削除してしまい、新しく購入した方が早いです。

# まとめ
App Service におけるカスタムドメインや証明書の発行時に関する情報をまとめました。

クラウドはセルフサービス型で提供される都合上、各種セキュリティ要件 (サブドメインテイクオーバーへの対応など) の対応もユーザーが実施する必要があります。
企業のドメインを使用する場合、社内の申請などにより時間がかかる場合もあるので、調整の上で早めに動かれることをオススメします。