Filtros de segurança para cortar resultados da Pesquisa de IA do Azure usando o MAzure Active Directory

Este artigo demonstra como usar identidades de segurança junto com filtros na Pesquisa de IA do Azure para cortar resultados de pesquisa com base na associação ao grupo de usuários.

Este artigo aborda as seguintes tarefas:

  • Criar grupos e usuários
  • Associar o usuário ao grupo que você criou
  • Cache dos novos grupos
  • Indexar documentos com grupos associados
  • Emitir uma solicitação de pesquisa com filtro de identificadores de grupo

Pré-requisitos

O índice no Azure AI Search deve ter um campo de segurança para armazenar a lista de identidades de grupo que têm acesso de leitura ao documento. Esse caso de uso pressupõe uma correspondência individual entre um item protegível (como um aplicativo de admissão de faculdade de um indivíduo) e um campo de segurança especificando quem tem acesso a esse item (equipe de admissão).

Você deve ter permissões de administrador de locatário (proprietário ou administrador) para criar usuários, grupos e associações.

Seu aplicativo também deve ser registrado como um aplicativo multilocatário, conforme descrito no procedimento a seguir.

Registrar seu aplicativo no Azure Active Directory

Esta etapa integra seu aplicativo ao Active Directory do Azure com a finalidade de aceitar entradas de contas de usuário e grupo. Caso você não seja um administrador de locatário em sua organização, talvez seja necessário criar um novo locatário para executar as etapas a seguir.

  1. No portal do Azure, localize o locatário do Active Directory do Azure.

  2. À esquerda, em Gerenciar, selecione Registros de aplicativo e, em seguida, escolha Novo registro.

  3. Dê um nome ao registro, talvez um nome semelhante ao nome do aplicativo de pesquisa. Consulte este artigo para obter informações sobre outras propriedades opcionais.

  4. Selecione Registrar.

  5. Quando o registro do aplicativo for criado, copie o valor da ID do aplicativo (cliente). Será necessário fornecer essa cadeia de caracteres para seu aplicativo.

    Se você estiver percorrendo o DotNetHowToSecurityTrimming, cole esse valor no arquivo app.config.

  6. Copie a ID do diretório (locatário).

  7. À esquerda, selecione Permissões de API e Adicionar uma permissão.

  8. Selecione Microsoft Graph e escolha Permissões delegadas.

  9. Pesquise e adicione as seguintes permissões delegadas:

    • Directory.ReadWrite.All
    • Group.ReadWrite.All
    • User.ReadWrite.All

    O Microsoft Graph fornece uma API que permite acesso programático ao Active Directory do Azure por meio de uma API REST. O exemplo de código para este passo a passo usa as permissões para chamar a API do Microsoft Graph para a criação de grupos, usuários e associações. As APIs também são usadas para o cache de identificadores de grupo para uma filtragem mais rápida.

  10. Selecione Conceder consentimento do administrador para que o locatário para concluir o processo de consentimento.

Criar usuários e grupos

Se você estiver adicionando pesquisa a um aplicativo estabelecido, talvez tenha identificadores de usuário e grupo existentes no Active Directory do Azure. Nesse caso, você pode ignorar as próximas três etapas.

No entanto, se você não tiver os usuários existentes, você pode usar as APIs do Microsoft Graph para criar entidades de segurança. Os snippets de código a seguir demonstram como gerar identificadores que se tornam os valores de dados para o campo de segurança no índice do Azure AI Search. Em nosso hipotético aplicativo de admissão de faculdade, isso seria os identificadores de segurança para a equipe de admissão.

A associação de grupo e de usuário pode ser muito flexível, especialmente em organizações de grandes porte. O código que cria as identidades de usuário e de grupo deve ser executado com frequência suficiente para acompanhar as alterações na associação da organização. Da mesma forma, o índice do Azure AI Search requer uma agenda de atualização semelhante para refletir o status atual de recursos e usuários permitidos.

Etapa 1: Criar grupo

