devsvc

package
v0.64.0 Latest Latest
Warning

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

Go to latest
Published: Jul 11, 2026 License: Apache-2.0 Imports: 12 Imported by: 0

Documentation

Overview

Package devsvc is the out-of-process, hot-reloadable sibling of the in-process authz.DevAuthorizer (WS-026 P1b): the dev-manipulable OSS reference behind the authz.Authorizer seam. It ships both halves of one wire protocol:

  • Client implements authz.Authorizer by calling a running dev authz service over HTTP — the same seam opaauthz (OPA/PARGS) implements for production, so a service swaps dev↔prod with no code change (server.Config.Authorizer).
  • [Handler] serves that protocol from a Store of readable authz.Grants, reusing authz.DevAuthorizer for the decision. The store is HOT-RELOADABLE (edit grants on disk and reload, or PUT them via the admin endpoint) so a developer flips a decision live — "make this method allowed/denied" — with no rebuild or restart.

It is dependency-light (stdlib + authz only) and lives in the root module. Production authz stays OPA/PARGS — this is the dev default, not a policy engine.

Index

Constants

View Source
const DefaultAuthorizePath = "/v1/authorize"

DefaultAuthorizePath is the decision endpoint the Client posts to and the Handler serves.

Variables

This section is empty.

Functions

func LoadGrantsFile

func LoadGrantsFile(path string) ([]authz.Grant, error)

LoadGrantsFile reads a YAML (or JSON — YAML is a superset) list of authz.Grant from path. It is the on-disk form a developer edits to manipulate dev authorization; YAML is the friendlier hand-edited default.

Example grants.yaml:

  • tenant: tenant-a subjects: [group:admin] verbs: ["*"] resource: "*"
  • tenant: "*" subjects: [group:viewer] verbs: [get, list] resource: order

The keys are lowercase snake_case (see authz.Grant's struct tags) and are identical whether the file is written as YAML or JSON.

func NewHandler

func NewHandler(store *Store, opts ...HandlerOptions) http.Handler

NewHandler serves the dev authz protocol from store. POST <AuthorizePath> decides one request; when EnableAdmin, PUT <AdminPath> replaces the grants (body: JSON array of authz.Grant) so a developer flips decisions live.

func WatchGrantsFile

func WatchGrantsFile(ctx context.Context, path string, store *Store, interval time.Duration, onErr func(error)) error

WatchGrantsFile reloads store from path whenever the file's modification time changes, polling every interval (zero-dependency hot-reload — no fsnotify). It loads once immediately, then runs until ctx is cancelled. A load error after the initial load is passed to onErr (if non-nil) and the last-good grants are kept — a bad edit never takes the service down. Returns the initial load error so a caller can fail fast on a broken file at startup.

Types

type Client

type Client struct {
	// BaseURL is the dev authz service root (e.g. "http://127.0.0.1:8090").
	BaseURL string
	// AuthorizePath overrides DefaultAuthorizePath.
	AuthorizePath string
	// HTTP is the client used; nil defaults to http.DefaultClient.
	HTTP *http.Client
}

Client is an authz.Authorizer that decides by calling a running dev authz service. It is the dev-time stand-in for opaauthz: the same seam, a different backend. Fail-closed: any transport/decode error denies.

func (*Client) Authorize

func (c *Client) Authorize(ctx context.Context, req authz.AccessRequest) (authz.Decision, error)

Authorize implements authz.Authorizer.

type HandlerOptions

type HandlerOptions struct {
	// AuthorizePath overrides DefaultAuthorizePath.
	AuthorizePath string
	// EnableAdmin mounts a PUT <AuthorizePath>/../grants endpoint that replaces the
	// grant set live (dev-manipulability via API). Off by default — the endpoint is
	// unauthenticated and dev-only.
	EnableAdmin bool
	// AdminPath overrides the admin grants endpoint path (default "/v1/grants").
	AdminPath string
}

HandlerOptions configures NewHandler.

type Store

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

Store holds the dev authz service's readable authz.Grants behind the decision engine, swappable atomically for hot-reload. Safe for concurrent use.

func NewStore

func NewStore(grants ...authz.Grant) *Store

NewStore returns a store seeded with grants.

func (*Store) Authorize

func (s *Store) Authorize(ctx context.Context, req authz.AccessRequest) (authz.Decision, error)

Authorize applies the current grants (implements authz.Authorizer too, so the Store is usable in-process as well as behind the Handler).

func (*Store) Grants

func (s *Store) Grants() []authz.Grant

Grants returns a copy of the currently installed grants.

func (*Store) Replace

func (s *Store) Replace(grants ...authz.Grant)

Replace swaps the whole grant set atomically — the hot-reload primitive. A concurrent Authorize sees either the old or the new set, never a torn one.

Jump to

Keyboard shortcuts

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