Skip to main content

chamelion-vault

자체 호스팅 chamelion vault 게이트웨이에서 시크릿 값을 받아 오는 클라이언트입니다.

  • 의존성이 없습니다. 표준 라이브러리만 씁니다.
  • 값을 디스크에 쓰지 않고 캐시하지 않습니다. 받은 값은 프로세스 메모리에만 있습니다.
  • 로깅을 설정하지 않습니다. 이 패키지는 여러분의 애플리케이션 안에서 돕니다.

이 패키지는 볼트를 운영하는 조직의 구성원을 위한 것입니다. 볼트 주소·API 키· 터널 접속 정보는 여기 없고 사내 문서에 있습니다. 그것을 모르면 설치까지는 되지만 값을 받는 단계에서 막히는 것이 정상입니다.

쓰는 법

범위(팀 · 프로젝트 · 환경 · 앱)를 정한 Vault 를 하나 만들고, 그 위에서 받습니다.

from chamelion_vault import Vault

vault = Vault(team="myteam", project="myproject", env="dev", app="api")

api_key = vault.secret("EXAMPLE_KEY").get_secret_value()   # 값 하나
everything = vault.secrets()                                # 받을 수 있는 것 전부
기능 하는 일 돌려주는 것
Vault(team=, project=, env=, app=) 범위를 정합니다. 비운 칸은 환경변수에서 읽습니다 Vault
vault.secret(name) 시크릿 하나의 값 값 상자(SecretStr)
vault.secret(name, field=) 번들의 필드 하나 값 상자
vault.secrets(shared=False) 이 범위에서 받을 수 있는 것 전부 이름 → Secret
chamelion-vault run -- 명령 전부 받아 명령의 환경변수로 명령의 종료 코드

같은 코드가 노트북에서는 dev, 배포 서버에서는 prod 를 받도록 범위를 환경변수로 둘 수 있습니다.

export CHAMELION_VAULT_TEAM=myteam CHAMELION_VAULT_PROJECT=myproject CHAMELION_VAULT_ENV=dev
vault = Vault()   # 팀 · 프로젝트 · 환경 · 앱을 환경변수에서

범위가 비어 있으면 요청을 보내기 전에 MissingScopeError 가 비어 있는 칸을 전부 알려 줍니다.

앱

한 프로젝트 안의 서비스마다 다른 값(각자의 DATABASE_URL 등)은 앱 전용으로 등록됩니다. app 을 주면 프로젝트 공통 + 그 앱 전용을 받고, 다른 앱의 값은 오지 않습니다 — secret() 도 그 앱에 없는 이름은 프로젝트 공통에서 찾습니다. CHAMELION_VAULT_APP 이 설정된 환경에서 공통만 받으려면 Vault(app="") · --app "" 를 씁니다. 공통과 앱 전용에 같은 이름은 등록할 수 없으므로 어느 값이 이기는지 고민할 일이 없습니다.

번들 — 필드가 여럿인 시크릿

아이디 · 비밀번호처럼 한 몸인 크리덴셜은 한 시크릿 안의 여러 필드입니다. secret() 은 어느 필드인지 추측하지 않습니다.

vault.secret("EXAMPLE_ACCOUNT", field="password").get_secret_value()
vault.secret("EXAMPLE_ACCOUNT")   # FieldSelectionError — 필드 이름(password, username)만 알려 줍니다

전부 필요하면 secrets() 의 Secret 을 씁니다.

account = vault.secrets()["EXAMPLE_ACCOUNT"]
sorted(account)                     # ['password', 'username']
account["username"].get_secret_value()
account.project, account.env, account.app, account.name   # 위치 — 비밀이 아닙니다

Secret.path 는 0.2 호환용 표기입니다. 공용 · common 에서 온 값의 실제 위치는 project · env 로 확인하세요.

공용 값까지 한 번에

여러 프로젝트가 함께 쓰는 값은 볼트의 공용 프로젝트에 있습니다. 볼트 관리자가 내 프로젝트에 그 공용 프로젝트를 구독으로 열어 두면 한 번에 받습니다.

everything = vault.secrets(shared=True)

shared=True 는 프로젝트 공통 + 앱 전용 + 환경과 무관한 값(common) + 구독한 공용 프로젝트(같은 환경과 common)를 한 응답으로 받습니다. 두 곳에 같은 이름이 있으면 서버가 어느 쪽도 고르지 않고 전부 거부합니다.

.env 파일 없이 실행하기

chamelion-vault run -- python app.py
chamelion-vault run --app api --shared -- python app.py

받을 수 있는 값을 전부 받아 실행할 명령의 환경변수로만 넣습니다. 파일을 만들지 않고, 값을 화면에 찍지 않습니다. 이름은 시크릿 이름 그대로이고, 번들은 이름_필드 입니다 (EXAMPLE_DB_HOST). 이미 있는 환경변수와 이름이 겹치면 볼트 값이 덮어쓰고, 덮인 이름을 경고로 알립니다. 실행한 명령에는 API 키(CHAMELION_VAULT_KEY)를 넘기지 않습니다.

