Sincronizar sistemas de identidades diferentes

El control de acceso en Google Cloud Search se basa en la cuenta de Google de los usuarios. Al indexar contenido, todas las listas de control de acceso (LCA) de los elementos deben resolverse en usuarios de Google o IDs de grupo válidos (direcciones de correo electrónico).

En muchos casos, un repositorio no tiene conocimiento directo de las cuentas de Google. Por ejemplo, un usuario podría identificarse mediante una cuenta local o utilizar un inicio de sesión federado con un proveedor de identidades y un ID, en vez de usar su dirección de correo electrónico. Este ID se llama "ID externo".

Las fuentes de identidad se crean con la consola de administración y ayudan a hallar las correspondencias entre los sistemas de identidades de las siguientes maneras:

Usa fuentes de identidad cuando:

  • El repositorio no tenga conocimiento de la dirección de correo electrónico principal del usuario en G Suite o Cloud Directory.
  • El repositorio defina grupos para el control de acceso que no se correspondan con grupos de correo electrónico en G Suite.

Las fuentes de identidad mejoran la eficacia de la indexación al desvincularla de la asignación de identidades, lo que te permite aplazar la búsqueda del usuario durante la creación de LCAs y la indexación de elementos.

Ejemplo de implementación

En la imagen 1 se muestra una implementación de ejemplo en la que una empresa utiliza repositorios locales y en la nube. Cada repositorio usa un tipo diferente de ID externo para hacer referencia a los usuarios.

Ejemplo de implementación
Imagen 1. Implementación empresarial de ejemplo con diferentes tipos de identidades

El repositorio 1 identifica al usuario por medio de la dirección de correo electrónico declarada mediante SAML. Como el repositorio 1 tiene conocimiento de la dirección de correo electrónico principal del usuario en G Suite o Cloud Directory, no se necesita una fuente de identidad.

El repositorio 2 se integra directamente con un directorio local e identifica al usuario por su atributo sAMAccountName. En este caso, como el repositorio 2 usa un atributo sAMAccountName como ID externo, sí se necesita una fuente de identidad.

Crear una fuente de identidad

Si necesitas una fuente de identidad, consulta el artículo Asignar identidades de usuarios en Cloud Search.

Antes de crear el conector de contenido, deberás crear una fuente de identidad porque necesitarás el ID de esta para crear LCAs e indexar los datos. Como mencionamos anteriormente, al crear una fuente de identidad también se creará una propiedad de usuario personalizada en Cloud Directory. Esta propiedad sirve para registrar el ID externo de cada usuario en tu repositorio. El nombre de la propiedad usa la convención

IDENTITY_SOURCE_ID_identity
.

En la siguiente tabla se muestran dos fuentes de identidad, una que retiene los nombres de las cuentas SAM (sAMAccountName) como ID externos y otra que retiene los ID de usuario (uid) como ID externos.

fuente de identidad propiedad de usuario ID externo
id1 id1_identity sAMAccountName
id2 id2_identity uid

Crea una fuente de identidad para cada ID externo posible que se use para hacer referencia a un usuario de tu empresa.

En la siguiente tabla se muestra cómo aparecen un usuario con una cuenta de Google y dos ID externos (id1_identity e id2_identity) y sus valores en Google Directory Services:

usuario email id1_identity id2_identity
Ann ann@example.com example\ann 1001

Cuando crees las LCA para llevar a cabo la indexación, puedes hacer referencia al mismo usuario con los tres ID: correo electrónico de Google, sAMAccountName y uid.

Crear LCAs de usuario

Usa los métodos getUserPrincpal() o getGroupPrincipal() para crear entidades principales con un ID externo proporcionado.

En el siguiente ejemplo se muestra cómo obtener permisos de archivo. En estos permisos se incluye el nombre de todos los usuarios que tienen acceso al archivo.

FilePermissionSample.java
/**
 * Sample for mapping permissions from a source repository to Cloud Search
 * ACLs. In this example, POSIX file permissions are used a the source
 * permissions.
 *
 * @return Acl
 * @throws IOException if unable to read file permissions
 */
static Acl mapPosixFilePermissionToCloudSearchAcl(Path pathToFile) throws IOException {
  // Id of the identity source for external user/group IDs. Shown here,
  // but may be omitted in the SDK as it is automatically applied
  // based on the `api.identitySourceId` configuration parameter.
  String identitySourceId = "abcdef12345";

  // Retrieve the file system permissions for the item being indexed.
  PosixFileAttributeView attributeView = Files.getFileAttributeView(
      pathToFile,
      PosixFileAttributeView.class,
      LinkOption.NOFOLLOW_LINKS);

  if (attributeView == null) {
    // Can't read, return empty ACl
    return new Acl.Builder().build();
  }

  PosixFileAttributes attrs = attributeView.readAttributes();
  // ...
}

En el siguiente fragmento de código se muestra cómo crear entidades principales que sean propietarias utilizando el ID externo (externalUserName) almacenado en los atributos.

FilePermissionSample.java
// Owner, for search quality.
// Note that for principals the name is not the primary
// email address in Cloud Directory, but the local ID defined
// by the OS. Users and groups must be referred to by their
// external ID and mapped via an identity source.
List<Principal> owners = Collections.singletonList(
    Acl.getUserPrincipal(attrs.owner().getName(), identitySourceId)
);

