Azure AI 検索 の結果をトリミングするためのセキュリティ フィルター

Note

Azure AI 検索は、Azure ポータル、REST API、およびAzure SDKから使用できます。 また、Foundry IQ は、エンタープライズ コンテンツを、Microsoft Foundry ポータルのエージェントの再利用可能なアクセス許可に対応したナレッジ ベースに変換するマネージド ナレッジ レイヤーです。

ドキュメント レベルの承認 に組み込みのアクセス制御リスト (ACL) サポート を使用できない検索ソリューションの場合、Azure AI 検索 では、グループまたはユーザー ID を含む文字列に基づいて検索結果をトリミングするフィルターの作成がサポートされています。

この記事では、以下の手順を含むセキュリティ フィルター処理のパターンについて説明します。

  • ID を格納するための文字列を含む、必要なコンテンツを含むソース ドキュメントをアセンブルする
  • プリンシパル識別子の検索インデックスにフィールドを作成する
  • インデックス作成のためにドキュメントを検索インデックスにプッシュする
  • search.in フィルター関数を使用してインデックスに対するクエリを実行する

最後に、ハンズオンの学習を提供するデモと例へのリンクを示します。 パターンを理解するには、まずこの記事を確認することをお勧めします。

セキュリティ フィルター パターンについて

セキュリティ フィルター パターンは、セキュリティ プリンシパルで構成される文字列に基づいて検索結果を含めたり除外したりする通常の OData フィルターを使用して、ドキュメント レベルの承認をシミュレートします。 セキュリティ プリンシパルによる認証や認可はありません。 プリンシパルは単なる文字列であり、検索結果にドキュメントを含めたり除外したりするためにフィルター式で使用されます。

セキュリティ フィルター処理を実現するには、いくつかの方法があります。 その 1 つは、Id eq 'id1' or Id eq 'id2' など、等値式の複雑な論理和演算を使用する方法です。 この方法は誤りが発生しやすく、保守が困難です。また、一覧の値の数が数百、数千単位の場合、クエリの応答時間が何秒も遅くなります。

この記事で説明するように、推奨される解決策として、セキュリティ フィルターに search.in 関数を使用します。 等値式ではなく search.in(Id, 'id1, id2, ...') を使用すると、1 秒未満の応答時間を期待できます。

前提条件

  • Microsoft Entra オブジェクトの識別子など、グループまたはユーザー ID を含む文字列フィールド。

  • 同じドキュメント内の他のフィールドは、そのグループまたはユーザーがアクセスできるコンテンツを提供する必要があります。 以下の JSON ドキュメントでは、"security_id" フィールドにセキュリティ フィルターで使用される ID が含まれており、呼び出し元の ID がドキュメントの "security_id" と一致する場合、名前、給与、結婚状況が含められます。

    {  
        "Employee-1": {  
            "employee_id": "100-1000-10-1-10000-1",
            "name": "Abram",   
            "salary": 75000,   
            "married": true,
            "security_id": "alphanumeric-object-id-for-employee-1"
        },
        "Employee-2": {  
            "employee_id": "200-2000-20-2-20000-2",
            "name": "Adams",   
            "salary": 75000,   
            "married": true,
            "security_id": "alphanumeric-object-id-for-employee-2"
        } 
    }  
    

セキュリティ フィールドを作成する

検索インデックスでは、フィールド コレクション内に、前の例の架空の "security_id" フィールドと同様の、グループまたはユーザー ID を含む 1 つのフィールドが必要です。

  1. セキュリティ フィールドを Collection(Edm.String) として追加します。

  2. フィールドの filterable 属性を true に設定します。

  3. 検索応答の一部として返されないように、フィールドの retrievable 属性を false に設定します。

  4. インデックスにはドキュメント キーが必要です。 "file_id" フィールドがこの要件を満たしています。

  5. インデックスには、検索可能かつ取得可能なコンテンツを含める必要もあります。 この例では、"file_name" と "file_description" のフィールドがそれを表しています。

    次のインデックス スキーマは、フィールドの要件を満たしています。 Azure AI 検索でインデックスを作成するドキュメントには、group_idsを含め、これらすべてのフィールドの値が必要です。 セキュリティ フィルターにgroup_id1またはgroup_id2が含まれている場合、クエリはfile_namesecured_file_bを含むドキュメントを返します。

    POST https://[search service].search.windows.net/indexes/securedfiles/docs/index?api-version=2026-04-01
    {
         "name": "securedfiles",  
         "fields": [
             {"name": "file_id", "type": "Edm.String", "key": true, "searchable": false },
             {"name": "file_name", "type": "Edm.String", "searchable": true },
             {"name": "file_description", "type": "Edm.String", "searchable": true },
             {"name": "group_ids", "type": "Collection(Edm.String)", "filterable": true, "retrievable": false }
         ]
     }
    

