App Serviceに対して設定できるアクセス制限方法と設定手順

# App Serviceに対して設定できるアクセス制限方法と設定手順

## はじめに

[Microsoft Azure Techのカレンダー | Advent Calendar 2022 - Qiita](https://qiita.com/advent-calendar/2022/microsoft-azure-tech) 19日目の記事です。



App Serviceは様々な方法のアクセス制限を提供しています。

本記事では下記のシナリオにおいて利用可能なアクセス制限方法と設定手順を紹介します。

- IPアドレスベースでアクセスを制限する
- Azure上の仮想ネットワークからのアクセスのみ許可する
- オンプレミス環境からのアクセスのみ許可する
- インターネットからのアクセスのうち、認証を通った場合のみアクセスを許可する





## IPアドレスベースでアクセスを制限する

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/502798/2a486dbe-5de6-354b-b48c-b67f48e4803c.png)


使用するリソース：App Serviceのアクセス制限機能



 ### App Serviceのアクセス制限機能

App Serviceでは、アクセス制限を設定することでIPアドレスによるアクセス制限を行うことができます。



> アクセス制限の設定により、優先度で順序付けした許可リストまたは拒否のリストを定義できます。このリストは、アプリへのネットワーク アクセスを制御します。 リストには、IP アドレスまたは Azure Virtual Network のサブネットを含めることができます。 
>
> [Azure App Service のアクセス制限 - Azure App Service | Microsoft Learn](https://learn.microsoft.com/ja-jp/azure/app-service/app-service-ip-restrictions)



**【手順】**

1 . **Azure portalから、App Serviceにアクセスし、左メニューの「ネットワーク」>「アクセス制限」を選択する**

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/502798/d98dd9a2-52ad-5e52-0ab1-35b8987efe58.png)




2 . **「規則の追加」からソースの設定で「IPv4」を選択し、IPアドレスブロックに該当のIPアドレスを入力し「規則の追加」を押下**

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/502798/2699114e-ebd9-d8b2-10b4-61b24878f280.png)

ここまでの設定でIPアドレスベースのアクセス制限が構成できます。



**【挙動】**

- 許可されたIPからのアクセス
  - 正常にアプリ画面が表示される
  - ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/502798/252a2027-7076-0769-0e7b-6089bba8095f.png)


- 許可されていないIPからのアクセス
  - 　Error 403を示す画面が表示される
  - ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/502798/2d74db3f-139e-edff-2e61-6010b6313de1.png)




**【補足】**

- IPアドレスでの制限以外にも、「仮想ネットワーク」「サービスタグ」が選択できます(後述します)
  - ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/502798/238af086-01b8-6fc3-1680-33deca185f51.png)
  - 仮想ネットワーク：
    - 指定した仮想ネットワークのサブネットからのアクセスのみ許可/拒否する
    - https://learn.microsoft.com/ja-jp/azure/app-service/app-service-ip-restrictions#set-a-service-endpoint-based-rule
  - サービスタグ：
    - 特定のAzureサービスからのアクセスのみ許可/拒否する
    - https://learn.microsoft.com/ja-jp/azure/app-service/app-service-ip-restrictions#set-a-service-tag-based-rule





## Azure上の仮想ネットワークからのアクセスのみ許可する


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/502798/4e681059-958c-f736-e0bd-336627a9f112.png)



使用するリソース：App Serviceのアクセス制限機能、Private Endpoint



### App Serviceのアクセス制限機能(サービスエンドポイント)

サービスエンドポイントを利用したアクセス制限について紹介します。

イメージとしては下記のようになります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/502798/5dd26e8b-06e8-a00e-e5eb-36ca3a950e9f.png)

**【手順】**

1 . **Azure portalから、App Serviceにアクセスし、左メニューの「ネットワーク」>「アクセス制限」を選択する**

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/502798/5fbe679f-4a4e-5cc3-6d58-8cee1a8e915e.png)


2 . **「規則の追加」からソースの設定で「仮想ネットワーク」を選択し、サブネットまで入力後「規則の追加」を押下**

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/502798/9afb98ae-4b17-cb39-909d-e0679df6654e.png)

ここまでの設定で仮想ネットワークからのアクセス制限が構成できます。