값이 상자에 담겨 옵니다

get_secret_value() 로 열기 전까지 값은 어디에도 그대로 나타나지 않습니다.

value = vault.secret("EXAMPLE_KEY")
print(value)   # <REDACTED>
print(vault)   # Vault(myproject/dev/api) — 키는 객체에 없습니다

무심코 남긴 로그 한 줄에 진짜 키가 찍히는 것을 막습니다. 연 뒤에는 막아 주지 않으니 꺼낸 값은 바로 쓰고 변수에 오래 들고 있지 마세요. 이 패키지는 값을 캐시하지 않습니다 — 같은 값을 두 번 부르면 두 번 요청합니다.

키는 두 종류입니다

키 받는 곳 열리는 것
개인 액세스 키 웹 콘솔 계정 메뉴 · Slack /vault key — 승인 없음 내가 멤버인 프로젝트의 local · dev · staging · common
서비스 키 볼트 관리자가 발급 그 프로젝트의 모든 환경(prod 포함) · 구독한 공용 프로젝트
  • 개인 액세스 키로는 prod 를 받지 못합니다(본인 비공개 시크릿도 마찬가지). 노트북의 키가 새도 운영 서비스가 무사하도록 정한 규칙입니다. prod 는 배포 서버 · CI 에 둔 서비스 키로 받습니다.
  • 개인 액세스 키는 30일 동안 쓰지 않으면 만료됩니다. 다시 받으면 이전 키는 그 자리에서 폐기됩니다 — 잃어버렸을 때도 다시 받으면 됩니다.
  • 키는 Slack 창에 한 번만 표시됩니다.

처음 한 번 — 빈 프로젝트에서 값이 올 때까지

네 단계입니다. 어느 하나가 빠져도 값이 오지 않고, 볼트는 어느 단계가 빠졌는지 알려주지 않습니다 — 대신 이 패키지의 오류 문안이 다음에 할 일을 알려줍니다.

① 설치

mkdir myproject && cd myproject
python -m venv .venv
source .venv/bin/activate          # Windows: .venv\Scripts\activate
pip install chamelion-vault

pip list 에 chamelion-vault 하나만 늘어납니다. 딸려 오는 것이 없습니다.

② 키 — 개인 액세스 키를 받아 환경변수에 넣습니다.

read -rs CHAMELION_VAULT_KEY && export CHAMELION_VAULT_KEY

⚠️ 키를 명령줄에 그대로 쓰지 마세요. 셸 기록에 원문이 남습니다. 위 명령은 입력이 화면에 보이지 않는 것이 정상입니다.

③ 터널 — 창을 하나 따로 열어 띄웁니다. 아래 "터널" 절을 보세요.

ssh -N vault-tunnel

④ 받기

# app.py
from chamelion_vault import Vault, VaultError

try:
    value = Vault(team="myteam", project="myproject", env="dev").secret("EXAMPLE_KEY")
except VaultError as error:
    raise SystemExit(f"\n{error}")

print(value)  # <REDACTED>

<REDACTED> 가 찍히면 값이 온 것입니다. 값 자체는 찍히지 않습니다.

설정 — 환경변수

환경변수 뜻 기본값
CHAMELION_VAULT_KEY API 키 (개인 액세스 · 서비스) 없음 (필수)
CHAMELION_VAULT_URL 게이트웨이 주소 http://127.0.0.1:8081
CHAMELION_VAULT_TEAM Vault 의 팀 없음
CHAMELION_VAULT_PROJECT Vault 의 프로젝트 없음
CHAMELION_VAULT_ENV Vault 의 환경 없음
CHAMELION_VAULT_APP Vault 의 앱 없음 — 프로젝트 공통만

설정 파일은 지원하지 않습니다. 파일을 읽게 만들면 거기에 키를 적게 되고, 그 파일은 언젠가 저장소에 들어갑니다. 키를 인자로 받지도 않습니다 — 같은 이유입니다.

터널

게이트웨이는 볼트 호스트의 루프백에만 열려 있습니다. 밖에서 값을 받으려면 그 루프백까지 가는 SSH 터널이 필요하고, 이 패키지는 터널을 대신 띄우지 않습니다. 프로세스 수명·키 경로·OS 차이가 전부 따라 들어와, 실패했을 때 터널 문제인지 조회 문제인지 구분이 안 되기 때문입니다.

~/.ssh/config 에 한 번 적어 두면 그 뒤로는 한 줄입니다.

Host vault-tunnel
    HostName <볼트 호스트>
    Port <SSH 포트>
    User <계정>
    IdentityFile ~/.ssh/<터널 키>
    IdentitiesOnly yes
    LocalForward 8081 127.0.0.1:8081
ssh -N vault-tunnel

