Azure Network Security Perimeter 

Azure Network Security Perimeter がパブリックプレビュー (2024/11/20) となっています。Azure PaaS リソースの論理ネットワークの境界を作るサービスですが、実際にどういったことができるのかを試してみましたので、ご利用の際に、参考になれば幸いです。

https://learn.microsoft.com/ja-jp/azure/private-link/network-security-perimeter-concepts

## 利用シナリオ

- PaaS のファイアウォール設定を一元管理したい
- PaaS のファイアウォールのログを一元管理したい
- AI Search 等からのアウトバウンドの通信を制御したい
- マネージド ID を使った通信をサブスクリプション単位で通信制御を行いたい
- サービスタグを使って送受信の通信制御を行いたい (現時点で利用不可)
 
## Network Security Group との違い

- NSG が対応しているのは VNet 上のリソース (VM, VMSS, Private Endpoint, Application Gateway 等) のみ

## サポートされるリソース

https://learn.microsoft.com/ja-jp/azure/private-link/network-security-perimeter-concepts#onboarded-private-link-resources

## 留意点

- IP レンジの指定はパブリック IP アドレスのみ
- Azure Storage へのアクセスの場合、同じリージョンのパブリック IP アドレスからの通信はプライベート IP となるため IP アドレスレンジでは制御できない

## 設定手順
前提: 
- AI Search, BLOB Storage が作成済みであること
- ポータル経由で操作できるようにネットワーク設定されていること
- AllowNSPInPublicPreview の機能が登録済みであること

### リソース作成
こちらの手順に従ってリソースを作成します。送受信の規則はあとで作成するためスキップします。

https://learn.microsoft.com/ja-jp/azure/private-link/create-network-security-perimeter-portal#create-a-network-security-perimeter

### プロファイル作成
プロファイル (送受信ルールと関連付けるリソースをまとめたもの) を作成します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2266293/e184edb0-404b-6704-5adf-472233040c42.png)

NSP を割り当てるリソースを指定します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2266293/3704359a-7fc4-a543-d04d-1cbaa5b59290.png)

インバウンドルールを作成します。次の動作確認で使えるように特定のパブリック IP アドレスからの通信のみ受け付けられるようにします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2266293/a03974f5-b8d8-b299-8651-ec6401979ec5.png)

アウトバウンドルールはスキップしてプロファイルを作成します。

## 動作確認

### インバウンド
#### IP アドレス制限
Azure の Public IP アドレスからの通信を許可するような設定を試します。
東日本リージョンのパブリック IP アドレスだと[ストレージの制限](https://learn.microsoft.com/ja-jp/azure/storage/common/storage-network-security?tabs=azure-portal#grant-access-from-an-internet-ip-range)でうまく動作しなかったため、東南アジアリージョンを使っています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2266293/472d4634-0fe1-82a1-0829-be0e3df6609b.png)

インバウンドルールで NAT Gateway のパブリック IP アドレスを指定しておきます。(事前実施)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2266293/ce6195e9-ec32-74f7-24ae-f97e4dcf8f55.png)

対称のストレージに関連付けを行い、学習モードにしておきます。学習モードの場合は各 PaaS のファイアウォールの動作に従います。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2266293/f899c5c8-3482-e508-8dbe-3fac438767e7.png)

Azure VM からも外部の端末からもアクセス可能なことを確認します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2266293/d982b148-54c0-78db-5242-790464f8c342.png)

ログにも異なる IP アドレスからの通信が許可されていることがわかります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2266293/6f5fb639-7f16-882c-414e-7f0aca050cd9.png)

強制モードに切り替えます。強制モードの場合は NSP のルールの設定に従います。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2266293/41966bd0-679d-c12d-6a73-8f2a8ba1920f.png)

ルールで許可されていないパブリック IP アドレスからの通信は拒否されるようになりました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2266293/4ded8d2c-0415-e678-ca14-f39fc621ed2e.png)

ログからもルールで許可されていないパブリック IP アドレスからの通信が拒否されていることがわかります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2266293/ba963555-72a7-0537-1d0e-2276c3c2995d.png)

#### サービスタグ

