Filtros de seguridad para recortar los resultados de Azure AI Search mediante Azure Active Directory
En este artículo se muestra cómo usar identidades de seguridad junto con filtros en Azure AI Search para recortar los resultados de búsqueda en función de la pertenencia a grupos de usuarios.
En este artículo se tratan las siguientes tareas:
- Creación de grupos y usuarios
- Asociar el usuario al grupo que ha creado
- Almacenar en caché los nuevos grupos
- Indexar documentos con grupos asociados
- Emitir una solicitud de búsqueda con el filtro de identificadores de grupo
Prerrequisitos
El índice de Azure AI Search debe tener un campo de seguridad para almacenar la lista de identidades de grupo que tienen acceso de lectura al documento. En este caso de uso se supone una correspondencia uno a uno entre un elemento protegible (como la aplicación universitaria de un individuo) y un campo de seguridad que especifica quién tiene acceso a ese elemento (personal de admisiones).
Debe tener permisos de administrador de inquilinos (propietario o administrador) para crear usuarios, grupos y asociaciones.
La aplicación también debe registrarse como una aplicación multiinquilino, como se describe en el procedimiento siguiente.
Registro de la aplicación con Azure Active Directory
Este paso integra la aplicación con Azure Active Directory para aceptar inicios de sesión de cuentas de usuario y grupo. Si no es un administrador de inquilinos de su organización, es posible que tenga que crear un nuevo inquilino para realizar los pasos siguientes.
En Azure Portal, busque el inquilino de Azure Active Directory.
A la izquierda, en Administrar, seleccione Registros de aplicacionesy, a continuación, seleccione Nuevo registro.
Asigne un nombre al registro, quizás un nombre similar al nombre de la aplicación de búsqueda. Consulte este artículo para obtener información sobre otras propiedades opcionales.
Seleccione Registro.
Una vez creado el registro de la aplicación, copie el identificador de aplicación (cliente). Deberá proporcionar esta cadena a su aplicación.
Si está siguiendo el proceso DotNetHowToSecurityTrimming, pegue este valor en el archivo app.config.
Copie el identificador de directorio (inquilino).
A la izquierda, seleccione permisos de API y luego seleccione Añadir un permiso.
Seleccione Microsoft Graph y, después, seleccione permisos delegados.
Busque y agregue los siguientes permisos delegados:
- Directory.ReadWrite.All
- Group.ReadWrite.All
- User.ReadWrite.All
Microsoft Graph proporciona una API que permite el acceso mediante programación a Azure Active Directory a través de una API REST. El ejemplo de código de este tutorial usa los permisos para llamar a Microsoft Graph API para crear grupos, usuarios y asociaciones. Las API también se usan para almacenar en caché los identificadores de grupo para un filtrado más rápido.
Seleccione Conceder consentimiento del administrador para el inquilino para completar el proceso de consentimiento.
Creación de usuarios y grupos
Si va a agregar la búsqueda a una aplicación establecida, es posible que tenga identificadores de usuario y grupo existentes en Azure Active Directory. En este caso, puede omitir los tres pasos siguientes.
Sin embargo, si no tiene usuarios existentes, puede usar las API de Microsoft Graph para crear las entidades de seguridad. Los fragmentos de código siguientes muestran cómo generar identificadores, que se convierten en valores de datos para el campo de seguridad en el índice de Azure AI Search. En nuestra solicitud hipotética de admisiones universitarias, este sería el identificador de seguridad para el personal de admisiones.
La pertenencia a usuarios y grupos puede ser muy fluida, especialmente en organizaciones grandes. El código que compila identidades de usuario y grupo debe ejecutarse con frecuencia suficiente para recoger los cambios en la pertenencia a la organización. Del mismo modo, el índice de Azure AI Search requiere una programación de actualización similar para reflejar el estado actual de los usuarios y recursos permitidos.
Paso 1: Crear 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"
};
Paso 2: Crear usuario
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
};
Paso 3: Asociar usuario y grupo
List<User> users = new List<User>() { user1, user2 };
Dictionary<Group, List<User>> groups = new Dictionary<Group, List<User>>() { { group, users } };
Paso 4: Almacenar en caché los identificadores de grupos
Opcionalmente, para reducir la latencia de red, puede almacenar en caché las asociaciones de grupo de usuarios para que cuando se emita una solicitud de búsqueda, los grupos se devuelven desde la memoria caché y se guarda un recorrido de ida y vuelta. Puede usar Batch API para enviar una única solicitud HTTP para múltiples usuarios y generar la memoria caché.
Microsoft Graph está diseñado para controlar un gran volumen de solicitudes. Si se produce un número abrumador de solicitudes, Microsoft Graph produce un error en la solicitud con el código de estado HTTP 429. Para obtener más información, consulte limitación de solicitudes de Microsoft Graph.
Indexar el documento con los grupos permitidos
Las operaciones de consulta en Azure AI Search se ejecutan a través de un índice de Azure AI Search. En este paso, una operación de indexación importa datos que se pueden buscar en un índice, incluidos los identificadores usados como filtros de seguridad.
Azure AI Search no autentica las identidades de usuario ni proporciona lógica para establecer qué contenido tiene permiso para ver un usuario. El caso de uso para el recorte de seguridad supone que se proporciona la asociación entre un documento confidencial y el identificador de grupo que tiene acceso a ese documento, importado intacto en un índice de búsqueda.
En el ejemplo hipotético, el cuerpo de la solicitud PUT en un índice de Azure AI Search incluiría el ensayo universitario o la transcripción académica de un solicitante, junto con el identificador del grupo que tiene permiso para ver ese contenido.
En el ejemplo genérico usado en el ejemplo de código de este tutorial, la acción de índice podría tener el siguiente aspecto:
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 una solicitud de búsqueda
Con fines de recorte de seguridad, los valores del campo de seguridad del índice son valores estáticos que se usan para incluir o excluir documentos en los resultados de búsqueda. Por ejemplo, si el identificador de grupo de Admisiones es "A11B22C33D44-E55F66G77-H88I99JKK", los documentos de un índice de Azure AI Search que tengan ese identificador en el campo de seguridad se incluyen (o excluyen) en los resultados de búsqueda enviados de vuelta al autor de la llamada.
Para filtrar los documentos devueltos en los resultados de búsqueda en función de los grupos del usuario que emite la solicitud, revise los pasos siguientes.
Paso 1: Recuperar identificadores de grupo de usuarios
Si los grupos del usuario aún no están almacenados en caché o la memoria caché ha expirado, emita la solicitud 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);
}
Paso 2: Redactar la solicitud de búsqueda
Suponiendo que tiene la pertenencia del usuario a grupos, puede realizar la solicitud de búsqueda con los valores de filtro adecuados.
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));
}
Paso 3: Control de los resultados
La respuesta incluye una lista filtrada de documentos, que consta de las que el usuario tiene permiso para ver. En función de cómo construya la página de resultados de búsqueda, es posible que desee incluir indicaciones visuales para reflejar el conjunto de resultados filtrado.
Conclusiones
En este tutorial, ha aprendido un patrón para usar inicios de sesión de usuario para filtrar documentos en los resultados de Azure AI Search, recortando los resultados de los documentos que no coinciden con el filtro proporcionado en la solicitud.