Help us shape the future of Go! Take the 2026 Go Developer Survey

controlplane

package
v0.1.1 Latest Latest
Warning

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

Go to latest
Published: Oct 18, 2026 License: Apache-2.0 Imports: 54 Imported by: 0

Documentation

Index

Constants

View Source
const (
	// STSRateLimitDefault sizes per-node STS throughput for workload JWT
	// rotation and egress border JWT minting.
	STSRateLimitDefault = 100
	// STSRateBurstDefault sizes per-node STS burst capacity.
	STSRateBurstDefault = 200
	// DefaultWorkloadSessionTTL is the default session TTL for workload OIDC
	// issuers (48h, twice BiscuitTokenTTL so a single missed refresh does not
	// sever the node).
	DefaultWorkloadSessionTTL = 48 * time.Hour
)
View Source
const (
	// DefaultNodeRetention keeps a lapsed enrollment for a month past its
	// session, and a bootstrap enrollment for a month past its last refresh,
	// long enough to be looked up when investigating an incident, and is
	// what --node-retention defaults to.
	DefaultNodeRetention = 30 * 24 * time.Hour

	// DefaultEphemeralNodeRetention is how long a member an ephemeral token
	// enrolled is kept after its last refresh: an hour, long past the few
	// minutes a member of a fleet, a probe or a CI job stays, and what
	// --ephemeral-node-retention defaults to.
	DefaultEphemeralNodeRetention = time.Hour
)
View Source
const (
	EnrollRateLimit        = 10
	EnrollBurst            = 20
	JWTVerificationTimeout = 10 * time.Second
)
View Source
const DefaultMeshReconnectInterval = 30 * time.Second

DefaultMeshReconnectInterval is how often the publisher re-reads the lease table; a router that just enrolled waits at most this long for events. It is one query and at most a few dials per tick, so it is kept short.

View Source
const RouterDialTimeout = 10 * time.Second

RouterDialTimeout bounds each attempt to reach a leased router.

Variables

This section is empty.

Functions

func SetNodeBan

func SetNodeBan(ctx context.Context, store storage.Store, node *storage.EnrolledNode, banned bool) error

SetNodeBan bans or unbans a node and, when its record carries OIDC claims, the identity behind it. The one place both halves are toggled together, for the HTTP handlers and the CLI alike: a ban that names only the peer id is shed with a new keypair, and an unban that lifts only the peer id leaves the human locked out of /register.

func ValidatePolicyConfig

func ValidatePolicyConfig(req *api.PolicyConfig) error

ValidatePolicyConfig checks a mesh policy the way POST /policies does; any other writer of the policy (e.g. a seed file) must run it too.

Types

type IssuerFlags added in v0.1.1

type IssuerFlags struct {
	Login    []string
	Workload []string
}

IssuerFlags are the OIDC issuer settings a control plane binary takes on its command line. Both flags accumulate: given twice, or once with a comma-separated value, every issuer counts. A repeated flag that replaced the previous value dropped an issuer silently, and every member of the platform behind the dropped one was refused with "unknown issuer".

func (*IssuerFlags) Empty added in v0.1.1

func (f *IssuerFlags) Empty() bool

Empty reports whether no issuer of either kind was given.

func (*IssuerFlags) OIDCIssuer added in v0.1.1

func (f *IssuerFlags) OIDCIssuer() string

OIDCIssuer is the value for Options.OIDCIssuer.

func (*IssuerFlags) Register added in v0.1.1

func (f *IssuerFlags) Register(fs *pflag.FlagSet, optional string)

Register adds --issuer and --workload-issuer to fs. optional names what an empty value means in the help text ("Optional " for agentmesh-one, "" for the control plane, where one of the two is required).

func (*IssuerFlags) WorkloadIssuer added in v0.1.1

func (f *IssuerFlags) WorkloadIssuer() string

WorkloadIssuer is the value for Options.WorkloadIssuer.

type JSONWebKey

type JSONWebKey struct {
	Kty string `json:"kty"`
	Crv string `json:"crv"`
	Use string `json:"use"`
	Alg string `json:"alg"`
	Kid string `json:"kid"`
	X   string `json:"x"`
	Y   string `json:"y"`
}

