Documentation
¶
Overview ¶
Package httpgw provides the HTTP Gateway forward proxy handler. It intercepts HTTP requests, normalizes them to CanonicalAction, runs the canonical security chain (policy, outbound, scan), and forwards allowed requests to their original destination.
Package httpgw provides the HTTP Gateway handler including reverse proxy support. The reverse proxy routes incoming requests to configured upstream targets based on path prefix matching, running the canonical security chain before forwarding.
Package httpgw provides the HTTP Gateway forward proxy handler.
Index ¶
- Constants
- func NewAuthMiddleware(cfg AuthConfig) func(http.Handler) http.Handler
- type AuthConfig
- type CAConfig
- type CAManager
- type CertCache
- type Handler
- func (h *Handler) DisableSSRFProtection()
- func (h *Handler) Routes() http.Handler
- func (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request)
- func (h *Handler) SetResponseScanner(scanner *action.ResponseScanner, modeGetter func() action.ScanMode, ...)
- func (h *Handler) SetReverseProxy(rp *ReverseProxy)
- func (h *Handler) SetTimeout(d time.Duration)
- func (h *Handler) SetWebSocketProxy(ws *WebSocketProxy)
- type ReverseProxy
- func (rp *ReverseProxy) Forward(w http.ResponseWriter, r *http.Request, target *UpstreamTarget)
- func (rp *ReverseProxy) Match(path string) *UpstreamTarget
- func (rp *ReverseProxy) SetResponseScanner(scanner *action.ResponseScanner, modeGetter func() action.ScanMode, ...)
- func (rp *ReverseProxy) SetTargets(targets []UpstreamTarget)
- func (rp *ReverseProxy) SetTimeout(d time.Duration)
- func (rp *ReverseProxy) Targets() []UpstreamTarget
- type TLSInspector
- type TLSInspectorConfig
- type UpstreamTarget
- type WebSocketProxy
Constants ¶
const ( // ContextKeyIdentity is the context key for the authenticated identity. ContextKeyIdentity contextKey = "httpgw_identity" // ContextKeyAPIKey is the context key for the raw API key. ContextKeyAPIKey contextKey = "httpgw_api_key" )
Variables ¶
This section is empty.
Functions ¶
func NewAuthMiddleware ¶
func NewAuthMiddleware(cfg AuthConfig) func(http.Handler) http.Handler
NewAuthMiddleware creates an HTTP middleware that authenticates HTTP Gateway requests. It extracts an API key from one of three sources (in priority order):
- Proxy-Authorization: Bearer <key> (standard forward proxy auth)
- Authorization: Bearer <key> (standard HTTP auth fallback)
- X-SentinelGate-Key: <key> (alternative for restricted clients)
On success, the middleware stores the authenticated identity in the request context (ContextKeyIdentity) for the handler to read.
On failure, it returns HTTP 407 Proxy Authentication Required.
In dev mode, authentication is skipped and a dev identity is used.
Types ¶
type AuthConfig ¶
type AuthConfig struct {
// APIKeyService validates API keys against the auth store.
APIKeyService *auth.APIKeyService
// DevMode skips authentication when true (uses dev identity).
DevMode bool
// Logger for authentication events.
Logger *slog.Logger
}
AuthConfig configures the HTTP Gateway authentication middleware.
type CAConfig ¶
type CAConfig struct {
// CertFile is the path to the CA certificate PEM file.
// Default: "~/.sentinelgate/ca-cert.pem".
CertFile string
// KeyFile is the path to the CA private key PEM file.
// Default: "~/.sentinelgate/ca-key.pem".
KeyFile string
// Organization is the subject organization for the CA certificate.
// Default: "SentinelGate TLS Inspection".
Organization string
// ValidityYears is how many years the CA certificate is valid.
// Default: 10.
ValidityYears int
}
CAConfig holds the configuration for the CA manager.
type CAManager ¶
type CAManager struct {
// contains filtered or unexported fields
}
CAManager manages a CA keypair for TLS inspection. It auto-generates an ECDSA P-256 CA on first use, persists it to disk, and loads it from disk on subsequent starts. It can generate per-domain leaf certificates signed by the CA for MITM decryption.
func NewCAManager ¶
NewCAManager creates a new CAManager. If both CertFile and KeyFile exist on disk, they are loaded. If neither exists, a new CA keypair is generated and persisted. If only one file exists, an error is returned (inconsistent state).
func (*CAManager) CACertPEM ¶
CACertPEM returns the PEM-encoded CA certificate. Clients should add this to their trust pool to accept leaf certs generated by this CA.
func (*CAManager) CACertPath ¶
CACertPath returns the file path to the CA certificate.
func (*CAManager) GenerateCert ¶
func (cm *CAManager) GenerateCert(domain string) (*tls.Certificate, error)
GenerateCert creates a new TLS leaf certificate for the given domain, signed by the CA. The returned tls.Certificate contains the leaf cert, its private key, and the CA cert in the chain.
type CertCache ¶
type CertCache struct {
// contains filtered or unexported fields
}
CertCache is a thread-safe per-domain TLS certificate cache. On cache miss it delegates to a CAManager to generate a new leaf cert. Entries expire after the configured TTL, at which point the next access triggers a fresh certificate generation.
The RWMutex pattern follows the existing dns_resolver.go approach: read lock for fast-path cache hits, write lock only on cache miss.
func NewCertCache ¶
NewCertCache creates a new CertCache backed by the given CAManager. The ttl controls how long cached certificates remain valid before regeneration on the next access.
func (*CertCache) Clear ¶
func (cc *CertCache) Clear()
Clear removes all cached certificates. Useful for CA rotation.
type Handler ¶
type Handler struct {
// contains filtered or unexported fields
}
Handler is the HTTP Gateway handler supporting both forward and reverse proxy modes. It normalizes incoming HTTP requests to CanonicalAction, runs them through the ActionInterceptor security chain, and forwards allowed requests upstream. In reverse proxy mode, requests matching upstream targets are forwarded to the configured upstream after the security chain approves the request.
func NewHandler ¶
func NewHandler(chain action.ActionInterceptor, logger *slog.Logger) *Handler
NewHandler creates a new HTTP Gateway handler. The chain is the ActionInterceptor that processes the security pipeline (policy -> outbound -> response scan -> passthrough).
func (*Handler) DisableSSRFProtection ¶
func (h *Handler) DisableSSRFProtection()
DisableSSRFProtection removes the SSRF-safe dialer from the HTTP client. This is intended ONLY for testing and dev mode where forward proxy targets may be on localhost.
func (*Handler) Routes ¶
Routes returns the handler itself (Handler implements http.Handler via ServeHTTP).
func (*Handler) ServeHTTP ¶
func (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request)
ServeHTTP handles an incoming HTTP request through the gateway. Flow: check reverse proxy -> normalize -> identity from context -> chain -> forward or error.
In reverse proxy mode, if the request path matches an upstream target, the Destination is overridden with the actual upstream URL so that outbound rules and CEL dest_* variables evaluate against the real target.
func (*Handler) SetResponseScanner ¶
func (h *Handler) SetResponseScanner(scanner *action.ResponseScanner, modeGetter func() action.ScanMode, enabledGetter func() bool)
SetResponseScanner attaches a response scanner for scanning HTTP response bodies before returning them to the client. The modeGetter and enabledGetter closures provide thread-safe access to the current scan mode and enabled state.
func (*Handler) SetReverseProxy ¶
func (h *Handler) SetReverseProxy(rp *ReverseProxy)
SetReverseProxy enables reverse proxy mode by attaching a ReverseProxy. When set, requests matching upstream targets are forwarded to the configured upstream instead of using forward proxy mode.
func (*Handler) SetTimeout ¶
SetTimeout configures the HTTP client timeout for forwarding requests.
func (*Handler) SetWebSocketProxy ¶
func (h *Handler) SetWebSocketProxy(ws *WebSocketProxy)
SetWebSocketProxy attaches a WebSocketProxy for handling WebSocket upgrade requests. When set, requests with Connection: Upgrade and Upgrade: websocket headers are routed to the WebSocket proxy after passing through the security chain.
type ReverseProxy ¶
type ReverseProxy struct {
// contains filtered or unexported fields
}
ReverseProxy manages upstream targets and forwards requests to them. It uses an atomic pointer for lock-free reads of the target list, matching the pattern used by OutboundInterceptor.SetRules.
func NewReverseProxy ¶
func NewReverseProxy(logger *slog.Logger) *ReverseProxy
NewReverseProxy creates a new ReverseProxy with sensible HTTP client defaults.
func (*ReverseProxy) Forward ¶
func (rp *ReverseProxy) Forward(w http.ResponseWriter, r *http.Request, target *UpstreamTarget)
Forward sends the request to the upstream target and copies the response back to the client. On error, it returns a 502 Bad Gateway JSON response.
func (*ReverseProxy) Match ¶
func (rp *ReverseProxy) Match(path string) *UpstreamTarget
Match finds the most specific (longest PathPrefix) matching enabled target for the given path. Returns nil if no target matches.
func (*ReverseProxy) SetResponseScanner ¶
func (rp *ReverseProxy) SetResponseScanner(scanner *action.ResponseScanner, modeGetter func() action.ScanMode, enabledGetter func() bool)
SetResponseScanner attaches a response scanner for scanning reverse proxy response bodies before returning them to the client.
func (*ReverseProxy) SetTargets ¶
func (rp *ReverseProxy) SetTargets(targets []UpstreamTarget)
SetTargets stores the upstream targets via atomic pointer for lock-free reads.
func (*ReverseProxy) SetTimeout ¶
func (rp *ReverseProxy) SetTimeout(d time.Duration)
SetTimeout updates the HTTP client timeout for upstream requests.
func (*ReverseProxy) Targets ¶
func (rp *ReverseProxy) Targets() []UpstreamTarget
Targets returns a copy of the current upstream targets. Thread-safe for concurrent access via atomic pointer.
type TLSInspector ¶
type TLSInspector struct {
// contains filtered or unexported fields
}
TLSInspector intercepts CONNECT requests for TLS inspection. When TLS inspection is enabled and the domain is not bypassed, the CONNECT tunnel is hijacked, a TLS handshake is performed using a certificate signed by the SentinelGate CA, and the decrypted HTTP request is served through the security chain.
When TLS inspection is disabled or the domain is bypassed, the CONNECT request is tunneled as a raw TCP relay.
Non-CONNECT requests are passed through to the handler directly.
func NewTLSInspector ¶
func NewTLSInspector(config TLSInspectorConfig) *TLSInspector
NewTLSInspector creates a new TLS inspector with the given configuration. The bypass list is parsed into exact matches and glob patterns.
func (*TLSInspector) BypassList ¶
func (ti *TLSInspector) BypassList() []string
BypassList returns a copy of the current bypass domain list. Thread-safe for concurrent access from admin API.
func (*TLSInspector) IsEnabled ¶
func (ti *TLSInspector) IsEnabled() bool
IsEnabled returns whether TLS inspection is active.
func (*TLSInspector) ServeHTTP ¶
func (ti *TLSInspector) ServeHTTP(w http.ResponseWriter, r *http.Request)
ServeHTTP routes requests based on method. CONNECT requests are handled via handleConnect (tunnel or intercept). All other requests are delegated to the inner handler directly.
func (*TLSInspector) SetBypassList ¶
func (ti *TLSInspector) SetBypassList(domains []string)
SetBypassList atomically updates the bypass set and glob patterns. Thread-safe for concurrent reads during request handling and writes from the admin API.
func (*TLSInspector) SetEnabled ¶
func (ti *TLSInspector) SetEnabled(enabled bool)
SetEnabled enables or disables TLS inspection at runtime. Thread-safe for concurrent reads during request handling and writes from the admin API.
type TLSInspectorConfig ¶
type TLSInspectorConfig struct {
// Enabled controls whether TLS inspection is active (default false).
Enabled bool
// BypassList contains domain patterns to never inspect.
// Supports exact match (e.g. "example.com") and glob patterns (e.g. "*.google.com").
BypassList []string
// CertCache provides per-domain TLS certificates signed by the SentinelGate CA.
CertCache *CertCache
// Handler is the HTTP handler (auth + gateway handler) to serve decrypted requests through.
Handler http.Handler
// Logger for TLS inspection events.
Logger *slog.Logger
}
TLSInspectorConfig holds configuration for the TLS inspector.
type UpstreamTarget ¶
type UpstreamTarget struct {
// ID uniquely identifies this target.
ID string
// Name is the human-readable display name.
Name string
// PathPrefix is the URL path prefix to match (e.g., "/api/openai/").
PathPrefix string
// Upstream is the target URL base (e.g., "https://api.openai.com").
Upstream string
// StripPrefix controls whether PathPrefix is stripped before forwarding.
StripPrefix bool
// Headers are additional headers to inject into proxied requests.
Headers map[string]string
// Enabled controls whether this target is active.
Enabled bool
}
UpstreamTarget represents a configured reverse proxy upstream target. Requests matching the PathPrefix are forwarded to the Upstream URL after passing through the security chain.
type WebSocketProxy ¶
type WebSocketProxy struct {
// contains filtered or unexported fields
}
WebSocketProxy handles WebSocket upgrade requests by hijacking the client connection, dialing the upstream, performing the handshake, and relaying frames bidirectionally with per-frame content inspection.
func NewWebSocketProxy ¶
func NewWebSocketProxy( scanner *action.ResponseScanner, modeGetter func() action.ScanMode, enabledGetter func() bool, logger *slog.Logger, ) *WebSocketProxy
NewWebSocketProxy creates a new WebSocketProxy.
func (*WebSocketProxy) Proxy ¶
func (ws *WebSocketProxy) Proxy(w http.ResponseWriter, r *http.Request, destURL string) error
Proxy upgrades the client connection to WebSocket and relays frames bidirectionally to the upstream at destURL. It hijacks the incoming connection, dials the upstream, forwards the WebSocket upgrade handshake, then starts two goroutines for bidirectional frame relay with inspection.