Crea vistas autorizadas

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

Para crear una vista autorizada en BigQuery, debes seguir estos pasos:

  • Usa Cloud Console.
  • Usa el comando bq de la herramienta de línea de comandos bq mk
  • Mediante una llamada al método de la API tables.insert
  • Usa 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.

Si deseas obtener un instructivo sobre cómo crear una vista autorizada, consulta esta página.

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.

Por último, si deseas crear una vista de datos que no te pertenecen, debes tener permisos bigquery.jobs.create en la tabla para hacerlo.

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 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 Explorador, expande tu proyecto y selecciona un conjunto de datos.

  2. Expande la opción Acciones y haz clic en Abrir.

  3. En el panel de detalles, haz clic en Compartir conjunto de datos.

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

  5. 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.
  6. Haz clic en Agregar y, luego, en Listo.

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 Go de BigQuery.

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. Para 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 Python de BigQuery.

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

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

  • Si deseas obtener un instructivo sobre cómo crear una vista autorizada, consulta esta página.
  • Para obtener información sobre cómo crear vistas, consulta Crea vistas.
  • Para obtener información sobre las vistas de listado, consulta Enumera vistas.
  • Para conocer el método sobre cómo obtener metadatos de vistas, consulta Obtén información sobre las vistas.
  • Para obtener más información sobre cómo actualizar vistas, consulta la página sobre cómo actualizar vistas.
  • Para obtener más información sobre cómo administrar vistas, consulta Administra vistas.