TariqDreamsTech/ranbval-sdk

GitHub: TariqDreamsTech/ranbval-sdk

Ranbval SDK 是一个 Python 密钥管理客户端,通过加密令牌和仓库白名单机制防止 API 密钥泄露,并追踪每次访问。

Stars: 1 | Forks: 0

[![PyPI](https://img.shields.io/pypi/v/ranbval-sdk)](https://pypi.org/project/ranbval-sdk/) [![Python](https://img.shields.io/pypi/pyversions/ranbval-sdk)](https://pypi.org/project/ranbval-sdk/) [![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE) # Ranbval SDK `v3.5.2` **The Python client for Ranbval — a secret manager for API keys.** Encrypt secrets in the Ranbval dashboard, store the encrypted tokens in `.ranbval` files, and decrypt them only at runtime — AES-256-GCM with PBKDF2 key derivation, no plaintext ever touches source control. Unlike a plain `.env`, a stolen config is useless off your allowlisted repos, and every use is attributable in the Live Monitor. pip install ranbval-sdk ## Why Ranbval Exists Every team now juggles a pile of API keys — LLM providers, payment processors, databases, third-party services. Those keys leak constantly, and almost always the same handful of ways: - A key gets **committed to Git** — and bots scrape public repos within minutes. - A `.env` file is **copied and shared** over Slack/email — then forwarded, forgotten, and lives forever with no expiry. - A key is **accidentally printed to logs** or captured by an error reporter — and now it sits in Datadog/Sentry, readable by the whole org, retained for years. - When a key *does* leak, **nobody knows who leaked it or which repo burned the tokens** — so you can't rotate with confidence. `.env` + `load_dotenv()` does nothing about any of this: the secret is plaintext on disk, works anywhere it's copied, forever, with zero visibility. Ranbval is built to close exactly these gaps. ### What it actually protects (and what nothing can) Be clear-eyed about the threat model — it's what makes the guarantees trustworthy: - **What no tool can stop:** an attacker who already runs code *inside your process*. If they can execute in your app, they can read `os.environ`, hook functions, or dump memory — and **no** secret manager (Vault, AWS/GCP Secrets Manager, Doppler, Ranbval) prevents that. It isn't the real-world leak vector. - **What Ranbval does stop** — the leaks that actually happen: | Real-world leak | `.env` | Ranbval | |---|---|---| | Key committed to Git | 🔴 plaintext, public instantly | 🟢 encrypted token — a commit leaks nothing usable | | Config file copied / shared | 🔴 works anywhere, forever | 🟢 **useless without the project secret *and* an allowlisted repo** | | Key printed to logs / captured by Sentry | 🔴 sits in log storage for years | 🟢 `SecretString` masks every display path; can't be pickled into a cache/report | | A key leaks — who? which repo? | 🔴 zero visibility | 🟢 **Live Monitor** flags the same credential on a new device/IP → rotate with proof | The crown jewel is the **repo allowlist**: even if someone steals your entire `.ranbval` file *and* your project secret, they still can't decrypt it from a repo that isn't on your control-plane allowlist. A stolen config is a dead config. ### An analogy You can't make a house key that opens *your* door but that a thief holding it can't use — if the key opens the lock, whoever holds it gets in. That's physics, not a flaw. Real security comes from three other things, and Ranbval gives you all three: 1. **The key isn't lying in the street** → plaintext never touches Git (encrypted tokens). 2. **The key only works at your house** → the repo allowlist makes a stolen file worthless elsewhere. 3. **An alarm rings if a stranger walks in** → leak detection alerts on a new device/IP. ### Why use it - **Drop-in.** One `load_ranbval()` replaces scattered `load_dotenv()`; keys pass straight into your existing SDKs — Ranbval ships no vendor dependencies. - **Safe by default.** Secrets are sealed `SecretString`s that refuse to print, log, or serialize; plain config is opt-in plaintext via `PUBLIC_` name prefixes and `public()`. - **Accountable.** Every decrypt is attributable, and misuse is detectable — something a plain `.env` can never offer. ## Quick Start from ranbval_sdk import load_ranbval, decrypt_key import os, openai # 1. Load encrypted config from .ranbval files (no network, no decryption) load_ranbval() # 2. Decrypt a vault token — returns a SecretString, never printable. # This also auto-reports the usage to your Live Monitor (no extra code). api_key = decrypt_key("SECRET_OPENAI_KEY") # 3. Pass directly to the SDK — value is never exposed in logs or prints client = openai.OpenAI(api_key=api_key.use()) response = client.chat.completions.create( model="gpt-4o", messages=[{"role": "user", "content": "Hello"}], ) `.ranbval.local` (never commit this file): RANBVAL_PROJECT_SECRET=your_dashboard_project_secret SECRET_OPENAI_KEY=ranbval.4ii0a022aa.p1GOZ...ahsan ## CLI `pip install ranbval-sdk` ships a `ranbval` command: ranbval init # starter .ranbval + gitignore .ranbval.local ranbval check # lint: unclassified keys, [section] headers, competing .env, mismatches ranbval run -- python app.py # load .ranbval into the env, then run (secrets only in that process) `ranbval check` exits non-zero on errors, so drop it into CI or a pre-commit hook. ## Remote config (no local file) Pull the whole env-set from the Ranbval control plane instead of shipping a `.ranbval` — the project secret is the credential, and everything downstream (decryption, prefixes, enforcement) is identical to loading from a file: from ranbval_sdk import load_ranbval, decrypt_key load_ranbval(remote=True, project_secret="ranbval-proj-…") # fetches SECRET_/PROXY_/PUBLIC_ client = openai.OpenAI(api_key=decrypt_key("SECRET_OPENAI_KEY").use()) `SECRET_`/`PROXY_` values come down as encrypted `ranbval.*` tokens (decrypted client-side); `PUBLIC_` values are plaintext. Add a key in the dashboard → it appears here on the next load. **Owner vs developer.** The owner fetches with the project secret. A developer fetches with a `ranbval-dev-…` token the owner issues from the dashboard, and can add `PUBLIC_` envs from code — attributed to them: load_ranbval(remote=True, api_key="ranbval-dev-…") # developer fetch from ranbval_sdk import push_env push_env("PUBLIC_FEATURE_FLAG", "on", api_key="ranbval-dev-…") # shows as "added by " `SECRET_`/`PROXY_` keys stay owner-only (created encrypted in the dashboard). ## Environments (dev / staging / production) A project holds up to **10 named environments**, and every key and `PUBLIC_` value lives in one of them. The *same name* therefore holds a *different value* per stage: project "My App" ├── development SECRET_OPENAI_KEY=ranbval.… PUBLIC_DATABASE_URL=postgres://dev… ├── staging SECRET_OPENAI_KEY=ranbval.… PUBLIC_DATABASE_URL=postgres://stg… └── production SECRET_OPENAI_KEY=ranbval.… PUBLIC_DATABASE_URL=postgres://prod… Pull exactly one: load_ranbval(remote=True, environment="production") client = openai.OpenAI(api_key=decrypt_key("SECRET_OPENAI_KEY").use()) # production's key Only that stage's values are fetched — **production credentials never reach a development machine**, even if the developer's token is valid for the project. **How the stage is chosen** — explicit argument first, then the environment: load_ranbval(remote=True, environment="staging") # 1. explicit # else RANBVAL_ENV / ENVIRONMENT / ENV # 2. from the environment # else the project's first environment # 3. server default export RANBVAL_ENV=production # CI / server sets this once; code stays identical `RANBVAL_ENV` is the same variable that picks a local `.ranbval.{mode}` file — one idea ("which stage am I running in"), one variable, whether the config comes from disk or the control plane. `push_env` takes the same argument, so a developer can add a `PUBLIC_` value to one stage: push_env("PUBLIC_FEATURE_FLAG", "on", api_key="ranbval-dev-…", environment="staging") Environments are created, renamed, and deleted from the dashboard. Deleting one deletes every key and `PUBLIC_` value inside it; a project always keeps at least one. ## Module Reference | Symbol | Description | |--------|-------------| | `load_ranbval()` | Merges layered `.ranbval*` files into `os.environ`; `remote=True, environment="…"` pulls one stage from the control plane | | `public()` | Read a plaintext (unencrypted) config value — never decrypts | | `public_config()` | Dict of every `PUBLIC_`-prefixed key as `{name: plaintext}` | | `proxy_token()` | Raw encrypted token for a `PROXY_` key — pass to `proxy_request()` (never decrypted client-side) | | `safe_decrypt()` | Decrypts a vault token string → `SecretString` | | `decrypt_key()` | Reads an env var and decrypts it in one call | | `SecretString` | Wrapper that blocks all display paths — value only via `.use()` | | `require_reveal_scope()` / `reveal_scope()` | Restrict a secret so `.use()` works only inside an approved block | | `install_access_monitor()` | Detect & report suspicious secret access / possible exfiltration | | `set_enforcement()` / `is_enforced()` | Toggle strict mode — extraction attempts raise `RanbvalSecurityError` (on by default) | | `proxy_request()` | Route an HTTP request through the Ranbval proxy (key injected server-side) | | `emit_telemetry()` | Record a **custom** usage event (basic usage is auto-reported on every `decrypt_key()`) | | `get_audit_log()` | Return the in-process audit log list | | `clear_audit_log()` | Clear the in-process audit log | | `get_project_key()` | Read `RANBVAL_PROJECT_SECRET` from env | | `find_ranbval_file()` | Locate the nearest `.ranbval*` file on disk | | `find_ranbval_directory()` | Locate the config root directory | | `resolve_ranbval_mode()` | Determine the active mode from env/args | ## Package Layout Everything is organized by concern. You only import from the top level (`from ranbval_sdk import …`); the table shows where each piece lives. ranbval_sdk/ ├── __init__.py # the public API (re-exports everything below) ├── exceptions.py # RanbvalError hierarchy ├── py.typed # ships type information (PEP 561) ├── config/ # your .ranbval configuration surface │ ├── loader.py # load_ranbval, find_*, resolve_ranbval_mode, get_project_key │ ├── access.py # imperative access — Vault, env, inject, secrets, iter_secrets │ └── declarative.py # class-based access — Secret, SecretConfig ├── crypto/ # cryptography & sealed secrets (only crypto lives here) │ ├── cipher.py # AES-256-GCM decrypt + project-secret resolution │ ├── secret_string.py # SecretString — the sealed, never-printable value │ └── audit.py # in-memory log of every .use() ├── policy/ # provenance & access policy (the decrypt gate) │ └── repo.py # git-remote allowlist enforcement (server-controlled) ├── serializers/ # wire (de)serializers — one module per payload shape │ ├── telemetry.py # /api/telemetry body + security metadata │ ├── proxy.py # /api/execute request body │ ├── token.py # parse ranbval...
标签:LNA, Python, Streamlit, 加密, 文档结构分析, 无后门, 漏洞扫描器, 访问控制, 逆向工具