JSONWebKey represents a single public key in an RFC 7517 JSON Web Key Set.

type JSONWebKeySet

type JSONWebKeySet struct {
	Keys []JSONWebKey `json:"keys"`
}

JSONWebKeySet represents an RFC 7517 JSON Web Key Set served at GET /jwks.

type LocalES256Signer

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

LocalES256Signer is the default OIDCSigner using P-256 (ES256) keys with overlap grace-period support and optional SQLStore persistence.

func NewLocalES256SignerWithStore

func NewLocalES256SignerWithStore(store storage.Store) (*LocalES256Signer, error)

NewLocalES256SignerWithStore creates a LocalES256Signer backed by store when non-nil.

func (*LocalES256Signer) JWKS

JWKS returns the active public key plus any retired keys still within their overlap grace window.

func (*LocalES256Signer) Rotate

func (s *LocalES256Signer) Rotate(gracePeriod time.Duration) (string, error)

Rotate generates a new active ES256 signing key and retains the previous key in JWKS for gracePeriod so in-flight border JWTs remain verifiable.

func (*LocalES256Signer) SignJWT

func (s *LocalES256Signer) SignJWT(ctx context.Context, claims jwt.MapClaims) (string, error)

SignJWT signs claims with the active ES256 key and sets the "kid" header.

type MeshAdapter

type MeshAdapter interface {
	// PublishEvent constructs, signs, and broadcasts a Control Plane MeshEvent (POLICY_UPDATE, BANNED, KEY_ROTATION).
	PublishEvent(ctx context.Context, eventType api.MeshEvent_Type, peerID string, payload []byte) error

	// DiscoverServices queries active mesh nodes/DHT for services matching a type or pattern.
	DiscoverServices(ctx context.Context, serviceType string) ([]*ServiceAnnouncement, error)

	// GetNodeStatus retrieves node reachability and status from the mesh.
	GetNodeStatus(ctx context.Context, peerID string) (*NodeStatus, error)

	// Close gracefully releases any P2P host resources, streams, and PubSub topics.
	Close() error
}

MeshAdapter defines the generic interface for Control Plane operations interacting with the Agent Mesh.

type NodeStatus

type NodeStatus struct {
	PeerID      string
	IsReachable bool
	Addresses   []string
	LastSeen    time.Time
}

NodeStatus represents mesh status information for a peer.

type NopMeshAdapter

type NopMeshAdapter struct{}

NopMeshAdapter provides a no-op implementation used when P2P mesh integration is disabled or in unit tests.

func NewNopMeshAdapter

func NewNopMeshAdapter() *NopMeshAdapter

func (*NopMeshAdapter) Close

func (n *NopMeshAdapter) Close() error

func (*NopMeshAdapter) DiscoverServices

func (n *NopMeshAdapter) DiscoverServices(ctx context.Context, serviceType string) ([]*ServiceAnnouncement, error)

func (*NopMeshAdapter) GetNodeStatus

func (n *NopMeshAdapter) GetNodeStatus(ctx context.Context, peerID string) (*NodeStatus, error)

func (*NopMeshAdapter) PublishEvent

func (n *NopMeshAdapter) PublishEvent(ctx context.Context, eventType api.MeshEvent_Type, peerID string, payload []byte) error

type OIDCSigner

type OIDCSigner interface {
	SignJWT(ctx context.Context, claims jwt.MapClaims) (string, error)
	JWKS(ctx context.Context) (*JSONWebKeySet, error)
}

OIDCSigner signs outbound ES256 border JWTs at POST /sts/token and publishes the corresponding public keys at GET /jwks.

type Options

