Compartilhar via


Filtros de segurança para resultados de corte na IA do Azure Search

A Pesquisa de IA do Azure não fornece permissões nativas em nível de documento e não pode variar os resultados da pesquisa de dentro do mesmo índice por permissões de usuário. Como solução alternativa, você pode criar um filtro que corta os resultados da pesquisa com base em uma cadeia de caracteres que contém uma identidade de grupo ou de usuário.

Este artigo descreve um padrão para filtragem de segurança com as seguintes etapas:

  • Montar documentos de origem com o conteúdo necessário
  • Criar um campo para os identificadores de entidade de segurança
  • Enviar os documentos por push para o índice de pesquisa para indexação
  • Consultar o índice com a função de filtro search.in

Ele conclui com links para demonstrações e exemplos que fornecem aprendizado prático. Recomendamos revisar esse artigo primeiro para entender o padrão.

Sobre o padrão de filtro de segurança

Embora a Pesquisa de IA do Azure não se integre aos subsistemas de segurança para acesso ao conteúdo em um índice, muitos clientes que têm requisitos de segurança em nível de documento descobrem que os filtros podem atender às suas necessidades.

Na Pesquisa de IA do Azure, um filtro de segurança é um filtro OData regular que inclui ou exclui um resultado de pesquisa com base em uma cadeia de caracteres que consiste em uma entidade de segurança. Não há autenticação ou autorização por meio da entidade de segurança. A entidade de segurança é apenas uma cadeia de caracteres, usada em uma expressão de filtro, para incluir ou excluir um documento dos resultados da pesquisa.

Há várias maneiras de obter a filtragem de segurança. Uma maneira de obter filtragem de segurança é por meio de uma disjunção complicada de expressões de igualdade, por exemplo, Id eq 'id1' or Id eq 'id2' e assim por diante. Essa abordagem está propensa a erros, é de difícil manutenção e, em casos em que a lista contém centenas ou milhares de valores, diminui o tempo de resposta de consulta em muitos segundos.

Uma solução melhor é usar a função search.in para filtros de segurança, conforme descrito neste artigo. Se você usar search.in(Id, 'id1, id2, ...'), em vez de uma expressão de igualdade, poderá esperar tempos de resposta inferiores a um segundo.

Pré-requisitos

  • Um campo de cadeia de caracteres que contém um grupo ou identidade de usuário, como um identificador de objeto do Microsoft Entra.

  • Outros campos no mesmo documento devem fornecer o conteúdo acessível a esse grupo ou usuário. Nos documentos JSON a seguir, os campos "security_id" contêm identidades utilizadas em um filtro de segurança e o nome, o salário e o estado civil são incluídos se a identidade do chamador corresponder à "security_id" do documento.

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

Criar campo de segurança

No índice de pesquisa, dentro da coleção de campos, você precisa de um campo que contenha a identidade do grupo ou do usuário, semelhante ao campo fictício "security_id" do exemplo anterior.

  1. Adicione um campo de segurança como um Collection(Edm.String).

  2. Defina o atributo filterable do campo como true.

  3. Verifique se o atributo retrievable do campo está definido como false para que ele não seja retornado como parte da solicitação de pesquisa.

  4. Os índices exigem uma chave de documento. O campo “file_id” atende a esse requisito.

  5. Os índices também devem conter conteúdo pesquisável e recuperável. Os campos “file_name” e “file_description” representam isso neste exemplo.

    O esquema de índice a seguir satisfaz os requisitos de campo. Os documentos que você indexa na Pesquisa de IA do Azure devem ter valores para todos esses campos, incluindo as "group_ids". Para o documento com file_name "secured_file_b", somente os usuários que pertencem as IDs de grupo "group_id1" ou "group_id2" têm acesso de leitura ao arquivo.

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

Envio de dados por push para seu índice usando a API REST

Preencha seu índice de pesquisa com documentos que fornecem valores para cada campo na coleção de campos, incluindo valores para o campo de segurança. O Pesquisa de IA do Azure não fornece APIs ou recursos para preencher o campo de segurança especificamente. No entanto, vários dos exemplos listados no final deste artigo explicam técnicas para preencher esse campo.

Na Pesquisa de IA do Azure, as abordagens para carregar dados são:

  • Uma única operação push ou pull (indexador) que importa documentos preenchidos com todos os campos
  • Várias operações push ou pull. Desde que as operações de importação secundárias tenham como alvo o identificador de documentos correto, você pode carregar campos individualmente por meio de várias importações.

O exemplo a seguir mostra uma única solicitação HTTP POST para a coleção de documentos do ponto de extremidade de URL do seu índice (consulte Documentos – Índice). O corpo da solicitação HTTP é uma renderização JSON dos documentos a serem indexados:

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

Se você precisar atualizar um documento existente com a lista de grupos, poderá usar a ação merge ou mergeOrUpload:

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

Aplicar o filtro de segurança na consulta

Para cortar documentos com base em acesso group_ids, você deverá emitir uma consulta de pesquisa com um filtro group_ids/any(g:search.in(g, 'group_id1, group_id2,...')), em que 'group_id1, group_id2,...' são os grupos aos quais o emissor da solicitação de pesquisa pertence.

Esse filtro corresponde a todos os documentos para os quais o campo group_ids contém um dos identificadores determinados. Para obter detalhes completos sobre como pesquisar documentos usando a IA do Azure Search, você pode ler Pesquisar documentos.

Este exemplo mostra como configurar a consulta usando uma solicitação POST.

Emita a solicitação HTTP POST, especificando o filtro no corpo da solicitação:

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

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

Você deve obter os documentos de volta, em que group_ids contém "group_id1" ou "group_id2". Em outras palavras, você obtém os documentos aos quais o emissor da solicitação tem acesso de leitura.

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

Próximas etapas

Este artigo descreve um padrão para filtrar resultados com base na identidade do usuário e na função search.in(). Você pode usar essa função para passar identificadores de entidade ao usuário solicitante para correspondência com os identificadores de entidade associados a cada documento de destino. Quando uma solicitação de pesquisa é manipulada, a função search.in filtra os resultados da pesquisa aos quais nenhuma das entidades do usuário têm acesso de leitura. Os identificadores de entidade podem representar itens como grupos de segurança, funções ou até mesmo a própria identidade do usuário.

Para obter mais exemplos, demonstrações e vídeos: