Crea vistas autorizadas

En este documento, se describe cómo crear vistas autorizadas en BigQuery.

Tienes las siguientes opciones para crear una vista autorizada en BigQuery:

  • Usar Cloud Console o la IU web clásica de BigQuery
  • Mediante el comando bq mk de la herramienta de línea de comandos de bq
  • Realiza una llamada al método de API tables.insert
  • Enviar una instrucción CREATE VIEW de lenguaje de definición de datos (DDL)
  • Usar bibliotecas cliente

Descripción general

Dar acceso para ver un conjunto de datos también se conoce como crear una vista autorizada en BigQuery. Una vista autorizada te permite compartir resultados de consultas con usuarios y grupos específicos sin darles acceso a las fuentes de datos subyacentes. También puedes usar la consulta de SQL de la vista para restringir las columnas (campos) que los usuarios pueden consultar.

Cuando realizas una vista autorizada en otro conjunto de datos, el conjunto de datos de origen y el del conjunto de vistas autorizado deben estar en la misma ubicación regional.

Para obtener un instructivo sobre cómo crear una vista autorizada, consulta Crea una vista autorizada en.

Permisos necesarios

Para crear o actualizar una vista autorizada, necesitas permisos en el conjunto de datos que contiene la vista y en el conjunto de datos que proporciona acceso a la vista.

Conjunto de datos que contiene la vista

Las vistas se tratan como recursos de tabla en BigQuery, por lo que la creación de una vista requiere los mismos permisos que la creación de una tabla. Como mínimo, para crear una vista, debes tener permisos bigquery.tables.create. En las siguientes funciones predefinidas de IAM, se incluyen los permisos bigquery.tables.create:

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

Además, si un usuario tiene permisos bigquery.datasets.create, se le otorga el acceso bigquery.dataOwner cuando crea un conjunto de datos. El acceso bigquery.dataOwner le da al usuario la capacidad de crear vistas en el conjunto de datos.

Para obtener más información sobre las funciones y los permisos de IAM en BigQuery, consulta Funciones y permisos predefinidos.

Conjunto de datos que otorga acceso a la vista

Como mínimo, para actualizar las propiedades del conjunto de datos, debes tener los permisos bigquery.datasets.update y bigquery.datasets.get. En las siguientes funciones predefinidas de IAM, se incluyen los permisos bigquery.datasets.update y bigquery.datasets.get:

  • bigquery.dataOwner
  • bigquery.admin

Además, si un usuario tiene permisos bigquery.datasets.create, se le otorga el acceso bigquery.dataOwner cuando crea un conjunto de datos. El acceso bigquery.dataOwner otorga a los usuarios la capacidad de actualizar las propiedades de los conjuntos de datos que crean.

Para obtener más información sobre las funciones y los permisos de IAM en BigQuery, consulta Control de acceso.

Otorga acceso de visualización a los conjuntos de datos

Para otorgar acceso de visualización a un conjunto de datos, sigue estos pasos:

Console

  1. En el panel de navegación, en la sección Recursos, expande tu proyecto y selecciona un conjunto de datos.

  2. Haz clic en Compartir conjunto de datos, en el lado derecho de la ventana.

  3. En el panel Permisos del conjunto de datos, selecciona la pestaña Vistas autorizadas.

  4. En la sección Compartir vista autorizada, haz lo siguiente:

    • En Seleccionar proyecto, verifica el nombre. Si la vista está en un proyecto diferente, asegúrate de seleccionarlo.
    • En Seleccionar conjunto de datos, elige el conjunto de datos que contenga la vista.
    • En Seleccionar vista, elige la vista que quieres autorizar.
  5. Haz clic en Agregar y, luego, en Listo.

IU clásica

  1. Haz clic en la flecha desplegable a la derecha del conjunto de datos que contiene las tablas fuente y elige Compartir conjunto de datos.

  2. En el cuadro de diálogo Compartir conjunto de datos para Add People (Agregar personas), haz clic en el menú desplegable a la izquierda del campo y selecciona Authorized View (Vista autorizada).

  3. Haz clic en Select View (Seleccionar vista).

  4. En el cuadro de diálogo Seleccionar vista, realiza estas acciones:

    • Para Project (Proyecto), verifica el nombre del proyecto. Si la vista está en un proyecto diferente, asegúrate de seleccionarlo.
    • Para Dataset (Conjunto de datos), elige el conjunto de datos que contiene la vista.
    • Para Table ID (ID de tabla), ingresa el nombre de la vista que autorizas.
    • Haz clic en Aceptar.

      Selecciona vista autorizada

  5. Haz clic en Add (Agregar) y, luego, en Guardar cambios.

