Documentation
¶
Index ¶
- Constants
- Variables
- func BearerAuthMiddleware(token string) func(http.Handler) http.Handler
- func DecryptSecret(nsk []byte, ciphertext string, nonce string) (string, error)
- func HandleNodeSecretsUpdated(cache *StateCache, logger *slog.Logger, env api.SignedEnvelope) error
- func HandleNodeStateUpdated(cache *StateCache, logger *slog.Logger, env api.SignedEnvelope) error
- func RegisterEventHandlers(dispatcher *api.EventDispatcher, cache *StateCache, logger *slog.Logger)
- func SecretAuthMiddleware(checker GroupChecker, getter PeerCredGetter, logger *slog.Logger) func(http.Handler) http.Handler
- func SetSocketPermissions(socketPath string, logger *slog.Logger) error
- type ActionProvider
- type Config
- type ForwarderStatus
- type ForwarderStatusProvider
- type GroupChecker
- type Handler
- func (h *Handler) Mux() *http.ServeMux
- func (h *Handler) SetActionProvider(provider ActionProvider)
- func (h *Handler) SetAuditStatus(p ForwarderStatusProvider)
- func (h *Handler) SetHookReloader(reloader HookReloader)
- func (h *Handler) SetLogStatus(p ForwarderStatusProvider)
- func (h *Handler) SetPeerProvider(p PeerProvider)
- func (h *Handler) SetPolicyProvider(p PolicyProvider)
- type HookReloader
- type LocalActionRunner
- type NodeAPIClient
- type NodeSecretsUpdatePayload
- type NodeStateUpdatePayload
- type OSGroupChecker
- type PeerCredGetter
- type PeerCredentials
- type PeerProvider
- type PeerStatus
- type PolicyProvider
- type ReportEntry
- type ReportSyncClient
- type ReportSyncer
- type SecretFetcher
- type Server
- func (s *Server) Cache() *StateCache
- func (s *Server) ReconcileHandler() reconcile.ReconcileHandler
- func (s *Server) RegisterEventHandlers(dispatcher *api.EventDispatcher)
- func (s *Server) SetActionProvider(provider ActionProvider)
- func (s *Server) SetAuditStatus(p ForwarderStatusProvider)
- func (s *Server) SetHookReloader(reloader HookReloader)
- func (s *Server) SetLogStatus(p ForwarderStatusProvider)
- func (s *Server) SetPeerProvider(p PeerProvider)
- func (s *Server) SetPolicyProvider(p PolicyProvider)
- func (s *Server) Start(ctx context.Context, nodeID string) error
- type StateCache
- func (sc *StateCache) DeleteReport(key string) error
- func (sc *StateCache) GetData() map[string]api.DataEntry
- func (sc *StateCache) GetDataEntry(key string) (api.DataEntry, bool)
- func (sc *StateCache) GetMetadata() map[string]string
- func (sc *StateCache) GetMetadataKey(key string) (string, bool)
- func (sc *StateCache) GetReport(key string) (ReportEntry, bool)
- func (sc *StateCache) GetReports() map[string]ReportEntry
- func (sc *StateCache) GetSecretIndex() []api.SecretRef
- func (sc *StateCache) Load() error
- func (sc *StateCache) PutReport(key, contentType string, payload json.RawMessage, ifMatch *int) (ReportEntry, error)
- func (sc *StateCache) UpdateData(entries []api.DataEntry)
- func (sc *StateCache) UpdateMetadata(m map[string]string)
- func (sc *StateCache) UpdateSecretIndex(refs []api.SecretRef)
- type StateSummary
Constants ¶
const DefaultDebouncePeriod = 5 * time.Second
DefaultDebouncePeriod is the default debounce period.
const DefaultHTTPListen = "127.0.0.1:9100"
DefaultHTTPListen is the default HTTP listen address.
const DefaultShutdownTimeout = 5 * time.Second
DefaultShutdownTimeout is the default graceful shutdown timeout.
const DefaultSocketPath = "/var/run/plexd/api.sock"
DefaultSocketPath is the default Unix domain socket path.
Variables ¶
var ( // ErrVersionConflict is returned when an optimistic locking check fails. ErrVersionConflict = errors.New("nodeapi: version conflict") // ErrNotFound is returned when the requested entry does not exist. ErrNotFound = errors.New("nodeapi: not found") )
Functions ¶
func BearerAuthMiddleware ¶
BearerAuthMiddleware returns middleware that validates Bearer token authentication. Requests without a valid token receive 401 Unauthorized. Unix socket requests bypass this middleware (it is only applied to the TCP listener).
func DecryptSecret ¶
DecryptSecret decrypts an AES-256-GCM encrypted secret. The ciphertext and nonce are base64-encoded (standard encoding). The NSK (node secret key) must be exactly 32 bytes. Returns a generic error on failure to avoid leaking cryptographic details.
func HandleNodeSecretsUpdated ¶
func HandleNodeSecretsUpdated(cache *StateCache, logger *slog.Logger, env api.SignedEnvelope) error
HandleNodeSecretsUpdated parses the event payload and updates the secret index in the cache.
func HandleNodeStateUpdated ¶
func HandleNodeStateUpdated(cache *StateCache, logger *slog.Logger, env api.SignedEnvelope) error
HandleNodeStateUpdated parses the event payload and updates metadata and data entries in the cache.
func RegisterEventHandlers ¶
func RegisterEventHandlers(dispatcher *api.EventDispatcher, cache *StateCache, logger *slog.Logger)
RegisterEventHandlers registers SSE event handlers for node_state_updated and node_secrets_updated with the given dispatcher.
func SecretAuthMiddleware ¶
func SecretAuthMiddleware(checker GroupChecker, getter PeerCredGetter, logger *slog.Logger) func(http.Handler) http.Handler
SecretAuthMiddleware returns HTTP middleware that restricts access to secret endpoints. Access is granted to root (UID 0) or processes whose user is a member of the plexd-secrets group.
The middleware extracts peer credentials from the request's underlying connection using a PeerCredGetter. In production, this is backed by SO_PEERCRED; in tests, a mock can be injected.
func SetSocketPermissions ¶
SetSocketPermissions sets ownership and permissions on the Unix socket file. If the plexd group exists, the socket is chowned to root:plexd with mode 0660. If the group does not exist, the socket gets mode 0666 and a warning is logged.
Types ¶
type ActionProvider ¶
type ActionProvider interface {
Capabilities() ([]api.ActionInfo, []api.HookInfo)
}
ActionProvider supplies action and hook information to the local API.
type Config ¶
type Config struct {
// SocketPath is the path to the Unix domain socket.
// Default: /var/run/plexd/api.sock
SocketPath string `yaml:"socket_path"`
// HTTPEnabled enables the optional HTTP listener.
// Default: false
HTTPEnabled bool `yaml:"http_enabled"`
// HTTPListen is the HTTP listen address.
// Default: 127.0.0.1:9100
HTTPListen string `yaml:"http_listen"`
// HTTPTokenFile is the path to the HTTP bearer token file.
HTTPTokenFile string `yaml:"http_token_file"`
// DebouncePeriod is the debounce period for coalescing events.
// Default: 5s
DebouncePeriod time.Duration `yaml:"debounce_period"`
// ShutdownTimeout is the maximum time to wait for a graceful shutdown.
// Default: 5s
ShutdownTimeout time.Duration `yaml:"shutdown_timeout"`
// DataDir is the path to the data directory (required).
DataDir string `yaml:"data_dir"`
// SecretAuthEnabled enables SO_PEERCRED-based authentication for
// /v1/state/secrets/* routes on the Unix socket. When enabled, only
// root (UID 0) or plexd-secrets group members may access secrets.
// Default: false (enabled by cmd/plexd/cmd/up.go in production).
SecretAuthEnabled bool `yaml:"secret_auth_enabled"`
}
Config holds the configuration for the local node API server. Config is passed as a constructor argument — no file I/O in this package.
func (*Config) ApplyDefaults ¶
func (c *Config) ApplyDefaults()
ApplyDefaults sets default values for zero-valued fields.
type ForwarderStatus ¶
type ForwarderStatus struct {
Enabled bool `json:"enabled"`
BufferSize int `json:"buffer_size"`
SourceCount int `json:"source_count"`
ErrorCount int `json:"error_count"`
LastReportAt string `json:"last_report_at,omitempty"`
}
ForwarderStatus describes the operational status of a log or audit forwarder.
type ForwarderStatusProvider ¶
type ForwarderStatusProvider interface {
ForwarderStatus() ForwarderStatus
}
ForwarderStatusProvider supplies forwarder status information.
type GroupChecker ¶
type GroupChecker interface {
// IsInGroup reports whether the user identified by uid belongs to the
// named group, or if the user's primary group (gid) matches the group.
IsInGroup(uid, gid uint32, groupName string) bool
}
GroupChecker checks group membership for a given user.
type Handler ¶
type Handler struct {
// contains filtered or unexported fields
}
Handler provides HTTP handlers for the local node API.
func NewHandler ¶
func NewHandler(cache *StateCache, secretFetcher SecretFetcher, nodeID string, nsk []byte, logger *slog.Logger) *Handler
NewHandler creates a new Handler.
func (*Handler) SetActionProvider ¶
func (h *Handler) SetActionProvider(provider ActionProvider)
SetActionProvider sets the action provider for action/hook endpoints.
func (*Handler) SetAuditStatus ¶
func (h *Handler) SetAuditStatus(p ForwarderStatusProvider)
SetAuditStatus sets the audit forwarder status provider.
func (*Handler) SetHookReloader ¶
func (h *Handler) SetHookReloader(reloader HookReloader)
SetHookReloader sets the hook reloader for the reload endpoint.
func (*Handler) SetLogStatus ¶
func (h *Handler) SetLogStatus(p ForwarderStatusProvider)
SetLogStatus sets the log forwarder status provider.
func (*Handler) SetPeerProvider ¶
func (h *Handler) SetPeerProvider(p PeerProvider)
SetPeerProvider sets the peer status provider.
func (*Handler) SetPolicyProvider ¶
func (h *Handler) SetPolicyProvider(p PolicyProvider)
SetPolicyProvider sets the policy provider.
type HookReloader ¶
HookReloader triggers a re-scan of hooks from the filesystem.
type LocalActionRunner ¶
type LocalActionRunner interface {
RunLocal(ctx context.Context, action string, params map[string]string) (stdout, stderr string, exitCode int, err error)
}
LocalActionRunner runs a built-in action synchronously and returns output.
type NodeAPIClient ¶
type NodeAPIClient interface {
SecretFetcher
ReportSyncClient
}
NodeAPIClient combines the control plane methods needed by the node API server.
type NodeSecretsUpdatePayload ¶
NodeSecretsUpdatePayload is the payload for node_secrets_updated events.
type NodeStateUpdatePayload ¶
type NodeStateUpdatePayload struct {
Metadata map[string]string `json:"metadata"`
Data []api.DataEntry `json:"data"`
}
NodeStateUpdatePayload is the payload for node_state_updated events.
type OSGroupChecker ¶
type OSGroupChecker struct{}
OSGroupChecker checks group membership using the OS user/group database.
type PeerCredGetter ¶
type PeerCredGetter interface {
GetPeerCredentials(r *http.Request) (*PeerCredentials, error)
}
PeerCredGetter extracts peer credentials from an HTTP request's underlying connection.
type PeerCredentials ¶
PeerCredentials holds the peer credentials extracted from a Unix socket connection.
func GetPeerCredentials ¶
func GetPeerCredentials(conn net.Conn) (*PeerCredentials, error)
GetPeerCredentials extracts peer credentials from a Unix socket connection using the SO_PEERCRED socket option. Returns an error if the connection is not a Unix socket or the credentials cannot be retrieved.
type PeerProvider ¶
type PeerProvider interface {
PeerStatuses() []PeerStatus
}
PeerProvider supplies mesh peer information.
type PeerStatus ¶
type PeerStatus struct {
ID string `json:"id"`
PublicKey string `json:"public_key"`
MeshIP string `json:"mesh_ip"`
Endpoint string `json:"endpoint"`
}
PeerStatus describes a single mesh peer's status.
type PolicyProvider ¶
PolicyProvider supplies active network policies.
type ReportEntry ¶
type ReportEntry struct {
Key string `json:"key"`
ContentType string `json:"content_type"`
Payload json.RawMessage `json:"payload"`
Version int `json:"version"`
UpdatedAt time.Time `json:"updated_at"`
}
ReportEntry represents a locally-managed report entry.
type ReportSyncClient ¶
type ReportSyncClient interface {
SyncReports(ctx context.Context, nodeID string, req api.ReportSyncRequest) error
}
ReportSyncClient is the interface for syncing reports to the control plane.
type ReportSyncer ¶
type ReportSyncer struct {
// contains filtered or unexported fields
}
ReportSyncer buffers report changes and syncs them to the control plane with debouncing to coalesce rapid updates.
func NewReportSyncer ¶
func NewReportSyncer(client ReportSyncClient, nodeID string, debouncePeriod time.Duration, logger *slog.Logger) *ReportSyncer
NewReportSyncer creates a new ReportSyncer.
func (*ReportSyncer) NotifyChange ¶
func (s *ReportSyncer) NotifyChange(entries []api.ReportEntry, deleted []string)
NotifyChange buffers report changes and signals the run loop. Entries are appended; later entries for the same key overwrite earlier ones. Deleted keys are appended.
type SecretFetcher ¶
type SecretFetcher interface {
FetchSecret(ctx context.Context, nodeID, key string) (*api.SecretResponse, error)
}
SecretFetcher abstracts the control plane client for secret retrieval.
type Server ¶
type Server struct {
// contains filtered or unexported fields
}
Server is the local node API server. It serves HTTP over a Unix socket and optionally over TCP with bearer token authentication.
func NewServer ¶
NewServer creates a new Server. Config defaults are applied automatically. The cache is initialized eagerly so that RegisterEventHandlers and ReconcileHandler can be called before Start.
func (*Server) Cache ¶
func (s *Server) Cache() *StateCache
Cache returns the server's state cache for use by SSE event handlers.
func (*Server) ReconcileHandler ¶
func (s *Server) ReconcileHandler() reconcile.ReconcileHandler
ReconcileHandler returns a reconcile.ReconcileHandler that updates the cache when drift is detected in metadata, data, or secret refs.
func (*Server) RegisterEventHandlers ¶
func (s *Server) RegisterEventHandlers(dispatcher *api.EventDispatcher)
RegisterEventHandlers registers SSE event handlers with the given dispatcher.
func (*Server) SetActionProvider ¶
func (s *Server) SetActionProvider(provider ActionProvider)
SetActionProvider sets the action provider for action/hook endpoints. Must be called before Start.
func (*Server) SetAuditStatus ¶
func (s *Server) SetAuditStatus(p ForwarderStatusProvider)
SetAuditStatus sets the audit forwarder status provider. Must be called before Start.
func (*Server) SetHookReloader ¶
func (s *Server) SetHookReloader(reloader HookReloader)
SetHookReloader sets the hook reloader for the reload endpoint. Must be called before Start.
func (*Server) SetLogStatus ¶
func (s *Server) SetLogStatus(p ForwarderStatusProvider)
SetLogStatus sets the log forwarder status provider. Must be called before Start.
func (*Server) SetPeerProvider ¶
func (s *Server) SetPeerProvider(p PeerProvider)
SetPeerProvider sets the peer status provider. Must be called before Start.
func (*Server) SetPolicyProvider ¶
func (s *Server) SetPolicyProvider(p PolicyProvider)
SetPolicyProvider sets the policy provider. Must be called before Start.
type StateCache ¶
type StateCache struct {
// contains filtered or unexported fields
}
StateCache holds node state in memory with file persistence.
func NewStateCache ¶
func NewStateCache(dataDir string, logger *slog.Logger) *StateCache
NewStateCache creates a new StateCache with empty maps. dataDir is the base path; the state subdirectory tree will be created under dataDir/state/.
func (*StateCache) DeleteReport ¶
func (sc *StateCache) DeleteReport(key string) error
DeleteReport removes a report entry and its file. Returns ErrNotFound if the key does not exist.
func (*StateCache) GetData ¶
func (sc *StateCache) GetData() map[string]api.DataEntry
GetData returns a copy of the data map.
func (*StateCache) GetDataEntry ¶
func (sc *StateCache) GetDataEntry(key string) (api.DataEntry, bool)
GetDataEntry returns a data entry by key and whether it exists.
func (*StateCache) GetMetadata ¶
func (sc *StateCache) GetMetadata() map[string]string
GetMetadata returns a copy of the metadata map.
func (*StateCache) GetMetadataKey ¶
func (sc *StateCache) GetMetadataKey(key string) (string, bool)
GetMetadataKey returns the value for a metadata key and whether it exists.
func (*StateCache) GetReport ¶
func (sc *StateCache) GetReport(key string) (ReportEntry, bool)
GetReport returns a report entry by key and whether it exists.
func (*StateCache) GetReports ¶
func (sc *StateCache) GetReports() map[string]ReportEntry
GetReports returns a copy of the reports map.
func (*StateCache) GetSecretIndex ¶
func (sc *StateCache) GetSecretIndex() []api.SecretRef
GetSecretIndex returns a copy of the secret index.
func (*StateCache) Load ¶
func (sc *StateCache) Load() error
Load reads persisted state from disk. Missing files or directories are treated as fresh (empty) state. The directory tree is created if absent.
func (*StateCache) PutReport ¶
func (sc *StateCache) PutReport(key, contentType string, payload json.RawMessage, ifMatch *int) (ReportEntry, error)
PutReport creates or updates a report entry. If the entry exists and ifMatch is non-nil, it must equal the current version or ErrVersionConflict is returned. Version starts at 1 for new entries and increments on update.
func (*StateCache) UpdateData ¶
func (sc *StateCache) UpdateData(entries []api.DataEntry)
UpdateData replaces data entries in memory and persists each to data/{key}.json. Files for entries no longer present are removed.
func (*StateCache) UpdateMetadata ¶
func (sc *StateCache) UpdateMetadata(m map[string]string)
UpdateMetadata replaces the metadata in memory and persists to metadata.json.
func (*StateCache) UpdateSecretIndex ¶
func (sc *StateCache) UpdateSecretIndex(refs []api.SecretRef)
UpdateSecretIndex replaces the secret index in memory and persists to secrets.json.
type StateSummary ¶
type StateSummary struct {
Metadata map[string]string `json:"metadata"`
DataKeys []dataKeySummary `json:"data_keys"`
SecretKeys []secretKeySummary `json:"secret_keys"`
ReportKeys []reportKeySummary `json:"report_keys"`
}
StateSummary is the response for GET /v1/state.