Como criar visualizações autorizadas

Neste documento, você verá como criar visualizações autorizadas no BigQuery.

Para criar uma visualização autorizada no BigQuery:

  • usando o Console do Cloud;
  • usando o comando bq da ferramenta de linha de comando bq mk;
  • chamando o método de API tables.insert;
  • enviando uma instrução CREATE VIEW de linguagem de definição de dados (DDL);
  • usando bibliotecas de cliente.

Visão geral

A concessão de acesso de visualização a um conjunto de dados também é conhecida como criação de visualização autorizada no BigQuery. Uma visualização autorizada permite compartilhar resultados de consultas com determinados usuários e grupos sem que eles possam acessar os dados de origem subjacentes. Também é possível usar a consulta SQL da visualização para restringir as colunas (campos) que os usuários podem consultar.

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

Para ver um tutorial, consulte Como criar uma visualização autorizada.

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.

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. No mínimo, para criar uma visualização, você precisa ter as permissões bigquery.tables.create. Os seguintes papéis predefinidos do IAM incluem as permissões bigquery.tables.create:

  • bigquery.dataEditor
  • bigquery.dataOwner
  • bigquery.admin

Além disso, quando um usuário tem permissões bigquery.datasets.create e cria um conjunto de dados, ele recebe o acesso bigquery.dataOwner ao conjunto. O acesso bigquery.dataOwner permite que o usuário crie visualizações no conjunto de dados.

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

Conjunto de dados que dá acesso à visualização

Para atualizar propriedades de conjuntos de dados, é necessário ter pelo menos as permissões bigquery.datasets.update e bigquery.datasets.get. Os seguintes papéis predefinidos do IAM incluem as permissões bigquery.datasets.update e bigquery.datasets.get:

  • bigquery.dataOwner
  • bigquery.admin

Além disso, quando um usuário tem permissões bigquery.datasets.create e cria um conjunto de dados, ele recebe o acesso bigquery.dataOwner ao conjunto. Com o acesso de bigquery.dataOwner, os usuários conseguem atualizar as propriedades dos conjuntos de dados criados por eles.

Para mais informações sobre papéis e permissões do IAM no BigQuery, consulte Controle de acesso.

Como conceder acesso de visualização a conjuntos de dados

Para conceder acesso de visualização a um conjunto de dados, faça o seguinte:

Console

  1. Na seção Recursos do painel de navegação, expanda o projeto e selecione um conjunto de dados.

  2. Clique em Compartilhar conjunto de dados no lado direito da janela.

  3. No painel Permissões do conjunto de dados, selecione a guia Visualizações autorizadas.

  4. Na seção Compartilhar visualização autorizada:

    • Verifique o nome do projeto em Selecionar projeto. Se a visualização estiver em um projeto diferente, selecione-o.
    • Em Selecionar conjunto de dados, escolha o conjunto de dados que contém a visualização.
    • Em Selecionar visualização, escolha a visualização a ser autorizada.
  5. Clique em Adicionar e depois em Concluído.

bq

  1. Use o comando 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
    

    Onde:

    • 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 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
    

    Onde:

    • 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 essa amostra, siga as instruções de configuração para 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 (em inglês).

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 essa amostra, siga as instruções de configuração para 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 para Java.

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 essa amostra, siga as instruções de configuração para 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.

Ver no GitHub (em inglês) Feedback
# from google.cloud import bigquery
# client = bigquery.Client()

# Assign access controls to the dataset containing the view
# shared_dataset_id = 'my_shared_dataset'
# analyst_group_email = 'data_analysts@example.com'
project = client.project
shared_dataset_ref = bigquery.DatasetReference(project, shared_dataset_id)
shared_dataset = client.get_dataset(shared_dataset_ref)  # API request
access_entries = shared_dataset.access_entries
access_entries.append(
    bigquery.AccessEntry("READER", "groupByEmail", analyst_group_email)
)
shared_dataset.access_entries = access_entries
shared_dataset = client.update_dataset(
    shared_dataset, ["access_entries"]
)  # API request

# Authorize the view to access the source dataset
# project = 'my-project'
# source_dataset_id = 'my_source_dataset'
project = client.project
source_dataset_ref = bigquery.DatasetReference(project, source_dataset_id)
source_dataset = client.get_dataset(source_dataset_ref)  # API request
view_reference = {
    "projectId": project,
    "datasetId": shared_dataset_id,
    "tableId": "my_shared_view",
}
access_entries = source_dataset.access_entries
access_entries.append(bigquery.AccessEntry(None, "view", view_reference))
source_dataset.access_entries = access_entries
source_dataset = client.update_dataset(
    source_dataset, ["access_entries"]
)  # API request

Como 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, mas, mesmo que use um campo repetido, o armazenamento de nomes de usuários 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 grupos e usuários 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

Próximas etapas