[Architect] #617 define runtime DDS authorization

This commit is contained in:
devmrko
2026-07-03 10:05:26 +09:00
parent ef1331be4b
commit b77966abaf
8 changed files with 233 additions and 104 deletions

View File

@@ -4,11 +4,11 @@
## 결정
OCI IAM Confidential Application의 client-credentials token을 database-access token으로 사용한다. MCP 요청자는 기존 opaque Bearer → `CB_APP_USER` 매핑으로 판정하고, 그 사용자를 local DDS `END USER`로 attach한다.
OCI IAM Confidential Application의 client-credentials token을 database-access token으로 사용한다. MCP 요청자는 기존 opaque Bearer → `CB_APP_USER` 매핑으로 판정하고, 그 사용자를 local DDS `END USER`로 attach한다. 업무 권한의 런타임 판정 방식은 [ADR-0002](0002-dds-runtime-permission-source.md)를 따른다.
## 근거
client-credentials token의 `client_id`/`sub`는 서비스 애플리케이션이다. 이를 업무 사용자로 사용하면 모든 MCP 요청이 같은 사람 권한으로 해석되는 오류가 생긴다. 서비스 승인과 업무 사용자 신원을 분리하면 기존 사용자·그룹·권한 관리 모델을 유지하면서 DDS가 사용자별 `DATA ROLE`/`DATA GRANT` 집행한다.
client-credentials token의 `client_id`/`sub`는 서비스 애플리케이션이다. 이를 업무 사용자로 사용하면 모든 MCP 요청이 같은 사람 권한으로 해석되는 오류가 생긴다. 서비스 승인과 업무 사용자 신원을 분리하면 기존 사용자·그룹·권한 관리 모델을 유지하면서 DDS가 local END USER Context와 `DATA GRANT` predicate로 권한을 집행한다.
## 검증

View File

@@ -0,0 +1,40 @@
# ADR-0002: DDS 권한은 기존 권한 테이블을 런타임에 판정한다
> **상태**: Accepted · **날짜**: 2026-07-03 · **관련 이슈**: #617
## 맥락
현재 PoC는 `CB_*` 사용자·그룹·역할·퍼미션 모델을 사용자별 local DDS `DATA ROLE``DATA GRANT`로 게시한다. 권한 변경 뒤 즉시 집행하려면 영향을 받는 모든 사용자의 DDS DDL을 재생성해야 한다. 이는 권한 원천이 두 곳이 되고, 동기화 실패·지연·drift를 만든다.
DDS `DATA GRANT`의 predicate는 SQL 서브쿼리와 `ORA_END_USER_CONTEXT`를 사용할 수 있다. 컬럼 권한은 Data Grant의 `SELECT (column...)`/`UPDATE (column...)`으로 정적 선언되지만, 그 Grant의 predicate는 매 SQL 실행 때 권한 테이블을 조회할 수 있다.
## 결정
1. `CB_*` 권한 테이블을 업무 권한의 유일한 원천으로 둔다.
2. `ADMIN.DDS_MCP_AUTHZ_PKG`의 definer-rights 함수를 통해 local DDS END USER를 업무 사용자로 해석하고, Object·CRUD·컬럼 그룹·행 속성에 대한 권한을 런타임에 판정한다.
3. DDS에는 보호 Object/CRUD/컬럼 그룹별 장기 `DATA GRANT`를 한 번 provisioning한다. 각 predicate는 `ORA_END_USER_CONTEXT.username`과 DDL에 고정한 whitelist Object·동작·컬럼 그룹을 함수에 전달한다.
4. 모든 MCP END USER에는 공통 `DDS_MCP_RUNTIME` DATA ROLE만 부여한다. 권한 테이블의 값 변경은 DDL 없이 다음 쿼리부터 반영한다.
5. 새 보호 Object·컬럼·CRUD, 또는 컬럼 그룹 재설계는 검토된 DDL provisioning 대상이다. 사용자/그룹/역할/퍼미션 값 변경은 provisioning 대상이 아니다.
## 결과
- 권한 변경의 즉시성은 권한 테이블 transaction commit으로 보장한다.
- Object/컬럼 목록은 여전히 정적이다. 함수는 컬럼 목록을 동적으로 만들거나 클라이언트 제공 Object 명으로 dynamic SQL을 실행하지 않는다.
- 셀 수준 제어는 고정 컬럼 그룹별 Grant와 동적 predicate를 결합한다. 여러 Grant는 additive이므로 광범위한 공통 `SELECT` Grant를 만들지 않는다.
- 함수는 권한 테이블을 보호 대상 Object와 분리해 조회해야 한다. 동일 Object 재조회는 순환 predicate 오류를 만든다.
- 권한 테이블은 같은 Oracle DB에 있어야 한다. DB link/원격 권한 원천은 DDS predicate에서 지원하지 않는다.
- 현재 사용자별 재게시 구현은 전환 기간의 PoC다. 기능 이행과 회귀 검증 후 `DdsMcpAuthorizationChangeListener`의 bulk publish 의존성을 제거한다.
## 대안
### 사용자별 DDS Grant 재게시
권한 계산 결과가 DB dictionary에 명시적으로 남고 쿼리 비용이 낮다는 장점이 있다. 그러나 권한 원천을 복제하고, 변경마다 bulk DDL·실패 복구·drift 관리가 필요해 채택하지 않는다.
### MCP Tool이 권한을 판정한 뒤 SQL을 선택
애플리케이션 버그·우회 경로·새 Tool이 데이터 보호를 무력화할 수 있어 채택하지 않는다. 판정은 보호 SQL과 같은 DB에서 DDS predicate로 집행한다.
### 컬럼별 동적 View 마스킹
View의 `CASE`와 함수로 구현할 수 있으나, 원본 Object 차단·View 권한·함수 성능을 별도로 보장해야 한다. DDS 컬럼 Grant가 필요한 기본 경로의 대체안으로 사용하지 않는다.