vault-mcp

vault-mcp

Centralized credential management for servers, websites, and APIs with HashiCorp Vault integration. Provides authentication, authorization, and audit logging for secure access to secrets.

Category
访问服务器

README

vault-mcp

vault-mcp 는 단순한 HashiCorp Vault 관리 도구가 아니라, 사내 서버·웹사이트·API 접속 정보(Credential)를 중앙에서 인증·인가·감사하며 관리하는 Ops Broker 다.

LLM(Claude) 또는 CLI 가 사용자의 요청을 중앙 API 에 전달하면, 중앙 API 가 사용자 인증·인가 → 리소스 해석 → Vault Credential 조회 → 결과 마스킹 → 감사 기록을 통제한다. 실제 Secret 은 Vault 에만 있고, LLM·CLI·DB·API 응답 어디에도 새지 않는다.

현재 단계: STEP 8.7 — Resource 유형 확장(SERVER/WEBSITE/API) 완료. 다음은 STEP 9(인증 개선). SSH 실행(Runner)은 STEP 10 으로 아직 미구현이다. 단계별 상세는 docs/development-roadmap.md.


목차


핵심 원칙

원칙 내용
Secret 격리 실제 Secret 은 Vault 에만. DB·API 응답·로그·감사에는 credential_ref(논리 경로)만.
1 Resource = 1 Credential 하나의 등록 항목 = 하나의 접속 대상 = 하나의 Credential. credential_id 개념 없음(1:N 아님).
소유자 전용 리소스는 소유자만 관리. 타인 리소스는 403 이 아니라 404(존재 은닉).
클라이언트 입력 불신 요청 body 의 user_id/credential_ref/vault_path/host 를 신뢰하지 않는다. 서버가 결정.
LLM 은 별칭만 Claude 는 alias + operation 만 추출. 서버 해석·Credential 조회는 중앙 API 가 사용자 권한 안에서 수행.
감사 강제 모든 Credential 접근(등록/교체/삭제/reveal)은 감사 로그에 기록(Secret 원문 제외).

아키텍처

현재 구현된 데이터 흐름(등록 / 조회 / 삭제). SSH 실행(Runner)은 STEP 10 으로 아직 없다.

flowchart TD
    subgraph client [클라이언트]
      W[Web UI · Jinja2]
      S[Claude Skill · REST]
    end
    W -->|Cookie 세션 + CSRF| API
    S -->|API Key| API
    API[vault-mcp FastAPI]

    API -->|인증 4종 → users.id| AUTH{인증·인가}
    AUTH -->|비민감 메타데이터| PG[(PostgreSQL<br/>vault_mcp schema)]
    AUTH -->|credential_ref 로 Secret| VAULT[(HashiCorp Vault<br/>KV v2)]
    API --> AUDIT[(audit_logs)]

    PG -.->|credential_ref = 논리 경로| VAULT
흐름 경로
등록 리소스 등록(PG) → Credential 등록 → Vault write → credential_ref 를 PG 에 저장
조회(reveal) 소유권 확인(PG) → credential_ref 로 Vault read → 평문 Secret 반환(no-store)
삭제 Vault soft delete → PG 상태/credential_ref 갱신 → commit. commit 실패 시 Vault undelete 로 보상

컴포넌트 책임:

컴포넌트 한다 하지 않는다
Claude Skill alias/operation 추출, 결과 분석, 비민감 요약만 출력 Secret 원문 출력(사용자 요청해도 금지), Vault/경로 접근
Web UI 로그인, 리소스 CRUD, Credential 등록/교체/삭제, API Key 발급 Secret 재표시(Web 에 reveal 없음)
FastAPI 인증·인가·리소스 해석·Vault 연동·마스킹·감사 Secret 을 응답/로그에 노출
Vault 실제 Secret 저장
PostgreSQL 비민감 메타데이터 + credential_ref 실제 Secret 저장

