ABAC - Row-Level Security
Attribute-Based Access Control (ABAC) provides fine-grained, row-level security that complements QRY's Role-Based Access Control (RBAC) system. While RBAC controls which tables users can access, ABAC controls which rows within those tables they can see.
The Problem ABAC Solves
Traditional RBAC tells you: "Alice can access the sales database."
ABAC adds precision: "Alice can access the sales database, but only rows where company_code = 'E003' and region = 'EMEA'."
Real-World Scenario
Imagine you have a global sales database with millions of records across 50 countries and 20 business units. You need:
- Regional managers to see only their region's data
- Country managers to see only their country's data
- Holding company users to see data from specific subsidiaries
- Auditors to see everything (but you need to log their access)
Creating separate tables or views for each permission level? That's a maintenance nightmare. Enter ABAC.
How ABAC Works
ABAC uses a simple but powerful three-step approach:
1. Tag Your Tables
Tables are labeled with tags that describe their attributes:
has_company_code- Contains company/organization identifierhas_region- Contains geographic region datahas_customer_data- Contains customer informationsales_domain- Sales-related datapii_sensitive- Personally identifiable information
Tags can be assigned manually or discovered automatically by scanning your schema.
2. Create Policies
Policies define filter requirements for tagged tables:
Policy: "Regional Sales Restriction"
Applies to: Sales Team (group)
Tables: Any table tagged with "has_region"
Required Filter: region IN ('EMEA', 'APAC')
When anyone in the Sales Team queries a table tagged with has_region, they must include WHERE region IN ('EMEA', 'APAC') in their query.
3. Automatic Enforcement
ABAC enforces policies using a two-layer defense:
Layer 1: AI Guidance
- When users ask questions, the AI sees policy requirements in the schema metadata
- The AI proactively generates queries with correct filters
- Reduces errors and improves user experience
Layer 2: Server-Side Validation
- Every query is validated before execution
- Missing or incorrect filters = Access Denied
- Complete audit trail of all access attempts
Key Concepts
Tags
Tags are labels that categorize tables based on their attributes. Think of them as searchable metadata.
Tag Categories:
| Category | Purpose | Examples |
|---|---|---|
| Column Presence | Table contains specific columns | has_company_code, has_email, has_customer_id |
| Business Domain | Department or functional area | sales_domain, finance_domain, hr_domain |
| Sensitivity | Data classification level | pii_email, pii_ssn, confidential, public |
| Compliance | Regulatory requirements | gdpr_regulated, hipaa_protected, sox_controlled |
Auto-Discovery: Tags can have discovery rules that automatically find matching tables:
{
"column_names": ["COMPANY_CODE", "BUKRS", "ORG_ID"],
"case_sensitive": false
}
This rule tags any table containing a column named COMPANY_CODE, BUKRS, or ORG_ID.
Policies
Policies connect tags to filter requirements. Each policy specifies:
- Who it applies to - Specific user, group, or everyone
- Which tables - Via tag matching (e.g., "any table with
has_company_code") - Required filters - What WHERE clause conditions must be present
- Enforcement mode - Enforce (block) or Log-only (warn)
Example Policy:
Name: Company Code Restriction
Target: Coated Group
Tags: [has_company_code]
Match Mode: ANY (applies if table has any of these tags)
Filter Requirements:
- Column: COMPANY_CODE
Operator: IN
Values: ['E003', 'E004']
Enforcement: Enforce
Priority: 100
What this does:
- Applies to all users in the "Coated" group
- Affects any table tagged with
has_company_code - Requires
WHERE COMPANY_CODE IN ('E003', 'E004')in all queries - Blocks queries that don't include this filter
Multi-Column Policies
Policies can require multiple filters (AND logic):
Name: Multi-Column Access Control
Tags: [has_company_code, has_region]
Match Mode: ALL (table must have all tags)
Filter Requirements:
- Column: COMPANY_CODE
Operator: IN
Values: ['E003', 'E004']
- Column: REGION
Operator: =
Values: ['EMEA']
Users must include both filters: WHERE COMPANY_CODE IN ('E003', 'E004') AND REGION = 'EMEA'
Quick Start Workflow
Scenario: Restrict Users by Company Code
Goal: Users in the "Regional Team" should only see data where COMPANY_CODE = 'E003'
Step 1: Create a Tag (or Use Existing)
Navigate to Admin Panel → ABAC → Tag Catalog
Create tag:
- Tag Key:
has_company_code - Display Name: Has Company Code
- Category: column_presence
- Discovery Rule: Auto-detect tables with
COMPANY_CODEcolumn
Step 2: Run Auto-Discovery
Navigate to Admin Panel → ABAC → Tag Discovery
Start discovery job:
- Datasource: Your production database
- Tags: Select
has_company_code - Scope: All schemas (or specific ones)
Wait for completion. The system scans your database and tags all tables containing a COMPANY_CODE column.
Step 3: Review Tagged Tables
Navigate to Admin Panel → ABAC → Table Tags
Review the auto-tagged tables. You can:
- Remove incorrect assignments
- Add manual tags to missed tables
- See confidence scores for auto-discovered tags
Step 4: Create Access Policy
Navigate to Admin Panel → ABAC → ABAC Policies
Create policy:
- Policy Name: Regional_Team_Company_Filter
- Target: Group → "Regional Team"
- Tags:
has_company_code - Match Mode: ANY
- Filter Requirements:
- Column:
COMPANY_CODE - Operator:
IN - Values:
E003
- Column:
- Enforcement: Enforce
Step 5: Test
Log in as a user in "Regional Team" and try queries:
-- ✅ ALLOWED: Includes required filter
SELECT * FROM sales_orders WHERE COMPANY_CODE = 'E003'
-- ❌ BLOCKED: Missing required filter
SELECT * FROM sales_orders
-- ❌ BLOCKED: Wrong company code
SELECT * FROM sales_orders WHERE COMPANY_CODE = 'E001'
The AI will automatically suggest correct queries, and the server will block non-compliant ones.
Step 6: Monitor
Navigate to Admin Panel → ABAC → Audit Log
View all access attempts:
- Successful queries (with filters applied)
- Blocked queries (with denial reasons)
- User activity patterns
- Policy effectiveness
Real-World Use Cases
Use Case 1: Multi-Entity Holding Company
Challenge: Holding company with 10 subsidiaries. Each subsidiary's team should only see their own data.
ABAC Solution:
- Create Tag:
has_company_code(auto-discover) - Create Groups: One per subsidiary (
Subsidiary_E001,Subsidiary_E002, etc.) - Create Policies: One per group
Policy: Subsidiary_E001_Filter
Target: Group "Subsidiary_E001"
Tags: [has_company_code]
Filter: COMPANY_CODE = 'E001'
Result: 10 policies manage access across thousands of tables. New tables are automatically tagged and protected.
Use Case 2: Geographic Data Segregation
Challenge: Global company needs regional data isolation (GDPR compliance).
ABAC Solution:
-
Create Tags:
has_region(auto-discover region column)has_customer_data(manually tag customer tables)
-
Create Policies:
Policy: EMEA_Data_Restriction
Target: Group "EMEA Team"
Tags: [has_region, has_customer_data]
Match Mode: ALL (must have both tags)
Filter Requirements:
- Column: REGION
Operator: IN
Values: ['EMEA', 'UK', 'EU']
- Column: DATA_RESIDENCY
Operator: =
Values: ['EU']
Result: Automated compliance with data residency requirements.
Use Case 3: Audit & Compliance
Challenge: Auditors need full access, but all queries must be logged and traceable.
ABAC Solution:
-
Create Tag:
audit_required(manually tag sensitive tables) -
Create Policy:
Policy: Auditor_Full_Access_Logged
Target: Group "Auditors"
Tags: [audit_required]
Match Mode: ANY
Filter: (none - full access)
Enforcement: Log-Only (don't block, just log)
Result: Complete audit trail without restricting access.
Use Case 4: Time-Based Access Control
Challenge: Users should only access recent data, not historical archives.
ABAC Solution:
Policy: Recent_Data_Only
Target: Group "Analysts"
Tags: [has_date_column]
Filter Requirements:
- Column: CREATED_DATE
Operator: >=
Values: ['2024-01-01']
Result: Automatic enforcement of data retention policies.
ABAC vs RBAC: When to Use Each
RBAC (Table-Level)
Use when: Access is binary - user either sees the whole table or nothing.
Examples:
- "Finance team can access financial database"
- "Marketing cannot see HR tables"
- "Contractors have read-only access"
ABAC (Row-Level)
Use when: Users need access to the same tables but different subsets of data.
Examples:
- "Regional managers see only their region's rows"
- "Each client sees only their own data in shared tables"
- "Employees see current data, managers see historical data"
Use Both Together
Best Practice: Combine RBAC and ABAC for defense in depth:
1. RBAC: Grant "Sales Team" access to sales database
2. ABAC: Restrict rows to their assigned territories
RBAC provides the base access, ABAC adds fine-grained filtering.
Benefits
🎯 Scalability
Manage 10,000+ tables with simple tag-based rules. Add a new table? It gets auto-tagged and protected automatically.
🤖 Automation
Auto-discovery eliminates manual configuration. Let the system find and tag tables based on patterns.
🔒 Security
Two-layer defense ensures policies are always enforced - even if the AI makes a mistake, the server catches it.
📊 Auditability
Complete audit trail of every access attempt. Know who accessed what, when, and whether it was allowed.
🔧 Flexibility
Supports multiple filter operators, multi-column policies, group and user-level rules, and log-only mode for testing.
💰 Cost-Effective
No need to duplicate data or create complex view structures. One table, multiple access patterns.
Best Practices
Start Simple
Phase 1: Column presence tags
Create tags like has_company_code, has_region
Use auto-discovery
Apply to one or two groups
Phase 2: Business domain tags
Add sales_domain, finance_domain tags
Create department-based policies
Phase 3: Compliance tags
Add pii_email, gdpr_regulated tags
Implement regulatory requirements
Test Before Enforcing
- Create policy in Log-Only mode
- Monitor audit log for 1-2 weeks
- Review violations and adjust filters
- Switch to Enforce mode
- Continue monitoring
Use Groups, Not Individual Users
❌ Don't: Create user-specific policies for 100 users
✅ Do: Create 5 group-based policies
Groups scale. Individual policies don't.
Document Your Tags
Create a tag catalog with clear descriptions:
Tag: has_company_code
Purpose: Tables containing organizational identifier
Columns: COMPANY_CODE, BUKRS, ORG_ID
Used By: All multi-entity policies
Created: 2025-01-15
Regular Audits
Weekly: Review denied access attempts Monthly: Check policy effectiveness Quarterly: Audit tag assignments Annually: Review overall ABAC strategy
Admin Features
Tag Catalog
- Create and manage metadata tags
- Define discovery rules
- Organize by category
- Track usage statistics
Tag Discovery
- Automated schema scanning
- Pattern-based table detection
- Confidence scoring
- Job progress tracking
- Scope filtering (catalogs, schemas, tables)
Table Tags
- View all tag assignments
- Manual tag management
- Filter by datasource, tag, or table
- See auto-discovered vs manual tags
ABAC Policies
- Policy creation wizard
- Multi-condition filters
- Priority management
- Test mode (log-only)
- Bulk operations
Audit Log
- Complete access history
- Allowed and denied queries
- User activity tracking
- Policy violation analysis
- Export for compliance reporting
Troubleshooting
"Access Denied: Missing required filter"
Check:
- Audit log for exact denial reason
- Policy filter requirements
- Query syntax (case sensitivity)
- Table alias usage
Common Fix: Ensure filter values match exactly (case-sensitive in most databases).
Discovery job finds no tables
Check:
- Discovery rule pattern (case sensitivity)
- Scope filters (too narrow?)
- Datasource connection
- Column name variations
Common Fix: Set case_sensitive: false in discovery rule.
Policy not applying
Check:
- User group membership
- Table has required tags
- Policy is active (not disabled)
- Enforcement mode (not log-only)
Common Fix: Verify table tags in "Table Tags" view.
FAQ
Q: Does ABAC slow down queries? A: Minimal impact. Validation adds ~20-50ms per query. The AI layer actually improves performance by generating correct queries the first time.
Q: Can I use ABAC without RBAC? A: Yes, but we recommend using both. RBAC provides base access control, ABAC adds fine-grained filtering.
Q: What happens if no policies match a table? A: The table is accessible according to RBAC permissions (no row-level filtering applied).
Q: Can policies conflict? A: Multiple policies are combined with AND logic. All filter requirements must be satisfied.
Q: Can I test policies before enforcing them? A: Yes! Use "Log-Only" enforcement mode to see what would be blocked without actually blocking it.
Q: How do I grant full access to admins? A: Don't apply ABAC policies to admin groups, or create a policy with no filter requirements.
Q: What operators are supported?
A: =, IN, >=, <=, >, <, LIKE, NOT IN, !=, NOT LIKE
Security Considerations
Defense in Depth
ABAC is Layer 2 of QRY's security model:
1. Authentication (who are you?)
2. RBAC (which tables can you access?)
3. ABAC (which rows within those tables?)
4. Audit Logging (track everything)
AI Guidance + Server Enforcement
Why two layers?
- AI Layer: Improves user experience (fewer errors)
- Server Layer: Guarantees security (even if AI fails)
The server always validates. The AI helps, but doesn't replace validation.
Audit Trail
Every query validation is logged with:
- User ID and email
- Full SQL query
- Access decision (granted/denied)
- Denial reason (if denied)
- Applied policies
- Timestamp
Retention: Configure based on compliance needs (90 days recommended, longer for regulated industries).
Integration with QRY Features
Works With
✅ Notebooks: Scheduled notebooks respect ABAC policies ✅ Scheduled Tasks: Automated queries are validated ✅ Workspaces: Team members see data according to their permissions ✅ Python Execution: Data loaded from queries respects filters ✅ File Upload: Uploaded data not subject to ABAC (separate permission system)
Next Steps
- Admin Guide: ABAC Administration - Complete admin workflows
- RBAC Feature: Role-Based Access Control - Table-level permissions
- Security Best Practices: Admin Guide - Security and compliance
ABAC: Because sometimes "access to the sales table" isn't specific enough. Welcome to row-level security that actually scales.