Crear un conector de identidades

De forma predeterminada, Google Cloud Search solo reconoce las identidades de Google almacenadas en Google Cloud Directory (usuarios y grupos). Los conectores de identidades permiten sincronizar las identidades de tu empresa con las identidades de Google utilizadas por Google Cloud Search.

Google ofrece las siguientes opciones para desarrollar conectores de identidades:

  • El SDK Identity Connector. Esta opción es muy adecuada para los desarrolladores que utilizan el lenguaje de programación Java. El SDK Identity Connector es un envoltorio de la API REST que permite crear conectores rápidamente. Para crear un conector de identidades con el SDK, consulta el apartado Crear un conector de identidades con el SDK Identity Connector.

  • Una API REST de nivel bajo y bibliotecas API. Estas opciones están dirigidas a desarrolladores que quizás no programen en Java o cuya base de código se ajuste más al uso de una API REST o una biblioteca. Si quieres crear un conector de identidades con la API REST, consulta el apartado sobre cuentas de usuario de la API Directory para obtener información sobre cómo asignar usuarios, y la documentación de Cloud Identity para ver instrucciones sobre cómo asignar grupos.

Crear un conector de identidades con el SDK Identity Connector

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

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

Descargar e instalar el SDK Identity Connector

Si quieres instalar el SDK Identity Connector, deberás tener Maven en el ordenador. Para instalar el SDK Identity Connector:

  1. Descarga el SDK Identity Connector.

  2. Desde la línea de comandos, descomprime el archivo que has descargado. Se creará un directorio del SDK Identity Connector.

  3. En ese directorio, usa los siguientes comandos para instalar los distintos componentes del SDK:

mvn org.apache.maven.plugins:maven-install-plugin:3.0.0-M1::install-file -DpomFile=parent/pom.xml -Dpackaging=pom -Dfile=parent/pom.xml

mvn org.apache.maven.plugins:maven-install-plugin:3.0.0-M1::install-file -Dfile=lib/google-api-services-cloudsearch-v1-rev0-1.23.0.jar

mvn org.apache.maven.plugins:maven-install-plugin:3.0.0-M1::install-file -Dfile=lib/google-api-services-cloudidentity-v1beta1-rev0-1.23.0.jar

mvn org.apache.maven.plugins:maven-install-plugin:3.0.0-M1::install-file -Dfile=lib/google-cloudsearch-connector-sdk-v1-0.0.2.jar

mvn org.apache.maven.plugins:maven-install-plugin:3.0.0-M1::install-file -Dfile=google-cloudsearch-identity-connector-sdk-v1-0.0.2.jar

Configurar dependencias

Para usar el SDK, debes incluir determinadas dependencias en el archivo de compilación. Haz clic en una de las pestañas que se muestran a continuación para ver las dependencias de tu entorno de compilación:

Maven

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

Gradle

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

Crear la configuración del conector

Todos los conectores incluyen un archivo de configuración que contiene los parámetros que utilizan, como el ID de tu repositorio. Los parámetros se definen como pares clave-valor, como en el ejemplo siguiente:

api.sourceId=1234567890abcdef
.

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

  • Si se trata de un conector de contenido, deberás declarar api.sourceId y api.serviceAccountPrivateKeyFile, ya que estos parámetros identifican la ubicación de tu repositorio y la clave privada necesaria para acceder a él.
  • Si se trata de un conector de identidades, deberás declarar api.identitySourceId, ya que este parámetro identifica la ubicación de tu fuente de identidad externa. Si vas a sincronizar cuentas de usuario, también deberás declarar api.customerId como ID único de la cuenta de G Suite de tu empresa.

A menos que quieras anular los valores predeterminados de otros parámetros proporcionados por Google, no tendrás que declararlos en el archivo de configuración. Para obtener más información sobre los parámetros facilitados por Google (por ejemplo, si quieres ver instrucciones sobre cómo crear determinados ID y claves), consulta el capítulo sobre parámetros de configuración proporcionados por Google.

También puedes definir tus propios parámetros del repositorio para usarlos en el archivo de configuración.

