Documentation
¶
Overview ¶
Package server serves the fleetsweeper HTTP API and the embedded web dashboard backed by the scan store.
Index ¶
- Constants
- Variables
- func RunScanners(ctx context.Context, clients []*kube.Client, ...) map[string]map[string]scanner.Result
- func SeedDemo(ctx context.Context, st store.Store, now time.Time) error
- func SetBuildInfo(version, commit, date string)
- func StoreReportOptions(ctx context.Context, st store.Store) (report.BuildOptions, error)
- type Actor
- type Config
- type Event
- type OIDCConfig
- type Server
- func (s *Server) Close()
- func (s *Server) Handler() http.Handler
- func (s *Server) ListenAndServe() error
- func (s *Server) ListenAndServeAdmin() error
- func (s *Server) PublishEvent(typ string, payload any)
- func (s *Server) ScanOnce(ctx context.Context, opts controller.ScanOptions) (controller.ScanSummary, error)
- func (s *Server) Shutdown(ctx context.Context) error
- func (s *Server) StartAuditRetention(ctx context.Context, retain time.Duration)
- func (s *Server) StartScheduler(ctx context.Context, interval time.Duration, contexts []string)
Constants ¶
const ( // EventScanComplete fires once after each scan persists. EventScanComplete = "scan.complete" // EventScanFailed fires when a triggered scan errored out. EventScanFailed = "scan.failed" // EventKeyRevoked fires when an admin revokes an API key. EventKeyRevoked = "key.revoked" // EventAlertReceived fires for each alert delivered by AlertManager. EventAlertReceived = "alert.received" )
Event type constants. New event types must follow `<noun>.<verb>` so consumers can subscribe by prefix.
Variables ¶
var ( // ErrServer indicates a general server failure. ErrServer = errors.New("server") // ErrBadRequest indicates invalid client input. ErrBadRequest = errors.New("bad request") // ErrMissingCredential indicates a request with no credential to a server that holds one. ErrMissingCredential = errors.New("credential required") )
var ErrDemoSeed = errors.New("demo seed failed")
ErrDemoSeed is returned when the demo store cannot be seeded.
Functions ¶
func RunScanners ¶ added in v0.10.0
func RunScanners(ctx context.Context, clients []*kube.Client, scanners map[string]scanner.Scanner, workers int, timeout time.Duration, log *zap.Logger) map[string]map[string]scanner.Result
RunScanners executes every scanner against every client with at most workers running at once, each bounded by timeout, and returns results keyed by context then scanner. A scanner that fails, or that never starts because ctx was canceled, is recorded as an errored result so the report counts it as missing coverage rather than as a clean read. Each scanner-cluster pair gets a child span so traces show the per-scanner fan-out.
func SeedDemo ¶ added in v0.10.0
SeedDemo fills an empty store with the demo fleet: a series of scans ending at now whose results are built from each scanner's own data types and run through the real engine on read, plus inbound alerts, cohort tags, groups, and manual locations. A store that already holds scans is left alone.
func SetBuildInfo ¶
func SetBuildInfo(version, commit, date string)
SetBuildInfo records build metadata so the /admin/system endpoint can report it. The cmd package calls this once during startup.
func StoreReportOptions ¶ added in v0.12.0
StoreReportOptions returns the cohort tags and groups that every report built from st uses, so the CLI and the server partition the same stored scan the same way. It returns whatever it loaded together with any error.
Types ¶
type Actor ¶
type Actor struct {
// ID is the API key identifier, or "bootstrap" for --auth-token, or
// "anonymous" for --insecure mode.
ID string
// Name is a human-readable label for log lines and audit entries.
Name string
// Role is one of store.RoleAdmin, store.RoleOperator, store.RoleViewer.
Role string
// ClusterScope is the list of cluster names (or "group:<n>" entries) this
// actor may act upon. The single element "*" grants unrestricted access.
ClusterScope []string
}
Actor describes who is performing a request after authentication. An Actor is always present once authMiddleware has run, even in --insecure mode where it represents an anonymous admin.
func (*Actor) AllowsCluster ¶
AllowsCluster reports whether the actor may act on the given cluster. groupLookup, when non-nil, resolves "group:<name>" scope entries to their member cluster names so a group-scoped key authorizes any current member.
func (*Actor) CanManageGroups ¶ added in v0.10.0
CanManageGroups reports whether the actor may create or delete groups. A group widens every key scoped to it, so defining one is an admin act whatever the actor's cluster scope.
func (*Actor) FilterClusters ¶
FilterClusters returns the subset of clusters the actor is permitted to act on.
func (*Actor) HasWildcardScope ¶
HasWildcardScope reports whether the actor may act on any cluster.
type Config ¶
type Config struct {
// Addr is the listen address for the public API and UI. Empty means ":8080".
Addr string
// AdminAddr is the listen address for pprof and metrics. Empty disables the admin server.
AdminAddr string
// Store is the database backend.
Store store.Store
// Registry is the scanner registry.
Registry *scanner.Registry
// Log is the zap logger.
Log *zap.Logger
// KubeconfigPath is the kubeconfig file path for scans.
KubeconfigPath string
// Workers is the max concurrent operations for scans.
Workers int
// AuthToken is the bearer token required for mutating endpoints. When
// empty and Insecure is false, mutating endpoints return 403.
AuthToken string
// Insecure disables authentication entirely when true. Demo implies it.
Insecure bool
// CORSOrigins is the explicit allowlist of permitted cross-origin Origins.
// Wildcard is intentionally not supported.
CORSOrigins []string
// Demo, when true, causes /api/geo to return synthetic fleet data so the
// globe can be previewed without any real clusters or scans, and a
// triggered scan scans the synthetic fleet instead of the kubeconfig. Demo
// turns authentication off, since nothing in the demo reaches a real cluster.
Demo bool
// SlackWebhookURL, when non-empty, is the incoming-webhook URL that
// receives new critical findings.
SlackWebhookURL string
// FleetDriftOutputDir, when non-empty, is a local directory the server
// writes FleetDriftReport YAMLs into after every scan. One file per
// cluster, overwritten in place so the directory tracks the latest scan.
FleetDriftOutputDir string
// PolicyReportOutputDir, when non-empty, is a local directory the server
// writes wgpolicyk8s.io PolicyReport YAMLs to after every scan.
PolicyReportOutputDir string
// PolicyReportNamespace is the namespace placed on emitted PolicyReports.
// Defaults to "fleetsweeper" when empty.
PolicyReportNamespace string
// CostCSVPath, when non-empty, points at a CSV mapping clusters to costs.
// Loaded once at startup and refreshed on a periodic ticker so dashboard
// cost correlation reflects current billing without a restart.
CostCSVPath string
// WebhookConfigPath, when non-empty, points at a YAML file of outbound
// HTTP subscribers. See internal/webhooks for the schema.
WebhookConfigPath string
// WebhookSecret, when non-empty, is the HMAC-SHA256 shared secret an
// inbound webhook caller must use to authenticate scan-trigger calls.
WebhookSecret string
// SealKey, when non-empty, is the HMAC-SHA256 secret used to sign every
// saved scan report. Sealed scans can be verified later with
// `fleetsweeper verify`.
SealKey string
// OIDC configures browser SSO. When zero-valued the server runs in
// bearer-only mode.
OIDC OIDCConfig
// ReadRPM is the per-client budget for GET/HEAD/OPTIONS requests,
// keyed by client address. Zero disables read limiting; 600 (10 per
// second per client) is a sensible start.
ReadRPM int
// WriteRPM is the per-client budget for mutating requests, keyed by
// client address. Zero disables write limiting; 60 (one per second
// per client) is a sensible start.
WriteRPM int
// TrustedProxyHeader, when set, names the header (for example X-Forwarded-For) a trusted
// reverse proxy uses to carry the client address. The rate limiter keys on its last entry.
// Leave it empty unless every request arrives through that proxy, since clients can set
// the header themselves.
TrustedProxyHeader string
// AdmissionMetrics, when non-nil, has its counters written on /metrics.
AdmissionMetrics *admission.Metrics
}
Config holds server configuration.
type Event ¶
type Event struct {
// Type categorizes the event (for example "scan.complete").
Type string `json:"type"`
// At is when the event was emitted.
At time.Time `json:"at"`
// Payload is the event-specific data.
Payload any `json:"payload,omitempty"`
}
Event is one server-sent event the dashboard or external consumers subscribe to. The Type field is the SSE event name; Data is JSON- serialized on the wire.
type OIDCConfig ¶
type OIDCConfig struct {
// IssuerURL is the OIDC discovery URL (e.g. https://accounts.google.com).
IssuerURL string
// ClientID identifies the fleetsweeper application at the IdP.
ClientID string
// ClientSecret is the matching client secret.
ClientSecret string
// RedirectURL is fleetsweeper's callback URL, e.g.
// https://fleetsweeper.example.com/oidc/callback. Must be registered
// with the IdP exactly.
RedirectURL string
// Scopes requested. Defaults to openid + email + profile.
Scopes []string
// SessionSecret is the HMAC-SHA256 key used to sign session cookies.
// Treat as a long-term server secret.
SessionSecret string
// SessionLifetime is the cookie validity window. Defaults to 8 hours.
SessionLifetime time.Duration
// AdminClaim is the JWT claim consulted to assign the admin role.
// Format: "<claim_name>:<value>" — e.g. "groups:fleetsweeper-admins"
// or "email:ops@example.com". Empty disables admin promotion via OIDC.
AdminClaim string
// OperatorClaim is the JWT claim for the operator role. Empty disables.
OperatorClaim string
// DefaultRole is the role granted to authenticated users who match no
// claim mapping. Defaults to viewer.
DefaultRole string
}
OIDCConfig configures the OIDC login flow. All fields are required when OIDC is enabled; the auth middleware silently ignores cookies when OIDCConfig.SessionSecret is empty.
type Server ¶
type Server struct {
// contains filtered or unexported fields
}
Server wraps the HTTP server with its dependencies.
func (*Server) Close ¶
func (s *Server) Close()
Close is a convenience wrapper that cancels the server context and waits for background goroutines to drain. Used by tests and offline tooling.
func (*Server) Handler ¶ added in v0.7.0
Handler returns the root HTTP handler with request logging applied, exactly as ListenAndServe serves it, so the server can be embedded behind another router or driven in tests without binding a socket.
func (*Server) ListenAndServe ¶
ListenAndServe serves the public API and UI on Config.Addr until Shutdown. It returns nil after a graceful shutdown, including one that happens before it is called.
func (*Server) ListenAndServeAdmin ¶
ListenAndServeAdmin serves pprof and metrics on Config.AdminAddr, intended for an internal address that is not exposed to untrusted networks. It is a no-op when no admin address is configured.
func (*Server) PublishEvent ¶
PublishEvent is the server-facing API for emitting events. Other handlers call it after persisting a scan or revoking a key.
func (*Server) ScanOnce ¶
func (s *Server) ScanOnce(ctx context.Context, opts controller.ScanOptions) (controller.ScanSummary, error)
ScanOnce executes a single scan with the given options and returns a summary. It satisfies the controller.ScanRunner interface so the ClusterScan operator can drive scans without depending on internal server types beyond Server. It runs through executeScan, so a controller-driven scan and any other scan cannot interleave.
func (*Server) Shutdown ¶
Shutdown gracefully stops both HTTP servers, cancels the server context, and waits for fire-and-forget background goroutines to drain.
func (*Server) StartAuditRetention ¶
StartAuditRetention launches a goroutine that periodically deletes audit_log rows older than retain. retain <= 0 disables retention pruning (the table grows unboundedly until pruned externally). The ticker runs every hour but the first prune fires immediately so a fresh deployment with an existing database does not wait an hour.
func (*Server) StartScheduler ¶
StartScheduler scans contexts every interval, starting immediately, and blocks until ctx or the server context is canceled. Under leader election ctx is the leadership term, so losing the lease stops the scheduler. At most one scheduler runs per process: a call made while an earlier one is still winding down waits for it to return, so a replica that loses and regains leadership never runs two.
Source Files
¶
- acks_handler.go
- admin_keys_handler.go
- alertmanager_handler.go
- audit_handler.go
- audit_middleware.go
- audit_retention.go
- auth.go
- cohorts_map_handler.go
- cost_handler.go
- demo_fleet.go
- demo_results.go
- demo_seed.go
- distributions_handler.go
- errors.go
- events.go
- falco_handler.go
- findings_timeline_handler.go
- fleetdrift_emit.go
- forecast_handler.go
- geo_handlers.go
- handlers.go
- history_findings.go
- inbound_webhook.go
- integrations_handler.go
- metrics.go
- metrics_otel.go
- middleware.go
- oidc.go
- openapi.go
- policyreport_emit.go
- ratelimit.go
- report_cache.go
- scan_once.go
- seal_handler.go
- server.go
- slack.go
- system_handler.go
- tag_filter.go
- tags_handler.go
- timeline_handler.go
- webhook_dispatcher_type.go
- webhook_emit.go
- whatif_handler.go