11 KiB
11 KiB
설계서: ORDS/VPD 권한 적용 SQL trace (#567)
상태: Approved 작성: [AI] Architect · 최종수정: 2026-06-30 추적성 — Redmine: #567 · 관련 이슈: #561 · 관련 ADR: 없음 · 구현 파일:
ProbeResult,OrdsProbeService,OrdsMetadataService,probe-result.html,ords-handlers.html,sql/adb/17_*,22_*,26_*,29_*,33_*· 테스트:ProbeResultTest,OrdsMetadataServiceTest,GuidedFlowTemplateTest,mvn test
1. 목적 (Why)
권한 결과 확인에서 set_vpd_context가 토큰 사용자를 DB 컨텍스트로 설정한 뒤, VPD 정책 함수가 반환한 행 조건이 기본 SELECT에 어떻게 결합되는지 운영자가 직접 확인할 수 있게 한다. 이 기능은 #561의 Handler 흐름 설명을 실행 증거까지 확장한다.
2. 범위 (Scope)
- 포함:
- ORDS Handler 성공 응답의
vpd_predicate,effective_sqltrace 필드. - 기존 trace 미적용 Handler를 위한 동일 DB fallback predicate 조회.
/probe결과의 “토큰 적용 후 SQL” 영역과 trace 미지원 안내.- 신규/갱신 Handler SQL 및 기존 설치용
GRANT패치 스크립트. - 토큰 원문 마스킹과 trace 관련 단위/템플릿/소스 테스트.
- ORDS Handler 성공 응답의
- 제외 (out of scope):
- Oracle optimizer 실행계획,
V$SQL조회, bind 값 치환 결과의 수집. - custom VPD Filter의 임의 SQL 해석 또는 자동 수정.
- 권한 모델/토큰 저장 구조 변경.
- 원문 Bearer Token의 응답·로그·DB 저장.
- Oracle optimizer 실행계획,
3. 인수조건 (Acceptance Criteria)
- 유효 토큰으로 권한 결과를 조회하면 VPD predicate와 기본 SELECT에 결합한 effective SQL을 확인할 수 있다.
- 0행 결과도 성공적인 VPD 차단 결과로 trace 표시 대상이 된다.
- 신규/갱신 object Handler와 기본 VPD/벡터 Handler는 진단 필드를 응답에 포함한다.
- 기존 Handler가 진단 필드를 반환하지 않아도 같은 DB의
set_user_by_bearer컨텍스트에서 기본 VPD predicate를 재조회한다. - trace를 얻을 수 없는 DB 계정·custom Filter·구버전 Handler는 조회 결과를 실패로 바꾸지 않고 적용 방법을 안내한다.
- trace에는 predicate 표현식과 SQL 구조만 포함하며 Bearer 원문은 포함하지 않는다.
- 초기화 및 기존 설치용 SQL에
CB_AGENT_DOC_VPD_FILTER실행 권한과 갱신 절차가 명시된다. - 관련 단위/템플릿/Handler source 테스트와 전체 Maven 테스트가 통과한다.
4. 컨텍스트 & 제약
- ORDS는 공통
CB_ORDS계정으로 접속하고cb_ords_handler_pkg.set_vpd_context가 Bearer key를CB_AGENT_CTX에 매핑한다. - 기본 VPD 함수
ADMIN.CB_AGENT_DOC_VPD_FILTER가 현재 컨텍스트의 권한 규칙으로 predicate를 만든다. 정책 함수의 반환값을 직접 표시하는 것이 행 결과를 다시 계산하는 별도 Java 권한 로직보다 정합성이 높다. - 기존 Handler는 응답 계약을 바꾸지 않을 수 있으므로, 백오피스 DB 연결에서 같은 Bearer key를 별도 세션 컨텍스트에 설정해 fallback을 수행한다. fallback은 세션 종료 전에 반드시
clear_user를 실행한다. - ORDS 응답 trace가 없거나 fallback 권한이 없으면 권한 결과 자체는 그대로 반환한다. trace는 관측성 보조 기능이며 접근 통제 경로가 아니다.
ADMIN은 현재 PoC의 VPD 함수/컨텍스트 소유자다. 다른 소유자 구조는 이번 범위에서 자동 추론하지 않는다.
5. 아키텍처 개요
[Probe form: bearerToken + object]
│
▼
[ORDS Handler: set_vpd_context]
│
┌──────┴────────┐
│ │
▼ ▼
[DBMS_RLS SELECT] [same-context trace]
│ │
└──────┬────────┘
▼
[ORDS JSON: items + vpd_predicate + effective_sql]
│
▼ (trace absent only)
[Backoffice DB fallback: set_user_by_bearer → filter → clear_user]
│
▼
[ProbeResult → “토큰 적용 후 SQL”]
- I/O 경계:
OrdsProbeService.findVpdPredicate와 ORDS HTTP 호출은 외부 I/O다.ProbeResult.hasSqlTrace/withSqlTrace와 SQL 문자열 조합은 표현/변환 책임으로 둔다. - 안전 경계: predicate 조회 실패는 조회 실패가 아니며 trace만 생략한다. Bearer header는 기존처럼 마스킹된 request detail만 노출한다.
6. 데이터 모델
ProbeResult.vpdPredicate: VPD 정책 함수가 현재 토큰 컨텍스트에서 반환한 predicate 문자열(nullable).ProbeResult.effectiveSql: Handler의 기본 SELECT와 predicate/row limit을 결합한 확인용 SQL(nullable).- ORDS JSON 성공 응답에 두 문자열을 optional root field로 추가한다.
items/rows기존 배열 계약은 유지한다. - trace SQL은
:row_limitbind 표기를 유지하며 실제 Bearer 값이나 context 값은 문자열에 치환하지 않는다.
7. 함수 명세 (Function Specs)
| 함수 | 책임(1줄) | 시그니처(잠정) | 입력 | 출력 | 에러/실패 | 복잡? |
|---|---|---|---|---|---|---|
ProbeResult.hasSqlTrace |
effective SQL 존재 여부를 판단 | boolean hasSqlTrace() |
result fields | boolean | blank/null이면 false | 단순 |
ProbeResult.withSqlTrace |
기존 결과에 trace 두 필드를 불변으로 부착 | ProbeResult withSqlTrace(String, String) |
predicate, SQL | 새 ProbeResult |
없음 | 단순 |
OrdsProbeService.runProbe |
ORDS 결과를 파싱하고 필요한 경우 trace fallback을 연결 | ProbeResult runProbe(ProbeCommand) |
token/object/limit | ProbeResult | 기존 상태 분류 유지 | 복잡 |
parseSuccess |
ORDS JSON 배열과 optional trace 필드 파싱 | ProbeResult parseSuccess(...) |
body, objectId, HTTP evidence | ProbeResult | 배열 누락 시 예외 | 단순 |
traceValue |
JSON scalar trace 필드 정규화 | String traceValue(JsonNode, String) |
root/field | nullable String | 비 scalar/blank이면 null | 단순 |
addLocalSqlTrace |
predicate와 보호 객체 컬럼으로 effective SQL 생성 | ProbeResult addLocalSqlTrace(...) |
result/token/object | trace 부착 결과 | DB/컬럼 조회 실패 시 원 결과 | 복잡 |
findVpdPredicate |
같은 DB 연결에서 컨텍스트 설정→predicate 조회→컨텍스트 정리 | String findVpdPredicate(String, ProtectedObject) |
bearer/object | nullable predicate | 권한/DB 오류는 null | 복잡 |
executeContextSetter |
DB 세션에 Bearer 기반 사용자 컨텍스트 설정 | void executeContextSetter(Connection, String) |
connection/token | 없음 | SQLException | 단순 |
clearContext |
fallback 세션의 사용자 컨텍스트 제거 | void clearContext(Connection) |
connection | 없음 | cleanup 오류 무시 | 단순 |
objectQuerySource |
생성 Handler에 trace metadata 출력 블록을 포함 | String objectQuerySource(ProtectedObject,List<String>) |
object/columns | PL/SQL source | 식별자/컬럼 검증은 호출부 | 복잡 |
복잡 함수 상세는 fn-addLocalSqlTrace.md, fn-findVpdPredicate.md에 둔다. runProbe의 기본 상태 분류 계약은 기존 #557 설계를 계승한다.
8. 흐름 / 알고리즘
- ORDS base URL, token, 보호 객체를 기존 검증 절차로 확인한다.
- ORDS POST를 호출한다. 갱신된 Handler는
set_vpd_context직후 동일 VPD 함수를 호출해 trace를 만들고,items와 함께 JSON으로 반환한다. - 백오피스는
items/rows를 기존 방식으로 파싱한다. - trace가 없고 일반 object Handler이면 백오피스 DB의 한 연결에서
set_user_by_bearer를 호출한다. - 같은 연결에서
SELECT admin.cb_agent_doc_vpd_filter(?, ?) FROM dual을 수행한다. finally경로에서clear_user를 호출하고 연결을 pool에 반환한다.- 보호 객체의 등록 컬럼과 predicate를 이용해
SELECT ... FROM OWNER.OBJECT o WHERE (...) AND ROWNUM ...형태를 만든다. - 화면은 결과 행·사용자 권한 뒤에 predicate와 effective SQL을 표시한다. trace가 없으면 ORDS/DB 적용 절차를 안내한다.
9. 엣지케이스 & 에러 처리
- token/ORDS 오류: 기존
ProbeStatus와 HTTP evidence 처리만 수행하며 fallback을 실행하지 않는다. - 0행:
VPD_DENY_EMPTY_RESULT를 유지하고 trace를 표시한다. - ORDS 신규 trace가 있고 local DB trace가 불가능한 경우: ORDS 응답 trace를 그대로 사용한다.
- 기존 Handler·DB 계정에 trace 권한이 없는 경우: 결과 성공/0행을 유지하고 trace 미지원 안내를 표시한다.
- fallback context setter가 실패한 경우: 반드시 cleanup을 시도하고 trace는 null로 둔다.
- vector object: 전용 Handler의 복합 vector SQL을 일반
SELECT로 오표시하지 않도록 local generic fallback을 생략한다. 갱신된 vector Handler가 자체 trace를 반환하면 표시한다. - custom VPD Filter: 기본 함수 반환값을 custom Filter의 실제 predicate로 주장하지 않는다. trace가 없으면 별도 Filter 확인을 안내한다.
- predicate가 길어도 DB 함수 반환 한도(
VARCHAR2(32767))와 화면<pre>로 처리한다.
10. 테스트 계획
ProbeResultTest: trace 부착 후 기존 rows/status 보존, blank trace 미표시.OrdsMetadataServiceTest: 생성 object Handler에set_vpd_context, default VPD function, JSON trace 필드와 컬럼 SQL이 포함되는지 확인.GuidedFlowTemplateTest: 결과 화면/Handler 안내/초기화 SQL/기존 설치 grant 및 vector trace source 확인.mvn test: 전체 단위·템플릿 테스트.- 운영 smoke: 신규 토큰으로
/probe에서 HR/SELF/ALL 결과를 각각 실행하고 predicate의DEPT_CODE,OWNER_EMP_NO,1 = 1또는1 = 0차이를 확인한다. 토큰 원문이 response body/log에 없는지 확인한다.
11. 리스크 & 대안 검토
V$SQL/DBMS_XPLAN조회는 connection pool의 다른 세션·cursor·권한 문제 때문에 결과가 불안정하다. 정책 함수 반환값을 같은 context에서 표시하는 방식을 선택한다.- Java에서 permission table을 다시 계산하는 방식은 그룹 상속·DENY 우선순위·custom policy와 어긋날 수 있다. DB의 정책 함수 자체를 trace source로 사용한다.
- Handler 응답 계약을 강제로 변경하면 기존 Handler가 실패할 수 있다. optional response fields와 non-failing fallback을 사용한다.
- fallback에서 context cleanup을 놓치면 pool connection 간 사용자 혼선이 발생한다.
finallycleanup을 고정하고 cleanup 오류는 결과를 덮지 않는다.
12. 미해결 질문 (Open Questions)
- custom VPD Filter까지 정책 함수별로 자동 trace할지는 별도 이슈로 남긴다.
- 운영 DB에서
ADMIN이외의 VPD 소유자 구조를 지원하려면 함수 owner 설정을 명시적으로 추가해야 한다.