Nota: Aunque no hay una norma fija sobre la nomenclatura del archivo de propiedades del conector, se recomienda guardarlo con la extensión .properties o .config.

Enviar el archivo de configuración al conector

Para enviar el archivo de configuración al conector, define la propiedad del sistema config. Puedes definir esta propiedad utilizando el argumento -D al iniciar 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 intentará acceder a un archivo de configuración predeterminado denominado connector-config.properties.

Crear un conector de identidades de sincronización completa con una clase que se facilita como plantilla

El SDK Identity Connector contiene una clase que se facilita como 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 te explicamos cómo usar la plantilla FullSyncIdentityConnector para realizar una sincronización completa de los usuarios y 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 del ejemplo IdentityConnecorSample.java. En este ejemplo, se leen las identidades de usuarios y grupos de dos archivos CSV y se sincronizan con las identidades de Google.

Implementar 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 y hacer una llamada a su método start() para ejecutar el conector.

Antes de realizar una llamada a application.start(), usa la clase IdentityApplication.Builder para crear una instancia de la plantilla FullSyncIdentityConnector. La plantilla FullSyncIdentityConnector acepta un objeto Repository que contiene los métodos que vas a implementar. Repository. 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 haga una llamada a Application.build. El método initConfig() realiza las siguientes tareas:

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

Implementar la interfaz Repository

La única finalidad del objeto Repository es sincronizar las identidades del repositorio con las identidades de Google. Al usar una plantilla, solo tienes que anular ciertos métodos incluidos en la interfaz Repository para crear un conector de identidades. Para FullTraversalConnector, probablemente anularás los siguientes métodos:

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

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

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

  • (Opcional) Método close(). Si tienes que hacer una limpieza del repositorio, anula el método close(). Se realiza una llamada a este método al cerrar el conector.

Obtener parámetros de configuración personalizados

Cuando crees la configuración del conector, tendrás que obtener los parámetros personalizados del objeto Configuration. Esta tarea generalmente se realiza en el método init() de una clase Repository.

La clase Configuration contiene varios métodos para obtener diferentes tipos de datos de una configuración. Cada método devuelve un objeto ConfigValue. Deberás usar el método get() del objeto ConfigValue para obtener el valor real. En el siguiente fragmento se muestra cómo obtener los valores 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();
}

Si quieres 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. El siguiente fragmento, del conector del tutorial, 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);

Obtener la asignación de todos los usuarios

Anula listUsers() para obtener la asignación de todos los usuarios de tu 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 continuar la sincronización en caso de que se interrumpa el proceso. Con cada usuario del repositorio, sigue 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 un iterador devuelto por el método listUsers().

Obtener la asignación de un usuario

En el siguiente fragmento de código se muestra 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);
    }
  }
  // ...
}

Empaquetar una asignación de usuarios en un iterador

El método listUsers() devuelve un Iterator, en concreto un CheckpointCloseableIterable, de los objetos IdentityUser. Puedes utilizar la clase CheckpointClosableIterableImpl.Builder para crear y devolver un iterador. En el siguiente fragmento de código se muestra cómo empaquetar cada asignación en una lista y crear el iterador a partir de esa lista:

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

Obtener un grupo

Anula listGroups() para obtener todos los grupos y sus miembros de tu 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 continuar la sincronización en caso de que se interrumpa el proceso. Con cada usuario del repositorio, sigue estos pasos en el método listGroups():

  1. Obtén el grupo y sus miembros.
  2. Empaqueta el grupo y los miembros en un iterador devuelto por el método listGroups().

Obtener la identidad del grupo

En el siguiente fragmento de código se muestra cómo obtener los grupos y 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);
    }
  }
  // ...

}

Empaquetar el grupo y los miembros en un iterador

El método listGroups() devuelve un Iterator, en concreto un CheckpointCloseableIterable, de los objetos IdentityGroup. Puedes utilizar la clase CheckpointClosableIterableImpl.Builder para crear y devolver un iterador. En el siguiente fragmento de código se muestra cómo empaquetar cada grupo y sus miembros en una lista y crear el iterador a partir de esa lista:

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

Pasos siguientes

A continuación te indicamos algunos pasos que puedes seguir: