> ## Documentation Index
> Fetch the complete documentation index at: https://honeydew.ai/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Row-Level Security

## Overview

Row-Level Security (RLS) restricts which rows a user can
access when querying data.

Three independent layers can enforce RLS, and you can
combine them:

```mermaid theme={null}
flowchart LR
    U[User] --> BI[BI Tool]
    BI --> H[Honeydew]
    H --> DW[Data Warehouse]
    DW --> D[(Data)]

    BI -. "BI-tool RLS\n(applies BI-level\ndata filter)" .-> H
    H -. "Honeydew RLS\n(domain filters,\nuser-mapping tables)" .-> DW
    DW -. "Data Warehouse RLS\n(policies or\nfiltered views)" .-> D
```

| Layer                                 | What it does                                                   | Why use it                                                                                              |
| ------------------------------------- | -------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------- |
| [Data Warehouse](#data-warehouse-rls) | RLS policies or filtered views on data warehouse objects       | Enforced at data warehouse level                                                                        |
| [Honeydew](#honeydew-rls)             | Applies data filters on [Honeydew domains](/domains)           | Leverages fields defined in Honeydew for RLS. Can leverage Honeydew to propagate RLS filters over joins |
| [BI tool](#bi-tool-rls)               | Applies a data filter at the BI level to pass into every query | Enables RLS when using a shared service account for BI                                                  |

## Identity model

The way you identify end users defines how row-level security is applied.

<Tip>
  User authentication is the most secure approach for row-level security
</Tip>

### End users authenticate into Honeydew with their own identity

When end users authenticate into Honeydew, you can use
their identity to set row-level security per user.

The main approaches are:

* [Data warehouse RLS](#data-warehouse-rls) with **user identity propagation**:
  map every Honeydew user to a corresponding data warehouse user.
  Row-level security is then applied at the data warehouse level
  using [OAuth authentication](#via-user-identity-propagation-oauth)
  or [filtered views](#via-filtered-views-with-session-variables).

* [Honeydew RLS](#honeydew-rls) at the semantic layer level with **domain filters**:
  row-level security is applied with domain filters.
  End user identity can be identified with a session variable (`$honeydew_username`).

### End users authenticate into Honeydew with a shared service account

When end users use a shared service account (typically an API key),
there is no way to identify a specific user within Honeydew to apply
per-user row-level security.

The main security approaches are:

1. [Domain roles](#via-domain-roles): apply security filters at the domain level,
   shared for all users using that domain via the shared account.
2. [BI tool RLS](#bi-tool-rls): apply security filters at the BI tool level,
   and pass them down to Honeydew as filters.

## Data Warehouse RLS

Data warehouse RLS policies control which rows are visible per user / role.

### Via user identity propagation (OAuth)

When per-user OAuth is configured, each user's identity flows
from the BI tool through Honeydew to the data warehouse.
The data warehouse sees the actual user, so data warehouse-native RLS policies apply directly.

<Tip>
  No configuration is required in Honeydew when using
  native data warehouse RLS with identity propagation.
</Tip>

<Tabs>
  <Tab title="Snowflake">
    Configure
    [Snowflake OAuth](/integration/data-sources/snowflake#oauth-authentication)
    per the
    [user access control](/access-control/user-access-control#option-1-snowflake-oauth-integration)
    guide, then define
    [Snowflake RLS policies](https://docs.snowflake.com/en/user-guide/security-row-using)
    on the relevant tables.

    Each user needs a Snowflake account with appropriate roles.
  </Tab>

  <Tab title="Databricks">
    Configure
    [Databricks OAuth](/integration/data-sources/databricks#oauth-user-authentication),
    then define
    [row filters](https://docs.databricks.com/aws/en/data-governance/unity-catalog/filters-and-masks)
    on the relevant Unity Catalog tables.

    Each user needs a Databricks account with appropriate
    permissions.
  </Tab>

  <Tab title="BigQuery">
    Configure
    [BigQuery OAuth](/integration/data-sources/bigquery#oauth-user-authentication),
    then define
    [BigQuery RLS policies](https://cloud.google.com/bigquery/docs/row-level-security-intro)
    on the relevant tables.

    Each user needs a Google Cloud account with appropriate
    IAM permissions.
  </Tab>
</Tabs>

### Via domain roles

You can assign a data warehouse role to each [domain](/domains).
RLS policies scoped to that role control which rows are visible.
Each domain becomes a separate datasource in your BI tool,
each enforcing its own RLS configuration.

Configure the role in the domain's data warehouse metadata section.
See [data warehouse access control](/domains#data-warehouse-access-control)
for setup instructions and YAML examples for Snowflake,
Databricks, and BigQuery.

<Tip>
  Combine domain-level roles with
  [domain hierarchy](/domains#domain-hierarchy) to create
  regional or team-specific domains that inherit a shared
  base configuration.
</Tip>

### Via filtered views with session variables

You can enforce row-level access through filtered views,
instead of using the data warehouse-native RLS policies.
Honeydew provides the user identity via a session
variable, and the views use it for filtering:

1. **In the data warehouse**, create filtered views that join
   each table to a lookup table filtered by the querying
   user's identity session variable (`$honeydew_username`).
   The view returns no data unless the session variable is set.
   Grant Honeydew access only to these filtered views, not the underlying tables.
2. **In Honeydew**, map these filtered views as entities.
   Honeydew automatically sets `$honeydew_username` on
   each data warehouse session, which the filtered views use for filtering.

The BI tool must propagate user identity to the
Honeydew connection so that `$honeydew_username` is
set correctly for each query. This keeps access control
logic centrally managed in the data warehouse while Honeydew
provides the user identity at query time.

## Honeydew RLS

Honeydew enforces RLS through
[domain semantic filters](/domains#semantic-filters)
applied at query time. There are two approaches.

### Domain source filters

Add a filter directly on a domain source table. This works
for simple cases where access depends on a column value
in the queried table.

```yaml theme={null}
type: domain
name: us_orders

entities:
  - name: orders

filters:
  - name: region_filter
    sql: orders.region = 'US'
```

### User-mapping table

For more complex access rules, create a mapping table that
defines which data each user can access. Honeydew
propagates the filter over joins, so all related entities
respect the access rules.

#### Example tables

A `user_data_access` mapping table defines which regions
and accounts each user can access:

```sql theme={null}
CREATE TABLE user_data_access (
    user_id INT,
    username VARCHAR,
    region VARCHAR,
    account_id INT
);

INSERT INTO user_data_access VALUES
    (1, 'alice', 'US', 1001),
    (1, 'alice', 'US', 1002),
    (2, 'bob', 'EU', 2001),
    (3, 'carol', 'APAC', 3001);
```

#### Modeling setup

Map `user_data_access` as an
[entity](/modeling/entities) in Honeydew. Define a
[relation](/modeling/relations) from `user_data_access`
to your data entities with
[one-to-many cross-filtering](/modeling/relations#cross-filtering).
This ensures that filtering on the mapping table propagates
to the data entities.

#### Domain filter with OAuth

When per-user OAuth is configured, use the data warehouse's
current user function in a domain filter:

```yaml theme={null}
type: domain
name: restricted_orders

entities:
  - name: orders
  - name: user_data_access

filters:
  # Snowflake
  - name: user_access
    sql: user_data_access.username = CURRENT_USER()

  # Databricks
  - name: user_access
    sql: user_data_access.username = current_user()

  # BigQuery
  - name: user_access
    sql: user_data_access.username = SESSION_USER()
```

Use only the filter that matches your data warehouse.

#### Domain filter with service account

When a service account is used to connect to the data warehouse,
Honeydew user can be used to identify the querying user.
Honeydew sets a `$honeydew_username` session variable on each
data warehouse session containing the authenticated Honeydew username.

```yaml theme={null}
type: domain
name: restricted_orders

entities:
  - name: orders
  - name: user_data_access

filters:
  - name: user_access
    sql: user_data_access.username = $honeydew_username
```

<Note>
  `$honeydew_username` is set automatically on each data warehouse session.
  It contains the username of the user who initiated the query through Honeydew.
</Note>

## BI tool RLS

When a shared service account is used at both the BI and
data warehouse level, the BI tool identifies the signed-in user
and passes their identity as a filter to Honeydew.
Combine this with a [user-mapping table](#user-mapping-table) or
[domain source filters](#domain-source-filters) in Honeydew.

### Power BI

Power BI uses `USERPRINCIPALNAME()` to identify the signed-in user
and pass their identity as query filters.

See [Power BI RLS](/integration/bi-tools/powerbi#row-level-security-rls)
for configuration details.

### Looker

Looker uses `_user_attributes` to pass user context into queries.

See [Looker integration](/integration/bi-tools/looker) for configuration details.
