Создание соединителя удостоверений

По умолчанию Google Cloud Search распознает только учетные записи Google в Google Cloud Directory. Используйте коннекторы идентификации для синхронизации корпоративных учетных записей с учетными записями Google, которые использует Cloud Search.

Google предоставляет следующие возможности для разработки коннекторов идентификации:

Создайте коннектор идентификации с помощью SDK коннектора идентификации.

Типичный коннектор идентификации выполняет следующие задачи:

  1. Настраивает коннектор.
  2. Извлекает пользователей из вашей системы идентификации и перенаправляет их в Google.
  3. Извлекает группы из вашей системы идентификации и отправляет их в Google.

Настройка зависимостей

Включите эти зависимости в свой файл сборки.

Мэйвен

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

Грэдл

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

Создайте конфигурацию коннектора.

Каждый коннектор использует конфигурационный файл для параметров, таких как идентификатор вашего репозитория. Определяйте параметры в виде пар ключ-значение , например, api.sourceId= 1234567890abcdef .

В состав Google Cloud Search SDK входят параметры, предоставляемые Google, для всех коннекторов. В файле конфигурации необходимо указать следующее:

  • Коннектор контента : Объявите api.sourceId и api.serviceAccountPrivateKeyFile . Они идентифицируют ваш репозиторий и закрытый ключ, необходимый для доступа.
  • Коннектор идентификации : укажите api.identitySourceId для идентификации внешнего источника идентификации. Для синхронизации пользователей также укажите api.customerId (уникальный идентификатор вашей учетной записи Google Workspace).

Другие параметры, предоставляемые Google, следует указывать только для переопределения их значений по умолчанию. Подробную информацию о генерации идентификаторов и ключей см. в разделе «Параметры, предоставляемые Google» .

Вы также можете определить параметры, специфичные для репозитория, в своем конфигурационном файле.

Передайте файл конфигурации коннектору.

Укажите системное свойство config , чтобы передать файл конфигурации. Используйте аргумент -D при запуске коннектора. Например:

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

Если этот аргумент не будет указан, SDK попытается использовать файл с именем connector-config.properties расположенный в локальном каталоге.

Создайте коннектор идентификации с полной синхронизацией, используя шаблонный класс.

В состав SDK входит шаблон FullSyncIdentityConnector для синхронизации всех пользователей и групп из вашего репозитория. В этом разделе объясняется, как его использовать.

В этом разделе используется код из примера IdentityConnectorSample.java , который считывает данные об идентификаторах из CSV-файлов.

Реализуйте точку входа коннектора.

Точкой входа является метод main() . Он создает экземпляр Application и вызывает start() для запуска коннектора.

Перед вызовом application.start() используйте IdentityApplication.Builder для создания экземпляра шаблона 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();
}

SDK вызывает initConfig() после того, как ваш метод main() вызывает Application.build() . Метод initConfig() :

  1. Гарантирует, что Configuration еще не инициализирована.
  2. Инициализирует объект Configuration парами ключ-значение, предоставленными Google.

Реализуйте интерфейс репозитория.

Объект Repository синхронизирует идентификаторы репозитория с идентификаторами Google. При использовании шаблона достаточно переопределить только определенные методы. Для FullSyncIdentityConnector переопределите следующие методы:

  • init() : Для настройки и инициализации.
  • listUsers() : Для синхронизации всех пользователей.
  • listGroups() : Для синхронизации всех групп.
  • (Необязательно) close() : Для очистки ресурсов во время завершения работы.

Получить пользовательские параметры конфигурации

Получение пользовательских параметров из объекта Configuration , как правило, происходит в методе init() . Следующий фрагмент кода показывает, как получить пути к 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();
}

Чтобы получить и проанализировать параметр, содержащий несколько значений, используйте один из парсеров типов класса Configuration для разделения данных на отдельные фрагменты. В следующем фрагменте кода из коннектора из учебного пособия используется метод getMultiValue для получения списка имен репозиториев GitHub:

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

Получить карту для всех пользователей

Переопределите listUsers() для получения сопоставлений пользователей. Этот метод принимает контрольную точку для возобновления синхронизации в случае её прерывания. Для каждого пользователя:

  1. Получите соответствие между идентификатором Google и внешним идентификатором.
  2. Упакуйте пару в итератор, возвращаемый функцией listUsers() .

Получите сопоставление пользователей.

Этот фрагмент кода демонстрирует извлечение сопоставлений идентификаторов из 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);
    }
  }
  // ...
}

Преобразовать сопоставление пользователей в итератор.

Метод listUsers() возвращает объект CheckpointCloseableIterable содержащий объекты IdentityUser .

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

Соберите группу

Переопределите listGroups() , чтобы получить группы и их участников. Этот метод принимает контрольную точку. Для каждой группы:

  1. Найдите группу и её участников.
  2. Упакуйте их в итератор, возвращаемый функцией listGroups() .

Получите идентификатор группы.

Этот фрагмент кода демонстрирует извлечение групп и участников из 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);
    }
  }
  // ...

}

Объедините группу и ее участников в итератор.

Метод listGroups() возвращает объект CheckpointCloseableIterable содержащий объекты IdentityGroup .

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

Следующие шаги