server

package
v0.41.0 Latest Latest
Warning

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

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

Documentation

Overview

Package server provides a batteries-included gRPC server builder for Infoblox services. It assembles the framework interceptor chain (request-ID, error mapping, tenant-ID, fail-closed authz, field-mask validation, ETag preconditions, read-mask response shaping) and, optionally, an HTTP/JSON gateway in front of the gRPC endpoint.

Index

Constants

View Source
const DefaultGRPCAddr = ":9090"

DefaultGRPCAddr is the default listen address for the gRPC endpoint.

Variables

This section is empty.

Functions

func AssertAggregateBoundaries added in v0.19.0

func AssertAggregateBoundaries(methods []string, members []MemberBinding) error

AssertAggregateBoundaries returns an error if any aggregate MEMBER resource registers a write-capable standard method on the transport surface. methods is the full set of registered gRPC FullMethods (as recorded by RecordMethods); members is the accumulated set of member→root bindings. It is a pure function over (methods, members) so it can be unit-tested directly, and it is run at Serve beside the authz completeness gate (fail-closed, default-deny: a member resource cannot independently mutate — writes route through the root).

Reads (Get/List) are intentionally NOT considered: addressability is not write authority, and a read-only projection of a member is not a member write. Only the WriteMethods recorded on each binding are checked.

Types

type Config

type Config struct {
	// GRPCAddr is the TCP address to listen on (e.g. ":9090" or ":0"). Required.
	GRPCAddr string
	// HTTPAddr is the optional gateway address (e.g. ":8080"). Empty disables
	// the HTTP gateway.
	HTTPAddr string
	// Rules are the declared authz rules; they feed both grpcauthz (enforcement)
	// and the field-mask interceptor (verb lookup).
	Rules []authz.MethodRule
	// Authorizer is the pluggable decision point. Defaults to
	// authz.NewDevAuthorizer(nil) if nil.
	Authorizer authz.Authorizer
	// PrincipalFunc derives the authenticated authz.Principal from each request's
	// context. When nil the principal is empty, so — with a default-deny
	// Authorizer — every non-public method is denied (fail closed). For local
	// development set grpcauthz.DevPrincipalFunc() to derive the principal from
	// request metadata; in production supply one backed by a verified token.
	PrincipalFunc grpcauthz.PrincipalFunc
	// FeatureSource, when set, makes the gate entitlement-aware (P12): server.New
	// wraps Authorizer with authz.WithEntitlement so the SAME decision enforces
	// both a method's permission AND its declared entitlement Features
	// (MethodRule.Features). Dev default is authz.StaticFeatures; production binds
	// the licensing/entitlement service (the OPA sidecar already returns the
	// combined decision, so it is wired here as the Authorizer and NOT wrapped).
	// Nil = permission-only authz (unchanged).
	FeatureSource authz.FeatureSource
	// AlertSink receives alerts when a method declared authz.ModeAlert fails its
	// policy decision but is allowed through (P12 observation mode). Defaults to a
	// structured-log sink on Logger.
	AlertSink authz.AlertSink
	// UsageMeter, when set, enforces declared per-method quotas (MethodRule.Quota,
	// P13) with a reserve→commit/release lifecycle around the handler — separate
	// from the authz decision, running just after authz so the principal/tenant is
	// established. Dev default is quota.NewMemoryMeter; production binds the
	// token-allocation/usage service. Nil = no quota enforcement.
	UsageMeter quota.Meter
	// Interceptors are additional unary interceptors appended after the
	// framework chain. They run post-handler too (an interceptor may observe or
	// wrap the response), so a gRPC-side cross-cutting extension (e.g. an audit
	// hook) wires in here — the way an Authorizer wires into Authorizer.
	Interceptors []grpc.UnaryServerInterceptor
	// HTTPMiddleware are net/http middlewares wrapping the REST gateway mux (the
	// P2 HTTP extension seam). They wrap only the gateway routes — never the
	// /healthz and /readyz probes — and run inside the SDK's tracing span;
	// HTTPMiddleware[0] is the outermost wrapper. A REST request still traverses
	// the full gRPC interceptor chain on the in-process hop, so these compose
	// with (do not bypass) the gRPC stages. Used by an internal extension exactly
	// as Interceptors is — e.g. an audit/identity HTTP middleware shipped in
	// devedge-sdk-internal.
	HTTPMiddleware []func(http.Handler) http.Handler
	// DeduplicationStore is the idempotency store for DeduplicateUnary. Defaults to MemoryDeduplicationStore (10-minute TTL) when nil.
	DeduplicationStore middleware.DeduplicationStore
	// LROStore is the operation store for long-running operations (AIP-151).
	// Defaults to lro.NewMemoryStore(1h) when nil.
	LROStore lro.Store
	// Logger is the structured logger the default chain's middleware.LoggingUnary
	// writes one record per RPC to (trace-correlated, secret-redacted payloads at
	// Debug). Defaults to slog.Default() when nil.
	Logger *slog.Logger
	// ReadinessChecks is the list of readiness checks the server runs on every
	// /readyz probe and whenever it drives the gRPC health status. An empty slice
	// means "always ready" (the default). Each check is bounded by a 2s timeout;
	// a single failure flips /readyz to 503 and the gRPC overall status to
	// NOT_SERVING. Liveness (/healthz, gRPC health Check on "") is always
	// process-up only — deps never go in the liveness check.
	ReadinessChecks []sdkhealth.Check
	// Resilience configures optional resilience policy interceptors inserted into
	// the default chain. server.New applies a 30-second request timeout when the
	// zero value is supplied; rate limiting and circuit breaking are opt-in (nil).
	Resilience ResilienceConfig
}

