Zero-Trust Security & PBAC Engine¶
The Policy-Based Access Control (PBAC) engine in VDA provides a mathematically rigorous, attribute-aware security boundary that guarantees principle-of-least-privilege access across all data retrieval, metadata discovery, and SQL execution pathways.
1. Formal Policy Definition & Grammar¶
An authorization state $\mathcal{S}$ is defined by a set of policy rules $\mathcal{R}$, where each rule $r \in \mathcal{R}$ is a 4-tuple:
$$r = \langle \text{role}, \text{action}, \text{scope}, \text{effect} \rangle$$
- $\text{role} \in \Sigma^*$: The identifier of the role (e.g.,
RiskAuditor,DataEngineer,CoreBankingAnalyst). - $\text{action} \in \mathcal{A}$: The semantic operation requested.
- $\text{scope} \in \mathcal{C}$: The targeted resource identifier.
- $\text{effect} \in {\text{ALLOW}, \text{DENY}}$: The policy directive.
Canonical Semantic Actions ($\mathcal{A}$)¶
VDA standardizes all operations into a canonical action hierarchy:
$$\begin{aligned} \text{admin:*} &\implies \text{All administrative, configuration, and data actions} \ \text{data:query} &\implies \text{Execute analytical SQL queries and view tabular results} \ \text{data:read} &\implies \text{Read table records, sample preview, and export charts} \ \text{metadata:read} &\implies \text{Inspect schema, column types, descriptions, and lineage DAGs} \ * &\implies \text{Wildcard matching any action} \end{aligned}$$
$$\text{Action Implication Rule: } \text{data:read} \implies \text{metadata:read}$$
graph TD
Admin["admin:* (Full Control)"] --> DataQuery["data:query (Run Arbitrary SQL)"]
DataQuery --> DataRead["data:read (Preview & Read Records)"]
DataRead --> MetaRead["metadata:read (View Schema & Lineage)"]
Canonical Resource Scopes ($\mathcal{C}$)¶
Resources follow a hierarchical naming convention:
- Datasource Scope: datasource:<datasource_name> (e.g., datasource:retail_banking)
- Dataset / Table Scope: dataset:<datasource_name>.<table_name> (e.g., dataset:retail_banking.transactions)
- Column Scope: column:<datasource_name>.<table_name>.<column_name> (e.g., column:retail_banking.transactions.cust_national_id)
- Global Wildcard Scope: *
2. The Evaluation Algorithm & Invariants¶
When a principal $P$ associated with active roles $Roles(P)$ attempts an action $A$ against resource $S$:
$$\text{Decision}(P, A, S) = \begin{cases} \text{DENIED}, & \text{if } \exists r \in \mathcal{R}{\text{active}} : r.\text{effect} = \text{DENY} \land \text{Matches}(r, A, S) \ \text{PERMITTED}, & \text{if } \exists r \in \mathcal{R}(r, A, S) \ \text{DENIED}, & \text{otherwise (Default Closed)} \end{cases}$$}} : r.\text{effect} = \text{ALLOW} \land \text{Matches
flowchart TD
Req["Access Request (User, Action, Scope)"] --> Load["Load Active Role Rules"]
Load --> Step1{"Any Matching DENY Rule?"}
Step1 -->|Yes| Deny["DECISION: DENIED<br/>(Deny Dominance)"]
Step1 -->|No| Step2{"Any Matching ALLOW Rule?<br/>(Direct or Inherited)"}
Step2 -->|Yes| Allow["DECISION: PERMITTED"]
Step2 -->|No| Default["DECISION: DENIED<br/>(Default Closed)"]
Invariant 1: Explicit Deny Dominance¶
A DENY rule always takes absolute precedence over any ALLOW rule, regardless of whether the ALLOW was declared at a more specific level.
Invariant 2: Container Inheritance¶
An ALLOW rule targeting datasource:retail_banking grants implicit permissions to all datasets under retail_banking, unless an explicit child rule declares a DENY.
Invariant 3: Implicit Traversal Visibility¶
A user possessing access to a child dataset (e.g., dataset:retail_banking.transactions) is granted implicit traversal visibility to the parent datasource (datasource:retail_banking) so the dataset can be located within the catalog navigation tree, without granting access to sibling tables.
3. SQL Security Firewall & Policy Enforcement¶
To prevent unauthorized data access or column leakage during conversational analytics and Text-to-SQL execution, VDA incorporates an active SQL Security Firewall:
flowchart TD
RawSQL["Generated / User SQL Query"] --> Firewall["SQL Security Firewall"]
Firewall --> Inspect{"Recursive Query Analysis"}
Inspect --> WildcardCheck["Wildcard Inspection (SELECT *, t.*)"]
Inspect --> ColumnCheck["Column Inspection (SELECT, WHERE, JOIN, GROUP BY)"]
Inspect --> SubqueryCheck["Subquery & CTE Inspection"]
WildcardCheck --> PolicyCheck{"Evaluate Against Role Permissions"}
ColumnCheck --> PolicyCheck
SubqueryCheck --> PolicyCheck
PolicyCheck -->|Restricted Column Detected| Reject["Access Denied (HTTP 403)<br/>Query Execution Blocked"]
PolicyCheck -->|Policy Compliant| Approved["Authorize Query Execution<br/>Forward to Datasource"]
In-Depth Query Security & Policy Enforcement¶
- Comprehensive Wildcard Defense: Prevents data leakage through wildcard projections (
SELECT *,SELECT t.*) on tables containing restricted or sensitive columns. - Deep Recursive Inspection: Thoroughly validates subqueries, Common Table Expressions (CTEs), and joined tables to prevent indirect column exfiltration.
- Zero-Trust Access Interception: Any query attempting to access, filter, or aggregate columns denied by the user's effective PBAC policy is immediately intercepted and rejected prior to database execution.
- Dynamic Masking & Redaction: In data preview and export workflows, columns subject to masking policies are sanitized at the database boundary before results leave the data layer.
4. Cryptographic Authentication & Token Security¶
- Session Tokens: Minted as cryptographically signed RSA-256 JWTs by Keycloak with short lifespans (default: 15 minutes) and automated refresh rotation.
- Personal & Agent Access Keys:
- Structured format:
vda_<32_byte_hex_token>. - Persisted in PostgreSQL exclusively as salted SHA-256 hashes. Plaintext tokens are never stored on disk.
- Role-bound tokens automatically reflect real-time permissions changes made in the PBAC administration console.