Application GatewayとApp Serviceに同じカスタムドメインを設定する

# Azure Application GatewayをReverse Proxyとしたときの問題点

Application Gatewayにwww.hoge.comなどのカスタムドメインを設定して、Backend Poolにはfuga.azurewebsites.netみたいなPrivate EndpointのFQDNを設定したい、、、というのが普通な考えに思えてしまうのだが。

実はそれだけだとリダイレクトの問題というのが発生してしまい、一筋縄ではいかないらしい。

https://jpaztech.github.io/blog/network/appgw-appservice-redirectissue/

https://logico-jp.io/2024/03/09/configure-custom-domain-on-application-gateway/

要はクライアントからはApplication GatewayのFQDNにアクセスしているが、バックエンドプールには別のApp ServiceのFQDNでアクセスしている状態。その場合、WebAppsはPoolにはfuga.azurewebsites.netのようなFQDNでアクセスされることを期待しているのだが、実際はwwww.hoge.comのホスト名でアクセスされてしまい、リダイレクトが発生してしまう。最終的にユーザーにfuga.azurewebsites.netのURLが見えてしまうし、場合によってはApplication Gatewayをスキップしてそっちに直接アクセスしてしまう可能性がある。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/654538/5df0f1ce-94a7-d238-dbfc-2045fe955e7c.png)

一番簡単な解決策としてはホスト名の上書きというのがあるので、Application GatewayでバックエンドのHost名でで無理やり上書きにできる。それを有効にしてしまえばいいのだが、それはそれで問題が起こるときがある。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/654538/d1956e55-e5da-6558-21fc-f0970089db2a.png)

https://learn.microsoft.com/ja-jp/azure/architecture/best-practices/host-name-preservation


# 解決策
解決策としては先ほどの上のgithubのサポートブログにある通り、以下2種類。

> カスタム ドメインをつかう
> Application Gateway V1 SKU を利用の場合、または V2 SKU を利用しているものの referer ヘッダーや Cookie などにもドメインが含まれていて書き換えでの対応が複雑となる場合
>　
> Application Gateway の書き換え規則をつかう
> Application Gateway V2 SKU を利用の場合で、Location ヘッダーのみの書き換えで対応が可能な場合

Microsoft推奨はカスタムドメインを設定する法なのだが、どうも手順が見つからない。いや、さっきのGithubのサポートブログに書いてあるのだが、自分の頭ではパッと理解できない。NW周り等慣れている人には当たり前なのかもしれないけど、苦戦してしまったのでメモを残す。

# カスタムドメインをFrontとBack両方に設定する方法
Application GatewayとApp Serviceの両方に同じカスタムドメインを使う方法を試してみる。実際Microsoftのドキュメントではこれが推奨となっている。

https://learn.microsoft.com/ja-jp/azure/application-gateway/configure-web-app?tabs=customdomain%2Cazure-portal

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/654538/c1978f2b-4de3-fda8-9ba7-324c50979d4d.png)

やることとしては以下の感じで。
- Application GatewayからWebAppsにPrivate Endpoint経由でアクセスしたい。
- App Serviceは直接アクセスは不可にする。
- Application Gatewayにはカスタムドメインでアクセスできるようにする。
- Application GatewayとApp Service間もHTTPS化する。

参考：

https://learn.microsoft.com/en-us/answers/questions/1361123/custom-domain-for-private-app-service


## やってみる

前提として
1. お名前.comでsimari.xyzというドメインを取得しています。
1. 証明書は高いので、自己署名証明書を利用します。
1. 動作確認用に同じVNet内にVMを立てます。
1. DNSを変更した後は適宜ipconfig /flushdnsが必要ですが、手順からは省いています。

## Application GatewayとApp ServiceをPrivate Endpointでつなぐ
App Service のプライベートエンドポイントを作成します。これは以下のサイトに手順があったので、省略。

https://zenn.dev/microsoft/articles/20240113-appgw-webapp-pe

## Private DNS Zone作成

今回取得したドメイン名と同じ名前でPrivate DNS Zoneを作成し、App ServiceのPrivate EndpointのIPに対してAレコードを作成します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/654538/9d1ddd77-b6dc-d5b0-20db-fe1d72790e84.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/654538/6bf96864-e569-7ecd-c917-fad1cc924364.png)

VNetにLink。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/654538/b37c85ed-3a2b-b30c-4046-f28bc90e9594.png)

動作確認用VMからnslookupでwww.simari.xyzにアクセスしてみるとPrivate IPで解決されることを確認。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/654538/5ef894f4-0439-fac6-ba2e-d00a2a7d29dd.png)

## App Serviceにもカスタムドメインをセット

https://www.sigmact.com/updated/zero-to-hero/part4-customdomain/#add-custom-domain

https://learn.microsoft.com/ja-jp/azure/app-service/app-service-web-tutorial-custom-domain?tabs=root%2Cazurecli

Domainにお名前.comで購入したドメインを入力すると、Validationのための値が出力される。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/654538/d04ed3fc-fc1a-fa7d-f6d4-e42cd65de19d.png)

