Criar um conector de identidade

Por padrão, o Google Cloud Search reconhece apenas identidades do Google no Google Cloud Directory. 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 essas 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 a 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 substituir 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 instância Application 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 o Configuration ainda não foi inicializado.
  2. Inicializa o objeto Configuration com pares de chave-valor fornecidos pelo Google.

Implementar a interface do repositório

O objeto Repository sincroniza identidades de repositório com identidades do Google. Ao usar um modelo, você só precisa substituir determinados métodos. Para FullSyncIdentityConnector, substitua 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, geralmente no método init(). O snippet a seguir mostra como recuperar caminhos de 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 método getMultiValue 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

Substitua listUsers() para recuperar os 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 uma CheckpointCloseableIterable de objetos IdentityUser.

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

Receber um grupo

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

  1. Receba o grupo e os membros dele.
  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 objetos IdentityGroup.

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

Próximas etapas