[Architect] #617 design DDS MCP end-user context
This commit is contained in:
32
docs/adr/0001-dds-mcp-service-identity.md
Normal file
32
docs/adr/0001-dds-mcp-service-identity.md
Normal file
@@ -0,0 +1,32 @@
|
||||
# ADR-0001: DDS MCP Context에는 개인 IAM 사용자 대신 서비스 애플리케이션을 사용한다
|
||||
|
||||
> **상태**: Proposed
|
||||
> **날짜**: 2026-07-01 · **결정자**: [AI] Architect · **관련 이슈**: #617
|
||||
|
||||
## 맥락 (Context)
|
||||
|
||||
MCP SSE 서비스는 자체 Bearer로 애플리케이션 사용자를 식별하고, local DDS END USER Context를 부착해 Tool SQL을 실행해야 한다. application-mediated DDS Context에는 database-access token이 필요하다.
|
||||
|
||||
개인 IAM 사용자 `joungmin.ko@oracle.com`의 장기 token을 서비스 설정에 넣으면 개인 계정 수명주기, 감사, 회전, 퇴사, 권한 범위가 MCP 서비스의 가용성과 보안 경계에 직접 결합된다.
|
||||
|
||||
## 결정 (Decision)
|
||||
|
||||
`mcp-dds-service`라는 OCI IAM 서비스 애플리케이션을 별도로 등록하고, client-credentials flow로 short-lived database-access token을 취득한다. MCP 사용자는 IAM 사용자가 아니라 기존 `CB_APP_USER` 및 로컬 DDS END USER로 관리한다.
|
||||
|
||||
이 결정은 P0 스파이크에서 실제 OCI tenancy/ADB 설정으로 Context attach가 증명되기 전까지 Proposed 상태다.
|
||||
|
||||
## 근거 (Rationale)
|
||||
|
||||
서비스 신뢰와 업무 사용자 신원을 분리한다. database-access token은 서비스의 Context 부착 권한이고, DDS END USER는 DB가 DATA ROLE/DATA GRANT를 집행할 실제 권한 주체다.
|
||||
|
||||
## 결과 (Consequences)
|
||||
|
||||
- **긍정**: 개인 계정과 서비스 실행 권한을 분리하고, 사용자별 IAM 계정 없이 DDS Context를 적용할 수 있다.
|
||||
- **부정 / 비용**: OCI IAM 애플리케이션 등록, token cache/rotation, TLS/DB identity 구성, secret 관리가 필요하다.
|
||||
- **후속 작업**: Free Identity Domain entitlement, client-credentials database token, ADB local END USER Context attach를 스파이크로 검증한다.
|
||||
|
||||
## 검토한 대안 (Alternatives Considered)
|
||||
|
||||
- **개인 IAM 사용자 token 고정** — 개인 수명주기·감사·권한 회전에 서비스가 종속되어 기각.
|
||||
- **MCP 사용자마다 IAM 사용자 생성** — ERP/기존 사용자 관리 모델을 IAM으로 중복 이전해야 하므로 기각.
|
||||
- **IAM 없이 자체 Bearer만 사용** — application-mediated DDS Context attach에 필요한 database-access token을 제공하지 못하므로 기각.
|
||||
211
docs/design/617-dds-mcp-end-user-context/README.md
Normal file
211
docs/design/617-dds-mcp-end-user-context/README.md
Normal file
@@ -0,0 +1,211 @@
|
||||
# 설계서: DDS MCP 사용자별 END USER Context 및 권한 게시 (#617)
|
||||
|
||||
> **상태**: Draft — P0 스파이크 승인 전 구현 금지
|
||||
> **작성**: [AI] Architect · **최종수정**: 2026-07-01
|
||||
> **추적성** — Redmine: #617 · 관련 ADR: [ADR-0001](../../adr/0001-dds-mcp-service-identity.md)
|
||||
> · 구현 파일: TBD · 테스트: TBD
|
||||
|
||||
## 1. 목적 (Why)
|
||||
|
||||
MCP SSE 서비스가 요청자의 권한을 대신 판단하거나 SQL에 조건을 덧붙이지 않고, 각 Tool의 DB 작업을 해당 요청자에 대응하는 Oracle Deep Data Security(DDS) END USER Context로 실행한다.
|
||||
|
||||
VPD 트랙은 기존 구현과 데이터 모델을 변경하지 않는다. DDS 트랙은 별도의 보호 객체, 별도의 권한 게시 모델, 별도의 런타임 Context 경로를 갖는다.
|
||||
|
||||
## 2. 범위 (Scope)
|
||||
|
||||
- **포함**
|
||||
- MCP Bearer → `CB_APP_USER` → 로컬 DDS END USER의 명시적 매핑.
|
||||
- MCP Tool 호출마다 DDS END USER Context를 부착·해제하는 실행 경계.
|
||||
- 보호 데이터 객체, 접근 역할, 테이블 세부 권한, 사용자/그룹 역할 할당을 관리하는 DDS 전용 백오피스 모델.
|
||||
- 역할·그룹의 유효 멤버십을 DDS `END USER` / `DATA ROLE` / `DATA GRANT` DDL로 게시·회수·검증하는 Publisher.
|
||||
- OCI IAM 서비스 애플리케이션 database-access token과 local END USER lookup key의 기술 스파이크.
|
||||
- **제외 (out of scope)**
|
||||
- VPD 정책, VPD 백오피스, 기존 `CB_AGENT_CTX` 경로의 변경.
|
||||
- MCP 사용자마다 OCI IAM 사용자를 생성·관리하는 기능.
|
||||
- 사용자 요청 시점의 `CREATE END USER`, `GRANT DATA ROLE`, `CREATE DATA GRANT` 수행.
|
||||
- 임의 SQL predicate 입력 및 기존 VPD `DENY 우선` 규칙의 자동 변환.
|
||||
- OCI IAM 도메인/애플리케이션 등록의 실제 운영 배포. 스파이크 성공 후 별도 작업으로 분리한다.
|
||||
|
||||
## 3. 인수조건 (Acceptance Criteria)
|
||||
|
||||
- [ ] 활성 MCP Bearer는 정확히 하나의 활성 `CB_APP_USER`로 해석되며, DDS END USER 매핑이 없으면 Tool 실행 전에 권한 없음으로 종료된다.
|
||||
- [ ] 동일한 공용 연결 풀에서 서로 다른 두 요청자가 연속·동시 Tool을 호출해도 각 요청은 자신의 DDS END USER Context와 DATA GRANT 결과만 받는다.
|
||||
- [ ] 예외·취소·타임아웃을 포함한 모든 실행 경로에서 Context가 해제되어 다음 요청에 이전 권한이 남지 않는다.
|
||||
- [ ] 백오피스 게시기는 사용자/그룹 역할 할당과 테이블 세부 권한을 idempotent DDS DDL로 반영하며, 게시 diff·사유·결과·드리프트를 보관한다.
|
||||
- [ ] 그룹 멤버 추가/제거 후 게시하면 필요한 DDS END USER/DATA ROLE은 부여되고 불필요한 역할은 회수된다.
|
||||
- [ ] MCP Tool SQL은 권한 `WHERE`를 직접 만들지 않으며, DDS DATA GRANT가 반환 행·컬럼을 제한한다.
|
||||
- [ ] 미매핑·비활성·회수된 Bearer, 미게시 사용자, DATA GRANT 없는 사용자, Context attach 실패는 fail-closed로 처리한다.
|
||||
- [ ] VPD 회귀 테스트가 통과하며 VPD 스키마·정책·UI에 변경이 없다.
|
||||
|
||||
## 4. 컨텍스트 & 제약
|
||||
|
||||
- 기존 `CB_BEARER_TOKEN`/`CB_APP_USER`는 애플리케이션 논리 사용자 식별 수단이다. DDS 내장 인증 객체가 아니다.
|
||||
- 로컬 DDS END USER는 `CREATE END USER`로 별도 생성한다. ERP/MCP 사용자는 IAM 사용자가 아니어도 되지만, DDS END USER는 사용자별로 존재한다.
|
||||
- MCP SSE 서비스는 공용 DB 연결을 사용한다. DDS END USER Context는 SSE 연결 전체가 아니라 **매 Tool DB 실행 경계**마다 부착·해제한다.
|
||||
- application-mediated local END USER Context에는 서비스 애플리케이션의 database-access token이 필요하다. 개인 IAM 사용자 토큰을 장기 설정값으로 저장하지 않는다.
|
||||
- 서비스 애플리케이션의 OCI IAM 등록, token 발급, TLS/DB 설정, lookup key 발급은 P0 스파이크로 검증되기 전에는 구현 사실로 간주하지 않는다.
|
||||
- DDS DATA GRANT는 additive다. 여러 DATA ROLE의 권한은 합집합이므로 VPD의 `DENY 우선` 의미를 자동 보존할 수 없다.
|
||||
- END USER 이름은 ASCII 안정 식별자 `DDS_U_<CB_APP_USER.user_id>`를 사용한다. 표시 이름·한글 로그인명과 분리한다.
|
||||
|
||||
## 5. 아키텍처 개요
|
||||
|
||||
### 5.1 두 평면
|
||||
|
||||
```text
|
||||
권한 게시 평면
|
||||
백오피스
|
||||
→ 보호 데이터 객체 / 접근 역할 / 세부 권한 / 사용자·그룹 할당
|
||||
→ 유효 멤버십 계산
|
||||
→ DDS Publisher
|
||||
→ END USER · DATA ROLE · DATA GRANT DDL
|
||||
→ 게시 이력 · 검증 · 드리프트 상태
|
||||
|
||||
요청 실행 평면
|
||||
MCP Client Bearer
|
||||
→ MCP SSE 인증
|
||||
→ CB_BEARER_TOKEN / CB_APP_USER 확인
|
||||
→ DDS END USER 매핑 확인
|
||||
→ 서비스 IAM database-access token + lookup key로 Context 부착
|
||||
→ MCP Tool DB 작업
|
||||
→ DDS DATA GRANT 집행
|
||||
→ Context 해제
|
||||
```
|
||||
|
||||
### 5.2 신원 분리
|
||||
|
||||
| 항목 | 의미 | 관리 주체 |
|
||||
|---|---|---|
|
||||
| MCP Bearer | MCP 요청자가 어느 애플리케이션 사용자 인지 식별 | 기존 `CB_BEARER_TOKEN` |
|
||||
| 애플리케이션 사용자 | 업무 사용자·그룹·역할 할당의 기준 | `CB_APP_USER` 및 DDS 전용 할당 모델 |
|
||||
| DDS END USER | DB가 DATA ROLE/DATA GRANT를 집행하는 보안 주체 | DDS Publisher |
|
||||
| Database-access token | MCP SSE 서비스가 Context를 부착할 수 있다는 애플리케이션 신뢰 | OCI IAM 서비스 애플리케이션 |
|
||||
|
||||
### 5.3 실행 경계
|
||||
|
||||
`McpDdsContextExecutor`만 보호 객체용 연결을 획득한다. 이 경계는 다음 순서를 강제한다.
|
||||
|
||||
1. Bearer를 재검증하고 활성 애플리케이션 사용자를 찾는다.
|
||||
2. 게시 완료된 DDS END USER 매핑과 lookup key 참조를 찾는다.
|
||||
3. 서비스 database-access token을 획득/갱신한다.
|
||||
4. 연결에 DDS END USER Context를 부착한다.
|
||||
5. Tool의 제한된 DB 작업을 실행한다.
|
||||
6. `finally`에서 Context를 해제한 뒤 연결을 반환한다.
|
||||
|
||||
Tool·Repository는 Context 설정 API, DATA GRANT DDL, 원시 Bearer를 직접 다루지 않는다.
|
||||
|
||||
## 6. 데이터 모델
|
||||
|
||||
기존 VPD 공통 권한 테이블은 읽거나 변경하지 않는다. DDS 게시용 모델은 별도 관리한다.
|
||||
|
||||
| 개념 | 잠정 저장 구조 | 핵심 값 |
|
||||
|---|---|---|
|
||||
| 보호 데이터 객체 | `CB_DDS_PROTECTED_OBJECT` | object owner/name, Tool 노출명, 활성 상태 |
|
||||
| 접근 역할 | `CB_DDS_ACCESS_ROLE` | 표시명, `DATA ROLE` 이름, 상태 |
|
||||
| 테이블 세부 권한 | `CB_DDS_OBJECT_GRANT` | 역할, 객체, action, 허용/제외 컬럼, 행 조건 DSL |
|
||||
| 역할 할당 | `CB_DDS_ROLE_ASSIGNMENT` | 역할, 대상 유형(USER/GROUP), 대상 ID |
|
||||
| DDS END USER 매핑 | `CB_DDS_END_USER_MAP` | `CB_APP_USER.user_id`, DDS END USER 이름, 게시 상태, lookup key 참조 |
|
||||
| 게시 실행 | `CB_DDS_PUBLISH_RUN` / 항목 | diff, 사유, 실행 결과, DDL fingerprint, 검증 결과 |
|
||||
|
||||
행 조건은 자유 SQL 문자열이 아니다. 객체별 허용 컬럼, 비교 연산자, 리터럴 타입, `ORA_END_USER_CONTEXT` 허용 경로만으로 구성된 DSL을 Publisher가 검증된 SQL predicate로 컴파일한다.
|
||||
|
||||
## 7. 함수 명세 (Function Specs)
|
||||
|
||||
| 함수 | 책임(1줄) | 시그니처(잠정) | 입력 | 출력 | 에러/실패 | 복잡? |
|
||||
|---|---|---|---|---|---|---|
|
||||
| `authenticateMcpBearer` | Bearer를 활성 업무 사용자로 해석 | `Bearer → AppUser` | Bearer | `AppUser` | 미존재·만료·회수 → deny | **복잡** |
|
||||
| `resolveDdsEndUser` | 업무 사용자의 게시된 DDS END USER를 찾음 | `AppUser → DdsPrincipal` | 사용자 ID | END USER/lookup key 참조 | 미매핑·미게시 → deny | 단순 |
|
||||
| `getDatabaseAccessToken` | 서비스용 short-lived DB access token을 제공 | `() → Token` | 서비스 IAM 설정 | token | 발급 실패 → fail closed | **복잡** |
|
||||
| `withDdsEndUserContext` | Context를 부착·DB 작업·해제를 원자적으로 수행 | `(DdsPrincipal, SqlWork) → T` | DDS principal, 작업 | 결과 | attach/query/clear 실패 | **복잡** |
|
||||
| `compileDdsPublishPlan` | 백오피스 권한 모델을 DDL diff로 변환 | `Draft → PublishPlan` | 객체/역할/할당 | DDL plan | DSL/충돌/deny 규칙 오류 | **복잡** |
|
||||
| `publishDdsPlan` | 승인된 plan을 멱등 게시하고 검증 | `PublishPlan → PublishRun` | plan, 사유 | 결과/증적 | 부분 실패·drift | **복잡** |
|
||||
| `verifyDdsIsolation` | 대표 사용자별 Context·객체·행·컬럼 결과를 확인 | `PublishRun → Verification` | 사용자 matrix | 검증 결과 | context 누수·권한 불일치 | **복잡** |
|
||||
|
||||
복잡 함수의 세부 명세는 다음 문서로 분리한다.
|
||||
|
||||
- [Bearer 인증](fn-authenticate-mcp-bearer.md)
|
||||
- [서비스 database-access token](fn-get-database-access-token.md)
|
||||
- [DDS Context 실행 경계](fn-with-dds-end-user-context.md)
|
||||
- [DDS 게시 계획 컴파일](fn-compile-dds-publish-plan.md)
|
||||
- [DDS 게시·검증](fn-publish-and-verify-dds-plan.md)
|
||||
|
||||
## 8. 흐름 / 알고리즘
|
||||
|
||||
### 8.1 권한 게시
|
||||
|
||||
1. 운영자가 보호 객체, 접근 역할, 세부 권한, 사용자/그룹 할당을 수정한다.
|
||||
2. Publisher는 그룹을 포함한 역할별 유효 사용자를 계산한다.
|
||||
3. 누락된 사용자에 대해 비밀번호 없는 DDS END USER 생성 계획을 만든다.
|
||||
4. 역할별 DATA ROLE과 객체별 DATA GRANT의 생성·교체·회수 diff를 만든다.
|
||||
5. 승인된 plan만 실행한다. 요청 실행 경로에서는 DDL을 실행하지 않는다.
|
||||
6. 게시 후 END USER/ROLE/GRANT dictionary와 대표 사용자 matrix를 확인한다.
|
||||
|
||||
### 8.2 MCP Tool 실행
|
||||
|
||||
1. MCP 요청의 Bearer를 검증한다.
|
||||
2. 사용자·DDS END USER 매핑·게시 상태를 확인한다.
|
||||
3. Context 부착 전에 미매핑/비활성/회수 상태면 권한 없음으로 중단한다.
|
||||
4. Tool의 DB 작업을 DDS Context 안에서 실행한다.
|
||||
5. 성공·실패와 상관없이 Context를 제거한다.
|
||||
6. MCP 응답에는 Tool이 반환한 DDS 제한 결과만 포함한다. END USER 이름, lookup key, database-access token은 노출하지 않는다.
|
||||
|
||||
## 9. 엣지케이스 & 에러 처리
|
||||
|
||||
| 상황 | 처리 |
|
||||
|---|---|
|
||||
| Bearer가 없거나 회수됨 | 인증 실패. DDS END USER 조회/부착을 시도하지 않는다. |
|
||||
| 사용자 매핑 없음 | 권한 없음. 요청 중 END USER를 생성하지 않는다. |
|
||||
| 사용자 비활성/게시 실패/drift | 권한 없음. 마지막 성공 게시 결과를 사용하지 않는다. |
|
||||
| Context attach 실패 | Tool SQL을 실행하지 않는다. correlation ID만 기록한다. |
|
||||
| Tool SQL 예외/취소/시간초과 | `finally`에서 Context 해제 후 안전한 오류 응답. |
|
||||
| 연결 풀 재사용 | 매 DB 작업에 새 Context를 부착하고 `finally`에서 해제한다. |
|
||||
| 그룹에서 사용자 제거 | 다음 게시에서 DATA ROLE 회수, 이후 요청은 새 게시 결과만 사용한다. |
|
||||
| 비ASCII 업무 사용자명 | `DDS_U_<id>`를 사용하며 표시명과 END USER 식별자를 분리한다. |
|
||||
| VPD DENY 규칙 | DDS 1차 모델에서 미지원. 게시 전 오류로 차단한다. |
|
||||
|
||||
## 10. 테스트 계획
|
||||
|
||||
| 인수조건 | 검증 |
|
||||
|---|---|
|
||||
| Context 사용자 격리 | 같은 공용 풀에서 A → B → A 순서와 동시 실행. `ORA_END_USER_CONTEXT.username` 및 결과 행/컬럼이 각 사용자와 일치. |
|
||||
| Context 해제 | Tool 예외·취소·타임아웃 뒤 다음 요청이 이전 사용자의 Context를 갖지 않음. |
|
||||
| 토큰 fail-closed | 미존재·만료·회수 Bearer와 미매핑 사용자 모두 SQL 실행 전 거부. |
|
||||
| 역할/그룹 게시 | 직접 사용자·그룹 추가/제거 후 예상 DATA ROLE grant/revoke와 결과 확인. |
|
||||
| 세부 권한 | 역할별 객체 차단, 행 조건, 컬럼 제외, 다중 역할 합집합을 검증. |
|
||||
| DDL 멱등성 | 동일 plan 재게시가 변경 없음으로 완료. |
|
||||
| 드리프트 | dictionary의 END USER/DATA ROLE/DATA GRANT를 의도적으로 변경한 뒤 탐지. |
|
||||
| VPD 회귀 | 기존 VPD Maven/SQL/HTTP 회귀 테스트 전체 통과. |
|
||||
| P0 스파이크 | OCI IAM 서비스 token + local END USER name/lookup key로 Context attach 성공 및 두 사용자 격리 증명. |
|
||||
|
||||
## 11. 리스크 & 대안 검토
|
||||
|
||||
### 선택: DDS 선언 게시 + MCP Context 부착
|
||||
|
||||
권한을 백오피스에서 검토·승인·게시하고, MCP Tool은 게시된 DDS 권한을 집행한다. Agent가 SQL을 만들더라도 DB가 결과를 제한한다.
|
||||
|
||||
### 대안: 기존 VPD 공통 권한 테이블을 요청마다 동적 해석
|
||||
|
||||
기존 VPD 모델과 즉시 반영 특성은 유지하지만, DDS DATA ROLE/DATA GRANT를 권한의 단일 출처로 쓰려는 목표와 맞지 않는다. VPD 트랙에 남긴다.
|
||||
|
||||
### 대안: 사용자별 IAM 계정
|
||||
|
||||
IAM token claim에서 DATA ROLE을 직접 활성화할 수 있으나 ERP/MCP 사용자 관리 주체를 IAM으로 옮겨야 한다. 이번 범위에서는 제외한다.
|
||||
|
||||
### 주요 리스크
|
||||
|
||||
- local END USER application-mediated Context에는 service IAM database-access token이 필요하다.
|
||||
- lookup key 생성/보관 방식이 미확정이다.
|
||||
- DDS 권한은 additive이므로 VPD DENY 우선 모델을 그대로 이식할 수 없다.
|
||||
- Publisher의 partial failure는 사용자별 권한 불일치를 만들 수 있으므로 실행 plan, compensation, drift 탐지가 필요하다.
|
||||
|
||||
OCI IAM 서비스 애플리케이션의 도메인·token flow·비밀 보관 방식은 되돌리기 어려우므로 ADR로 분리한다.
|
||||
|
||||
## 12. 미해결 질문 (Open Questions)
|
||||
|
||||
1. local END USER security-context lookup key의 정확한 생성 API/명령, 회전·보관 기준은 무엇인가?
|
||||
2. 현재 OCI tenancy의 Free Identity Domain에서 DDS용 application registration 및 client-credentials database-access token을 발급할 수 있는가?
|
||||
3. ADB의 TLS, identity provider, application identity, pool account에 필요한 정확한 설정·권한은 무엇인가?
|
||||
4. Java 26ai JDBC artifact/API와 현재 `dds-backoffice`의 OJDBC 버전·Spring pool이 Context attach를 지원하는가?
|
||||
5. VPD의 DENY 규칙을 DDS 1차 모델에서 명시적으로 제외할지, 제한된 조합 규칙으로 컴파일할지?
|
||||
6. Data Grant의 다중 역할 컬럼/행 합집합 의미를 실제 ADB에서 어떤 matrix로 검증할지?
|
||||
|
||||
이 여섯 항목은 P0 스파이크가 승인되기 전까지 임의 구현으로 채우지 않는다.
|
||||
@@ -0,0 +1,28 @@
|
||||
# 함수 명세: `authenticateMcpBearer` (#617)
|
||||
|
||||
> **상태**: Draft · **분류**: 복잡 — 인증 저장소 I/O 및 fail-closed 경계
|
||||
|
||||
## 책임
|
||||
|
||||
MCP Tool 호출의 Bearer를 기존 애플리케이션 사용자로 해석한다. DDS 역할·DDL을 결정하지 않는다.
|
||||
|
||||
## 시그니처
|
||||
|
||||
`BearerToken -> AuthenticatedAppUser`
|
||||
|
||||
## 입력과 출력
|
||||
|
||||
- 입력: `Authorization: Bearer <opaque-token>`에서 추출한 원문 token.
|
||||
- 출력: 활성 `CB_APP_USER`의 `userId`, 표시명, token 식별자, 검증 시각.
|
||||
|
||||
## 규칙
|
||||
|
||||
1. token 형식·길이를 먼저 검증한다.
|
||||
2. 해시 비교, 만료, 회수, 활성 사용자 여부를 한 트랜잭션에서 검증한다.
|
||||
3. token이 없거나 하나의 활성 사용자로 해석되지 않으면 동일한 권한 없음 결과를 반환한다.
|
||||
4. 원문 token, 해시, 사용자 상세를 로그·MCP 응답에 넣지 않는다.
|
||||
5. 각 Tool 호출마다 재검증한다. SSE 연결 생성 시점의 결과를 재사용하지 않는다.
|
||||
|
||||
## 실패
|
||||
|
||||
`AUTHORIZATION_DENIED`로 fail-closed한다. DDS Context 부착과 DB Tool SQL을 호출하지 않는다.
|
||||
@@ -0,0 +1,33 @@
|
||||
# 함수 명세: `compileDdsPublishPlan` (#617)
|
||||
|
||||
> **상태**: Draft · **분류**: 복잡 — 권한 컴파일·DDL diff·안전 검증
|
||||
|
||||
## 책임
|
||||
|
||||
DDS 백오피스의 보호 객체, 접근 역할, 테이블 세부 권한, 사용자/그룹 할당을 실행 가능한 DDS DDL diff로 바꾼다.
|
||||
|
||||
## 시그니처
|
||||
|
||||
`DdsAuthorizationDraft -> DdsPublishPlan`
|
||||
|
||||
## 규칙
|
||||
|
||||
1. 그룹을 포함해 역할별 유효 사용자를 계산한다.
|
||||
2. `CB_APP_USER.userId`마다 ASCII `DDS_U_<id>` END USER 이름을 결정한다.
|
||||
3. 접근 역할마다 하나의 stable DATA ROLE 이름을 결정한다.
|
||||
4. 사용자·역할·객체·세부 권한의 현재 게시 상태와 목표 상태를 비교한다.
|
||||
5. 생성/교체/회수 DDL과 예상 영향 사용자·객체를 계산한다.
|
||||
6. 행 조건 DSL은 whitelist 기반 compiler만 사용한다. raw SQL은 거부한다.
|
||||
7. `DENY` 또는 지원하지 않는 권한 조합은 plan 생성 단계에서 오류로 끝낸다.
|
||||
|
||||
## 출력
|
||||
|
||||
- END USER 생성/활성화/비활성화 목록
|
||||
- DATA ROLE 생성/역할 부여/회수 목록
|
||||
- DATA GRANT 생성·교체·삭제 목록
|
||||
- 예상 영향 사용자·객체·컬럼 matrix
|
||||
- 이전/목표 fingerprint와 승인 대상 diff
|
||||
|
||||
## 실패
|
||||
|
||||
충돌, 비활성 객체, DSL 오류, DENY 규칙, 이름 충돌은 게시 전에 차단한다.
|
||||
@@ -0,0 +1,28 @@
|
||||
# 함수 명세: `getDatabaseAccessToken` (#617)
|
||||
|
||||
> **상태**: Draft · **분류**: 복잡 — OCI IAM 외부 I/O·비밀·만료 관리
|
||||
|
||||
## 책임
|
||||
|
||||
MCP SSE 서비스 애플리케이션의 short-lived database-access token을 제공한다. MCP 사용자 Bearer와 혼동하거나 대체하지 않는다.
|
||||
|
||||
## 시그니처
|
||||
|
||||
`() -> DatabaseAccessToken`
|
||||
|
||||
## 규칙
|
||||
|
||||
1. 개인 IAM 사용자(`joungmin.ko@oracle.com`)의 장기 token을 사용하지 않는다.
|
||||
2. `mcp-dds-service` 전용 OCI IAM 애플리케이션의 client-credentials flow를 사용한다.
|
||||
3. access token은 만료 전 안전 여유를 두고 갱신하며, 원문을 로그·DB·Redmine에 저장하지 않는다.
|
||||
4. 토큰 발급 실패 시 이전 만료 token을 재사용하지 않고 Tool DB 작업을 차단한다.
|
||||
5. secret은 배포 환경의 secret store만 사용한다.
|
||||
|
||||
## 스파이크 확인
|
||||
|
||||
- OCI Identity Domain의 무료/현재 entitlement에서 database-access token 발급이 가능한지 확인한다.
|
||||
- ADB의 identity provider, TLS, pool account, application identity 조건을 실제 연결로 확인한다.
|
||||
|
||||
## 실패
|
||||
|
||||
`DDS_CONTEXT_UNAVAILABLE`로 fail-closed한다.
|
||||
@@ -0,0 +1,31 @@
|
||||
# 함수 명세: `publishDdsPlan` 및 `verifyDdsIsolation` (#617)
|
||||
|
||||
> **상태**: Draft · **분류**: 복잡 — 보안 DDL 변경·검증·드리프트
|
||||
|
||||
## 책임
|
||||
|
||||
승인된 DDL plan을 멱등 실행하고, dictionary와 representative END USER matrix로 실제 결과를 확인한다.
|
||||
|
||||
## 시그니처
|
||||
|
||||
- `DdsPublishPlan, Reason -> DdsPublishRun`
|
||||
- `DdsPublishRun -> DdsVerificationResult`
|
||||
|
||||
## 게시 규칙
|
||||
|
||||
1. 승인 사유와 diff fingerprint가 없으면 게시하지 않는다.
|
||||
2. Publisher lock으로 같은 보호 객체의 동시 게시를 막는다.
|
||||
3. END USER/Data Role/Data Grant를 dependency 순서로 적용한다.
|
||||
4. 각 DDL 결과와 Oracle 오류를 `DdsPublishRun`에 기록한다.
|
||||
5. 중간 실패 시 성공으로 표시하지 않는다. 부분 적용 상태로 기록하고 drift로 승격한다.
|
||||
|
||||
## 검증 규칙
|
||||
|
||||
1. `DBA_END_USERS`, `DBA_DATA_ROLES`, `DBA_DATA_ROLE_GRANTS`, `DBA_DATA_GRANTS`를 목표 fingerprint와 비교한다.
|
||||
2. 대표 사용자별 Context, 객체 접근, 행, 컬럼 결과를 검증한다.
|
||||
3. 역할 제거와 객체 미권한 경로도 반드시 검증한다.
|
||||
4. Context attach/clear 격리 검증이 실패하면 publish 결과를 정상으로 표시하지 않는다.
|
||||
|
||||
## 실패
|
||||
|
||||
게시·검증 실패는 `FAILED` 또는 `DRIFT` 상태다. MCP 요청 경로는 마지막 성공 게시 상태를 우회 권한으로 사용하지 않는다.
|
||||
@@ -0,0 +1,36 @@
|
||||
# 함수 명세: `withDdsEndUserContext` (#617)
|
||||
|
||||
> **상태**: Draft · **분류**: 복잡 — 연결 풀 보안 경계
|
||||
|
||||
## 책임
|
||||
|
||||
한 DB 작업을 정확히 하나의 local DDS END USER Context 안에서 실행하고, 어떤 종료 경로에서도 Context를 해제한다.
|
||||
|
||||
## 시그니처
|
||||
|
||||
`(DdsPrincipal, SqlWork<T>) -> T`
|
||||
|
||||
## 입력
|
||||
|
||||
- `DdsPrincipal`: 게시된 DDS END USER 이름, lookup key 참조, 사용자 ID, 게시 version.
|
||||
- `SqlWork<T>`: 보호 객체를 읽거나 쓰는 제한된 Tool DB 작업.
|
||||
|
||||
## 알고리즘
|
||||
|
||||
1. `DdsPrincipal`이 활성·게시 완료 상태인지 확인한다.
|
||||
2. 공용 연결을 획득하고 서비스 database-access token을 얻는다.
|
||||
3. local END USER 이름과 lookup key로 DDS Context를 부착한다.
|
||||
4. `SqlWork`를 실행한다. Repository는 Context 설정/해제를 직접 호출할 수 없다.
|
||||
5. 성공·실패·취소·시간초과와 무관하게 `finally`에서 Context를 해제한다.
|
||||
6. 해제 실패는 연결을 풀에 반환하지 않고 폐기한다.
|
||||
|
||||
## 보안 불변식
|
||||
|
||||
- 하나의 Tool DB 작업에는 하나의 DDS END USER만 존재한다.
|
||||
- 이전 Tool의 Context가 다음 Tool에 남아서는 안 된다.
|
||||
- Context 부착 이전과 해제 이후에는 보호 SQL을 실행하지 않는다.
|
||||
- local END USER의 DATA ROLE은 payload로 임의 추가하지 않고, 게시된 DDS DDL에서만 얻는다.
|
||||
|
||||
## 스파이크 확인
|
||||
|
||||
동일 풀 연결에서 사용자 A → B → A와 동시 요청을 실행해 `ORA_END_USER_CONTEXT.username`, 행, 컬럼이 각각 맞는지 확인한다.
|
||||
Reference in New Issue
Block a user