Row-level Security (RLS) is a fine-grained access control mechanism that restricts which rows of data a principal can access within a BigQuery table. BigQuery implements this using Row Access Policies (RAPs).
A Row Access Policy is a table-level object that filters rows at query time based on two components:
- A Grantee List: the Google Principals (users, Google Groups, etc.) to whom the Policy applies.
- A Filter Expression: an SQL predicate that determines which rows are visible to the granted principals.
Row Access Policies provide dynamic, identity-aware filtering without modifying the underlying data, so users only see rows they're authorized to access.
BigQuery syntax, supported 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 Row-level Policy.
If a user belongs to multiple groups, each with a different Row Access Policy on the same table, BigQuery applies union (OR) logic: the user sees all rows any applicable Policy permits. This aligns with PlainID's standard permissive combining algorithm, so PlainID needs no additional merge logic.
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.
Viewing Row-level Policies in PlainID
PlainID displays Row-level Policies in Native mode.
To view a Row-level Policy in Native:
- In the Policies Workspace, select the relevant Policy connected to Google BigQuery.
- On the top navigation bar, click Native.
- The Native Code panel displays the Policy Core Logic and Identities Link sections for the Row-level Policy, described in Policy Core Logic and Identities Link below.
In Learn Mode, the Native view is read-only. You can view the native Row-level Policy structure, but you can't make changes.
Asset Type Requirements for Row-level Policies
Discovery creates the Asset Type for a BigQuery table automatically, and Manage Mode reuses that same Asset Type when you build a Row-level Policy. You don't need to create or configure an Asset Type yourself. During discovery, the Platform:
- Names the Asset Type using the BigQuery resource format:
project_ID.dataset.table_name. - Maps Asset Attribute names exactly to BigQuery column names, which are case-sensitive.
- Marks the Asset Type as used for data filtering.
- Excludes JSON columns from the Asset Type, since BigQuery Row Access Policies don't support filtering on JSON column types.
BigQuery allows a maximum of 100 Row Access Policies per table. PlainID displays a warning if you approach this limit.
Creating a Row-level Policy from Native
Switch your Google BigQuery application in the Orchestration Workspace to Manage Mode to create, edit, or deploy Row-level Policies from the Policy catalog section. See Managing POPs for more information on how to change the POP Mode.
You can create new Row-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. You can only create it through Native.
Details Step:
- From the Create Policy drop-down, select From Native.
- On the Policy Details step, input a:
- Display Name
- Change the Policy ID if required
- Enter an optional description
-
The Access Type is fixed to Allow. BigQuery Row Access Policies only grant visibility into rows, so there's no restrictive option to choose here.
-
In the Google POP Details section, under the Vendor Policy Kind dropdown, choose Row Access Policy.
-
Enter a Vendor Policy Name.
-
Input the following.
- Project ID: inherited from the POP's Service Account JSON of the selected application (no input required).
- Dataset ID: select from the datasets discovered by the POP.
- Table ID: select from the tables discovered for the selected dataset.
-
Input the custom details if applicable to your Policies (optional).
-
Click Continue.
Code Step:
In the Code step, input the logic and relevant links. Replace the placeholder with the intended filter logic. Each section includes its predefined structure and a logic placeholder, for example:
{
"filterPredicate": "{{logic placeholder}}"
}
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 Row-level Native Policy in BigQuery consists of two sections: Policy Core Logic and Identities Link.
Policy Core Logic
The Policy Core Logic defines the SQL filter predicate that determines which rows are visible to the granted principals.
{
"filterPredicate": "<sql_filter_expression>"
}
Examples:
Simple condition:
{
"filterPredicate": "region = 'EMEA'"
}
Compound condition:
{
"filterPredicate": "col1 = 'one' AND (col2 = 'two' OR col3 = 'three')"
}
Subquery using SESSION_USER():
{
"filterPredicate": "col1 IN (
SELECT
col2
FROM
`plainid-orchestration.name_dataset.nametable6`
WHERE
col2 = SESSION_USER()
)"
}
JOIN subquery:
{
"filterPredicate": "col1 IN (
SELECT
t10.col4
FROM
`plainid-orchestration.name_dataset.nametable9` AS t9
JOIN
`plainid-orchestration.name_dataset.nametable10` AS t10
ON t9.col2 = t10.col3
)"
}
Field Reference
| Field | Description | Value |
|---|---|---|
filterPredicate |
A SQL Boolean expression that the Row Access Policy applies as the FILTER USING clause. The Row Access Policy returns rows where the expression evaluates to TRUE. Supports simple comparisons, compound Conditions, and subqueries including SESSION_USER(). |
string |
- The
filterPredicatemust be a valid GoogleSQL Boolean expression. - Attribute names in the expression must match BigQuery column names exactly and are case-sensitive.
- BigQuery Row Access Policies don't support IP address-based filtering.
- Row Access Policy filter predicates can't use JSON columns.
- Consult the Google BigQuery documentation for the complete, current list of supported syntaxes and limitations, since BigQuery can add or restrict SQL capabilities independently of the Platform.
Identities Link
The Identities Link defines the grantee list: the Google Principals to whom the Row Access Policy applies.
{
"grantees": ["<principal_1>", "<principal_2>"]
}
Example:
{
"grantees": ["serviceAccount:bq-emea-reader@plainid-orchestration.iam.gserviceaccount.com"]
}
All supported grantee types:
{
"grantees": [
"allAuthenticatedUsers",
"domain:plainid.com",
"group:qa@plainid.com",
"serviceAccount:bq-learn-research@acme-orchestration.iam.gserviceaccount.com",
"user:name@acme.com"
]
}
Field Reference
| Field | Description | Value |
|---|---|---|
grantees |
An array of Google Principal identifiers to whom the Row Access Policy grants access. | array of strings |
Supported principal types:
| Principal | Description |
|---|---|
allAuthenticatedUsers |
All users authenticated with a Google Account |
domain:<domain> |
All users in a Google Workspace domain (e.g., domain:plainid.com) |
group:<email> |
A Google Group (e.g., group:analysts@example.com) |
serviceAccount:<email> |
A GCP Service Account (e.g., serviceAccount:name@project.iam.gserviceaccount.com) |
user:<email> |
A specific Google Account (e.g., user:alice@example.com) |
What Step
In the What Step, add the relevant table as an Asset Type. Ensure it's the same table you set as the Table ID in the Details step.
Deploying Policy Changes
When you discover or edit a Row-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 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.
The Platform doesn't validate the native 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.
Known Limitations
| Limitation | Details |
|---|---|
| Native Mode | You can only use this POP in Native Mode. |
| IP Address Filtering | BigQuery Row Access Policies don't support IP address-based filtering in the filterPredicate. |
| Linked Asset | You can't unlink or replace the table linked to a Row-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. |