Skip to main content

Embedded SpiceDB for Python — embedded authorization using the standard gRPC API

Project description

spicedb-embedded (Python)

Sometimes you need a simple way to run access checks without spinning up a new service. This library provides an embedded version of SpiceDB in various languages. Each implementation is based on a C-shared library (compiled from the SpiceDB source code) with a very thin FFI binding on top of it. This means that it runs the native SpiceDB code within your already-running process.

from spicedb_embedded import EmbeddedSpiceDB
from authzed.api.v1 import (
    CheckPermissionRequest,
    CheckPermissionResponse,
    Consistency,
    ObjectReference,
    Relationship,
    SubjectReference,
)

schema = """
definition user {}

definition document {
    relation reader: user
    permission read = reader
}
"""

rel = Relationship(
    resource=ObjectReference(object_type="document", object_id="readme"),
    relation="reader",
    subject=SubjectReference(object=ObjectReference(object_type="user", object_id="alice")),
)

with EmbeddedSpiceDB.start(schema, [rel]) as spicedb:
    req = CheckPermissionRequest(
        consistency=Consistency(fully_consistent=True),
        resource=ObjectReference(object_type="document", object_id="readme"),
        permission="read",
        subject=SubjectReference(object=ObjectReference(object_type="user", object_id="alice")),
    )
    resp = spicedb.permissions().CheckPermission(req)
    allowed = resp.permissionship == CheckPermissionResponse.PERMISSIONSHIP_HAS_PERMISSION

Who should consider using this?

If you want to spin up SpiceDB, but don't want the overhead of managing another service, this might be for you.

If you want an embedded server for your unit tests and don't have access to Docker / Testcontainers, this might be for you.

If you have a schema and set of permissions that are static / readonly, this might be for you.

Who should avoid using this?

If you live in a world of microservices that each need to perform permission checks, you should almost certainly spin up a centralized SpiceDB deployment.

If you want visibility into metrics for SpiceDB, you should avoid this.

How does storage work?

The default datastore is "memory" (memdb). If you use this datastore, keep in mind that it will reset on each app startup. This is a great option if you can easily provide your schema and relationships at runtime. This way, there are no external network calls to check relationships at runtime.

If you need a longer term storage, you can use any SpiceDB-compatible datastores.

from spicedb_embedded import EmbeddedSpiceDB, StartOptions

# Run migrations first: spicedb datastore migrate head --datastore-engine postgres --datastore-conn-uri "postgres://..."
schema = """
definition user {}

definition document {
    relation reader: user
    permission read = reader
}
"""

options = StartOptions(
    datastore="postgres",
    datastore_uri="postgres://user:pass@localhost:5432/spicedb",
)

with EmbeddedSpiceDB.start(schema, [], options=options) as spicedb:
    # Use full Permissions API (writeRelationships, checkPermission, etc.)
    pass

Running code written in Go compiled to a C-shared library within my service sounds scary

It is scary! Using a C-shared library via FFI bindings introduces memory management in languages that don't typically have to worry about it.

That being said, the SpiceDB code still runs in a Go runtime with garbage collection, which is where the vast majority of time is spent. To help mitigate some of the risk, the FFI layer is kept as straightforward as possible. protobuf is marshalled and unmarshalled at the FFI <--> language runtime boundary in a standardized way. After unmarshalling, requests are sent directly to the SpiceDB server, and responses are returned directly back to the language runtime (after marshalling).

Installation

pip install spicedb-embedded

Or from source:

cd python && pip install -e .

Prerequisites: Go 1.23+ with CGO enabled. Build the shared library first:

cd shared/c && CGO_ENABLED=1 go build -buildmode=c-shared -o libspicedb.dylib .  # macOS
cd shared/c && CGO_ENABLED=1 go build -buildmode=c-shared -o libspicedb.so .      # Linux

The library looks for libspicedb.dylib (macOS) or libspicedb.so (Linux) in SPICEDB_LIBRARY_PATH or relative to the working directory (shared/c, ../shared/c, etc.). Override with SPICEDB_LIBRARY_PATH=/path/to/shared/c.

Usage

from spicedb_embedded import EmbeddedSpiceDB
from authzed.api.v1 import (
    CheckPermissionRequest,
    CheckPermissionResponse,
    Consistency,
    ObjectReference,
    Relationship,
    SubjectReference,
)

schema = """
definition user {}

definition document {
    relation reader: user
    permission read = reader
}
"""

rel = Relationship(
    resource=ObjectReference(object_type="document", object_id="readme"),
    relation="reader",
    subject=SubjectReference(object=ObjectReference(object_type="user", object_id="alice")),
)

with EmbeddedSpiceDB.start(schema, [rel]) as spicedb:
    stub = spicedb.permissions()
    req = CheckPermissionRequest(
        consistency=Consistency(fully_consistent=True),
        resource=ObjectReference(object_type="document", object_id="readme"),
        permission="read",
        subject=SubjectReference(object=ObjectReference(object_type="user", object_id="alice")),
    )
    resp = stub.CheckPermission(req)
    allowed = resp.permissionship == CheckPermissionResponse.PERMISSIONSHIP_HAS_PERMISSION

API

  • EmbeddedSpiceDB.start(options=) — Start an instance without bootstrapping schema or relationships. Supports context manager (with).
  • EmbeddedSpiceDB.start(schema, relationships, options=) — Start an instance and bootstrap it with schema and optional relationships. Supports context manager (with).
  • permissions() — Permissions service stub (CheckPermission, WriteRelationships, ReadRelationships, etc.).
  • schema() — Schema service stub (ReadSchema, WriteSchema, ReflectSchema, etc.).
  • watch() — Watch service stub for relationship changes.
  • channel() — Underlying gRPC channel for custom usage.
  • close() — Dispose the instance and close the channel.

