Crea un conector de identidad

Según la configuración predeterminada, Google Cloud Search solo reconoce las identidades de Google almacenadas en Google Cloud Directory (usuarios y grupos). Los conectores de identidad se utilizan para sincronizar las identidades empresariales con las identidades de Google que utiliza Google Cloud Search.

Google brinda las siguientes opciones para desarrollar conectores de identidad:

  • El SDK de Identity Connector. Esta opción es para desarrolladores que programan en el lenguaje de programación Java. El SDK de Identity Connector es un wrapper alrededor de la API de REST que te permite crear conectores rápidamente. Para crear un conector de identidad con el uso de SDK, consulta Crea un conector de identidad con el uso del SDK de Identity Connector.

  • Una API de REST de bajo nivel y las bibliotecas de la API. Estas opciones son para desarrolladores que quizás no programen en Java o cuya base de código se adapta mejor a una API de REST o a una biblioteca. Si quieres crear un conector de identidad con la API de REST, consulta API de Directory: Cuentas de usuario para obtener información sobre la asignación de usuarios y la Documentación de Cloud Identity para obtener información sobre la asignación de grupos.

Crea un conector de identidad con el uso del SDK de Identity Connector

Un conector de identidad típico realiza las siguientes tareas:

  1. Configurar el conector.
  2. Obtener todos los usuarios del sistema de identidad empresarial y enviarlos a Google para que se sincronicen con las identidades de Google.
  3. Obtener todos los grupos del sistema de identidad empresarial y enviarlos a Google para que se sincronicen con las identidades de Google.

Configura dependencias

Debes incluir determinadas dependencias en el archivo de compilación para usar el SDK. Haz clic en la pestaña a continuación para ver las dependencias del entorno de compilación:

Maven

<dependency>
<groupId>com.google.enterprise.cloudsearch</groupId>
<artifactId>google-cloudsearch-identity-connector-sdk</artifactId>
<version>v1-0.0.3</version>
</dependency>

Gradle

 compile group: 'com.google.enterprise.cloudsearch',
         name: 'google-cloudsearch-identity-connector-sdk',
         version: 'v1-0.0.3'

Crea tu configuración del conector

Cada conector tiene un archivo de configuración que contiene los parámetros que usa el conector, como el ID de tu repositorio. Los parámetros se definen como pares clave-valor, como api.sourceId=1234567890abcdef.

El SDK de Google Cloud Search contiene varios parámetros de configuración proporcionados por Google que son usados por todos los conectores. Debes declarar los siguientes parámetros proporcionados por Google en tu archivo de configuración:

  • Para un conector de contenido, debes declarar api.sourceId y api.serviceAccountPrivateKeyFile, ya que estos parámetros identifican la ubicación de tu repositorio y la clave privada necesarias para acceder al repositorio.
  • Para un conector de identidad, debes declarar api.identitySourceId, ya que este parámetro identifica la ubicación de la fuente de identidad externa. Si sincronizas usuarios, también debes declarar api.customerId como el ID único para la cuenta de Google Workspace de tu empresa.

A menos que desees anular los valores predeterminados de otros parámetros proporcionados por Google, no necesitas declararlos en el archivo de configuración. Para obtener información adicional sobre los parámetros de configuración proporcionados por Google, como la forma de generar determinados ID y claves, consulta Parámetros de configuración proporcionados por Google.

También puedes definir tus propios parámetros específicos del repositorio para usar en tu archivo de configuración.

Pasa el archivo de configuración al conector

Configura la propiedad del sistema config para pasar el archivo de configuración al conector. Puedes configurar la propiedad con el argumento -D cuando inicies el conector. Por ejemplo, el siguiente comando inicia el conector con el archivo de configuración MyConfig.properties:

java -classpath myconnector.jar;... -Dconfig=MyConfig.properties MyConnector

Si falta este argumento, el SDK intenta acceder a un archivo de configuración predeterminado denominado connector-config.properties.

Crea un conector de identidad de sincronización completa con una clase de plantilla

El SDK de Identity Connector contiene una clase de plantilla FullSyncIdentityConnector que puedes usar para sincronizar todos los usuarios y grupos del repositorio de identidades con las identidades de Google. En esta sección, se explica cómo usar la plantilla FullSyncIdentityConnector para realizar una sincronización completa de los usuarios y los grupos desde un repositorio de identidades que no sea de Google.

En esta sección de los documentos, se hace referencia a fragmentos de código de la muestra IdentityConnecorSample.java. En esta muestra se leen las identidades de usuarios y grupos de dos archivos CSV y se sincronizan con las identidades de Google.

Implementa el punto de entrada del conector

El punto de entrada a un conector es el método main(). La tarea principal de este método es crear una instancia de la clase Application e invocar su método start() para ejecutar el conector.

Antes de llamar a application.start(), usa la clase IdentityApplication.Builder para crear una instancia de la plantilla FullSyncIdentityConnector. FullSyncIdentityConnector acepta un objeto Repository cuyos métodos implementarás. En el siguiente fragmento de código, se muestra cómo implementar el método main():

