Visualizações autorizadas

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

Para criar uma visualização autorizada no BigQuery:

Visão geral

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.

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, é preciso ter a permissão bigquery.tables.create do IAM.

Cada um dos seguintes papéis predefinidos do IAM inclui as permissões necessárias para criar uma visualização:

  • roles/bigquery.dataEditor
  • roles/bigquery.dataOwner
  • roles/bigquery.admin

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

Para mais informações sobre os papéis e as 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.get

Cada um dos papéis predefinidos do IAM a seguir inclui as permissões necessárias para atualizar as propriedades de um conjunto de dados:

  • roles/bigquery.dataOwner
  • roles/bigquery.admin

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

Para mais informações sobre os papéis e as 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, faça o seguinte:

Console

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

  2. Expanda a opção Ações e clique em Abrir.

  3. No painel de detalhes, clique em Compartilhar conjunto de dados.

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

  5. 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.
  6. Clique em Adicionar e depois em Concluído.

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
    

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

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

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.

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

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

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