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

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

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

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

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

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

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

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

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

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

Мавен

<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 .

SDK Google Cloud Search содержит несколько предоставленных 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 .

Создайте соединитель удостоверений полной синхронизации с помощью класса шаблона.

SDK Identity Connector содержит класс шаблона 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, переопределите метод 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();

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

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