Visualizzazioni autorizzate e viste materializzate

Questo documento descrive come creare viste autorizzate e viste materializzate in BigQuery.

Le visualizzazioni autorizzate e le visualizzazioni materializzate autorizzate ti consentono di condividere i risultati di una query con utenti e gruppi specifici senza concedere loro l'accesso ai dati di origine sottostanti. La visualizzazione o vista materializzata viene concessa l'accesso ai dati, invece dell'utente. Puoi anche utilizzare la query SQL che crea la vista o la vista materializzata per limitare le colonne e i campi su cui gli utenti possono eseguire query.

Quando crei una vista autorizzata o una vista materializzata in un altro set di dati, sia il set di dati di origine sia il set di dati di vista autorizzata devono trovarsi nella stessa posizione regionale.

Per informazioni su come autorizzare tutte le visualizzazioni in un set di dati, anziché singole visualizzazioni, consulta Set di dati autorizzati.

Prima di iniziare

Concedi i ruoli IAM (Identity and Access Management) che concedono agli utenti le autorizzazioni necessarie per eseguire ogni attività in questo documento.

Autorizzazioni obbligatorie

Per creare o aggiornare una visualizzazione autorizzata, devi disporre delle autorizzazioni per il set di dati che contiene la visualizzazione e per il set di dati che fornisce l'accesso alla visualizzazione.

Autorizzazioni per il set di dati che contiene la visualizzazione

Le viste vengono trattate come risorse di tabella in BigQuery, pertanto la creazione di una vista richiede le stesse autorizzazioni necessarie per creare una tabella. Devi inoltre disporre delle autorizzazioni per eseguire query su tutte le tabelle a cui fa riferimento la query SQL della vista.

Per creare una vista, devi disporre dell'bigquery.tables.createautorizzazione IAM. Il ruolo IAM predefinito roles/bigquery.dataEditor include le autorizzazioni necessarie per creare una visualizzazione.

Inoltre, se disponi dell'autorizzazione bigquery.datasets.create, puoi creare visualizzazioni nei set di dati che crei. Per creare una vista per i dati che non possiedi, devi disporre dell'autorizzazione bigquery.tables.getData per la tabella in questione.

Per ulteriori informazioni sui ruoli e sulle autorizzazioni IAM in BigQuery, consulta Ruoli e autorizzazioni predefiniti.

Autorizzazioni sul set di dati che consentono l'accesso alla visualizzazione

Per aggiornare le proprietà dei set di dati, devi disporre delle seguenti autorizzazioni IAM:

  • bigquery.datasets.update
  • bigquery.datasets.setIamPolicy (obbligatorio solo per aggiornare i controlli di accesso ai set di dati nella console Google Cloud)

Il ruolo IAM predefinito roles/bigquery.dataOwner include le autorizzazioni necessarie per aggiornare le proprietà del set di dati.

Inoltre, se disponi dell'autorizzazione bigquery.datasets.create, puoi aggiornare le proprietà dei set di dati che crei.

Per ulteriori informazioni sui ruoli e sulle autorizzazioni IAM in BigQuery, consulta Ruoli e autorizzazioni predefiniti.

Autorizzare una visualizzazione

Per concedere a una visualizzazione l'accesso a un set di dati:

Console

  1. Vai alla pagina BigQuery nella console Google Cloud.

    Vai a BigQuery

  2. Nel riquadro Explorer, espandi il progetto e seleziona un set di dati.

  3. Fai clic su Visualizza azioni e poi su Apri.

  4. Nel riquadro Informazioni sul set di dati, fai clic su Condivisione e poi seleziona Autorizza visualizzazioni.

  5. In Autorizza visualizzazione, digita il nome della visualizzazione da autorizzare.

  6. Fai clic su Aggiungi autorizzazione.

  7. Fai clic su Chiudi.

