SpiceDB Documentation

repository·main·Indexed 27 days ago

https://github.com/authzed/spicedb

A high-performance, scalable authorization service inspired by Google's Zanzibar. SpiceDB enables fine-grained access control using a schema-based approach with relationships, supporting ReBAC and ABAC patterns. It supports multiple datastore backends including Google Cloud Spanner, CockroachDB, PostgreSQL, MySQL, and a memory-based MemDB for local development. Additionally, it provides an experimental Postgres Foreign Data Wrapper (FDW) proxy to interact with SpiceDB data using standard SQL queries.

Tokens
30.9K
Snippets
37
Records
177
Agent score
92%

What's inside SpiceDB

  1. Overview of SpiceDB Postgres FDW Proxy

    main

    The SpiceDB Postgres FDW (Foreign Data Wrapper) proxy acts as a translation layer that implements the PostgreSQL wire protocol. It converts incoming SQL queries into SpiceDB API calls, enabling standard PostgreSQL clients (like psql or application drivers) and existing PostgreSQL databases to interact with SpiceDB's permissions and relationships data as if they were standard PostgreSQL tables.

    To use this, a PostgreSQL database must have the postgres_fdw extension enabled. The proxy exposes foreign tables for:

    • permissions
    • relationships
    • schema
  2. Overview of SpiceDB

    main

    SpiceDB is an open-source authorization service inspired by Google's Zanzibar system. It allows developers to manage access control by defining a schema, writing data as relationships, and performing permission checks (e.g., "can subject X perform action Y on resource Z?").

    Key features include:

    • ReBAC & ABAC: Combines Relationship-Based Access Control and Attribute-Based Access Control via caveated relationships.
    • Global Consistency: Configurable per-request consistency.
    • Reverse Indexes: Supports queries like "What can this subject do?" or "Who can access this resource?".
    • Scalability: Designed to handle millions of queries per second and billions of relationships.
    • Agnosticism: Focused purely on authorization and is independent of your authentication/identity provider.
  3. SpiceDB CLI command overview

    main

    The spicedb CLI provides several subcommands for managing the service:

    • spicedb serve: Serve the permissions database.
    • spicedb serve-testing: Test server with an in-memory datastore.
    • spicedb datastore: Perform operations against the configured datastore (e.g., migrate, gc, repair).
    • spicedb lsp: Serve the Language Server Protocol.
    • spicedb postgres-fdw: Serve a Postgres Foreign Data Wrapper for SpiceDB (EXPERIMENTAL).
    • spicedb version: Display the version of SpiceDB.
    • spicedb man: Generate a man page.
  4. Understand the SpiceDB Proposal Process

    main

    SpiceDB uses an RFC-style proposal process to identify problems and reach consensus before implementation. This ensures that complex features are thoroughly planned and stakeholders are aligned.

    • Proposals: Used for large initiatives. A good proposal should include a problem statement with use cases, proposed solutions, open problems, and links to related issues.
    • Non-proposals: Smaller contributions that do not require formal RFCs but are tracked via GitHub issues without the kind/proposal label.

    You can participate in these discussions via the SpiceDB Discord.

  5. Use the SpiceDB embedded permission engine

    main

    The embedded package allows you to run SpiceDB's permission engine in-process without a gRPC server. This is ideal for high-performance, low-latency permission checks where you want to avoid network overhead and gRPC serialization costs. It allows passing caveat context as native Go values instead of structpb.

    Key Characteristics:

    • Scope: Only provides the Check API. It does not support schema writes, relationship writes, bulk operations, watch, lookup, or reflection.
    • Consistency: Checks are always fully consistent (evaluated at the datastore head revision).
    • Concurrency: A Permissions instance is safe for concurrent use.
    • Lifecycle: You must call Close() on the Permissions instance to release the dispatcher, but Close() does not close the underlying datastore.Datastore.
    import "github.com/authzed/spicedb/pkg/embedded"
    
    // Initialize permissions
    perms, err := embedded.NewPermissions(embedded.Config{
        Datastore: ds,
        SchemaMode: datalayer.SchemaModeReadNewWriteNew,
        SchemaCacheMaxCostBytes: 16 << 20,
    })
    if err != nil {
        log.Fatal(err)
    }
    defer perms.Close()
  6. Understand PostgreSQL datastore MVCC and snapshot queries

    main

    Because standard PostgreSQL does not allow reading dirty data without extensions, the SpiceDB PostgreSQL datastore driver implements a second layer of MVCC (Multi-Version Concurrency Control).

    This implementation manually controls all writes to the database, allowing SpiceDB to:

    1. Explicitly track all database revisions.
    2. Perform point-in-time snapshot queries.
  7. Understand the SpiceDB Query Package architecture

    main

    The query package implements SpiceDB's query plan system for evaluating permissions and relationships using a tree-based iterator architecture. Query plans are built from schema definitions and are used to answer three fundamental questions:

    1. Check: Does a specific subject have access to a resource?
    2. IterSubjects: Which subjects have access to a given resource?
    3. IterResources: Which resources can a given subject access?

    Complex permission queries are evaluated by composing simple operations through a tree of iterators.

  8. Understand the New Enemy problem in SpiceDB on CockroachDB

    main

    The 'New Enemy' problem is a consistency issue that can occur when using SpiceDB with CockroachDB. It happens when a client observes an exclude write followed by a direct write, requests a check using the revision from the direct write, but is still granted access because the direct write's timestamp is lower than the exclude write's timestamp.

    This occurs because CockroachDB does not provide the same external consistency guarantees as Google Spanner's TrueTime. The problem is most likely to occur when:

    1. Writes land in different ranges.
    2. The leader of the second write's range is not on the same node as any follower of the first write's range.
    3. Writes are received by different nodes, one of which has a slower clock.

    This issue is specifically relevant when the keys being written do not overlap.

  9. Query the Permissions table using different patterns

    main

    The Permissions table handler maps SQL SELECT queries to specific SpiceDB API calls based on the fields provided in the WHERE clause. Use these patterns to trigger the desired SpiceDB behavior:

    1. CheckPermission: Provide all fields (resource_type, resource_id, permission, subject_type, and subject_id).
    2. LookupResources: Omit resource_id to find all resources that satisfy a permission for a specific subject.
    3. LookupSubjects: Omit subject_id to find all subjects that have a specific permission on a resource.
    -- 1. CheckPermission pattern
    SELECT has_permission FROM permissions
    WHERE resource_type = 'doc' AND resource_id = '1'
      AND permission = 'view'
      AND subject_type = 'user' AND subject_id = 'alice';
    
    -- 2. LookupResources pattern
    SELECT resource_id FROM permissions
    WHERE resource_type = 'doc' AND permission = 'view'
      AND subject_type = 'user' AND subject_id = 'alice'
      AND has_permission = true;
    
    -- 3. LookupSubjects pattern
    SELECT subject_id FROM permissions
    WHERE resource_type = 'doc' AND resource_id = '1'
      AND permission = 'view'
      AND subject_type = 'user'
      AND has_permission = true;
  10. Disable SpiceDB Telemetry

    main
    SpiceDB automatically reports metrics to telemetry.authzed.com hourly using the Prometheus Remote Write protocol. To prevent SpiceDB from sending these metrics, start the binary with the --telemetry-endpoint="" flag.
  11. Provide caveat context in embedded checks

    main

    In the embedded package, caveat context is supplied directly as a map[string]any. The engine consumes these values without conversion.

    Type Handling:

    • For most types, use their natural Go representation.
    • For caveat parameters typed as bytes, the value must be a base64-encoded string (the caveat type system handles the decoding).