Note

retrievableを false に設定すると、検索結果のドキュメントの一部としてgroup_idsが返されなくなります。 コンテンツ難読化またはフィールド レベルのセキュリティ メカニズムではありません。 このパターンでは、すべてのクエリにセキュリティ フィルターを適用することで、ドキュメント レベルの承認が適用されます。 すべてのクエリ機能や応答形式から機密情報を保護するために、 retrievable だけに依存しないでください。

REST API を使用してインデックスにデータをプッシュする

セキュリティ フィールドの値を含め、フィールド コレクション内の各フィールドの値を提供するドキュメントを検索インデックスに設定します。 Azure AI 検索には、セキュリティ フィールドを設定するための特別な API や機能は用意されていません。 しかし、この記事の最後に示すいくつかの例では、このフィールドを設定する手法について説明します。

Azure AI 検索においてデータを読み込む方法は以下のとおりです。

  • すべてのフィールドが設定されたドキュメントをインポートする 1 回のプッシュまたはプル (インデクサー) 操作
  • 複数のプッシュまたはプル操作。 二次的なインポート操作が適切なドキュメント識別子を対象としている限り、複数のインポートを通してフィールドを個別に読み込むことができます。

次の例は、インデックスの URL エンドポイントのドキュメント コレクションに対する 1 つの HTTP POST 要求を示しています (「ドキュメント - インデックス」を参照してください)。 HTTP 要求の本文は、インデックスを作成するドキュメントの JSON レンダリングです。

POST https://[search service].search.windows.net/indexes/securedfiles/docs/index?api-version=2026-04-01
{
    "value": [
        {
            "@search.action": "upload",
            "file_id": "1",
            "file_name": "secured_file_a",
            "file_description": "File access is restricted to Human Resources.",
            "group_ids": ["group_id1"]
        },
        {
            "@search.action": "upload",
            "file_id": "2",
            "file_name": "secured_file_b",
            "file_description": "File access is restricted to Human Resources and Recruiting.",
            "group_ids": ["group_id1", "group_id2"]
        },
        {
            "@search.action": "upload",
            "file_id": "3",
            "file_name": "secured_file_c",
            "file_description": "File access is restricted to Operations and Logistics.",
            "group_ids": ["group_id5", "group_id6"]
        }
    ]
}

グループの一覧を使用して既存のドキュメントを更新する必要がある場合は、merge または mergeOrUpload アクションを使用できます。

{
    "value": [
        {
            "@search.action": "mergeOrUpload",
            "file_id": "3",
            "group_ids": ["group_id7", "group_id8", "group_id9"]
        }
    ]
}

クエリでセキュリティ フィルターを適用する

group_ids のアクセス権に基づいてドキュメントをトリミングするには、group_ids/any(g:search.in(g, 'group_id1, group_id2,...')) フィルターを含む検索クエリを発行する必要があります (この "group_id1, group_id2,..." は、検索要求の発行元が属するグループです)。

このフィルターは、指定された識別子のいずれかが group_ids フィールドに含まれるすべてのドキュメントと一致します。 Azure AI 検索 を使用してドキュメントを検索する方法の詳細については、ドキュメントの検索に関するページを参照してください。

このサンプルでは、POST 要求を使用してクエリを設定する方法を示します。

以下のような HTTP POST 要求を発行し、要求本文でフィルターを指定します。

POST https://[service name].search.windows.net/indexes/securedfiles/docs/search?api-version=2026-04-01

{
   "filter":"group_ids/any(g:search.in(g, 'group_id1, group_id2'))"  
}

group_ids に "group_id1" または "group_id2" が含まれるドキュメントが返されます。 つまり、要求の発行元が読み取りアクセス権を持っているドキュメントが取得されます。

{
 [
   {
    "@search.score":1.0,
     "file_id":"1",
     "file_name":"secured_file_a",
   },
   {
     "@search.score":1.0,
     "file_id":"2",
     "file_name":"secured_file_b"
   }
 ]
}

次のステップ

この記事では、ユーザー ID と search.in() 関数に基づいて結果をフィルター処理するためのパターンについて説明します。 この関数を使用して、各ターゲット ドキュメントに関連付けられたプリンシパルの識別子と一致する要求元のユーザーについて、プリンシパルの識別子を渡すことができます。 検索要求が処理されると、search.in 関数によって、ユーザーのプリンシパルが読み取りアクセス権を持っていない検索結果は除外されます。 プリンシパルの識別子は、セキュリティ グループ、ロール、さらにはユーザー自身の ID を表す場合があります。

その他の例、デモ、ビデオについては以下を参照してください。