Resource 유형과 저장 책임

STEP 8.7 부터 등록 대상은 SERVER / WEBSITE / API 세 유형이다(OTHER 는 범위 밖). 유형은 등록 후 변경 불가(409). 정본: docs/resource-types.md.

사용 · 항상 NULL(보내면 400) · 굵게 = 필수

필드 저장소 SERVER WEBSITE API
alias / description / service_name PG / ✓ / / ✓ / ✓ / ✓ / ✓
status / environment PG ✓ / ✓ ✓ / — ✓ / —
host / ssh_port PG /
site_url PG
base_url / auth_type(ApiAuthType) PG /
header_name / token_prefix / scopes / expires_at PG
login_id PG (¹) ✓(= client_id)
memo PG
username / port Vault / ✓
password Vault ✓(²)
private_key / passphrase Vault ✓(²)
api_key / token / refresh_token / client_secret / webhook_secret Vault ✓(³)
  • (¹) SERVER 의 SSH username 은 Vault 에만 있다(하위 호환). 그래서 목록 응답의 login_id 는 SERVER 에서 항상 null.
  • (²) SERVER 는 auth_type(SshAuthType) 에 따라 password 또는 private_key(+선택 passphrase).
  • (³) API 는 auth_type(ApiAuthType) 이 어떤 Secret 이 필수인지 결정한다. client_id 는 secret 이 아니므로 PG, client_secret 은 Vault — reveal 이 한 쌍으로 반환.

인증 유형 enum 은 분리 유지한다: SERVER = SshAuthType(PASSWORD/PRIVATE_KEY, Vault), API = ApiAuthType(API_KEY/ACCESS_TOKEN/BEARER_TOKEN/PERSONAL_ACCESS_TOKEN/CLIENT_CREDENTIALS/ OAUTH_TOKEN/WEBHOOK_SECRET/CUSTOM, PostgreSQL). WEBSITE 는 인증 유형 개념이 없다.


API 레퍼런스

Base prefix /api/v1. 스키마·Authorize·curl 예시: docs/swagger-guide.md (/docs, /redoc, /openapi.json 은 local/dev 에서만 노출).

Secret 반환 은 reveal 하나뿐이다. 나머지 Credential API 는 상태 메타데이터만 준다.

Method Path 용도 인증 / scope Secret
GET /health · /ready Liveness / Readiness(DB+Vault) 없음
POST /auth/register · /auth/login LOCAL 가입 / 로그인(JWT 발급) 없음
GET /me 현재 사용자 프로필 인증
POST/GET/DELETE /api-keys · /api-keys/{id} API Key 발급(1회 노출)/목록/폐기 Web 사용자만(API Key 로 불가) 발급 시 1회
GET /servers · /servers/{alias} operation 권한 있는 서버 목록/상세 servers.read
POST/PUT/GET/DELETE /resources/{id}/credentials 전 유형 Credential 등록/교체/상태/삭제 인증
POST/PUT/GET/DELETE /servers/{id}/credentials/ssh SSH Credential (SERVER 전용 하위 호환) 인증
GET /my/resources · /my/resources/search 내 소유 리소스 목록/검색(전 유형) resources:read
POST /my/resources/{id}/credentials/reveal ⚠️ Credential 원문 조회 credentials:reveal 평문
  • /resources/{id}/credentials(전 유형, STEP 8.7 신규)와 /servers/{id}/credentials/ssh(SERVER 전용 하위 호환)는 SERVER 에 대해 동작·저장 결과가 동일하다. 후자는 WEBSITE/API 대상이면 409.
  • reveal 응답은 resource_type discriminator 로 갈리는 oneOf(SERVER/WEBSITE/API). SERVER 응답은 resource_type 키만 additive 로 추가돼 기존 Skill 이 그대로 동작한다.
  • scope 표기 불일치는 코드 그대로다: servers.read(점) vs resources:read/credentials:reveal(콜론).

