Filtros de seguridad para restringir los resultados en Azure AI Search

Azure AI Search no proporciona permisos en el nivel de documento y no puede variar los resultados de búsqueda desde dentro del mismo índice mediante permisos de usuario. Como solución alternativa, puede crear un filtro que restrinja los resultados de búsqueda en función de una cadena que contenga un grupo o una identidad de usuario.

En este artículo se describe un patrón para el filtrado de seguridad que incluye los pasos siguientes:

  • Ensamblar los documentos de origen con el contenido necesario
  • Crear un campo que contiene los identificadores de entidad de seguridad
  • Insertar los documentos en el índice de búsqueda para la indexación
  • Consulta del índice con la función de filtro de search.in

Acerca del patrón de filtro de seguridad

Aunque Azure AI Search no se integra con subsistemas de seguridad para acceder al contenido dentro de un índice, muchos clientes que tienen requisitos de seguridad en el nivel de documento han encontrado que los filtros pueden satisfacer sus necesidades.

En Azure AI Search, un filtro de seguridad es como un filtro de OData normal que incluye o excluye un resultado de búsqueda en función de un valor coincidente, a excepción de que en un filtro de seguridad, los criterios son una cadena que consta de una entidad de seguridad. No hay autenticación ni autorización a través de la entidad de seguridad. La entidad de seguridad es simplemente una cadena, que se usa en una expresión de filtro, para incluir o excluir un documento de los resultados de la búsqueda.

Hay varias maneras de conseguir el filtrado de seguridad. Una forma es a través de una disyunción complicada de expresiones de igualdad: por ejemplo, Id eq 'id1' or Id eq 'id2', y así sucesivamente. Este enfoque es propenso a errores, es difícil de mantener y, en los casos en que la lista contiene cientos o miles de valores, ralentiza muchos segundos el tiempo de respuesta de consulta.

Una mejor solución es usar la función search.in para los filtros de seguridad, como se describe en este artículo. Si utiliza search.in(Id, 'id1, id2, ...') en lugar de una expresión de igualdad, puede esperar tiempos de respuesta de fracciones de segundo.

Requisitos previos

  • El campo que contiene la identidad de grupo o usuario debe ser una cadena con el atributo filterable. Debe ser una colección. No debe permitir valores NULL.

  • Otros campos del mismo documento deben proporcionar un contenido accesible para ese grupo o usuario. En los siguientes documentos JSON, los campos "security_id" contienen identidades que se usan en un filtro de seguridad y el nombre, salario y estado civil se incluirán si la identidad del autor de la llamada coincide con el "security_id" del documento.

    {  
        "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"
        } 
    }  
    

    Nota:

    El proceso de recuperar los identificadores principales e insertar esas cadenas en documentos de origen que Azure AI Search puede indexar no se trata en este artículo. Consulte la documentación del proveedor de servicios de identidad para recibir ayuda con la obtención de identificadores.

Creación del campo de seguridad

En el índice de búsqueda, dentro de la colección de campos, necesita un campo que contenga la identidad de grupo o usuario, similar al campo ficticio "security_id" del ejemplo anterior.

  1. Agregue un campo de seguridad como Collection(Edm.String). Asegúrese de que tiene un atributo filterable establecido en true para que los resultados de la búsqueda se filtren según el acceso del usuario. Por ejemplo, si establece el campo group_ids en ["group_id1, group_id2"] para el documento con file_name "secured_file_b", solo los usuarios que pertenezcan a los identificadores de grupo "group_id1" o "group_id2" tendrán acceso de lectura al archivo.

    Establezca el atributo retrievable del campo en false para que no se devuelva como parte de la solicitud de búsqueda.

  2. Los índices requieren una clave de documento. El campo "file_id" cumple ese requisito. Los índices también deben contener contenido en el que se puedan realizar búsquedas. Los campos "file_name" y "file_description" representan eso en este ejemplo.

    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 }
         ]
     }
    

Inserción de datos en el índice mediante la API REST

Envíe una solicitud de HTTP POST a la colección de documentos del punto de conexión de dirección URL del índice (consulte Documentos: índice). El cuerpo de la solicitud HTTP es una representación JSON de los documentos que se van a indexar:

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

En el cuerpo de la solicitud, especifique el contenido de los documentos:

{
    "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 necesita actualizar un documento existente con la lista de grupos, puede usar la acción merge o mergeOrUpload:

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

Aplicación del filtro de seguridad en la consulta

Para recortar documentos basados en el acceso group_ids, debe emitir una consulta de búsqueda con un filtro group_ids/any(g:search.in(g, 'group_id1, group_id2,...')), donde "group_id1, group_id2,..." son los grupos a los que pertenece el emisor de la solicitud de búsqueda.

Este filtro coincide con todos los documentos para los que el campo group_ids contiene uno de los identificadores especificados. Para obtener detalles completos sobre cómo buscar documentos con Azure AI Search, puede leer Búsqueda en documentos.

En este ejemplo se muestra cómo configurar la consulta mediante una solicitud POST.

Emita la solicitud POST HTTP:

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]

Especifique el filtro en el cuerpo de la solicitud:

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

Debería obtener los documentos en que group_ids contenga "group_id1" o "group_id2". En otras palabras, obtendrá los documentos a los que el emisor de la solicitud tiene acceso de lectura.

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

Pasos siguientes

En este artículo se describe un patrón para filtrar los resultados en función de la identidad del usuario y la función search.in(). Puede usar esta función para pasar los identificadores de entidad de seguridad del usuario solicitante para que coincidan con los identificadores de entidad de seguridad asociados a cada documento de destino. Cuando se controla una solicitud de búsqueda, la función search.in filtra los resultados de la búsqueda para los que ninguna de las entidades de seguridad del usuario tiene acceso de lectura. Los identificadores de entidad de seguridad pueden representar elementos como los grupos de seguridad, los roles o incluso la identidad del usuario.

Para ver un patrón alternativo basado en Microsoft Entra ID o para revisar otras características de seguridad, consulte los vínculos siguientes.