Visualizações autorizadas e materializadas

Neste documento, descrevemos como criar visualizações autorizadas e materializadas no BigQuery.

As visualizações autorizadas e materializadas permitem compartilhar resultados de consultas com determinados usuários e grupos sem conceder acesso aos dados de origem subjacentes. A visualização ou a visualização materializada recebe acesso aos dados em vez do usuário. Também é possível usar a consulta SQL que cria a visualização materializada ou a visualização para restringir as colunas e os campos que os usuários podem consultar.

Ao criar uma visualização autorizada ou materializada em outro conjunto de dados, o conjunto de dados de origem e o conjunto de dados de visualização autorizada precisam estar no mesmo local regional.

Para informações sobre como autorizar todas as visualizações em um conjunto de dados, em vez de autorizar visualizações individuais, consulte Conjuntos de dados autorizados.

Antes de começar

Atribua papéis do Identity and Access Management (IAM) que concedam aos usuários as permissões necessárias para realizar cada tarefa deste documento.

Permissões necessárias

Para criar ou atualizar uma visualização autorizada, é necessário ter permissões no conjunto de dados que contém a visualização e no que fornece acesso a ela.

Permissões no conjunto de dados que contém a visualização

As visualizações são tratadas como recursos de tabela no BigQuery. Portanto, para criá-las, são necessárias as mesmas permissões usadas para criar uma tabela. Você também precisa ter permissões para consultar as tabelas referenciadas pela consulta SQL da visualização.

Para criar uma visualização, você precisa ter a permissão bigquery.tables.create do IAM. O papel predefinido roles/bigquery.dataEditor do IAM inclui as permissões necessárias para criar uma visualização.

Além disso, se você tiver a permissão bigquery.datasets.create, será possível criar visualizações nos conjuntos de dados que forem criados. Para criar uma visualização para dados que não pertencem a você, é necessário ter a permissão bigquery.tables.getData para essa tabela.

Para mais informações sobre papéis e permissões do IAM no BigQuery, consulte Papéis e permissões predefinidos.

Permissões no conjunto de dados que dão acesso à visualização

Para atualizar as propriedades do conjunto de dados, você precisa das seguintes permissões do IAM:

  • bigquery.datasets.update
  • bigquery.datasets.setIamPolicy (obrigatório apenas ao atualizar os controles de acesso do conjunto de dados no console do Google Cloud)

O papel predefinido do IAM roles/bigquery.dataOwner inclui as permissões necessárias para atualizar as propriedades do conjunto de dados.

Além disso, se você tiver a permissão bigquery.datasets.create, será possível atualizar as propriedades dos conjuntos de dados que criar.

Para mais informações sobre papéis e permissões do IAM no BigQuery, consulte Papéis e permissões predefinidos.

Autorizar uma visualização

Para conceder acesso de visualização a um conjunto de dados, siga estas etapas:

Console

  1. Acesse a página do BigQuery no console do Google Cloud.

    Acessar o BigQuery

  2. No painel Explorer, expanda o projeto e selecione um conjunto de dados.

  3. Clique em Consultar ações e em Abrir.

  4. No painel Informações do conjunto de dados, clique em Compartilhamento e selecione Autorizar visualizações.

  5. Em Autorizar visualização, digite o nome da visualização a ser autorizada.

  6. Clique em Adicionar autorização.

  7. Clique em Fechar.