IdentityConnectorSample.java
/**
 * This sample connector uses the Cloud Search SDK template class for a full
 * sync connector. In the full sync case, the repository is responsible
 * for providing a snapshot of the complete identity mappings and
 * group rosters. This is then reconciled against the current set
 * of mappings and groups in Cloud Directory.
 *
 * @param args program command line arguments
 * @throws InterruptedException thrown if an abort is issued during initialization
 */
public static void main(String[] args) throws InterruptedException {
  Repository repository = new CsvRepository();
  IdentityConnector connector = new FullSyncIdentityConnector(repository);
  IdentityApplication application = new IdentityApplication.Builder(connector, args).build();
  application.start();
}

En segundo plano, el SDK llama al método initConfig() después de que el método main() de tu conector llama a Application.build. El método initConfig() realiza las siguientes tareas:

  1. Llama al método Configuation.isInitialized() para asegurarse de que no se haya inicializado Configuration.
  2. Inicializa un objeto Configuration con los pares clave-valor proporcionados por Google. Cada par clave-valor se almacena en un objeto ConfigValue dentro del objeto Configuration.

Implementa la interfaz Repository

El único propósito del objeto Repository es realizar la sincronización de las identidades del repositorio con las identidades de Google. Cuando usas una plantilla, solo debes anular ciertos métodos dentro de la interfaz Repository para crear un conector de identidad. En el caso de FullTraversalConnector, es probable que debas anular los siguientes métodos:

  • El método init(). Para realizar cualquier inicialización y configuración del repositorio de identidades, anula el método `init().

  • El método listUsers(). Para sincronizar todos los usuarios en el repositorio de identidades con los usuarios de Google, anula el método listUsers().

  • El método listGroups(). Para sincronizar todos los grupos en el repositorio de identidades con los Grupos de Google, anula el método listGroups().

  • close() (opcional): Si tienes que hacer una limpieza del repositorio, anula el método close(). Se llama a este método una vez durante el cierre del conector.

Obtén parámetros de configuración personalizados

Como parte del control de la configuración del conector, deberás obtener los parámetros personalizados del objeto Configuration. Por lo general, esta tarea se realiza en el método init() de una clase Repository.

La clase Configuration tiene varios métodos para obtener tipos de datos diferentes de una configuración. Cada método muestra un objeto ConfigValue. Luego, usa el método get() del objeto ConfigValue para recuperar el valor real. En el siguiente fragmento, se muestra cómo recuperar el valor de userMappingCsvPath y groupMappingCsvPath de un objeto Configuration:

IdentityConnectorSample.java
/**
 * Initializes the repository once the SDK is initialized.
 *
 * @param context Injected context, contains convenienve methods
 *                for building users & groups
 * @throws IOException if unable to initialize.
 */
@Override
public void init(RepositoryContext context) throws IOException {
  log.info("Initializing repository");
  this.context = context;
  userMappingCsvPath = Configuration.getString(
      "sample.usersFile", "users.csv").get().trim();
  groupMappingCsvPath = Configuration.getString(
      "sample.groupsFile", "groups.csv").get().trim();
}

Para obtener y analizar un parámetro que contenga varios valores, usa uno de los analizadores de tipos de la clase Configuration para analizar los datos en fragmentos separados. En el siguiente fragmento del conector del instructivo, se usa el método getMultiValue para obtener una lista de nombres de repositorios de GitHub:

GithubRepository.java
ConfigValue<List<String>> repos = Configuration.getMultiValue(
    "github.repos",
    Collections.emptyList(),
    Configuration.STRING_PARSER);

Obtén la asignación para todos los usuarios

Anula listUsers() para obtener la asignación para todos los usuarios del repositorio de identidades. El método listUsers() acepta un punto de control que representa la última identidad que se sincronizará. El punto de control se puede utilizar para reanudar la sincronización en caso de que se interrumpa el proceso. Para cada usuario en el repositorio, deberás seguir estos pasos en el método listUsers():

  1. Obtén una asignación que incluya la identidad de Google y la identidad externa asociada.
  2. Empaqueta el par en el iterador que muestra el método listUsers().

Obtén una asignación de usuario

En el siguiente fragmento de código, se demuestra cómo obtener las asignaciones de identidades almacenadas en un archivo CSV:

IdentityConnectorSample.java
/**
 * Retrieves all user identity mappings for the identity source. For the
 * full sync connector, the repository must provide a complete snapshot
 * of the mappings. This is reconciled against the current mappings
 * in Cloud Directory. All identity mappings returned here are
 * set in Cloud Directory. Any previously mapped users that are omitted
 * are unmapped.
 *
 * The connector does not create new users. All users are assumed to
 * exist in Cloud Directory.
 *
 * @param checkpoint Saved state if paging over large result sets. Not used
 *                   for this sample.
 * @return Iterator of user identity mappings
 * @throws IOException if unable to read user identity mappings
 */
@Override
public CheckpointCloseableIterable<IdentityUser> listUsers(byte[] checkpoint)
    throws IOException {
  List<IdentityUser> users = new ArrayList<>();
  try (Reader in = new FileReader(userMappingCsvPath)) {
    // Read user mappings from CSV file
    CSVParser parser = CSVFormat.RFC4180
        .withIgnoreSurroundingSpaces()
        .withIgnoreEmptyLines()
        .withCommentMarker('#')
        .parse(in);
    for (CSVRecord record : parser.getRecords()) {
      // Each record is in form: "primary_email", "external_id"
      String primaryEmailAddress = record.get(0);
      String externalId = record.get(1);
      if (primaryEmailAddress.isEmpty() || externalId.isEmpty()) {
        // Skip any malformed mappings
        continue;
      }
      log.info(() -> String.format("Adding user %s/%s",
          primaryEmailAddress, externalId));

      // Add the identity mapping
      IdentityUser user = context.buildIdentityUser(
          primaryEmailAddress, externalId);
      users.add(user);
    }
  }
  // ...
}

Empaqueta una asignación de usuario en un iterador

El método listUsers() muestra un Iterator, específicamente un CheckpointCloseableIterable, de objetos IdentityUser. Puedes usar la clase CheckpointClosableIterableImpl.Builder para construir y mostrar un iterador. En el siguiente fragmento de código, se muestra cómo empaquetar cada asignación en la lista y compilar el iterador a partir de esa lista:

IdentityConnectorSample.java
CheckpointCloseableIterable<IdentityUser> iterator =
  new CheckpointCloseableIterableImpl.Builder<IdentityUser>(users)
      .setHasMore(false)
      .setCheckpoint((byte[])null)
      .build();

Obtén un grupo

Anula listGroups() para obtener todos los grupos y sus miembros del repositorio de identidades. El método listGroups() acepta un punto de control que representa la última identidad que se sincronizará. El punto de control se puede utilizar para reanudar la sincronización en caso de que se interrumpa el proceso. Para cada usuario en el repositorio, deberás seguir estos pasos en el método listGroups():

  1. Obtén el grupo y sus miembros.
  2. Empaqueta cada grupo y sus miembros en el iterador que muestra el método listGroups().

Obtén la identidad del grupo

En el siguiente fragmento de código, se demuestra cómo obtener los grupos y sus miembros almacenados en un archivo CSV:

IdentityConnectorSample.java
/**
 * Retrieves all group rosters for the identity source. For the
 * full sync connector, the repository must provide a complete snapshot
 * of the rosters. This is reconciled against the current rosters
 * in Cloud Directory. All groups and members  returned here are
 * set in Cloud Directory. Any previously created groups or members
 * that are omitted are removed.
 *
 * @param checkpoint Saved state if paging over large result sets. Not used
 *                   for this sample.
 * @return Iterator of group rosters
 * @throws IOException if unable to read groups
 */    @Override
public CheckpointCloseableIterable<IdentityGroup> listGroups(byte[] checkpoint)
    throws IOException {
  List<IdentityGroup> groups = new ArrayList<>();
  try (Reader in = new FileReader(groupMappingCsvPath)) {
    // Read group rosters from CSV
    CSVParser parser = CSVFormat.RFC4180
        .withIgnoreSurroundingSpaces()
        .withIgnoreEmptyLines()
        .withCommentMarker('#')
        .parse(in);
    for (CSVRecord record : parser.getRecords()) {
      // Each record is in form: "group_id", "member"[, ..., "memberN"]
      String groupName = record.get(0);
      log.info(() -> String.format("Adding group %s", groupName));
      // Parse the remaining columns as group memberships
      Supplier<Set<Membership>> members = new MembershipsSupplier(record);
      IdentityGroup group = context.buildIdentityGroup(groupName, members);
      groups.add(group);
    }
  }
  // ...

}

Empaqueta el grupo y sus miembros en un iterador

El método listGroups() muestra un Iterator, específicamente un CheckpointCloseableIterable, de objetos IdentityGroup. Puedes usar la clase CheckpointClosableIterableImpl.Builder para construir y mostrar un iterador. En el siguiente fragmento de código, se muestra cómo empaquetar cada grupo y sus miembros en una lista y compilar el iterador a partir de esa lista:

IdentityConnectorSample.java
CheckpointCloseableIterable<IdentityGroup> iterator =
   new CheckpointCloseableIterableImpl.Builder<IdentityGroup>(groups)
      .setHasMore(false)
      .setCheckpoint((byte[])null)
      .build();

Próximos pasos

Aquí hay algunos pasos que puedes seguir:

  • Implementa el método close() para liberar cualquier recurso antes de finalizar el procedimiento (opcional).
  • Crea un conector de contenido mediante el SDK de Content Connector (opcional).