Por último, en el siguiente fragmento de código se muestra cómo crear entidades principales que sean lectoras del archivo.

FilePermissionSample.java
// List of users to grant access to
List<Principal> readers = new ArrayList<>();

// Add owner, group, others to readers list if permissions
// exist. For this example, other is mapped to everyone
// in the organization.
Set<PosixFilePermission> permissions = attrs.permissions();
if (permissions.contains(PosixFilePermission.OWNER_READ)) {
  readers.add(Acl.getUserPrincipal(attrs.owner().getName(), identitySourceId));
}
if (permissions.contains(PosixFilePermission.GROUP_READ)) {
  String externalGroupName = attrs.group().getName();
  Principal group = Acl.getGroupPrincipal(externalGroupName, identitySourceId);
  readers.add(group);
}
if (permissions.contains(PosixFilePermission.OTHERS_READ)) {
  Principal everyone = Acl.getCustomerPrincipal();
  readers.add(everyone);
}

Una vez que tengas la lista de lectores y propietarios, podrás crear la LCA:

FilePermissionSample.java
// Build the Cloud Search ACL. Note that inheritance of permissions
// from parents is omitted. See `setInheritFrom()` and `setInheritanceType()`
// methods on the builder if required by your implementation.
Acl acl = new Acl.Builder()
    .setReaders(readers)
    .setOwners(owners)
    .build();

La API REST subyacente utiliza el patrón

identitysources/IDENTITY_SOURCE_ID/users/EXTERNAL_ID
con el ID al crear entidades principales. En las tablas anteriores, si creas una LCA con el id1_identity (SAMAccountName) de Ann, el ID se resolvería en:

identitysources/id1_identity/users/example/ann

Este ID completo se denomina "ID intermedio" del usuario porque funciona de puente entre el ID externo y los ID de Google almacenados en Google Cloud Directory.

Para obtener más información sobre cómo modelar las LCA utilizadas con un repositorio, consulta la sección Asignar LCAs.

Asignar grupos

Las fuentes de identidad también sirven como espacio de nombres de los grupos utilizados en las LCA. Puedes usar esta función de espacio de nombres para crear y asignar a un repositorio grupos que se usan solo con fines de seguridad o que son locales.

La API Groups de Cloud Identity permite crear un grupo y gestionar los miembros. Si quieres asociar el grupo con una fuente de identidad, usa el nombre del recurso de esta como espacio de nombres del grupo.

En el siguiente fragmento de código se muestra cómo crear un grupo utilizando la API Groups de Cloud Identity:

CreateGroupCommand.java
String namespace = "identitysources/" + idSource;
Group group = new Group()
    .setGroupKey(new EntityKey().setNamespace(namespace).setId(groupId))
    .setDescription("Demo group")
    .setDisplayName(groupName)
    .setLabels(Collections.singletonMap("system/groups/external", ""))
    .setParent(namespace);
try {
  CloudIdentity service = Utils.buildCloudIdentityService();
  Operation createOperation = service.groups().create(group).execute();

  if (createOperation.getDone()) {
    // Note: The response contains the data for a Group object, but as
    // individual fields. To convert to a Group instance, either populate
    // the fields individually or serialize & deserialize to/from JSON.
    //
    // Example:
    // String json = service.getJsonFactory().toString(response);
    // Group createdGroup =  service.getObjectParser()
    //     .parseAndClose(new StringReader(json), Group.class);
    System.out.printf("Group: %s\n",
        createOperation.getResponse().toString());
  } else {
    // Handle case where operation not yet complete, poll for
    // completion. API is currently synchronous and all operations return
    // as completed.
    // ...
  }
} catch (Exception e) {
  System.err.printf("Unable to create group: %s", e.getMessage());
  e.printStackTrace(System.err);
}

Crear la LCA de un grupo

Para crear la LCA de un grupo, usa el método getGroupPrincipal() con el que se creará una entidad principal de grupo usando un ID externo proporcionado. A continuación, crea la LCA con la clase Acl.Builder de la siguiente manera:

FilePermissionSample.java
if (permissions.contains(PosixFilePermission.GROUP_READ)) {
  String externalGroupName = attrs.group().getName();
  Principal group = Acl.getGroupPrincipal(externalGroupName, identitySourceId);
  readers.add(group);
}

Conectores de identidades

Aunque puedes usar ID externos que no sean de Google para crear LCAs e indexar elementos, los usuarios no podrán ver los elementos en una búsqueda hasta que sus ID externos se resuelvan en un ID de Google en Google Directory Services. Para asegurarte de que Google Directory Services conozca tanto la ID de Google como los ID externos de un usuario, tienes estas opciones:

Los conectores de identidades son programas que se utilizan para asociar IDs externos de identidades de empresas (usuarios y grupos) con identidades internas de Google utilizadas por Google Cloud Search. Si tienes que crear una fuente de identidad, deberás crear un conector de identidades.

Google Cloud Directory Sync (GCDS) es un ejemplo de un conector de identidades. Asocia información de usuarios y grupos de Active Directory de Microsoft con Cloud Directory, junto con los atributos de usuario que pueden representar su identidad en otros sistemas.