App Service Linux で HTTPS リバースプロキシーを試してみた

## 背景と目的

App Service Linux の PHP ランタイムには、Apache と HTTPS リバースプロキシーに必要なモジュールが入っているので、App Service のスタートアップスクリプトを利用して HTTPS リバースプロキシーを有効にします。これが出来れば、App Service の無料TLS証明書など便利な機能を享受しつつ VNET 統合からのサービスエンドポイント経由で Storage Account の静的サイトなど VNET 内の様々なリソースにアクセスする事が容易になります。

## 前提条件

検証コマンドの実施環境は、Mac + Azure CLI です。

```zsh:zsh
% sw_vers
ProductName:    macOS
ProductVersion: 11.4
BuildVersion:   20F71

% az version
{
  "azure-cli": "2.25.0",
  "azure-cli-core": "2.25.0",
  "azure-cli-telemetry": "1.0.6",
  "extensions": {}
}
```

## 実施内容

App Service を作成後、SSH 接続してリバースプロキシーの設定ファイルを作成します。

```zsh:zah
# 環境変数をセットします
region=japaneast
prefix=mnrappsvclnx

# リソースグループを作成します
az group create \
  --name ${prefix}-rg \
  --location $region

# App Service Plan を作成します
az appservice plan create \
  --name ${prefix}-plan \
  --resource-group ${prefix}-rg \
  --is-linux \
  --sku B1

# App Service を作成します
az webapp create \
  --name ${prefix}-app \
  --resource-group ${prefix}-rg \
  --plan ${prefix}-plan \
  --runtime "PHP|7.4"

# App Service のデフォルトページにアクセス出来ることを確認します
curl -s https://${prefix}-app.azurewebsites.net

# SSH トンネルを開きます
az webapp create-remote-connection \
  --name ${prefix}-app \
  --resource-group ${prefix}-rg &

# しばらくすると下記のメッセージが表示されます
Verifying if app is running....
App is running. Trying to establish tunnel connection...
Opening tunnel on port: 50093
SSH is available { username: root, password: Docker! }
Ctrl + C to close

# 上記ポート番号で SSH 接続し App Service にログインします
ssh root@127.0.0.1 -p 50093
```

```bash:bash
# パスワードは Docker! です
root@127.0.0.1\'s password: 
  _____                               
  /  _  \ __________ _________   ____  
 /  /_\  \___   /  |  \_  __ \_/ __ \ 
/    |    \/    /|  |  /|  | \/\  ___/ 
\____|__  /_____ \____/ |__|    \___  >
        \/      \/                  \/ 
A P P   S E R V I C E   O N   L I N U X

Documentation: http://aka.ms/webapp-linux
PHP quickstart: https://aka.ms/php-qs
PHP version : 7.4.16
Note: Any data outside '/home' is not persisted

# Apache が起動していることを確認します
root@38d1e44dfa3c:/home# ps auxww
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root         1  0.0  0.0   2384   656 ?        SNs  11:29   0:00 /bin/sh /opt/startup/startup.sh
root        24  0.0  0.2  15848  4184 ?        SNs  11:29   0:00 /usr/sbin/sshd
root        30  0.3  1.7 250104 35432 ?        SN   11:29   0:00 apache2 -DFOREGROUND
www-data    41  0.0  0.6 250608 12304 ?        SN   11:29   0:00 apache2 -DFOREGROUND
www-data    42  0.0  0.5 250192 11612 ?        SN   11:29   0:00 apache2 -DFOREGROUND
www-data    43  0.0  0.5 250184 11612 ?        SN   11:29   0:00 apache2 -DFOREGROUND
www-data    44  0.0  0.5 250192 11608 ?        SN   11:29   0:00 apache2 -DFOREGROUND
www-data    45  0.0  0.5 250192 11608 ?        SN   11:29   0:00 apache2 -DFOREGROUND
www-data    46  0.0  0.5 250136  9972 ?        SN   11:29   0:00 apache2 -DFOREGROUND
www-data    47  0.0  0.5 250136  9972 ?        SN   11:29   0:00 apache2 -DFOREGROUND
root        49  0.0  0.3  15848  7036 ?        SNs  11:30   0:00 sshd: root@pts/0
root        51  0.0  0.1   3996  3136 pts/0    SNs  11:30   0:00 -bash
root        54  0.0  0.1   7636  2720 pts/0    RN+  11:31   0:00 ps auxww

# リバースプロキシーの設定ファイルを App Service のスタートアップスクリプトから生成します
oot@38d1e44dfa3c:/home# cat << EOS > setup.sh
cat << EOF > /etc/apache2/conf-enabled/reverse-proxy.conf
LoadModule proxy_module /usr/lib/apache2/modules/mod_proxy.so
LoadModule proxy_http_module /usr/lib/apache2/modules/mod_proxy_http.so
LoadModule ssl_module /usr/lib/apache2/modules/mod_ssl.so
ProxyRequests Off
SSLProxyEngine On
ProxyPass /test https://example.com/
ProxyPassReverse /test https://example.com/
EOF
EOS

# PHP INFO を表示してモジュールが有効になっているか確認します
root@38d1e44dfa3c:/home# echo '<?php phpinfo(); ?>' > site/wwwroot/index.php

# SSH 接続を終了します
root@38d1e44dfa3c:/home# exit
```

```zsh:zsh
# バックグラウンドプロセスをフォアグランドにした後、Ctrl+C で SSH トンネルを閉じます
fg

# リバースプロキシーが有効になる前にモジュールの状態を確認します
curl -s https://${prefix}-app.azurewebsites.net | grep mod_

<tr><td class="e">Loaded Modules </td><td class="v">core mod_so mod_watchdog http_core mod_log_config mod_logio mod_version mod_unixd mod_access_compat mod_alias mod_auth_basic mod_authn_core mod_authn_file mod_authz_core mod_authz_host mod_authz_user mod_autoindex mod_deflate mod_dir mod_env mod_expires mod_filter mod_headers mod_include mod_mime prefork mod_negotiation mod_php7 mod_remoteip mod_reqtimeout mod_rewrite mod_setenvif mod_status </td></tr>

# App Service のスタートアップスクリプトを設定します
az webapp config set \
  --name ${prefix}-app \
  --resource-group ${prefix}-rg \
  --startup-file "/home/setup.sh"
```

## 実施結果

```zsh:zah
# リバースプロキシーが有効になったことを追加されたモジュールで確認します
curl -s https://${prefix}-app.azurewebsites.net | grep mod_     

<tr><td class="e">Loaded Modules </td><td class="v">core mod_so mod_watchdog http_core mod_log_config mod_logio mod_version mod_unixd mod_access_compat mod_alias mod_auth_basic mod_authn_core mod_authn_file mod_authz_core mod_authz_host mod_authz_user mod_autoindex mod_deflate mod_dir mod_env mod_expires mod_filter mod_headers mod_include mod_mime prefork mod_negotiation mod_php7 mod_remoteip mod_reqtimeout mod_rewrite mod_setenvif mod_status mod_proxy mod_proxy_http mod_ssl </td></tr>

# リバースプロキシー経由で https://example.com にアクセス出来ることを確認します
curl -s https://${prefix}-app.azurewebsites.net/test | grep Example
    <title>Example Domain</title>
    <h1>Example Domain</h1>
```

## 参考

作成したリソースを削除します。

```zsh:zsh
az group delete \
  --name ${prefix}-rg
```