Documentation
¶
Index ¶
- Constants
- func AuthorizeAction(ctx context.Context, k8sClient kubernetes.Interface, auditLogger *AuditLogger, ...) error
- func AuthorizePodLogs(ctx context.Context, k8sClient kubernetes.Interface, auditLogger *AuditLogger, ...) error
- func CRDEnvToProto(crd *v1alpha1.Environment) (*pb.Environment, error)
- func CRDPgToProto(crd *v1alpha1.PreviewGroup) (*pb.PreviewGroup, error)
- func GetBroadcasterMetrics() streaming.BroadcasterMetrics
- func ListenAndServeTunnelProxy(tm *TunnelManager, port int, logger *slog.Logger) error
- func NewAuthInterceptor(authAttempts *prometheus.CounterVec) connect.Interceptor
- func NewAuthMetrics() *auth.AuthMetrics
- func NewAuthService(k8s kubernetes.Interface, logger *slog.Logger, auditLogger *AuditLogger) divergev1alpha1connect.AuthServiceHandler
- func NewClusterService(c client.Client, k8s kubernetes.Interface, logger *slog.Logger, ...) divergev1alpha1connect.ClusterServiceHandler
- func NewEnvironmentService(c client.Client, k8s kubernetes.Interface, ...) divergev1alpha1connect.EnvironmentServiceHandler
- func NewMetricsInterceptor() connect.Interceptor
- func NewPreviewGroupService(c client.Client, k8s kubernetes.Interface, ...) divergev1alpha1connect.PreviewGroupServiceHandler
- func NewTunnelProxyServer(tm *TunnelManager, port int, logger *slog.Logger) *http.Server
- func ProtoEnvToCRD(proto *pb.Environment) (*v1alpha1.Environment, error)
- func ProtoPgToCRD(proto *pb.PreviewGroup) (*v1alpha1.PreviewGroup, error)
- func ProtocolTelemetryMiddleware(next http.Handler) http.Handler
- func ResolveSecureCookies(mode string, tlsEnabled bool, oidcRedirectURL string) (bool, error)
- func SanitizeK8sError(logger *slog.Logger, err error) error
- func SetStreamLimiterMax(max int)
- func ValidateDNS1123Label(value, field string) error
- func ValidateNamespaceMatch(requestNS, resourceNS string) error
- type AuditLogger
- func (a *AuditLogger) LogAuth(ctx context.Context, event string, user *auth.UserInfo, r *http.Request, ...)
- func (a *AuditLogger) LogAuthz(ctx context.Context, event string, user *auth.UserInfo, ...)
- func (a *AuditLogger) LogMutation(ctx context.Context, event string, resourceType, name, namespace string)
- type AuthService
- func (s *AuthService) GetCurrentUser(ctx context.Context, req *connect.Request[pb.GetCurrentUserRequest]) (*connect.Response[pb.GetCurrentUserResponse], error)
- func (s *AuthService) ListPermissions(ctx context.Context, req *connect.Request[pb.ListPermissionsRequest]) (*connect.Response[pb.ListPermissionsResponse], error)
- type ClusterService
- type CookiePolicy
- type CookiePolicyResolver
- type EnvironmentService
- func (s *EnvironmentService) CreateEnvironment(ctx context.Context, req *connect.Request[pb.CreateEnvironmentRequest]) (*connect.Response[pb.CreateEnvironmentResponse], error)
- func (s *EnvironmentService) DeleteEnvironment(ctx context.Context, req *connect.Request[pb.DeleteEnvironmentRequest]) (*connect.Response[pb.DeleteEnvironmentResponse], error)
- func (s *EnvironmentService) ExtendTTL(ctx context.Context, req *connect.Request[pb.ExtendTTLRequest]) (*connect.Response[pb.ExtendTTLResponse], error)
- func (s *EnvironmentService) GetEnvironment(ctx context.Context, req *connect.Request[pb.GetEnvironmentRequest]) (*connect.Response[pb.GetEnvironmentResponse], error)
- func (s *EnvironmentService) ListEnvironments(ctx context.Context, req *connect.Request[pb.ListEnvironmentsRequest]) (*connect.Response[pb.ListEnvironmentsResponse], error)
- func (s *EnvironmentService) ListHookJobs(ctx context.Context, req *connect.Request[pb.ListHookJobsRequest]) (*connect.Response[pb.ListHookJobsResponse], error)
- func (s *EnvironmentService) RetryHook(ctx context.Context, req *connect.Request[pb.RetryHookRequest]) (*connect.Response[pb.RetryHookResponse], error)
- func (s *EnvironmentService) StreamLogs(ctx context.Context, req *connect.Request[pb.StreamLogsRequest], ...) error
- func (s *EnvironmentService) UpdateEnvironment(ctx context.Context, req *connect.Request[pb.UpdateEnvironmentRequest]) (*connect.Response[pb.UpdateEnvironmentResponse], error)
- func (s *EnvironmentService) WatchEnvironments(ctx context.Context, req *connect.Request[pb.WatchEnvironmentsRequest], ...) error
- type OIDCHandler
- func (h *OIDCHandler) HandleCallback(w http.ResponseWriter, r *http.Request)
- func (h *OIDCHandler) HandleConfig(w http.ResponseWriter, r *http.Request)
- func (h *OIDCHandler) HandleLogin(w http.ResponseWriter, r *http.Request)
- func (h *OIDCHandler) HandleLogout(w http.ResponseWriter, r *http.Request)
- func (h *OIDCHandler) RegisterRoutes(mux *http.ServeMux)
- type OIDCHandlerConfig
- type PreviewGroupService
- func (s *PreviewGroupService) CreatePreviewGroup(ctx context.Context, req *connect.Request[pb.CreatePreviewGroupRequest]) (*connect.Response[pb.CreatePreviewGroupResponse], error)
- func (s *PreviewGroupService) DeletePreviewGroup(ctx context.Context, req *connect.Request[pb.DeletePreviewGroupRequest]) (*connect.Response[pb.DeletePreviewGroupResponse], error)
- func (s *PreviewGroupService) GetPreviewGroup(ctx context.Context, req *connect.Request[pb.GetPreviewGroupRequest]) (*connect.Response[pb.GetPreviewGroupResponse], error)
- func (s *PreviewGroupService) ListPreviewGroups(ctx context.Context, req *connect.Request[pb.ListPreviewGroupsRequest]) (*connect.Response[pb.ListPreviewGroupsResponse], error)
- func (s *PreviewGroupService) UpdatePreviewGroup(ctx context.Context, req *connect.Request[pb.UpdatePreviewGroupRequest]) (*connect.Response[pb.UpdatePreviewGroupResponse], error)
- func (s *PreviewGroupService) WatchPreviewGroups(ctx context.Context, req *connect.Request[pb.WatchPreviewGroupsRequest], ...) error
- type ServeMuxConfig
- type StreamLimiter
- type StreamLimiterMetrics
- type TunnelGC
- type TunnelLease
- func (tl *TunnelLease) Acquire(ctx context.Context, namespace, previewID, tunnelID string) (previousHolder string, err error)
- func (tl *TunnelLease) Release(ctx context.Context, namespace, previewID, tunnelID string)
- func (tl *TunnelLease) Renew(ctx context.Context, namespace, previewID, tunnelID string) bool
- type TunnelManager
- func (tm *TunnelManager) ForwardRequest(ctx context.Context, previewID string, req *pb.TunnelHTTPRequest) (*pb.TunnelHTTPResponse, error)
- func (tm *TunnelManager) HasTunnel(previewID string) bool
- func (tm *TunnelManager) NewTunnelProxyHandler() http.Handler
- func (tm *TunnelManager) StartGC(ctx context.Context, namespaces []string)
- func (tm *TunnelManager) Tunnel(ctx context.Context, ...) error
Constants ¶
const ( SecureCookiesAuto = "auto" SecureCookiesAlways = "true" SecureCookiesDisabled = "false" )
Secure cookie modes for the --secure-cookies flag.
const MaxStreamLogsPods = 5
MaxStreamLogsPods is the maximum number of pod log streams per StreamLogs request.
const (
// tunnelProxyPort is the dedicated port for tunnel proxy (no auth).
TunnelProxyPort = 8081
)
Variables ¶
This section is empty.
Functions ¶
func AuthorizeAction ¶ added in v0.6.0
func AuthorizeAction(ctx context.Context, k8sClient kubernetes.Interface, auditLogger *AuditLogger, verb, namespace, resource string) error
AuthorizeAction performs a Kubernetes SubjectAccessReview for the authenticated user against a Diverge resource. The user's identity is extracted from the request context (set by the auth middleware).
func AuthorizePodLogs ¶ added in v0.6.0
func AuthorizePodLogs(ctx context.Context, k8sClient kubernetes.Interface, auditLogger *AuditLogger, namespace string) error
AuthorizePodLogs performs a SubjectAccessReview for pods/log access. StreamLogs requires both environment read AND pod log read permissions.
func CRDEnvToProto ¶ added in v0.7.0
func CRDEnvToProto(crd *v1alpha1.Environment) (*pb.Environment, error)
CRDEnvToProto maps a CRD Environment to the protobuf type.
func CRDPgToProto ¶ added in v0.7.0
func CRDPgToProto(crd *v1alpha1.PreviewGroup) (*pb.PreviewGroup, error)
CRDPgToProto maps a CRD PreviewGroup to the protobuf type.
func GetBroadcasterMetrics ¶ added in v0.5.0
func GetBroadcasterMetrics() streaming.BroadcasterMetrics
func ListenAndServeTunnelProxy ¶ added in v0.7.0
func ListenAndServeTunnelProxy(tm *TunnelManager, port int, logger *slog.Logger) error
ListenAndServeTunnelProxy starts the tunnel proxy server on the given port.
func NewAuthInterceptor ¶
func NewAuthInterceptor(authAttempts *prometheus.CounterVec) connect.Interceptor
func NewAuthMetrics ¶ added in v0.6.0
func NewAuthMetrics() *auth.AuthMetrics
NewAuthMetrics returns the auth metrics wired to the auth middleware's expected types.
func NewAuthService ¶
func NewAuthService(k8s kubernetes.Interface, logger *slog.Logger, auditLogger *AuditLogger) divergev1alpha1connect.AuthServiceHandler
func NewClusterService ¶
func NewClusterService(c client.Client, k8s kubernetes.Interface, logger *slog.Logger, auditLogger *AuditLogger, version string) divergev1alpha1connect.ClusterServiceHandler
NewClusterService creates a ClusterService with the given version string. Pass the build-injected version (e.g. from ldflags) for accurate reporting.
func NewEnvironmentService ¶
func NewEnvironmentService(c client.Client, k8s kubernetes.Interface, informerMgr *streaming.InformerManager, logStreamer *streaming.LogStreamer, limiter *StreamLimiter, logger *slog.Logger, audit *AuditLogger) divergev1alpha1connect.EnvironmentServiceHandler
func NewMetricsInterceptor ¶ added in v0.5.0
func NewMetricsInterceptor() connect.Interceptor
func NewPreviewGroupService ¶
func NewPreviewGroupService(c client.Client, k8s kubernetes.Interface, informerMgr *streaming.InformerManager, limiter *StreamLimiter, logger *slog.Logger, audit *AuditLogger) divergev1alpha1connect.PreviewGroupServiceHandler
func NewTunnelProxyServer ¶ added in v0.7.0
NewTunnelProxyServer creates a dedicated HTTP server for the tunnel proxy. P0 #3: This runs on a SEPARATE port from the RPC server. P0 #6: NO auth middleware — cluster-internal traffic only. Host-header validation prevents open proxy abuse.
func ProtoEnvToCRD ¶ added in v0.7.0
func ProtoEnvToCRD(proto *pb.Environment) (*v1alpha1.Environment, error)
ProtoEnvToCRD maps a protobuf Environment to the CRD type.
func ProtoPgToCRD ¶ added in v0.7.0
func ProtoPgToCRD(proto *pb.PreviewGroup) (*v1alpha1.PreviewGroup, error)
ProtoPgToCRD maps a protobuf PreviewGroup to the CRD type.
func ProtocolTelemetryMiddleware ¶ added in v0.7.0
ProtocolTelemetryMiddleware records the ConnectRPC wire protocol and client SDK for every request. Designed for <1μs overhead per request.
func ResolveSecureCookies ¶ added in v0.10.0
ResolveSecureCookies decides whether session cookies get the Secure flag.
In auto mode the server is Secure when it terminates TLS itself, and also when the OIDC redirect URL — the public address a browser is sent back to — is https. The latter is what covers the common deployment where an ingress or gateway terminates TLS and forwards cleartext, which the server would otherwise read as plain HTTP and issue a non-Secure cookie for an HTTPS-only site.
The redirect URL is used rather than a per-request X-Forwarded-Proto header because it is operator-supplied configuration rather than caller-controlled input, so it cannot be spoofed by a client.
func SanitizeK8sError ¶ added in v0.6.0
SanitizeK8sError maps Kubernetes API errors to safe Connect error codes. The raw K8s error is logged server-side but never returned to the client. Returns nil when err is nil.
func SetStreamLimiterMax ¶ added in v0.7.0
func SetStreamLimiterMax(max int)
SetStreamLimiterMax sets the static capacity gauge (called once at startup).
func ValidateDNS1123Label ¶ added in v0.6.0
ValidateDNS1123Label checks that a string is a valid DNS-1123 label.
func ValidateNamespaceMatch ¶ added in v0.6.0
ValidateNamespaceMatch ensures that the namespace in the request wrapper matches the namespace in the resource, preventing RBAC bypass where a user authorized for namespace "foo" creates a resource in namespace "bar". Both requestNS and resourceNS must be non-empty for comparison. Callers must ensure requestNS is defaulted before calling this function.
Types ¶
type AuditLogger ¶ added in v0.6.0
type AuditLogger struct {
// contains filtered or unexported fields
}
AuditLogger emits structured audit events for authentication, authorization, and resource mutations. All events are JSON-formatted via slog for compatibility with standard log aggregators.
func NewAuditLogger ¶ added in v0.6.0
func NewAuditLogger(logger *slog.Logger) *AuditLogger
NewAuditLogger creates an audit logger wrapping the given structured logger.
func (*AuditLogger) LogAuth ¶ added in v0.6.0
func (a *AuditLogger) LogAuth(ctx context.Context, event string, user *auth.UserInfo, r *http.Request, attrs ...slog.Attr)
LogAuth logs authentication events (success, failure, cache hit).
func (*AuditLogger) LogAuthz ¶ added in v0.6.0
func (a *AuditLogger) LogAuthz(ctx context.Context, event string, user *auth.UserInfo, verb, resource, namespace string)
LogAuthz logs authorization events (denied, error).
func (*AuditLogger) LogMutation ¶ added in v0.6.0
func (a *AuditLogger) LogMutation(ctx context.Context, event string, resourceType, name, namespace string)
LogMutation logs resource mutation events (create, update, delete).
type AuthService ¶
type AuthService struct {
// contains filtered or unexported fields
}
func (*AuthService) GetCurrentUser ¶
func (s *AuthService) GetCurrentUser(ctx context.Context, req *connect.Request[pb.GetCurrentUserRequest]) (*connect.Response[pb.GetCurrentUserResponse], error)
func (*AuthService) ListPermissions ¶
func (s *AuthService) ListPermissions(ctx context.Context, req *connect.Request[pb.ListPermissionsRequest]) (*connect.Response[pb.ListPermissionsResponse], error)
type ClusterService ¶
type ClusterService struct {
// contains filtered or unexported fields
}
func (*ClusterService) GetClusterInfo ¶
func (s *ClusterService) GetClusterInfo(ctx context.Context, req *connect.Request[pb.GetClusterInfoRequest]) (*connect.Response[pb.GetClusterInfoResponse], error)
type CookiePolicy ¶ added in v0.11.0
type CookiePolicy struct {
Secure bool
}
CookiePolicy defines the security settings for HTTP cookies issued by the server.
type CookiePolicyResolver ¶ added in v0.11.0
type CookiePolicyResolver struct {
Mode string // "auto", "true", "false"
TLSEnabled bool
PublicURL string // Generalized public URL (e.g. OIDC redirect URL or external base URL)
}
CookiePolicyResolver resolves the effective CookiePolicy based on operator configuration and environment signals (such as local TLS termination or public redirect URLs).
func (CookiePolicyResolver) Resolve ¶ added in v0.11.0
func (r CookiePolicyResolver) Resolve() (CookiePolicy, error)
Resolve evaluates the policy according to the configured mode and environmental signals.
In auto mode the server sets Secure when it terminates TLS itself, and also when the public URL (e.g. OIDC redirect URL) is https. The latter covers deployments where an ingress or gateway terminates TLS and forwards cleartext, which the server would otherwise read as plain HTTP and issue a non-Secure cookie.
type EnvironmentService ¶
type EnvironmentService struct {
// contains filtered or unexported fields
}
func (*EnvironmentService) CreateEnvironment ¶
func (s *EnvironmentService) CreateEnvironment(ctx context.Context, req *connect.Request[pb.CreateEnvironmentRequest]) (*connect.Response[pb.CreateEnvironmentResponse], error)
func (*EnvironmentService) DeleteEnvironment ¶
func (s *EnvironmentService) DeleteEnvironment(ctx context.Context, req *connect.Request[pb.DeleteEnvironmentRequest]) (*connect.Response[pb.DeleteEnvironmentResponse], error)
func (*EnvironmentService) ExtendTTL ¶
func (s *EnvironmentService) ExtendTTL(ctx context.Context, req *connect.Request[pb.ExtendTTLRequest]) (*connect.Response[pb.ExtendTTLResponse], error)
func (*EnvironmentService) GetEnvironment ¶
func (s *EnvironmentService) GetEnvironment(ctx context.Context, req *connect.Request[pb.GetEnvironmentRequest]) (*connect.Response[pb.GetEnvironmentResponse], error)
func (*EnvironmentService) ListEnvironments ¶
func (s *EnvironmentService) ListEnvironments(ctx context.Context, req *connect.Request[pb.ListEnvironmentsRequest]) (*connect.Response[pb.ListEnvironmentsResponse], error)
func (*EnvironmentService) ListHookJobs ¶ added in v0.7.0
func (s *EnvironmentService) ListHookJobs(ctx context.Context, req *connect.Request[pb.ListHookJobsRequest]) (*connect.Response[pb.ListHookJobsResponse], error)
ListHookJobs returns hook Jobs for an environment, sorted newest-first, with each Job's K8s status mapped to a proto phase (Pending/Running/Succeeded/Failed).
func (*EnvironmentService) RetryHook ¶ added in v0.7.0
func (s *EnvironmentService) RetryHook(ctx context.Context, req *connect.Request[pb.RetryHookRequest]) (*connect.Response[pb.RetryHookResponse], error)
RetryHook deletes the newest failed Job matching the hook type, then annotates the Environment CR with a retry marker so the controller reconciles a new run. It does NOT accept arbitrary image/command — only re-triggers from CRD spec.
func (*EnvironmentService) StreamLogs ¶
func (s *EnvironmentService) StreamLogs(ctx context.Context, req *connect.Request[pb.StreamLogsRequest], stream *connect.ServerStream[pb.StreamLogsResponse]) error
func (*EnvironmentService) UpdateEnvironment ¶
func (s *EnvironmentService) UpdateEnvironment(ctx context.Context, req *connect.Request[pb.UpdateEnvironmentRequest]) (*connect.Response[pb.UpdateEnvironmentResponse], error)
func (*EnvironmentService) WatchEnvironments ¶
func (s *EnvironmentService) WatchEnvironments(ctx context.Context, req *connect.Request[pb.WatchEnvironmentsRequest], stream *connect.ServerStream[pb.WatchEnvironmentsResponse]) error
type OIDCHandler ¶ added in v0.7.0
type OIDCHandler struct {
// contains filtered or unexported fields
}
OIDCHandler implements the OIDC authorization code flow endpoints.
func NewOIDCHandler ¶ added in v0.7.0
func NewOIDCHandler(cfg OIDCHandlerConfig) (*OIDCHandler, error)
NewOIDCHandler creates a new OIDC handler. It performs OIDC discovery on startup.
func (*OIDCHandler) HandleCallback ¶ added in v0.7.0
func (h *OIDCHandler) HandleCallback(w http.ResponseWriter, r *http.Request)
HandleCallback processes the OIDC provider's authorization code callback.
func (*OIDCHandler) HandleConfig ¶ added in v0.7.0
func (h *OIDCHandler) HandleConfig(w http.ResponseWriter, r *http.Request)
HandleConfig returns the public auth configuration for the frontend.
func (*OIDCHandler) HandleLogin ¶ added in v0.7.0
func (h *OIDCHandler) HandleLogin(w http.ResponseWriter, r *http.Request)
HandleLogin initiates the OIDC authorization code flow.
func (*OIDCHandler) HandleLogout ¶ added in v0.7.0
func (h *OIDCHandler) HandleLogout(w http.ResponseWriter, r *http.Request)
HandleLogout clears the session cookie and redirects to the login page.
func (*OIDCHandler) RegisterRoutes ¶ added in v0.7.0
func (h *OIDCHandler) RegisterRoutes(mux *http.ServeMux)
RegisterRoutes registers the OIDC auth endpoints on the given mux.
type OIDCHandlerConfig ¶ added in v0.7.0
type OIDCHandlerConfig struct {
// IssuerURL is the OIDC provider's issuer URL.
IssuerURL string
// ClientID is the OIDC client ID.
ClientID string
// ClientSecret is the OIDC client secret.
ClientSecret string
// RedirectURL is the callback URL (e.g. https://diverge.example.com/auth/callback).
RedirectURL string
// Scopes are the OIDC scopes to request.
Scopes []string
// ProviderName is the display name shown on the login button (e.g. "Okta", "Google").
ProviderName string
// SessionManager mints and verifies session JWTs.
SessionManager *auth.SessionManager
// SessionMaxAge is the cookie max age. Defaults to 24 hours.
SessionMaxAge time.Duration
// SecureCookies sets the Secure flag on cookies. Should be true in production.
SecureCookies bool
// UsernameClaim is the JWT claim used for the username.
UsernameClaim string
// GroupsClaim is the JWT claim used for group membership.
GroupsClaim string
// Logger for request logging.
Logger *slog.Logger
}
OIDCHandlerConfig configures the OIDC authentication HTTP handlers.
type PreviewGroupService ¶
type PreviewGroupService struct {
// contains filtered or unexported fields
}
func (*PreviewGroupService) CreatePreviewGroup ¶
func (s *PreviewGroupService) CreatePreviewGroup(ctx context.Context, req *connect.Request[pb.CreatePreviewGroupRequest]) (*connect.Response[pb.CreatePreviewGroupResponse], error)
func (*PreviewGroupService) DeletePreviewGroup ¶
func (s *PreviewGroupService) DeletePreviewGroup(ctx context.Context, req *connect.Request[pb.DeletePreviewGroupRequest]) (*connect.Response[pb.DeletePreviewGroupResponse], error)
func (*PreviewGroupService) GetPreviewGroup ¶
func (s *PreviewGroupService) GetPreviewGroup(ctx context.Context, req *connect.Request[pb.GetPreviewGroupRequest]) (*connect.Response[pb.GetPreviewGroupResponse], error)
func (*PreviewGroupService) ListPreviewGroups ¶
func (s *PreviewGroupService) ListPreviewGroups(ctx context.Context, req *connect.Request[pb.ListPreviewGroupsRequest]) (*connect.Response[pb.ListPreviewGroupsResponse], error)
func (*PreviewGroupService) UpdatePreviewGroup ¶ added in v0.6.0
func (s *PreviewGroupService) UpdatePreviewGroup(ctx context.Context, req *connect.Request[pb.UpdatePreviewGroupRequest]) (*connect.Response[pb.UpdatePreviewGroupResponse], error)
func (*PreviewGroupService) WatchPreviewGroups ¶
func (s *PreviewGroupService) WatchPreviewGroups(ctx context.Context, req *connect.Request[pb.WatchPreviewGroupsRequest], stream *connect.ServerStream[pb.WatchPreviewGroupsResponse]) error
type ServeMuxConfig ¶ added in v0.6.0
type ServeMuxConfig struct {
Client client.Client
K8sClient kubernetes.Interface
InformerMgr *streaming.InformerManager
LogStreamer *streaming.LogStreamer
StreamLimiter *StreamLimiter
Logger *slog.Logger
AuditLogger *AuditLogger
Version string
DashboardEnabled bool
}
ServeMuxConfig holds all dependencies for the ConnectRPC server mux.
type StreamLimiter ¶ added in v0.7.0
type StreamLimiter struct {
// contains filtered or unexported fields
}
StreamLimiter enforces per-user and global stream concurrency limits. It replaces the previous global channel semaphore to prevent a single user from exhausting all stream slots (noisy-neighbor DoS).
func NewStreamLimiter ¶ added in v0.7.0
func NewStreamLimiter(maxGlobal, maxPerUser int, metrics ...StreamLimiterMetrics) *StreamLimiter
NewStreamLimiter creates a limiter with the given global and per-user caps. Panics if maxGlobal <= 0 or maxPerUser <= 0 or maxPerUser > maxGlobal.
func (*StreamLimiter) Acquire ¶ added in v0.7.0
func (l *StreamLimiter) Acquire(ctx context.Context) (func(), error)
Acquire reserves a stream slot for the authenticated user in ctx. Returns a release function that MUST be called when the stream ends. The release function is always non-nil and safe to call multiple times.
Errors:
- CodeUnauthenticated: missing or anonymous user identity
- CodeResourceExhausted: per-user or global limit reached
func (*StreamLimiter) ActiveStreams ¶ added in v0.7.0
func (l *StreamLimiter) ActiveStreams() int
ActiveStreams returns the current global stream count (for testing/metrics).
func (*StreamLimiter) ActiveStreamsForUser ¶ added in v0.7.0
func (l *StreamLimiter) ActiveStreamsForUser(username string) int
ActiveStreamsForUser returns the active stream count for a user (for testing/metrics).
type StreamLimiterMetrics ¶ added in v0.7.0
type StreamLimiterMetrics struct {
IncActive func()
DecActive func()
Rejected func(reason string) // "per_user" or "global"
}
StreamLimiterMetrics provides decoupled metric callbacks. Matches the BroadcasterMetrics pattern to avoid coupling to Prometheus.
func GetStreamLimiterMetrics ¶ added in v0.7.0
func GetStreamLimiterMetrics() StreamLimiterMetrics
GetStreamLimiterMetrics returns callbacks wired to Prometheus collectors.
type TunnelGC ¶ added in v0.7.0
type TunnelGC struct {
// contains filtered or unexported fields
}
TunnelGC periodically garbage-collects expired tunnel K8s resources. Resources are annotated with divergedev.com/tunnel-expires (RFC3339). If the annotation is past, the resource is deleted.
func NewTunnelGC ¶ added in v0.7.0
func NewTunnelGC(k8s kubernetes.Interface, logger *slog.Logger) *TunnelGC
type TunnelLease ¶ added in v0.7.0
type TunnelLease struct {
// contains filtered or unexported fields
}
TunnelLease provides distributed fencing for tunnel ownership using K8s Leases. When multiple server replicas exist, only one can own a tunnel at a time.
func NewTunnelLease ¶ added in v0.7.0
func NewTunnelLease(k8s kubernetes.Interface, logger *slog.Logger, podName string) *TunnelLease
func (*TunnelLease) Acquire ¶ added in v0.7.0
func (tl *TunnelLease) Acquire(ctx context.Context, namespace, previewID, tunnelID string) (previousHolder string, err error)
Acquire attempts to acquire or steal the lease for a tunnel. Returns the previous holder (empty if none) and any error.
type TunnelManager ¶ added in v0.7.0
type TunnelManager struct {
// contains filtered or unexported fields
}
func NewServeMux ¶
func NewServeMux(cfg ServeMuxConfig) (*http.ServeMux, *TunnelManager)
NewServeMux creates the ConnectRPC service mux with all handlers registered. Auth is NOT applied here — it is applied at the net/http middleware layer.
func NewTunnelManager ¶ added in v0.7.0
func NewTunnelManager(crdClient client.Client, k8s kubernetes.Interface, logger *slog.Logger, audit *AuditLogger) *TunnelManager
func (*TunnelManager) ForwardRequest ¶ added in v0.7.0
func (tm *TunnelManager) ForwardRequest(ctx context.Context, previewID string, req *pb.TunnelHTTPRequest) (*pb.TunnelHTTPResponse, error)
ForwardRequest sends an HTTP request through the tunnel to the CLI. P0 #4: Supports chunked streaming — for large bodies, sends chunks via TunnelRequestChunk.
func (*TunnelManager) HasTunnel ¶ added in v0.7.0
func (tm *TunnelManager) HasTunnel(previewID string) bool
func (*TunnelManager) NewTunnelProxyHandler ¶ added in v0.7.0
func (tm *TunnelManager) NewTunnelProxyHandler() http.Handler
NewTunnelProxyHandler creates the HTTP handler for the tunnel proxy. P0 #3: This handler is served on a DEDICATED port (8081), NOT the RPC mux. P0 #6: No auth middleware — cluster-internal traffic only. Validates Host header to prevent open proxy abuse.
func (*TunnelManager) StartGC ¶ added in v0.7.0
func (tm *TunnelManager) StartGC(ctx context.Context, namespaces []string)
StartGC starts the background garbage collector for tunnel resources.
func (*TunnelManager) Tunnel ¶ added in v0.7.0
func (tm *TunnelManager) Tunnel(ctx context.Context, stream *connect.BidiStream[pb.TunnelServiceTunnelRequest, pb.TunnelServiceTunnelResponse]) error