Azure Application Gateway v2 の証明書更新を自動化する

Azure の Application Gateway はリバースプロキシの機能を提供するもので、インターネットやオンプレから Web サーバーへのアクセスの際のフロントエンドとして利用することが多々あります。Application Gateway には SSL オフロード、負荷分散、ヘッダー書き換え、Web Application Firewall 等の様々な機能があり、かつ Azure のマネージドサービスであるため、Web サーバーを構成する際にはセットで利用されることが多いです。

https://docs.microsoft.com/ja-jp/azure/application-gateway/overview

Application Gateway の V2 SKU では Key Vault 連携による証明書の管理がサポートされておりますが、別途 AppService 証明書と連携することで証明書の管理を自動化することができます ( [※AppService 証明書の更新でドメイン検証が必要](https://azure.github.io/jpazpaas/2022/08/26/2022-08-25-App-Service-Certificate-Renewal.html) ) ので、以下に手順を記載します。**Application Gateway には証明書を発行する機能はありません。**

参考ドキュメント

https://docs.microsoft.com/ja-jp/azure/application-gateway/configure-key-vault-portal

## 前提

- Azure Powershell を利用できる環境があること
- Application Gateway v2 SKU (Standard or WAF) を作成済みであること
- バックエンド用の Web サーバーを構成し、アクセスできる構成となってること
- Azure Key Vault のキーコンテナを作成済みであること
- 有効なドメインを所有していること (この例では購入済みの AppService ドメインを利用しています)
※ AppService ドメインは AppService という名はついてますが、AppService の以外の Azure サービスでも利用可能です。

https://docs.microsoft.com/ja-jp/azure/app-service/manage-custom-dns-buy-domain#buy-an-app-service-domain

## 1. AppService 証明書の作成
Azure ポータルにて App Service 証明書を選択し、作成していきます。
以下の画面の様にサブスクリプション、リソースグループ、SKU、ネイキッド ドメインのホスト名、証明書名、自動更新を設定します。
ワイルドカード証明書を利用したい場合、SKU をワイルドカードにします。
Standard の場合、ネイキッド ドメインのホスト名が証明書の Common Name (CN) となります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2266293/f83979d6-199a-74e3-fc98-82df1308d701.png)

証明書の作成が完了したら、Key Vault へのインポートとドメインの検証を行っていきます。 <font color="Red">**リソースを作成しただけでは使えません。**</front>

作成した AppService 証明書を選択し、**"証明書の構成 > [手順1: 格納]"** を選択します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2266293/f19ddda7-9724-de01-59f3-0a6f6218da86.png)

キー コンテナーから選ぶをクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2266293/9b89e63c-f7e2-8dbd-82b7-757576bd7129.png)

事前に作成しておいたキーコンテナを選択します。(キーコンテナがない場合は新規作成でも問題ありません)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2266293/d7b770dd-7eef-467c-9543-8a382e1c2fc7.png)

キーコンテナへのインポートが完了したら、**"証明書の構成 > [手順2: 確認]"** を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2266293/778957be-4cb8-3f60-16b1-fd27319c2975.png)

ドメインの検証を行います。ドメインの検証は DNS による TXT レコード、ドメイン管理者宛てのメール、HTML の Web ページ (ワイルドカード不可) のいずれかがサポートされています。

**1.ドメインの検証**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2266293/bfdc332a-7a38-3c1c-0d4c-39af6772768b.png)

**2. メールによる確認**
**ドメイン管理者宛てのメールで行う必要があります。**[電子メールの指示] でその他のメールアドレス宛てにメール送信してもドメインの検証を行うことはできません。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2266293/f41d4f71-111b-a33e-9544-36a7898685e5.png)

**3. DNS または Web ページによる確認**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2266293/cc54c688-04c7-219d-9eb3-43a21748d9dc.png)

Azure DNS に頂点ドメイン (@) として上記で指定された TXT レコードを追加します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2266293/8fd00e9e-3915-0fc1-065c-0ab70c669a13.png)

先ほどのドメインの検証画面で、確認をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2266293/6c8b8006-4c59-02e9-70a6-e547f7f1c1ed.png)

ドメインの確認が成功したことを確認します。<font color="Red">**この時点で証明書のエクスポート等が可能となります。**</front>
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2266293/f98e6479-524b-4125-e353-79ca104635c8.png)

## 2. 証明書のシークレット名の確認

