[Developer] #573 normalize vector access whitelist
This commit is contained in:
@@ -61,8 +61,12 @@ BEGIN
|
||||
|| 'FROM (SELECT d.chunk_id, d.document_id, d.chunk_no, d.title, d.chunk_text, '
|
||||
|| 'd.source_uri, d.tech_tag, VECTOR_DISTANCE(d.embedding, TO_VECTOR(:embedding), COSINE) AS score '
|
||||
|| 'FROM admin.cb_vector_search_documents d '
|
||||
|| 'WHERE d.embedding IS NOT NULL AND (' || v_vpd_predicate || ') '
|
||||
|| 'ORDER BY score) ranked_chunks '
|
||||
|| 'WHERE d.embedding IS NOT NULL';
|
||||
IF TRIM(v_vpd_predicate) <> '1 = 1' THEN
|
||||
v_effective_sql := v_effective_sql || ' AND (' || v_vpd_predicate || ')';
|
||||
END IF;
|
||||
v_effective_sql := v_effective_sql
|
||||
|| ' ORDER BY score) ranked_chunks '
|
||||
|| 'WHERE ROWNUM <= LEAST(GREATEST(NVL(:row_limit, 10), 1), 100)';
|
||||
EXCEPTION
|
||||
WHEN OTHERS THEN
|
||||
|
||||
@@ -78,19 +78,14 @@ CREATE OR REPLACE DATA GRANT admin.dds_demo_both_vector_grant
|
||||
-- dds_demo_none_role intentionally receives no grant (default deny).
|
||||
|
||||
PROMPT === 3. Registering the vector object in the common application permission model ===
|
||||
-- The application permission tables remain the source of truth. These rows
|
||||
-- make the standalone DDS example use the same role/TAG scenario as VPD:
|
||||
-- one ALLOW permission per role and multiple TAG rules combined with OR.
|
||||
-- The backoffice's DDS publish screen compiles these rows into the grants
|
||||
-- above (and excludes the protected EMBEDDING column by default).
|
||||
-- The application permission tables remain the source of truth. Basic vector
|
||||
-- access is a role whitelist: the seeded application roles have one ALLOW
|
||||
-- permission plus an ALL rule and can search every vector chunk. TAG rules
|
||||
-- are reserved for a role deliberately configured with a row condition.
|
||||
DECLARE
|
||||
PROCEDURE ensure_vector_permission(
|
||||
p_role_id IN NUMBER,
|
||||
p_tag_list IN SYS.ODCIVARCHAR2LIST
|
||||
) IS
|
||||
PROCEDURE ensure_vector_all_permission(p_role_id IN NUMBER) IS
|
||||
v_perm_id NUMBER;
|
||||
v_rule_id NUMBER;
|
||||
v_tag VARCHAR2(100);
|
||||
BEGIN
|
||||
BEGIN
|
||||
SELECT perm_id
|
||||
@@ -111,33 +106,36 @@ DECLARE
|
||||
);
|
||||
END;
|
||||
|
||||
FOR i IN 1 .. p_tag_list.COUNT LOOP
|
||||
v_tag := UPPER(TRIM(p_tag_list(i)));
|
||||
BEGIN
|
||||
SELECT rule_id
|
||||
INTO v_rule_id
|
||||
FROM cb_permission_rule
|
||||
WHERE perm_id = v_perm_id
|
||||
AND rule_column = 'TECH_TAG'
|
||||
AND rule_type = 'TAG'
|
||||
AND rule_value = v_tag
|
||||
AND ROWNUM = 1;
|
||||
EXCEPTION
|
||||
WHEN NO_DATA_FOUND THEN
|
||||
SELECT NVL(MAX(rule_id), 0) + 1 INTO v_rule_id FROM cb_permission_rule;
|
||||
INSERT INTO cb_permission_rule (
|
||||
rule_id, perm_id, rule_column, rule_type, rule_value
|
||||
) VALUES (
|
||||
v_rule_id, v_perm_id, 'TECH_TAG', 'TAG', v_tag
|
||||
);
|
||||
END;
|
||||
END LOOP;
|
||||
-- The old demo seed put arbitrary TECH_TAG filters on these base roles.
|
||||
-- Full access must not depend on the current list of document tags.
|
||||
DELETE FROM cb_permission_rule
|
||||
WHERE perm_id = v_perm_id
|
||||
AND UPPER(TRIM(rule_type)) = 'TAG';
|
||||
|
||||
SELECT MIN(rule_id)
|
||||
INTO v_rule_id
|
||||
FROM cb_permission_rule
|
||||
WHERE perm_id = v_perm_id
|
||||
AND UPPER(TRIM(rule_type)) = 'ALL';
|
||||
|
||||
IF v_rule_id IS NULL THEN
|
||||
SELECT NVL(MAX(rule_id), 0) + 1 INTO v_rule_id FROM cb_permission_rule;
|
||||
INSERT INTO cb_permission_rule (
|
||||
rule_id, perm_id, rule_column, rule_type, rule_value
|
||||
) VALUES (
|
||||
v_rule_id, v_perm_id, NULL, 'ALL', NULL
|
||||
);
|
||||
END IF;
|
||||
|
||||
DELETE FROM cb_permission_rule
|
||||
WHERE perm_id = v_perm_id
|
||||
AND UPPER(TRIM(rule_type)) = 'ALL'
|
||||
AND rule_id <> v_rule_id;
|
||||
END;
|
||||
BEGIN
|
||||
ensure_vector_permission(10, SYS.ODCIVARCHAR2LIST('SPRING_BOOT', 'ORDS'));
|
||||
ensure_vector_permission(20, SYS.ODCIVARCHAR2LIST('ORACLE_VPD', 'ORACLE_DDS'));
|
||||
ensure_vector_permission(30, SYS.ODCIVARCHAR2LIST(
|
||||
'SPRING_BOOT', 'ORDS', 'ORACLE_VPD', 'ORACLE_DDS', 'MCP'));
|
||||
ensure_vector_all_permission(10);
|
||||
ensure_vector_all_permission(20);
|
||||
ensure_vector_all_permission(30);
|
||||
END;
|
||||
/
|
||||
|
||||
|
||||
@@ -0,0 +1,91 @@
|
||||
-- ============================================================
|
||||
-- 38_agent_ords_vector_all_permission_normalization.sql
|
||||
-- Normalize the seeded vector access roles to whitelist / ALL access.
|
||||
--
|
||||
-- The default roles 10, 20 and 30 may search every document chunk. A role
|
||||
-- with no matching ALLOW permission remains fail-closed through the VPD
|
||||
-- function (1 = 0). Keep row conditions such as TAG on dedicated restricted
|
||||
-- roles that do not also have an ALL rule.
|
||||
-- ============================================================
|
||||
WHENEVER SQLERROR EXIT SQL.SQLCODE
|
||||
SET ECHO ON
|
||||
SET FEEDBACK ON
|
||||
SET DEFINE OFF
|
||||
|
||||
PROMPT === Normalizing default vector roles to ALL ===
|
||||
DECLARE
|
||||
PROCEDURE normalize_vector_role(p_role_id IN NUMBER) IS
|
||||
v_perm_id NUMBER;
|
||||
v_rule_id NUMBER;
|
||||
BEGIN
|
||||
SELECT MIN(perm_id)
|
||||
INTO v_perm_id
|
||||
FROM cb_permission
|
||||
WHERE role_id = p_role_id
|
||||
AND target_name = 'CB_VECTOR_SEARCH_DOCUMENTS'
|
||||
AND action_name = 'SELECT'
|
||||
AND permission_effect = 'ALLOW';
|
||||
|
||||
IF v_perm_id IS NULL THEN
|
||||
SELECT NVL(MAX(perm_id), 0) + 1 INTO v_perm_id FROM cb_permission;
|
||||
INSERT INTO cb_permission (
|
||||
perm_id, role_id, target_name, action_name, permission_effect
|
||||
) VALUES (
|
||||
v_perm_id, p_role_id, 'CB_VECTOR_SEARCH_DOCUMENTS', 'SELECT', 'ALLOW'
|
||||
);
|
||||
END IF;
|
||||
|
||||
-- Remove only the legacy demo TAG filters from the default ALL roles.
|
||||
DELETE FROM cb_permission_rule
|
||||
WHERE perm_id = v_perm_id
|
||||
AND UPPER(TRIM(rule_type)) = 'TAG';
|
||||
|
||||
SELECT MIN(rule_id)
|
||||
INTO v_rule_id
|
||||
FROM cb_permission_rule
|
||||
WHERE perm_id = v_perm_id
|
||||
AND UPPER(TRIM(rule_type)) = 'ALL';
|
||||
|
||||
IF v_rule_id IS NULL THEN
|
||||
SELECT NVL(MAX(rule_id), 0) + 1 INTO v_rule_id FROM cb_permission_rule;
|
||||
INSERT INTO cb_permission_rule (
|
||||
rule_id, perm_id, rule_column, rule_type, rule_value
|
||||
) VALUES (
|
||||
v_rule_id, v_perm_id, NULL, 'ALL', NULL
|
||||
);
|
||||
END IF;
|
||||
|
||||
DELETE FROM cb_permission_rule
|
||||
WHERE perm_id = v_perm_id
|
||||
AND UPPER(TRIM(rule_type)) = 'ALL'
|
||||
AND rule_id <> v_rule_id;
|
||||
END;
|
||||
BEGIN
|
||||
normalize_vector_role(10); -- HR_DEPT_ROLE
|
||||
normalize_vector_role(20); -- FIN_SELF_ROLE
|
||||
normalize_vector_role(30); -- ALL_DOC_ROLE
|
||||
COMMIT;
|
||||
END;
|
||||
/
|
||||
|
||||
PROMPT === Verifying default vector whitelist rules ===
|
||||
SELECT r.role_id,
|
||||
r.role_name,
|
||||
p.target_name,
|
||||
p.action_name,
|
||||
p.permission_effect,
|
||||
pr.rule_type,
|
||||
pr.rule_column,
|
||||
pr.rule_value
|
||||
FROM cb_app_role r
|
||||
JOIN cb_permission p
|
||||
ON p.role_id = r.role_id
|
||||
LEFT JOIN cb_permission_rule pr
|
||||
ON pr.perm_id = p.perm_id
|
||||
WHERE r.role_id IN (10, 20, 30)
|
||||
AND p.target_name = 'CB_VECTOR_SEARCH_DOCUMENTS'
|
||||
AND p.action_name = 'SELECT'
|
||||
ORDER BY r.role_id, p.perm_id, pr.rule_id;
|
||||
|
||||
PROMPT === Default vector whitelist normalization complete ===
|
||||
EXIT;
|
||||
Reference in New Issue
Block a user