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(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

# 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
}
"""

with EmbeddedSpiceDB(schema, [], options={
    "datastore": "postgres",
    "datastore_uri": "postgres://user:pass@localhost:5432/spicedb",
}) 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(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(schema, relationships, options=None) — Create an instance. Pass [] for no initial relationships. Pass options dict for datastore/transport config. 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.).

Options

options = {
    "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(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.5.2.tar.gz (8.8 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.5.2-py3-none-win_amd64.whl (9.3 kB view details)

Uploaded Python 3Windows x86-64

spicedb_embedded-0.5.2-py3-none-manylinux_2_28_x86_64.whl (8.8 kB view details)

Uploaded Python 3manylinux: glibc 2.28+ x86-64

spicedb_embedded-0.5.2-py3-none-manylinux_2_28_aarch64.whl (9.3 kB view details)

Uploaded Python 3manylinux: glibc 2.28+ ARM64

spicedb_embedded-0.5.2-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.5.2.tar.gz.

File metadata

  • Download URL: spicedb_embedded-0.5.2.tar.gz
  • Upload date:
  • Size: 8.8 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.5.2.tar.gz
Algorithm Hash digest
SHA256 d7e0dd708200d9d4860dd62f6a91d90d9c339d323e07335e13929a6923d86354
MD5 e39fecc8fcde2b434c675194e8b7c2f4
BLAKE2b-256 dbcb10fcb9222dcdf3676b1cf24a8df78d5c117c263865ec5405c455f7048f0b

See more details on using hashes here.

Provenance

The following attestation bundles were made for spicedb_embedded-0.5.2.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.5.2-py3-none-win_amd64.whl.

File metadata

File hashes

Hashes for spicedb_embedded-0.5.2-py3-none-win_amd64.whl
Algorithm Hash digest
SHA256 e0320b659fa2c21f2b8eba9177264b40ffd696c96082aec43aff206bfa14352a
MD5 40ea2c36c2482f53a930e83b936f1bd2
BLAKE2b-256 16d32667fe2d8d60b4a5e13d5f403c7817edf2a2aacba03c22d7054ff69c81a0

See more details on using hashes here.

Provenance

The following attestation bundles were made for spicedb_embedded-0.5.2-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.5.2-py3-none-manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for spicedb_embedded-0.5.2-py3-none-manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 39fc220b22248052329f185ad4c83fc23617006b195759003028c570b2be0a6c
MD5 4e1945ca872ab0928c00ecdb2e6577cc
BLAKE2b-256 120870e95b4a07b6c71d33c201d1fe712ec4b8671acbda416492e3169445d3ed

See more details on using hashes here.

Provenance

The following attestation bundles were made for spicedb_embedded-0.5.2-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.5.2-py3-none-manylinux_2_28_aarch64.whl.

File metadata

File hashes

Hashes for spicedb_embedded-0.5.2-py3-none-manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 ed2545fd174d90e84754dfd4d3ef253a3aba58cc76106dd7d205ecfd76a0628a
MD5 b10faaa85358b699a5e0df53c6fcd1fd
BLAKE2b-256 35bc5c39347c442906ee882da67fa41c0e51a584db06d203c37c30ddc30bf9dd

See more details on using hashes here.

Provenance

The following attestation bundles were made for spicedb_embedded-0.5.2-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.5.2-py3-none-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for spicedb_embedded-0.5.2-py3-none-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 dbf39d5ac3599db5400b0465a62f95e5dc6172c9f6a862a85d6702d062018e9d
MD5 ae040c8071705b972e0c2c439fd06e4a
BLAKE2b-256 645be9b9b9bb51d1951f65707863281a7042e6b915da0cfee2501cc5c42e00be

See more details on using hashes here.

Provenance

The following attestation bundles were made for spicedb_embedded-0.5.2-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