bq

  1. Use o comando bq show para gravar as informações atuais do conjunto de dados, incluindo controles de acesso, em um arquivo JSON. Se o conjunto de dados estiver em um projeto diferente do padrão, adicione o ID do projeto ao nome do conjunto de dados no seguinte formato: project_id:dataset.

    bq show \
    --format=prettyjson \
    project_id:dataset > path_to_file

    Em que:

    • project_id é o ID do projeto;
    • dataset é o nome do conjunto de dados;
    • path_to_file é o caminho do arquivo JSON na sua máquina local.

    Exemplos:

    Digite o comando a seguir para gravar os controles de acesso para mydataset em um arquivo JSON. mydataset está no projeto padrão.

    bq show --format=prettyjson mydataset > /tmp/mydataset.json
    

    Digite o comando a seguir para gravar os controles de acesso para mydataset em um arquivo JSON. mydataset está em myotherproject.

    bq show --format=prettyjson \
    myotherproject:mydataset > /tmp/mydataset.json
    
  2. Adicione a visualização autorizada à seção "access" do arquivo JSON.

    Por exemplo, a seção "access" do arquivo JSON de um conjunto de dados tem esta aparência:

    {
     "access": [
      {
       "role": "READER",
       "specialGroup": "projectReaders"
      },
      {
       "role": "WRITER",
       "specialGroup": "projectWriters"
      },
      {
       "role": "OWNER",
       "specialGroup": "projectOwners"
      }
      {
       "role": "READER",
       "specialGroup": "allAuthenticatedUsers"
      }
      {
       "role": "READER",
       "domain": "[DOMAIN_NAME]"
      }
      {
       "role": "WRITER",
       "userByEmail": "[USER_EMAIL]"
      }
      {
       "role": "READER",
       "groupByEmail": "[GROUP_EMAIL]"
      },
      {
       "view":{
       "datasetId": "[DATASET_NAME]",
       "projectId": "[PROJECT_NAME]",
       "tableId": "[VIEW_NAME]"
       }
      }
     ],
    }

  3. Quando as edições estiverem concluídas, use o comando bq update e inclua o arquivo JSON usando a sinalização --source. Se o conjunto de dados estiver em um projeto diferente do padrão, adicione o ID do projeto ao nome do conjunto de dados no seguinte formato: project_id:dataset.

    bq update \
    --source path_to_file \
    project_id:dataset

    Em que:

    • path_to_file é o caminho do arquivo JSON na sua máquina local;
    • project_id é o ID do projeto;
    • dataset é o nome do conjunto de dados;

    Exemplos:

    Digite o comando a seguir para atualizar os controles de acesso para mydataset. mydataset está no projeto padrão.

     bq update --source /tmp/mydataset.json mydataset
    

    Digite o comando a seguir para atualizar os controles de acesso para mydataset. mydataset está em myotherproject.

     bq update --source /tmp/mydataset.json myotherproject:mydataset
    
  4. Para verificar as alterações no controle de acesso, insira o comando show novamente sem gravar as informações em um arquivo.

    bq show --format=prettyjson [DATASET]
    

    ou

    bq show --format=prettyjson [PROJECT_ID]:[DATASET]
    

API

Chame datasets.patch e use a propriedade access para atualizar seus controles de acesso. Para mais informações, consulte Conjuntos de dados.

Como datasets.update substitui todo o recurso do conjunto de dados, é melhor usar o método datasets.patch para atualizar os controles de acesso.

Go

Antes de testar esta amostra, siga as instruções de configuração do Go no Guia de início rápido do BigQuery: como usar bibliotecas de cliente. Para mais informações, consulte a documentação de referência da API BigQuery em Go.

Para autenticar no BigQuery, configure o Application Default Credentials. Para mais informações, acesse Configurar a autenticação para bibliotecas de cliente.

import (
	"context"
	"fmt"

	"cloud.google.com/go/bigquery"
)

// updateViewDelegated demonstrates the setup of an authorized view, which allows access to a view's results
// without the caller having direct access to the underlying source data.
func updateViewDelegated(projectID, srcDatasetID, viewDatasetID, viewID string) error {
	// projectID := "my-project-id"
	// srcDatasetID := "sourcedata"
	// viewDatasetID := "views"
	// viewID := "myview"
	ctx := context.Background()
	client, err := bigquery.NewClient(ctx, projectID)
	if err != nil {
		return fmt.Errorf("bigquery.NewClient: %v", err)
	}
	defer client.Close()

	srcDataset := client.Dataset(srcDatasetID)
	viewDataset := client.Dataset(viewDatasetID)
	view := viewDataset.Table(viewID)

	// First, we'll add a group to the ACL for the dataset containing the view.  This will allow users within
	// that group to query the view, but they must have direct access to any tables referenced by the view.
	vMeta, err := viewDataset.Metadata(ctx)
	if err != nil {
		return err
	}
	vUpdateMeta := bigquery.DatasetMetadataToUpdate{
		Access: append(vMeta.Access, &bigquery.AccessEntry{
			Role:       bigquery.ReaderRole,
			EntityType: bigquery.GroupEmailEntity,
			Entity:     "example-analyst-group@google.com",
		}),
	}
	if _, err := viewDataset.Update(ctx, vUpdateMeta, vMeta.ETag); err != nil {
		return err
	}

	// Now, we'll authorize a specific view against a source dataset, delegating access enforcement.
	// Once this has been completed, members of the group previously added to the view dataset's ACL
	// no longer require access to the source dataset to successfully query the view.
	srcMeta, err := srcDataset.Metadata(ctx)
	if err != nil {
		return err
	}
	srcUpdateMeta := bigquery.DatasetMetadataToUpdate{
		Access: append(srcMeta.Access, &bigquery.AccessEntry{
			EntityType: bigquery.ViewEntity,
			View:       view,
		}),
	}
	if _, err := srcDataset.Update(ctx, srcUpdateMeta, srcMeta.ETag); err != nil {
		return err
	}
	return nil
}