```
az account set --subscription 8ac4d210-xxxx-xxxx-xxxx-e03dc217172c

az network perimeter profile access-rule create -n MyAccessRule --profile-name profile2 --perimeter-name testnsp1 -g rg-nsp-test-01 --service-tags AzureCloud --direction "Inbound"
```
以下のようなエラーがでて利用できませんでした。今後の機能追加を待ちたいと思います。

**"Message: AFEC flag EnableServiceTagsInNsp should be registered on the subscription: 8ac4d210-xxxx-xxxx-xxxx-e03dc217172c to process the Access Rule with Service Tags."**


また、Azure Storage へのインバウンド方向のアクセスは同じリージョン内のサービスタグでは制御できないと思われますので注意が必要です。
理由は以下の通り、同じリージョン内のアクセスの場合、送信元がプライベート IP となるためサービスタグでは対応できないからです。

https://learn.microsoft.com/ja-jp/azure/storage/common/storage-network-security?tabs=azure-portal#grant-access-from-an-internet-ip-range

:::note warn
ストレージ アカウントと同じリージョンにデプロイされている Azure サービスへのアクセスを制限する。 ストレージ アカウントと同じリージョンでデプロイされたサービスでは、プライベート Azure IP アドレスが通信に使用されます。 **そのため、特定の Azure サービスへのアクセスを、そのパブリック送信 IP アドレスの範囲に基づいて制限することはできません。**
:::

#### サブスクリプション
以下のような構成を作成し、NSP にて制御できることを確認していきます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2266293/1a3b3652-f85e-8906-24ac-e3e9b4b679c8.png)

プロファイルを作成し、特定のサブスクリプション (図のサブスクリプション B) のインバウンド通信を許可するルールを作成しておきます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2266293/f845061e-0bd0-cf70-ff41-35b5234c34ca.png)

まずは学習モードにて動作を確認します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2266293/885b0e4e-d063-d04e-b408-ce527e601eb3.png)

AI Search で BLOB ストレージからインデックス作成を行う操作を実施して、バリデーションが通ることを確認します。
サブスクリプション A の AI Search の操作
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2266293/6874c7c4-6222-5cd8-2867-4f1ff94c7ae1.png)
サブスクリプション B の AI Search の操作
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2266293/1564349d-81dd-6faa-7d9b-711e609e26f4.png)

ログでもそれぞれの操作が許可されていることがわかります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2266293/4dbf1227-3124-3f89-5579-1b1bb23af012.png)

ルールのモードを強制モードに切り替えます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2266293/212669ea-fa21-7cde-72fc-3d75c125d1c0.png)

以下のような動作になるはずです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2266293/a64d899d-8eb1-f0af-9264-551ea6d8f657.png)

サブスクリプション A の方の AI Search の画面。操作が拒否されていることがわかります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2266293/17136f1e-a55b-38fa-c111-e605f1de56e2.png)

サブスクリプション B の方は特に変化がありません。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2266293/adda4407-d47a-7253-ca28-48a73e153bdc.png)

ログからもサブスクリプション A の方の操作が拒否されていることがわかります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2266293/b5dbf777-892d-23a5-1d2c-1a56cacce6c6.png)

### アウトバウンド
IP アドレス、サブスクリプション、サービスタグの指定は現時点ではできないようです。CLI で駄目したところ以下のエラーがでました。EmailAddresses or PhoneNumbers の利用用途は不明。。

**"(BadRequest) Either FQDNs or EmailAddresses or PhoneNumbers are mandatory for outbound access rules."**

#### FQDN
特定の FQDN のみ許可するようなアウトバウンドルールを作成して動作を確認します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2266293/084d0647-4950-c666-840c-65d2e88a08d4.png)

特定の FQDN のみ許可するようなアウトバウンドルールを作成します。インバウンドルールは Azure Portal での操作が可能なように最低限のルールを入れておきます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2266293/15e8bec5-f1a4-99cf-b870-d0753b42a467.png)

AI Search を関連付けし、強制モードに切り替えます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2266293/886c60f3-d2eb-32b4-c9bc-02fdc4af9693.png)