bq

  1. Escribe la información del conjunto de datos existente (incluidos los controles de acceso) en un archivo JSON mediante el comando show. Si el conjunto de datos está en un proyecto que no es tu proyecto predeterminado, agrega el ID del proyecto al nombre del conjunto de datos en el siguiente formato: project_id:dataset.

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

    En el ejemplo anterior, se ilustra lo siguiente:

    • project_id es el ID del proyecto.
    • dataset es el nombre del conjunto de datos.
    • path_to_file es la ruta al archivo JSON en tu máquina local.

    Ejemplos:

    Ingresa el siguiente comando para escribir los controles de acceso de mydataset en un archivo JSON. mydataset está en tu proyecto predeterminado.

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

    Ingresa el siguiente comando para escribir los controles de acceso de mydataset en un archivo JSON. mydataset está en myotherproject.

    bq show --format=prettyjson \
    myotherproject:mydataset > /tmp/mydataset.json
    
  2. Agrega la vista autorizada a la sección "acceso" del archivo JSON.

    Por ejemplo, la sección de acceso del archivo JSON de un conjunto de datos se vería de la manera siguiente:

    {
     "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. Cuando tus ediciones estén completas, usa el comando update con la marca --source para incluir el archivo JSON. Si el conjunto de datos está en un proyecto que no es tu proyecto predeterminado, agrega el ID del proyecto al nombre del conjunto de datos en el siguiente formato: project_id:dataset.

    bq update \
    --source path_to_file \
    project_id:dataset
    

    En el ejemplo anterior, se ilustra lo siguiente:

    • path_to_file es la ruta al archivo JSON en tu máquina local.
    • project_id es el ID del proyecto.
    • dataset es el nombre del conjunto de datos.

    Ejemplos:

    Ingresa el siguiente comando a fin de actualizar los controles de acceso para mydataset. mydataset está en tu proyecto predeterminado.

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

    Ingresa el siguiente comando a fin de actualizar los controles de acceso para mydataset. mydataset está en myotherproject.

     bq update --source /tmp/mydataset.json myotherproject:mydataset
    
  4. Para verificar los cambios del control de acceso, ingresa otra vez el comando show sin escribir la información en un archivo.

    bq show --format=prettyjson [DATASET]
    

    o

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

API

Llama a datasets.patch y usa la propiedad access para actualizar tus controles de acceso. Para obtener más información, consulta Conjuntos de datos.

Debido a que el método datasets.update reemplaza todo el recurso de conjunto de datos, es preferible usar el método datasets.patch para actualizar los controles de acceso.

Go

Antes de probar este ejemplo, sigue las instrucciones de configuración para Go que se encuentran en la guía de inicio rápido de BigQuery sobre cómo usar bibliotecas cliente. Si deseas obtener más información, consulta la documentación de referencia de la API de BigQuery para 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 probar este ejemplo, sigue las instrucciones de configuración para Java que se encuentran en la guía de inicio rápido de BigQuery sobre cómo usar bibliotecas cliente. Si deseas obtener más información, consulta la documentación de referencia de la API de 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 probar esta muestra, sigue las instrucciones de configuración para Python incluidas en la Guía de inicio rápido de BigQuery sobre cómo usar bibliotecas cliente. Si deseas obtener más información, consulta la documentación de referencia de la API de BigQuery para Python.

# 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

Aplica accesos a nivel de fila con una vista

Las vistas se pueden usar para restringir el acceso a columnas específicas (campos). Si deseas restringir el acceso a las filas individuales en tu tabla, no necesitas crear vistas por separado para cada usuario o grupo. En su lugar, puedes usar la función SESSION_USER() para mostrar la dirección de correo electrónico del usuario actual.

A fin de mostrar filas diferentes a distintos usuarios, agrega otro campo a la tabla que contiene el usuario que tiene permiso para ver la fila. Luego, crea una vista que use la función SESSION_USER(). En el siguiente ejemplo, los nombres de usuario se almacenan en el campo allowed_viewer:

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

La limitación de este método es que puedes otorgar acceso a un solo usuario a la vez. Puedes evitar esta limitación si haces que allowed_viewer sea un campo repetido. Este enfoque te permite proporcionar una lista de usuarios para cada fila, pero, incluso si usas un campo repetido, almacenar los nombres de usuario en la tabla requerirá que realices el seguimiento manual de los usuarios individuales que tienen acceso a cada fila.

En su lugar, propaga el campo allowed_viewer con nombres de grupos y crea una tabla aparte que asigne los grupos a los usuarios. La tabla que asigna los grupos a los usuarios tendría un esquema que almacene los nombres de grupos y de usuarios. Por ejemplo: {group:string, user_name:string} Este método te permite administrar la información del usuario y del grupo por separado desde la tabla que contiene los datos.

Si la tabla de asignación se llama private.access_control, la consulta de SQL que se usa para crear la vista autorizada sería como la que se ve a continuación:

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óximos pasos