server

package
v0.70.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 6, 2026 License: MIT Imports: 19 Imported by: 0

Documentation

Overview

Package server implements the gRPC RegistryService.

The server is the public entry point to a running protoregistry. It validates and rate-limits incoming requests, applies the configured Authenticator (defaulting to NoAuth), gates privileged operations (writes to the __builtins__ namespace, Publish with Force=true) on Identity.Admin, and sanitizes errors so that backend implementation detail (raw PostgreSQL errors, unwrapped wrap chains) does not leak to clients.

Index

Constants

This section is empty.

Variables

View Source
var AnonymousIdentity = Identity{Subject: "anonymous", Admin: false}

AnonymousIdentity is the placeholder returned by NoAuth and used when no authentication metadata accompanies a request.

Functions

func ParseTokenFile

func ParseTokenFile(r io.Reader) (map[string]Identity, error)

ParseTokenFile reads the TokenAuth file format described on the TokenAuth type. It returns the parsed token map suitable for NewTokenAuth.

func UnaryAuthInterceptor

func UnaryAuthInterceptor(a Authenticator) grpc.UnaryServerInterceptor

UnaryAuthInterceptor returns a grpc.UnaryServerInterceptor that runs the configured Authenticator and stashes the resulting Identity on the request context. Handlers retrieve it via IdentityFromContext.

Types

type Authenticator

type Authenticator interface {
	Authenticate(ctx context.Context, fullMethod string) (Identity, error)
}

Authenticator extracts an Identity from incoming RPC metadata. Implementations may consult bearer tokens, mTLS client certs, JWT claims, or any other transport-supplied data.

Returning a non-nil error rejects the RPC; the error should be a gRPC status (e.g. codes.Unauthenticated) so the caller sees a meaningful failure rather than codes.Internal.

type Identity

type Identity struct {
	Subject string
	Admin   bool
}

Identity is the authenticated principal behind an RPC. It is attached to the request context by the auth interceptor; handlers retrieve it via IdentityFromContext.

Subject is the human/service name (used in audit logs). Admin grants the bearer the ability to perform privileged operations: writes to the __builtins__ namespace, Publish with Force=true, and (in a future patch) rollbacks that bypass dependent compat checks.

func IdentityFromContext

func IdentityFromContext(ctx context.Context) Identity

IdentityFromContext returns the Identity attached by the auth interceptor, or AnonymousIdentity if none is present.

type Limits

type Limits struct {
	// MaxIDLength is the maximum length, in bytes, of a namespace ID,
	// schema ID, or token cursor. Applied to user-supplied identifiers only.
	MaxIDLength int

	// MaxFilenameLength is the maximum length, in bytes, of a source
	// filename inside a Publish request.
	MaxFilenameLength int

	// MaxSourcesPerRequest caps the number of source files in a single
	// Publish request. Each file allocates AST nodes during normalization,
	// so this cap bounds compile-time memory.
	MaxSourcesPerRequest int

	// MaxTotalSourceBytes caps the sum of all source file sizes in a
	// single Publish request.
	MaxTotalSourceBytes int64

	// MaxFileSourceBytes caps the size of any individual source file.
	MaxFileSourceBytes int64

	// DefaultListPageSize is used when a List* RPC sends page_size = 0.
	DefaultListPageSize int

	// MaxListPageSize is the upper bound the server will honour even if a
	// caller asks for more.
	MaxListPageSize int
}

Limits caps the size and shape of incoming RPC payloads. Every limit is expressed in user units (bytes, count, length) so operators can reason about them directly. Limits are enforced at the RPC boundary before any expensive work (compilation, blob storage, descriptor materialization) happens — they are the first line of defence against DoS via crafted inputs.

The compile-time wall-clock cap lives on the compiler (see compiler.WithTimeout). It is enforced where the cost is paid, and so applies whether the compiler is invoked from the server, a CLI command, or an embedded library caller.

func DefaultLimits

func DefaultLimits() Limits