type Options struct {
	ListenAddr     string
	DriverName     string
	DataSourceName string
	OIDCIssuer     string
	// WorkloadIssuer is a comma-separated list of OIDC issuers (subset of or
	// addition to OIDCIssuer) that issue machine/workload tokens rather than
	// human user tokens. Tokens from a workload issuer are accepted at
	// /register, /refresh, and /token/exchange, and refused at /user/* and
	// /oauth/authorize.
	WorkloadIssuer      string
	OIDCClientID        string // OAuth client id advertised via /info; defaults to the first allowed audience
	AllowedAudiences    []string
	LeaseDuration       time.Duration
	KeyRotationInterval time.Duration
	KeyGracePeriod      time.Duration
	// SigningKeyPath names a PEM file with the control plane's private
	// signing keys (PKCS#8 or SEC 1): Ed25519 for Biscuits, P-256 for the
	// ES256 JWTs. For each kind the first key signs and later keys only
	// verify. When set, the operator owns rotation: the control plane
	// installs these keys through its normal rotation path at start-up and
	// never rotates on its own.
	SigningKeyPath string
	// DHTReplication and DHTReprovideInterval are the mesh's directory
	// parameters, published on /info for every member and router
	// (api.DirectoryParameters); 0 is the api default of each.
	DHTReplication        int
	DHTReprovideInterval  time.Duration
	InsecureSkipTLSVerify bool
	BiscuitTimeout        time.Duration
	BiscuitTTL            time.Duration // Lifespan minted into every issued Biscuit's expiration() fact; defaults to api.BiscuitTokenTTL
	OIDCSessionTTL        time.Duration // How long an OIDC enrollment stays refreshable before the identity must re-authenticate interactively; defaults to api.OIDCSessionTTL
	WorkloadSessionTTL    time.Duration // Session TTL for enrollments from a WorkloadIssuer; defaults to DefaultWorkloadSessionTTL (48h)
	// NodeRetention is how long an enrolled node's row is kept after its
	// session expired, or, for a bootstrap enrollment, after its last
	// refresh, before being deleted; unset is DefaultNodeRetention, and
	// Validate refuses a negative value. Every pod restart without a
	// persistent data dir enrolls a fresh identity, so without a bound the
	// nodes table only ever grows.
	NodeRetention time.Duration
	// EphemeralNodeRetention is NodeRetention for a member an ephemeral
	// bootstrap token enrolled; unset is DefaultEphemeralNodeRetention.
	EphemeralNodeRetention time.Duration
	AdminToken             string // Optional: administrative bearer token for protecting policy and enrollment queue REST APIs
	AutoApproveEnrollment  bool   // If true, valid bootstrap token enrollment requests are immediately approved without administrative manual gate
	// STSIssuerURL is the public issuer URL advertised in
	// /.well-known/openid-configuration and minted as the "iss" claim in
	// outbound /sts/token JWTs. If empty, derived from the incoming HTTP request.
	STSIssuerURL string
	// DelegatedBiscuitTTL bounds the lifespan of Delegated Session Biscuits
	// minted by POST /token/exchange and OAuth 2.1 flows (defaults to 1h).
	DelegatedBiscuitTTL time.Duration
	// STSTokenTTL is the default lifespan of short-lived ES256 border JWTs
	// minted by POST /sts/token (defaults to 5m, capped at 15m).
	STSTokenTTL time.Duration
	// OIDCSigner signs outbound border JWTs and serves /jwks. If nil, a
	// LocalES256Signer is initialized automatically.
	OIDCSigner OIDCSigner
	// STSRateLimit is the per-node request rate limit (requests/second) for
	// /token/exchange and /sts/token (defaults to STSRateLimitDefault).
	STSRateLimit float64
	// STSRateBurst is the per-node burst size for /token/exchange and
	// /sts/token (defaults to STSRateBurstDefault).
	STSRateBurst int
	// TrustForwardedHeaders controls whether oidcIssuerURL trusts X-Forwarded-Proto
	// when STSIssuerURL is not explicitly configured.
	TrustForwardedHeaders bool
}

Options holds configuration for the control plane.

func (*Options) Default

func (o *Options) Default()

Default sets default values for control plane options.

func (*Options) Validate

func (o *Options) Validate() error

Validate ensures options are valid.

type P2PMeshAdapter

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

P2PMeshAdapter publishes control plane events on the mesh's gossip topic.

It is the control plane's whole presence on the mesh, and it is one-way: events go out so a ban, a key rotation or a policy change reaches routers and nodes the moment it happens, and nothing is read back. Every consumer still pulls /keys, /info and /policies on its own schedule, so a missed event is a delay, never a divergence. Where the adapter runs on a host of its own (NewMeshPublisher) that host has no listen address, no DHT, no relay and no stream handlers: it can dial routers and nothing can dial it.

func NewMeshPublisher

