Azure OpenAI Service をノーコード開発してみる(5) ~ Azure リソースのセキュリティ強化 ~

NTTデータ先端技術株式会社の原田です。

Azure OpenAI Service の学習にあたって試してみたフルノーコードによる開発のご紹介です。  
この記事は2023/11/15時点の情報で記載しています、アップデートにより変わってしまっている部分がありましたらご容赦ください。

今回は全6回の第5回~ Azure リソースのセキュリティ強化 ~になります。  

## 記事一覧
[第1回. Logic Apps でサーバーサイド開発(構築編) ](https://qiita.com/koutaro_harada/items/ba5646e2d90a56f9ec3b)   
[第2回. Logic Apps でサーバーサイド開発(開発編) ](https://qiita.com/koutaro_harada/items/bbb4271e333943e09061)    
[第3回. Power Platform でクライアントサイド開発](https://qiita.com/koutaro_harada/items/ac074acb2264bcaed28d)    
[第4回. ServiceNow でクライアントサイド開発](https://qiita.com/koutaro_harada/items/c9ce99047dc1b80cceb3)  
**第5回. Azure リソースのセキュリティ強化**  
第6回. Azure OpenAI Service をノーコード開発してみるのまとめ  

## はじめに
第1回で構築した Azure リソースは、 
   
① エンドポイント + キーを知っていると誰でも OpenAI Service が呼び出せてしまう  
② URI + キーを知っていると誰でも Cosmos DB に読み書きできてしまう  
③ ワークフロー URL を知っていると誰でも Logic Apps が呼び出せてしまう  
  
と言うあまりセキュリティが考慮されているとは言えない状態になっています。  
第5回ではここにセキュリティ強化を施していきます。  
![b98fee970049aa39f69c_01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3620633/2c801d67-915e-1ea6-3449-ba8cf4afab22.png)

## Logic Apps にユーザー割り当てマネージド ID を割り当て
Logic Apps に OpenAI Service および Cosmos DB へのアクセス制御に用いるユーザー割り当てマネージド ID を割り当てます。  
![b98fee970049aa39f69c_02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3620633/66e2fabd-dfe8-282b-6250-7e1b74627d47.png)

## OpenAI Service の ロールをマネージド ID に割り当て
OpenAI Service の <INS>Cognitice Services OpenAI User ロール</INS>をマネージド ID に割り当てます。   
![b98fee970049aa39f69c_03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3620633/6e1a6aaf-928a-71f4-69ef-451e8595f8f2.png)

## OpenAI Service の キー無効化
Cloud Shell 等で↓の Powershell を実行して OpenAI Service の キーを無効化します。  
パラメータは <INS>disableLocalAuth</INS> ですので true を指定します。   
```
$sid = "サブスクリプション ID"
$rg = "リソースグループ"
$account = "OpenAI Service アカウント"
$body = '{"properties":{"disableLocalAuth":"true"}}'
$uri = "https://management.azure.com/subscriptions/${sid}/resourceGroups/${rg}/providers/Microsoft.CognitiveServices/accounts/${account}?api-version=2023-05-01"

$azContext = Get-AzContext
$azProfile = [Microsoft.Azure.Commands.Common.Authentication.Abstractions.AzureRmProfileProvider]::Instance.Profile
$profileClient = New-Object -TypeName Microsoft.Azure.Commands.ResourceManager.Common.RMProfileClient -ArgumentList ($azProfile)
$token = $profileClient.AcquireAccessToken($azContext.Subscription.TenantId)
$authHeader = @{
    'Content-Type'='application/json'
    'Authorization'='Bearer ' + $token.AccessToken
}

Invoke-RestMethod -Method Patch -Uri $uri -Body $body -ContentType "application/json" -Headers $authHeader
```  

## OpenAI Service の ファイアウォール設定
OpenAI Service の ファイアウォールを Logic Apps よりのアクセスのみ許可に設定します。  
Logic Apps の<INS>ランタイム発信 IP アドレス</INS>を取得して、  
![b98fee970049aa39f69c_04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3620633/99a3046c-c68b-6857-3055-ab4a38c8386a.png)  
ネットワーク設定にて、許可するアクセス元 : 選択したネットワークとプライベート エンドポイントを選択し、ファイアウォールに IP アドレスを登録します。  
![b98fee970049aa39f69c_05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3620633/77757391-3313-29a0-605b-2fc1c10a14d1.png) 

## Cosmos DB の ロールをマネージド ID に割り当て
Cosmos DB のロールは [組み込みロール](https://learn.microsoft.com/ja-jp/azure/cosmos-db/how-to-setup-rbac#built-in-role-definitions) を使用します。  
まずはマネージド ID の<INS>プリンシパル ID</INS> を取得して、   
![b98fee970049aa39f69c_06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3620633/613631e1-df6c-a78d-7fb6-93c1d4020d58.png) 
Cloud Shell 等で↓の Powershell を実行して <INS>Cosmos DB 組み込みデータ共同作成者ロール</INS>をマネージド ID に割り当てます。   
```
$sid = "サブスクリプション ID"
$rg = "リソースグループ"
$account = "Cosmos DB アカウント"
$principalId = "マネージド ID のプリンシパル ID"
$definitionId = "/subscriptions/${sid}/resourceGroups/${rg}/providers/Microsoft.DocumentDB/databaseAccounts/${account}/sqlRoleDefinitions/00000000-0000-0000-0000-000000000002"
az cosmosdb sql role assignment create -a $account -g $rg -s "/" -p $principalId -d $definitionId
```  
組み込みロールの割り当ては IAM では確認できませんので、代わりに↓の Powershell にて取得します。  
```
az cosmosdb sql role assignment list --account-name "Cosmos DB アカウント" -g "リソースグループ"
```  

## Cosmos DB の キー無効化
Cloud Shell 等で↓の Powershell を実行して Cosmos DB の キーを無効化します。  
パラメータは <INS>disableLocalAuth</INS> ですので true を指定します。   
```
$sid = "サブスクリプション ID"
$rg = "リソースグループ"
$account = "Cosmos DB アカウント"
$body = '{"properties":{"disableLocalAuth":"true"}}'
$uri = "https://management.azure.com/subscriptions/${sid}/resourceGroups/${rg}/providers/Microsoft.DocumentDB/databaseAccounts/${account}?api-version=2021-06-15"

$azContext = Get-AzContext
$azProfile = [Microsoft.Azure.Commands.Common.Authentication.Abstractions.AzureRmProfileProvider]::Instance.Profile
$profileClient = New-Object -TypeName Microsoft.Azure.Commands.ResourceManager.Common.RMProfileClient -ArgumentList ($azProfile)
$token = $profileClient.AcquireAccessToken($azContext.Subscription.TenantId)
$authHeader = @{
    'Content-Type'='application/json'
    'Authorization'='Bearer ' + $token.AccessToken
}

Invoke-RestMethod -Method Patch -Uri $uri -Body $body -ContentType "application/json" -Headers $authHeader
```  
<font color="Red">**!! Warning !!**</font>  
キーを無効化すると Azure ポータルのデータエクスプローラーではデータの読み書きが不可となります。  
その際には↑の組み込みロールをユーザーに割り当てた上で[こちら](https://cosmos.azure.com/?feature.enableAadDataPlane=true)からご利用いただくことで対処可能です。  

## Cosmos DB の ファイアウォール設定
Cosmos DB の ファイアウォールを Logic Apps よりのアクセスのみ許可に設定します。  
こちらは Logic Apps の<INS>コネクタ発信 IP アドレス</INS>を取得して、  
![b98fee970049aa39f69c_09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3620633/b605729f-d64d-db1a-1d39-a0ca30d23123.png)  
ネットワーク設定にて、パブリック ネットワーク アクセス : 選択したネットワークを選択し、ファイアウォールに IP アドレスを登録します。  
![b98fee970049aa39f69c_07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3620633/e632bfb3-4173-a106-fd38-3e769b567aec.png)

## Logic Apps の セキュリティ強化
Logic Apps の セキュリティ強化 (図の③) は、マネージド ID やファイアウォールの適用が難しく一旦このままにします。  
(強化案は次回掲載の予定です)　　

## Logic Apps の 認証設定変更
あと一息、OpenAI Service と Cosmos DB への認証設定をマネージド ID に変更します。  
OpenAI Service 用。  
![b98fee970049aa39f69c_10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3620633/4d601aaa-3788-3d60-3a88-3ddb18124ee0.png)
Cosmos DB 用。  
![b98fee970049aa39f69c_08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3620633/4c7e523e-5b92-4ff8-a685-8e7b77e69d9e.png)

## テスト
↓のテストケースでアクセスが拒否されることを確認しました。    
* Logic Apps からキーを使用しての OpenAI Service 呼び出し
* Logic Apps からキーを使用しての Cosmos DB 読み書き
* ローカル PC から OpenAI Studio の利用
* ローカル PC から Cosmos DB データエクスプローラーの利用

## おわりに
今回は API でしかできない設定も結構あってちょっと苦戦しましたが、その分勉強になる部分も多かったです。  
セキュリティ強化のベースラインはこのあたりだと思います、さらなる強化については次回へ。

## 次回 
さて次回は本連載の最後として連載通してのまとめをいたします。