diff --git a/scenarios/04-view-bypass-mac/README.md b/scenarios/04-view-bypass-mac/README.md index 77ac5e3..41caeee 100755 --- a/scenarios/04-view-bypass-mac/README.md +++ b/scenarios/04-view-bypass-mac/README.md @@ -12,6 +12,7 @@ Before Oracle Deep Data Security, a legacy view can expose rows that should be p - `emma`: account owner. - `marvin`: account owner. +- `erik`: account owner. ## Where To Run The Commands @@ -49,15 +50,25 @@ sql "" @scenarios/04-view-bypass-mac/sql/02_identities.sql ``` -4. Query the legacy view: +4. Connect as `emma` and query both access paths: + + ```bash + sql 'emma/Welcome1_DDS!@ddslab_tunnel' + ``` ```sql + ALTER SESSION SET CURRENT_SCHEMA = ADMIN; + + SELECT account_id, account_name, owner_name, region, balance + FROM dds_mac_accounts + ORDER BY account_id; + SELECT account_id, account_name, owner_name, region, balance FROM dds_mac_accounts_view ORDER BY account_id; ``` -Expected result before protection: the view may show accounts owned by other users. +Expected result before protection: both direct table access and the legacy view may show accounts owned by other users. ## Step By Step - After, With Deep Data Security @@ -73,12 +84,13 @@ Expected result before protection: the view may show accounts owned by other use @scenarios/04-view-bypass-mac/sql/04_test_queries.sql ``` -3. Repeat the test by simulating `emma` and `marvin`. +3. Repeat the test by simulating `emma`, `marvin`, and `erik`. Expected result after protection: - The table returns only the authorized account. - The view returns the same authorized subset. +- `emma` sees `Account Alpha`, `marvin` sees `Account Beta`, and `erik` sees `Account Gamma`. - The alternate access path no longer works as a bypass. ## Optional Automated Execution diff --git a/scenarios/04-view-bypass-mac/WORKSHOP.md b/scenarios/04-view-bypass-mac/WORKSHOP.md index dfac80d..f58e576 100755 --- a/scenarios/04-view-bypass-mac/WORKSHOP.md +++ b/scenarios/04-view-bypass-mac/WORKSHOP.md @@ -21,6 +21,7 @@ This workshop demonstrates why access rules should be enforced on the protected | --- | --- | --- | | `emma` | Account owner | Only accounts owned by Emma. | | `marvin` | Account owner | Only accounts owned by Marvin. | +| `erik` | Account owner | Only accounts owned by Erik. | ## Before You Begin @@ -75,12 +76,43 @@ The script creates: ```sql CREATE END USER emma IDENTIFIED BY "Welcome1_DDS!"; CREATE END USER marvin IDENTIFIED BY "Welcome1_DDS!"; +CREATE END USER erik IDENTIFIED BY "Welcome1_DDS!"; CREATE DATA ROLE account_owner_role; ``` ## Lab 2 - Demonstrate The View Bypass Risk -### Task 2.1 - Query The Legacy View +### Task 2.1 - Connect As Emma Before DDS + +Exit the administrator session: + +```sql +exit +``` + +Connect as Emma: + +```bash +sql 'emma/Welcome1_DDS!@ddslab_tunnel' +``` + +Emma represents an account owner. Before DDS enforcement, she still has a broad legacy role, so this section demonstrates why view-based controls and object grants can be risky. + +### Task 2.2 - Query The Base Table Directly Before DDS + +```sql +ALTER SESSION SET CURRENT_SCHEMA = ADMIN; + +SELECT account_id, account_name, owner_name, region, balance +FROM dds_mac_accounts +ORDER BY account_id; +``` + +Expected result before DDS: Emma can see `Account Alpha`, `Account Beta`, and `Account Gamma`, even though only `Account Alpha` belongs to her. + +This is the direct table access path. + +### Task 2.3 - Query The Legacy View Before DDS ```sql SELECT account_id, account_name, owner_name, region, balance @@ -88,11 +120,34 @@ FROM dds_mac_accounts_view ORDER BY account_id; ``` -Expected result before DDS: the view may expose accounts belonging to multiple owners. +Expected result before DDS: the view also returns accounts owned by multiple users. + +This is the alternate access path. The important point is not that the view itself is bad; the risk is relying on a specific access path as the only security boundary. + +### Customer Message + +Before DDS, Emma can reach the same overexposed data through both paths: + +```text +Direct table query -> all accounts +Legacy view query -> all accounts +``` + +The business rule "Emma should only see Emma's account" is not being enforced at the protected data boundary yet. ## Lab 3 - Apply Oracle Deep Data Security -### Task 3.1 - Apply Data Grants +### Task 3.1 - Reconnect As ADMIN + +```sql +exit +``` + +```bash +sql admin@ddslab_tunnel +``` + +### Task 3.2 - Apply Data Grants ```sql @scenarios/04-view-bypass-mac/sql/03_data_grants.sql @@ -110,9 +165,17 @@ CREATE OR REPLACE DATA GRANT mac_account_owner This filters accounts to the authenticated owner. The script enables DDS on `DDS_MAC_ACCOUNTS`. +In this lab, the predicate compares the account owner with the active DDS end-user context: + +```sql +WHERE UPPER(owner_name) = ORA_END_USER_CONTEXT.username +``` + +That means Emma, Marvin, and Erik can run the same SQL, but the database returns different rows for each persona. + ## Lab 4 - Validate Table And View Access -### Task 4.1 - Test Emma +### Task 4.1 - Test Emma After DDS ```sql exit @@ -126,9 +189,18 @@ sql 'emma/Welcome1_DDS!@ddslab_tunnel' @scenarios/04-view-bypass-mac/sql/04_test_queries.sql ``` -Expected result: Emma sees only her authorized account from both table and view paths. +Expected result: Emma sees only `Account Alpha` from both table and view paths. -### Task 4.2 - Test Marvin +The same two access paths are tested again: + +```text +Direct table query -> only Account Alpha +Legacy view query -> only Account Alpha +``` + +The SQL did not become smarter. The database security boundary became mandatory. + +### Task 4.2 - Quick Validation With Marvin ```sql exit @@ -142,7 +214,35 @@ sql 'marvin/Welcome1_DDS!@ddslab_tunnel' @scenarios/04-view-bypass-mac/sql/04_test_queries.sql ``` -Expected result: Marvin sees only his authorized account. +Expected result: Marvin sees only `Account Beta` from both paths. + +### Task 4.3 - Quick Validation With Erik + +```sql +exit +``` + +```bash +sql 'erik/Welcome1_DDS!@ddslab_tunnel' +``` + +```sql +@scenarios/04-view-bypass-mac/sql/04_test_queries.sql +``` + +Expected result: Erik sees only `Account Gamma` from both paths. + +### Customer Message + +After DDS, the result is consistent regardless of the path: + +```text +Emma -> Account Alpha only +Marvin -> Account Beta only +Erik -> Account Gamma only +``` + +This shows the value of DDS versus relying only on view logic, application SQL, BI filters, or agent-generated SQL. ## Lab 5 - Clean Up @@ -165,7 +265,7 @@ exit | --- | --- | | `DDS_MAC_ACCOUNTS` | Protected base table. | | `DDS_MAC_ACCOUNTS_VIEW` | Legacy view used to demonstrate alternate access paths. | -| `END USER` | `emma`, `marvin`; account owner personas. | +| `END USER` | `emma`, `marvin`, `erik`; account owner personas. | | `DATA ROLE` | `account_owner_role`; owner authorization profile. | | `DATA GRANT` | Filters rows by `owner_name = ORA_END_USER_CONTEXT.username`. | | `SET USE DATA GRANTS ONLY` | Enforces DDS on the base table. | @@ -177,4 +277,3 @@ The trust chain is: **end-user identity -> account owner role -> owner data gran - Views are useful, but they should not be the only security boundary. - DDS protects the data regardless of the access path. - This reduces bypass risk from direct SQL, legacy views, and reporting tools. - diff --git a/scenarios/04-view-bypass-mac/sql/00_schema.sql b/scenarios/04-view-bypass-mac/sql/00_schema.sql index 771ce5b..7d62618 100755 --- a/scenarios/04-view-bypass-mac/sql/00_schema.sql +++ b/scenarios/04-view-bypass-mac/sql/00_schema.sql @@ -1,14 +1,28 @@ WHENEVER SQLERROR EXIT SQL.SQLCODE -CREATE TABLE dds_mac_accounts ( - account_id NUMBER PRIMARY KEY, - account_name VARCHAR2(100), - owner_name VARCHAR2(60), - region VARCHAR2(30), - balance NUMBER(12,2) -); - -CREATE VIEW dds_mac_accounts_view AS -SELECT account_id, account_name, owner_name, region, balance -FROM dds_mac_accounts; +BEGIN + EXECUTE IMMEDIATE q'[ + CREATE TABLE dds_mac_accounts ( + account_id NUMBER PRIMARY KEY, + account_name VARCHAR2(100), + owner_name VARCHAR2(60), + region VARCHAR2(30), + balance NUMBER(12,2) + ) + ]'; +EXCEPTION + WHEN OTHERS THEN + IF SQLCODE != -955 THEN + RAISE; + END IF; +END; +/ +BEGIN + EXECUTE IMMEDIATE q'[ + CREATE OR REPLACE VIEW dds_mac_accounts_view AS + SELECT account_id, account_name, owner_name, region, balance + FROM dds_mac_accounts + ]'; +END; +/ diff --git a/scenarios/04-view-bypass-mac/sql/01_seed_data.sql b/scenarios/04-view-bypass-mac/sql/01_seed_data.sql index b1030db..00fcfa2 100755 --- a/scenarios/04-view-bypass-mac/sql/01_seed_data.sql +++ b/scenarios/04-view-bypass-mac/sql/01_seed_data.sql @@ -1,5 +1,7 @@ WHENEVER SQLERROR EXIT SQL.SQLCODE +DELETE FROM dds_mac_accounts; + INSERT INTO dds_mac_accounts VALUES (1, 'Account Alpha', 'emma', 'LATAM', 100000); INSERT INTO dds_mac_accounts VALUES (2, 'Account Beta', 'marvin', 'LATAM', 250000); INSERT INTO dds_mac_accounts VALUES (3, 'Account Gamma', 'erik', 'EMEA', 900000); diff --git a/scenarios/04-view-bypass-mac/sql/02_identities.sql b/scenarios/04-view-bypass-mac/sql/02_identities.sql index fb19fb9..90ca699 100755 --- a/scenarios/04-view-bypass-mac/sql/02_identities.sql +++ b/scenarios/04-view-bypass-mac/sql/02_identities.sql @@ -2,6 +2,7 @@ WHENEVER SQLERROR EXIT SQL.SQLCODE CREATE END USER emma IDENTIFIED BY "Welcome1_DDS!"; CREATE END USER marvin IDENTIFIED BY "Welcome1_DDS!"; +CREATE END USER erik IDENTIFIED BY "Welcome1_DDS!"; CREATE DATA ROLE account_owner_role; @@ -9,5 +10,13 @@ CREATE ROLE mac_session_role; GRANT CREATE SESSION TO mac_session_role; GRANT mac_session_role TO account_owner_role; +-- Vulnerable baseline: this broad role simulates legacy direct table and view +-- access before DDS mandatory enforcement is enabled. +CREATE ROLE mac_legacy_broad_access_role; +GRANT SELECT ON dds_mac_accounts TO mac_legacy_broad_access_role; +GRANT SELECT ON dds_mac_accounts_view TO mac_legacy_broad_access_role; +GRANT mac_legacy_broad_access_role TO account_owner_role; + GRANT DATA ROLE account_owner_role TO emma; GRANT DATA ROLE account_owner_role TO marvin; +GRANT DATA ROLE account_owner_role TO erik; diff --git a/scenarios/04-view-bypass-mac/sql/03_data_grants.sql b/scenarios/04-view-bypass-mac/sql/03_data_grants.sql index cb0ecdd..f009eb5 100755 --- a/scenarios/04-view-bypass-mac/sql/03_data_grants.sql +++ b/scenarios/04-view-bypass-mac/sql/03_data_grants.sql @@ -3,7 +3,7 @@ WHENEVER SQLERROR EXIT SQL.SQLCODE CREATE OR REPLACE DATA GRANT mac_account_owner AS SELECT ON dds_mac_accounts - WHERE owner_name = ORA_END_USER_CONTEXT.username + WHERE UPPER(owner_name) = ORA_END_USER_CONTEXT.username TO account_owner_role; CREATE OR REPLACE DATA GRANT mac_accounts_view_broad diff --git a/scenarios/04-view-bypass-mac/sql/99_reset.sql b/scenarios/04-view-bypass-mac/sql/99_reset.sql index 62fe4e5..9a82133 100755 --- a/scenarios/04-view-bypass-mac/sql/99_reset.sql +++ b/scenarios/04-view-bypass-mac/sql/99_reset.sql @@ -12,7 +12,11 @@ BEGIN EXECUTE IMMEDIATE 'DROP DATA ROLE account_owner_role'; EXCEPTION WHEN OTHE / BEGIN EXECUTE IMMEDIATE 'DROP ROLE mac_session_role'; EXCEPTION WHEN OTHERS THEN NULL; END; / +BEGIN EXECUTE IMMEDIATE 'DROP ROLE mac_legacy_broad_access_role'; EXCEPTION WHEN OTHERS THEN NULL; END; +/ BEGIN EXECUTE IMMEDIATE 'DROP END USER emma'; EXCEPTION WHEN OTHERS THEN NULL; END; / BEGIN EXECUTE IMMEDIATE 'DROP END USER marvin'; EXCEPTION WHEN OTHERS THEN NULL; END; / +BEGIN EXECUTE IMMEDIATE 'DROP END USER erik'; EXCEPTION WHEN OTHERS THEN NULL; END; +/