**【挙動】**

- 許可されたサブネットからのアクセス
  - 正常にアプリ画面が表示される
  - ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/502798/3e254bda-8567-2970-465a-c3e5467ab321.png)


- 許可されていないサブネットからのアクセス
  - 　Error 403を示す画面が表示される
  - ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/502798/f643a50f-9ff8-299d-fbf9-f2208fa21188.png)




**【補足】**

上記のアクセス制限を構成すると、制限対象の仮想ネットワーク側に、サービスエンドポイントが自動で構成されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/502798/5ef2236e-dbbf-93c7-1663-bd4e2c681769.png)


サービスエンドポイントとは

> 仮想ネットワーク (VNet) サービス エンドポイントでは、Azure のバックボーン ネットワーク上で最適化されたルートを介して、Azure サービスに安全に直接接続できます。 エンドポイントを使用することで、重要な Azure サービス リソースへのアクセスを仮想ネットワークのみに限定することができます。
>
> [Azure 仮想ネットワーク サービス エンドポイント | Microsoft Learn](https://learn.microsoft.com/ja-jp/azure/virtual-network/virtual-network-service-endpoints-overview)





### プライベートエンドポイント

プライベートエンドポイントを利用したアクセス制限について紹介します。

イメージとしては下記のようになります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/502798/55d8aab0-45c0-48b2-5c69-eb19b5c5c539.png)



**【手順】**



前提として、ある仮想ネットワークのサブネット上に仮想マシンが構成されている状態で、ここからプライベートエンドポイントを構成していきます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/502798/9be98824-bb7d-e793-269d-edb034856a18.png)


1 . **Azure portalから、App Serviceにアクセスし、左メニューの「ネットワーク」>「プライベートエンドポイント」を選択する**

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/502798/20551474-9587-3849-6255-88aef5eafdd6.png)


2 . **「追加」から対象のApp Serviceへのアクセスを許可するサブネットを入力後「OK」を押下**

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/502798/9f184fb5-6fb8-ba4b-efd0-889c265329e6.png)


ここまでの設定で仮想ネットワークからのアクセス制限が構成できます。



**【挙動】**

- 許可されたサブネットに配置されたVMからのアクセス
  - 正常にアプリ画面が表示される
  - ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/502798/911baceb-c3af-1b35-4a4b-d365920e0e4c.png)


- 許可されていないサブネットからのアクセス
  - 　Error 403を示す画面が表示される
  - ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/502798/172999c9-27a6-ca1e-e4db-7056bfba07b2.png)


**【補足】**

**プライベートエンドポイント作成時の、「プライベートDNSゾーンと統合する」について**

プライベートエンドポイントを利用する際、アクセス対象(今回でいうAppService)の名前解決を行うためにプライベートDNSゾーンが必要です。

​	Azure PortalからプライベートDNSゾーンを見てみると、リソースに対してどんなプライベートIPアドレスが振られているか確認することができます。![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/502798/aebb159a-fbce-9b45-f8c7-88e0d7018d07.png)



​	名前解決を行うフローの詳細は下記ご参照ください。

​	[Azure プライベート エンドポイントの DNS 構成 | Microsoft Learn](https://learn.microsoft.com/ja-jp/azure/private-link/private-endpoint-dns#virtual-network-workloads-without-custom-dns-server)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/502798/b2295189-46b9-475f-1395-8d2f1d7d7e74.png)





**仮想ネットワークに接続されたデバイスの確認**

仮想ネットワークの「接続デバイス」から、接続されているデバイスを確認できます。

今回追加したプライベートエンドポイントもここから参照できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/502798/a97d016c-86b6-c01a-ad0d-d31ad542ac15.png)






### (ちょっと脱線)サービスエンドポイントとプライベートエンドポイントの違い

App Serviceへのアクセスを限られたネットワーク(仮想ネットワーク)に限定する方法として、サービスエンドポイントとプライベートエンドポイントを使う方法を紹介しました。



どちらも同様の機能を提供しているサービスエンドポイントとプライベートエンドポイントについて、両者の違いとそれぞれのユースケースを紹介します。



#### サービスエンドポイント

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/502798/7922dc7f-e754-823c-ff68-8086f9c758bf.png)