お名前.com側でレコード追加する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/654538/a039002c-4fa1-41a6-4e56-d6d68c8a7687.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/654538/06a37bc9-5892-4a18-4ab5-35d62e071a6e.png)

DNSレコード設定を利用するを選択。
（ここは最低限TXTレコードだけあれば良い。実はこのApp Serviceに設定したカスタムドメインはPublic IPで解決するものなので、実際には使われないのだ。なんか裏技ぽい。）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/654538/e67f7187-0dc1-b730-5f1d-8af77dde767f.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/654538/5c9e3665-c832-d580-18ee-cd75c7915fc0.png)

少し時間がかかるが、これでAddできるようになる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/654538/947284c2-b7e5-5936-a95e-ecf97aee2dc3.png)

## Bindingを追加

このままだとカスタムドメインは設定できたが、証明書が設定されていない状態。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/654538/407f414f-7c7f-2761-a766-6e56fe427513.png)

### 自己署名証明書を作成

基本的には以下の手順に則ればOK。
注意点として、CNはカスタムドメイン名と同じ（今回はwww.simari.xyz）にしておく必要がある。

https://learn.microsoft.com/ja-jp/entra/identity-platform/howto-create-self-signed-certificate#optional-export-your-public-certificate-with-its-private-key

```
$cert = New-SelfSignedCertificate `
 -Subject "CN=www.simari.xyz" `
 -CertStoreLocation "Cert:\CurrentUser\My" `
 -KeyExportPolicy Exportable `
 -KeySpec Signature `
 -KeyLength 2048 `
 -KeyAlgorithm RSA `
 -HashAlgorithm SHA256

$cert | Format-List

# 秘密鍵なしのcer
Export-Certificate -Cert $cert -FilePath "C:\work\certificate2.cer"

$password = ConvertTo-SecureString -String "`{PASSWORD}" -Force -AsPlainText

# 秘密鍵ありのpfx
Export-PfxCertificate -Cert $cert -FilePath "C:\work\certificate2.pfx" -Password $password
```

### Add binding
Add bindingから。本当はKV使ったほうがいいんだけど、力尽きたためUploadで。。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/654538/e18c3880-3d83-81c4-d633-144342296b23.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/654538/b33ed320-b947-a368-1563-1ff5593843e2.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/654538/0a7a0852-2496-3ad7-b672-3e5537c77888.png)

## お名前.com側でApplication GatewayのPublic IPのAレコード追加

Application GatewayのPublic IPを確認。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/654538/34a8faf2-697d-adc8-fb66-d5015fb6b946.png)

お名前.comに追加。
これでApplication Gatewayもwww.simari.xyzでアクセスできるようになる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/654538/9b5b2556-b5c4-195e-5b6c-f1be32d96a65.png)
（この時同時にさっき追加したApp Serviceのレコードを消しても良い。そう、App Serviceのお名前.comのDNSレコードはApp Serviceにカスタムドメインを設定したいから必要になっただけであって、Public IPで名前解決されることは一度もないので最終的に不要なのだ。）


## Application GatewayのBackend settingsもCertificateを追加
App Serviceに設定したものと同じCertificateを追加。（※これはApplication GatewayからBackendの通信のためのCertificate。）
ここはOverride with new hostnameをNoにするのが大事。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/654538/6db2d313-c8fc-cae2-eec9-2c9d396346d5.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/654538/8e42fdb7-ef1f-7577-7459-a9b0c24a81f9.png)

## ListenerにもCertificateを追加

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/654538/85c88a44-d1b6-af2d-0a14-3338dbc46067.png)

Listener側にもCertificateを設定。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/654538/b1dad967-d203-fd64-7286-430b6f209126.png)


## 動作確認
Httpsで通信するhelath probeを設定して。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/654538/9dba13a6-3b5b-3514-73a4-f343470f3093.png)

Backend healthでグリーンなことを確認。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/654538/286e7968-0f1a-c971-3f09-a1def287cbfd.png)

VMからではなく、インターネット経由で設定したカスタムドメインにアクセスしてサイトが表示されることを確認。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/654538/80bcc7d5-473b-a2a6-5004-ab1c8c41c776.png)

最初に挙げたgithubのサポートブログのようにRedirectが走っていないのが確認できる。OK！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/654538/dbad0754-6f25-b05a-90c1-38c435e70f5f.png)


# 参考
未来の自分用メモとしてApplication gatewayの設定のスクショを残す。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/654538/4763804e-5814-80dd-c7a1-aa8d52f57b49.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/654538/55314d29-155f-27fd-1136-f5cddeeb26fc.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/654538/23c56f64-d81d-ccff-88b0-bb5105bcf9d3.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/654538/2f5d31a8-e5c4-7c4a-0105-851075fb4856.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/654538/30464db9-724b-ec2b-2f17-81ac85ede525.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/654538/37dda338-e599-99f4-a465-e1c45b0fddc2.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/654538/554763b2-d9cb-77f8-dd87-de18f94ff573.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/654538/727c14ee-ece8-325a-8f1c-0348ea65655e.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/654538/f5885349-c465-ffed-7d22-a4155190c7f2.png)