|
|
|
|
@@ -1,110 +1,148 @@
|
|
|
|
|
# 설계서: DDS MCP 사용자별 END USER Context 및 권한 게시 (#617)
|
|
|
|
|
# 설계서: DDS MCP END USER Context 및 런타임 권한 판정 (#617)
|
|
|
|
|
|
|
|
|
|
> **상태**: Implemented — OCI IAM·ADB·SSE 실증 완료
|
|
|
|
|
> **최종수정**: 2026-07-02
|
|
|
|
|
> **추적성** — Redmine: #617 · 관련 ADR: [ADR-0001](../../adr/0001-dds-mcp-service-identity.md)
|
|
|
|
|
> · 구현: `DdsMcpBearerAuthenticator`, `DdsMcpEndUserResolver`, `DdsMcpContextExecutor`, `DdsMcpSseController`
|
|
|
|
|
> · DB 게시: `sql/adb/44_dds_mcp_local_end_user_setup.sql`
|
|
|
|
|
> **상태**: Context 경로 Implemented · 런타임 권한 함수 설계 Approved, 이행 Pending
|
|
|
|
|
> **최종수정**: 2026-07-03
|
|
|
|
|
> **추적성** — Redmine: #617 · 관련 ADR: [ADR-0001](../../adr/0001-dds-mcp-service-identity.md), [ADR-0002](../../adr/0002-dds-runtime-permission-source.md)
|
|
|
|
|
> · 현재 구현: `DdsMcpBearerAuthenticator`, `DdsMcpEndUserResolver`, `DdsMcpContextExecutor`, `DdsMcpSseController`
|
|
|
|
|
> · 기존 PoC 게시: `sql/adb/44_dds_mcp_local_end_user_setup.sql`
|
|
|
|
|
> · 검증: `sql/adb/45_dds_mcp_local_end_user_test.sql`, SSE `tools/call`
|
|
|
|
|
|
|
|
|
|
## 1. 결정과 목적
|
|
|
|
|
|
|
|
|
|
MCP Tool의 보호 SQL은 요청 Bearer가 지정한 업무 사용자의 local DDS `END USER` Context에서만 실행한다. DDS가 `DATA ROLE`과 `DATA GRANT`로 행·컬럼 접근을 집행하며, Tool은 권한 predicate를 직접 만들지 않는다.
|
|
|
|
|
MCP Tool의 보호 SQL은 요청 Bearer가 지정한 업무 사용자의 local DDS `END USER` Context에서만 실행한다. OCI IAM Confidential Application은 이 Context attach를 승인하는 서비스 신원이며, 사람 사용자 계정을 IAM에 만들 필요는 없다.
|
|
|
|
|
|
|
|
|
|
VPD 경로는 변경하지 않는다. 기존 DDS 관리의 권한 게시 경계는 MCP용 END USER/역할/grant도 함께 갱신한다.
|
|
|
|
|
업무 사용자·그룹·역할·퍼미션(`CB_APP_USER`, `CB_USER_ROLE`, `CB_USER_GROUP`, `CB_GROUP_ROLE`, `CB_PERMISSION`, 규칙·컬럼 테이블)은 권한의 단일 원천이다. DDS는 이 원천을 복제한 사용자별 Grant를 매 변경마다 재생성하는 대신, 보호 Object/행/컬럼 그룹별로 미리 만든 `DATA GRANT`가 DB 소유 권한 판정 함수를 호출하도록 한다.
|
|
|
|
|
|
|
|
|
|
따라서 **역할·퍼미션 변경은 다음 SQL부터 반영되고 DDS DDL 재게시가 필요 없다.** 새 보호 Object·새 컬럼·새 CRUD 동작을 등록하는 경우에만 안전하게 검토한 DDL을 한 번 provisioning한다.
|
|
|
|
|
|
|
|
|
|
## 2. 토큰과 사용자 — 반드시 구분할 것
|
|
|
|
|
|
|
|
|
|
| 값 | 현재 구현에서의 역할 | 사람 사용자인가 |
|
|
|
|
|
| 값 | 역할 | 사람 사용자인가 |
|
|
|
|
|
|---|---|---|
|
|
|
|
|
| MCP 요청 Bearer | `CB_AGENT_BEARER_KEY` 해시·만료·회수 검증 후 `CB_APP_USER`를 결정 | **예.** DB의 업무 사용자 매핑 기준 |
|
|
|
|
|
| local DDS END USER | `DDS_U_<CB_APP_USER.user_id>` | **예.** DDS가 집행하는 보안 주체 |
|
|
|
|
|
| OCI IAM database-access token | Confidential application의 client-credentials로 매 Tool Context attach를 승인 | 아니오. 서비스 애플리케이션 신원 |
|
|
|
|
|
| OCI IAM end-user token | 향후 authorization-code/OBO 전용 확장 | 현재 MCP 인증 입력으로 사용하지 않음 |
|
|
|
|
|
| MCP 요청 Bearer | 해시·만료·회수 검증 후 `CB_APP_USER`를 결정 | 예. 업무 사용자 매핑 기준 |
|
|
|
|
|
| local DDS END USER | `DDS_U_<CB_APP_USER.user_id>` | 예. DDS가 집행하는 보안 주체 |
|
|
|
|
|
| OCI IAM database-access token | Confidential Application의 client-credentials로 Context attach를 승인 | 아니오. 서비스 애플리케이션 신원 |
|
|
|
|
|
| OCI IAM end-user token | 향후 authorization-code/OBO 확장 | 현재 MCP 인증 입력으로 사용하지 않음 |
|
|
|
|
|
|
|
|
|
|
따라서 현재 MCP Bearer가 `CB_APP_USER`를 지정할 수 있으면 그 사용자별 DDS 권한은 적용된다. 반면 client-credentials 토큰의 `sub`/`client_id`는 서비스 애플리케이션이므로 사람 사용자를 판정하는 데 사용하면 안 된다.
|
|
|
|
|
client-credentials token의 `sub`/`client_id`는 서비스 애플리케이션이다. 이를 업무 사용자로 쓰면 모든 요청이 같은 사람 권한으로 해석된다. MCP Bearer 검증 결과와 local END USER 매핑이 업무 사용자를 결정한다.
|
|
|
|
|
|
|
|
|
|
OCI IAM JWT의 사람 사용자 claim을 그대로 DDS에 전달하려면 별도의 authorization-code 또는 OBO flow, 해당 end-user token 검증, IAM role↔DDS DATA ROLE 매핑으로 확장해야 한다. 이 경로는 현재 local END USER 모델과 혼용하지 않는다.
|
|
|
|
|
|
|
|
|
|
## 3. 실제 아키텍처
|
|
|
|
|
## 3. 목표 아키텍처
|
|
|
|
|
|
|
|
|
|
```text
|
|
|
|
|
권한 관리 / DDS 게시
|
|
|
|
|
CB_APP_USER + 직접/그룹 역할 + CB_PERMISSION 규칙
|
|
|
|
|
→ DDS Publisher
|
|
|
|
|
→ CB_DDS_END_USER_MAP
|
|
|
|
|
→ CREATE END USER DDS_U_<id>
|
|
|
|
|
→ CREATE/GRANT DATA ROLE DDS_U_<id>_ROLE
|
|
|
|
|
→ CREATE DATA GRANT (보호 벡터 객체)
|
|
|
|
|
|
|
|
|
|
MCP SSE Tool 호출
|
|
|
|
|
Authorization: Bearer <MCP bearer>
|
|
|
|
|
→ 매 메시지마다 bearer 검증
|
|
|
|
|
→ CB_APP_USER 확인
|
|
|
|
|
→ 게시된 DDS_U_<id> map 확인
|
|
|
|
|
→ OCI IAM database-access token 취득/캐시
|
|
|
|
|
→ EndUserSecurityContext(name, lookup key) attach
|
|
|
|
|
→ 보호 SQL 실행 (DATA GRANT 집행)
|
|
|
|
|
→ finally: context clear, 연결 반환
|
|
|
|
|
권한 원천 (같은 Oracle DB의 별도 관리 테이블)
|
|
|
|
|
CB_APP_USER + 직접/그룹 역할 + CB_PERMISSION + RULE + COLUMN
|
|
|
|
|
↑
|
|
|
|
|
│ 함수가 매 보호 SQL에서 읽음
|
|
|
|
|
ADMIN.DDS_MCP_AUTHZ_PKG.can_access(...)
|
|
|
|
|
↑
|
|
|
|
|
고정 DDS DATA GRANT ── Object/CRUD/컬럼 그룹별 1회 provisioning
|
|
|
|
|
ON ADMIN.CUSTOMER
|
|
|
|
|
AS SELECT (CUSTOMER_ID, CUSTOMER_NAME)
|
|
|
|
|
WHERE can_access(ORA_END_USER_CONTEXT.username,
|
|
|
|
|
'ADMIN.CUSTOMER', 'SELECT', 'BASIC', ...) = 1
|
|
|
|
|
TO DDS_MCP_RUNTIME
|
|
|
|
|
↑
|
|
|
|
|
local END USER DDS_U_<id> ── GRANT DATA ROLE DDS_MCP_RUNTIME
|
|
|
|
|
↑
|
|
|
|
|
MCP Bearer → CB_APP_USER → EndUserSecurityContext attach
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
SSE 연결 자체는 인증을 보조할 뿐이다. `/dds/mcp/messages`의 **매 요청마다** Bearer와 사용자를 재검증하므로, 연결을 오래 유지해도 이전 사용자 권한을 신뢰하지 않는다.
|
|
|
|
|
`object`, `action`, `column group`은 DATA GRANT 정의에 넣는 검증된 상수다. DDS `WHERE`에 현재 조회 중인 Object 명을 자동 전달하는 내장 인자는 없다. 함수의 업무 사용자 인자는 클라이언트가 보낸 ID가 아니라 `ORA_END_USER_CONTEXT.username`이며, 함수가 `CB_DDS_END_USER_MAP`을 통해 실제 `user_id`로 해석한다.
|
|
|
|
|
|
|
|
|
|
## 4. 게시 모델과 운영 규칙
|
|
|
|
|
## 4. 권한 모델: 동적 범위와 정적 범위
|
|
|
|
|
|
|
|
|
|
- 활성 `CB_APP_USER`마다 `CB_DDS_END_USER_MAP`에 `DDS_U_<id>`, `DDS_U_<id>_ROLE`, grant 이름과 게시 상태를 기록한다.
|
|
|
|
|
- local END USER Context의 lookup key는 서비스 secret과 사용자 ID로 HMAC 파생한다. 원문/파생값은 DB·Git·Redmine·로그에 저장하지 않는다.
|
|
|
|
|
- 사용자의 직접 역할과 활성 그룹 역할에서 `CB_PERMISSION` / `CB_PERMISSION_RULE` / 허용 컬럼을 계산해 벡터 보호 객체의 `DATA GRANT`를 재생성한다.
|
|
|
|
|
- ALLOW가 없으면 grant를 제거하여 DDS 기본 거부 상태를 유지한다. 비활성 사용자는 data role과 grant를 회수한다.
|
|
|
|
|
- 사용자 활성화·직접 역할·그룹 멤버/역할·permission rule/허용 컬럼 변경은 같은 요청 안에서 활성 사용자 전체를 bulk 재발행한다. 수동 **DDS 관리의 게시 작업**은 전체 복구·재검증용으로도 제공한다.
|
|
|
|
|
- `withDataRoles(...)`는 local username+lookup-key Context에 사용하지 않는다. 역할은 게시된 local END USER grant에서만 활성화된다.
|
|
|
|
|
|
|
|
|
|
## 5. OCI IAM / ADB 전제조건
|
|
|
|
|
|
|
|
|
|
1. ADB external authentication을 `OCI_IAM`으로 등록하고 application ID와 domain URL을 설정한다.
|
|
|
|
|
2. `OCI_IAM_DOMAIN_DB_CRED$` credential에 Confidential application의 client ID/secret을 보관한다.
|
|
|
|
|
3. pool account에 `CREATE SESSION`, `CREATE END USER SECURITY CONTEXT`를 부여하고 TLS wallet 연결을 사용한다.
|
|
|
|
|
4. application identity를 `IAM_OAUTH_CLIENT_ID=<client id>`로 등록한다. 서비스 역할을 application identity에 부여할 경우 해당 역할만 활성화된다.
|
|
|
|
|
5. application은 database resource scope로 client-credentials token을 얻는다.
|
|
|
|
|
|
|
|
|
|
DB가 확인하는 token claim은 `resource_app_id`, `tenant_iss`, audience와 scope다. 이 값은 DB OCI IAM 설정 및 database resource registration과 일치해야 한다.
|
|
|
|
|
|
|
|
|
|
## 6. 구현 경계
|
|
|
|
|
|
|
|
|
|
| 컴포넌트 | 책임 | 실패 처리 |
|
|
|
|
|
| 구분 | 결정 위치 | 권한 변경 시 DDL |
|
|
|
|
|
|---|---|---|
|
|
|
|
|
| `DdsMcpBearerAuthenticator` | MCP Bearer → 활성 `CB_APP_USER` | 인증 실패, SQL 미실행 |
|
|
|
|
|
| `DdsMcpEndUserResolver` | 사용자 → 게시된 DDS principal | 미매핑/미게시면 거부 |
|
|
|
|
|
| `DdsMcpDatabaseAccessTokenProvider` | OCI IAM service token 발급·만료 전 갱신 | Context 실행 차단 |
|
|
|
|
|
| `DdsMcpContextExecutor` | attach → 제한된 SQL → clear | clear 실패 시 연결 폐기 |
|
|
|
|
|
| `DdsMcpVectorSearchService` | Context 내부 보호 벡터 SQL만 실행 | DDS 오류를 안전한 MCP 오류로 변환 |
|
|
|
|
|
| `DdsMcpAuthorizationChangeListener` | 권한 변경 event → 전체 local END USER grant 재발행 | 요청을 실패로 알리고 게시 상태를 확인하게 함 |
|
|
|
|
|
| DDS Publisher | 기존 권한 모델 → local END USER/DATA ROLE/DATA GRANT | 부분 실패를 게시 실패로 기록 |
|
|
|
|
|
| 업무 사용자 활성·역할·그룹·퍼미션 | `CB_*` 권한 테이블, `can_access`/`EXISTS` | 불필요 — 다음 쿼리부터 반영 |
|
|
|
|
|
| 행 범위: 본인·테넌트·부서·상태·태그 | DATA GRANT `WHERE`와 Context/함수 인자 | 불필요 |
|
|
|
|
|
| 컬럼 노출/수정 | Object·CRUD·컬럼 그룹별 DATA GRANT | 퍼미션 값 변경은 불필요. 새 컬럼/새 그룹만 provisioning |
|
|
|
|
|
| Object·View·CRUD 등록 | 안전 검토한 DATA GRANT DDL | 필요 |
|
|
|
|
|
| local END USER 등록 | `CREATE END USER`, 공통 `DDS_MCP_RUNTIME` Role 부여 | 신규 사용자 최초 1회 |
|
|
|
|
|
|
|
|
|
|
Tool/Repository는 raw Bearer, client secret, lookup key 또는 `setEndUserSecurityContext`를 직접 다루지 않는다.
|
|
|
|
|
예를 들어 `PHONE`, `EMAIL`의 열 그룹에는 다음처럼 **한 번만** Grant를 만든다.
|
|
|
|
|
|
|
|
|
|
## 7. 검증 결과 (2026-07-02)
|
|
|
|
|
```sql
|
|
|
|
|
CREATE DATA GRANT admin.customer_contact_read
|
|
|
|
|
AS SELECT (phone, email)
|
|
|
|
|
ON admin.customer
|
|
|
|
|
WHERE admin.dds_mcp_authz_pkg.can_access(
|
|
|
|
|
ORA_END_USER_CONTEXT.username,
|
|
|
|
|
'ADMIN.CUSTOMER', 'SELECT', 'CONTACT', tenant_id, customer_type
|
|
|
|
|
) = 1
|
|
|
|
|
TO dds_mcp_runtime;
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
권한 테이블에서 해당 사용자의 `CONTACT` 읽기 권한을 제거하면 함수가 `0`을 반환하므로 즉시 `PHONE`과 `EMAIL`은 노출되지 않는다. 같은 Object의 기본 컬럼은 별도 Grant로 정의한다. DDS Grant는 합산(additive)되므로 `AS SELECT` 같은 광범위 Grant를 공통 Role에 만들면 안 되며, 컬럼 그룹은 겹치지 않게 관리한다.
|
|
|
|
|
|
|
|
|
|
`WHERE`는 행별 true/false를 판단한다. 따라서 함수가 컬럼 목록을 반환하거나 클라이언트의 Object/컬럼 문자열로 동적 SQL을 만드는 구조는 사용하지 않는다. 함수는 고정 Object·컬럼 그룹의 권한과 행 조건만 판정한다.
|
|
|
|
|
|
|
|
|
|
## 5. 함수와 데이터 경계
|
|
|
|
|
|
|
|
|
|
`DDS_MCP_AUTHZ_PKG.can_access`는 `AUTHID DEFINER` 패키지로 구현하고 다음을 지킨다.
|
|
|
|
|
|
|
|
|
|
1. `ORA_END_USER_CONTEXT.username` → `CB_DDS_END_USER_MAP` → 활성 `CB_APP_USER`를 해석한다. MCP 파라미터의 사용자 ID·테넌트 ID를 신뢰하지 않는다.
|
|
|
|
|
2. 직접 역할과 활성 그룹 역할, `ALLOW`/`DENY`, Object·동작·컬럼 그룹·행 규칙을 같은 DB의 `CB_*` 테이블에서 평가한다.
|
|
|
|
|
3. 미매핑, 비활성, 권한 없음, 예상 밖의 입력, 예외는 모두 `0`으로 처리한다. 예외를 허용으로 바꾸지 않는다.
|
|
|
|
|
4. Function의 SQL은 bind 기반 정적 SQL만 사용한다. Object·동작·컬럼 그룹은 DATA GRANT에 적은 whitelist 상수로만 전달하며 동적 SQL을 만들지 않는다.
|
|
|
|
|
5. 권한 테이블은 보호 대상 업무 Object와 분리한다. predicate가 대상 Object를 다시 조회하면 DDS 순환 predicate 오류가 발생한다.
|
|
|
|
|
6. Grant owner에는 함수와 권한 테이블에 대한 필요한 **직접** 권한만 부여한다. MCP END USER에는 권한 테이블의 직접 조회·수정 권한을 주지 않는다.
|
|
|
|
|
7. 즉시 반영이 목적이므로 함수에 `DETERMINISTIC` 또는 임의의 결과 캐시를 붙이지 않는다. 권한 테이블에는 사용자·역할·Object·동작 기준 인덱스를 둔다.
|
|
|
|
|
|
|
|
|
|
권한 테이블이 다른 DB나 DB link에만 존재하면 이 모델은 사용할 수 없다. DDS predicate는 원격 Object 참조를 지원하지 않는다. 이 경우에는 현행 게시형 동기화나, 동일 DB의 읽기 전용 권한 projection 테이블이 필요하다.
|
|
|
|
|
|
|
|
|
|
## 6. 전환 계획과 현재 구현의 위치
|
|
|
|
|
|
|
|
|
|
현재 PoC는 사용자별 `DDS_U_<id>_ROLE` 및 사용자별 벡터 `DATA GRANT`를 생성하고, 권한 변경 시 전체 재게시한다. Context attach·OCI IAM token·Bearer→사용자 매핑·fail-closed clear는 실증 완료된 기반이며 그대로 유지한다.
|
|
|
|
|
|
|
|
|
|
다음 이행에서 바꿀 부분은 권한 집행 계층이다.
|
|
|
|
|
|
|
|
|
|
1. `DDS_MCP_RUNTIME` 공통 DATA ROLE과 `CB_DDS_END_USER_MAP` 기반 local END USER provisioning을 만든다.
|
|
|
|
|
2. `DDS_MCP_AUTHZ_PKG`와 권한 테이블 인덱스를 만든다.
|
|
|
|
|
3. 보호 Object/CRUD/컬럼 그룹별 장기 DATA GRANT를 생성한다. Object/컬럼 메타데이터 변경 때만 이 DDL을 변경한다.
|
|
|
|
|
4. `DdsMcpAuthorizationChangeListener`의 사용자별 Grant bulk 재발행을 제거한다. 관리 변경은 권한 테이블 transaction commit만으로 즉시 반영한다.
|
|
|
|
|
5. 기존 사용자별 Grant를 회수하고 dictionary·MCP regression으로 default deny, 컬럼 `NULL`, 행 필터, 권한 변경 직후 반영을 검증한다.
|
|
|
|
|
|
|
|
|
|
수동 publish는 권한 변경 반영 수단이 아니라 최초 provisioning, 스키마 변경, drift 복구와 검증 용도로 남긴다.
|
|
|
|
|
|
|
|
|
|
## 7. OCI IAM / ADB 전제조건
|
|
|
|
|
|
|
|
|
|
1. ADB external authentication에 `OCI_IAM` 및 domain/application ID를 설정한다.
|
|
|
|
|
2. `OCI_IAM_DOMAIN_DB_CRED$`에 Confidential Application 자격증명을 보관한다.
|
|
|
|
|
3. pool account에 `CREATE SESSION`, `CREATE END USER SECURITY CONTEXT`를 부여하고 TLS wallet 연결을 사용한다.
|
|
|
|
|
4. application identity를 `IAM_OAUTH_CLIENT_ID=<client id>`로 등록한다.
|
|
|
|
|
5. application은 database resource scope의 client-credentials token을 얻는다.
|
|
|
|
|
|
|
|
|
|
DB는 `resource_app_id`, `tenant_iss`, audience와 scope를 OCI IAM/DB 설정과 비교한다. client ID, secret, raw token, lookup key는 문서·Git·Redmine·로그에 기록하지 않는다.
|
|
|
|
|
|
|
|
|
|
## 8. 검증 상태와 인수 기준
|
|
|
|
|
|
|
|
|
|
### 완료된 기반 검증 (2026-07-02)
|
|
|
|
|
|
|
|
|
|
- [x] SQLcl로 ADB 접속 및 local `END USER`, `DATA ROLE`, `DATA GRANT` catalog 생성 검증.
|
|
|
|
|
- [x] OCI IAM database-access token 발급 성공. `resource_app_id`, `tenant_iss`, audience `DDSDB`, scope `DB_ACCESS_SCOPE`가 DB 설정과 일치.
|
|
|
|
|
- [x] DB credential `OCI_IAM_DOMAIN_DB_CRED$`, OCI IAM application identity mapping 확인.
|
|
|
|
|
- [x] `/dds/mcp/sse` endpoint event 및 `tools/list` HTTP 200 확인.
|
|
|
|
|
- [x] `dds_vector_search` tool call: Bearer → application user 101 → local DDS Context attach → 보호 query 3행 반환 → context clear, HTTP 200.
|
|
|
|
|
- [ ] 사용자 A→B→A 및 동시 요청의 full isolation regression을 자동화한다.
|
|
|
|
|
- [ ] DDS 관리 UI publish가 MCP END USER map/grant를 같은 트랜잭션 경계에서 갱신하도록 통합한다.
|
|
|
|
|
- [x] OCI IAM database-access token, database credential, application identity mapping 검증.
|
|
|
|
|
- [x] `/dds/mcp/sse`, `tools/list`, 실제 `dds_vector_search`의 Bearer → Context attach → 보호 query → clear HTTP 200 검증.
|
|
|
|
|
|
|
|
|
|
SSE stream은 연결을 유지하므로 client read timeout이 날 수 있다. 이는 실패 판정 기준이 아니며, Tool RPC의 HTTP 결과와 attach/query/clear 로그로 성공을 판정한다.
|
|
|
|
|
### 런타임 권한 함수 이행 인수 기준
|
|
|
|
|
|
|
|
|
|
## 8. 보안 불변식
|
|
|
|
|
- [ ] `CB_PERMISSION`의 ALLOW/DENY 또는 사용자·그룹 역할을 commit하면 다음 MCP 쿼리 결과가 DDL 없이 바뀐다.
|
|
|
|
|
- [ ] Object 권한 제거 시 결과는 default deny(행 없음 또는 접근 불가)다.
|
|
|
|
|
- [ ] 컬럼 그룹 권한 제거 시 해당 컬럼만 `NULL`이고, 다른 승인 컬럼·행 범위는 유지된다.
|
|
|
|
|
- [ ] 다른 사용자/테넌트/부서의 행은 함수 predicate를 통과하지 않는다.
|
|
|
|
|
- [ ] 함수 예외, 매핑 누락, 비활성 사용자는 fail-closed다.
|
|
|
|
|
- [ ] A→B→A 및 동시 pooled connection에서 Context와 권한이 섞이지 않는다.
|
|
|
|
|
|
|
|
|
|
1. 유효한 MCP Bearer 하나는 정확히 하나의 활성 `CB_APP_USER`와 하나의 게시된 DDS END USER로만 해석된다.
|
|
|
|
|
## 9. 보안 불변식
|
|
|
|
|
|
|
|
|
|
1. 유효한 MCP Bearer 하나는 정확히 하나의 활성 `CB_APP_USER`와 local DDS END USER로만 해석된다.
|
|
|
|
|
2. Context attach 이전·clear 이후에는 보호 SQL을 실행하지 않는다.
|
|
|
|
|
3. attach/query/clear 어느 단계가 실패해도 fail-closed한다.
|
|
|
|
|
4. client-credentials token은 서비스 승인용이며 업무 사용자 권한 확대에 사용하지 않는다.
|
|
|
|
|
5. secret, raw bearer, database-access token, lookup key는 응답·로그·Git·Redmine에 기록하지 않는다.
|
|
|
|
|
3. 서비스 token은 Context attach 승인용일 뿐 사용자 권한을 결정하지 않는다.
|
|
|
|
|
4. 업무 권한 원천은 `CB_*` 테이블 하나이며 함수와 관리 UI 모두 이를 사용한다.
|
|
|
|
|
5. 예외·미매핑·권한 없음은 항상 거부다.
|
|
|
|
|
6. secret, raw bearer, database-access token, lookup key는 응답·로그·Git·Redmine에 기록하지 않는다.
|
|
|
|
|
|
|
|
|
|
## 9. 참고
|
|
|
|
|
## 10. 참고
|
|
|
|
|
|
|
|
|
|
- [Oracle: End-User Security Context](https://docs.oracle.com/en/database/oracle/oracle-database/26/ddscg/end-user-security-context.html)
|
|
|
|
|
- [Oracle: Create Data Grants](https://docs.oracle.com/en/database/oracle/oracle-database/26/ddscg/create-data-grants.html)
|
|
|
|
|
- [Oracle: About Data Grants](https://docs.oracle.com/en/database/oracle/oracle-database/26/ddscg/data-grants.html)
|
|
|
|
|
- [Oracle: Configure the Database for IAM Integration](https://docs.oracle.com/en/database/oracle/oracle-database/26/ddscg/configure-database-iam-integration.html)
|
|
|
|
|
- [Oracle: Prerequisites for Establishing a Local Security Context](https://docs.oracle.com/en/database/oracle/oracle-database/26/ddscg/prerequisites-establishing-local-security-context.html)
|
|
|
|
|
- [Oracle: End-User Security Context Issues](https://docs.oracle.com/en/database/oracle/oracle-database/26/ddscg/end-user-security-context-issues.html)
|
|
|
|
|
|