同步處理不同識別資訊系統

Google Cloud Search 的存取權控管機制是以使用者的 Google 帳戶為依據。為內容建立索引時,項目上的所有 ACL 都必須解析為有效的 Google 使用者或群組 ID (電子郵件地址)。

在許多情況下,存放區不會直接瞭解 Google 帳戶。使用者可能改用本機帳戶,或透過身分識別提供者和 ID (而非使用者的電子郵件地址) 進行同盟登入,以識別每個帳戶。這個 ID 稱為外部 ID

透過管理控制台建立的識別資訊來源可協助彌合身分識別系統之間的差距,方法如下:

在下列情況下使用身分識別來源:

  • 存放區不知道 Google Workspace 或 Google Cloud Directory 中使用者的主要電子郵件地址。
  • 存放區定義的存取權控制群組,與 Google Workspace 中以電子郵件為基礎的群組不符。

身分來源會將索引編製作業與身分對應作業分離,藉此提升索引編製效率。這種解耦方式可讓您在建立 ACL 和為項目建立索引時,延後查詢使用者。

部署範例

圖 1 顯示企業同時使用內部部署和雲端存放區的部署範例。每個存放區都會使用不同類型的外部 ID 參照使用者。

部署範例
圖 1. 以不同身分類型進行企業部署的範例。

存放區 1 會使用透過 SAML 聲明的電子郵件地址識別使用者。由於存放區 1 瞭解 Google Workspace 或 Cloud Directory 中使用者的主要電子郵件地址,因此不需要身分識別來源。

存放區 2 會直接與內部部署目錄整合,並透過使用者的 sAMAccountName 屬性識別使用者。由於存放區 2 使用 sAMAccountName 屬性做為外部 ID,因此需要身分來源。

建立識別資訊來源

如需識別資訊來源,請參閱「在 Cloud Search 中對應使用者識別資訊」。

您必須先建立身分來源,才能建立內容連線器,因為您需要身分來源 ID 才能建立存取控制清單和索引資料。如先前所述,建立身分識別來源時,也會在 Cloud Directory 中建立自訂使用者屬性。您可以使用這項屬性,記錄存放區中每位使用者的外部 ID。屬性名稱採用 IDENTITY_SOURCE_ID_identity 慣例。

下表顯示兩個身分來源,一個用來將 SAM 帳戶名稱 (sAMAccountName) 做為外部 ID,另一個則用來將使用者 ID (uid) 做為外部 ID。

識別資訊來源 使用者屬性 外部 ID
id1 id1_identity sAMAccountName
id2 id2_identity uid

為企業中用來參照使用者的每個可能外部 ID 建立身分來源。

下表顯示在 Cloud Directory 中,擁有 Google 帳戶和兩個外部 ID (id1_identity 和 id2_identity) 的使用者及其值:

使用者 電子郵件 id1_identity id2_identity
小安 ann@example.com example\ann 1001

建立索引的存取控制清單時,您可以使用三種不同的 ID (Google 電子郵件、sAMAccountName 和 uid) 參照同一位使用者。

寫入使用者 ACL

使用 getUserPrincpal() 方法或 getGroupPrincipal() 方法,透過提供的外部 ID 建立主體。

以下範例說明如何擷取檔案權限。這些權限包括有權存取檔案的使用者名稱。

FilePermissionSample.java
/**
 * Sample for mapping permissions from a source repository to Cloud Search
 * ACLs. In this example, POSIX file permissions are used a the source
 * permissions.
 *
 * @return Acl
 * @throws IOException if unable to read file permissions
 */
static Acl mapPosixFilePermissionToCloudSearchAcl(Path pathToFile) throws IOException {
  // Id of the identity source for external user/group IDs. Shown here,
  // but may be omitted in the SDK as it is automatically applied
  // based on the `api.identitySourceId` configuration parameter.
  String identitySourceId = "abcdef12345";

  // Retrieve the file system permissions for the item being indexed.
  PosixFileAttributeView attributeView = Files.getFileAttributeView(
      pathToFile,
      PosixFileAttributeView.class,
      LinkOption.NOFOLLOW_LINKS);

  if (attributeView == null) {
    // Can't read, return empty ACl
    return new Acl.Builder().build();
  }

  PosixFileAttributes attrs = attributeView.readAttributes();
  // ...
}

下列程式碼片段說明如何使用屬性中儲存的外部 ID (externalUserName),建立擁有者主體。

FilePermissionSample.java
// Owner, for search quality.
// Note that for principals the name is not the primary
// email address in Cloud Directory, but the local ID defined
// by the OS. Users and groups must be referred to by their
// external ID and mapped via an identity source.
List<Principal> owners = Collections.singletonList(
    Acl.getUserPrincipal(attrs.owner().getName(), identitySourceId)
);

最後,下列程式碼片段說明如何建立檔案讀取者主體。

FilePermissionSample.java
// List of users to grant access to
List<Principal> readers = new ArrayList<>();

