설계서: ORDS/VPD 실제 실행 감사 증적 (#567)
상태: Implemented 작성: [AI] Architect · 최종수정: 2026-07-01 추적성 — Redmine: #567 · 관련 이슈: #561 · 구현:
ProbeResult,FgaExecutionEvidence,OrdsProbeService,OrdsMetadataService,probe-result.html,22_*,29_*,42_*,43_*· 검증:ProbeResultTest,ProbeResultTemplateRenderTest,mvn test
목적
권한 결과 확인에서 보여 주는 SQL을 두 종류로 분리한다.
| 구분 | 출처 | 용도 |
|---|---|---|
| DB 감사 실행 증적 | Oracle FGA 감사 행 | 실제로 실행된 SQL과 DB가 기록한 VPD RLS_INFO 확인 |
| 참고용 SQL 재현 | Handler 응답/동일 정책 함수 | 사람이 권한 규칙과 SELECT 형태를 이해하는 보조 설명 |
재현 SQL이나 정책 함수를 다시 호출해 얻은 predicate를 실제 실행 증적으로 주장하지 않는다. V$SQL의 최신 cursor 후보를 찾아 추정하는 방식도 요청별 상관관계가 없어 증적 화면의 기준으로 사용하지 않는다.
해결 방식
[권한 결과 확인]
│ UUID 생성
▼
X-VPD-Probe-Id HTTP header
│
▼
[ORDS Handler]
set_vpd_context(auth, probe_id)
│ └─ DBMS_SESSION.SET_IDENTIFIER(probe_id)
▼
[VPD 보호 SELECT]
│
├─ DBMS_RLS가 정책 predicate 적용
▼
[DBMS_FGA SELECT 감사]
SQL_TEXT + RLS_INFO + CLIENT_ID 저장
│
▼
[Backoffice]
UNIFIED_AUDIT_TRAIL(ADB)에서 CLIENT_IDENTIFIER=probe_id로 한 행 조회
DBA_FGA_AUDIT_TRAIL은 전통 FGA DB fallback
│
▼
DB 감사 실행 증적 화면
CLIENT_ID는 백오피스가 매 probe마다 생성한 UUID다. 토큰, 사용자명, 권한 값은 넣지 않는다.- ORDS connection pool 재사용 시 남는 식별자가 없도록
set_vpd_context시작과clear_vpd_context에서DBMS_SESSION.CLEAR_IDENTIFIER를 호출한다. - FGA는
SQL_TEXT와 VPD 정책명·predicate가 담긴RLS_INFO를 DB 감사 trail에 저장한다. 이 Autonomous DB에서는UNIFIED_AUDIT_TRAIL을 사용하며, 전통 FGA 환경은DBA_FGA_AUDIT_TRAIL을 fallback으로 조회한다. - FGA 감사 행이 없으면 기존의 권한 결과 성공/0행 상태를 실패로 바꾸지 않는다. 다만 “실제 실행 증적 없음”으로 명확히 표시한다.
데이터 계약
ORDS 요청
X-VPD-Probe-Id: 8db9fc64-c71b-4b9e-9514-2fcaa355d9f3
Authorization: Bearer <masked>
X-VPD-Probe-Id는 일반 object handler, 기본 문서 handler, vector handler 모두 :probe_id로 bind한다.
화면 모델
FgaExecutionEvidence는 다음 값을 보관한다.
- 감사 시각
EVENT_TIMESTAMP_UTC(EXTENDED_TIMESTAMPfallback) - DB 실행 사용자
DBUSERNAME(DB_USERfallback) - 요청 식별자
CLIENT_IDENTIFIER(CLIENT_IDfallback) - 문장 유형
ACTION_NAME(STATEMENT_TYPEfallback) - 실제 SQL
SQL_TEXT - 실제 VPD 정보
RLS_INFO
ProbeResult는 이 값을 별도 필드로 보관한다. 기존 vpdPredicate/effectiveSql은 “참고용 SQL 재현”에만 사용한다.
설치와 운영 절차
ADMIN으로 42_agent_ords_fga_execution_audit.sql을 실행해 활성 보호 객체마다 FGASELECT정책을 만든다.CB_ORDS로 22_agent_ords_security_ords_handler_setup.sql, 29_agent_ords_vector_search_ords.sql, 43_agent_ords_probe_id_handler_patch.sql을 순서대로 실행한다.- 새 권한 결과 확인을 실행한다. 이전 요청에는
CLIENT_ID가 없으므로 소급해 매칭하지 않는다. - 백오피스 실행 계정이 Autonomous의
UNIFIED_AUDIT_TRAIL을 조회할 수 있어야 한다. 전통 FGA 환경은DBA_FGA_AUDIT_TRAIL을 fallback으로 사용한다. 일반 계정이면 감사 조회 권한을 가진 전용 observer 계정을 사용한다.
인수조건
- probe마다 새로운 request ID가 ORDS header에 전달된다.
- Handler가 request ID를
CLIENT_IDENTIFIER로 설정하고 종료 시 제거한다. - FGA가 활성 보호 객체의
SELECT를 감사한다. - 화면은 같은 request ID의
SQL_TEXT와RLS_INFO만 실제 실행 증적으로 보여 준다. - FGA 행이 없거나 읽기 권한이 없을 때 다른 cursor나 재현 predicate를 실제 값처럼 대신 보여 주지 않는다.
- 재현 SQL은 참고용으로만 표시되며 실제 증적과 시각적으로 구분된다.
- Bearer token 원문은 header, 감사 correlation ID, 화면 어느 곳에도 기록하지 않는다.
실패 처리
| 상황 | 화면 동작 |
|---|---|
| FGA 정책 미적용 | 권한 결과는 표시하고, FGA 적용 안내를 표시 |
| ORDS Handler가 구버전 | request ID가 DB에 설정되지 않아 해당 요청의 감사 행을 표시하지 않음 |
| 감사 조회 권한 없음 | 권한 결과는 유지하고, audit trail 권한 안내 표시 |
RLS_INFO 비어 있음 |
SQL_TEXT는 표시하고 audit 설정 확인 안내 표시 |
| 0행 결과 | VPD 차단 결과와 FGA SELECT 감사 행을 함께 표시 |
리스크와 선택 근거
- VPD policy function 안에서 별도 DML 로그를 남기지 않는다. 정책 함수에는 DB 상태 변경 제약이 있어, 감사 책임을 FGA에 둔다.
V$SQL은 shared pool cursor cache이며 보존·권한·동시성에 따라 해당 요청을 신뢰성 있게 찾을 수 없다. 운영 진단 보조로는 가능하지만 요청 증적의 기준으로는 부적합하다.- FGA audit trail은 보존 정책을 운영에서 정해야 한다. 장기 감사가 필요하면 Unified Audit 보존·전송 정책을 별도로 설정한다.
테스트 계획
- 단위:
ProbeResult가 FGA 증적과 참고용 재현 SQL을 서로 다른 필드로 유지한다. - 템플릿: FGA
SQL_TEXT,RLS_INFO,CLIENT_ID가 표시되고 V$SQL 후보 목록은 표시되지 않는다. - 통합: ADMIN/CB_ORDS 설치 후 각 보호 객체에 probe 실행 →
UNIFIED_AUDIT_TRAIL.CLIENT_IDENTIFIER가 화면 요청 ID와 같은지,RLS_INFO에 해당 VPD 정책이 있는지 확인한다.