ID コネクタを作成する

デフォルトでは、Google Cloud Search は Google Cloud Directory の Google ID のみを認識します。ID コネクタを使用して、企業の ID を Cloud Search で使用される Google ID と同期します。

Google は、ID コネクタを開発するための以下のオプションを提供しています。

Identity Connector SDK を使用して ID コネクタを作成する

ID コネクタによって行われる標準的なタスクは、次のとおりです。

  1. コネクタを構成します。
  2. ID システムからユーザーを取得して Google に送信します。
  3. ID システムからグループを取得して Google に送信します。

依存関係を設定する

これらの依存関係をビルドファイルに含めます。

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'

コネクタ構成を作成する

すべてのコネクタは、リポジトリ ID などのパラメータに構成ファイルを使用します。パラメータを api.sourceId=1234567890abcdef などの Key-Value ペアとして定義します。

Google Cloud Search SDK には、すべてのコネクタ用の Google 提供のパラメータが含まれています。構成ファイルで次のことを宣言する必要があります。

  • コンテンツ コネクタ: api.sourceIdapi.serviceAccountPrivateKeyFile を宣言します。これらは、リポジトリとアクセスに必要な秘密鍵を識別します。
  • ID コネクタ: 外部 ID ソースを識別するために api.identitySourceId を宣言します。ユーザーの同期では、api.customerId(Google Workspace アカウントの固有 ID)も宣言します。

他の Google 提供パラメータは、デフォルト値をオーバーライドする場合にのみ宣言します。ID と鍵の生成について詳しくは、Google 提供のパラメータをご覧ください。

構成ファイルでリポジトリ固有のパラメータを定義することもできます。

構成ファイルをコネクタに渡す

構成ファイルを渡すように config システム プロパティを設定します。コネクタを起動するときに -D 引数を使用します。次に例を示します。

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

この引数を省略すると、SDK はローカル ディレクトリ内の connector-config.properties という名前のファイルを使用しようとします。

テンプレート クラスを使用して完全同期 ID コネクタを作成する

SDK には、リポジトリのすべてのユーザーとグループを同期するための FullSyncIdentityConnector テンプレートが含まれています。このセクションでは、その使用方法について説明します。

このセクションでは、CSV ファイルから ID を読み取る IdentityConnectorSample.java サンプルのコードについて説明します。

コネクタのエントリ ポイントを実装する

エントリ ポイントは 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 は、main() メソッドが Application.build() を呼び出した後に initConfig() を呼び出します。initConfig() メソッド:

  1. Configuration が初期化されていないことを確認します。
  2. Google 提供の Key-Value ペアで Configuration オブジェクトを初期化します。

Repository インターフェースを実装する

Repository オブジェクトは、リポジトリ ID と Google ID を同期します。テンプレートを使用する場合は、一部のメソッドをオーバーライドするだけで済みます。FullSyncIdentityConnector の場合は、次のメソッドをオーバーライドします。

  • init(): セットアップと初期化用。
  • listUsers(): すべてのユーザーを同期します。
  • listGroups(): すべてのグループを同期します。
  • (省略可)close(): シャットダウン時のクリーンアップ用。

カスタム構成パラメータを取得する

通常は init() メソッドで、Configuration オブジェクトからカスタム パラメータを取得します。次のスニペットは、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 ID と外部 ID の間のマッピングを取得します。
  2. ペアを listUsers() から返されるイテレータにパッケージ化します。

ユーザー マッピングを取得する

このスニペットは、CSV ファイルから ID マッピングを取得する方法を示しています。

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() メソッドは、IdentityUser オブジェクトの CheckpointCloseableIterable を返します。

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

グループを取得する

listGroups() をオーバーライドして、グループとそのメンバーを取得します。このメソッドはチェックポイントを受け取って処理します。各グループに対して次の操作を行います。

  1. グループとそのメンバーを取得します。
  2. それらを listGroups() から返されるイテレータにパッケージ化します。

グループ ID を取得する

次のスニペットは、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() メソッドは、IdentityGroup オブジェクトの CheckpointCloseableIterable を返します。

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

次のステップ