Config carries the options for constructing a Server.

type MemberBinding added in v0.19.0

type MemberBinding struct {
	// Resource is the member resource's Go type name (e.g. "Item").
	Resource string
	// Root is the owning aggregate root's message name (e.g. "Order").
	Root string
	// WriteMethods are the gRPC FullMethod names of the write-capable standard
	// methods this member service registers (e.g.
	// "/order.v1.ItemService/CreateItem"). A non-empty intersection with the
	// registered method set is the boundary violation the gate fails on.
	WriteMethods []string
}

MemberBinding records that a service's resource is a DDD aggregate MEMBER owned by Root, together with the write-capable standard methods (Create/Update/ Delete/Undelete/Batch*) the service registers on the transport surface. The generated Register<Svc> contributes one MemberBinding per member service (via Server.RecordMemberBinding); the boot-time boundary gate AssertAggregateBoundaries reads the accumulated set at Serve.

A member resource is addressable for READS (Get/List) but written THROUGH its root, so a registered member write is a boundary violation that fails closed — mirroring the authz completeness gate (an undeclared method is denied).

type ResilienceConfig added in v0.25.0

type ResilienceConfig struct {
	// RequestTimeout bounds every unary handler invocation. server.New defaults
	// to 30s when this field is zero; set to resilience.NoTimeout to explicitly
	// disable the timeout. Per-method overrides (PerMethodTimeout) take
	// precedence; a per-method value of resilience.NoTimeout disables that
	// method's timeout regardless of RequestTimeout.
	//
	// A handler that exceeds the deadline receives codes.DeadlineExceeded.
	// Handlers should honour ctx.Done() for clean early exit.
	RequestTimeout time.Duration
	// PerMethodTimeout overrides RequestTimeout for specific gRPC full-method
	// names (e.g. "/mypackage.MyService/LongOp": 5*time.Minute). Set a method's
	// value to resilience.NoTimeout to disable the timeout for that method only.
	PerMethodTimeout map[string]time.Duration
	// RateLimiter, when non-nil, is inserted right after TenantIDUnary (before
	// authz) to shed excess load early with codes.ResourceExhausted. Default
	// nil = off. Use resilience.NewTokenBucket or supply your own implementation.
	RateLimiter resilience.RateLimiter
	// CircuitBreaker, when non-nil, wraps handler invocations just inside the
	// framework chain. Default nil = off. Plug in sony/gobreaker,
	// afex/hystrix-go, or any resilience.CircuitBreaker implementation.
	CircuitBreaker resilience.CircuitBreaker
}

