Documentation Index

Fetch the complete documentation index at: https://docs.plainid.io/llms.txt

Use this file to discover all available pages before exploring further.

Google BigQuery Column-Level Security

Prev Next

Column-level Security (CLS) lets organizations control access to specific columns within a BigQuery table, ensuring that sensitive data is visible only to authorized principals.

BigQuery enforces Column-level Security through a three-layer architecture:

  • Policy Tag (Taxonomy): a classification label within a Data Catalog Taxonomy (e.g., "SSN" under a "Sensitivity" taxonomy).
  • Schema Association: the step that attaches the Policy Tag to a specific column in the table schema.
  • Data Policy: a resource that links the Policy Tag to a masking rule and grants access to specific principals.

BigQuery doesn't apply masking directly to a column. Instead, it applies masking to the tag on that column. PlainID discovers Policy Tags as protected resources and the linked Data Policies in their native form, giving users visibility into data protection in Google BigQuery and laying the foundation for centralized Policy management.

Note

BigQuery syntax, supported masking expressions, and limitations can change independently of the Platform. Always consult the Google BigQuery documentation for the current list of valid supported syntaxes and limitations before you deploy a Column-level Policy.

For general Native Policy concepts that Row-level and Column-level Policies share (the Native tab, the Protected Resource sub-tab, and how Vendor Compare deploys changes to BigQuery), see Google BigQuery Native Support.

Dynamic Data Masking

BigQuery supports the following masking rules, which PlainID exposes as options when you define a Column-level Policy:

Masking Rule Behavior
SHA256 Replaces the column value with its SHA-256 hash
ALWAYS_NULL Returns NULL for all values (full redaction)
DEFAULT_MASKING_VALUE Returns 0 for numbers, empty string for strings
LAST_FOUR_CHARACTERS Shows only the last four characters (e.g., for SSN)
FIRST_FOUR_CHARACTERS Shows only the first four characters
EMAIL_MASK Masks the local part of an email address
DATE_YEAR_MASK Returns only the year portion of a date

You can also create Routines (User Defined Functions) and set them as masking logic within a Data Policy in Google BigQuery.


Viewing Column-level Policies in PlainID

PlainID displays Column-level Policies in Native mode.

To view a Column-level Policy in Native:

  1. In the Policies Workspace, select the relevant Policy connected to Google BigQuery.
  2. On the top navigation bar, click Native.
  3. The Native Code panel displays the Policy Core Logic, Identities Filter, and UDF (if applicable) for the Column-level Policy. See Policy Core Logic, Identities Filter, and UDF (Conditional) below for the full JSON structure of each section.
Learn Mode

In Learn Mode, the Native view is read-only. You can view the native Column-level Policy structure, but you can't make changes.

Manage Mode

In Manage Mode, the Native view is editable. Selecting Edit on a Column-level Policy opens the Policy Core Logic and Identities Filter sections for editing as beautified JSON. You can technically edit the fields in the UDF section, when discovered and present, but edits have no effect: the Platform reads the routine directly from BigQuery, so changes made here don't apply.


Creating a Column-level Policy from Native

Manage Mode Required

Switch your Google BigQuery application in the Integration Workspace to Manage Mode to create, edit, or deploy Column-level Policies from the Policy catalog section. See Managing POPs for more information on how to change the POP Mode.

You can create new Column-level Policies for Google BigQuery directly from their native structure. There are three steps when you create a Policy:

  • Details
  • Code
  • What

This POP has no Wizard-based creation path.

Details Step

  1. From the Create Policy drop-down, select From Native.
  2. On the Policy Details step, input a:
  • Display Name
  • Change the Policy ID if required
  • Enter an optional description
  1. The Access Type is fixed to Allow. BigQuery Data Policies only grant visibility into masked or unmasked values, so there's no restrictive option to choose here.

  2. In the Google POP Details section, under the Vendor Policy Kind dropdown, choose Masking Policy.

  3. Enter a Vendor Policy Name.

  4. Input the following.

    • Project ID: Select the project ID inherited from the POP.
    • Location: Select the location manually. This must match the location of the selected Taxonomy.
    • Taxonomy: select from the taxonomies discovered by the POP.
    • Policy Tag ID: select from the Policy Tags discovered for the selected taxonomy.
  5. Input the custom details if applicable to your Policies (optional).

  6. Click Continue.

