How to apply Column masking and RLS on Views in Databricks
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
02-11-2025 12:24 AM
Hello Databricks Community,
We are working on a use case where we need to apply column masking and row-level filtering on top of existing views or while creating new views dynamically.
Currently, we know that Delta tables support column masking and row-level filtering via Alter commands. However, we are wondering if there is a way to achieve similar functionality for views.
Can anyone provide guidance on how to achieve this for views in Databricks?
Any suggestions, workarounds, or examples would be much appreciated!
Thank you!
- Labels:
-
Spark
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
02-11-2025 08:37 AM - edited 02-11-2025 08:54 AM
Hello @TejeshS ,
We cannot directly mask a view since we cannot alter it or add data to it. However, we can apply column masking at the view level using Databricks Dynamic Views. This allows us to control access to specific columns based on the user's role.
For example, we can create a view where the Salary column is only visible to ab***@gmail.com and xy****@gmail.com while all other users see a masked value like "Masked".This is achieved using a Case When condition that checks the current user.
Sample Query :
SELECT
Name,
Department,
CASE
WHEN current_user() IN ('ab***@gmail.com', 'xy***@gmail.com') THEN Salary
ELSE 'MASKED'
END AS Salary
FROM employees;
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
02-11-2025 11:56 AM - edited 02-11-2025 11:58 AM
@TejeshS You can alternatively use, mask function instead of hardcoding with value 'Masked'.
CREATE OR REPLACE VIEW masked_employees AS
SELECT
Name,
Department,
CASE
WHEN current_user() IN ('ab***@gmail.com', 'xy***@gmail.com') THEN Salary
ELSE mask(cast(Salary as string))
END AS Salary
FROM employees;
Else create custom functions like code, which is more dynamic for maintenance purposes.
-- First create a group for users who can see unmasked data
CREATE GROUP IF NOT EXISTS sensitive_data_viewers;
-- Create masking functions with role-based logic
CREATE OR REPLACE FUNCTION mask_functions.conditional_mask_email(email STRING)
RETURNS STRING
RETURN CASE
WHEN IS_MEMBER('sensitive_data_viewers') THEN email
WHEN email IS NULL THEN NULL
ELSE CONCAT(
LEFT(SPLIT(email, '@')[0], 2),
REPEAT('*', LENGTH(SPLIT(email, '@')[0]) - 2),
'@',
SPLIT(email, '@')[1]
)
END;
-- Create view with conditional masking
CREATE OR REPLACE VIEW customer_data_masked AS
SELECT
customer_id,
full_name,
mask_functions.conditional_mask_email(email) as email,
phone_number,
-- Non-sensitive fields shown to everyone
city,
country,
registration_date
FROM customer_table;
-- Grant access to the view for all users
GRANT SELECT ON VIEW customer_data_masked TO role_analyst;
GRANT SELECT ON VIEW customer_data_masked TO role_developer;
-- Add specific users to the sensitive data viewers group
ALTER GROUP sensitive_data_viewers ADD USER user1@company.com;
ALTER GROUP sensitive_data_viewers ADD USER user2@company.com;