func NewMeshPublisher(ctx context.Context, store storage.Store, reconnect time.Duration) (*P2PMeshAdapter, error)

NewMeshPublisher builds the control plane's own publish-only peer and keeps it connected to every router holding a lease, re-checking the lease table every reconnect. The lease table is all the control plane needs to know about the mesh's shape, and it already has it. Close stops the loop and the host.

func NewP2PMeshAdapter

func NewP2PMeshAdapter(h host.Host, topic *pubsub.Topic, store storage.Store) (*P2PMeshAdapter, error)

NewP2PMeshAdapter publishes on an existing host's topic. The caller owns both and closes them; Close on the adapter is a no-op.

func (*P2PMeshAdapter) Close

func (p *P2PMeshAdapter) Close() error

func (*P2PMeshAdapter) DiscoverServices

func (p *P2PMeshAdapter) DiscoverServices(ctx context.Context, serviceType string) ([]*ServiceAnnouncement, error)

func (*P2PMeshAdapter) GetNodeStatus

func (p *P2PMeshAdapter) GetNodeStatus(ctx context.Context, peerID string) (*NodeStatus, error)

func (*P2PMeshAdapter) PublishEvent

func (p *P2PMeshAdapter) PublishEvent(ctx context.Context, eventType api.MeshEvent_Type, peerID string, payload []byte) error

type Server

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

Server implements the Agent Mesh Control Plane web app.

func NewServer

func NewServer(config Options, store storage.Store) (*Server, error)

NewServer initializes the control plane server and stores configuration.

func (*Server) Addr

func (s *Server) Addr() string

Addr returns the network address the server is listening on.

func (*Server) Close

func (s *Server) Close() error

Close shuts down background loops and HTTP server.

func (*Server) HandleAdminBootstrapTokenAction

func (s *Server) HandleAdminBootstrapTokenAction(w http.ResponseWriter, r *http.Request)

HandleAdminBootstrapTokenAction HTTP DELETE `/admin/bootstrap-tokens/{id}` soft-revokes a token (see storage.BootstrapToken.RevokedAt): idempotent, and 404 only when the id names no token at all, per #368.

func (*Server) HandleAdminBootstrapTokens

func (s *Server) HandleAdminBootstrapTokens(w http.ResponseWriter, r *http.Request)

HandleAdminBootstrapTokens HTTP POST/GET `/admin/bootstrap-tokens`

func (*Server) HandleAdminEnrollmentAction

func (s *Server) HandleAdminEnrollmentAction(w http.ResponseWriter, r *http.Request)

HandleAdminEnrollmentAction HTTP POST `/admin/enrollments/{id}/approve` or `/admin/enrollments/{id}/reject`

func (*Server) HandleAdminEnrollments

func (s *Server) HandleAdminEnrollments(w http.ResponseWriter, r *http.Request)

HandleAdminEnrollments HTTP GET `/admin/enrollments`

func (*Server) HandleAdminNodeAction

func (s *Server) HandleAdminNodeAction(w http.ResponseWriter, r *http.Request)

HandleAdminNodeAction HTTP POST `/admin/nodes/{peer_id}/autonomous-recovery` with body {"enabled": bool} toggles storage.EnrolledNode.AutonomousRecovery for one enrolled node. This is the per-node counterpart of the flag on a bootstrap token, for a node that is already enrolled.

func (*Server) HandleAdminPolicy

func (s *Server) HandleAdminPolicy(w http.ResponseWriter, r *http.Request)

HandleAdminPolicy HTTP GET `/admin/policy`: the mesh policy as the operator wrote it, protojson of PolicyConfig, the same document POST /policies takes.

func (*Server) HandleAdminRevoke

func (s *Server) HandleAdminRevoke(w http.ResponseWriter, r *http.Request)

HandleAdminRevoke HTTP POST `/admin/revoke`

func (*Server) HandleAdminStatus

func (s *Server) HandleAdminStatus(w http.ResponseWriter, r *http.Request)

HandleAdminStatus HTTP GET `/admin/status`: the whole mesh as the console shows it, protojson of AdminStatusResponse.

func (*Server) HandleEgress

func (s *Server) HandleEgress(w http.ResponseWriter, r *http.Request)

