Documentation
¶
Index ¶
- Variables
- func ValidateBrowseURL(raw string) (*url.URL, error)
- type CSRFStore
- type EnrolStateInfo
- type EnrolmentRunner
- func (r *EnrolmentRunner) AnyRunning() bool
- func (r *EnrolmentRunner) Complete()
- func (r *EnrolmentRunner) GetState(key string) (EnrolStateInfo, error)
- func (r *EnrolmentRunner) HasPending() bool
- func (r *EnrolmentRunner) MarkComplete(key string)
- func (r *EnrolmentRunner) Reset(key string) error
- func (r *EnrolmentRunner) Skip(key string) error
- func (r *EnrolmentRunner) Start(ctx context.Context, key string, vc *vault.Client, ...) error
- func (r *EnrolmentRunner) States() []EnrolStateInfo
- func (r *EnrolmentRunner) Wait()
- func (r *EnrolmentRunner) WaitForKey(key string)
- type OAuthManager
- type PromptSecretFunc
- type Server
- func (s *Server) EnrolPromptSecret(ctx context.Context, label string) (string, error)
- func (s *Server) ForceReauth()
- func (s *Server) InitEnrolments(ctx context.Context, enrolments map[string]config.Enrolment)
- func (s *Server) InitialSyncComplete() bool
- func (s *Server) MarkInitialSyncComplete()
- func (s *Server) SetReauthGate(g interface{ ... })
- func (s *Server) Shutdown(ctx context.Context) error
- func (s *Server) Start() error
- func (s *Server) URL() string
- func (s *Server) UpdateDynamicConfig(rules []config.Rule, syncCfg config.SyncConfig)
- func (s *Server) UpdateEnrolments(ctx context.Context, enrolments map[string]config.Enrolment) bool
- func (s *Server) WaitForAuth(ctx context.Context) error
- func (s *Server) WaitForEnrolments()
- func (s *Server) WaitReady() error
- type ServerConfig
Constants ¶
This section is empty.
Variables ¶
var ( ErrEnrolNotFound = fmt.Errorf("enrolment not found") ErrEnrolAlreadyRunning = fmt.Errorf("enrolment already running") ErrEnrolBusy = fmt.Errorf("another enrolment is running") ErrEnrolInvalidEngine = fmt.Errorf("enrolment has no valid engine") ErrEnrolNotStartable = fmt.Errorf("enrolment is not in a startable state") ErrEnrolNotResettable = fmt.Errorf("enrolment is not in a resettable state") )
Sentinel errors for enrolment operations.
Functions ¶
func ValidateBrowseURL ¶ added in v0.28.0
ValidateBrowseURL enforces the remote-browse allowlist: the value must parse as an absolute http or https URL with a host and no embedded credentials. Everything else — file://, custom protocol handlers (vscode:, ssh:), scheme-relative or bare paths, user:pass@ forms — is rejected, because the browser opener hands the string to xdg-open / `open` / ShellExecute, which would happily dispatch non-web schemes to arbitrary local handlers, and userinfo would carry credentials into the opener and its logs. Returns the parsed URL so callers never re-parse (the canonical string form is u.String()).
The rule itself lives in internal/urlallow so the notification action link (internal/notify) enforces byte-for-byte the same allowlist from one implementation — notify cannot import web (web imports notify), so a shared leaf package is the seam.
Types ¶
type CSRFStore ¶
type CSRFStore struct {
// contains filtered or unexported fields
}
CSRFStore manages CSRF token generation and validation.
func (*CSRFStore) IssueHandler ¶
func (cs *CSRFStore) IssueHandler() http.HandlerFunc
IssueHandler returns an HTTP handler that issues a new CSRF token.
type EnrolStateInfo ¶
type EnrolStateInfo struct {
Key string `json:"key"`
Engine string `json:"engine"`
EngineName string `json:"name"`
Status string `json:"status"`
Fields []string `json:"fields"`
Output []string `json:"output,omitempty"`
Error string `json:"error,omitempty"`
HelpTextHTML string `json:"help_text_html,omitempty"`
}
EnrolStateInfo is the JSON-serializable view of an enrolment's state.
type EnrolmentRunner ¶
type EnrolmentRunner struct {
// contains filtered or unexported fields
}
EnrolmentRunner manages per-enrolment lifecycle for web mode.
func NewEnrolmentRunner ¶
func NewEnrolmentRunner(enrolments map[string]config.Enrolment) *EnrolmentRunner
NewEnrolmentRunner creates a runner from the enrolments config. All enrolments start as "pending". Call MarkComplete() for enrolments that are already satisfied in Vault before exposing to the frontend.
func (*EnrolmentRunner) AnyRunning ¶ added in v0.22.0
func (r *EnrolmentRunner) AnyRunning() bool
AnyRunning reports whether any enrolment is currently executing. The daemon's config-refresh loop checks it before swapping the runner for a changed enrolments map, so a mid-run engine is never orphaned.
func (*EnrolmentRunner) Complete ¶
func (r *EnrolmentRunner) Complete()
Complete signals that the user is done with enrolments.
func (*EnrolmentRunner) GetState ¶
func (r *EnrolmentRunner) GetState(key string) (EnrolStateInfo, error)
GetState returns the state of a single enrolment.
func (*EnrolmentRunner) HasPending ¶
func (r *EnrolmentRunner) HasPending() bool
HasPending returns true if any enrolment is pending, running, or failed.
func (*EnrolmentRunner) MarkComplete ¶
func (r *EnrolmentRunner) MarkComplete(key string)
MarkComplete sets an enrolment to "complete" (e.g. already in Vault).
func (*EnrolmentRunner) Reset ¶
func (r *EnrolmentRunner) Reset(key string) error
Reset returns a complete or skipped enrolment to pending so it can be re-run. Returns an error if the key is not found, the enrolment is running, or it is in a state that cannot be reset (e.g. pending or failed).
func (*EnrolmentRunner) Skip ¶
func (r *EnrolmentRunner) Skip(key string) error
Skip marks an enrolment as skipped. Returns error if key not found or running.
func (*EnrolmentRunner) Start ¶
func (r *EnrolmentRunner) Start(ctx context.Context, key string, vc *vault.Client, kvMount, userPrefix, username string, promptSecret PromptSecretFunc) error
Start launches an enrolment engine in a background goroutine. Returns error if the key is unknown, the enrolment is already running, or another enrolment is currently running (only one may run at a time because the secret prompt mechanism is global).
func (*EnrolmentRunner) States ¶
func (r *EnrolmentRunner) States() []EnrolStateInfo
States returns the current state of all enrolments in stable order.
func (*EnrolmentRunner) Wait ¶
func (r *EnrolmentRunner) Wait()
Wait blocks until Complete() is called. Returns immediately if there are no pending enrolments.
func (*EnrolmentRunner) WaitForKey ¶
func (r *EnrolmentRunner) WaitForKey(key string)
WaitForKey blocks until the given enrolment is no longer "running". Returns immediately if the enrolment is not found or not running.
type OAuthManager ¶
type OAuthManager struct {
// contains filtered or unexported fields
}
OAuthManager manages OAuth2 state parameters for CSRF protection.
func NewOAuthManager ¶
func NewOAuthManager() *OAuthManager
NewOAuthManager creates a new OAuth state manager.
func (*OAuthManager) CreateState ¶
func (om *OAuthManager) CreateState(ruleName string) (string, error)
CreateState generates a cryptographically random state parameter for an OAuth flow.
func (*OAuthManager) ValidateState ¶
func (om *OAuthManager) ValidateState(state string) (string, bool)
ValidateState checks and consumes a state parameter. Returns the rule name and true if valid.
type PromptSecretFunc ¶
PromptSecretFunc is the function signature for web-based secret prompting.
type Server ¶
type Server struct {
// contains filtered or unexported fields
}
Server is the web UI HTTP server.
func NewServer ¶
func NewServer(sc ServerConfig) (*Server, error)
NewServer creates a new web server.
func (*Server) EnrolPromptSecret ¶
EnrolPromptSecret implements a web-based PromptSecret. It sets the pending prompt state and blocks until the frontend submits a value via the /api/v1/enrol/secret endpoint, or the context is cancelled.
func (*Server) ForceReauth ¶
func (s *Server) ForceReauth()
ForceReauth clears the in-memory Vault token so /api/v1/status reports authenticated=false on the next poll. The SPA is configured to redirect to the login screen whenever that flag flips, which effectively invalidates any browser session that was sitting on a stale "logged-in" view while the underlying token rotted. The token file on disk is intentionally left in place — operators may have written a fresh token out-of-band that the daemon can pick up without involving the user.
Also resets the authDone channel so a fresh call to WaitForAuth (e.g. from a re-entry into the startup auth flow) will block until the user completes the new login.
func (*Server) InitEnrolments ¶
InitEnrolments sets up the enrolment runner for web-driven enrolment. It checks Vault for already-completed enrolments and marks them as such.
func (*Server) InitialSyncComplete ¶
InitialSyncComplete reports whether MarkInitialSyncComplete has fired. Exposed for tests and the /readyz handler.
func (*Server) MarkInitialSyncComplete ¶
func (s *Server) MarkInitialSyncComplete()
MarkInitialSyncComplete flips the readiness flag. The daemon calls this once engine.RunOnce returns at startup (success or per-rule failure — partial progress is still "we've tried"). /readyz only reports ready once this has fired AND the daemon holds a Vault token, so a k8s readinessProbe or the OTel httpcheckreceiver doesn't observe a green daemon before secrets exist on disk.
func (*Server) SetReauthGate ¶ added in v0.30.0
SetReauthGate wires the daemon's token lifecycle manager so /api/v1/token can decline to hand out a token the daemon already knows is dead. Safe to call while requests are in flight; the daemon calls it once, after the lifecycle manager is constructed.
func (*Server) Start ¶
Start begins serving HTTP on every configured listener. It signals WaitReady once all of them are bound, or sends the bind error so the caller can fail fast.
There may be one or two: the loopback TCP listener (web.enabled) and the per-user Unix socket (api.enabled). They share one http.Server and one mux, so a request means the same thing whichever way it arrived — the surfaces differ in who can reach them, not in what they do.
func (*Server) UpdateDynamicConfig ¶ added in v0.22.0
func (s *Server) UpdateDynamicConfig(rules []config.Rule, syncCfg config.SyncConfig)
UpdateDynamicConfig swaps the rule and sync sections the web server serves. Called by the daemon's config-refresh loop when the remote overlay (or an edited local config) changes them at runtime, so the dashboard, the rules API, and the Effective Configuration download all reflect the live state.
func (*Server) UpdateEnrolments ¶ added in v0.22.0
UpdateEnrolments swaps the web enrolment runner for a changed enrolments map at runtime. It refuses (returning false) while an enrolment is mid-run, because InitEnrolments replaces the runner wholesale and would orphan the running engine's progress — the caller retries on its next refresh tick. The check-then-swap is not atomic with a concurrent start, but the refresh cadence makes that window academic and the consequence is a re-runnable enrolment, not corruption.
func (*Server) WaitForAuth ¶
WaitForAuth blocks until authentication completes or the context is cancelled.
func (*Server) WaitForEnrolments ¶
func (s *Server) WaitForEnrolments()
WaitForEnrolments blocks until the user completes the enrolment page. Returns immediately if there are no pending enrolments or no runner.
type ServerConfig ¶
type ServerConfig struct {
WebCfg config.WebConfig
VaultCfg config.VaultConfig
SyncCfg config.SyncConfig
ObsCfg config.ObservabilityConfig
Rules []config.Rule
Vault *vault.Client
Engine *internalsync.Engine
// Agent, when non-nil, exposes the SSH agent status on /api/v1/status.
Agent agentStatusProvider
// AgentCfg is the loaded agent configuration. It is the section the
// config-download endpoint re-emits, so it round-trips through the same
// YAML/.reg renderers as every other section even when the daemon loaded
// its config from a Windows GPO.
AgentCfg config.AgentConfig
// APICfg is the loaded local-API-socket configuration, retained for the
// config-download round-trip (like AgentCfg).
APICfg config.APIConfig
// APISocketPath is the resolved path for the local API socket. Empty
// serves no socket. The caller resolves it (config.APISocketPath) so this
// package holds no path-defaulting policy; when it is set, Start binds it
// with owner-only permissions in addition to — or instead of — the
// loopback TCP listener that WebCfg.Enabled controls.
APISocketPath string
// RemoteCfg is the local-only remote_config section, retained for the
// config-download round-trip (like AgentCfg).
RemoteCfg config.RemoteConfig
// RemoteStatus, when non-nil, reports the remote-config overlay's last
// fetch outcome; surfaced on /api/v1/status alongside the per-rule sync
// state. It may return nil before the first fetch.
RemoteStatus func() *remoteconfig.Status
Username string
TokenFilePath string
Version string
// OpenBrowser, when non-nil, overrides how the remote-browse endpoint
// launches URLs in this host's default browser (tests inject a fake).
// Nil selects the real browser.OpenURL.
OpenBrowser func(string) error
// SendNotification, when non-nil, overrides how the remote-notify
// endpoint delivers desktop notifications (tests inject a fake). Nil
// selects the real notify.Send.
SendNotification notify.Notifier
// SetClipboard, when non-nil, overrides how the remote-clipboard
// endpoint writes to this host's clipboard (tests inject a fake). Nil
// selects the real clipboard.Set.
SetClipboard clipboard.Setter
}
ServerConfig holds all dependencies for the web server.