Java

Antes de testar esta amostra, siga as instruções de configuração do Java no Guia de início rápido do BigQuery: como usar bibliotecas de cliente. Para mais informações, consulte a documentação de referência da API BigQuery em Java.

Para autenticar no BigQuery, configure o Application Default Credentials. Para mais informações, acesse Configurar a autenticação para bibliotecas de cliente.

import com.google.cloud.bigquery.Acl;
import com.google.cloud.bigquery.BigQuery;
import com.google.cloud.bigquery.BigQueryException;
import com.google.cloud.bigquery.BigQueryOptions;
import com.google.cloud.bigquery.Dataset;
import com.google.cloud.bigquery.DatasetId;
import com.google.cloud.bigquery.Table;
import java.util.ArrayList;
import java.util.List;

// Sample to grant view access on dataset
public class GrantViewAccess {

  public static void runGrantViewAccess() {
    // TODO(developer): Replace these variables before running the sample.
    String srcDatasetId = "MY_DATASET_ID";
    String viewDatasetId = "MY_VIEW_DATASET_ID";
    String viewId = "MY_VIEW_ID";
    grantViewAccess(srcDatasetId, viewDatasetId, viewId);
  }

  public static void grantViewAccess(String srcDatasetId, String viewDatasetId, String viewId) {
    try {
      // Initialize client that will be used to send requests. This client only needs to be created
      // once, and can be reused for multiple requests.
      BigQuery bigquery = BigQueryOptions.getDefaultInstance().getService();

      Dataset srcDataset = bigquery.getDataset(DatasetId.of(srcDatasetId));
      Dataset viewDataset = bigquery.getDataset(DatasetId.of(viewDatasetId));
      Table view = viewDataset.get(viewId);

      // First, we'll add a group to the ACL for the dataset containing the view. This will allow
      // users within that group to query the view, but they must have direct access to any tables
      // referenced by the view.
      List<Acl> viewAcl = new ArrayList<>();
      viewAcl.addAll(viewDataset.getAcl());
      viewAcl.add(Acl.of(new Acl.Group("example-analyst-group@google.com"), Acl.Role.READER));
      viewDataset.toBuilder().setAcl(viewAcl).build().update();

      // Now, we'll authorize a specific view against a source dataset, delegating access
      // enforcement. Once this has been completed, members of the group previously added to the
      // view dataset's ACL no longer require access to the source dataset to successfully query the
      // view
      List<Acl> srcAcl = new ArrayList<>();
      srcAcl.addAll(srcDataset.getAcl());
      srcAcl.add(Acl.of(new Acl.View(view.getTableId())));
      srcDataset.toBuilder().setAcl(srcAcl).build().update();
      System.out.println("Grant view access successfully");
    } catch (BigQueryException e) {
      System.out.println("Grant view access was not success. \n" + e.toString());
    }
  }
}

Python

Antes de testar esta amostra, siga as instruções de configuração do Python no Guia de início rápido do BigQuery: como usar bibliotecas de cliente. Para mais informações, consulte a documentação de referência da API BigQuery em Python.

Para autenticar no BigQuery, configure o Application Default Credentials. Para mais informações, acesse Configurar a autenticação para bibliotecas de cliente.

from google.cloud import bigquery

client = bigquery.Client()