HandleEgress HTTP GET `/egress`: the egress destinations the requesting node serves, selected by its roles and labels (see EgressDestination). Mesh protocol, biscuit-authenticated with signed challenge, binary protobuf.

func (*Server) HandleEnroll

func (s *Server) HandleEnroll(w http.ResponseWriter, r *http.Request)

HandleEnroll HTTP POST `/enroll`

func (*Server) HandleEnrollStatus

func (s *Server) HandleEnrollStatus(w http.ResponseWriter, r *http.Request)

HandleEnrollStatus HTTP GET `/enroll/status`

The approved response carries the enrollee's Biscuit, so polling requires proof of possession of the key submitted at /enroll: the api.HeaderChallengeTimestamp header (unix milliseconds) and the api.HeaderChallengeSignature header (unpadded base64url signature over api.EnrollStatusChallenge) must accompany `peer_id`. Every failure mode after the header parse answers a uniform 401 so the endpoint is not a peer-ID existence oracle for anonymous callers.

func (*Server) HandleHealthz

func (s *Server) HandleHealthz(w http.ResponseWriter, r *http.Request)

HandleHealthz HTTP GET `/healthz`

func (*Server) HandleInfo

func (s *Server) HandleInfo(w http.ResponseWriter, r *http.Request)

HandleInfo HTTP GET `/info`

func (*Server) HandleJWKS

func (s *Server) HandleJWKS(w http.ResponseWriter, r *http.Request)

HandleJWKS serves GET `/jwks`.

func (*Server) HandleKeys

func (s *Server) HandleKeys(w http.ResponseWriter, r *http.Request)

HandleKeys HTTP GET `/keys`

func (*Server) HandleListNodes

func (s *Server) HandleListNodes(w http.ResponseWriter, r *http.Request)

HandleListNodes HTTP GET `/user/nodes`: one page of the nodes the caller may see, protojson of NodeListResponse. An administrator sees every owner's nodes and may pick one with owner_id; a user sees only its own.

func (*Server) HandleNodeCatalog

func (s *Server) HandleNodeCatalog(w http.ResponseWriter, r *http.Request)

HandleNodeCatalog HTTP POST /nodes/catalog - a node self-reports the services it currently has registered locally (the same data list_local_services already answers on the node itself), so the control plane can show mesh-wide service topology without needing to be a DHT participant or open a P2P connection to every enrolled node itself.

The body is an api.NodeCatalogReport. The reporting peer is the one bound in the presented Biscuit, verified with a signed challenge in HeaderChallengeTimestamp and HeaderChallengeSignature so a node can only ever describe itself.

This is a live-status cache, not authoritative state: a node that goes offline without ever reporting an empty catalog just leaves its last report in place until ReportedAt visibly goes stale or its enrollment ends.

func (*Server) HandleOAuthAuthorizationServer

func (s *Server) HandleOAuthAuthorizationServer(w http.ResponseWriter, r *http.Request)

HandleOAuthAuthorizationServer serves GET `/.well-known/oauth-authorization-server` (RFC 8414).

func (*Server) HandleOAuthAuthorize

func (s *Server) HandleOAuthAuthorize(w http.ResponseWriter, r *http.Request)

HandleOAuthAuthorize serves GET and POST `/oauth/authorize` (OAuth 2.1 Authorization Code + PKCE S256).

func (*Server) HandleOAuthToken

func (s *Server) HandleOAuthToken(w http.ResponseWriter, r *http.Request)

HandleOAuthToken serves POST `/oauth/token` supporting OAuth 2.1 `authorization_code` (with PKCE S256) and RFC 8693 `token-exchange`.

func (*Server) HandleOpenIDConfiguration

func (s *Server) HandleOpenIDConfiguration(w http.ResponseWriter, r *http.Request)

HandleOpenIDConfiguration serves GET `/.well-known/openid-configuration`.

func (*Server) HandlePolicies

func (s *Server) HandlePolicies(w http.ResponseWriter, r *http.Request)

HandlePolicies HTTP GET/POST/PUT `/policies`

func (*Server) HandleReadyz

func (s *Server) HandleReadyz(w http.ResponseWriter, r *http.Request)

HandleReadyz HTTP GET `/readyz`

func (*Server) HandleRefresh