Code Step

In the Code step, input the logic and relevant links. Replace the placeholder with the intended masking logic. Each section includes its predefined structure and a logic placeholder, for example:

{
  "dataMaskingPolicy": {
    "predefinedExpression": "{{logic placeholder}}"
  }
}
Tip

You can add // style inline comments in this step for visibility. They don't show up in the Vendor Compare section and aren't deployed to the Vendor. PlainID retains comments, but a Policy override from the Vendor also overrides the comment.

A Column-level Native Policy in BigQuery consists of two required sections and one conditional section.

  • Section 1: Policy Core Logic (always present): defines the masking behavior
  • Section 2: Identities Filter (always present): defines the IAM bindings
  • Section 3: UDF (conditional): present only when the Data Policy uses a routine instead of a predefinedExpression

Policy Core Logic

The Policy Core Logic defines the masking behavior applied to the column via the dataMaskingPolicy object. This can use either a predefinedExpression or a routine, but not both.

Using a predefined expression:

{
  "dataMaskingPolicy": {
    "predefinedExpression": "SHA256"
  }
}

Using a custom routine:

{
  "dataMaskingPolicy": {
    "routine": "projects/498531790395/datasets/jon_dataset/routines/mask_last_four"
  }
}

Field Reference:

Field Description Value
dataMaskingPolicy The masking policy object. Contains either predefinedExpression or routine. object
predefinedExpression A built-in BigQuery masking expression. Use it to apply a standard masking rule. string
routine The fully qualified resource path of a custom UDF. Format: projects/<projectId>/datasets/<dataset>/routines/<routineName>. Use it when you define a custom masking function. string

Identities Filter

The Identities Filter defines the IAM bindings that control which principals receive masked access. The Platform retrieves these bindings via a separate getIamPolicy request.

{
  "bindings": [
    {
      "members": ["<principal_1>", "<principal_2>"],
      "role": "roles/bigquerydatapolicy.maskedReader"
    }
  ]
}

Example:

{
  "bindings": [
    {
      "role": "roles/bigquerydatapolicy.maskedReader",
      "members": [
        "domain:plainid.com",
        "group:qa@plainid.com",
        "principalSet://cloudresourcemanager.googleapis.com/projects/498531790395/type/ServiceAccount",
        "serviceAccount:bq-learn-research@plainid-orchestration.iam.gserviceaccount.com",
        "user:jon.kraversky@plainid.com"
      ]
    }
  ]
}

Field Reference:

Field Description Value
bindings An array of IAM binding objects, each of which assigns a role to a set of principals. array of objects
members The Google Principals assigned to the role. Values prefixed with user: or serviceAccount: are direct assignments. The Platform treats values prefixed with group:, domain:, or principalSet: as Identity Filters. array of strings
role The role is fixed to roles/bigquerydatapolicy.maskedReader as part of the masking Policy. You don't set or choose this value. "roles/bigquerydatapolicy.maskedReader"

UDF (Conditional)

The UDF section appears only when the Data Policy uses a routine in the Policy Core Logic section above. It describes the custom masking function applied to the column.

Note

You can technically edit the fields in this section, but editing them has no effect: the Platform reads the routine directly from BigQuery, so changes made here don't apply. To change the masking behavior, edit the UDF directly in BigQuery.

Example:

{
  "arguments": [
    {
      "dataType": { "typeKind": "STRING" },
      "name": "input_val"
    }
  ],
  "creationTime": "1779708810580",
  "dataGovernanceType": "DATA_MASKING",
  "definitionBody": "LPAD(SUBSTR(input_val, -4), LENGTH(input_val), '*')",
  "etag": "1pZPdwussEQJ2fUxO8qLHw==",
  "language": "SQL",
  "lastModifiedTime": "1779708810580",
  "returnType": { "typeKind": "STRING" },
  "routineReference": {
    "datasetId": "jon_dataset",
    "projectId": "plainid-orchestration",
    "routineId": "mask_last_four"
  },
  "routineType": "SCALAR_FUNCTION"
}

Field Reference:

Field Description Value
arguments The input parameters the UDF accepts. array of objects
arguments.dataType.typeKind The BigQuery data type of the argument (e.g., STRING, INT64). string
arguments.name The name of the argument, as used in the definitionBody. string
creationTime The Unix timestamp (in milliseconds) when BigQuery created the UDF. Read-only. string
dataGovernanceType Identifies this UDF as a data masking function. Always "DATA_MASKING" for Column-level Policies. "DATA_MASKING"
definitionBody The SQL expression that defines the masking logic applied to the column value. string
language The language used to define the UDF body. string
returnType.typeKind The BigQuery data type the UDF returns. string
routineReference.datasetId The dataset that contains the routine. string
routineReference.projectId The GCP project that contains the routine. string
routineReference.routineId The name of the routine. string
routineType The type of routine. Always "SCALAR_FUNCTION" for masking UDFs. "SCALAR_FUNCTION"

What Step

In the What Step, add the relevant Policy Tag as the Asset Type. Ensure it's the same Policy Tag ID you set in the Details step.


How PlainID Deploys a Column-level Policy

When you deploy a Column-level Policy from PlainID, the Platform orchestrates the three-layer architecture described above:

Step 1: Taxonomy and Policy Tag
The Policy Tag and its Taxonomy must already exist in BigQuery. PlainID discovers them as protected resources so you can link a Column-level Policy to the correct Policy Tag, but it doesn't create or manage Taxonomies or Policy Tags themselves.

Step 2: Schema Association
PlainID retrieves the current table schema and attaches the Policy Tag to the target column. This is a schema modification operation (tables.update).

Step 3: Data Policy
PlainID creates or updates a Data Policy resource that links the Policy Tag to the selected masking rule, and assigns the maskedReader role to the target principals.

PlainID handles the Schema Association and Data Policy steps for you whenever you deploy a Column-level Policy. Taxonomies and Policy Tags, however, must already exist in BigQuery; PlainID discovers and links to them but doesn't create or manage them.


Deploying Policy Changes

When you discover or edit a Column-level Policy in Manage Mode, PlainID doesn't push the changes to BigQuery automatically. Use the Policy Deploy operation to:

  • Accept the vendor's version of a single Policy, discarding the pending Platform change.
  • Accept the Platform's version of a single Policy, or all pending Policies, and push the Data Policy update to BigQuery.

The Platform marks discrepancies between the vendor and Platform versions of a Policy, and you can review them side by side in Vendor Compare. For general information on how the Native tab, Protected Resource linking, and Vendor Compare work, see Google BigQuery Native Support.

Validation Happens at Deploy

The Platform doesn't validate the native masking and filter syntax when you save changes. Validation happens in BigQuery when you deploy the Policy. If BigQuery rejects the Policy, PlainID returns the error and displays it on the Policy in Side-by-Side and Vendor Compare. For more information, see our Policy Side Panel documentation.


Known Limitations

Limitation Details
Native Mode You can only use this POP in Native Mode.
UDF Section You can edit the fields in the UDF section of a Column-level Policy, but edits have no effect. Make changes to the underlying routine directly in BigQuery.
Linked Asset You can't unlink or replace the Policy Tag linked to a Column-level Policy.
Vendor Policy Section The Vendor Policy section shown in Vendor Compare is metadata only. You can't edit it, including through Policy-as-Code import.

© 2026 PlainID LTD. All rights reserved.