はじめに
Azure OpenAI Service は Private Endpoint をサポートしています。ですので、Azure OpenAI Service の特定のドメイン宛ての通信をインターネット経由ではなく閉域網経由にできます。また、ファイアウオールの機能もあるので、インターネットからAzure OpenAI Service の特定のドメイン宛ての通信を拒否することもできます。
ドキュメントを読んでも構成がピンと来なかったので、実際にやってみました。
環境
オンプレミスと Azure の仮想ネットワークは S2S VPN で接続されています。その仮想ネットワーク上に Azure OpenAI Service 向けの Private Endpoint を用意しました。Azure OpenAI Service 側のファイアウオールでは、インターネットからの通信を拒否するように設定しました。なお、仮想ネットワークは東日本に、Azure OpenAI Service は East US に用意しました。
設定
Azure OpenAI Service を作成すると、<リソース名>.openai.azure.com という専用の FQDN が用意されます。
{
"id": "/subscriptions/<サブスクリプション ID>/resourceGroups/<リソースグループ名>/providers/Microsoft.CognitiveServices/accounts/<リソース名>",
"name": "<リソース名>",
"type": "Microsoft.CognitiveServices/accounts",
"etag": "\"de004200-0000-0100-0000-643f438b0000\"",
"location": "eastus",
"sku": {
"name": "S0"
},
"kind": "OpenAI",
"tags": {},
"properties": {
"endpoint": "https://<リソース名>.openai.azure.com/"
}
}
そして、このアカウントに対して作成した Private Endpoint には、<リソース名>.privatelink.openai.azure.com のドメインのみが登録されます。
{
"value": [
{
"name": "default",
"id": "/subscriptions/<サブスクリプション ID>/resourceGroups/<リソースグループ名>/providers/Microsoft.Network/privateEndpoints/openai-pe/privateDnsZoneGroups/default",
"type": "Microsoft.Network/privateEndpoints/privateDnsZoneGroups",
"properties": {
"privateDnsZoneConfigs": [
{
"name": "privatelink-openai-azure-com",
"id": "/subscriptions/<サブスクリプション ID>/resourceGroups/<リソースグループ名>/providers/Microsoft.Network/privateEndpoints/openai-pe/privateDnsZoneGroups/default/privateDnsZoneConfigs/privatelink-openai-azure-com",
"type": "Microsoft.Network/privateEndpoints/privateDnsZoneGroups/privateDnsZoneConfigs",
"properties": {
"privateDnsZoneId": "/subscriptions/<サブスクリプション ID>/resourceGroups/<リソースグループ名>/providers/Microsoft.Network/privateDnsZones/privatelink.openai.azure.com",
"recordSets": [
{
"recordType": "A",
"recordSetName": "<リソース名>",
"fqdn": "<リソース名>.privatelink.openai.azure.com",
"ttl": 10,
"ipAddresses": [
"10.1.10.4"
]
}
]
}
}
]
}
}
]
}
この Private Endpoint を利用するためには、クライアントからの <リソース名>.openai.azure.com の名前解決要求に対して、クライアントが参照する DNS キャッシュサーバが Private Endpoint の 10.1.10.4 を返す必要があります。
今回の構成では、クライアントが参照しているドメインコントローラに <リソース名>.openai.azure.com のゾーンファイルを作る方式で対応しました。
PS > Get-DnsServerResourceRecord -ComputerName dc01 -ZoneName <リソース名>.openai.azure.com
HostName RecordType Type Timestamp TimeToLive RecordData
-------- ---------- ---- --------- ---------- ----------
@ A 1 0 01:00:00 10.1.10.4
実際に、クライアントで <リソース名>.openai.azure.com を名前解決すると、Private Endpoint のプライベート IP アドレスが返ってきます。
PS > nslookup <リソース名>.openai.azure.com
Server: UnKnown
Address: 192.168.111.248
Name: <リソース名>.openai.azure.com
Address: 10.1.10.4
動作
上記の設定の通り、Azure OpenAI Service を利用するために必要な通信の中で、<リソース名>.openai.azure.com への通信のみが Private Endpoint 経由になります。Azure OpenAI Service の API キーが手元にあり、Azure OpenAI Service の全ての操作を Azure OpenAI Service の API 経由で実施するのであれば、全ての通信を Private Endpoint 経由にできます。
一方で、Azure OpenAI Service を GUI から利用できる Azure OpenAI Studio の FQDN は oai.azure.com ですので、Azure OpenAI Service の Private Endpoint 経由にはなりません。また、Azure OpenAI Studio を利用するために必要な Azure AD 認証の通信も Private Endpoint 経由にはなりません。
構築した構成で動作を確認します。今回の検証では Azure OpenAI Service のファイアウオールでインターネットからのアクセスを拒否しているので Azure OpenAI Studio を利用できません。PowerShell を利用して Private Endpoint 経由で Azure OpenAI Service の API を直叩きする形でモデルをデプロイして AI に質問してみます。
$apiKey = "API KEY"
$header = @{
"content-type" = "application/json"
"api-key" = $apiKey
}
$body = @{
"model" = "gpt-35-turbo"
"scale_settings" = @{
"scale_type"= "standard"
}
} | convertto-json -depth 10
$res = Invoke-RestMethod -Method POST -Uri "https://<リソース名>.openai.azure.com/openai/deployments?api-version=2023-03-15-preview" -Body $body -header $header
$res
scale_settings : @{scale_type=standard}
model : gpt-35-turbo
owner : organization-owner
id : deployment-25c4dc853b6044dd976e797d9e67d714
status : succeeded
created_at : 1681897083
updated_at : 1681897083
object : deployment
$body = @"
{
"messages": [
{
"role": "system",
"content": "Your are the professional of coffee and you know the price of cofee around the world"
},
{
"role": "user",
"content": "How much is Tokyo's coffee?"
}
],
"temperature": 0.7,
"top_p": 0.95,
"frequency_penalty": 0,
"presence_penalty": 0,
"max_tokens": 800,
"stop": null
}
"@
$res = Invoke-RestMethod -Method POST -Uri "https://<リソース名>openai.openai.azure.com/openai/deployments/deployment-25c4dc853b6044dd976e797d9e67d714/chat/completions?api-version=2023-03-15-preview" -Body $body -header $header
$res.choices[0].message.content
上記の通り、東京のコーヒーの値段を聞いてみました。AI の回答は次の通りです。無事に答えてくれました。Private Endpoint 経由で AI とお話できてそうです。
The price of coffee in Tokyo can vary depending on the type of coffee and the location of the café. On average, a cup of coffee in Tokyo can cost anywhere between 400 to 800 Japanese yen (approximately $4 to $8 USD). However, there are also specialty coffee shops that offer higher quality coffee for a higher price. It is also worth noting that some coffee shops in Tokyo have a seating charge, which can add to the overall cost of your coffee.
注意点
Azure OpenAI Service の一部の操作は、次の Azure Resource Manager のエンドポイント経由でも実行できます。
https://management.azure.com/subscriptions/<サブスクリプション ID>/resourceGroups/<リソースグループ名>/providers/Microsoft.CognitiveServices/accounts/<リソース名>/deployments
https://management.azure.com/subscriptions/<サブスクリプション ID>/resourceGroups/<リソースグループ名>/providers/Microsoft.CognitiveServices/accounts/<リソース名>/models
API の定義を見る限りでは、デプロイに関する Read/Write 操作とモデルに対する Read 操作を実行できそうです。
私が検証した際には、Azure OpenAI Service のファイアウオールでインターネットからの操作を拒否していたとしても、Azure Resource Manager 経由での操作は拒否されませんでした。Azure Resource Manager 経由での操作に対しては、RBAC を利用して操作できるアカウントを制限する、Azure AD の条件付きアクセスを利用して操作できる IP アドレスや端末を制限するなど、別の対応が必要になります。ただしこの対応は Azure OpenAI Service の利用に限った話ではなく、Azure のサービスを利用する際に必要になる一般的な対応です。
まとめ
Azure OpenAI Service を Private Endpoint 経由で利用してみました。利用する方法や操作する内容によって、Azure OpenAI Service の Private Endpoint を経由するものと経由しないものがある点に注意です。
Note
- 当サイトは個人のブログです。このブログに示されている見解や意見は個人的なものであり、所属組織の見解や意見を表明するものではありません。
- 公開情報を踏まえて正確な情報を掲載するよう努めますが、その内容の完全性や正確性、有用性、安全性、最新性について一切保証しません。
- 添付文章やリンク先などを含む本サイトの内容は作成時点でのものであり、予告なく変更される場合があります。