func (s *Server) HandleRefresh(w http.ResponseWriter, r *http.Request)

HandleRefresh HTTP POST `/refresh`

func (*Server) HandleRegister

func (s *Server) HandleRegister(w http.ResponseWriter, r *http.Request)

HandleRegister HTTP POST `/register`

func (*Server) HandleRevocations

func (s *Server) HandleRevocations(w http.ResponseWriter, r *http.Request)

HandleRevocations serves GET `/revocations` (mesh protocol, binary protobuf).

func (*Server) HandleRouterLease

func (s *Server) HandleRouterLease(w http.ResponseWriter, r *http.Request)

HandleRouterLease HTTP POST `/routers/lease`

func (*Server) HandleSTSToken

func (s *Server) HandleSTSToken(w http.ResponseWriter, r *http.Request)

HandleSTSToken serves stateless HTTP POST `/sts/token` (mesh protocol). It authenticates the calling egress agentmesh-node via Biscuit + PoP challenge, verifies the caller's Biscuit + appended tar_block chain against standing mesh policy and egress://<destination>, and mints a short-lived ES256 JWT.

func (*Server) HandleTokenExchange

func (s *Server) HandleTokenExchange(w http.ResponseWriter, r *http.Request)

HandleTokenExchange serves stateless HTTP POST `/token/exchange` (mesh protocol). It verifies the calling agentmesh-node's Biscuit + PoP challenge, verifies the inbound subject JWT, resolves subject roles from mesh policy, and mints a short-lived Delegated Session Biscuit with zero database writes.

func (*Server) HandleUserBootstrapTokens

func (s *Server) HandleUserBootstrapTokens(w http.ResponseWriter, r *http.Request)

func (*Server) HandleUserRevoke

func (s *Server) HandleUserRevoke(w http.ResponseWriter, r *http.Request)

func (*Server) HandleUserStatus

func (s *Server) HandleUserStatus(w http.ResponseWriter, r *http.Request)

func (*Server) Init

func (s *Server) Init() error

Init prepares the control plane without binding a listener: it bootstraps the signing keyring, discovers OIDC providers and starts the key-rotation loop. Embedders that own their own listener call Init + RegisterRoutes instead of Start.

func (*Server) RegisterRoutes

func (s *Server) RegisterRoutes(mux *http.ServeMux)

RegisterRoutes registers every control-plane HTTP handler on mux. Probes and /metrics are left uncounted so scrapers do not dominate the figures.

func (*Server) ReloadOperatorSigningKeys added in v0.1.1

func (s *Server) ReloadOperatorSigningKeys()

ReloadOperatorSigningKeys is one pass of the key file watcher, for callers that cannot wait for its timer (tests, an operator signal).

func (*Server) RevokeBiscuitID

func (s *Server) RevokeBiscuitID(revocationID string, expiry time.Time)

RevokeBiscuitID records a root Biscuit revocation ID (base64url-encoded) as revoked until expiry.

func (*Server) RevokeBiscuitToken

func (s *Server) RevokeBiscuitToken(rawToken []byte, expiry time.Time) (string, error)

RevokeBiscuitToken extracts the root (block 0) RevocationId of rawToken and records it in the control plane's revocation set.

func (*Server) RotateOIDCKey

func (s *Server) RotateOIDCKey(gracePeriod time.Duration) (string, error)

RotateOIDCKey rotates the control plane's ES256 OIDC signing key when backed by LocalES256Signer.

func (*Server) SetMeshAdapter

func (s *Server) SetMeshAdapter(m MeshAdapter)

SetMeshAdapter sets a custom MeshAdapter implementation for the control plane.

func (*Server) Start

func (s *Server) Start() error

Start boots up HTTP services, sets up OIDC providers, loads initial keys and policies, and schedules rotations. Start boots up HTTP services, sets up OIDC providers, loads initial keys and policies, and schedules rotations.

type ServiceAnnouncement

type ServiceAnnouncement struct {
	ServiceName string
	ServiceType string
	PeerID      string
	Addresses   []string
}

ServiceAnnouncement represents service discovery details retrieved from the mesh.

Directories

Path Synopsis
Package client is how a mesh component reads from its control plane.
Package client is how a mesh component reads from its control plane.

Jump to

Keyboard shortcuts

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