Hone logo
Hone
Problems

Secure Database Access: Implementing Row-Level Security and Data Masking

Organizations often need to restrict access to sensitive data based on user roles or other criteria. This challenge focuses on implementing advanced security policies within a SQL database to enforce row-level security (RLS) and data masking, ensuring that users only see the data they are authorized to view. This is crucial for compliance with regulations like GDPR and HIPAA and protecting sensitive information from unauthorized access.

Problem Description

You are tasked with designing and implementing SQL security policies to control access to a database table named Employees. The Employees table contains employee information, including employee_id, first_name, last_name, department, salary, and social_security_number.

What needs to be achieved:

  1. Row-Level Security (RLS): Implement RLS to restrict access to employee records based on the user's department. A user belonging to the 'Sales' department should only be able to view records where the department is 'Sales'. Similarly, 'Marketing' users should only see 'Marketing' department records, and so on. Users not belonging to any defined department should see no records.
  2. Data Masking: Implement data masking to protect sensitive information like social_security_number. For users who are not administrators (identified by a role column user_role in a separate Users table), the social_security_number should be masked (e.g., replaced with 'XXX-XX-XXXX'). Administrators (where user_role is 'admin') should see the full social_security_number.

Key Requirements:

  • The solution must be implemented using SQL-specific security features (e.g., policies, views, functions, roles).
  • The solution should be dynamic, meaning it adapts to changes in user roles and department assignments.
  • The solution should be efficient and not significantly impact query performance.
  • Assume a Users table exists with columns user_id, username, and user_role. The user_id corresponds to the user executing the query.

Expected Behavior:

  • When a user queries the Employees table, they should only see rows where their department matches their allowed department (based on RLS).
  • Non-administrator users should see masked social_security_number values.
  • Administrator users should see the unmasked social_security_number values.
  • Queries should function correctly regardless of the complexity of the query (e.g., joins, aggregations).

Edge Cases to Consider:

  • Users with no department assignment.
  • Users with invalid or missing roles.
  • Performance impact of the security policies.
  • Handling of NULL values in the department column.
  • Security implications of granting excessive privileges.

Examples

Example 1:

Input: User 'sales_user' (department = 'Sales', user_role = 'regular') executes: SELECT * FROM Employees;
Output: Only rows where department = 'Sales' are returned, and social_security_number is masked as 'XXX-XX-XXXX'.
Explanation: RLS filters by department, and data masking hides the SSN for non-admins.

Example 2:

Input: User 'admin_user' (department = 'Engineering', user_role = 'admin') executes: SELECT * FROM Employees;
Output: All rows are returned, and social_security_number is displayed in full.
Explanation: RLS does not apply (as all departments are accessible to admin), and data masking is bypassed for admins.

Example 3:

Input: User 'unknown_user' (department = NULL, user_role = 'regular') executes: SELECT * FROM Employees;
Output: No rows are returned.
Explanation: RLS filters out users with no department assignment.

Constraints

  • The database system is assumed to be PostgreSQL. While the concepts are transferable, specific syntax may need adjustment for other SQL dialects.
  • The Employees table already exists with the specified columns.
  • The Users table already exists with the specified columns.
  • The solution must be implemented using SQL only; no procedural code (e.g., stored procedures) is allowed.
  • The solution should be reasonably performant; avoid complex or inefficient queries. A query taking longer than 1 second on a table with 10,000 rows is considered unacceptable.

Notes

  • Consider using PostgreSQL's security policies and roles for RLS.
  • For data masking, explore using functions or views to transform the social_security_number column.
  • Think about how to manage user roles and department assignments effectively.
  • Test your solution thoroughly with various user roles and department assignments to ensure it behaves as expected.
  • Pay close attention to the security implications of your design. Avoid granting unnecessary privileges.
  • The Users table is assumed to be populated with appropriate user information. You do not need to create or populate this table.
  • Focus on the SQL implementation of the security policies. The user authentication and authorization mechanisms are assumed to be handled elsewhere.
Loading editor...
plaintext