# To use a view, the analyst requires ACLs to both the view and the source
# table. Create an authorized view to allow an analyst to use a view
# without direct access permissions to the source table.
view_dataset_id = "my-project.my_view_dataset"
# Make an API request to get the view dataset ACLs.
view_dataset = client.get_dataset(view_dataset_id)

analyst_group_email = "data_analysts@example.com"
access_entries = view_dataset.access_entries
access_entries.append(
    bigquery.AccessEntry("READER", "groupByEmail", analyst_group_email)
)
view_dataset.access_entries = access_entries

# Make an API request to update the ACLs property of the view dataset.
view_dataset = client.update_dataset(view_dataset, ["access_entries"])
print(f"Access to view: {view_dataset.access_entries}")

# Group members of "data_analysts@example.com" now have access to the view,
# but they require access to the source table to use it. To remove this
# restriction, authorize the view to access the source dataset.
source_dataset_id = "my-project.my_source_dataset"
# Make an API request to set the source dataset ACLs.
source_dataset = client.get_dataset(source_dataset_id)

view_reference = {
    "projectId": "my-project",
    "datasetId": "my_view_dataset",
    "tableId": "my_authorized_view",
}
access_entries = source_dataset.access_entries
access_entries.append(bigquery.AccessEntry(None, "view", view_reference))
source_dataset.access_entries = access_entries

# Make an API request to update the ACLs property of the source dataset.
source_dataset = client.update_dataset(source_dataset, ["access_entries"])
print(f"Access to source: {source_dataset.access_entries}")

Remover a autorização de uma visualização

Para remover a autorização de uma visualização:

Console

  1. Acesse a página do BigQuery no console do Google Cloud.

    Acessar o BigQuery

  2. No painel Explorer, expanda o projeto e selecione um conjunto de dados.

  3. Clique em Compartilhamento > Autorizar visualizações.

  4. Clique em Remover autorização.

  5. Clique em Fechar.

Cotas e limites

  • As visualizações autorizadas estão sujeitas aos limites de conjuntos de dados. Consulte mais informações em Limites do conjunto de dados.
  • Quando você remove uma visualização autorizada, pode levar até 24 horas para que todas as referências a ela sejam removidas do sistema. Para evitar erros, aguarde 24 horas antes de reutilizar o nome de uma visualização removida ou crie um nome exclusivo para ela.

Aplicar acesso no nível da linha com uma visualização

As visualizações podem ser usadas para restringir o acesso a colunas (campos) específicas. Se quiser restringir o acesso a linhas individuais na tabela, não será preciso criar visualizações separadas para cada usuário ou grupo. Em vez disso, é possível usar a função SESSION_USER() para retornar o endereço de e-mail do usuário atual.

Para exibir linhas diferentes para diferentes usuários, adicione outro campo à sua tabela, contendo o usuário que está autorizado a ver a linha. Em seguida, crie uma visualização que use a função SESSION_USER(). No exemplo a seguir, os nomes de usuários são armazenados no campo allowed_viewer:

SELECT
  COLUMN_1,
  COLUMN_2
FROM
  `dataset.view`
WHERE
  allowed_viewer = SESSION_USER()

A limitação dessa abordagem é que é possível conceder acesso a apenas um usuário por vez. Contorne essa limitação tornando allowed_viewer um campo repetido. Essa abordagem permite que você forneça uma lista de usuários para cada linha. No entanto, mesmo se você usar um campo repetido, o armazenamento de nomes de usuário na tabela ainda exigirá o rastreamento manual dos usuários individuais que têm acesso a cada linha.

Em vez disso, preencha o campo allowed_viewer com nomes de grupos e crie uma tabela separada que correlacione grupos a usuários. Essa tabela teria um esquema que armazena nomes de grupos e nomes de usuários. Por exemplo, {group:string, user_name:string}. Essa abordagem permite administrar as informações de usuários e grupos separadamente da tabela que contém os dados.

Se a tabela de mapeamento for denominada private.access_control, a consulta SQL usada para criar a visualização autorizada seria:

SELECT
  c.customer,
  c.id
FROM
  `private.customers` c
INNER JOIN (
  SELECT
    group
  FROM
    `private.access_control`
  WHERE
    SESSION_USER() = user_name) g
ON
  c.allowed_group = g.group

A seguir