DefaultLimits returns the default Limits used when the server is constructed without WithLimits. The numbers are chosen to be permissive enough for normal use (multi-megabyte schemas, hundreds of files) while still bounding worst-case server memory.

type NoAuth

type NoAuth struct{}

NoAuth permits every request, returning AnonymousIdentity. It is the default when the server is constructed without WithAuth and is intended for local development and trusted-network deployments. Combined with AllowAnonymousWrites=false it allows reads but rejects writes; combined with AllowAnonymousWrites=true (the back-compat default) it preserves the pre-auth-seam behaviour and emits a startup warning instead.

func (NoAuth) Authenticate

func (NoAuth) Authenticate(_ context.Context, _ string) (Identity, error)

Authenticate always succeeds with AnonymousIdentity.

type Option

type Option func(*Options)

Option mutates an Options. Apply via New(reg, store, WithAuth(...), ...).

func WithAllowAnonymousWrites

func WithAllowAnonymousWrites(allow bool) Option

WithAllowAnonymousWrites controls whether anonymous callers may invoke write RPCs. The default is true; pass false to require authentication for any state-mutating call.

func WithAuth

func WithAuth(a Authenticator) Option

WithAuth installs an Authenticator. The Authenticator's result is available on the request context via IdentityFromContext.

func WithLimits

func WithLimits(l Limits) Option

WithLimits replaces the default Limits.

func WithLogger

func WithLogger(l *slog.Logger) Option

WithLogger replaces the default slog.Logger used for audit lines.

type Options

type Options struct {
	// Limits caps incoming RPC payload sizes. Defaults to DefaultLimits().
	Limits Limits

	// Auth runs on every RPC and produces the Identity on the request
	// context. Defaults to NoAuth (anonymous, non-admin).
	Auth Authenticator

	// Logger receives audit and warning lines. Defaults to slog.Default().
	Logger *slog.Logger

	// AllowAnonymousWrites controls whether write RPCs (Publish, Promote,
	// Rollback, DiscardStaging, CreateNamespace) accept callers whose
	// Identity is AnonymousIdentity. Defaults to true to preserve the
	// pre-auth-seam behaviour; operators who want to lock the server down
	// should set this to false and configure WithAuth.
	AllowAnonymousWrites bool
}

Options configures a Server. Use the With* helpers rather than mutating directly; the zero Options is not a valid configuration.

func DefaultOptions

func DefaultOptions() Options

DefaultOptions returns the Options used when no With* options are passed to New. The defaults are permissive enough to keep existing local-dev setups working (anonymous reads, anonymous writes, no auth) but the server emits a startup warning in this configuration so the operator knows it is unprotected.

type Server

type Server struct {
	registrypb.UnimplementedRegistryServiceServer
	// contains filtered or unexported fields
}

Server implements the RegistryService gRPC server.

func New

func New(registry *protoregistry.Registry, st store.Store, opts ...Option) *Server

New creates a new gRPC server backed by the given registry and store. The variadic options replace fields on DefaultOptions.

func (*Server) GetSchema

func (*Server) GetSource

func (*Server) Promote

func (*Server) Publish

func (*Server) Rollback

type TokenAuth

type TokenAuth struct {
	// contains filtered or unexported fields
}

TokenAuth authenticates bearer tokens against a static map loaded from a file or constructed in code. Tokens are presented in the standard `authorization: Bearer <token>` metadata header.

File format (one entry per line, tab-separated; `#` starts a comment):

# token        subject  role
abc123def456   alice    admin
0123456789ab   ci-bot   user

`role` is `admin` or `user` (default `user`). Tokens with role `admin` receive Identity.Admin = true.

func NewTokenAuth

func NewTokenAuth(tokens map[string]Identity) *TokenAuth

NewTokenAuth constructs a TokenAuth over the given token→identity map. Callers wanting a file loader should use ParseTokenFile.

func (*TokenAuth) Authenticate

func (t *TokenAuth) Authenticate(ctx context.Context, _ string) (Identity, error)

Authenticate looks up the bearer token in the configured map. Missing, malformed, or unknown tokens produce codes.Unauthenticated.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL