建立識別資訊連接器

透過集合功能整理內容 你可以依據偏好儲存及分類內容。

根據預設,Google Cloud Search 只會識別儲存在 Google Cloud Directory (使用者和群組) 中的 Google 身分。身分識別連接器是用於將企業的身分與 Google Cloud Search 使用的 Google 身分保持同步。

Google 提供下列選項,用於開發識別資訊連接器:

  • Identity Connector SDK。這個選項適用於以 Java 程式設計語言編寫程式的開發人員。Identity Connector SDK 是 REST API 的包裝函式,可讓您快速建立連接器。如要使用 SDK 建立識別資訊連接器,請參閱使用 Identity Connector SDK 建立識別資訊連接器

  • 低階 REST API 和 API 程式庫。這些選項可能不適用於 Java 程式設計,或是程式碼集更符合 REST API 或程式庫的開發人員。如要使用 REST API 建立識別資訊連接器,請參閱目錄 API:使用者帳戶瞭解對應使用者的相關資訊,以及 Cloud Identity 說明文件對應對應群組。

使用 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>

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 設定設定參數。您必須在設定檔中宣告下列 Google 提供的參數:

  • 針對內容連接器,您必須宣告 api.sourceIdapi.serviceAccountPrivateKeyFile,因為這些參數可識別存放區的位置,以及存取存放區所需的私密金鑰。
  • 針對識別資訊連接器,您必須宣告 api.identitySourceId,因為這個參數可識別外部識別資訊來源的位置。如要同步處理使用者,您也必須將 api.customerId 宣告為您的企業 Google Workspace 帳戶的專屬 ID。

除非您想覆寫其他 Google 提供參數的預設值,否則不需要在設定檔中宣告。如要進一步瞭解 Google 提供的設定參數,例如如何產生特定 ID 和金鑰,請參閱 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 檔案中讀取使用者和群組 ID,並將這些資訊與 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();
}

在連接器的 main() 方法呼叫 Application.build 後,SDK 會在背景呼叫 initConfig() 方法。initConfig() 方法會執行下列工作:

  1. 呼叫 Configuation.isInitialized() 方法來確保 Configuration 尚未初始化。
  2. 使用 Google 提供的鍵/值組合初始化 Configuration 物件。每個鍵/值組合都會儲存在 Configuration 物件內的 ConfigValue 物件中。

導入 Repository 介面

Repository 物件的唯一用途是執行將存放區身分同步至 Google 身分。使用範本時,您只需要覆寫 Repository 介面中的特定方法,就能建立識別資訊連接器。針對 FullTraversalConnector,您可能需要覆寫下列方法:

  • init() 方法。如要執行任何身分存放區設定和初始化作業,請覆寫「init()」方法。

  • listUsers() 方法。如要將身分存放區中的所有使用者與 Google 使用者同步,請覆寫 listUsers() 方法。

  • listGroups() 方法。如要將身分存放區中的所有群組與 Google 群組同步,請覆寫 listGroups() 方法。

  • (選用) close() 方法。如果您需要執行存放區清理作業,請覆寫 close() 方法。在連接器關閉時,系統會呼叫此方法。

取得自訂設定參數

在處理連接器設定的過程中,您必須從 Configuration 物件取得任何自訂參數。這項工作通常會在 Repository 類別的 init() 方法中執行。

Configuration 類別有多種方法,可以從設定取得不同的資料類型。每個方法都會傳回 ConfigValue 物件。然後,請使用 ConfigValue 物件的 get() 方法擷取實際值。下列程式碼片段說明如何從 Configuration 物件擷取 userMappingCsvPathgroupMappingCsvPath 值:

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() 方法傳回的 iterator。

取得使用者對應關係

以下程式碼片段示範如何擷取儲存在 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 物件的 Iterator,特別是 CheckpointCloseableIterable。您可以使用 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);
    }
  }
  // ...

}

將群組和成員封裝為 iterator

listGroups() 方法會傳回 IdentityGroup 物件的 Iterator,特別是 CheckpointCloseableIterable。您可以使用 CheckpointClosableIterableImpl.Builder 類別建構及傳回疊代器。下列程式碼片段說明如何將每個群組和成員封裝至清單,並從該清單建構疊代器:

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

後續步驟

以下是建議採取的後續步驟: