次の方法で共有


Azure AI Search でデータ暗号化用にカスタマー マネージド キーを構成する

Azure AI Search は、 サービスマネージド キーを使用して保存データを自動的に暗号化します。 保護を強化する必要がある場合は、Azure Key Vault 内で作成して管理するキーを使用して、既定の暗号化を別の暗号化レイヤーで補完できます。

この記事では、カスタマー マネージド キー (CMK) または "Bring-Your-Own-Key" (BYOK) の暗号化を設定する手順について説明します。

Note

インデックスが CMK で暗号化されている場合、検索サービスでキーにアクセスできる場合にのみ、そのインデックスにアクセスできます。 アクセスが取り消された場合、インデックスは使用できず、インデックスが削除されるか、キーへのアクセスが復元されるまで、サービスをスケーリングできません。

CMK 暗号化されたオブジェクト

CMK 暗号化は、個々のオブジェクトに対して適用されます。 検索サービス全体で CMK が必要な場合は、適用ポリシーを設定します

CMK 暗号化は、オブジェクトが作成されるときに操作可能になります。 既に存在するオブジェクトを暗号化することはできません。 CMK 暗号化は、オブジェクトがディスクに保存されるたびに発生します。長期ストレージの場合は保存データ、短期ストレージの場合は一時データのいずれかです。 CMK では、ディスクに暗号化されていないデータが表示されることはありません。

暗号化できるオブジェクトには、インデックス、シノニム リスト、インデクサー、データ ソース、スキルセットがあります。 暗号化すると復号に評価コストがかかるため、機密性の高いコンテンツのみが暗号化されます。

暗号化は、次のコンテンツに対して実行されます。

  • インデックスとシノニム リスト内のすべてのコンテンツ。

  • インデクサー、データ ソース、スキルセット、およびベクトライザーの機密性の高いコンテンツ。 このコンテンツは、接続文字列、説明、ID、キー、ユーザー入力を格納するフィールドのみで構成されます。 たとえば、スキルセットには Azure AI サービス キーがあり、一部のスキルではカスタム エンティティなどのユーザー入力が受け取られます。 どちらの場合も、キーとスキルへのユーザー入力は暗号化されます。 外部リソース (Azure データ ソースや Azure OpenAI モデルなど) への参照も暗号化されます。

完全な二重暗号化

CMK 暗号化を導入すると、コンテンツが 2 回暗号化されます。 前のセクションで説明したオブジェクトとフィールドの場合、コンテンツは最初に CMK で暗号化され、次に Microsoft マネージド キーを使用して暗号化されます。 コンテンツは、長期ストレージ用のデータ ディスクと、短期ストレージに使用される一時ディスク上で二重に暗号化されます。

CMK での暗号化を有効にすると、インデックスのサイズが増加し、クエリのパフォーマンスが低下します。 これまでの観測に基づくと、実際のパフォーマンスはインデックスの定義やクエリの種類によって異なりますが、クエリ時間が 30 から 60 パーセント増加することが予想されます。 パフォーマンスが低下するため、この機能をオブジェクトで有効にするのは、実際に必要な場合のみにすることをお勧めします。

二重暗号化は、すべてのリージョンで使用できるようになりましたが、サポートは 2 つのフェーズでロール アウトされました。

  • 最初のロールアウトは 2020 年 8 月 1 日に行われ、以下に示す 5 つのリージョンが含まれていました。 次のリージョンで作成された検索サービスでは、データ ディスクの CMK がサポートされていましたが、一時ディスクはサポートされていませんでした。

    • 米国西部 2
    • 米国東部
    • 米国中南部
    • US Gov バージニア州
    • US Gov アリゾナ
  • 2021 年 5 月 13 日の 2 回目のロールアウトでは、一時ディスクの暗号化が追加され、CMK 暗号化がすべてのサポートされているリージョンへ拡張されました。

    最初のロールアウト中に作成されたサービスから CMK を使用していて、一時ディスクに対する CMK 暗号化も必要な場合は、選択したリージョンで新しい検索サービスを作成し、コンテンツを再デプロイする必要があります。 サービスの作成日を確認するには、「サービス作成日を確認する方法」を参照してください。

前提条件

制限事項

  • Azure Key Vault Managed Hardware Security Model (HSM) はサポートされません。

  • クロス サブスクリプションのサポートはありません。 Azure Key Vault と Azure AI Search は、同じサブスクリプションに存在する必要があります。

Key Vault に関するヒント

