Partage via


Filtres de sécurité pour le filtrage des résultats dans la recherche Azure AI

La recherche Azure AI ne fournit pas d’autorisations au niveau du document et ne peut pas varier les résultats de recherche à partir du même index par les autorisations utilisateur. Pour contourner ce problème, vous pouvez créer un filtre qui répartit les résultats de la recherche en fonction d’une chaîne contenant une identité de groupe ou d’utilisateur.

Cet article décrit un modèle de filtrage de sécurité qui comprend les étapes suivantes :

  • Assembler des documents sources avec le contenu requis
  • Créer un champ pour les identificateurs de principal
  • Envoyer (push) les documents à l’index de recherche pour l’indexation
  • Interroger l’index avec la fonction de filtre search.in

À propos du modèle de filtre de sécurité

Bien que la recherche Azure AI ne s’intègre pas aux sous-systèmes de sécurité pour accéder au contenu dans un index, de nombreux clients qui ont des exigences de sécurité au niveau du document ont constaté que les filtres peuvent répondre à leurs besoins.

Dans la recherche Azure AI, un filtre de sécurité est un filtre OData standard qui inclut ou exclut un résultat de recherche basé sur une valeur correspondante. La seule différence réside dans le fait que, dans un filtre de sécurité, les critères sont une chaîne composée d’un principal de sécurité. Il n’existe aucune authentification ou autorisation par le biais du principal de sécurité. Le principal est simplement une chaîne, utilisée dans une expression de filtre, pour inclure ou exclure un document des résultats de la recherche.

Il existe plusieurs façons de mettre en place le filtrage de sécurité. Une méthode consiste à utiliser une disjonction complexe d’expressions d’égalité. Par exemple : Id eq 'id1' or Id eq 'id2', etc. Cette approche est sujette aux erreurs et difficile à gérer. De plus, si la liste contient des centaines voire des milliers de valeurs, elle ralentit le temps de réponse de plusieurs secondes.

Une meilleure solution consiste à utiliser la fonction search.in pour les filtres de sécurité, comme décrit dans cet article. En utilisant search.in(Id, 'id1, id2, ...') à la place d’une expression d’égalité, vous pouvez obtenir des temps de réponse inférieurs à une seconde.

Prérequis

  • Le champ contenant un groupe ou une identité utilisateur doit être une chaîne avec l’attribut Filtrable. Il doit s’agir d’une collection. Elle ne doit pas autoriser les valeurs Null.

  • Les autres champs du même document doivent fournir le contenu accessible à ce groupe ou à cet utilisateur. Dans les documents JSON suivants, les champs « security_id » contiennent des identités utilisées dans un filtre de sécurité, et le nom, le salaire et l’état civil seront inclus si l’identité de l’appelant correspond au « security_id » du document.

    {  
        "Employee-1": {  
            "id": "100-1000-10-1-10000-1",
            "name": "Abram",   
            "salary": 75000,   
            "married": true,
            "security_id": "10011"
        },
        "Employee-2": {  
            "id": "200-2000-20-2-20000-2",
            "name": "Adams",   
            "salary": 75000,   
            "married": true,
            "security_id": "20022"
        } 
    }  
    

    Remarque

    Le processus de récupération des identificateurs principaux et d’injection de ces chaînes dans des documents sources qui peuvent être indexés par la recherche Azure AI n’est pas abordé dans cet article. Reportez-vous à la documentation de votre fournisseur de services d’identité pour obtenir des identificateurs.

Créer le champ de sécurité

Dans l’index de recherche, dans la collection de champs, vous avez besoin d’un champ qui contient l’identité du groupe ou de l’utilisateur, similaire au champ fictif « security_id » dans l’exemple précédent.

  1. Ajoutez un champ de sécurité en tant que Collection(Edm.String). Vérifiez qu’il a un attribut filterable défini avec la valeur true pour que les résultats de la recherche soient filtrés en fonction de l’accès dont dispose l’utilisateur. Par exemple, si vous définissez le champ group_ids avec la valeur ["group_id1, group_id2"] pour le document ayant comme file_name « secured_file_b », seuls les utilisateurs qui appartiennent à l’ID de groupe « group_id1 » ou « group_id2 » ont accès en lecture au fichier.

    Définissez l’attribut retrievable du champ sur false pour qu’il ne soit pas retourné dans le cadre de la requête de recherche.

  2. Les index nécessitent une clé de document. Le champ « file_id » répond à cette exigence. Les index doivent également contenir du contenu pouvant faire l’objet d’une recherche. Les champs « file_name » et « file_description » représentent cela dans cet exemple.

    POST https://[search service].search.windows.net/indexes/securedfiles/docs/index?api-version=2023-11-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 }
         ]
     }
    

Envoi (push) des données à votre index à l’aide de l’API REST

Envoyez une requête HTTP POST à la collection de documents du point de terminaison d’URL de votre index (voir Documents - Index). Le corps de la requête HTTP est un rendu JSON des documents à indexer :

POST https://[search service].search.windows.net/indexes/securedfiles/docs/index?api-version=2023-11-01

Dans le corps de la requête, spécifiez le contenu de vos documents :

{
    "value": [
        {
            "@search.action": "upload",
            "file_id": "1",
            "file_name": "secured_file_a",
            "file_description": "File access is restricted to the 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"]
        }
    ]
}

Si vous avez besoin de mettre à jour un document existant avec la liste des groupes, vous pouvez utiliser l’action merge ou mergeOrUpload :

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

Appliquer le filtre de sécurité sur la requête

Pour filtrer des documents en fonction de l’accès de group_ids, vous devez émettre une requête de recherche avec un filtre group_ids/any(g:search.in(g, 'group_id1, group_id2,...')), où « group_id1, group_id2,... » sont les groupes auxquels l’émetteur de la requête de recherche appartient.

Ce filtre correspond à tous les documents dont le champ group_ids contient l’un des identificateurs donnés. Pour obtenir des informations détaillées sur la recherche de documents à l’aide de la recherche Azure AI, lisez Recherche dans des documents.

Cet exemple montre comment configurer une requête à l’aide d’une requête POST.

Émettez la requête HTTP POST :

POST https://[service name].search.windows.net/indexes/securedfiles/docs/search?api-version=2020-06-30
Content-Type: application/json  
api-key: [admin or query key]

Spécifiez le filtre dans le corps de la requête :

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

Vous devez obtenir les documents où group_ids contient « group_id1 » ou « group_id2 ». En d’autres termes, vous obtenez les documents auxquels l’émetteur de la requête a accès en lecture.

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

Étapes suivantes

Cet article a décrit un modèle de filtrage des résultats en fonction de l’identité utilisateur et de la fonction search.in(). Vous pouvez utiliser cette fonction pour passer les identificateurs de principal de l’utilisateur demandeur et les mettre en correspondance avec les identificateurs de principal associés à chaque document cible. Quand une requête de recherche est traitée, la fonction search.in exclut les résultats de la recherche inaccessibles en lecture aux principaux de l’utilisateur. Les identificateurs de principal peuvent représenter des groupes de sécurité, des rôles ou même la propre identité de l’utilisateur.

Pour obtenir un autre modèle basé sur Microsoft Entra ID, ou pour revisiter d’autres fonctionnalités de sécurité, consultez les liens suivants.