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

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

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

  • Identity Connector SDK. Этот вариант предназначен для разработчиков, использующих язык программирования Java. Identity Connector SDK — это оболочка для REST API, позволяющая быстро создавать коннекторы. Чтобы создать коннектор Identity с помощью этого SDK, см. статью Создание коннектора Identity с помощью Identity Connector SDK .

  • Низкоуровневый REST API и библиотеки API. Эти варианты предназначены для разработчиков, которые, возможно, не программируют на Java или чья кодовая база лучше подходит для REST API или библиотеки. Чтобы создать коннектор удостоверений с помощью REST API, см. раздел Directory API: Учётные записи пользователей для получения информации о сопоставлении пользователей и раздел Cloud Identity Documentation для получения информации о сопоставлении групп.

Создайте соединитель удостоверений с помощью Identity Connector SDK

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

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

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

Для использования SDK необходимо включить определённые зависимости в файл сборки. Нажмите на вкладку ниже, чтобы просмотреть зависимости для вашей среды сборки:

Maven

<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, используемых всеми коннекторами. В файле конфигурации необходимо указать следующие параметры, предоставляемые Google:

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

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

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

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

Настройте config системных свойств для передачи файла конфигурации в коннектор. Вы можете задать это свойство, используя аргумент -D при запуске коннектора. Например, следующая команда запускает коннектор с файлом конфигурации MyConfig.properties :

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

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

Создайте полностью синхронизированный коннектор идентификации с использованием шаблонного класса

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

В этом разделе документации используются фрагменты кода из примера IdentityConnecorSample.java . Этот пример считывает идентификаторы пользователей и групп из двух CSV-файлов и синхронизирует их с идентификаторами Google.

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

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

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

В фоновом режиме SDK вызывает метод initConfig() после того, как метод main() вашего коннектора вызывает Application.build . Метод initConfig() выполняет следующие задачи:

  1. Вызывает метод Configuation.isInitialized() чтобы убедиться, что Configuration не инициализирована.
  2. Инициализирует объект Configuration с помощью пар «ключ-значение», предоставленных Google. Каждая пара «ключ-значение» хранится в объекте ConfigValue внутри объекта Configuration .

Реализовать интерфейс Repository

Единственная цель объекта Repository — синхронизация идентификаторов репозитория с идентификаторами Google. При использовании шаблона для создания коннектора идентификаторов достаточно переопределить лишь некоторые методы в интерфейсе Repository . Для FullTraversalConnector вам, скорее всего, потребуется переопределить следующие методы:

  • Метод init() . Для настройки и инициализации репозитория идентификаторов переопределите метод init().

  • Метод listUsers() . Чтобы синхронизировать всех пользователей в репозитории удостоверений с пользователями Google, переопределите метод listUsers() .

  • Метод listGroups() . Чтобы синхронизировать все группы в репозитории идентификаторов с Google Groups, переопределите метод listGroups() .

  • (необязательно) Метод close() . Если вам нужно очистить репозиторий, переопределите метод close() . Этот метод вызывается один раз при завершении работы коннектора.

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

В рамках настройки коннектора вам потребуется получить все необходимые параметры из объекта Configuration . Эта задача обычно выполняется в методе init() класса Repository .

Класс Configuration содержит несколько методов для получения различных типов данных из конфигурации. Каждый метод возвращает объект ConfigValue . Затем вы используете метод get() объекта ConfigValue для получения фактического значения. В следующем фрагменте кода показано, как получить значения userMappingCsvPath и groupMappingCsvPath из объекта 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();
}

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

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

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

Переопределите listUsers() , чтобы получить сопоставление для всех пользователей из вашего репозитория идентификационных данных. Метод listUsers() принимает контрольную точку, представляющую последнюю синхронизированную идентификационную информацию. Контрольную точку можно использовать для возобновления синхронизации в случае прерывания процесса. Для каждого пользователя в вашем репозитории выполните следующие действия в методе 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() возвращает Iterator , а именно CheckpointCloseableIterable , объектов IdentityUser . Для создания и возврата итератора можно использовать класс CheckpointClosableIterableImpl.Builder . В следующем фрагменте кода показано, как упаковать каждое сопоставление в список и создать итератор из этого списка:

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

Получить группу

Переопределите метод listGroups() , чтобы получить все группы и их участников из вашего репозитория идентификаторов. Метод listGroups() принимает контрольную точку, представляющую последнюю синхронизированную идентификацию. Контрольную точку можно использовать для возобновления синхронизации в случае прерывания процесса. Для каждого пользователя в вашем репозитории выполните следующие действия в методе 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() возвращает Iterator , а именно CheckpointCloseableIterable , объектов IdentityGroup . Для создания и возврата итератора можно использовать класс CheckpointClosableIterableImpl.Builder . В следующем фрагменте кода показано, как упаковать каждую группу и её элементы в список и создать итератор на основе этого списка:

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

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

Вот несколько следующих шагов, которые вы можете предпринять:

  • (необязательно) Реализуйте метод close() для освобождения всех ресурсов перед завершением работы.
  • (необязательно) Создайте коннектор контента с помощью Content Connector SDK.