private static Dictionary<Group, List<User>> CreateGroupsWithUsers(string tenant)
{
    Group group = new Group()
    {
        DisplayName = "My First Prog Group",
        SecurityEnabled = true,
        MailEnabled = false,
        MailNickname = "group1"
    };

Etapa 2: Criar usuário

User user1 = new User()
{
    GivenName = "First User",
    Surname = "User1",
    MailNickname = "User1",
    DisplayName = "First User",
    UserPrincipalName = String.Format("user1@{0}", tenant),
    PasswordProfile = new PasswordProfile() { Password = "********" },
    AccountEnabled = true
};

Etapa 3: Associar o usuário e o grupo

List<User> users = new List<User>() { user1, user2 };
Dictionary<Group, List<User>> groups = new Dictionary<Group, List<User>>() { { group, users } };

Etapa 4: Armazenar em Cache os identificadores de grupos

Opcionalmente, para reduzir a latência da rede, você pode armazenar em cache as associações de grupo de usuários para que, quando uma solicitação de pesquisa for emitida, os grupos sejam retornados do cache, salvando uma viagem de ida e volta. Você pode usar a API em lote para enviar uma única solicitação Http com vários usuários e criar o cache.

O Microsoft Graph foi projetado para lidar com um grande volume de solicitações. Caso haja um número excessivo de solicitações, o Microsoft Graph apresenta uma falha na solicitação com o código de status HTTP 429. Para saber mais, veja Limitação de mecanismo do Microsoft Graph.

Documento do índice com seus grupos permitidos

As operações de consulta no Azure AI Search são executadas em um índice do Azure AI Search. Nesta etapa, uma operação de indexação importa dados pesquisáveis em um índice, incluindo os identificadores usados como filtros de segurança.

O Azure AI Search não autentica identidades de usuário ou fornece lógica para estabelecer que conteúdo um usuário tem permissão para exibir. O caso de uso para as restrições de segurança pressupõe que você forneça a associação entre um documento confidencial e o identificador do grupo que tem acesso a esse documento, importado intacto a um índice de pesquisa.

No exemplo hipotético, o corpo da solicitação PUT em um índice do Azure AI Search incluiria a redação ou o histórico escolar de um candidato, juntamente com o identificador de grupo com permissão para exibir esse conteúdo.

No exemplo genérico usado na amostra de código para este passo a passo, a ação de índice será semelhante ao seguinte:

private static void IndexDocuments(string indexName, List<string> groups)
{
    IndexDocumentsBatch<SecuredFiles> batch = IndexDocumentsBatch.Create(
        IndexDocumentsAction.Upload(
            new SecuredFiles()
            {
                FileId = "1",
                Name = "secured_file_a",
                GroupIds = new[] { groups[0] }
            }),
              ...
            };

IndexDocumentsResult result = searchClient.IndexDocuments(batch);

Emitir uma solicitação de pesquisa

Para fins de restrições de segurança, os valores no seu campo de segurança no índice são valores estáticos usados para incluir ou excluir documentos nos resultados da pesquisa. Por exemplo, se o identificador de grupo para Admissões for "A11B22C33D44-E55F66G77-H88I99JKK", todos os documentos em um índice do Azure AI Search com esse identificador no campo de segurança serão incluídos (ou excluídos) nos resultados da pesquisa enviados de volta ao chamador.

Para filtrar os documentos retornados nos resultados da pesquisa com base nos grupos de usuários que emitirem a solicitação, analise as etapas a seguir.

Etapa 1: Recuperar os identificadores de grupo do usuário

Se os grupos do usuário ainda não estiverem armazenados em cache ou se o cache tiver expirado, emita a solicitação de grupos.

private static async void RefreshCache(IEnumerable<User> users)
{
    HttpClient client = new HttpClient();
    var userGroups = await _microsoftGraphHelper.GetGroupsForUsers(client, users);
    _groupsCache = new ConcurrentDictionary<string, List<string>>(userGroups);
}

Etapa 2: Criar a solicitação de pesquisa

Supondo que você tenha associação de grupos do usuário, você pode emitir a solicitação de pesquisa com os valores de filtro apropriados.

private static void SearchQueryWithFilter(string user)
{
    // Using the filter below, the search result will contain all documents that their GroupIds field   
    // contain any one of the Ids in the groups list
    string filter = String.Format("groupIds/any(p:search.in(p, '{0}'))", string.Join(",", String.Join(",", _groupsCache[user])));
    SearchOptions searchOptions =
        new SearchOptions()
        {
            Filter = filter
        };
    searchOptions.Select.Add("name");

    SearchResults<SecuredFiles> results = searchClient.Search<SecuredFiles>("*", searchOptions);

    Console.WriteLine("Results for groups '{0}' : {1}", _groupsCache[user], results.GetResults().Select(r => r.Document.Name));
}

Etapa 3: Lidar com os resultados

A resposta inclui uma lista filtrada de documentos, que consiste naqueles que o usuário tem permissão para visualizar. Dependendo de como você criar a página de resultados da pesquisa, você talvez queira incluir dicas visuais para refletir o conjunto de resultados filtrados.

Observações

Nesta explicação passo a passo, você aprendeu um padrão para usar entradas de usuário para filtrar documentos nos resultados da Pesquisa de IA do Azure, cortando os resultados de documentos que não correspondem ao filtro fornecido na solicitação.