【アクセス制限方法】

- サブネットのルートテーブルの書き換えで制御する

  - ex: AppServiceとの通信に使用するプロトコル・ポートの制限をルートテーブルに追加する(Microsoft.Webのサービスエンドポイントを作成した場合)

- - 上記のルートテーブルの変更はAzure Portalからは参照できず、内部的な上位のルートテーブルに適応される



【アクセス制限が可能な領域】

- 仮想ネットワークのサブネット

  - ピアリング先仮想ネットワークやオンプレからのアクセスは出来ない

- 特定のサービス(AppService/SQLServerなど)単位でアクセス制限を行う

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/502798/f521cc7c-c502-a36c-e037-686ca732eb56.png)


  

【利用料】

- 無料で使用可能



【ユースケース】

- あるサブネットのみからのアクセスを許可したい場合
- 追加のコストをかけずにアクセス制限したい場合



#### プライベートエンドポイント

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/502798/b7ce25ba-ce6d-6966-b3c0-3fceebfb2cf7.png)


【アクセス制限方法】

- 指定したサブネット内にネットワークインターフェースを用意し、プライベートIP アドレスを割り当てることで制御する(割り当てられたプライベートIPアドレスからでしかアクセスを許可しない)
  - 用意されたネットワークインタフェース=プライベートエンドポイント
  - プライベートエンドポイントを名前解決するためのDNS設定が必要



【アクセス制限が可能な領域】

- 仮想ネットワークのサブネット

- オンプレミス環境からのアクセスも許可できる

- 特定のリソース単位でアクセス制限を行う(SQLServer1のみ許可など)

  - ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/502798/729b59f7-d2e8-367f-1886-06941f66f9fc.png)


  

【利用料】

有料([価格 - Azure Private Link | Microsoft Azure](https://azure.microsoft.com/ja-jp/pricing/details/private-link/))



【ユースケース】

- オンプレミス環境からのアクセスを許可したい場合
- あるサービスの中でも、特定のリソースのみアクセスを許可したい場合(ex: SQLServer1は許可したいが、SQLServer2は拒否したい)
- サービスエンドポイントが提供していないリソースへのアクセス制限をしたい場合
  - 下記サービスエンドポイントが提供しているリソース([Azure 仮想ネットワーク サービス エンドポイント | Microsoft Learn](https://learn.microsoft.com/ja-jp/azure/virtual-network/virtual-network-service-endpoints-overview))
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/502798/219abe15-b67e-082c-2471-032a8295b97f.png)




## オンプレミス環境からのアクセスのみ許可する


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/502798/a8b6c0eb-f364-ce9a-6c34-41b91a7cfa23.png)


使用するリソース：ExpressRoute

### ExpressRoute

ExpressRouteを使って、オンプレミスのネットワークとAzure上の仮想ネットワークを接続することができます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/502798/48c7ba6f-8ac3-92cd-1dd0-17f26cea2a31.png)


[Azure ExpressRoute: 接続モデル | Microsoft Learn](https://learn.microsoft.com/ja-jp/azure/expressroute/expressroute-connectivity-models)



ExpressRouteの概要や利点は下記ドキュメントをご参照ください。

[Azure ExpressRoute の概要プライベート接続を介して接続する | Microsoft Learn](https://learn.microsoft.com/ja-jp/azure/expressroute/expressroute-introduction#key-benefits)



【手順】

ここではドキュメントの紹介のみさせていただきます。

[クイックスタート: ExpressRoute を使った回線の作成と変更 - Azure portal | Microsoft Learn](https://learn.microsoft.com/ja-jp/azure/expressroute/expressroute-howto-circuit-portal-resource-manager)

[チュートリアル:ExpressRoute 回線のピアリングの構成 - Azure portal | Microsoft Learn](https://learn.microsoft.com/ja-jp/azure/expressroute/expressroute-howto-routing-portal-resource-manager)

[チュートリアル: Azure portal を使用して ExpressRoute の仮想ネットワーク ゲートウェイを構成する | Microsoft Learn](https://learn.microsoft.com/ja-jp/azure/expressroute/expressroute-howto-add-gateway-portal-resource-manager)



## インターネットからのアクセスのうち、認証を通った場合のみアクセスを許可する

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/502798/6d0a03e1-26a8-efc8-173e-b078109ac02c.png)

使用するリソース：AzureAD、クライアント証明書、IDaabS等の外部認証サービス



### AzureAD

App Service認証機能を使って、App Serviceに到達する前にAzure ADログインを求めることができます。

イメージとしては下記のようになります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/502798/70a21338-4568-f805-e4ed-c52bc616a3e5.png)


[Azure AD 認証を構成する - Azure App Service | Microsoft Learn](https://learn.microsoft.com/ja-jp/azure/app-service/configure-authentication-provider-aad)



**【手順】**

1 . **Azure portalから、App Serviceにアクセスし、左メニューの「認証」>「ID プロバイダーを追加」を選択する**

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/502798/9dd326d4-7678-9994-e52f-7f678f6bdaf9.png)



2 . **「ID プロバイダー」でMicrosoftを選択し、「追加」を押下**

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/502798/d1af8883-270d-4ad0-60a1-374eda0b772d.png)


ここまでの設定でAzureADを使ったアクセス制限が構成できます。



**【挙動】**

- AppServiceにアクセスする(サインイン情報が残っている場合があるので、シークレットウィンドウでアクセスする)
  - サインイン画面が表示される
    - ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/502798/7934f576-a924-6883-ad9d-3b01ad342f31.png)

    - 認証に成功すると、正常にアプリ画面が表示される
      - ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/502798/85119c12-6f02-5470-2d8e-80bb11a30a27.png)


**【補足】**

**IDプロバイダー追加時の設定について**

「IDプロバイダー」はMicrosoft以外に、下記からも選択可能です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/502798/e3b6303d-dc73-5ad9-b557-84e4c3cb42aa.png)




