- Column-level security — control which columns users can see.
- Data masking — expose columns in a transformed or redacted form rather than hiding them entirely.
- Row-level security — control which rows users can see.
How owner rights work in views
When a user queries a view, Firebolt checks two sets of permissions:- The querying user must have
SELECTon the view. - The view owner (the user who created the view) must have
SELECTon every underlying table or view that the view references.
If the view owner loses access to any referenced object (for example, if
USAGE on the schema or SELECT on a table is revoked from the owner’s role), all users who query the view will receive an authorization error — even if their own SELECT on the view is still in place. For more details, see View permissions.Prerequisites
Before implementing view-based security, ensure the following:- You have a user with privileges to create views, tables, and roles (typically an
account_adminor a user with the relevantCREATEandGRANTprivileges). - You understand RBAC basics and view permissions.
- The database and schema already exist, and you have
USAGEon both.
Column-level security
Column-level security restricts which columns a user can see. To implement it, create a view that exposes only the permitted columns from the base table, then grant usersSELECT on the view instead of the table.
There are two approaches to choosing which columns a view exposes:
- Allowlist — explicitly list the columns that should be visible. Any new columns added to the base table later are not visible through the view by default. This is the more restrictive approach.
- Denylist — use the
EXCLUDEclause to remove specific columns that must be secured. Any new columns added to the base table later are visible through the view by default. This is more convenient but requires you to update the view whenever a new sensitive column is added.
Example: Hiding sensitive columns
Suppose you have anemployees table with sensitive salary and SSN data:
hire_date column is later added to the employees table, it will not appear in employees_public until the view is updated.
Denylist approach — exclude only the sensitive columns using EXCLUDE:
hire_date column is later added to the employees table, it will automatically appear in employees_public. If a new sensitive column is added, you must update the EXCLUDE list.
Set up roles and permissions (same for either approach):
employees table, so she cannot see salary or ssn.
Multiple views for different access levels
You can create multiple views on the same table to provide different levels of column visibility. You can mix and match allowlist and denylist approaches:Row-level security
Row-level security restricts which rows a user can see. To implement it, create a view with aWHERE clause that filters rows, then grant users SELECT on the view instead of the table.
Static row-level security
Use a static filter when specific roles should see a fixed subset of rows.Dynamic row-level security using SESSION_USER
For more flexible row-level security, use theSESSION_USER function inside a view. SESSION_USER() returns the name of the user who is running the query, so the view dynamically filters rows based on the current user.
Step 1 — Create a mapping table that associates users with the data they are allowed to see:
SESSION_USER():
The view owner must have
SELECT on both the orders table and the user_region_access table. The querying users only need SELECT on the orders_secure view.Data masking
Data masking lets users see that a column exists, but replaces the actual values with redacted or transformed versions. This is useful when users need to know that data is present — for example, to join or group on a column — without seeing the sensitive values. To implement data masking, create a view that applies transformation functions to sensitive columns. The following subsections describe common masking techniques.Nulling out
Replace sensitive data withNULL. This is the simplest form of masking — the column is present in the result set but contains no usable value.
employees_nulled returns every row, but ssn and salary are always NULL.
Substitution
Replace real data with fake but realistic values from a lookup table. This preserves the look and feel of the data, which can be useful for testing or demo environments.James Miller) instead of the real employee names.
Hashing (pseudonymization)
Use a cryptographic hash function such asMD5 to turn data into a fixed-length string. The same input always produces the same output, so hashed values can still be used for joins, grouping, and deduplication without revealing the original data.
c14fa496dfd5ebbb08aaca16a7c2781b instead of the real name or SSN.
Redaction (masking out)
Replace specific characters with a generic character such as* while preserving enough structure for the value to remain recognizable. This is especially useful for email addresses, phone numbers, and identifiers.
m...p@acme.com — enough to identify the domain and rough address without revealing the full mailbox name.
Blurring (generalization)
Replace a specific value with a range or a more general category to prevent precise identification. This is common for numeric data such as age, salary, or transaction amounts.72500, users see a range like 70000-79999.
Combining masking with column exclusion
You can combine data masking with column-level security to mask some columns and hide others entirely:Combining column-level, masking, and row-level security
You can combine all three techniques in a single view to control which columns are visible, how sensitive values are displayed, and which rows a user can see:internal_notes entirely, masks amount into a rounded range, and filters rows based on the querying user’s region access.
Managing view ownership
The owner rights model means that the view owner’s permissions are critical. Keep the following best practices in mind:- Use a dedicated admin user or role to create security views. This ensures the view owner always has the necessary permissions on the underlying tables.
-
Do not revoke base table permissions from the view owner. If the view owner loses
SELECTon a referenced table orUSAGEon the schema, all queries through the view will fail. -
Transfer ownership deliberately. If you need to change the view owner, use
ALTER VIEWto transfer ownership and ensure the new owner has all required permissions:For more information about ownership, see Ownership. -
Audit view ownership regularly. Query
information_schema.viewsto check who owns each view and verify they still have the correct permissions:
Setting up default privileges for security views
If you create security views regularly, use ALTER DEFAULT PRIVILEGES to automatically grantSELECT on new views to the appropriate roles:
analyst_role, reducing manual grant overhead.
Summary
| Security type | Technique | Key mechanism |
|---|---|---|
| Column-level | Create a view that selects only permitted columns | View exposes a subset of columns; users have no direct table access |
| Data masking | Create a view that transforms sensitive column values | View exposes columns with redacted or generalized values |
| Row-level (static) | Create a view with a WHERE clause | View filters rows to a fixed subset |
| Row-level (dynamic) | Create a view using SESSION_USER() in a WHERE clause | View filters rows based on the querying user’s identity |
| Combined | Combine column selection, masking, and WHERE filtering | View restricts columns, masks values, and filters rows |
- The view owner’s permissions on underlying tables control whether the view can access the data.
- The querying user only needs
SELECTon the view, not on the underlying tables.
Related topics
- View permissions — Permissions that control access to views
- Ownership — How ownership works in Firebolt
- Role-Based Access Control — Overview of Firebolt’s RBAC model
- CREATE VIEW — Syntax reference for creating views
- SESSION_USER — Function reference for dynamic row-level security
- Role-based access control guide — How-to guide for managing RBAC