bq

  1. Scrivi le informazioni esistenti del set di dati (inclusi i controlli di accesso) in un file JSON utilizzando il comando bq show. Se il set di dati si trova in un progetto diverso da quello predefinito, aggiungi l'ID progetto al nome del set di dati nel seguente formato: project_id:dataset.

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

    Dove:

    • project_id è l'ID progetto.
    • dataset è il nome del set di dati.
    • path_to_file è il percorso del file JSON sulla tua macchina locale.

    Esempi:

    Inserisci il seguente comando per scrivere i controlli di accesso per mydataset in un file JSON. mydataset si trova nel tuo progetto predefinito.

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

    Inserisci il seguente comando per scrivere i controlli di accesso per mydataset in un file JSON. mydataset si trova in myotherproject.

    bq show --format=prettyjson \
    myotherproject:mydataset > /tmp/mydataset.json
    
  2. Aggiungi la visualizzazione autorizzata alla sezione "access" del file JSON.

    Ad esempio, la sezione di accesso del file JSON di un set di dati sarà simile al seguente:

    {
     "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. Al termine delle modifiche, utilizza il comando bq update e includi il file JSON utilizzando il flag --source. Se il set di dati si trova in un progetto diverso da quello predefinito, aggiungi l'ID progetto al nome del set di dati nel seguente formato: project_id:dataset.

    bq update \
    --source path_to_file \
    project_id:dataset

    Dove:

    • path_to_file è il percorso del file JSON sulla tua macchina locale.
    • project_id è l'ID progetto.
    • dataset è il nome del set di dati.

    Esempi:

    Inserisci il seguente comando per aggiornare i controlli di accesso per mydataset. mydataset si trova nel tuo progetto predefinito.

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

    Inserisci il seguente comando per aggiornare i controlli di accesso per mydataset. mydataset si trova in myotherproject.

     bq update --source /tmp/mydataset.json myotherproject:mydataset
    
  4. Per verificare le modifiche controllo dell'accesso#39;accesso, inserisci di nuovo il comando show senza scrivere le informazioni in un file.

    bq show --format=prettyjson [DATASET]
    

    o

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

API

Chiama datasets.patch e utilizza la proprietà access per aggiornare i controlli di accesso. Per maggiori informazioni, consulta la sezione Set di dati.

Poiché il metodo datasets.update sostituisce l'intera risorsa del set di dati, datasets.patch è il metodo preferito per aggiornare i controlli di accesso.

Vai

Prima di provare questo esempio, segui le istruzioni di configurazione Go riportate nella guida rapida all'utilizzo di BigQuery con le librerie client. Per ulteriori informazioni, consulta la documentazione di riferimento dell'API BigQuery Go.

Per autenticarti in BigQuery, configura le Credenziali predefinite dell'applicazione. Per saperne di più, consulta Configurare l'autenticazione per le librerie client.

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

Prima di provare questo esempio, segui le istruzioni di configurazione Java riportate nella guida rapida all'utilizzo di BigQuery con le librerie client. Per ulteriori informazioni, consulta la documentazione di riferimento dell'API BigQuery Java.

Per autenticarti in BigQuery, configura le Credenziali predefinite dell'applicazione. Per saperne di più, consulta Configurare l'autenticazione per le librerie client.

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

Prima di provare questo esempio, segui le istruzioni di configurazione Python riportate nella guida rapida all'utilizzo di BigQuery con le librerie client. Per ulteriori informazioni, consulta la documentazione di riferimento dell'API BigQuery Python.

Per autenticarti in BigQuery, configura le Credenziali predefinite dell'applicazione. Per saperne di più, consulta Configurare l'autenticazione per le librerie client.

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

Rimuovere l'autorizzazione per una visualizzazione

Per rimuovere l'autorizzazione per una visualizzazione:

Console

  1. Vai alla pagina BigQuery nella console Google Cloud.

    Vai a BigQuery

  2. Nel riquadro Explorer, espandi il progetto e seleziona un set di dati.

  3. Fai clic su Condivisione > Autorizza visualizzazioni.

  4. Fai clic su Rimuovi autorizzazione.

  5. Fai clic su Chiudi.

Quote e limiti

  • Le visualizzazioni autorizzate sono soggette ai limiti del set di dati. Per ulteriori informazioni, consulta Limiti dei set di dati.
  • Se rimuovi una visualizzazione autorizzata, possono essere necessarie fino a 24 ore prima che tutti i riferimenti alla visualizzazione vengano rimossi dal sistema. Per evitare errori, attendi 24 ore prima di riutilizzare il nome di una visualizzazione rimossa o crea un nome univoco per la visualizzazione.

Applicare l'accesso a livello di riga con una vista

Le visualizzazioni possono essere utilizzate per limitare l'accesso a colonne (campi) specifiche. Se vuoi limitare l'accesso alle singole righe della tabella, non è necessario creare visualizzazioni separate per ogni utente o gruppo. In alternativa, puoi utilizzare la funzione SESSION_USER() per restituire l'indirizzo email dell'utente corrente.

Per visualizzare righe diverse a utenti diversi, aggiungi un altro campo alla tabella contenente l'utente che ha il permesso di visualizzare la riga. Quindi, crea una visualizzazione che utilizzi la funzione SESSION_USER(). Nell'esempio seguente, i nomi utente sono memorizzati nel campo allowed_viewer:

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

Il limite di questo approccio è che puoi concedere l'accesso a un solo utente alla volta. Puoi aggirare questa limitazione creando un allowed_viewer campo ripetuto. Questo approccio ti consente di fornire un elenco di utenti per ogni riga. Tuttavia, anche se utilizzi un campo ripetuto, la memorizzazione dei nomi utente nella tabella richiede comunque di monitorare manualmente i singoli utenti che hanno accesso a ogni riga.

Compila invece il campo allowed_viewer con i nomi dei gruppi e crea una tabella distinta che mappa i gruppi agli utenti. La tabella che mappa i gruppi agli utenti avrebbe uno schema che memorizza i nomi dei gruppi e i nomi utente. Ad esempio: {group:string, user_name:string}. Questo approccio ti consente di gestire le informazioni degli utenti e dei gruppi separatamente dalla tabella che contiene i dati.

Se la tabella di mappatura è denominata private.access_control, la query SQL utilizzata per creare la vista autorizzata sarà:

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

Passaggi successivi