Azure App Service の Azure AD 認証追加を Azure CLI でやってみた

## 背景と目的

昔のテレワークは、会社に VPN 接続して社内業務を行うのが当たり前でした。ここ数年でゼロトラストが浸透し、クラウドインフラの機能が増えたおかげで VPN 接続しなくてもセキュアにテレワークを行う事が出来るようになりました。例えば、テレワークで社内業務アプリケーションを使うには、Azure AD アプリケーションプロキシや、アプリケーション自体に Azure AD 認証ライブラリ (MSAL) を組み込む事が考えられます。あと、Azure AD の条件付きアクセスも重要な要素です。今回は、社内業務アプリケーションを Azure App Service で作る場合に、お手軽に Azure AD 認証機能を追加する方法を Azure CLI で試してみました。

## 前提条件

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

```bash:bash
$ sw_vers
ProductName:    macOS
ProductVersion: 12.3.1
BuildVersion:   21E258

$ az version
{
  "azure-cli": "2.36.0",
  "azure-cli-core": "2.36.0",
  "azure-cli-telemetry": "1.0.6",
  "extensions": {}
}
```

## 検証用の Azure App Service を作成

```bash:bash
# 環境変数をセットします
region=japaneast
prefix=mnrappauth

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

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

# App Service を作成します（あとで環境変数をお手軽に表示したいのでランタイムは PHP にしました）
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
```

## Azure App Service に SSH 接続して index.php を作成

```bash:bash
# App Service へのリモート接続を作ります（今回は Opening tunnel on port: 54912 を表示されました）
az webapp create-remote-connection \
  --name ${prefix}-app \
  --resource-group ${prefix}-rg &

# 上で表示されたポート番号で SSH 接続します（パスワードは Docker! です）
ssh root@127.0.0.1 -p 54912

# index.php を作成します
echo '<?php phpinfo(); ?>' > site/wwwroot/index.php

# SSH 接続を終了します
exit

# App Service へのリモート接続を終了します（Ctrl+C）
fg

# 環境変数が表示されている事を確認します
curl -s https://${prefix}-app.azurewebsites.net | grep "PHP_VERSION"
```

## Azure AD 認証機能を追加

00000003-0000-0000-c000-000000000000 は、Microsoft Graph の ID です。

e1fe6dd8-ba31-4d61-89e7-88639da4683d は、User.Read の ID です。

```bash:bash
# Azure AD にアプリ登録を行います（アクセス許可として Microsoft Graph の User.Read を付与します）
appid=$(az ad app create \
  --display-name ${prefix}-app \
  --homepage https://${prefix}-app.azurewebsites.net \
  --reply-urls https://${prefix}-app.azurewebsites.net/.auth/login/aad/callback \
  --required-resource-accesse '[
    {
      "resourceAccess": [
        {
          "id": "e1fe6dd8-ba31-4d61-89e7-88639da4683d",
          "type": "Scope"
        }
      ],
      "resourceAppId": "00000003-0000-0000-c000-000000000000"
    }
  ]' \
  --query appId \
  --output tsv)

# App Service に Azure AD 認証機能を追加します
az webapp auth update \
  --name ${prefix}-app \
  --resource-group ${prefix}-rg \
  --enabled true \
  --action LoginWithAzureActiveDirectory \
  --aad-client-id $appid \
  --aad-token-issuer-url https://sts.windows.net/$(az account show --query tenantId --output tsv)

# ブラウザで App Service にアクセスします（承諾画面が表示されます）
open https://${prefix}-app.azurewebsites.net
```

## 認証済みの環境変数

認証済みの情報として、下記の環境変数がアプリケーションから取得出来るようになります。HTTP_X_MS_CLIENT_PRINCIPAL は Base64 エンコードされているので、アプリケーション側でデコードする必要がありますが、JSON 形式で surname や givenname や name も取得する事が出来ました。

```bash:bash
$_SERVER['HTTP_X_MS_CLIENT_PRINCIPAL_NAME']
$_SERVER['HTTP_X_MS_CLIENT_PRINCIPAL_ID']
$_SERVER['HTTP_X_MS_CLIENT_PRINCIPAL_IDP']
$_SERVER['HTTP_X_MS_CLIENT_PRINCIPAL']
```

## 参考

```bash:bash
# アプリ登録を削除します
az ad sp delete --id $appid

# リソースグループを削除します
az group delete \
  --name ${prefix}-rg \
  --yes
```

https://docs.microsoft.com/ja-jp/azure/app-service/configure-authentication-provider-aad

https://docs.microsoft.com/ja-jp/azure/app-service/scenario-secure-app-authentication-app-service

https://docs.microsoft.com/ja-jp/graph/permissions-reference

https://docs.microsoft.com/ja-jp/azure/app-service/scenario-secure-app-access-microsoft-graph-as-app?tabs=azure-cli