Web UI(/web/*, HTML+Cookie, OpenAPI 미노출): 로그인, 대시보드, 리소스 CRUD(유형 선택 → 유형별 폼), Credential 등록/삭제(reveal 없음), API Key 발급/폐기. 상세: docs/web-ui.md.


인증 방식

Authorization 헤더에서 4종을 라우팅하며 모두 내부 users.id 로 귀결된다. 클라이언트가 보낸 user_id/tenant_id/oid 는 신뢰하지 않는다.

방식 헤더 알고리즘 사용자 식별 용도 · 활성 조건
LOCAL JWT Bearer <JWT> HS256 sub = 내부 user_id 개발 주 로그인 / Web UI. local_auth_enabled + issuer 일치
Microsoft Entra Bearer <JWT> RS256(only, JWKS) (tid, oid) 매핑 사내 SSO. Bearer JWT 기본 경로
API Key ApiKey <dv_...> (또는 Bearer dv_...) HMAC-SHA256 해시 key_hash → user_id Claude/CLI. 접두 dv_dev_/dv_live_
DEV 헤더 없음 dev_auth_user_id 로컬 편의. dev_auth_enabled + is_local(prod fail-fast)

Vault 경로와 삭제 정책

논리 경로(DB credential_ref 에 저장). DB 값이 경로의 정본 — 읽기/교체/삭제 시 재생성하지 않고 저장값을 그대로 쓴다(그래서 기존 행이 호환 로직 없이 동작). 경로는 UUID 로만 구성(사용자 입력·alias 미사용 → path traversal 차단).

구분 형식
신규(전 유형) users/{user_id}/resources/{resource_id}/credential
legacy(STEP 6~8 SERVER) users/{user_id}/servers/{server_resource_id}/ssh

KV v2 물리 경로 = {mount}/data/{credential_ref}. VaultClient 는 App Token Policy 가 실제로 허용하는 endpoint 만 쓴다:

동작 HTTP endpoint 필요 capability
write / read POST/GET /v1/{mount}/data/{path} data/* create·read·update
metadata read GET /v1/{mount}/metadata/{path} metadata/* read
soft delete POST /v1/{mount}/delete/{path} delete/* update
undelete(보상) POST /v1/{mount}/undelete/{path} undelete/* update

삭제는 soft delete 다(destroy 아님, 복구 가능). 정책이 data/* 에 delete 를 주지 않으므로 DELETE /data/ 가 아니라 POST /delete/(버전 지정, metadata 로 current_version 선조회)를 쓴다 — 전자를 쓰면 403 으로 삭제가 전부 실패한다. Resource 삭제도 Vault Secret 을 함께 soft delete 하고, DB commit 실패 시 undelete 로 보상한다. 정본: docs/vault-client.md, docs/credential-storage-flow.md.


데이터 모델

전용 PostgreSQL schema vault_mcp 에 격리(공유 DB vault_mcp 의 public·타 schema 미사용). enum 은 비네이티브 VARCHAR(32). 정본: docs/data-model.md.

테이블 역할
users 신원. LOCAL(login_id+password_hash) / MICROSOFT(tenant_id+entra_oid) 두 출처
api_keys API Key 메타데이터. 원문 미저장(key_hash/key_prefix 만)
server_resources 등록 대상 Resource(SERVER/WEBSITE/API 전부). 이름은 하위 호환으로 유지
server_permissions 인가 단위: 사용자 × 리소스 × operation. Default Deny, DENY 우선
vault_connections Vault 접속 메타데이터. 중앙 Vault(시스템 소유)면 owner NULL
audit_logs 감사 이력. Secret 컬럼 없음

주요 제약(server_resources):

  • uq_server_resources_owner_user_id_alias — UNIQUE(owner_user_id, alias) WHERE status ≠ 'DELETED'(partial). soft delete 는 행을 남기므로, 삭제한 별칭을 재사용할 수 있게 DELETED 를 제외한다(0006). → 같은 alias 의 DELETED 행이 여러 개일 수 있어 alias 조회는 DELETED 를 거른다.
  • resource_type_allowedresource_type IN ('SERVER','WEBSITE','API')
  • auth_type_api_onlyauth_type IS NULL OR resource_type = 'API'(SshAuthType/ApiAuthType 혼용 차단)

Migration 이력(revision id 는 alembic_version.version_num VARCHAR(32) 제약):

revision 내용
0001_initial 초기 스키마 5테이블(vault_mcp schema, enum=VARCHAR(32))
0002_local_auth_and_api_keys LOCAL 로그인 필드 + api_keys 테이블, Entra 필드 nullable 전환
0003_credential_ref_nullable server_resources.credential_ref nullable(미등록=NULL)
0004_server_environment environment 컬럼(DEV/STAGING/PROD 표시용)
0005_resource_types resource_type + 유형별 필드, host/ssh_port/service_name NOT NULL 해제, 기존 행 SERVER backfill
0006_alias_unique_active_only alias unique 를 DELETED 제외 partial index 로 교체

SQLite(테스트)는 ALTER COLUMN / ADD CONSTRAINT 미지원 → NOT NULL 완화·CHECK 추가는 PostgreSQL 에서만 수행하고, SQLite 는 모델 create_all 이 동일한 최종 스키마를 만든다.


빠른 시작

요구: Python 3.12+, uv. DB/Vault 없이도 /api/v1/health 는 뜬다.

# [로컬 PC / WSL·zsh]
uv sync                                   # 가상환경 + 의존성
cp .env.example .env                      # 값 채우기(아래 환경 변수 참고)
uv run uvicorn app.main:app --reload      # 또는: bash scripts/run-local.sh
  • API 문서: http://127.0.0.1:8000/docs (local/dev 에서만)
  • Web UI: http://127.0.0.1:8000/web/login
  • PoC 로그인 계정 생성: docs/poc-user-seed.md 의 seed 스크립트

LOCAL 로그인은 .env 에서 LOCAL_AUTH_ENABLED=true 여야 활성화된다(기본 false). Credential 등록/조회는 Vault 연결이 필요하다 — 개발 Vault 터널·App Token 준비는 docs/vault-local-development.md.


환경 변수

.env 로 관리(Git 커밋 금지, .env.example 만 저장). Secret 값은 Vault 또는 K8S Secret 으로, .env 에는 서버별 Credential 을 넣지 않는다.

접두 예시 키 비고
APP_* APP_ENV, APP_HOST, APP_PORT APP_ENV = local/dev/test/production
DB_* DB_HOST/PORT/NAME/USERNAME/PASSWORD/SCHEMA 공유 DB vault_mcp, schema vault_mcp
LOCAL_* / PASSWORD_* LOCAL_AUTH_ENABLED, LOCAL_JWT_SECRET, LOCAL_JWT_ISSUER HS256 자체 JWT
API_KEY_* API_KEY_HASH_SECRET, API_KEY_MAX_ACTIVE_PER_USER 미설정 시 SHA-256 fallback
ENTRA_* ENTRA_TENANT_ID, ENTRA_CLIENT_SECRET, ENTRA_AUDIENCE, ENTRA_ISSUER Resource Server 검증
VAULT_* VAULT_ADDR, VAULT_TOKEN / VAULT_TOKEN_FILE, VAULT_KV_MOUNT Token 원문 또는 0600 파일
DEV_AUTH_* DEV_AUTH_ENABLED, DEV_AUTH_USER_ID local/dev 한정(prod fail-fast)
기타 LOG_LEVEL, DOCS_ENABLED, CORS_ALLOWED_ORIGINS

굵게 = SecretStr(로그/응답 미노출): DB_PASSWORD, LOCAL_JWT_SECRET, API_KEY_HASH_SECRET, ENTRA_CLIENT_SECRET, VAULT_TOKEN.


테스트·품질 게이트

uv run pytest              # 493 passed, 7 skipped (skip = 실 Vault 통합 테스트)
uv run ruff check .        # All checks passed
uv run ruff format --check .
uv run mypy app            # strict, no issues (87 files)
  • 테스트 32개 파일. 보안 경계(타 사용자 접근, 권한 없는 operation, Secret 노출, alias 위조, Vault 실패 일관성 등)를 필수로 테스트.
  • 실 Vault 통합 테스트는 기본 skip. 실행: VAULT_MCP_INTEGRATION=1 VAULT_ADDR=... VAULT_TOKEN_FILE=... uv run pytest tests/vault/test_real_vault_integration.py.

디렉터리 구조

app/
  main.py                       FastAPI 앱 조립 + OpenAPI 설정
  core/                         config, exceptions, openapi, api_docs, logging, middleware, security
  api/
    dependencies.py             인증/서비스 DI
    v1/router.py, v1/endpoints/ health, auth, me, api_keys, servers,
                                credentials(SSH 하위호환), resource_credentials(전 유형),
                                my_resources(목록/검색/reveal)
    internal/                   dev 전용 라우터(local/dev 에서만 등록)
  auth/                         verifier(Entra), local_token/local_service, dependencies, context, jwks, password
  api_keys/                     generator, hasher, service, repository, schemas
  credentials/                  service, compensation, validation, schemas, errors
  server_resources/             crud, service(alias 해석/인가), repository, validation, schemas
  vault/                        client(KV v2), factory, token_file, credential_ref, errors
  db/                           base(schema 격리), session, models/{user,api_key,server_resource,...}
  domain/                       enums, errors, resolved
  audit/                        service(감사 기록)
  web/                          router(Jinja2), csrf, dependencies
  templates/  static/{css,js}   Web UI
  scripts/seed_poc_user.py      PoC 사용자 seed
  ssh/  operations/             SSH Runner·운영 API 자리(STEP 10~11, 미구현)
migrations/versions/            Alembic 0001~0006
tests/                          api, api_keys, auth, services, vault, web, skills, db, models
skills/vault-mcp/             전사 공통 Claude Skill(REST 호출, Secret 미출력)
deploy/                         gitops-repo(Kustomize+ArgoCD), k8s/dev(수동 kubectl 대안)
docs/                           설계·운영 문서(아래 인덱스)
Dockerfile  Jenkinsfile         멀티스테이지 이미지 / CI 파이프라인

개발 단계

STEP 내용 상태
1 FastAPI 골격
2 DB 모델·권한·서버 해석(Alembic, schema 격리)
3 Microsoft Entra 인증
4 LOCAL 로그인 + API Key + 사용자별 Vault 경로 모델
5 개발 Vault 설치·단독 검증(NCP)
6 FastAPI ↔ Vault 연동 + Credential 등록
7 Skill 기반 REST API PoC
8 사용자 Web UI(Jinja2)
8.5 / 8.6 개발 K8S 배포 / Jenkins+Harbor+ArgoCD GitOps
8.7 Resource 유형 확장(SERVER/WEBSITE/API)
9 사용자 인증 개선(Device Flow/짧은 Access Token) 예정
10 SSH Runner 등 Credential 활용 미구현
11 / 12 / 13 읽기 전용 운영 API / CLI+Keyring / K8S 배포 정리 미구현

아직 미구현: SSH 실행(Runner), 운영 API(logs/status/disk), CLI/OS Keyring. Entra 실제 App Registration 통합 검증은 조직 환경에서 수행 필요.


배포

Jenkins(CI) → Harbor(registry) → ArgoCD(GitOps). 정본: docs/ci-gitops.md, deploy/gitops-repo/README.md.

flowchart LR
    GIT[소스 push] -->|pollSCM| J[Jenkins]
    J -->|build| IMG[이미지 sha-태그]
    IMG -->|push| H[Harbor]
    J -->|newTag 갱신 commit| D[vault-mcp-deploy repo]
    D -->|watch| A[ArgoCD]
    A -->|PreSync: migration Job| K[K8S vault-mcp ns]
    A -->|sync: Deployment| K
  • 이미지: Dockerfile 멀티스테이지, non-root(uid 10001), uvicorn :8000. Secret 미포함(K8S Secret 주입).
  • Jenkinsfile: Init(short SHA) → Build → Push Harbor → deploy repo 의 newTagsha-<SHA> 로 갱신. Deployment 와 migration Job 이 같은 SHA 로 반영(불일치 방지).
  • GitOps: deploy/gitops-repo/(Kustomize + ArgoCD Application). migration 은 PreSync Hook, seed 는 수동 1회.
  • deploy/k8s/dev/ 는 GitOps 없이 수동 kubectl apply 로 검증하는 대안이다.

기술 스택

영역 스택
언어 Python 3.12+
FastAPI ≥0.115, Uvicorn ≥0.34
검증 Pydantic v2 ≥2.9, pydantic-settings ≥2.6
DB SQLAlchemy 2.x async, asyncpg ≥0.30, Alembic ≥1.14, PostgreSQL
인증 PyJWT[crypto] ≥2.9, pwdlib[argon2] ≥0.2
Vault/HTTP httpx ≥0.28 (KV v2 직접 호출)
Web Jinja2 ≥3.1, python-multipart
개발 pytest + pytest-asyncio, aiosqlite, ruff(line 100, py312), mypy(strict)
패키지 uv(비패키지 애플리케이션 모드)

문서 인덱스

주제 문서
개요 architecture.md · security-principles.md · development-roadmap.md
Resource / 데이터 resource-types.md · data-model.md · authorization-model.md · server-resolution-flow.md
인증 local-authentication.md · entra-authentication.md · entra-setup-guide.md · api-key-authentication.md · token-storage-policy.md
Vault / Credential vault-client.md · vault-architecture-and-key-management.md · user-owned-vault-layout.md · credential-storage-flow.md · credential-reveal-api.md · vault-error-handling.md · vault-local-development.md · vault-production-readiness.md
API / Swagger swagger-guide.md · skill-rest-api-poc.md · api-key-auth-flow.md
Web UI web-ui.md · web-authentication.md · api-key-web-flow.md · poc-user-seed.md
Skill 배포 cowork-skill-deployment.md · security-model.md
배포 ci-gitops.md · deploy/gitops-repo/README.md · deploy/k8s/dev/README.md
작업 기록 docs/work-log/

Git 정책: 기본 브랜치 main, 명시적 요청 없이 commit/push 하지 않는다. .env·Token·인증서· Private Key 는 커밋 금지. 프로젝트 원칙과 작업 하네스는 CLAUDE.md.

推荐服务器

Baidu Map

Baidu Map

百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。

官方
精选
JavaScript
Playwright MCP Server

Playwright MCP Server

一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。

官方
精选
TypeScript
Magic Component Platform (MCP)

Magic Component Platform (MCP)

一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。

官方
精选
本地
TypeScript
Audiense Insights MCP Server

Audiense Insights MCP Server

通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。

官方
精选
本地
TypeScript
VeyraX

VeyraX

一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。

官方
精选
本地
graphlit-mcp-server

graphlit-mcp-server

模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。

官方
精选
TypeScript
Kagi MCP Server

Kagi MCP Server

一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。

官方
精选
Python
e2b-mcp-server

e2b-mcp-server

使用 MCP 通过 e2b 运行代码。

官方
精选
Neon MCP Server

Neon MCP Server

用于与 Neon 管理 API 和数据库交互的 MCP 服务器

官方
精选
Exa MCP Server

Exa MCP Server

模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。

官方
精选