docs: align DDS token WHERE flow and vector scenario
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
# 설계서: 기술 태그 기반 벡터 지식자료 검색과 VPD 연결
|
||||
|
||||
> **상태**: 제품형 운영 흐름 구현 · 운영 확장 항목 별도
|
||||
> **추적성**: Redmine #565 · 기준 구현: `28_agent_ords_vector_tag_vpd_setup.sql`, `29_agent_ords_vector_search_ords.sql`
|
||||
> **상태**: 제품형 운영 흐름 구현 · DDS 병행 검증 완료 · 운영 확장 항목 별도
|
||||
> **추적성**: Redmine #565, #566 · 기준 구현: `28_agent_ords_vector_tag_vpd_setup.sql`, `29_agent_ords_vector_search_ords.sql`, `32_dds_vector_tag_setup.sql`
|
||||
|
||||
## 1. 한 문장으로 이해하기
|
||||
|
||||
@@ -182,3 +182,27 @@ backoffice의 `/objects` 화면은 이 객체에 일반 Handler를 생성하지
|
||||
- 대용량 파일 업로드, 비동기 작업 큐, 재시도·실패 격리, 임베딩 모델 버전별 재색인은 운영 파이프라인에서 별도로 설계한다.
|
||||
- 태그 사전 승인 워크플로와 문서별 소유자/보존기간 정책은 현재 화면의 범위를 넘어선다.
|
||||
- 운영 DB에 대한 DDL, 기존 정책 교체, 방화벽/NSG 변경은 별도 승인을 받아 실행한다.
|
||||
|
||||
## 10. DDS 병행 시나리오: 같은 TAG 권한, 단일 기술 사용자
|
||||
|
||||
VPD에서 검증한 기술 태그 권한을 DDS에서도 고객별 DDS 계정으로 복제하지 않고 적용할 수 있는지 별도로 확인했다. 업무 권한의 원천은 동일한 `CB_PERMISSION`·`CB_PERMISSION_RULE`이다. DDS 설치 스크립트는 이 규칙을 벡터 검색 뷰와 연결하고, 애플리케이션 함수가 토큰을 받아 같은 규칙을 `WHERE`로 집행한다.
|
||||
|
||||
```text
|
||||
Bearer token
|
||||
→ CB_AGENT_BEARER_KEY에서 사용자 식별
|
||||
→ CB_APP_USER의 직접 역할/활성 그룹 역할 계산
|
||||
→ ALLOW TAG는 OR, DENY TAG는 NOT EXISTS
|
||||
→ CB_DDS_VECTOR_SEARCH_DOCUMENTS 조회
|
||||
```
|
||||
|
||||
하나의 `dds_demo_both` DDS 기술 사용자 세션에서 임시 `CB_SIMPLE_DDS_TOKEN_SELECT(token)` 함수를 실행한 결과는 다음과 같다.
|
||||
|
||||
| 토큰 사용자 | 반환 청크 |
|
||||
|---|---|
|
||||
| `agent_hr` | `28001`, `28002` (2건) |
|
||||
| `agent_fin_self` | `28002` (1건) |
|
||||
| `agent_all` | `28001`, `28002`, `28003` (3건) |
|
||||
|
||||
이 방식의 의미는 “DDS가 토큰을 자동으로 이해한다”가 아니다. `DATA GRANT`에 호출 시점 토큰 인자를 직접 넘기는 것이 아니라, 토큰을 받는 함수/API가 공통 권한 테이블을 조회해 보호 뷰의 `WHERE`를 결정한다. 따라서 현재 제품형 기본 시나리오는 **단일 DDS 기술 사용자 + 토큰 WHERE 어댑터 + 공통 업무 권한**이다. 드라이버가 SQL 실행 전에 `EndUserSecurityContext`를 전달하는 순수 DDS Context 방식은 별도 확장 경계이며, 그 경우에만 `ORA_END_USER_CONTEXT`를 참조하는 일반 `DATA GRANT`를 설계한다.
|
||||
|
||||
토큰, 임시 함수, 임시 권한은 검증 뒤 삭제했다. 새 태그나 역할을 추가할 때도 VPD와 DDS가 각각 고객 사용자를 복제하는 대신, 공통 `CB_*` 권한을 먼저 수정하고 두 집행 경계의 회귀 테스트를 함께 실행한다.
|
||||
|
||||
@@ -1,8 +1,12 @@
|
||||
# 독립 VPD·DDS 데모 구성
|
||||
|
||||
> **상태**: VPD·DDS 병행 검증 완료, 운영 전환 항목 별도
|
||||
> **추적성**: Redmine #565, #566 · DDS 구현 커밋 `1e48864`
|
||||
> **기준 구현**: `sql/adb/32_dds_vector_tag_setup.sql`, `dds-backoffice/src/main/java/com/cloudhandson/ddsbackoffice/service/DdsGrantPublisher.java`
|
||||
|
||||
## 목적
|
||||
|
||||
VPD와 Oracle Deep Data Security(DDS)를 한 애플리케이션에 섞지 않고, 같은 접근 결과를 서로 다른 DB 보안 모델로 비교한다.
|
||||
VPD와 Oracle Deep Data Security(DDS)를 별도 인스턴스로 운영하면서도, 고객의 업무 권한을 정의하는 공통 테이블을 기준으로 같은 검색 시나리오를 비교한다. 고객마다 DDS 계정을 만드는 것이 목표가 아니다. 현재 기본 데모는 하나의 DDS 기술 사용자 세션에 Bearer 토큰을 함수 파라미터로 전달하고, 함수가 공통 권한 테이블을 읽어 `WHERE` 조건으로 결과를 제한한다.
|
||||
|
||||
## 인스턴스 경계
|
||||
|
||||
@@ -10,12 +14,12 @@ VPD와 Oracle Deep Data Security(DDS)를 한 애플리케이션에 섞지 않고
|
||||
|---|---|---|
|
||||
| 실행 디렉터리 | `/home/opc/apps/vpd-backoffice` | `/home/opc/apps/dds-backoffice` |
|
||||
| 기본 포트 | `8082` | `8083` |
|
||||
| 사용자 식별 | 공통 DB 계정 + Bearer/세션 컨텍스트 | DDS `END USER` 직접 logon |
|
||||
| 권한 기준 | 업무 권한 테이블 + VPD 함수 | `DATA ROLE` + `DATA GRANT` |
|
||||
| 사용자 식별 | 공통 DB 계정 + Bearer/세션 컨텍스트 | 단일 DDS 기술 사용자 + 토큰 파라미터 함수(기본 경로) |
|
||||
| 권한 기준 | 업무 권한 테이블 + VPD 함수 | 같은 업무 권한 테이블 + 토큰 기반 `WHERE`; DDS `DATA ROLE/GRANT`는 별도 경계 |
|
||||
| 보호 객체 | `V_CUSTOMERS_*` / VPD 전용 객체 | `V_DDS_CUSTOMERS_*` / DDS 전용 객체 |
|
||||
| 운영 프로세스 | VPD start/stop/status | DDS start/stop/status |
|
||||
|
||||
두 인스턴스는 화면, JAR, PID, 로그, 설정 파일을 공유하지 않는다. DDS 데모는 VPD 권한 테이블이나 VPD 정책 함수에 의존하지 않는다.
|
||||
두 인스턴스는 화면, JAR, PID, 로그, 설정 파일을 공유하지 않는다. 다만 권한의 업무 원천(source of truth)은 `CB_APP_USER`, 그룹·역할, `CB_PERMISSION`, `CB_PERMISSION_RULE` 같은 공통 테이블로 유지하고, 각 보안 엔진이 자기 방식으로 그 결과를 집행한다. DDS 벡터 설치 스크립트는 같은 TAG 권한을 DDS 검색 뷰와 연결한다.
|
||||
|
||||
## 동일하게 비교할 수 있는 것
|
||||
|
||||
@@ -24,13 +28,58 @@ VPD와 Oracle Deep Data Security(DDS)를 한 애플리케이션에 섞지 않고
|
||||
- 권한 없는 사용자의 default deny
|
||||
- 보호 VIEW 우회 시도 차단
|
||||
|
||||
## 동일하게 간주하면 안 되는 것
|
||||
## DDS 기본 시나리오: 한 사용자, 토큰 파라미터, 공통 `WHERE`
|
||||
|
||||
- VPD의 공통 DB 계정 + Bearer + 동적 predicate 흐름
|
||||
- 업무 권한 테이블을 매 요청마다 읽는 동적 변경 방식
|
||||
- ORDS Handler가 Bearer 값을 DDS 사용자명으로 바꾸는 것만으로 DDS 컨텍스트가 생기는 동작
|
||||
### 일반 사용자가 이해하는 흐름
|
||||
|
||||
DDS는 직접 `END USER`로 접속하거나 지원 드라이버가 `EndUserSecurityContext`를 전달해야 한다. 따라서 DDS 데모의 조회 결과가 VPD와 같더라도, 권한이 계산·전달되는 경로는 별도로 설명해야 한다.
|
||||
```text
|
||||
Bearer 토큰
|
||||
→ 토큰 해시로 CB_AGENT_BEARER_KEY 조회
|
||||
→ CB_APP_USER와 연결
|
||||
→ 직접 역할 + 활성 그룹 역할 계산
|
||||
→ CB_PERMISSION_RULE의 TAG 허용/거부 규칙 계산
|
||||
→ CB_DDS_VECTOR_SEARCH_DOCUMENTS에 함수가 WHERE 적용
|
||||
→ 허용된 청크만 반환
|
||||
```
|
||||
|
||||
`dds_demo_both` 하나의 DDS 기술 사용자 세션에서 임시 함수 `ADMIN.CB_SIMPLE_DDS_TOKEN_SELECT(token)`로 위 흐름을 검증했다. 함수는 고객용 DDS 계정을 새로 만들지 않고 토큰으로 업무 사용자를 식별한다. 같은 ALLOW 권한의 태그는 OR로 합치고, DENY 태그는 `NOT EXISTS`로 제외한다.
|
||||
|
||||
호출 계약은 의도적으로 단순하다.
|
||||
|
||||
```sql
|
||||
SELECT ADMIN.CB_SIMPLE_DDS_TOKEN_SELECT(:bearer_token)
|
||||
FROM dual;
|
||||
```
|
||||
|
||||
실제 함수 내부의 조회 조건은 다음 의미를 가진다.
|
||||
|
||||
```sql
|
||||
WHERE EXISTS (허용된 TAG 중 하나가 청크 TAG와 일치)
|
||||
AND NOT EXISTS (거부된 TAG 중 하나가 청크 TAG와 일치)
|
||||
```
|
||||
|
||||
즉, 토큰은 사용자 식별 입력이고 권한 결정은 기존 `CB_*` 테이블이 담당한다. 토큰별로 DDS 계정을 바꾸거나 고객 사용자마다 DDS `END USER`를 만드는 단계는 없다.
|
||||
|
||||
### 검증 결과
|
||||
|
||||
| 토큰으로 식별된 업무 사용자 | TAG 권한 결과 | 반환 청크 |
|
||||
|---|---|---|
|
||||
| `agent_hr` | `SPRING_BOOT` OR `ORACLE_VPD` | `28001`, `28002` (2건) |
|
||||
| `agent_fin_self` | `ORACLE_VPD` | `28002` (1건) |
|
||||
| `agent_all` | 전체 허용 역할 | `28001`, `28002`, `28003` (3건) |
|
||||
|
||||
토큰 행, 임시 함수, 임시 권한은 검증 직후 삭제했다. 이 결과는 “DDS 사용자 수 = 고객 사용자 수”가 아니라 “DDS 기술 사용자 1개 + 고객 권한 테이블” 모델이 동작함을 보여 준다.
|
||||
|
||||
## 두 가지 DDS 집행 경계
|
||||
|
||||
| 구분 | 현재 기본 데모 | 순수 DDS Context 확장 |
|
||||
|---|---|---|
|
||||
| 토큰 전달 | 함수의 `token` 파라미터 | 지원 드라이버/ORDS가 `EndUserSecurityContext`로 전달 |
|
||||
| 권한 계산 | 함수가 공통 `CB_*` 테이블을 읽어 `WHERE` 생성 | `DATA GRANT` predicate가 DDS 런타임 컨텍스트를 참조 |
|
||||
| 사용자 객체 | DDS 기술 사용자 1개 | DDS END USER 또는 데이터 역할 매핑 필요 |
|
||||
| 현재 상태 | 검증 완료 | 드라이버·ORDS 전달 경로를 별도 검증해야 함 |
|
||||
|
||||
중요한 경계는 `DATA GRANT` 자체가 호출 시점의 임의 함수 인자를 받는 구조가 아니라는 점이다. 따라서 현재 시나리오에서는 토큰을 받는 함수/API가 조회 경계가 되고, DDS는 그 함수가 조회하는 보호 뷰와 기술 사용자 세션을 보호한다. 향후 순수 DDS Context를 사용하려면 토큰을 SQL 실행 전에 드라이버가 붙이고, 그때만 `ORA_END_USER_CONTEXT` 기반 `DATA GRANT`를 적용한다. ORDS Handler가 Bearer 값을 DDS 사용자명으로 바꾸는 것만으로는 DDS Context가 자동 생성되지 않는다.
|
||||
|
||||
## 실행 확인
|
||||
|
||||
@@ -40,3 +89,11 @@ DDS는 직접 `END USER`로 접속하거나 지원 드라이버가 `EndUserSecur
|
||||
```
|
||||
|
||||
외부 공개 포트는 애플리케이션 분리와 별개의 운영 변경이다. DDS 기본 바인딩은 `127.0.0.1:8083`이며, 직접 공개하려면 HTTPS, NSG, VM firewalld 정책을 별도로 승인한다.
|
||||
|
||||
## 변경·확장 가이드
|
||||
|
||||
- 업무 사용자·역할·태그 권한은 기존 `CB_*` 테이블에서 관리한다. DDS 전용 고객 계정을 추가해 권한을 복제하지 않는다.
|
||||
- 토큰 조회 함수는 해시된 Bearer 키만 사용하고 원문 토큰을 저장하거나 로그에 남기지 않는다.
|
||||
- 새로운 TAG를 추가할 때는 태그 사전, `CB_PERMISSION_RULE`, 샘플 청크, 허용·거부 테스트를 함께 갱신한다.
|
||||
- 함수 경계를 벗어나 직접 DDS 객체를 노출하는 Handler를 만들지 않는다. 벡터 검색은 임베딩을 반환하지 않는 전용 뷰/Handler를 사용한다.
|
||||
- 운영에서 드라이버 기반 DDS Context로 전환할 때는 별도 설계·검증 이슈를 만들고, 현재의 토큰 WHERE 결과와 동일한 회귀 테스트를 통과시킨다.
|
||||
|
||||
Reference in New Issue
Block a user