建立識別資訊連接器

根據預設,Google Cloud Search 只會辨識 Google Cloud 目錄中的 Google 身分。使用身分識別連接器,將企業身分識別資訊同步至 Cloud Search 使用的 Google 身分識別資訊。

Google 提供下列選項,供您開發身分識別連接器:

使用 Identity Connector SDK 建立身分連接器

一般來說,身分識別連接器會執行下列工作:

  1. 設定連接器。
  2. 從身分系統擷取使用者,並傳送給 Google。
  3. 從身分識別系統擷取群組,並傳送至 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

Google Cloud Search SDK 包含所有連結器的 Google 提供參數。您必須在設定檔中宣告下列項目:

  • 內容連結器:宣告 api.sourceIdapi.serviceAccountPrivateKeyFile。這些資訊會識別您的儲存庫,以及存取所需的私密金鑰。
  • 身分識別連接器:宣告 api.identitySourceId,以識別外部身分識別來源。如要同步處理使用者,請一併宣告 api.customerId (Google Workspace 帳戶的專屬 ID)。

如要覆寫其他 Google 提供的參數預設值,請一併宣告這些參數。如要瞭解如何產生 ID 和金鑰,請參閱「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 會在 main() 方法呼叫 Application.build() 後呼叫 initConfig()initConfig() 方法:

  1. 確保 Configuration 尚未初始化。
  2. 使用 Google 提供的鍵/值組合初始化 Configuration 物件。

實作 Repository 介面

Repository 物件會將存放區身分同步至 Google 身分。使用範本時,您只需要覆寫特定方法。如要使用 FullSyncIdentityConnector,請覆寫下列方法:

取得自訂設定參數

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() 方法會傳回 IdentityUser 物件的 CheckpointCloseableIterable

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() 方法會傳回 IdentityGroup 物件的 CheckpointCloseableIterable

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

後續步驟