Criar um conector de identidade

Por padrão, o Google Cloud Search só reconhece identidades do Google no diretório do Google Cloud. Use conectores de identidade para sincronizar identidades empresariais com as identidades do Google usadas pelo Cloud Search.

O Google oferece estas opções para desenvolver conectores de identidade:

Criar um conector de identidade usando o SDK do Identity Connector

Um conector de identidade típico realiza estas tarefas:

  1. Configura o conector.
  2. Recupera usuários do seu sistema de identidade e os envia ao Google.
  3. Recupera grupos do seu sistema de identidade e os envia ao Google.

Configurar dependências

Inclua estas dependências no arquivo de build.

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'

Criar a configuração do conector

Cada conector usa um arquivo de configuração para parâmetros como o ID do repositório. Defina parâmetros como pares de chave-valor, como api.sourceId=1234567890abcdef.

O SDK do Google Cloud Search inclui parâmetros fornecidos pelo Google para todos os conectores. É necessário declarar o seguinte no arquivo de configuração:

  • Conector de conteúdo: declare api.sourceId e api.serviceAccountPrivateKeyFile. Eles identificam seu repositório e a chave privada necessária para acesso.
  • Conector de identidade: declare api.identitySourceId para identificar sua origem de identidade externa. Para sincronização de usuários, declare também api.customerId (o ID exclusivo da sua conta do Google Workspace).

Declare outros parâmetros fornecidos pelo Google apenas para modificar os valores padrão. Para detalhes sobre como gerar IDs e chaves, consulte Parâmetros fornecidos pelo Google.

Também é possível definir parâmetros específicos do repositório no arquivo de configuração.

Transmitir o arquivo de configuração para o conector

Defina a propriedade do sistema config para transmitir o arquivo de configuração. Use o argumento -D ao iniciar o conector. Exemplo:

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

Se você omitir esse argumento, o SDK tentará usar um arquivo chamado connector-config.properties no diretório local.

Criar um conector de identidade de sincronização completo usando uma classe de modelo

O SDK inclui um modelo FullSyncIdentityConnector para sincronizar todos os usuários e grupos do seu repositório. Esta seção explica como usá-lo.

Esta seção se refere ao código da amostra IdentityConnectorSample.java, que lê identidades de arquivos CSV.

Implementar o ponto de entrada do conector

O ponto de entrada é o método main(). Ele cria uma Application instância e chama start() para executar o conector.

Antes de chamar application.start(), use IdentityApplication.Builder para instanciar o modelo 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();
}

O SDK chama initConfig() depois que o método main() chama Application.build(). O método initConfig():

  1. Garante que a Configuration ainda não esteja inicializada.
  2. Inicializa o objeto Configuration com pares de chave-valor fornecidos pelo Google.

Implementar a interface Repository

O objeto Repository sincroniza identidades de repositório com identidades do Google. Ao usar um modelo, você só precisa modificar determinados métodos. Para FullSyncIdentityConnector, modifique estes métodos:

  • init(): para configuração e inicialização.
  • listUsers(): para sincronizar todos os usuários.
  • listGroups(): para sincronizar todos os grupos.
  • (Opcional) close(): Para limpeza durante o desligamento.

Receber parâmetros de configuração personalizados

Recupere parâmetros personalizados do objeto Configuration, normalmente no método init(). O snippet a seguir mostra como recuperar caminhos 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();
}

Para receber e analisar um parâmetro que contém vários valores, use um dos analisadores de tipo da classe Configuration para analisar os dados em blocos distintos. O snippet a seguir, do conector do tutorial, usa o getMultiValue método para receber uma lista de nomes de repositório do GitHub:

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

Receber o mapeamento de todos os usuários

Modifique listUsers() para recuperar mapeamentos de usuários. Esse método aceita um checkpoint para retomar a sincronização se ela for interrompida. Para cada usuário:

  1. Receba o mapeamento entre a identidade do Google e a identidade externa.
  2. Empacote o par no iterador retornado por listUsers().

Receber um mapeamento de usuários

Este snippet demonstra como recuperar mapeamentos de identidade de um arquivo 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);
    }
  }
  // ...
}

Empacotar um mapeamento de usuários em um iterador

O método listUsers() retorna um CheckpointCloseableIterable de IdentityUser objetos.

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

Receber um grupo

Modifique listGroups() para recuperar grupos e respectivos membros. Esse método aceita um checkpoint. Para cada grupo:

  1. Receba o grupo e respectivos membros.
  2. Empacote-os no iterador retornado por listGroups().

Receber a identidade do grupo

Este snippet demonstra como recuperar grupos e membros de um arquivo 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);
    }
  }
  // ...

}

Empacotar o grupo e respectivos membros em um iterador

O método listGroups() retorna um CheckpointCloseableIterable de IdentityGroup objetos.

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

Próximas etapas