**認証されていない要求**

「IDプロバイダー」で選択したサインインに失敗した要求に対して、どのステータスコートを返却するかの設定です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/502798/a46641c9-3f08-c71a-c4ed-ad749d8559d3.png)






### クライアント証明書

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/502798/3646d90e-ae30-a9dc-5f19-e579980bf54d.png)


AppServiseでは、クライアント要求が TLS/SSL を経由するときにクライアント証明書を要求し、その証明書をアプリ上で検証することでアクセスを制限することができます。



**【手順】**

1 . **Azure portalから、App Serviceにアクセスし、左メニューの「構成」>「全般設定」を選択する**

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/502798/195ebb03-0c49-851f-3a39-be5d2337be3d.png)


2 . **「着信クライアント証明書」で「必須」を選択し保存する**

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/502798/1451aa2d-db0a-f1de-ebf3-fc4cb2ec141e.png)

ここまでの設定で、クライアントがAppServiceにアクセスしてきた際に、証明書を求めることができます。



3 . **アプリコードで証明書を検証し、アクセスを制限する**

アクセスを制限するには、要求した証明書をアプリで検証する必要があります。



Node.jsのサンプルを紹介します。

```javascript
import { NextFunction, Request, Response } from 'express';
import { pki, md, asn1 } from 'node-forge';

export class AuthorizationHandler {
    public static authorizeClientCertificate(req: Request, res: Response, next: NextFunction): void {
        try {
            // Get header
            const header = req.get('X-ARR-ClientCert');
            if (!header) throw new Error('UNAUTHORIZED');

            // Convert from PEM to pki.CERT
            const pem = `-----BEGIN CERTIFICATE-----${header}-----END CERTIFICATE-----`;
            const incomingCert: pki.Certificate = pki.certificateFromPem(pem);

            // Validate certificate thumbprint
            const fingerPrint = md.sha1.create().update(asn1.toDer(pki.certificateToAsn1(incomingCert)).getBytes()).digest().toHex();
            if (fingerPrint.toLowerCase() !== 'abcdef1234567890abcdef1234567890abcdef12') throw new Error('UNAUTHORIZED');

            // Validate time validity
            const currentDate = new Date();
            if (currentDate < incomingCert.validity.notBefore || currentDate > incomingCert.validity.notAfter) throw new Error('UNAUTHORIZED');

            // Validate issuer
            if (incomingCert.issuer.hash.toLowerCase() !== 'abcdef1234567890abcdef1234567890abcdef12') throw new Error('UNAUTHORIZED');

            // Validate subject
            if (incomingCert.subject.hash.toLowerCase() !== 'abcdef1234567890abcdef1234567890abcdef12') throw new Error('UNAUTHORIZED');

            next();
        } catch (e) {
            if (e instanceof Error && e.message === 'UNAUTHORIZED') {
                res.status(401).send();
            } else {
                next(e);
            }
        }
    }
}
```

