Sincronizar diferentes sistemas de identidade

O controle de acesso no Google Cloud Search é baseado na conta do Google do usuário. Ao indexar o conteúdo, é preciso que todas as ACLs dos itens sejam resolvidas para códigos de usuário ou de grupo válidos do Google (endereços de e-mail).

Em muitos casos, um repositório não tem conhecimento direto das contas do Google. Em vez disso, os usuários podem ser representados por contas locais ou usar o login federado com um provedor de identidade e um código, que não seja o endereço de e-mail do usuário, para identificar cada conta. Esse código é chamado de código externo.

Criadas com o Admin Console, as origens de identidade ajudam a preencher essa lacuna entre os sistemas de identidade:

Use origens de identidade quando:

  • O repositório não tiver conhecimento do endereço de e-mail principal do usuário no Google Workspace ou no Google Cloud Directory.
  • O repositório define grupos para controle de acesso que não correspondem a grupos baseados em e-mail no Google Workspace.

A origens de identidade melhoram a eficiência da indexação ao desvinculá-la do mapeamento de identidade. Essa desvinculação permite adiar a pesquisa do usuário ao criar ACLs e indexar itens.

Exemplo de implantação

A Figura 1 mostra um exemplo de implantação em que os repositórios no local e na nuvem são utilizados por uma empresa. Cada repositório usa um tipo diferente de código externo para se referir a usuários.

Exemplo de implantação
Figura 1. Exemplo de implantação empresarial com diferentes tipos de identidade.

O repositório 1 identifica o usuário que usa o endereço de e-mail declarado com SAML. Como o repositório 1 tem conhecimento do endereço de e-mail principal do usuário no Google Workspace ou no Cloud Directory, uma origem de identidade não é necessária.

O repositório 2 se integra diretamente a um diretório local e identifica o usuário pelo atributo sAMAccountName. Como o repositório 2 usa um atributo sAMAccountName como ID externo, uma origem de identidade é necessária.

Criar uma origem de identidade

Caso você precise de uma origem de identidade, consulte Mapear identidades de usuário no Cloud Search.

É preciso criar uma origem de identidade antes de criar um conector de conteúdo porque o código dela é necessário para criar ACLs e indexar dados. Conforme mencionado anteriormente, a criação de uma origem de identidade também cria uma propriedade de usuário personalizada no Cloud Directory. Use essa propriedade para registrar o código externo para cada usuário no seu repositório. A propriedade é nomeada usando a convenção IDENTITY_SOURCE_ID_identity.

A tabela a seguir mostra duas origens de identidade: uma para manter nomes de contas SAM (sAMAccountName) como códigos externos e outra para manter códigos de usuário (uid) como códigos externos.

Origem de identidade Propriedade do usuário Código externo
id1 id1_identity sAMAccountName
id2 id2_identity uid

Crie uma origem de identidade para cada código externo possível utilizado para se referir a um usuário na sua empresa.

A tabela a seguir mostra como um usuário com uma conta do Google e dois códigos externos (id1_identity e id2_identity) com os respectivos valores aparecem no Cloud Directory:

Usuário E-mail id1_identity id2_identity
Ann ann@example.com example\ann 1001

É possível fazer referência ao mesmo usuário usando os três códigos diferentes (e-mail do Google, sAMAccountName e uid) ao formar ACLs para indexação.

Escrever ACLs de usuário

Use o método getUserPrincpal() ou o método getGroupPrincipal() para criar principais usando um ID externo fornecido.

O exemplo a seguir demonstra como recuperar permissões de arquivo. Essas permissões incluem o nome de cada usuário que tem acesso ao arquivo.

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();
  // ...
}

O snippet de código a seguir mostra como criar principais que são proprietários usando o ID externo (externalUserName) armazenado nos atributos.

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)
);

Finalmente, o snippet de código a seguir mostra como criar principais que são leitores do arquivo.

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);
}

Depois que você tiver uma lista de leitores e proprietários, crie a 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();

A API REST subjacente usa o padrão identitysources/IDENTITY_SOURCE_ID/users/EXTERNAL_ID para o ID ao criar principais. Fazendo referência às tabelas anteriores, se você criar uma ACL com o id1_identity de Ann (SAMAccountName), o ID será resolvido para:

identitysources/id1_identity/users/example/ann

Esse código inteiro é chamado de código intermediário do usuário porque faz uma ponte entre o código externo e os códigos do Google armazenados com o Cloud Directory.

Para mais informações sobre como modelar as ACLs usadas em um repositório, consulte ACLs.

Mapear grupos

As origens de identidade também servem como namespace para grupos usados em ACLs. É possível usar esse recurso de namespace para criar e mapear grupos que são usados apenas para fins de segurança ou que estão localizados em um repositório.

Use a API Cloud Identity Groups para criar um grupo e gerenciar as associações. Para associar o grupo a uma origem de identidade, use o nome do recurso da origem de identidade como namespace do grupo.

O snippet de código a seguir mostra como criar um grupo usando a API Cloud Identity Groups:

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);
}

Criar uma ACL de grupo

Para criar uma ACL de grupo, use o método getGroupPrincipal() para criar um principal de grupo usando um código externo fornecido. Em seguida, crie a ACL usando a classe Acl.Builder desta maneira:

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

Conectores de identidade

Embora seja possível usar códigos externos que não sejam do Google para criar ACLs e indexar itens, os usuários não poderão ver itens em uma pesquisa enquanto os códigos externos deles não forem resolvidos para um código do Google no Cloud Directory. Existem três maneiras de garantir que o Cloud Directory tenha conhecimento tanto do código do Google como dos códigos externos de um usuário:

Conectores de identidade são programas usados para mapear códigos externos de identidades empresariais (usuários e grupos) para identidades internas do Google usadas pelo Google Cloud Search. Se você tiver que criar uma origem de identidade, precisará criar também um conector de identidade.

O Google Cloud Directory Sync (GCDS) é um exemplo de conector de identidade. Ele mapeia informações de usuários e grupos do Active Directory da Microsoft para o Cloud Directory, além dos atributos do usuário que podem representar a identidade dele em outros sistemas.

Sincronizar identidades usando a API REST

Use o método update para sincronizar identidades usando a API REST.

Remapear identidades

Depois de remapear a identidade de um item para outra, você precisa reindexar os itens para que a nova identidade seja efetivada. Por exemplo,

  • se você tentar remover um mapeamento de um usuário ou remapeá-lo para outro, o mapeamento original vai ser preservado até que seja reindexado.
  • Se você excluir um grupo mapeado presente em uma ACL de item e criar um novo grupo com o mesmo groupKey, o novo grupo não fornecerá acesso ao item até que ele seja reindexado.