Azure Key Vault を初めて使用する場合は、このクイック スタート「PowerShell を使用して Azure Key Vault との間でシークレットの設定と取得を行う」を参照して、基本的なタスクについてご確認ください。

Key Vault を使用するときのヒントを次に示します。

  • 必要な数のキー コンテナーを使用します。 マネージド キーは異なるキー コンテナーに配置できます。 それぞれが異なるカスタマー マネージド暗号化キーで暗号化されて異なるキー コンテナーに格納されている、複数の暗号化されたオブジェクトに 1 つの検索サービスで対応できます。

  • システムまたはユーザーマネージド ID を介して接続してマネージド キーを取得できるように、同じテナントを使用します。 この動作では、両方のサービスで同じテナントを共有する必要があります。 テナント作成の詳細については、新しいテナントを設定する方法を参照してください。

  • 消去保護論理的な削除を有効にします。 カスタマー マネージド キーを使用する暗号化の性質上、Azure Key Vault キーが削除された場合、データを取得できません。 Key Vault キーの誤った削除によるデータ損失を防ぐため、キー コンテナーで論理的な削除と消去保護を有効にする必要があります。 論理的な削除は既定で有効になっているため、この機能を意図的に無効にした場合にのみ問題が発生します。 消去保護は既定では有効になっていませんが、Azure AI Search のカスタマー マネージド キー暗号化に必要です。

  • キーの使用状況を監視できるように、キー コンテナーでログを有効にします

  • キー コンテナー キーとアプリケーション シークレットの定期的なローテーションおよび登録時には、キーの自動ローテーションを有効にするか、厳密な手順に従います。 必ず、暗号化されたコンテンツすべてを新しいシークレットとキーを使用するように更新してから、古いものを削除します。 この手順を実行しないと、コンテンツの暗号化を解除できません。

手順 1: キー コンテナーにキーを作成する

使用する Azure Key Vault にキーが既に存在するが、キー識別子を収集する場合は、キーの生成をスキップします。 この情報は、暗号化されたオブジェクトを作成するときに必要です。

キーを追加する前に、Key Vault Crypto Officer ロールが自分に割り当てられていることを確認してください。

Azure AI Search 暗号化では、サイズ 2048、3072、4096 の RSA キーがサポートされます。 サポートされているキーの種類の詳細については、「キーについて」を参照してください。

  1. Azure portal にサインインして、キー コンテナーの概要ページを開きます。

  2. 左側の [オブジェクト]>[キー] を選択し、[生成/インポート] を選択します。

  3. [キーの作成] ペインの [オプション] の一覧から [生成] を選択して新しいキーを作成します。

  4. キーの [名前] を入力し、その他のキー プロパティの既定値をそのまま使用します。

  5. 必要に応じて、自動ローテーションを有効にするようにキー ローテーション ポリシーを設定します。

  6. [作成] を選択してデプロイを開始します。

  7. キーを選択し、現在のバージョンを選択してから、キー識別子をメモしておきます。 これは、キー値の URIキー名キー バージョンで構成されます。 Azure AI Search で暗号化されたインデックスを定義するには、識別子が必要です。

    新しい Key Vault キーを作成する

手順 2: セキュリティ プリンシパルを作成する

実行時に暗号化キーへの Azure AI Search アクセスを設定するには、いくつかのオプションがあります。 最も簡単な方法は、検索サービスのマネージド ID を使用してキーを取得することです。 システムまたはユーザーのマネージド ID を使用できます。 これにより、アプリケーション登録とアプリケーション シークレットの手順を省略できます。 または、Microsoft Entra アプリケーションを作成して登録し、要求に応じて検索サービスでアプリケーション ID を提供することもできます。

マネージド ID を使用することをお勧めします。 マネージド ID を使用すると、コードに資格情報 (ApplicationID や ApplicationSecret) を格納することなく、検索サービスで Azure Key Vault に対する認証を行うことができます。 この種類のマネージド ID のライフサイクルは、検索サービスのライフサイクルに関連付けられます。そのため、システムが割り当てることのできるマネージド ID は 1 つだけです。 マネージド ID が機能する方法について詳しくは、「Azure リソースのマネージド ID とは」を参照してください。

検索サービスのシステム割り当てマネージド ID を有効にします。

[システム割り当てマネージド ID] をオンにしているスクリーンショット。

手順 3: アクセス許可を付与する

Azure Key Vault では、ロールベースのアクセス制御を使用した承認がサポートされています。 キー コンテナーのアクセス ポリシーよりもこの方法をお勧めします。 詳細については、Azure ロールを使用して Key Vault のキー、証明書、シークレットへのアクセス権を付与する方法の説明を参照してください。