ResilienceConfig holds the resilience policy settings for the server's default interceptor chain.

type Server

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

Server is the assembled gRPC server (plus optional HTTP gateway).

func New

func New(cfg Config) (*Server, error)

New validates cfg and constructs a Server. It builds the framework interceptor chain and wires the authz rules into both the authorizer and the field-mask validator. Returns an error if any required field is missing.

func (*Server) AddReadinessCheck added in v0.28.0

func (s *Server) AddReadinessCheck(checks ...sdkhealth.Check)

AddReadinessCheck appends a readiness check to the server's accumulated set (Config.ReadinessChecks seeds it). The /readyz endpoint and the gRPC health loop read the live set on every probe, so a check contributed after New — e.g. by a servicekit module's HealthRegistry during composed-host registration — is aggregated like any configured check. Call before Serve.

func (*Server) AddRules added in v0.18.0

func (s *Server) AddRules(rules ...authz.MethodRule)

AddRules appends authz rules to the server's accumulated set. The generated Register<Svc>/Register<Svc>WithRepository call it with the service's <Svc>AuthzRules so the developer never hand-assembles Config.Rules. The authz and field-mask interceptors read the live set, and the boot-time completeness gate runs over it at Serve. Call before Serve.

func (*Server) GRPCAddr

func (s *Server) GRPCAddr() string

GRPCAddr returns the actual bound gRPC address once Serve has started (useful when GRPCAddr was ":0"); before that it returns the configured address.

func (*Server) GRPCServer

func (s *Server) GRPCServer() *grpc.Server

GRPCServer returns the underlying *grpc.Server so callers can register their service implementations on it.

func (*Server) GatewayMux

func (s *Server) GatewayMux() *runtime.ServeMux

GatewayMux returns the HTTP gateway mux, or nil when no HTTP gateway is configured.

func (*Server) HTTPAddr

func (s *Server) HTTPAddr() string

HTTPAddr returns the actual bound HTTP gateway address once Serve has started (useful when HTTPAddr was ":0"); before that it returns the configured address. Returns "" when no HTTP gateway is configured.

func (*Server) LROStore

func (s *Server) LROStore() lro.Store

LROStore returns the long-running operation store this server was configured with.

func (*Server) MemberBindings added in v0.19.0

func (s *Server) MemberBindings() []MemberBinding

MemberBindings returns the accumulated DDD aggregate member→root bindings.

func (*Server) RecordMemberBinding added in v0.19.0

func (s *Server) RecordMemberBinding(b MemberBinding)

RecordMemberBinding records that a service's resource is a DDD aggregate MEMBER owned by a root (with the write methods it registers). The generated Register<Svc> of a member service calls it; the boundary gate AssertAggregateBoundaries runs over the accumulated set at Serve (fail-closed: a member that registers a write method does not serve). Call before Serve.

func (*Server) RecordMethods added in v0.18.0

func (s *Server) RecordMethods(methods ...string)

RecordMethods records gRPC FullMethods registered with the server so the completeness gate at Serve can verify each has a rule or a public exemption. The generated Register<Svc> calls it with the service's method names.

func (*Server) RegisterGateway

func (s *Server) RegisterGateway(fn func(context.Context, *runtime.ServeMux, *grpc.ClientConn) error)

RegisterGateway records a gateway registration function to be invoked against the gateway mux and the in-process gRPC connection when Serve starts. It is a no-op at runtime unless an HTTP gateway is configured.

func (*Server) Rules

func (s *Server) Rules() []authz.MethodRule

Rules returns the accumulated authz rule set: Config.Rules plus everything contributed via AddRules (e.g. by the generated Register<Svc>).

func (*Server) Serve

func (s *Server) Serve(ctx context.Context) error

Serve starts the gRPC server (and the HTTP gateway when configured) and blocks until ctx is cancelled, after which it shuts both down gracefully. It returns the first fatal error from either server, or nil on clean shutdown.

Jump to

Keyboard shortcuts

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