Use types from authzed.api.v1 (ObjectReference, SubjectReference, Relationship, etc.).

StartOptions

from spicedb_embedded import EmbeddedSpiceDB, StartOptions

options = StartOptions(
    datastore="memory",           # or "postgres", "cockroachdb", "spanner", "mysql"
    datastore_uri="postgres://user:pass@localhost:5432/spicedb",  # required for remote
    spanner_credentials_file="/path/to/key.json",  # Spanner only
    spanner_emulator_host="localhost:9010",       # Spanner emulator
    mysql_table_prefix="spicedb_",                 # MySQL only (optional)
    metrics_enabled=False,                         # default; set True to enable Prometheus metrics
)

with EmbeddedSpiceDB.start(schema, [], options=options) as spicedb:
    ...

Building & Testing

mise run shared-c-build
cd python
pip install -e ".[dev]"
pytest

Or from the repo root: mise run python-test

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

spicedb_embedded-0.6.0.tar.gz (9.5 kB view details)

Uploaded Source

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

spicedb_embedded-0.6.0-py3-none-win_amd64.whl (9.9 kB view details)

Uploaded Python 3Windows x86-64

spicedb_embedded-0.6.0-py3-none-manylinux_2_28_x86_64.whl (9.9 kB view details)

Uploaded Python 3manylinux: glibc 2.28+ x86-64

spicedb_embedded-0.6.0-py3-none-manylinux_2_28_aarch64.whl (9.9 kB view details)

Uploaded Python 3manylinux: glibc 2.28+ ARM64

spicedb_embedded-0.6.0-py3-none-macosx_11_0_arm64.whl (25.6 MB view details)

Uploaded Python 3macOS 11.0+ ARM64

File details

Details for the file spicedb_embedded-0.6.0.tar.gz.

File metadata

  • Download URL: spicedb_embedded-0.6.0.tar.gz
  • Upload date:
  • Size: 9.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for spicedb_embedded-0.6.0.tar.gz
Algorithm Hash digest
SHA256 753b9cda85d49f5990a9f2f8ee415cb2677c5559c1c4bb80bda19f69d11ac3de
MD5 19797aeecfcfa110e299a2e51138d7c9
BLAKE2b-256 9755e141f7b6c10a0e8cd8ff21066b19aa226fb9b67c02f04ddbb0a7f75ba79b

See more details on using hashes here.

Provenance

The following attestation bundles were made for spicedb_embedded-0.6.0.tar.gz:

Publisher: publish.yml on borkfork/spicedb-embedded

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file spicedb_embedded-0.6.0-py3-none-win_amd64.whl.

File metadata

File hashes

Hashes for spicedb_embedded-0.6.0-py3-none-win_amd64.whl
Algorithm Hash digest
SHA256 090bdb1552f4bfa0db50d6060fc9de8f0672636ff20d24fc95884283d71f076a
MD5 edf0abefd8ed4d9125b50751c9767b22
BLAKE2b-256 fb1b965a5fd88f079da8544a6e1b88da2d8845c7425c300e6f9148ad8291c496

See more details on using hashes here.

Provenance

The following attestation bundles were made for spicedb_embedded-0.6.0-py3-none-win_amd64.whl:

Publisher: publish.yml on borkfork/spicedb-embedded

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file spicedb_embedded-0.6.0-py3-none-manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for spicedb_embedded-0.6.0-py3-none-manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 ab7232c247aeda46cbaff392967d227ddfd382117f58c28a323688f67c8efd1b
MD5 210a754c337ecd91661facf16169bd35
BLAKE2b-256 477c08bc3c9923238f0bda0f7e5944437c9d08819aa75cad2979f0e23f9896cb

See more details on using hashes here.

Provenance

The following attestation bundles were made for spicedb_embedded-0.6.0-py3-none-manylinux_2_28_x86_64.whl:

Publisher: publish.yml on borkfork/spicedb-embedded

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file spicedb_embedded-0.6.0-py3-none-manylinux_2_28_aarch64.whl.

File metadata

File hashes

Hashes for spicedb_embedded-0.6.0-py3-none-manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 cdb8e14c52d0f44d3a22f879d0a140ecc73bf071b4582afac65b6fff7d202c50
MD5 9ddb8044d9e04ca925a3cc0770edbab4
BLAKE2b-256 a650bbf46866d8279f106d2d75d10869665ece4f3bd7c3e7b7a1687205373dd0

See more details on using hashes here.

Provenance

The following attestation bundles were made for spicedb_embedded-0.6.0-py3-none-manylinux_2_28_aarch64.whl:

Publisher: publish.yml on borkfork/spicedb-embedded

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file spicedb_embedded-0.6.0-py3-none-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for spicedb_embedded-0.6.0-py3-none-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 db68597ab58a530edc7d37b276027a6b388e20df6a08e76b531349cc076c4c60
MD5 ea7299d46f9b8bf0626c1a72441f88ba
BLAKE2b-256 55b99e4666cf24c182d2b56deb859521ade479821496bed489cbe62cdad997e9

See more details on using hashes here.

Provenance

The following attestation bundles were made for spicedb_embedded-0.6.0-py3-none-macosx_11_0_arm64.whl:

Publisher: publish.yml on borkfork/spicedb-embedded

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page