この手順では、Key Vault Crypto Service Encryption User ロールを検索サービスに割り当てます。 ローカルでテストする場合は、このロールを自分にも割り当てます。

  1. Azure portal にサインインし、キー コンテナーを見つけます。

  2. [アクセス制御 (IAM)] を選択し、[ロール割り当ての追加] を選択します。

  3. [Key Vault Crypto Service Encryption User] を選択し、[次へ] を選択します。

  4. マネージド ID を選択し、メンバーを選択して、検索サービスのマネージド ID を選択します。

  5. [レビューと割り当て] を選択します。

ロールの割り当てが運用できるようになるまで数分待ちます。

手順 4: コンテンツを暗号化する

暗号化キーは、オブジェクトを作成するときに追加されます。 インデックス、シノニム マップ、インデクサー、データ ソース、またはスキルセットにカスタマー マネージド キーを追加するには、Azure portal、Search REST API、Azure SDK のいずれかを使用して、暗号化が有効なオブジェクトを作成します。 Azure SDK を使用して暗号化を追加するには、この記事の Python の例を参照してください。

  1. 作成の API を呼び出して encryptionKey プロパティを指定します。

  2. オブジェクト定義に encryptionKey コンストラクトを挿入します。 このプロパティは、名前および説明と同じレベルにある第 1 レベルのプロパティです。 同じコンテナー、キー、バージョンを使用している場合は、同じ encryptionKey コンストラクトを各オブジェクト定義に貼り付けることができます。

    最初の例は、マネージド ID を使用して接続する検索サービスの encryptionKey を示しています。

    {
      "encryptionKey": {
        "keyVaultUri": "<YOUR-KEY-VAULT-URI>",
        "keyVaultKeyName": "<YOUR-ENCRYPTION-KEY-NAME>",
        "keyVaultKeyVersion": "<YOUR-ENCRYPTION-KEY-VERSION>"
      }
    }
    

    2 番目の例には、Microsoft Entra ID にアプリケーションを登録した場合に必要な accessCredentials が含まれています。

    {
      "encryptionKey": {
        "keyVaultUri": "<YOUR-KEY-VAULT-URI>",
        "keyVaultKeyName": "<YOUR-ENCRYPTION-KEY-NAME>",
        "keyVaultKeyVersion": "<YOUR-ENCRYPTION-KEY-VERSION>",
        "accessCredentials": {
          "applicationId": "<YOUR-APPLICATION-ID>",
          "applicationSecret": "<YOUR-APPLICATION-SECRET>"
        }
      }
    }
    
  3. オブジェクトに対して GET を発行して、暗号化キーが存在することを確認します。

  4. 暗号化されたインデックスのクエリなどのタスクを実行して、オブジェクトが運用できることを確認します。

暗号化されたオブジェクトを検索サービス上で作成したら、それをその種類の他のオブジェクトと同様に使用できます。 暗号化は、ユーザーと開発者に対して透過的です。

Key Vault のこれらの詳細はシークレットとは見なされず、Azure portal 内の関連する Azure Key Vault のページを参照して簡単に取得できます。

重要

Azure AI Search の暗号化されたコンテンツは、特定の バージョンので特定の Azure Key Vault キーを使用するように構成されています。 キーまたはバージョンを変更する場合は、それを使用するようにオブジェクトを更新してから、前のオブジェクトを削除する必要があります。 このようにしないと、オブジェクトは使用できなくなります。 キーが失われると、コンテンツの暗号化を解除できなくなります。

手順 5: 暗号化をテストする

暗号化が機能していることを確認するために、暗号化キーを取り消し、インデックスにクエリを実行し (使用不可のはずです)、その後、暗号化キーを復帰させます。

このタスクには Azure portal を使用します。

  1. [Azure Key Vault] ページで、[オブジェクト]>[キー] を選択します。

  2. 直前に作成したキーを選択し、[削除] を選択します。

  3. [Azure AI Search] ページで、[検索管理]>[インデックス] を選択します。

  4. インデックスを選択し、Search エクスプローラーを使用してクエリを実行します。 エラーが発生します。

  5. Azure Key Vault の [オブジェクト]>[キー] ページに戻ります。

  6. [削除されたキーの管理] を選択します。

  7. キーを選択し、[回復] を選択します。

  8. Azure AI Search でインデックスに戻り、クエリを再実行します。 検索結果が表示されます。 すぐに結果が表示されない場合は、少し待ってからやり直してください。

