Filtros de seguridad para recortar los resultados de Azure AI Search mediante MAzure 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 tareas siguientes:
- Creación de grupos y usuarios
- Asociación del usuario con el grupo que ha creado
- Almacenamiento en caché de nuevos grupos
- Indexación de documentos con grupos asociados
- Emisión de una solicitud de búsqueda con filtro de identificadores de grupo
Requisitos previos
El índice de Azure AI Search debe tener un campo de seguridad para almacenar la lista de identidades de grupo que tengan acceso de lectura al documento. Este caso de uso supone una correspondencia uno a uno entre un elemento protegible (por ejemplo, la solicitud de la universidad de un individuo) y un campo de seguridad que especifica quién tiene acceso a ese elemento (personal de admisión).
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 en 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 administrador de inquilinos en su organización, es posible que tenga que crear un inquilino para realizar los pasos siguientes.
En Azure Portal, busque el inquilino de Azure Active Directory.
A la izquierda, en Administrar, seleccione Registros de aplicaciones y, luego, elija Nuevo registro.
Asigne un nombre al registro; podría ser uno similar al de la aplicación de búsqueda. Consulte este artículo para obtener información sobre otras propiedades opcionales.
Seleccione Registrar.
Una vez creado el registro de aplicaciones, copie el identificador de la aplicación (cliente). Deberá proporcionar esta cadena a la aplicación.
Si se encuentra DotNetHowToSecurityTrimming, pegue este valor en el archivo app.config.
Copie el valor de Id. de directorio (inquilino).
En el lado izquierdo, seleccione Permisos de API y, después, Agregar un permiso.
Seleccione Microsoft Graph y, luego, 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 para este tutorial usa los permisos para llamar a Microsoft Graph API para la creación de grupos, usuarios y asociaciones. Las API también se usan para almacenar en caché identificadores de grupo de caché para filtrar con mayor rapidez.
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 utilizar Microsoft Graph API para crear las entidades de seguridad. Los siguientes fragmentos de código 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 hipotética solicitud de admisión de la universidad, esto serían los identificadores de seguridad para el personal de admisión.
La pertenencia de usuarios y grupos podría ser muy fluida, especialmente en grandes organizaciones. El código que crea identidades de usuario y grupo debe ejecutarse con la frecuencia suficiente como para recoger los cambios en la pertenencia de 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 recursos y usuarios 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 el usuario y el grupo
List<User> users = new List<User>() { user1, user2 };
Dictionary<Group, List<User>> groups = new Dictionary<Group, List<User>>() { { group, users } };
Paso 4: Almacenar los identificadores de grupos en caché
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 con varios usuarios y compilar la memoria caché.
Microsoft Graph se ha diseñado para controlar un alto volumen de solicitudes. Si se produce un número excesivo de solicitudes, Microsoft Graph produce un error en la solicitud con el código de estado HTTP 429. Para más información, consulte Guía de limitación de Microsoft Graph.
Documento de índice con sus grupos permitidos
Las operaciones de consulta en Azure AI Search se ejecutan sobre un índice de Azure AI Search. En este paso, una operación de indexación importa datos que permiten realizar búsquedas en un índice, incluidos los identificadores usados como filtros de seguridad.
Azure AI Search no autentica identidades de usuario ni proporciona lógica para establecer el contenido que un usuario tiene permiso para ver. El caso de uso para el recorte de seguridad asume que se proporciona la asociación entre un documento confidencial y el identificador del grupo que tiene acceso a ese documento, que se ha 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 trabajo o la transcripción de la universidad de un solicitante junto con el identificador de grupo que tiene permiso para ver el contenido.
En el ejemplo genérico utilizado en el ejemplo de código para este tutorial, la acción del índice podría ser la siguiente:
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);
Emisión de una solicitud de búsqueda
Por motivos de recorte de seguridad, los valores del campo de seguridad en el índice son valores estáticos que se usan para incluir o excluir documentos en los resultados de la búsqueda. Por ejemplo, si el identificador de grupo de admisiones es "A11B22C33D44-E55F66G77-H88I99JKK", todos 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 devueltos al autor de llamada.
Para filtrar los documentos devueltos en los resultados de búsqueda en función de los grupos de usuario que emiten la solicitud, revise los siguientes pasos.
Paso 1: Recuperar identificadores de grupo del usuario
Si los grupos del usuario todavía no estaban almacenados en la 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: Crear la solicitud de búsqueda
Suponiendo que tiene pertenencia a grupos del usuario, puede emitir la solicitud de búsqueda con los valores de filtro apropiados.
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: Controlar los resultados
La respuesta incluye una lista filtrada de documentos, que consta de los que el usuario tiene permiso para ver. Dependiendo de cómo se cree la página de resultados de búsqueda, puede que desee incluir indicaciones visuales para reflejar el conjunto de resultados filtrados.
Puntos clave
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.