Authorized functions

Authorized functions let you share query results with particular users or groups without giving those users or groups access to the underlying tables. For example, an authorized function can compute an aggregation over data or look up a table value and use that value in a computation.

By default, if a user-defined function (UDF) or table function queries a table, then a user who invokes that function must have permission to read the data in the table. As an alternative, you can authorize the function to access the dataset that contains the referenced table. An authorized function can query the tables in the dataset, even if the user who calls the function can't query those tables directly.

Authorize a function

You can authorize both UDFs and table functions. To authorize a function, you can use the Google Cloud console, the REST API, or the bq command-line tool:

Console

  1. Go to the BigQuery page in the console.

    Go to BigQuery

  2. In the navigation panel, in the Resources section, expand your project and select a dataset.

  3. In the details panel, click Authorize Routines.

  4. In the Authorized routines page, in the Authorize routine section, select the project ID, dataset ID, and routine ID for the function that you want to authorize.

  5. Click Add authorization.

API

  1. Call the datasets.get method to fetch the dataset that you want the function to access. The response body contains a representation of the Dataset resource.

  2. Add the following JSON object to the access array in the Dataset resource:

    {
     "routine": {
       "datasetId": "DATASET_NAME",
       "projectId": "PROJECT_ID",
       "routineId": "ROUTINE_NAME"
     }
    }
    

    Where:

    • DATASET_NAME is the name of the dataset that contains the UDF.
    • PROJECT_ID is the project ID of the project that contains the UDF.
    • ROUTINE_NAME is the name of the function.
  3. Call the dataset.update method with the modified Dataset representation.

bq

  1. Use the bq show command to get the JSON representation of the dataset that you want the function to access. The output from the command is a JSON representation of the Dataset resource. Save the result to a local file.

    bq show --format=prettyjson TARGET_DATASET > dataset.json
    

    Replace TARGET_DATASET with the name of the dataset that the function will have access to.

  2. Edit the file to add the following JSON object to the access array in the Dataset resource:

    {
     "routine": {
       "datasetId": "DATASET_NAME",
       "projectId": "PROJECT_ID",
       "routineId": "ROUTINE_NAME"
     }
    }
    

    Where:

    • DATASET_NAME is the name of the dataset that contains the function.
    • PROJECT_ID is the project ID of the project that contains the function.
    • ROUTINE_NAME is the name of the function.
  3. Use the bq update command to update the dataset.

    bq update --source dataset.json TARGET_DATASET
    

Authorized function example

The following is an end-to-end example of creating and using an authorized UDF.

  1. Create two datasets named private_dataset and public_dataset. For more information about creating a dataset, see Creating a dataset.

  2. Run the following statement to create a table named private_table in private_dataset:

    CREATE OR REPLACE TABLE private_dataset.private_table
    AS SELECT key FROM UNNEST(['key1', 'key1','key2','key3']) key;
    
  3. Run the following statement to create a UDF named count_key in public_dataset. The UDF includes a SELECT statement on private_table.

    CREATE OR REPLACE FUNCTION public_dataset.count_key(input_key STRING)
    RETURNS INT64
    AS
    ((SELECT COUNT(1) FROM private_dataset.private_table t WHERE t.key = input_key));
    
  4. Grant the bigquery.dataViewer role to a user on the public_dataset dataset. This role includes the bigquery.routines.get permission, which lets the user call the function. For information about how to assign access controls to a dataset, see Controlling access to datasets.

  5. At this point, the user has permission to call the count_key function but cannot access the table in private_dataset. If the user tries to call the function, they get an error message similar to the following:

    Access Denied: Table myproject:private_dataset.private_table: User does
    not have permission to query table myproject:private_dataset.private_table.
    
  6. Using the bq command-line tool, run the show command as follows:

    bq show --format=prettyjson private_dataset > dataset.json
    

    The output is saved to a local file named dataset.json.

  7. Edit dataset.json to add the following JSON object to the access array:

    {
     "routine": {
       "datasetId": "public_dataset",
       "projectId": "PROJECT_ID",
       "routineId": "count_key"
     }
    }
    

    Replace PROJECT_ID with the project ID for public_dataset.

  8. Using the bq command-line tool, run the update command as follows:

    bq update --source dataset.json private_dataset
    
  9. To verify that the UDF has access to private_dataset, the user can run the following query:

    SELECT public_dataset.count_key('key1');