vault-mcp
Provides integration with HashiCorp Vault for centralized credential management, including secure storage, retrieval, and auditing of secrets for servers, websites, and APIs.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@vault-mcpshow me the SSH credentials for prod-web-01"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
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.
목차
Related MCP server: Better Auth MCP Server
핵심 원칙
원칙 | 내용 |
Secret 격리 | 실제 Secret 은 Vault 에만. DB·API 응답·로그·감사에는 |
1 Resource = 1 Credential | 하나의 등록 항목 = 하나의 접속 대상 = 하나의 Credential. |
소유자 전용 | 리소스는 소유자만 관리. 타인 리소스는 403 이 아니라 404(존재 은닉). |
클라이언트 입력 불신 | 요청 body 의 |
LLM 은 별칭만 | Claude 는 |
감사 강제 | 모든 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 → |
조회(reveal) | 소유권 확인(PG) → |
삭제 | Vault soft delete → PG 상태/ |
컴포넌트 책임:
컴포넌트 | 한다 | 하지 않는다 |
Claude Skill |
| Secret 원문 출력(사용자 요청해도 금지), Vault/경로 접근 |
Web UI | 로그인, 리소스 CRUD, Credential 등록/교체/삭제, API Key 발급 | Secret 재표시(Web 에 reveal 없음) |
FastAPI | 인증·인가·리소스 해석·Vault 연동·마스킹·감사 | Secret 을 응답/로그에 노출 |
Vault | 실제 Secret 저장 | — |
PostgreSQL | 비민감 메타데이터 + | 실제 Secret 저장 |
Resource 유형과 저장 책임
STEP 8.7 부터 등록 대상은 SERVER / WEBSITE / API 세 유형이다(OTHER 는 범위 밖). 유형은
등록 후 변경 불가(409). 정본: docs/resource-types.md.
✓ 사용 · — 항상 NULL(보내면 400) · 굵게 = 필수
필드 | 저장소 | SERVER | WEBSITE | API |
| PG | ✓ / ✓ / ✓ | ✓ / ✓ / ✓ | ✓ / ✓ / ✓ |
| PG | ✓ / ✓ | ✓ / — | ✓ / — |
| PG | ✓ / ✓ | — | — |
| PG | — | ✓ | — |
| PG | — | — | ✓ / ✓ |
| PG | — | — | ✓ |
| PG | —(¹) | ✓ | ✓(= |
| PG | — | ✓ | ✓ |
| Vault | ✓ / ✓ | — | — |
| Vault | ✓(²) | ✓ | — |
| Vault | ✓(²) | — | — |
| 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 |
| Liveness / Readiness(DB+Vault) | 없음 | — |
POST |
| LOCAL 가입 / 로그인(JWT 발급) | 없음 | — |
GET |
| 현재 사용자 프로필 | 인증 | — |
POST/GET/DELETE |
| API Key 발급(1회 노출)/목록/폐기 | Web 사용자만(API Key 로 불가) | 발급 시 1회 |
GET |
| operation 권한 있는 서버 목록/상세 |
| — |
POST/PUT/GET/DELETE |
| 전 유형 Credential 등록/교체/상태/삭제 | 인증 | — |
POST/PUT/GET/DELETE |
| SSH Credential (SERVER 전용 하위 호환) | 인증 | — |
GET |
| 내 소유 리소스 목록/검색(전 유형) |
| — |
POST |
| ⚠️ Credential 원문 조회 |
| 평문 |
/resources/{id}/credentials(전 유형, STEP 8.7 신규)와/servers/{id}/credentials/ssh(SERVER 전용 하위 호환)는 SERVER 에 대해 동작·저장 결과가 동일하다. 후자는 WEBSITE/API 대상이면 409.reveal 응답은
resource_typediscriminator 로 갈리는 oneOf(SERVER/WEBSITE/API). SERVER 응답은resource_type키만 additive 로 추가돼 기존 Skill 이 그대로 동작한다.scope 표기 불일치는 코드 그대로다:
servers.read(점) vsresources: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 |
| HS256 |
| 개발 주 로그인 / Web UI. |
Microsoft Entra |
| RS256(only, JWKS) |
| 사내 SSO. Bearer JWT 기본 경로 |
API Key |
| HMAC-SHA256 해시 |
| Claude/CLI. 접두 |
DEV | 헤더 없음 | — |
| 로컬 편의. |
저장 안 되는 것: 평문 password(Argon2id 해시만), Access/Refresh Token, API Key 원문(발급 시 1회만 노출). 상세: docs/token-storage-policy.md.
LOCAL(HS256)과 Entra(RS256)는 알고리즘·issuer·audience 로 분리, 교차검증 금지.
API Key scope:
resources:read,credentials:reveal,servers.read등. Web 사용자는 scope 검사를 통과(스코프 개념은 API Key 전용).상세: docs/local-authentication.md, docs/entra-authentication.md, docs/api-key-authentication.md.
Vault 경로와 삭제 정책
논리 경로(DB credential_ref 에 저장). DB 값이 경로의 정본 — 읽기/교체/삭제 시 재생성하지
않고 저장값을 그대로 쓴다(그래서 기존 행이 호환 로직 없이 동작). 경로는 UUID 로만 구성(사용자
입력·alias 미사용 → path traversal 차단).
구분 | 형식 |
신규(전 유형) |
|
legacy(STEP 6~8 SERVER) |
|
KV v2 물리 경로 = {mount}/data/{credential_ref}. VaultClient 는 App Token Policy 가 실제로
허용하는 endpoint 만 쓴다:
동작 | HTTP endpoint | 필요 capability |
write / read |
|
|
metadata read |
|
|
soft delete |
|
|
undelete(보상) |
|
|
삭제는 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.
테이블 | 역할 |
| 신원. LOCAL(login_id+password_hash) / MICROSOFT(tenant_id+entra_oid) 두 출처 |
| API Key 메타데이터. 원문 미저장(key_hash/key_prefix 만) |
| 등록 대상 Resource(SERVER/WEBSITE/API 전부). 이름은 하위 호환으로 유지 |
| 인가 단위: 사용자 × 리소스 × operation. Default Deny, DENY 우선 |
| Vault 접속 메타데이터. 중앙 Vault(시스템 소유)면 owner NULL |
| 감사 이력. 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_allowed—resource_type IN ('SERVER','WEBSITE','API')auth_type_api_only—auth_type IS NULL OR resource_type = 'API'(SshAuthType/ApiAuthType 혼용 차단)
Migration 이력(revision id 는 alembic_version.version_num VARCHAR(32) 제약):
revision | 내용 |
| 초기 스키마 5테이블(vault_mcp schema, enum=VARCHAR(32)) |
| LOCAL 로그인 필드 + api_keys 테이블, Entra 필드 nullable 전환 |
|
|
|
|
|
|
| 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.shAPI 문서:
http://127.0.0.1:8000/docs(local/dev 에서만)Web UI:
http://127.0.0.1:8000/web/loginPoC 로그인 계정 생성:
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_ENV, APP_HOST, APP_PORT |
|
| DB_HOST/PORT/NAME/USERNAME/PASSWORD/SCHEMA | 공유 DB |
| LOCAL_AUTH_ENABLED, LOCAL_JWT_SECRET, LOCAL_JWT_ISSUER | HS256 자체 JWT |
| API_KEY_HASH_SECRET, API_KEY_MAX_ACTIVE_PER_USER | 미설정 시 SHA-256 fallback |
| ENTRA_TENANT_ID, ENTRA_CLIENT_SECRET, ENTRA_AUDIENCE, ENTRA_ISSUER | Resource Server 검증 |
| VAULT_ADDR, VAULT_TOKEN / VAULT_TOKEN_FILE, VAULT_KV_MOUNT | Token 원문 또는 0600 파일 |
| 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 의
newTag를sha-<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(비패키지 애플리케이션 모드) |
문서 인덱스
Git 정책: 기본 브랜치 main, 명시적 요청 없이 commit/push 하지 않는다. .env·Token·인증서·
Private Key 는 커밋 금지. 프로젝트 원칙과 작업 하네스는 CLAUDE.md.
This server cannot be deployed
Maintenance
Related MCP Connectors
Scoped, audited SSH exec, sessions, and SFTP on your saved servers without exposing credentials
- FullmaktOAuthai.fullmakt
Credential broker for AI agents: scoped, revocable API access with policy enforcement and audit.
Issue, rotate and revoke scoped API-key passes for 25+ providers — the agent never sees a real key
Secrets for developers and agents—secure context and workflows without exposing secret values.
Related MCP Servers
- AlicenseBqualityDmaintenanceEnables enterprise-grade authentication management with secure credential handling and support for multi-protocol auth, complete with tools for analyzing, setting up, and testing authentication systems.841AGPL 3.0
- AlicenseBqualityDmaintenanceEnterprise-grade authentication solution that provides secure credential management with encryption, multi-protocol authentication (OAuth2, SAML, LDAP), and real-time threat detection for applications.81AGPL 3.0
- FlicenseNot gradedqualityDmaintenanceEnables secure management of agent-scoped secrets in HashiCorp Vault through MCP protocol. Provides per-agent namespacing, multiple authentication methods (API key, JWT, mTLS), and optional encryption/decryption capabilities with built-in rate limiting.3-
- AlicenseNot gradedqualityAmaintenanceEncrypted-at-rest credential vault with MCP server for agent credential lookup and management.8 npmMIT