// Add owner, group, others to readers list if permissions
// exist. For this example, other is mapped to everyone
// in the organization.
Set<PosixFilePermission> permissions = attrs.permissions();
if (permissions.contains(PosixFilePermission.OWNER_READ)) {
  readers.add(Acl.getUserPrincipal(attrs.owner().getName(), identitySourceId));
}
if (permissions.contains(PosixFilePermission.GROUP_READ)) {
  String externalGroupName = attrs.group().getName();
  Principal group = Acl.getGroupPrincipal(externalGroupName, identitySourceId);
  readers.add(group);
}
if (permissions.contains(PosixFilePermission.OTHERS_READ)) {
  Principal everyone = Acl.getCustomerPrincipal();
  readers.add(everyone);
}

有了讀者和擁有者清單後,您就可以建立 ACL:

FilePermissionSample.java
// Build the Cloud Search ACL. Note that inheritance of permissions
// from parents is omitted. See `setInheritFrom()` and `setInheritanceType()`
// methods on the builder if required by your implementation.
Acl acl = new Acl.Builder()
    .setReaders(readers)
    .setOwners(owners)
    .build();

建立主體時,基礎 REST API 會使用 identitysources/IDENTITY_SOURCE_ID/users/EXTERNAL_ID 模式做為 ID。回顧先前的資料表,如果您使用 Ann 的 id1_identity (SAMAccountName) 建立 ACL,ID 會解析為:

identitysources/id1_identity/users/example/ann

這個完整 ID 稱為使用者的中繼 ID,因為它在外部 ID 和 Cloud Directory 儲存的 Google ID 之間提供橋樑。

如要進一步瞭解如何為存放區建立 ACL 模型,請參閱「ACL」。

地圖群組

身分來源也會做為存取控管清單 (ACL) 中所用群組的命名空間。您可以使用這個命名空間功能建立及對應群組,這些群組僅用於安全性用途,或屬於存放區的本機群組。

使用 Cloud Identity Groups API 建立群組及管理成員。如要將群組與身分來源建立關聯,請使用身分來源資源名稱做為群組命名空間。

下列程式碼片段說明如何使用 Cloud Identity Groups API 建立群組:

CreateGroupCommand.java
String namespace = "identitysources/" + idSource;
Group group = new Group()
    .setGroupKey(new EntityKey().setNamespace(namespace).setId(groupId))
    .setDescription("Demo group")
    .setDisplayName(groupName)
    .setLabels(Collections.singletonMap("system/groups/external", ""))
    .setParent(namespace);
try {
  CloudIdentity service = Utils.buildCloudIdentityService();
  Operation createOperation = service.groups().create(group).execute();

  if (createOperation.getDone()) {
    // Note: The response contains the data for a Group object, but as
    // individual fields. To convert to a Group instance, either populate
    // the fields individually or serialize & deserialize to/from JSON.
    //
    // Example:
    // String json = service.getJsonFactory().toString(response);
    // Group createdGroup =  service.getObjectParser()
    //     .parseAndClose(new StringReader(json), Group.class);
    System.out.printf("Group: %s\n",
        createOperation.getResponse().toString());
  } else {
    // Handle case where operation not yet complete, poll for
    // completion. API is currently synchronous and all operations return
    // as completed.
    // ...
  }
} catch (Exception e) {
  System.err.printf("Unable to create group: %s", e.getMessage());
  e.printStackTrace(System.err);
}

建立群組 ACL

如要建立群組 ACL,請使用 getGroupPrincipal() 方法,透過提供的外部 ID 建立群組主體。然後使用 Acl.Builder 類別建構 ACL,如下所示:

FilePermissionSample.java
if (permissions.contains(PosixFilePermission.GROUP_READ)) {
  String externalGroupName = attrs.group().getName();
  Principal group = Acl.getGroupPrincipal(externalGroupName, identitySourceId);
  readers.add(group);
}

身分識別連接器

雖然您可以使用外部非 Google ID 建立 ACL 和索引項目,但使用者必須先將外部 ID 解析為 Cloud Directory 中的 Google ID,才能在搜尋結果中看到項目。您可以透過三種方式,確保 Cloud Directory 知道使用者的 Google ID 和外部 ID:

身分識別連接器是程式,用於將企業身分識別 (使用者和群組) 的外部 ID 對應至 Google Cloud Search 使用的內部 Google 身分識別。如需建立識別資訊來源,請務必建立識別資訊連接器。

Google Cloud Directory Sync (GCDS) 就是身分識別連接器的一例。這個身分識別連接器會將 Microsoft Active Directory 中的使用者和群組資訊,對應至 Cloud Directory,以及可能代表使用者在其他系統中身分的使用者屬性。

使用 REST API 同步處理身分

使用 update 方法,透過 REST API 同步處理身分。

重新對應 ID

將項目的身分重新對應至其他身分後,您必須重新為項目建立索引,新身分才會生效。例如:

  • 如果您嘗試從使用者移除對應或將對應重新對應至其他使用者,系統仍會保留原始對應,直到您重新建立索引為止。
  • 如果刪除項目 ACL 中對應的群組,然後建立具有相同 groupKey 的新群組,則必須重新為項目建立索引,新群組才能提供項目存取權。