⚠️ 왼쪽 포트와 오른쪽 포트는 다른 것입니다. LocalForward 8081 127.0.0.1:8081 에서 앞의 8081 은 내 컴퓨터에서 고른 포트이고, 뒤의 127.0.0.1:8081 은 볼트 호스트의 게이트웨이입니다. 내 컴퓨터에서 8081 을 이미 쓰고 있다면 앞의 값만 바꾸고 CHAMELION_VAULT_URL 을 거기에 맞추세요. 뒤의 값을 바꾸면 터널이 아예 열리지 않습니다.

    LocalForward 8082 127.0.0.1:8081
export CHAMELION_VAULT_URL=http://127.0.0.1:8082

⚠️ IdentitiesOnly yes 를 빠뜨리지 마세요. 이것이 없으면 기본 키(~/.ssh/id_*)가 먼저 인증을 시도해, 터널 키에 걸어 둔 제약이 통째로 비껴갑니다. 실패 원인을 찾기 가장 어려운 자리입니다.

<볼트 호스트>·<SSH 포트>·<계정>·<터널 키> 는 사내 터널 문서에 있습니다.

값을 받지 못했을 때

볼트는 실패 원인을 알려주지 않습니다. 키가 틀렸는지 · 권한이 없는지 · 그런 시크릿이 없는지를 응답으로 가르면 그것이 곧 남의 볼트를 훑는 도구가 되기 때문입니다. 그래서 이 패키지도 추측하지 않고, 대신 확실히 아는 것만 말합니다.

예외 뜻 할 일
MissingApiKeyError 키 환경변수가 비었다 개인 액세스 키를 받는다
MissingScopeError 팀 · 프로젝트 · 환경 중 빈 칸이 있다 인자나 환경변수를 채운다
VaultUnreachableError 연결 자체가 안 됐다 터널이 떠 있는지 본다
AccessRefusedError 볼트가 값을 주지 않았다 메시지의 원인 순서대로 확인한다
FieldSelectionError 번들에서 필드를 고르지 않았다 field= 로 고른다
UnexpectedResponseError 계약에 없는 응답이 왔다 주소가 정말 게이트웨이인지 확인한다

AccessRefusedError 의 흔한 원인 순서는 멤버십 → 환경(개인 액세스 키로 prod) → 팀 이름 → 키 만료 → 이름 오타 → 공용 겹침 → 남의 비공개 시크릿 입니다. 모든 예외는 VaultError 를 상속하므로 한 번에 잡을 수 있습니다.

받을 수 없는 것

  • 남의 비공개 시크릿. 소유자 본인만 받습니다. 관리자도 값을 볼 수 없습니다. 여러 사람 · 서버가 써야 하는 값이라면 비공개로 두면 안 됩니다.
  • 다른 앱 · 다른 프로젝트의 값. 범위 밖의 값은 응답에 들어가지 않고, 무엇이 빠졌는지도 알려주지 않습니다. 꼭 있어야 하는 이름이 있으면 받은 뒤 직접 확인하세요.

0.1 방식에서 옮기기

경로로 받던 get_secret · get_secrets 는 0.3.0 에서 제거 예정 경고를 내고 그대로 동작합니다.

# 0.1
from chamelion_vault import get_secret
get_secret("myproject", "dev", "EXAMPLE_KEY")["value"]

# 0.3
from chamelion_vault import Vault
Vault(team="myteam", project="myproject", env="dev").secret("EXAMPLE_KEY")

0.1 의 머신 키는 Vault 로 받지 못합니다. 개인 액세스 키나 서비스 키로 바꿔 주세요.

Metadata

Release files for chamelion-vault 0.3.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for chamelion-vault 0.3.1
File Size Uploaded
chamelion_vault-0.3.1.tar.gz 17.4 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for chamelion-vault 0.3.1
File Interpreter ABI Platform
chamelion_vault-0.3.1-py3-none-any.whl Python 3 none any Details

Total release size: 39.5 kB

Release files / chamelion_vault-0.3.1.tar.gz

Download URL chamelion_vault-0.3.1.tar.gz
Size 17.4 kB
Tags Source
SHA-256 checksum
How to use checksums
b69cbbf6b1b315db0e8d9fb0acc7b62483342ce0b88ac88d23326c18605682da
BLAKE2b-256 checksum
How to use checksums
07043166116956a802a1cc068ff162fbd32ec0aeb0de0a403ef2b199f6145639
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 12, 2026.

Transparency log

Release files / chamelion_vault-0.3.1-py3-none-any.whl

Download URL chamelion_vault-0.3.1-py3-none-any.whl
Size 22.1 kB
Tags Python 3
SHA-256 checksum
How to use checksums
715b3dcb543407ed17aa7eddcb9452b3e065e8668d7c23c5505b3321f03ba7a0
BLAKE2b-256 checksum
How to use checksums
fa6183164515b3537044be61c80c09577ee613254717e6502b0a69c56352d746
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 12, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.3.1 This release

2 release files

0.3.0

2 release files

0.1.1

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page