Improve RAG vector classified docs scenario
Some checks failed
Repo Quality / structure (push) Has been cancelled
Some checks failed
Repo Quality / structure (push) Has been cancelled
This commit is contained in:
@@ -17,35 +17,32 @@ Before Oracle Deep Data Security, vector search can retrieve confidential HR, le
|
||||
|
||||
## Where To Run The Commands
|
||||
|
||||
Run commands from the repository root:
|
||||
|
||||
```powershell
|
||||
cd C:\Users\rodrigo\Documents\Codex\oracle-deep-data-security-lab
|
||||
```
|
||||
|
||||
Connect to the database with SQLcl or SQL*Plus:
|
||||
Run SQL scripts from the repository root. On Linux/macOS/WSL:
|
||||
|
||||
```bash
|
||||
sql "<connect_string>"
|
||||
cd ~/DEEP-DATA-SECURITY/oracle-deep-data-security-lab
|
||||
export TNS_ADMIN=~/DEEP-DATA-SECURITY/wallet-ddslab
|
||||
```
|
||||
|
||||
Connect as the lab administrator:
|
||||
|
||||
```bash
|
||||
sql admin@ddslab_tunnel
|
||||
```
|
||||
|
||||
This scenario uses the `VECTOR` type, `TO_VECTOR`, and `VECTOR_DISTANCE`. Use a database version with Oracle AI Vector Search support.
|
||||
|
||||
SQLcl note: when running a script with `@file.sql`, press Enter once and wait for the output. Do not type `/` afterward, because `/` reruns the last command in the SQLcl buffer.
|
||||
|
||||
## Step By Step - Before, Vulnerable Environment
|
||||
|
||||
1. Connect to the database:
|
||||
|
||||
```bash
|
||||
sql "<connect_string>"
|
||||
```
|
||||
|
||||
2. Reset the scenario:
|
||||
1. Reset the scenario as `ADMIN`:
|
||||
|
||||
```sql
|
||||
@scenarios/06-rag-vector-classified-docs/sql/99_reset.sql
|
||||
```
|
||||
|
||||
3. Create the chunk table, simple embeddings, and personas:
|
||||
2. Create the chunk table, seed classified documents, and create personas:
|
||||
|
||||
```sql
|
||||
@scenarios/06-rag-vector-classified-docs/sql/00_schema.sql
|
||||
@@ -53,35 +50,53 @@ This scenario uses the `VECTOR` type, `TO_VECTOR`, and `VECTOR_DISTANCE`. Use a
|
||||
@scenarios/06-rag-vector-classified-docs/sql/02_identities.sql
|
||||
```
|
||||
|
||||
3. Show all available chunks as `ADMIN`:
|
||||
|
||||
```sql
|
||||
SELECT chunk_id, document_title, department, classification, chunk_text
|
||||
FROM dds_rag_chunks
|
||||
ORDER BY chunk_id;
|
||||
```
|
||||
|
||||
4. Simulate the RAG question:
|
||||
|
||||
```text
|
||||
Summarize critical documents about renewals, people, and legal risks.
|
||||
```
|
||||
|
||||
5. Run the vector search:
|
||||
5. Connect as `nina`, a regular employee:
|
||||
|
||||
```bash
|
||||
sql 'nina/Welcome1_DDS!@ddslab_tunnel'
|
||||
```
|
||||
|
||||
6. Run the vector search before DDS:
|
||||
|
||||
```sql
|
||||
@scenarios/06-rag-vector-classified-docs/sql/04_test_queries.sql
|
||||
```
|
||||
|
||||
Expected result before protection: retrieval may return `HR_CONFIDENTIAL`, `LEGAL_CONFIDENTIAL`, and `EXECUTIVE_CONFIDENTIAL` chunks.
|
||||
Expected result before protection: the retrieval may return `HR_CONFIDENTIAL`, `LEGAL_CONFIDENTIAL`, and `EXECUTIVE_CONFIDENTIAL` chunks to a regular employee because the legacy retrieval role is broad.
|
||||
|
||||
## Step By Step - After, With Deep Data Security
|
||||
|
||||
1. Apply data grants by classification:
|
||||
1. Reconnect as `ADMIN` and apply data grants by classification:
|
||||
|
||||
```sql
|
||||
@scenarios/06-rag-vector-classified-docs/sql/03_data_grants.sql
|
||||
```
|
||||
|
||||
2. Run the same vector search again:
|
||||
2. Connect as `nina` and run the same vector search:
|
||||
|
||||
```bash
|
||||
sql 'nina/Welcome1_DDS!@ddslab_tunnel'
|
||||
```
|
||||
|
||||
```sql
|
||||
@scenarios/06-rag-vector-classified-docs/sql/04_test_queries.sql
|
||||
```
|
||||
|
||||
3. Repeat the demo by simulating `nina`, `heitor`, `sofia`, and `carlos`.
|
||||
3. Repeat the same test as `heitor`, `sofia`, and `carlos`.
|
||||
|
||||
Expected result after protection:
|
||||
|
||||
@@ -108,4 +123,3 @@ Linux/macOS:
|
||||
## Demo Details
|
||||
|
||||
See the complete walkthrough, evidence, and official references in [RUNBOOK.md](RUNBOOK.md).
|
||||
|
||||
|
||||
@@ -18,13 +18,27 @@ Show that a RAG agent retrieves only authorized chunks/documents before sending
|
||||
|
||||
## Before - Vulnerable Environment
|
||||
|
||||
1. Reset the scenario:
|
||||
1. From the repository root, connect as `ADMIN`:
|
||||
|
||||
```bash
|
||||
cd ~/DEEP-DATA-SECURITY/oracle-deep-data-security-lab
|
||||
export TNS_ADMIN=~/DEEP-DATA-SECURITY/wallet-ddslab
|
||||
sql admin@ddslab_tunnel
|
||||
```
|
||||
|
||||
Presenter note: `ADMIN` prepares the classified chunks and security personas.
|
||||
|
||||
SQLcl note: after running a script with `@file.sql`, do not type `/`. The slash reruns the last command in the SQLcl buffer and can make a successful command look like an error.
|
||||
|
||||
2. Reset the scenario:
|
||||
|
||||
```sql
|
||||
@scenarios/06-rag-vector-classified-docs/sql/99_reset.sql
|
||||
```
|
||||
|
||||
2. Create chunks and personas without applying data grants:
|
||||
Presenter note: this removes prior Data Grants, roles, users, and test data.
|
||||
|
||||
3. Create chunks and personas without applying data grants:
|
||||
|
||||
```sql
|
||||
@scenarios/06-rag-vector-classified-docs/sql/00_schema.sql
|
||||
@@ -32,18 +46,44 @@ Show that a RAG agent retrieves only authorized chunks/documents before sending
|
||||
@scenarios/06-rag-vector-classified-docs/sql/02_identities.sql
|
||||
```
|
||||
|
||||
3. Simulate the RAG question:
|
||||
Presenter note: `rag_legacy_retrieval_role` simulates a broad RAG retrieval layer before DDS is enforced.
|
||||
|
||||
4. Show every chunk and its classification:
|
||||
|
||||
```sql
|
||||
SELECT chunk_id, document_title, department, classification, chunk_text
|
||||
FROM dds_rag_chunks
|
||||
ORDER BY chunk_id;
|
||||
```
|
||||
|
||||
Presenter note: explain that confidential chunks should not be sent to the LLM for every user.
|
||||
|
||||
5. Simulate the RAG question:
|
||||
|
||||
```text
|
||||
Summarize critical documents about renewals, people, and legal risks.
|
||||
```
|
||||
|
||||
4. Run the vector search:
|
||||
6. Exit and connect as Nina, a regular employee:
|
||||
|
||||
```sql
|
||||
exit
|
||||
```
|
||||
|
||||
```bash
|
||||
sql 'nina/Welcome1_DDS!@ddslab_tunnel'
|
||||
```
|
||||
|
||||
Presenter note: Nina represents a regular employee using an internal copilot.
|
||||
|
||||
7. Run the vector search before DDS:
|
||||
|
||||
```sql
|
||||
@scenarios/06-rag-vector-classified-docs/sql/04_test_queries.sql
|
||||
```
|
||||
|
||||
Presenter note: before DDS, a broad retrieval path can place HR, legal, or executive confidential chunks in the LLM context.
|
||||
|
||||
## Expected Result Before
|
||||
|
||||
- The search may retrieve `HR_CONFIDENTIAL`, `LEGAL_CONFIDENTIAL`, and `EXECUTIVE_CONFIDENTIAL` chunks.
|
||||
@@ -51,18 +91,50 @@ Show that a RAG agent retrieves only authorized chunks/documents before sending
|
||||
|
||||
## After - Applying Deep Data Security
|
||||
|
||||
1. Apply data grants by classification:
|
||||
1. Exit and reconnect as `ADMIN`:
|
||||
|
||||
```sql
|
||||
exit
|
||||
```
|
||||
|
||||
```bash
|
||||
sql admin@ddslab_tunnel
|
||||
```
|
||||
|
||||
2. Apply data grants by classification:
|
||||
|
||||
```sql
|
||||
@scenarios/06-rag-vector-classified-docs/sql/03_data_grants.sql
|
||||
```
|
||||
|
||||
2. Run the same search as `nina`, `heitor`, `sofia`, and `carlos`:
|
||||
Presenter note: the database now filters chunks before the LLM receives any context.
|
||||
|
||||
3. Test Nina after DDS:
|
||||
|
||||
```sql
|
||||
exit
|
||||
```
|
||||
|
||||
```bash
|
||||
sql 'nina/Welcome1_DDS!@ddslab_tunnel'
|
||||
```
|
||||
|
||||
```sql
|
||||
@scenarios/06-rag-vector-classified-docs/sql/04_test_queries.sql
|
||||
```
|
||||
|
||||
Presenter note: Nina should retrieve only `PUBLIC` and `INTERNAL` chunks.
|
||||
|
||||
4. Repeat the same search as HR, legal, and executive personas:
|
||||
|
||||
```bash
|
||||
sql 'heitor/Welcome1_DDS!@ddslab_tunnel'
|
||||
sql 'sofia/Welcome1_DDS!@ddslab_tunnel'
|
||||
sql 'carlos/Welcome1_DDS!@ddslab_tunnel'
|
||||
```
|
||||
|
||||
Presenter note: each persona receives only the chunk classifications authorized for that business role.
|
||||
|
||||
## Expected Result After
|
||||
|
||||
- `nina` retrieves only `PUBLIC` and `INTERNAL` chunks.
|
||||
@@ -83,4 +155,3 @@ Show that a RAG agent retrieves only authorized chunks/documents before sending
|
||||
- Create Data Grants: https://docs.oracle.com/en/database/oracle/oracle-database/26/ddscg/create-data-grants.html
|
||||
- TO_VECTOR SQL Reference: https://docs.oracle.com/en/database/oracle/oracle-database/26/sqlrf/to_vector.html
|
||||
- VECTOR operations in PL/SQL: https://docs.oracle.com/en/database/oracle/oracle-database/26/lnpls/sql-data-types.html
|
||||
|
||||
|
||||
@@ -1,8 +1,14 @@
|
||||
# Expected Results
|
||||
|
||||
## Before Oracle Deep Data Security
|
||||
|
||||
- A broad legacy retrieval role can return `HR_CONFIDENTIAL`, `LEGAL_CONFIDENTIAL`, and `EXECUTIVE_CONFIDENTIAL` chunks.
|
||||
- A regular employee such as `nina` may receive sensitive chunks in the RAG context before the LLM generates an answer.
|
||||
|
||||
## After Oracle Deep Data Security
|
||||
|
||||
- `nina` retrieves only `PUBLIC` and `INTERNAL` chunks.
|
||||
- `heitor` retrieves `HR_CONFIDENTIAL` plus public/internal chunks.
|
||||
- `sofia` retrieves `LEGAL_CONFIDENTIAL` plus public/internal chunks.
|
||||
- `carlos` retrieves all classifications.
|
||||
- `carlos` retrieves all classifications through the executive role.
|
||||
- The RAG layer receives only chunks authorized by the database policy.
|
||||
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
WHENEVER SQLERROR EXIT SQL.SQLCODE
|
||||
|
||||
BEGIN
|
||||
EXECUTE IMMEDIATE q'[
|
||||
CREATE TABLE dds_rag_chunks (
|
||||
chunk_id NUMBER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
|
||||
document_title VARCHAR2(160) NOT NULL,
|
||||
@@ -7,5 +9,12 @@ CREATE TABLE dds_rag_chunks (
|
||||
classification VARCHAR2(30) NOT NULL,
|
||||
chunk_text VARCHAR2(1000) NOT NULL,
|
||||
embedding VECTOR(3, FLOAT32)
|
||||
);
|
||||
|
||||
)
|
||||
]';
|
||||
EXCEPTION
|
||||
WHEN OTHERS THEN
|
||||
IF SQLCODE != -955 THEN
|
||||
RAISE;
|
||||
END IF;
|
||||
END;
|
||||
/
|
||||
|
||||
@@ -1,19 +1,22 @@
|
||||
WHENEVER SQLERROR EXIT SQL.SQLCODE
|
||||
SET DEFINE OFF
|
||||
|
||||
INSERT INTO dds_rag_chunks (document_title, department, classification, chunk_text, embedding)
|
||||
VALUES ('Benefits Policy', 'HR', 'INTERNAL', 'General benefits policy available to employees.', TO_VECTOR('[0.10,0.20,0.30]'));
|
||||
DELETE FROM dds_rag_chunks;
|
||||
|
||||
INSERT INTO dds_rag_chunks (document_title, department, classification, chunk_text, embedding)
|
||||
VALUES ('Executive Compensation Plan', 'HR', 'HR_CONFIDENTIAL', 'Compensation calibration for executives and retention risks.', TO_VECTOR('[0.11,0.21,0.31]'));
|
||||
INSERT INTO dds_rag_chunks (chunk_id, document_title, department, classification, chunk_text, embedding)
|
||||
VALUES (1, 'Benefits Policy', 'HR', 'INTERNAL', 'General benefits policy available to employees.', TO_VECTOR('[0.10,0.20,0.30]'));
|
||||
|
||||
INSERT INTO dds_rag_chunks (document_title, department, classification, chunk_text, embedding)
|
||||
VALUES ('Contract Renewal Risk', 'LEGAL', 'LEGAL_CONFIDENTIAL', 'Legal risk on renewal clauses for strategic accounts.', TO_VECTOR('[0.80,0.10,0.20]'));
|
||||
INSERT INTO dds_rag_chunks (chunk_id, document_title, department, classification, chunk_text, embedding)
|
||||
VALUES (2, 'Executive Compensation Plan', 'HR', 'HR_CONFIDENTIAL', 'Compensation calibration for executives and retention risks.', TO_VECTOR('[0.11,0.21,0.31]'));
|
||||
|
||||
INSERT INTO dds_rag_chunks (document_title, department, classification, chunk_text, embedding)
|
||||
VALUES ('Company Travel Guide', 'GENERAL', 'PUBLIC', 'Public travel and expense guidance for all employees.', TO_VECTOR('[0.20,0.70,0.10]'));
|
||||
INSERT INTO dds_rag_chunks (chunk_id, document_title, department, classification, chunk_text, embedding)
|
||||
VALUES (3, 'Contract Renewal Risk', 'LEGAL', 'LEGAL_CONFIDENTIAL', 'Legal risk on renewal clauses for strategic accounts.', TO_VECTOR('[0.80,0.10,0.20]'));
|
||||
|
||||
INSERT INTO dds_rag_chunks (document_title, department, classification, chunk_text, embedding)
|
||||
VALUES ('Board M&A Briefing', 'EXEC', 'EXECUTIVE_CONFIDENTIAL', 'Potential acquisition targets and board-level financial exposure.', TO_VECTOR('[0.90,0.20,0.40]'));
|
||||
INSERT INTO dds_rag_chunks (chunk_id, document_title, department, classification, chunk_text, embedding)
|
||||
VALUES (4, 'Company Travel Guide', 'GENERAL', 'PUBLIC', 'Public travel and expense guidance for all employees.', TO_VECTOR('[0.20,0.70,0.10]'));
|
||||
|
||||
INSERT INTO dds_rag_chunks (chunk_id, document_title, department, classification, chunk_text, embedding)
|
||||
VALUES (5, 'Board M&A Briefing', 'EXEC', 'EXECUTIVE_CONFIDENTIAL', 'Potential acquisition targets and board-level financial exposure.', TO_VECTOR('[0.90,0.20,0.40]'));
|
||||
|
||||
COMMIT;
|
||||
|
||||
SET DEFINE ON
|
||||
|
||||
@@ -17,6 +17,15 @@ GRANT rag_session_role TO rag_hr_role;
|
||||
GRANT rag_session_role TO rag_legal_role;
|
||||
GRANT rag_session_role TO rag_exec_role;
|
||||
|
||||
-- Vulnerable baseline: this broad role simulates a RAG retrieval layer that can
|
||||
-- query every chunk before DDS is enforced.
|
||||
CREATE ROLE rag_legacy_retrieval_role;
|
||||
GRANT SELECT ON dds_rag_chunks TO rag_legacy_retrieval_role;
|
||||
GRANT rag_legacy_retrieval_role TO rag_employee_role;
|
||||
GRANT rag_legacy_retrieval_role TO rag_hr_role;
|
||||
GRANT rag_legacy_retrieval_role TO rag_legal_role;
|
||||
GRANT rag_legacy_retrieval_role TO rag_exec_role;
|
||||
|
||||
GRANT DATA ROLE rag_employee_role TO nina;
|
||||
GRANT DATA ROLE rag_hr_role TO heitor;
|
||||
GRANT DATA ROLE rag_legal_role TO sofia;
|
||||
|
||||
@@ -20,6 +20,8 @@ BEGIN EXECUTE IMMEDIATE 'DROP DATA ROLE rag_exec_role'; EXCEPTION WHEN OTHERS TH
|
||||
/
|
||||
BEGIN EXECUTE IMMEDIATE 'DROP ROLE rag_session_role'; EXCEPTION WHEN OTHERS THEN NULL; END;
|
||||
/
|
||||
BEGIN EXECUTE IMMEDIATE 'DROP ROLE rag_legacy_retrieval_role'; EXCEPTION WHEN OTHERS THEN NULL; END;
|
||||
/
|
||||
BEGIN EXECUTE IMMEDIATE 'DROP END USER nina'; EXCEPTION WHEN OTHERS THEN NULL; END;
|
||||
/
|
||||
BEGIN EXECUTE IMMEDIATE 'DROP END USER heitor'; EXCEPTION WHEN OTHERS THEN NULL; END;
|
||||
|
||||
Reference in New Issue
Block a user