본문으로 건너뛰기

SDK·MCP 데이터 인가 (#2701)

MCP 도구·AI Agent·CLI 가 공통으로 쓰는 gend_api.sdk 계층의 데이터 인가 운영 가이드입니다. REST 라우터(/api/v1/query/execute, /api/v1/catalog/*)와 같은 시행 헬퍼를 쓰므로 두 경로의 판정이 갈리지 않습니다.

이전 동작

이 기능 이전에는 SDK 계층에 데이터 인가가 없었습니다. 같은 SQL 을 REST 로 보내면 마스킹되고 MCP 로 보내면 원본이 나왔습니다. ADR-0031 참조.

무엇이 언제 적용되는가

통제플래그기본 동작
PII 컬럼 마스크없음항상 시행. 면제는 unmask 역할 단독 (admin 이라는 이유만으로는 면제되지 않음, #2673)
행 필터 (AccessPolicy)없음항상 시행
gendpg 워크스페이스 행 필터없음항상 시행. 안전 재작성 불가 시 거부(fail-closed)
DataGrant SELECT 차단GEND_GRANT_ENFORCEMENT_MODEREST 와 동일 설정을 공유 (현재 prod whitelist)
DataGrant 가시성 필터 (카탈로그/스키마/테이블 목록)GEND_SDK_AUTHZ_MODEobserve — 관측만, 목록을 바꾸지 않음

가시성 필터만 단계 시행하는 이유는 기존 MCP 클라이언트가 grant 부족으로 갑자기 빈 목록을 받는 회귀를 막기 위해서입니다. 마스킹·행필터는 결과가 "빈 목록"이 아니라 "마스킹된 값"이라 그런 위험이 없어 즉시 시행합니다.

GEND_SDK_AUTHZ_MODE

동작
off가시성 필터를 계산하지 않음
observe기본. 필터를 계산해 카운터·로그만 남기고 원본 목록을 반환
enforceREST 라우터와 동일하게 실제 필터링. 단건 조회는 ForbiddenError
  • 알 수 없는 값은 error 로그 후 observe 로 폴백합니다 (오타가 전면 차단이나 전면 무시로 번지지 않도록).
  • observe필터 조회가 실패해도 원본을 반환합니다. 관측 목적으로 켜둔 코드가 DB 순단만으로 MCP 호출을 깨뜨려서는 안 되기 때문입니다. enforce 에서는 예외를 전파합니다(fail-closed).

메트릭

메트릭라벨의미
gend_sdk_authz_filtered_totaldomain, caller_type, mode가시성 필터가 걸러낸(또는 걸러냈을) 항목 수
gend_sdk_authz_bypass_totalcaller_typecontrol-plane(SYSTEM) 호출자가 게이트를 우회한 횟수
gend_sdk_authz_gate_totaldomain, caller_type, mode게이트가 평가된 횟수 (filtered 의 분모, #2719)

domaincatalogs / schemas / tables / columns / sample.

승격 절차 (observe → enforce)

  1. 관측 (1주 권장): 필터링 비율로 판단합니다 — sum(rate(gend_sdk_authz_filtered_total[1w])) / sum(rate(gend_sdk_authz_gate_total[1w])). 분모 없이 분자만 보면 "거를 게 없었다"와 "게이트가 안 돌았다"가 구분되지 않습니다. domain · caller_type 별로 확인합니다.
  2. 0 이 아니면 grant 를 먼저 발급합니다. 지금 목록을 보고 있는 caller 가 enforce 전환 즉시 못 보게 되는 것이 그 수치의 의미입니다. caller_type=mcp 가 대부분이라면 해당 M2M 클라이언트의 DataGrant 현황을 먼저 확인하세요.
  3. 1주간 0 에 수렴하면 승격합니다.
    kubectl --context aks-genos-prod -n gend set env deploy/gend-api \
    GEND_SDK_AUTHZ_MODE=enforce
    kubectl --context aks-genos-prod -n gend rollout status deploy/gend-api
  4. 롤백은 같은 명령으로 observe 를 되돌려 놓으면 됩니다 — DB 변경이 없어 즉시 복구됩니다.

감사

MCP 도구 호출은 mcp_call_logs 에 기록되며, 이 기능부터 다음이 채워집니다.

  • workspace_id — 호출자의 워크스페이스
  • params_hash — 도구 인자의 SHA-256 (인자 원본은 저장하지 않음)

대상 좌표(catalog/schema/table)는 mcp_access_history(#832)에 별도로 기록되며 두 테이블을 조인해 재구성합니다.

감사 범위의 한계

감사 HMAC 체인이 서명하는 것은 endpoint 와 status 이고, SQL 본문은 /api/v1/query 접두 경로에서만 2000자까지 저장됩니다. SDK·MCP·CLI 경로의 SQL 본문은 기록되지 않습니다. 고객 문서에 "모든 열람이 기록된다"고 쓰지 마십시오 — "열람 행위가 기록된다"까지가 정확합니다.

커버리지와 한계

커버: MCP 도구 6종(list_catalogs / list_schemas / list_tables / describe_table / sample_table / execute_query), AI Agent 의 SQL·카탈로그 도구, gend-cli 의 동일 경로.

미커버 (의도된 범위 제한):

  • sample_table 의 컬럼 마스킹 — REST 의 sample 엔드포인트에도 없습니다. 한쪽만 조이면 MCP 가 UI 보다 엄격해지는 포크가 되므로 양 평면 동시 적용을 별도 처리합니다.
  • MCP/Agent 쿼리의 query_history 기록 — 별도 작업.
  • governance / quality / engineering / compliance SDK 도메인의 워크스페이스 필터.
  • 엔진 계층 — gend-api 를 거치지 않고 Trino 에 직접 도달하는 경로는 본 시행 밖입니다 (ADR-0030, #2683).
  • 벡터/문서 검색(Weaviate) — Trino 를 거치지 않아 본 시행이 닿지 않습니다.

관련