FQDN が許可されていない BLOB ストレージへの接続は拒否されました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2266293/e968180c-438c-55e3-fc49-dbf04c64d4c9.png)

FQDN が許可されている方の BLOB ストレージへの接続は問題なくアクセスできます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2266293/592e44ca-40db-4272-60f3-03dc5a1d8054.png)

ログからも特定の FQDN 以外へのアウトバウンド通信が拒否されていることがわかります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2266293/80c71cff-8f17-f4f3-be77-6283d4740c77.png)

## モードの整理

https://learn.microsoft.com/ja-jp/azure/private-link/network-security-perimeter-transition#moving-new-resources-into-network-security-perimeter

### パブリックネットワークアクセス
PaaS のパブリックネットワークアクセスと同じ概念で PaaS のファイアウォールを上書きできる。元々、ファイアウォールには送信規則の概念がなかったため、SecuredByPerimeter モードのみ送信拒否が加わっています。
NSP のみで運用したい場合は強制モードを使うことですぐに実現可能です。

<table frame="box" border="1">
  <caption></caption>
    <tr>
        <td rowspan="2">パブリックネットワークアクセス</td>
        <td colspan="3">学習モード (ルール無し)</td>
        <td colspan="3">学習モード (ルールあり)</td>
        <td colspan="3">強制モード(ルールあり)</td>
    </tr>
    <tr>
        <td>NSP　</td>
        <td>PaaS FW</td>
        <td>ANY　</td>
        <td>NSP　</td>
        <td>PaaS FW</td>
        <td>ANY　</td>
        <td>NSP　</td>
        <td>PaaS FW</td>
        <td>ANY　</td>
    </tr>
    <tr>
        <td>Enabled (受信)</td>
        <td>×</td>
        <td>〇</td>
        <td>×</td>
        <td>〇</td>
        <td>〇</td>
        <td>×</td>
        <td>〇</td>
        <td>×</td>
        <td>×</td>
    </tr>
    <tr>
        <td>Enabled (送信)</td>
        <td>-</td>
        <td>-</td>
        <td>〇</td>
        <td>-</td>
        <td>-</td>
        <td>〇</td>
        <td>〇</td>
        <td>×</td>
        <td>×</td>
    </tr>
    <tr>
        <td>Disabled (受信)</td>
        <td>×</td>
        <td>×</td>
        <td>×</td>
        <td>〇</td>
        <td>×</td>
        <td>×</td>
        <td>〇</td>
        <td>×</td>
        <td>×</td>
    </tr>
    <tr>
        <td>Disabled (送信)</td>
        <td>-</td>
        <td>-</td>
        <td>〇</td>
        <td>-</td>
        <td>-</td>
        <td>〇</td>
        <td>〇</td>
        <td>×</td>
        <td>×</td>
    </tr>
    <tr>
        <td>SecuredByPerimeter (受信)</td>
        <td>×</td>
        <td>×</td>
        <td>×</td>
        <td>〇</td>
        <td>×</td>
        <td>×</td>
        <td>〇</td>
        <td>×</td>
        <td>×</td>
    </tr>
    <tr>
        <td>SecuredByPerimeter (送信)</td>
        <td>×</td>
        <td>×</td>
        <td>×</td>
        <td>〇</td>
        <td>×</td>
        <td>×</td>
        <td>〇</td>
        <td>×</td>
        <td>×</td>
    </tr>
</table>

ただし、以下のような例外もあるため要件に合うかは確認が必要です。

:::note 
信頼されたアクセス: ネットワーク セキュリティ境界では、信頼されたアクセスよりも詳細な制御が提供されるため、**信頼されたアクセスは強制モードではサポートされていません。**

プライベート アクセス: プライベート リンク経由のアクセスは、**ネットワーク セキュリティ境界の影響を受けません。**
:::

## プライベートエンドポイントのログは記録されるか？
試してみましたが、プライベートエンドポイント経由の通信は異なる IP アドレスで記録されており、通信ログとしては十分ではなさそうです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2266293/e59b3a19-b7c4-b5e0-83ef-a5e4301f204c.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2266293/b50d5825-0805-d3f1-f228-9cde1c2da924.png)