証明書のエクスポートから "Key Vault シークレットをひらく" をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2266293/60f4ca7f-d9fa-0107-18d2-b5a775b0e0f8.png)

Key Vault シークレットが表示されるのでシークレット名を控えておきます。後で使います。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2266293/44049eae-7515-2c4e-3fe2-b80f290b589f.png)

## 3. Application Gateway へ証明書を追加

Powershell を管理者権限で起動し、以下のコマンドでログインします。**Key Vualt のシークレットは Azure ポータルから指定することができないので Powershell を使います。**

```
Connect-AzAccount

#複数サブスクリプションがある場合、サブスクリプションを指定します。
Set-AzContext -SubscriptionId <サブスクリプション ID>
```

Application Gateway の情報を変数に格納します。
```
$appgw = Get-AzApplicationGateway -Name "アプリケーションゲートウェイ名" -ResourceGroupName "リソースグループ名"
```

証明書を配置した Key Vault (キーコンテナ) の情報を変数に格納します。

```
$keyVault = Get-AzKeyVault -VaultName "キーコンテナ名" -ResourceGroupName "リソースグループ名"
```

Managed ID 用のモジュールをインストールします。
```
Install-Module -Name Az.ManagedServiceIdentity
```

ユーザーマネージド ID を作成します。リージョン名は japaneast 等。
```
$identity = New-AzUserAssignedIdentity -Name "任意のマネージド ID 名" -Location "リージョン名" -ResourceGroupName "リソースグループ名"
```

Key Vault シークレットの取得権限を、上記で作成したユーザーマネージド ID に付与します。
```
Set-AzKeyVaultAccessPolicy -VaultName $keyVault.VaultName -PermissionsToSecrets get -ObjectId $identity.PrincipalId
```

シークレットの情報を取得します。 Name は先ほど控えておいたシークレット名 (例: appgwv20bdefcd6-f874-49fd-922f-93a5cad0fa4c) を使います。
```
$secret = Get-AzKeyVaultSecret -VaultName $keyVault.VaultName -Name "シークレット名"
```

シークレットID からバージョン部分の削除を削除します。バージョン情報を削除することで AppService 証明書が更新された際に自動的に Application Gateway 側の証明書も更新されます。**バージョンが入っていると、自動更新はされません。**
```
$secretId = $secret.Id.Replace($secret.Version, "")
```

Application Gateway に Key Vault のシークレットID を追加します。
```
Add-AzApplicationGatewaySslCertificate -ApplicationGateway $appgw -Name "任意の証明書の名前" -KeyVaultSecretId $secretId
```

Application Gateway に先ほど作成したユーザーマネージド ID を割り当てます。
```
Set-AzApplicationGatewayIdentity -ApplicationGateway $appgw -UserAssignedIdentityId $identity.Id
```

Application Gateway に設定を反映させます。**これをやらないと今までの設定が反映されません。**
```
Set-AzApplicationGateway -ApplicationGateway $appgw
```

Azure ポータルに戻り、Application Gateway のリスナーの画面から、追加した証明書を選択して、保存します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2266293/8fe19939-2941-b949-70d4-ce38e7f10b4a.png)

実際にアクセスして、証明書が Go Daddy から発行されたものであることを確認します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2266293/cdb75b91-75ca-8bf8-a5a6-a7a30d50ef45.png)

AppService 証明書の "キー更新と同期" の画面から確認できる証明書の拇印とブラウザから確認できる拇印が同じであることを確認します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2266293/fde545e3-6db4-f4a1-3950-12a5a1863bed.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2266293/9057caaa-f1f2-254b-8d17-cc70a5b8b997.png)

## 4. 自動更新の動作確認

App Service 証明書からキー更新を行います。(検証のため手動で証明書の更新を行います)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2266293/cbfed271-dcd5-cb65-1d14-d6d993e20b04.png)

10 分程度経過後、再度確認すると証明書の拇印が更新されています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2266293/fc53b5fb-8af6-405d-8554-fb3c56d8a8c4.png)

4 時間経過後に、Application Gateway にアクセスして、証明書の拇印を確認します。**この 4 時間というのは Application Gateway から Key Vault へのポーリング間隔です。**
即時に更新したい場合、何らかの更新を Application Gateway に行うことで Key Vault との連携が行われ証明書を更新できます。

私の環境では 2 時間後に自動的に更新されてました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2266293/3964142d-c139-cf4a-acd9-dfbdf710951f.png)