Skip to main content

Burrow SDK for Python

Read secrets from a self-hosted RatelKey Burrow with a machine identity.

  • Single and structured secrets, and individual fields of a structured secret.
  • The machine's own access map (list_projects, list_secrets).
  • Certificate pinning, or standard CA trust (TlsMode).
  • Live secrets that follow every change on the Burrow (live, live_environment).
  • An OIDC token instead of a key (Burrow.oidc).

Requirements

  • Python 3.9+.
  • One dependency: cryptography (Ed25519 signing and the certificate pin).

Install

pip install ratelkey-burrow-sdk

Bootstrap a machine

From the Burrow dashboard, Machines → Add machine, and run the install it gives you on the target host. The identity lands at ~/.burrow/burrows/<slug>/identity.json.

Quick start

from ratelkey_burrow import Burrow

# The single machine identity on this host (under ~/.burrow, or $BURROW_HOME).
burrow = Burrow()

# A single-value secret:
api_key = burrow.get_secret("payments/prod/API_KEY").value

# A structured secret — one read, projected locally (no re-fetch):
db = burrow.get_secret("payments/prod/DATABASE")
everything = db.to_dict()                                  # every field as name -> value
host = db.get_field("host")                                # one field
user, password = db.get_fields("username", "password")     # in order

# What this machine can read:
for p in burrow.list_projects():
    print(p.project, p.categories)

Point it at a specific identity by selector or path:

Burrow("burrow-a1b2c3d4e5f60718")                            # slug / name / machine id / URL
Burrow("/home/you/.burrow/burrows/burrow-a1b2c3d4e5f60718")  # path (a burrow dir or identity.json)

Without ~/.burrow

For an app that manages its own key material:

import os
from ratelkey_burrow import Burrow

burrow = Burrow.connect(
    burrow_url="https://burrow.internal:12010",
    machine_id="...",
    private_key_pem=os.environ["BURROW_MACHINE_KEY"],  # PKCS#8 PEM
)

Live secrets

A live handle holds a secret's current value and follows every change on the Burrow as it happens.

db = burrow.live("payments/prod/DATABASE")

db.get_field("password")                                    # always the current value
db.on_change(lambda next, prev: pool.reconnect(next))

burrow.live_environment("payments/prod") does the same for a whole environment: env.get("API_KEY"), and on_change receives what changed, was added or was removed.

  • The call returns after the first read. A missing secret or grant is refused there.
  • All live handles on a client share one connection on a background thread. It reconnects on its own and re-reads anything that changed while it was down.
  • status is live, reconnecting, revoked (access was taken away) or removed (deleted on the Burrow). The last two are final, and the handle keeps its last value.
  • Listeners run on the SDK's threads. One that raises is reported to on_error.
  • burrow.close() closes every handle.
  • Needs a Burrow with live updates; an older one is refused at live().

In-memory identity

Enroll with a machine token's code. The key is generated in memory and never written to disk; the code sets how the Burrow's certificate is trusted.

import os
from ratelkey_burrow import Burrow

with Burrow.enroll(os.environ["BURROW_ENROLL_CODE"]) as burrow:
    api_key = burrow.get_secret("payments/prod/API_KEY").value

The machine is enrolled on the first read. Shortly before it expires, the SDK enrolls a fresh one with the same code and retires the old one. close() (or leaving the with block) expires the machine at once.

Burrow() enrolls from BURROW_ENROLL_CODE when the host has no identity under ~/.burrow. A one-time invitation code is refused; use a machine token.

OIDC

import os
from ratelkey_burrow import Burrow

burrow = Burrow.oidc(
    burrow_url="https://burrow.example.com",
    fingerprint=os.environ.get("BURROW_FINGERPRINT"),  # omit for a publicly-trusted certificate
)

api_key = burrow.get_secret("payments/prod/API_KEY").value

audience defaults to burrow_url. GitHub Actions currently requires permissions: id-token: write.

Certificate trust

from ratelkey_burrow import Burrow, TlsMode

burrow = Burrow(tls=TlsMode.SystemTrust)

Without an explicit tls, the SDK uses the trust chosen when the machine was added: encrypted by default (works everywhere), or verified against the Burrow's own key or a CA if that was selected.

  • TlsMode.Pinned — trust-on-first-use, stored at ~/.burrow/burrows/<slug>/known_cert.
  • TlsMode.PinnedTo("aa:bb:...") — a fixed fingerprint (from the Burrow's network settings).
  • TlsMode.SystemTrust — CA + hostname verification, for a Burrow on a custom domain or Let's Encrypt.
  • TlsMode.Insecure — no verification; accepts any certificate. Opt-in only, for a network you already trust. Shortcut: Burrow().insecure_tls(True).

Webhooks

Verify a delivery from a Burrow's Signed webhook. Needs only the webhook's signing secret, not a machine identity.

import os
from flask import Flask, request
from ratelkey_burrow import verify_webhook

app = Flask(__name__)

@app.post("/hooks/burrow")
def burrow_hook():
    event = verify_webhook(request.get_data(), request.headers, os.environ["BURROW_WEBHOOK_SECRET"])
    print(event.event, event.data.summary)
    return "", 204

Pass the raw body, before JSON parsing (request.body in Django). A retry of the same event carries the same event.id, so keep the ids you've handled to ignore repeats.

Errors

Every failure is a BurrowError: BurrowAuthError (401), BurrowForbiddenError (403, no grant), BurrowNotFoundError (404), BurrowServerError (5xx), BurrowCertificateError (pin mismatch), BurrowTransportError (unreachable / unparsable), BurrowIdentityError (no/ambiguous/invalid identity), plus two projection errors on the result handle — SecretShapeError (e.g. .value on a structured secret) and FieldNotFoundError. The message carries the Burrow's own reason. verify_webhook raises BurrowWebhookError for a missing or wrong signature.

Metadata

Release files for ratelkey-burrow-sdk 1.2.0

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

Source distribution (sdist)

Source distribution for ratelkey-burrow-sdk 1.2.0
File Size Uploaded Provenance
ratelkey_burrow_sdk-1.2.0.tar.gz 32.8 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for ratelkey-burrow-sdk 1.2.0
File Interpreter ABI Platform
ratelkey_burrow_sdk-1.2.0-py3-none-any.whl Python 3 none any Details

Total release size: 73.0 kB

Release files / ratelkey_burrow_sdk-1.2.0.tar.gz

Download URL ratelkey_burrow_sdk-1.2.0.tar.gz
Size 32.8 kB
Tags Source
SHA-256 checksum
How to use checksums
0a68c7bf70d00e3c22ca59000b2b3eee4d8cf923757a697fcd32cfb268d0e5d1
BLAKE2b-256 checksum
How to use checksums
bc4d0936f9e1ee0f1ce21dbd0a3be73b187c427d516f3cceaedffe4acee8c666
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via ktor-client

Release files / ratelkey_burrow_sdk-1.2.0-py3-none-any.whl

Download URL ratelkey_burrow_sdk-1.2.0-py3-none-any.whl
Size 40.2 kB
Tags Python 3
SHA-256 checksum
How to use checksums
376cdca5924011255bb46825bc646a25f73a39f6da9f599c220b0bf5b96427b5
BLAKE2b-256 checksum
How to use checksums
b0beddc1c103c6803393f3d47b877a2c83ed1104bcd411500d65df6fadfc1645
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via ktor-client

Security for ratelkey-burrow-sdk 1.2.0

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.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

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