CMK コンプライアンスを適用するポリシーを設定する

Azure のポリシーは、組織の標準を適用し、コンプライアンスを大規模に評価するのに役立ちます。 Azure AI Search には、オプションのサービス全体の CMK 強制用の組み込みポリシーがあります。

このセクションでは、検索サービスの CMK 標準を定義するポリシーを設定します。 その後、このポリシーを適用するように検索サービスを設定します。

  1. Web ブラウザーで組み込みポリシーに移動します。 [割り当て] を選びます

    組み込み CMK ポリシーの割り当てのスクリーンショット。

  2. ポリシーのスコープを設定します。 [パラメーター] セクションで、[入力またはレビューが必要なパラメーターのみを表示する] をオフにし、[効果][拒否] に設定します。

    要求の評価中、拒否ポリシー定義に一致する要求に非準拠のマークが付けられます。 お使いのサービスの標準が CMK 暗号化であると仮定すると、"拒否" は、CMK 暗号化を指定 しない 要求が非準拠であることを意味します。

    組み込みの CMK ポリシーの効果を拒否に変更するスクリーンショット。

  3. ポリシーの作成を完了します。

  4. Services - Update API を呼び出して、サービス レベルで CMK ポリシーの強制を有効にします。

PATCH https://management.azure.com/subscriptions/<your-subscription-Id>/resourceGroups/<your-resource-group-name>/providers/Microsoft.Search/searchServices/<your-search-service-name>?api-version=2023-11-01

{
    "properties": {
        "encryptionWithCmk": {
            "enforcement": "Enabled"
        }
    }
}

暗号化キーをローテーションまたは更新する

Azure Key Vault の自動ローテーション機能を使用することをお勧めしますが、キーを手動でローテーションすることもできます。

キーまたはそのバージョンを変更する場合は、そのキーを使用するすべてのオブジェクトを新しい値を使用するように更新した後で、古い値を削除する必要があります。 そうしないと、オブジェクトは復号化できないため使用できなくなります。

  1. インデックスやシノニム マップによって使用されるキーを確認します。

  2. キー コンテナー内に新しいキーを作成しますが、元のキーは使用可能なままにしておきます。

  3. インデックスまたはシノニム マップの encryptionKey プロパティを更新して新しい値を使用します。 別の値を使用するように更新できるのは、当初このプロパティを使用して作成されたオブジェクトだけです。

  4. キー コンテナーで以前のキーを無効にするか削除します。 キー アクセスを監視して、新しいキーが使用されていることを確認します。

パフォーマンス上の理由で、検索サービスでは、キーが最大で数時間キャッシュされます。 新しいキーを指定せずにキーを無効にした、または削除した場合、キャッシュの有効期限が切れるまで、クエリは一時的に機能し続けます。 ただし、検索サービスでコンテンツの暗号化を解除できなくなると、次のメッセージが表示されます: "アクセスが禁止されています。 使用されたクエリ キーが失効している可能性があります - もう一度お試しください。"

暗号化されたコンテンツを使用する

カスタマー マネージド キーの暗号化を使用すると、暗号化/暗号化解除の処理が増えるため、インデックス作成とクエリの両方で待ち時間があることに気付く場合があります。 Azure AI Search は暗号化アクティビティをログに記録しませんが、キー コンテナーのログ記録を使用してキー アクセスを監視できます。

キー コンテナー構成の一環としてログを有効にすることが推奨されます。

  1. Log Analytics ワークスペースを作成します

  2. データ保有にワークスペースを使用するキー コンテナーに診断設定を追加します。

  3. カテゴリに audit または allLogs を選択し、診断設定に名前を付けて保存します。

暗号化キー構成の Python の例

このセクションでは、オブジェクト定義内の encryptionKey の Python 表現を示します。 インデックス、データ ソース、スキルセット、インデクサー、シノニム マップにも同じ定義が適用されます。 検索サービスとキー コンテナーでこの例を試すには、azure-search-python-samples からノートブックをダウンロードします。

いくつかのパッケージをインストールします。

! pip install python-dotenv
! pip install azure-core
! pip install azure-search-documents==11.5.1
! pip install azure-identity

暗号化キーを持つインデックスを作成します。

from azure.search.documents.indexes import SearchIndexClient
from azure.search.documents.indexes.models import (
    SimpleField,
    SearchFieldDataType,
    SearchableField,
    SearchIndex,
    SearchResourceEncryptionKey
)
from azure.identity import DefaultAzureCredential

