Private Endpoint が有効な(パブリックネットワークアクセスが無効な) App Service に デプロイを行う方法　その 2

# はじめに

https://qiita.com/georgeOsdDev@github/items/1827c2a5bc15db214cff

に対する回避策 2 となります。
この記事では、アクセス制限ルール を利用してデプロイを行う方法について記載します。

# 回避策

「Private Endpoint を有効にする」という状態と、「パブリックネットワークアクセスを無効にする」という状態は別の意味を持つことは前回の記事で記載しています。

この記事の回避策では、[アクセス制限規則](https://learn.microsoft.com/ja-jp/azure/app-service/app-service-ip-restrictions?tabs=azurecli) を用いて、

 - Private Endpoint は有効
 - パブリックネットワークアクセスは有効
 - ただし、アクセス制限規則を用いてパブリックネットワークアクセスはすべてブロックする

といった状態にし、デプロイ実行時のみ、デプロイ元からのアクセスを許可することでデプロイできるようにします。

## アクセス制限規則を用いてパブリックネットワークアクセスはすべてブロックする

[アクセス制限規則](https://learn.microsoft.com/ja-jp/azure/app-service/app-service-ip-restrictions?tabs=azurecli) は、Private Endpoint を経由しないリクエストに対して適用されます。
以下のようにルールに一致しないアクションを「拒否」に設定し、ルールを1件も構成しない場合、暗黙的にすべてのアクセスが拒否されるようになります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4914/ada55807-512c-c57f-284d-c9cb33b9ccee.png)

> ルールが一致しない場合 (既定のアクション) の動作を構成できます。 これは、ルール コレクションの最後のルールとして常に表示される特別なルールです。 設定が構成されていない場合、一致しないルールの動作は、1 つ以上のルールが存在しない限り、すべてのアクセスを許可することです。その後、すべてのアクセスを拒否するように暗黙的に変更されます。 この動作は、定義されたルールに関係なく、アクセスを許可または拒否するように明示的に構成できます。

また、ルールは SCM サイト(Kudu) 用に個別に構成することができ、 SCM サイト(Kudu) 側も同様に一致しないルールのアクションは「拒否」とします。

これによって、

 - Private Endpoint は有効
 - パブリックネットワークアクセスは有効
 - ただし、アクセス制限規則を用いてパブリックネットワークアクセスはすべてブロックする

といった状態となります。

## デプロイ時にのみ SCM サイトへのパブリックネットワークアクセスを許可する方法

アクセス制限規則は、az cli や Rest API から変更することができます。

https://learn.microsoft.com/ja-jp/cli/azure/webapp/config/access-restriction?view=azure-cli-latest

## 追加
```bash
az webapp config access-restriction add -n $appname -g $rgName --rule-name temporary-allow --action Allow --ip-address <アクセス元IP> --priority 100 --scm-site true
```

## 削除
```bash
az webapp config access-restriction remove -n $appname -g $rgName --rule-name temporary-allow --scm-site true
```

これによって、追加処理 ~ 削除処理を行うまでの間は、一時的に SCM サイト(Kudu) に対してパブリックネットワークアクセスが可能となり、zip デプロイ等のエンドポイントを利用することが可能となります。

## GitHub Actions で一連の処理を行う

以下のワークフローではジョブが実行されているホストの送信 IP を取得し、一時的に許可ルールを追加、デプロイ、許可ルールを削除といった処理を行っています。

```yaml
  deploy:
    runs-on: ubuntu-latest
    needs: build
    environment:
      name: 'Production'
      url: ${{ steps.deploy-to-webapp.outputs.webapp-url }}

    steps:
      - name: Download artifact from build job
        uses: actions/download-artifact@v2
        with:
          name: node-app

      - name: Check current ip
        id: current_ip_checker
        shell: bash
        run: |
          IP=$(curl https://checkip.amazonaws.com/)
          echo "CURRENT_IP=$IP" >> $GITHUB_OUTPUT

      - name: Azure Login
        uses: azure/login@v1
        with:
          creds: ${{ secrets.AZURE_CREDENTIALS }}

      - name: Add access rule
        uses: azure/CLI@v1
        with:
          azcliversion: 2.30.0
          inlineScript: |
            az webapp config access-restriction add  -n webapp-deploy-test2023 -g toshida-qiita-2022 --rule-name ghaction_${{ github.run_id }} --action Allow --ip-address ${{ steps.current_ip_checker.outputs.CURRENT_IP }} --priority 100 --scm-site true

      - name: 'Deploy to Azure Web App'
        id: deploy-to-webapp
        uses: azure/webapps-deploy@v2
        with:
          app-name: 'webapp-deploy-test2023'
          slot-name: 'Production'
          publish-profile: ${{ secrets.AZUREAPPSERVICE_PUBLISHPROFILE_A55D4C45434843C1BAF9200C61ADDB5A }}
          package: .

      - name: Remove access rule
        uses: azure/CLI@v1
        with:
          azcliversion: 2.30.0
          inlineScript: |
            az webapp config access-restriction remove -n webapp-deploy-test2023 -g toshida-qiita-2022 --rule-name ghaction_${{ github.run_id }} --scm-site true
```

### 結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4914/43891616-dfde-03ae-51d0-a62fe52a07f2.png)


### 注意

GitHub ホステッド ランナー の IP アドレス範囲はメタ API を利用して取得することができます。

https://docs.github.com/ja/actions/using-github-hosted-runners/about-github-hosted-runners#ip-addresses

GitHub ホステッド ランナーの 送信IP が必ずしも `current_ip_checker` のステップで取得した値と、`deploy-to-webapp`　のステップで SCM サイト(Kudu) へのアクセス時に利用するIP が同じかどうかは必ずしも同じかは不明です。

そのため、本質的にはメタAPI で取得した範囲を設定する方がよいかもしれません。

# 参考

https://azure.github.io/AppService/2022/11/24/Advanced-access-restriction-scenarios-in-Azure-App-Service.html

https://qiita.com/Annoske/items/6527c43d4f553acc4b61#app-service%E3%81%AB%E5%AF%BE%E3%81%97%E3%81%A6%E8%A8%AD%E5%AE%9A%E3%81%A7%E3%81%8D%E3%82%8B%E3%82%A2%E3%82%AF%E3%82%BB%E3%82%B9%E5%88%B6%E9%99%90%E6%96%B9%E6%B3%95%E3%81%A8%E8%A8%AD%E5%AE%9A%E6%89%8B%E9%A0%86