Créer un connecteur d'identité

Par défaut, Google Cloud Search ne reconnaît que les identités Google dans Google Cloud Directory. Utilisez des connecteurs d'identité pour synchroniser les identités de votre entreprise avec les identités Google utilisées par Cloud Search.

Google propose les options suivantes pour développer des connecteurs d'identité :

Créer un connecteur d'identité à l'aide du SDK Identity Connector

Un connecteur d'identité standard exécute les tâches suivantes :

  1. Configure le connecteur.
  2. Récupère les utilisateurs de votre système d'identité et les envoie à Google.
  3. Récupère les groupes de votre système d'identité et les envoie à Google.

Configurer des dépendances

Incluez ces dépendances dans votre fichier de compilation.

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'

Créer la configuration de votre connecteur

Chaque connecteur utilise un fichier de configuration pour les paramètres tels que l'ID de votre dépôt. Définissez les paramètres sous forme de paires clé-valeur, comme api.sourceId=1234567890abcdef.

Le SDK Google Cloud Search inclut des paramètres fournis par Google pour tous les connecteurs. Vous devez déclarer les éléments suivants dans votre fichier de configuration :

  • Connecteur de contenu : déclarez api.sourceId et api.serviceAccountPrivateKeyFile. Ils identifient votre dépôt et la clé privée nécessaire pour y accéder.
  • Connecteur d'identité : déclarez api.identitySourceId pour identifier votre source d'identité externe. Pour la synchronisation des utilisateurs, déclarez également api.customerId (l'ID unique de votre compte Google Workspace).

Déclarez les autres paramètres fournis par Google uniquement pour remplacer leurs valeurs par défaut. Pour savoir comment générer des ID et des clés, consultez Paramètres fournis par Google.

Vous pouvez également définir des paramètres propres au dépôt dans votre fichier de configuration.

Transmettre le fichier de configuration au connecteur

Définissez la propriété système config pour transmettre le fichier de configuration. Utilisez l'argument -D lorsque vous démarrez le connecteur. Exemple :

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

Si vous omettez cet argument, le SDK tente d'utiliser un fichier nommé connector-config.properties dans le répertoire local.

Créer un connecteur d'identité pour la synchronisation complète à l'aide d'un modèle de classe

Le SDK inclut un modèle FullSyncIdentityConnector permettant de synchroniser tous les utilisateurs et groupes de votre dépôt. Cette section explique comment l'utiliser.

Cette section fait référence au code de l'exemple IdentityConnectorSample.java, qui lit les identités à partir de fichiers CSV.

Ajouter le point d'entrée du connecteur

Le point d'entrée est la méthode main(). Il crée une instance Application et appelle start() pour exécuter le connecteur.

Avant d'appeler application.start(), utilisez IdentityApplication.Builder pour instancier le modèle FullSyncIdentityConnector.

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();
}

Le SDK appelle initConfig() après que votre méthode main() a appelé Application.build(). La méthode initConfig() :

  1. S'assure que Configuration n'est pas déjà initialisé.
  2. Initialise l'objet Configuration avec les paires clé/valeur fournies par Google.

Implémenter l'interface Repository

L'objet Repository synchronise les identités du dépôt avec celles de Google. Lorsque vous utilisez un modèle, il vous suffit de remplacer certaines méthodes. Pour FullSyncIdentityConnector, remplacez les méthodes suivantes :

  • init() : pour la configuration et l'initialisation.
  • listUsers() : pour synchroniser tous les utilisateurs.
  • listGroups() : pour synchroniser tous les groupes.
  • (Facultatif) close() : pour le nettoyage lors de l'arrêt.

Récupérer les paramètres de configuration personnalisés

Récupérez les paramètres personnalisés à partir de l'objet Configuration, généralement dans la méthode init(). L'extrait suivant montre comment récupérer les chemins d'accès aux fichiers CSV :

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();
}

Pour récupérer et analyser un paramètre contenant plusieurs valeurs, utilisez l'un des analyseurs de type de la classe Configuration, qui permettent d'analyser les données par fragments distincts. L'extrait de code suivant (issu du connecteur du tutoriel) permet d'obtenir la liste des noms de dépôts GitHub grâce à la méthode getMultiValue :

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

Récupérer le mappage de tous les utilisateurs

Remplacez listUsers() pour récupérer les mappages utilisateur. Cette méthode accepte un point de contrôle pour reprendre la synchronisation si elle est interrompue. Pour chaque utilisateur :

  1. Récupérer le mappage entre l'identité Google et l'identité externe
  2. Empaquetez la paire dans l'itérateur renvoyé par listUsers().

Récupérer un mappage d'utilisateurs

Cet extrait montre comment récupérer les mappages d'identité à partir d'un fichier 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);
    }
  }
  // ...
}

Empaqueter un mappage d'utilisateurs dans un itérateur

La méthode listUsers() renvoie un CheckpointCloseableIterable d'objets IdentityUser.

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

Récupérer un groupe

Remplacez listGroups() pour récupérer les groupes et leurs membres. Cette méthode accepte un point de contrôle. Pour chaque groupe :

  1. Récupérer le groupe et ses membres
  2. Empaquetez-les dans l'itérateur renvoyé par listGroups().

Récupérer l'identité du groupe

Cet extrait montre comment récupérer des groupes et des membres à partir d'un fichier 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);
    }
  }
  // ...

}

Empaqueter le groupe et ses membres dans un itérateur

La méthode listGroups() renvoie un CheckpointCloseableIterable d'objets IdentityGroup.

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

Étapes suivantes