15 KiB
Executable File
Workshop - Secure RAG Retrieval With Oracle Deep Data Security
About This Workshop
This workshop demonstrates how Oracle Deep Data Security can protect a Retrieval-Augmented Generation (RAG) workflow by filtering vector search results before retrieved chunks are sent to an LLM.
The lab simulates an internal enterprise copilot that searches classified document chunks stored in Oracle AI Database. Without database-enforced authorization, a regular employee can retrieve HR, legal, and executive confidential chunks. With Oracle Deep Data Security, the same vector search returns only the chunks authorized for the end-user persona.
Workshop Goals
By the end of this workshop, you will be able to:
- Explain why RAG security must be enforced before context reaches the LLM.
- Create a table with classified document chunks and vector embeddings.
- Simulate a vulnerable vector search that over-retrieves sensitive content.
- Apply Oracle Deep Data Security data grants by document classification.
- Validate that each user persona retrieves only authorized chunks.
Estimated Time
30 to 45 minutes.
Audience
- Product managers and solution engineers evaluating secure enterprise AI.
- Database security architects.
- OCI and Oracle Database consultants.
- Application teams building RAG, copilots, AI agents, or semantic search.
Scenario Summary
The company has an internal copilot that answers questions using RAG. The copilot retrieves document chunks by semantic similarity using vector search.
The data includes five document chunks:
| Classification | Example Document | Who Should See It |
|---|---|---|
PUBLIC |
Company Travel Guide | Everyone |
INTERNAL |
Benefits Policy | Employees |
HR_CONFIDENTIAL |
Executive Compensation Plan | HR |
LEGAL_CONFIDENTIAL |
Contract Renewal Risk | Legal |
EXECUTIVE_CONFIDENTIAL |
Board M&A Briefing | Executives |
The lab uses four personas:
| Persona | Business Role | Expected Access After DDS |
|---|---|---|
nina |
Regular employee | PUBLIC, INTERNAL |
heitor |
HR user | PUBLIC, INTERNAL, HR_CONFIDENTIAL |
sofia |
Legal user | PUBLIC, INTERNAL, LEGAL_CONFIDENTIAL |
carlos |
Executive user | All classifications |
Architecture Flow
User question
|
v
Internal copilot / RAG service
|
v
Vector search in Oracle AI Database
|
v
Oracle Deep Data Security filters rows by persona and classification
|
v
Only authorized chunks are sent to the LLM
Prerequisites
- Oracle AI Database with support for
VECTOR,TO_VECTOR, andVECTOR_DISTANCE. - Oracle Deep Data Security available in the database.
- SQLcl configured to connect to the lab Autonomous Database.
- A working wallet and
TNS_ADMINenvironment variable. - The lab repository synchronized to your WSL or Linux/macOS environment.
Before You Begin
Run all commands from the repository root:
cd ~/DEEP-DATA-SECURITY/oracle-deep-data-security-lab
export TNS_ADMIN=~/DEEP-DATA-SECURITY/wallet-ddslab
Connect as the lab administrator:
sql admin@ddslab_tunnel
SQLcl note: when you run a script with @file.sql, press Enter once and wait for the output. Do not type / afterward; / reruns the last command in the SQLcl buffer.
Lab 1 - Prepare The Environment
Task 1.1 - Reset The Scenario
Run:
@scenarios/06-rag-vector-classified-docs/sql/99_reset.sql
This removes previous users, data roles, data grants, and test tables.
Task 1.2 - Create The Chunk Table
Run:
@scenarios/06-rag-vector-classified-docs/sql/00_schema.sql
This creates DDS_RAG_CHUNKS, which stores document chunks, classification labels, text, and vector embeddings.
The table created by this task has the following shape:
| Column | Example Value | Purpose |
|---|---|---|
CHUNK_ID |
3 |
Unique identifier for the retrieved chunk. |
DOCUMENT_TITLE |
Contract Renewal Risk |
Human-readable source document title. |
DEPARTMENT |
LEGAL |
Business owner or source department. |
CLASSIFICATION |
LEGAL_CONFIDENTIAL |
Security label used by DDS to filter access. |
CHUNK_TEXT |
Legal risk on renewal clauses... |
Text that could be sent to the LLM as RAG context. |
EMBEDDING |
[0.80,0.10,0.20] |
Vector representation used for semantic similarity search. |
In customer terms: this table is the RAG knowledge base. The sensitive part is not only the document title, but the text chunk that may be sent to the model.
Task 1.3 - Load Sample Classified Chunks
Run:
@scenarios/06-rag-vector-classified-docs/sql/01_seed_data.sql
This loads public, internal, HR confidential, legal confidential, and executive confidential content.
Examples inserted by this task:
| Chunk | Classification | Example Text |
|---|---|---|
Benefits Policy |
INTERNAL |
General benefits policy available to employees. |
Executive Compensation Plan |
HR_CONFIDENTIAL |
Compensation calibration for executives and retention risks. |
Contract Renewal Risk |
LEGAL_CONFIDENTIAL |
Legal risk on renewal clauses for strategic accounts. |
Company Travel Guide |
PUBLIC |
Public travel and expense guidance for all employees. |
Board M&A Briefing |
EXECUTIVE_CONFIDENTIAL |
Potential acquisition targets and board-level financial exposure. |
The important point for the demo is that these chunks live in the same vector table. DDS lets us avoid creating separate vector stores for each audience.
Task 1.4 - Create Personas And Baseline Access
Run:
@scenarios/06-rag-vector-classified-docs/sql/02_identities.sql
This creates the end users, data roles, and a broad legacy retrieval role used only to demonstrate the vulnerable "before" state.
The personas and roles are created in 02_identities.sql.
First, the lab creates four DDS end users:
CREATE END USER nina IDENTIFIED BY "Welcome1_DDS!";
CREATE END USER heitor IDENTIFIED BY "Welcome1_DDS!";
CREATE END USER sofia IDENTIFIED BY "Welcome1_DDS!";
CREATE END USER carlos IDENTIFIED BY "Welcome1_DDS!";
These are lightweight end-user identities used by DDS to evaluate who is asking the RAG question.
Next, the lab creates one data role for each business profile:
CREATE DATA ROLE rag_employee_role;
CREATE DATA ROLE rag_hr_role;
CREATE DATA ROLE rag_legal_role;
CREATE DATA ROLE rag_exec_role;
These data roles are the authorization profiles used later by the Data Grants.
The lab also creates a normal database role that allows the DDS end users to open SQLcl sessions during the demo:
CREATE ROLE rag_session_role;
GRANT CREATE SESSION TO rag_session_role;
GRANT rag_session_role TO rag_employee_role;
GRANT rag_session_role TO rag_hr_role;
GRANT rag_session_role TO rag_legal_role;
GRANT rag_session_role TO rag_exec_role;
This is a lab convenience. In a real application, the connection pool would usually be maintained by a technical application account while the application propagates the end-user security context.
To demonstrate the vulnerable state before DDS, the lab creates a broad legacy retrieval role:
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;
This role simulates an initial RAG implementation where the retrieval service can query the entire vector table. It is intentionally broad so the "before" demo can show over-retrieval.
Finally, each end user receives the appropriate data 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;
GRANT DATA ROLE rag_exec_role TO carlos;
At this point, the identities exist, but DDS enforcement is not enabled yet. That means the broad legacy retrieval role still allows confidential chunks to appear in Nina's vector search results.
Task 1.5 - Review The Classified Corpus
Run:
SELECT chunk_id, document_title, department, classification, chunk_text
FROM dds_rag_chunks
ORDER BY chunk_id;
Expected result: five chunks with different classifications.
Lab 2 - Demonstrate Vulnerable RAG Retrieval
Task 2.1 - Connect As Nina
Exit the administrator session:
exit
Connect as Nina:
sql 'nina/Welcome1_DDS!@ddslab_tunnel'
Nina represents a regular employee using an internal copilot.
Task 2.2 - Run The RAG Retrieval Query Before DDS
Run:
@scenarios/06-rag-vector-classified-docs/sql/04_test_queries.sql
The simulated RAG question is:
Summarize critical documents about renewals, people, and legal risks.
In a real RAG application, the copilot would transform this question into an embedding and run a similarity search. In this lab, we use a fixed example vector to keep the demo repeatable.
The SQL executed by Nina is:
ALTER SESSION SET CURRENT_SCHEMA = ADMIN;
SELECT chunk_id,
document_title,
department,
classification,
chunk_text,
VECTOR_DISTANCE(embedding, TO_VECTOR('[0.85,0.15,0.25]'), COSINE) AS distance
FROM dds_rag_chunks
ORDER BY distance
FETCH FIRST 5 ROWS ONLY;
The VECTOR_DISTANCE function ranks chunks by semantic proximity to the question embedding. Before DDS, this ranking can return sensitive chunks even when the user is a regular employee.
Expected result before protection: Nina may retrieve sensitive chunks such as:
HR_CONFIDENTIALLEGAL_CONFIDENTIALEXECUTIVE_CONFIDENTIAL
Customer Message
Similarity search alone does not understand business authorization. If the retrieval layer returns confidential chunks, the LLM may receive sensitive context before it generates an answer.
Lab 3 - Apply Oracle Deep Data Security
Task 3.1 - Reconnect As ADMIN
Exit Nina's session:
exit
Connect as administrator:
sql admin@ddslab_tunnel
Task 3.2 - Apply Data Grants
Run:
@scenarios/06-rag-vector-classified-docs/sql/03_data_grants.sql
This applies classification-based data grants:
- Employee role:
PUBLIC,INTERNAL - HR role:
PUBLIC,INTERNAL,HR_CONFIDENTIAL - Legal role:
PUBLIC,INTERNAL,LEGAL_CONFIDENTIAL - Executive role: all classifications
The grants applied by the script are:
CREATE OR REPLACE DATA GRANT rag_public_internal_docs
AS SELECT (chunk_id, document_title, department, classification, chunk_text, embedding)
ON dds_rag_chunks
WHERE classification IN ('PUBLIC', 'INTERNAL')
TO rag_employee_role;
This is Nina's rule. It allows regular employees to retrieve only public and internal chunks. Even if the vector search finds confidential chunks as semantically relevant, DDS removes them from Nina's result set.
CREATE OR REPLACE DATA GRANT rag_hr_docs
AS SELECT
ON dds_rag_chunks
WHERE classification IN ('PUBLIC', 'INTERNAL', 'HR_CONFIDENTIAL')
TO rag_hr_role;
This is Heitor's rule. HR can retrieve regular employee content plus HR confidential chunks, such as compensation or people-risk material.
CREATE OR REPLACE DATA GRANT rag_legal_docs
AS SELECT
ON dds_rag_chunks
WHERE classification IN ('PUBLIC', 'INTERNAL', 'LEGAL_CONFIDENTIAL')
TO rag_legal_role;
This is Sofia's rule. Legal can retrieve public/internal content plus legal confidential chunks, such as renewal risks and contractual exposure.
CREATE OR REPLACE DATA GRANT rag_exec_docs
AS SELECT
ON dds_rag_chunks
TO rag_exec_role;
This is Carlos's rule. Executives can retrieve all classifications, including board-level and strategic content.
Finally, the script enables DDS enforcement on the table:
BEGIN
EXECUTE IMMEDIATE 'SET USE DATA GRANTS ONLY ON dds_rag_chunks ENABLED';
END;
/
This is the key DDS behavior: direct table privileges no longer decide the final result by themselves. The database returns only the rows and columns allowed by the active data grants for the end-user persona.
Customer Message
Oracle Deep Data Security filters the rows returned by vector search before the RAG layer sends context to the LLM.
Lab 4 - Validate Persona-Based Retrieval
Task 4.1 - Validate Nina
Connect as Nina:
exit
sql 'nina/Welcome1_DDS!@ddslab_tunnel'
Run:
@scenarios/06-rag-vector-classified-docs/sql/04_test_queries.sql
Expected result: Nina retrieves only PUBLIC and INTERNAL chunks.
Task 4.2 - Validate Heitor
Connect as Heitor:
exit
sql 'heitor/Welcome1_DDS!@ddslab_tunnel'
Run:
@scenarios/06-rag-vector-classified-docs/sql/04_test_queries.sql
Expected result: Heitor retrieves public/internal chunks plus HR_CONFIDENTIAL.
Task 4.3 - Validate Sofia
Connect as Sofia:
exit
sql 'sofia/Welcome1_DDS!@ddslab_tunnel'
Run:
@scenarios/06-rag-vector-classified-docs/sql/04_test_queries.sql
Expected result: Sofia retrieves public/internal chunks plus LEGAL_CONFIDENTIAL.
Task 4.4 - Validate Carlos
Connect as Carlos:
exit
sql 'carlos/Welcome1_DDS!@ddslab_tunnel'
Run:
@scenarios/06-rag-vector-classified-docs/sql/04_test_queries.sql
Expected result: Carlos retrieves all classifications, including executive confidential chunks.
Lab 5 - Clean Up
Connect as ADMIN:
exit
sql admin@ddslab_tunnel
Run:
@scenarios/06-rag-vector-classified-docs/sql/99_reset.sql
exit
Workshop Wrap-Up
This workshop showed that:
- RAG retrieval can overexpose sensitive context if vector search is not authorization-aware.
- Oracle AI Database can store vectors and run semantic search directly in SQL.
- Oracle Deep Data Security can enforce fine-grained access to rows and columns through data grants.
- The LLM receives only the chunks the end user is authorized to access.
Product Manager Talking Points
- The security control is applied at the data source, before model invocation.
- The RAG application does not need to duplicate classified documents across separate vector stores.
- The same vector query returns different authorized contexts for different personas.
- This reduces the risk of confidential content leaking through AI-generated answers.
Official References
- Oracle Deep Data Security Guide: https://docs.oracle.com/en/database/oracle/oracle-database/26/ddscg/index.html
- About Data Grants: https://docs.oracle.com/en/database/oracle/oracle-database/26/ddscg/data-grants.html
- 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
- Oracle AI Vector Search FAQ: https://www.oracle.com/database/ai-vector-search/faq/