Node.jsの場合、`X-ARR-ClientCert`ヘッダーに要求した証明書(base64エンコードPEM文字列)が入ります。

それを`node-forge`で証明書オブジェクトに変換して、検証を行います。



Node.js以外のサンプルコートは下記に記載があるので、ご参考までに紹介いたします。

[TLS 相互認証の構成 - Azure App Service | Microsoft Learn](https://learn.microsoft.com/ja-jp/azure/app-service/app-service-web-configure-tls-mutual-auth#access-client-certificate)



**【挙動】**

- AppServiceにアクセスする
  - 証明書を要求される
    - ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/502798/60b9da69-e7a0-80ba-a8b6-096f64aacb6c.png)

  - 有効な証明書を送信した
    - ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/502798/353b9d46-21aa-0b68-cf61-542187af9d90.png)

  - 無効な証明書を送信した
    - アプリコードに依存(先のNode.jsサンプルコードの場合、401エラーが返却される)
  - 証明書を送信しない(証明書の選択でキャンセルを押下)
    - ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/502798/9c4dc96f-a415-08bd-f4ef-281c9051a664.png)




### IDaaS等の外部認証サービス

ここでは詳細な手順は割愛しますが、外部のIDaaSを利用する方法もございます。

その場合、アプリ上でトークン取得や認証サイトへのリダイレクトを行う必要があります。



大まかな流れとしては下記のようになります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/502798/6b8bf7f8-c846-52f5-c526-720730893b34.png)




詳細は、IDaaSの一例であるAuth0のドキュメントを下記に紹介いたしますので、ご参照ください。

[Auth0 Universal Login](https://auth0.com/docs/authenticate/login/auth0-universal-login)



## その他のアクセス制限方法

さらに高度なアクセス制限については、下記ドキュメントをご参照ください。

[Azure App Service のアクセス制限 - Azure App Service | Microsoft Learn](https://learn.microsoft.com/ja-jp/azure/app-service/app-service-ip-restrictions)





## 最後に

AppServiceで利用できる様々なアクセス制限方法を紹介しました。



アクセス制御は安全なウェブサイトを構築するうえで欠かせない仕組みであるため、要件に合った方法を選定していただければと思います。

[安全なウェブサイトの作り方 - 1.11 アクセス制御や認可制御の欠落：IPA 独立行政法人 情報処理推進機構](https://www.ipa.go.jp/security/vuln/websecurity-HTML-1_11.html)



## 参考

[Azure App Service のアクセス制限 - Azure App Service | Microsoft Learn](https://learn.microsoft.com/ja-jp/azure/app-service/app-service-ip-restrictions)

[Azure 仮想ネットワーク サービス エンドポイント | Microsoft Learn](https://learn.microsoft.com/ja-jp/azure/virtual-network/virtual-network-service-endpoints-overview)

[プライベート エンドポイントとは - Azure Private Link | Microsoft Learn](https://learn.microsoft.com/ja-jp/azure/private-link/private-endpoint-overview#private-link-resource)

[Azure Private Link サービスとは | Microsoft Learn](https://learn.microsoft.com/ja-jp/azure/private-link/private-link-service-overview#limitations)

[Azure プライベート エンドポイントの DNS 構成 | Microsoft Learn](https://learn.microsoft.com/ja-jp/azure/private-link/private-endpoint-dns#virtual-network-workloads-without-custom-dns-server)

[Virtual network integration of Azure services for network isolation | Microsoft Learn](https://learn.microsoft.com/en-us/azure/virtual-network/vnet-integration-for-azure-services#compare-private-endpoints-and-service-endpoints)

[Azure ExpressRoute の概要プライベート接続を介して接続する | Microsoft Learn](https://learn.microsoft.com/ja-jp/azure/expressroute/expressroute-introduction)