endpoint="<PUT YOUR AZURE SEARCH SERVICE ENDPOINT HERE>"
credential = DefaultAzureCredential()

index_name = "test-cmk-index"
index_client = SearchIndexClient(endpoint=endpoint, credential=credential)  
fields = [
        SimpleField(name="Id", type=SearchFieldDataType.String, key=True),
        SearchableField(name="Description", type=SearchFieldDataType.String)
    ]

scoring_profiles = []
suggester = []
encryption_key = SearchResourceEncryptionKey(
    key_name="<PUT YOUR KEY VAULT NAME HERE>",
    key_version="<PUT YOUR ALPHANUMERIC KEY VERSION HERE>",
    vault_uri="<PUT YOUR KEY VAULT ENDPOINT HERE>"
)

index = SearchIndex(name=index_name, fields=fields, encryption_key=encryption_key)
result = index_client.create_or_update_index(index)
print(f' {result.name} created')

暗号化キーの構成が存在することを確認するインデックス定義を取得します。

index_name = "test-cmk-index-qs"
index_client = SearchIndexClient(endpoint=AZURE_SEARCH_SERVICE, credential=credential)  

result = index_client.get_index(index_name)  
print(f"{result}")  

いくつかのドキュメントでインデックスを読み込みます。 すべてのフィールド コンテンツは機密性が高いと見なされ、カスタマー マネージド キーを使用してディスク上で暗号化されます。

from azure.search.documents import SearchClient

# Create a documents payload
documents = [
    {
    "@search.action": "upload",
    "Id": "1",
    "Description": "The hotel is ideally located on the main commercial artery of the city in the heart of New York. A few minutes away is Time's Square and the historic centre of the city, as well as other places of interest that make New York one of America's most attractive and cosmopolitan cities."
    },
    {
    "@search.action": "upload",
    "Id": "2",
    "Description": "The hotel is situated in a  nineteenth century plaza, which has been expanded and renovated to the highest architectural standards to create a modern, functional and first-class hotel in which art and unique historical elements coexist with the most modern comforts."
    },
    {
    "@search.action": "upload",
    "Id": "3",
    "Description": "The hotel stands out for its gastronomic excellence under the management of William Dough, who advises on and oversees all of the Hotel's restaurant services."
    },
    {
    "@search.action": "upload",
    "Id": "4",
    "Description": "The hotel is located in the heart of the historic center of Sublime in an extremely vibrant and lively area within short walking distance to the sites and landmarks of the city and is surrounded by the extraordinary beauty of churches, buildings, shops and monuments. Sublime Cliff is part of a lovingly restored 1800 palace."
    }
]

search_client = SearchClient(endpoint=AZURE_SEARCH_SERVICE, index_name=index_name, credential=credential)
try:
    result = search_client.upload_documents(documents=documents)
    print("Upload of new document succeeded: {}".format(result[0].succeeded))
except Exception as ex:
    print (ex.message)

    index_client = SearchClient(endpoint=AZURE_SEARCH_SERVICE, credential=credential)

クエリを実行して、インデックスが動作することを確認します。

from azure.search.documents import SearchClient

query = "historic"  

search_client = SearchClient(endpoint=AZURE_SEARCH_SERVICE, credential=credential, index_name=index_name)
  
results = search_client.search(  
    query_type='simple',
    search_text=query, 
    select=["Id", "Description"],
    include_total_count=True
    )
  
for result in results:  
    print(f"Score: {result['@search.score']}")
    print(f"Id: {result['Id']}")
    print(f"Description: {result['Description']}")

クエリからの出力では、次の例のような結果が生成されます。

Score: 0.6130029
Id: 4
Description: The hotel is located in the heart of the historic center of Sublime in an extremely vibrant and lively area within short walking distance to the sites and landmarks of the city and is surrounded by the extraordinary beauty of churches, buildings, shops and monuments. Sublime Cliff is part of a lovingly restored 1800 palace.
Score: 0.26286605
Id: 1
Description: The hotel is ideally located on the main commercial artery of the city in the heart of New York. A few minutes away is Time's Square and the historic centre of the city, as well as other places of interest that make New York one of America's most attractive and cosmopolitan cities.

暗号化されたコンテンツはデータの更新またはクエリの前に復号化されるため、暗号化の視覚的証拠は表示されません。 暗号化が機能していることを確認するには、リソース ログを確認します。

次のステップ

Azure セキュリティ アーキテクチャを使い慣れていない場合は、Azure のセキュリティのドキュメントを確認してください。具体的には次の記事です。