App Service Environment を用いて App Service にルート証明書を取り組む

# はじめに
本記事は [Microsoft Azure Tech Advent Calendar 2020](https://qiita.com/advent-calendar/2020/microsoft-azure-tech) の投稿です。App Service にルート証明書を取り組むことはできるのかといったお問い合わせを度々いただきます。そこで、本稿ではその辺りを触れつつ、[App Service Environment](https://docs.microsoft.com/ja-jp/azure/app-service/environment/intro)（以後 ASE）を用いて、Windows の App Service にルート証明書を取り組む方法をご紹介します。

# 概要
App Service でルート証明書を読み込ませる場合、Web Apps をホストしている Worker ([こちらの記事](https://qiita.com/mym/items/1d364c0251daf88d417d#web-workers)で詳細に書かれています) と呼ばれる VM の Windows 証明書ストアにルート証明書を保存する必要があります。しかしながら、通常の Web Apps の場合、Worker はユーザー専用のものではないため、ユーザーから Worker の Windows 証明書ストアを操作することはできません。そのため、任意の場所にルート証明書として保存することができず、結果 App Service にルート証明書を取り組むことはできません。

このままでは本末転倒になりそうですが、ASE を用いると、ユーザー専用の Worker 等が確保されるため、App Service にルート証明書を取り組むことができます。

# 検証準備
それでは、実際に ASE に属する App Service にルート証明書を取り組むことができるか検証してみましょう。
今回は、ルート証明書を取り組んだ App Service から、同様のルート証明書で署名したサーバ証明書を用意し、それを取り組んだ HTTP サーバーに、HTTPS 通信で特定の HTML ファイルの内容を取得できるか検証してみます。また、自己署名したルート証明書を作成して利用します。初めに、検証の準備を行います。

## HTTP サーバーの準備
まずは、Azure VM（Linux）を作成し、HTTP サーバーの Nginx を立てます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/679419/e5de3a53-ab5b-3070-bd24-bda3604f161a.png)
次に、ルート証明書のキー "contoso.key" と、ルート証明書 ”contoso.crt" を作成し、自己署名します。その後、サーバー証明書のキー "fabrikam.key" と、Linux VM の FQDN を Common Name として指定した、サーバー証明書 "fabrikam.crt" を作成し、作成したルート証明書で署名します。そして、farbrikam.crt と farbrikam.key を、Nginx に割り当てます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/679419/eb938a8b-7d37-f88f-4caa-0a2892a6cb68.png)
ルート証明書、サーバー証明書の詳細な作成方法については、下記のドキュメントをご参照ください。
https://docs.microsoft.com/ja-jp/azure/application-gateway/self-signed-certificates#create-a-root-ca-certificate

## HTTP クライアントの準備 
初めに、Visual Studio で、Nginx の HTML ファイルの内容を取得する .NET Core の Web アプリケーションを作成します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/679419/846fb9ae-815b-7d9c-d6d4-dec5d13019de.png)
まずは、証明書を用いずに、HTTP 通信で、Nginx の HTML ファイルの内容を取得するようにします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/679419/837d024f-25e5-2bf8-87c5-d1cc06e6b3b9.png)
Web Apps を .NET Core 3.1 で作成し、先ほど作成した Web アプリケーションをデプロイします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/679419/34b6b4b8-7435-bf93-086c-64b8efe7dde7.png)
その後、アプリケーションをデプロイした App Service にアクセスすると、Nginx の HTML ファイルの内容を取得できています。今回は HTTP で通信しましたが、HTTPS で通信した際にも下記と同様の結果が返ってきたら、今回の検証が成功したことになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/679419/a54c648a-8159-f91b-7e88-e9263e9e9ee9.png)

# App Service で検証
それでは、実際に検証していきましょう。
まずは、App Service にルート証明書を取り組み、HTTPS 通信で Nginx の HTML ファイルの内容を取得ができるか検証してみます。Nginx で作成したルート証明書 ”contoso.crt” を ”contoso.cer” に変換し、App Service の [TLS/SSL の設定] - [公開キー証明書 (.cer)] - [+ 公開キー証明書のアップロード] を開き、ルート証明書 ”contoso.cer” をアップロードします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/679419/ecc3da71-ffdc-0c22-7fcb-01d63f65aba8.png)
補足になりますが、アプリコードで証明書にアクセスするには、Azure CLI で下記のコマンドを実行し、該当 App Service の [アプリケーション設定] に拇印を追加する必要があります。（今回は追加しません。）

```言語:AzureCLI
az webapp config appsettings set --name <app-name> --resource-group <resource-group-name> --settings WEBSITE_LOAD_CERTIFICATES=<comma-separated-certificate-thumbprints>
```

先ほど作成した Web アプリケーションを HTTPS 通信で、Nginx の HTML ファイルの内容を取得するように変更し、再度 App Service へデプロイします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/679419/df32e061-e54d-d0a2-d08d-bd40c01fb226.png)
その後、アプリケーションをデプロイした App Service にアクセスし、Nginx から HTML ファイルの内容を取得できるか見てみると。。。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/679419/fb29e79d-73e9-ad80-906d-c8a8d1bb7198.png)
やはり、アップロードしたルート証明書が適切に適用されておらず、Nginx に対して HTTPS 通信が正しく確立されませんでした。

# ASE に属した App Service で検証
では、ASE に属した App Service で検証してみましょう。
まずは、新しくASE に属した App Service を作成します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/679419/dd3602ba-b5af-6f68-03f5-700957f9675a.png)
作成後、上記で説明したのと同様に、HTTPS 通信で Nginx の HTML ファイルの内容を取得する Web アプリケーションをデプロイし、ルート証明書をアップロードします。

加えて、ASE にルート証明書を読み込ませる場合、該当 App Service の [アプリケーション設定] に、”WEBSITE_LOAD_ROOT_CERTIFICATES” の設定を追加する必要があります。まずは、該当 App Service で [TLS/SSL の設定] - [公開キー証明書 (.cer)] を開き、アップロードしたルート証明書のサムプリント値をコピーします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/679419/35885c16-a3e2-6d1b-8b6f-d5f2f46416a8.png)
その後、該当 App Service の [構成] を開き、[+ 新しいアプリケーション設定] から、下記のアプリケーション設定を追加し、保存します。

|名前  |値  |
|---|---|
|WEBSITE_LOAD_ROOT_CERTIFICATES  |アップロードしたルート証明書のサムプリント値 |

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/679419/79056d58-8a95-4d37-391d-4a82bfbe81e6.png)
これで準備は整いました。App Service で、デプロイしたアプリケーションを開き、HTTPS 通信で Nginx の HTML ファイル内容を取得できているか確認すると。。。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/679419/f162edb9-689e-ffd9-105e-c25a204430db.png)
無事、Nginx から HTTPS 通信で取得できました。

# まとめ
このように、ASE を用いた App Service の場合、ルート証明書を取り入れることができます。ASE は比較的価格が高くはありますが、既に ASE を利用している場合や、ルート証明書をどうしても App Service に取り組みたい場合など、様々な利用シーンで参考になれば幸いです。また、今回は Windows の .NET Core で検証してみましたが、Linux や違う言語の場合、動作や追加の設定が変わるかもしれませんので、ご注意いただけたらと思います。