Documentation
¶
Overview ¶
Package proxy provides a TLS-intercepting HTTP proxy for credential injection.
Security Model ¶
The proxy intercepts HTTPS traffic via CONNECT tunneling with dynamic certificate generation. It injects credentials (Authorization headers, etc.) for configured hosts without exposing raw tokens to the container.
Firewall Integration ¶
Container firewall rules (iptables) work in conjunction with the proxy:
Docker: Proxy binds to 127.0.0.1 (localhost only). Containers reach it via host.docker.internal or host network mode. Firewall allows proxy port only.
Apple containers: Proxy binds to 0.0.0.0 with per-run token authentication. Security is maintained via cryptographic tokens in HTTP_PROXY URL, not IP filtering.
The firewall rules intentionally do NOT filter by destination IP for the proxy port. This is because host.docker.internal resolves to different IPs across environments. The security boundaries are:
- Random high port assignment (reduces collision with other services)
- Token authentication for Apple containers
- Container isolation (other containers can't reach host ports by default)
This trade-off prioritizes reliability over defense-in-depth. The proxy validates credentials are only injected for explicitly configured hosts.
Index ¶
- Constants
- func FilterHeaders(headers http.Header, authInjected bool, injectedHeaderName string) map[string]string
- func GetHostsForGrant(grant string) []string
- func RegisterGrantHosts(grant string, hosts []string)
- type AWSCredentialHandler
- type AWSCredentialProvider
- func (p *AWSCredentialProvider) GetCredentials(ctx context.Context) (*AWSCredentials, error)
- func (p *AWSCredentialProvider) Handler() http.Handler
- func (p *AWSCredentialProvider) Region() string
- func (p *AWSCredentialProvider) RoleARN() string
- func (p *AWSCredentialProvider) SetAuthToken(token string)
- type AWSCredentials
- type CA
- type ContextResolver
- type CredentialHeader
- type ExtraHeader
- type HostPattern
- type Proxy
- func (p *Proxy) AddExtraHeader(host, headerName, headerValue string)
- func (p *Proxy) AddRelay(name, targetURL string) error
- func (p *Proxy) AddResponseTransformer(host string, transformer credential.ResponseTransformer)
- func (p *Proxy) RemoveRequestHeader(host, headerName string)
- func (p *Proxy) ResolveContext(token string) (*RunContextData, bool)
- func (p *Proxy) ServeHTTP(w http.ResponseWriter, r *http.Request)
- func (p *Proxy) SetAWSHandler(h http.Handler)
- func (p *Proxy) SetAuthToken(token string)
- func (p *Proxy) SetCA(ca *CA)
- func (p *Proxy) SetContextResolver(resolver ContextResolver)
- func (p *Proxy) SetCredential(host, authHeader string)
- func (p *Proxy) SetCredentialHeader(host, headerName, headerValue string)
- func (p *Proxy) SetCredentialStore(store credential.Store)
- func (p *Proxy) SetCredentialWithGrant(host, headerName, headerValue, grant string)
- func (p *Proxy) SetLogger(logger RequestLogger)
- func (p *Proxy) SetMCPServers(servers []config.MCPServerConfig)
- func (p *Proxy) SetNetworkPolicy(policy string, allows []string, grants []string)
- func (p *Proxy) SetTokenSubstitution(host, placeholder, realToken string)
- type RequestLogData
- type RequestLogger
- type RunContextData
- type STSAssumeRoler
- type Server
- type TokenSubstitution
Constants ¶
const MaxBodySize = 8 * 1024
MaxBodySize is the maximum size of request/response bodies to capture (8KB). Only this much is buffered for logging; the full body is always forwarded.
Variables ¶
This section is empty.
Functions ¶
func FilterHeaders ¶
func FilterHeaders(headers http.Header, authInjected bool, injectedHeaderName string) map[string]string
FilterHeaders creates a copy of headers with sensitive values filtered. If authInjected is true, the specified header name is redacted.
func GetHostsForGrant ¶
GetHostsForGrant returns the host patterns for a given grant name. Supports scoped grants like "github:repo" by extracting the provider name. Returns an empty slice if the grant is unknown.
func RegisterGrantHosts ¶ added in v0.3.0
RegisterGrantHosts registers host patterns for a grant name. This is used by config-driven providers to register their hosts dynamically. Must be called during initialization only (before concurrent access).
Types ¶
type AWSCredentialHandler ¶
type AWSCredentialHandler struct {
// contains filtered or unexported fields
}
AWSCredentialHandler serves AWS credentials via HTTP in ECS container format.
func (*AWSCredentialHandler) ServeHTTP ¶
func (h *AWSCredentialHandler) ServeHTTP(w http.ResponseWriter, r *http.Request)
ServeHTTP implements http.Handler, returning credentials in ECS format.
type AWSCredentialProvider ¶
type AWSCredentialProvider struct {
// contains filtered or unexported fields
}
AWSCredentialProvider manages AWS credential fetching and caching.
func NewAWSCredentialProvider ¶
func NewAWSCredentialProvider(ctx context.Context, roleARN, region string, sessionDuration time.Duration, externalID, sessionName string) (*AWSCredentialProvider, error)
NewAWSCredentialProvider creates a new AWS credential provider.
func (*AWSCredentialProvider) GetCredentials ¶
func (p *AWSCredentialProvider) GetCredentials(ctx context.Context) (*AWSCredentials, error)
GetCredentials returns cached credentials or fetches new ones.
func (*AWSCredentialProvider) Handler ¶
func (p *AWSCredentialProvider) Handler() http.Handler
Handler returns an HTTP handler for serving credentials.
func (*AWSCredentialProvider) Region ¶
func (p *AWSCredentialProvider) Region() string
Region returns the configured AWS region.
func (*AWSCredentialProvider) RoleARN ¶
func (p *AWSCredentialProvider) RoleARN() string
RoleARN returns the configured IAM role ARN.
func (*AWSCredentialProvider) SetAuthToken ¶
func (p *AWSCredentialProvider) SetAuthToken(token string)
SetAuthToken sets the required auth token for the credential endpoint.
type AWSCredentials ¶
type AWSCredentials struct {
AccessKeyID string
SecretAccessKey string
SessionToken string
Expiration time.Time
}
AWSCredentials holds temporary AWS credentials.
type CA ¶
type CA struct {
// contains filtered or unexported fields
}
CA represents a certificate authority for TLS interception.
func NewCA ¶
NewCA creates or loads a CA certificate. If the CA files exist at the given path, they are loaded. Otherwise, a new CA is generated and saved.
func (*CA) GenerateCert ¶
func (ca *CA) GenerateCert(host string) (*tls.Certificate, error)
GenerateCert creates a certificate for the given host signed by the CA.
type ContextResolver ¶ added in v0.3.0
type ContextResolver func(token string) (*RunContextData, bool)
ContextResolver resolves a proxy auth token to per-run context data.
type CredentialHeader ¶ added in v0.3.0
type CredentialHeader = credentialHeader
CredentialHeader is the exported version of credentialHeader for daemon use.
type ExtraHeader ¶ added in v0.3.0
type ExtraHeader = extraHeader
ExtraHeader is the exported version of extraHeader for daemon use.
type HostPattern ¶ added in v0.3.0
type HostPattern = hostPattern
HostPattern is the exported version of hostPattern.
func ParseHostPattern ¶ added in v0.3.0
func ParseHostPattern(pattern string) HostPattern
ParseHostPattern is the exported wrapper for parseHostPattern.
type Proxy ¶
type Proxy struct {
// contains filtered or unexported fields
}
Proxy is an HTTP proxy that injects credentials into outgoing requests.
Security Model ¶
The proxy handles two distinct security concerns:
Credential injection: The proxy injects credential headers for configured hosts (e.g., api.github.com, api.anthropic.com). When CA is set, it performs TLS interception (MITM) to inject headers into HTTPS requests. Supports custom header names (Authorization, x-api-key, etc).
Proxy authentication: When authToken is set, clients must authenticate to the proxy itself via Proxy-Authorization header. This prevents unauthorized access when the proxy binds to all interfaces (0.0.0.0), which is required for Apple containers that access the host via gateway IP rather than localhost.
For Docker containers, the proxy binds to localhost (127.0.0.1) and authentication is not required. For Apple containers, the proxy binds to all interfaces with a cryptographically secure token for authentication.
func (*Proxy) AddExtraHeader ¶
AddExtraHeader adds an additional header to inject for a host. This is used for headers beyond the main credential header, such as beta feature flags or API version headers. The host must be a valid hostname (not empty, no path components).
func (*Proxy) AddRelay ¶ added in v0.3.0
AddRelay registers a named relay endpoint. Requests to /relay/{name}/{path...} are forwarded to the target URL with credential injection. This is used when the target host would be in NO_PROXY (e.g., a host-side proxy reachable via the same address as the Moat proxy), which would cause direct connections to bypass credential injection.
AddRelay must be called before the proxy starts serving.
func (*Proxy) AddResponseTransformer ¶
func (p *Proxy) AddResponseTransformer(host string, transformer credential.ResponseTransformer)
AddResponseTransformer registers a response transformer for a host. Transformers are called in registration order after receiving the upstream response. Each transformer can inspect and optionally modify the response. The host must be a valid hostname (not empty, no path components).
func (*Proxy) RemoveRequestHeader ¶
RemoveRequestHeader removes a client-sent header before forwarding.
func (*Proxy) ResolveContext ¶ added in v0.3.0
func (p *Proxy) ResolveContext(token string) (*RunContextData, bool)
ResolveContext looks up per-run context data by auth token. Returns nil, false when no resolver is set or the token is not found.
func (*Proxy) ServeHTTP ¶
func (p *Proxy) ServeHTTP(w http.ResponseWriter, r *http.Request)
ServeHTTP handles proxy requests.
func (*Proxy) SetAWSHandler ¶
SetAWSHandler sets the handler for AWS credential requests.
func (*Proxy) SetAuthToken ¶
SetAuthToken sets the required authentication token for proxy access.
func (*Proxy) SetContextResolver ¶ added in v0.3.0
func (p *Proxy) SetContextResolver(resolver ContextResolver)
SetContextResolver sets the per-run context resolver for multi-tenant proxy use. When set, the proxy can resolve auth tokens to per-run credential data.
func (*Proxy) SetCredential ¶
SetCredential sets the credential for a host using the Authorization header.
func (*Proxy) SetCredentialHeader ¶
SetCredentialHeader sets a custom credential header for a host. Use this for APIs that use non-standard header names like "x-api-key". The host must be a valid hostname (not empty, no path components).
func (*Proxy) SetCredentialStore ¶
func (p *Proxy) SetCredentialStore(store credential.Store)
SetCredentialStore sets the credential store for MCP credential retrieval.
func (*Proxy) SetCredentialWithGrant ¶
SetCredentialWithGrant sets a credential header with grant info for logging. Grant is used for structured logging to identify the credential source.
func (*Proxy) SetLogger ¶
func (p *Proxy) SetLogger(logger RequestLogger)
SetLogger sets the request logger.
func (*Proxy) SetMCPServers ¶
func (p *Proxy) SetMCPServers(servers []config.MCPServerConfig)
SetMCPServers configures MCP servers for credential injection.
func (*Proxy) SetNetworkPolicy ¶
SetNetworkPolicy sets the network policy and allowed hosts. policy should be "permissive" or "strict". allows is a list of host patterns like "api.example.com" or "*.example.com". grants is a list of grant names like "github" that will be expanded to host patterns.
func (*Proxy) SetTokenSubstitution ¶
SetTokenSubstitution replaces placeholder tokens with real tokens in both Authorization headers and request bodies for a specific host.
type RequestLogData ¶
type RequestLogData struct {
Method string
URL string
StatusCode int
Duration time.Duration
Err error
RequestHeaders http.Header
ResponseHeaders http.Header
RequestBody []byte
ResponseBody []byte
AuthInjected bool // True if credential header was injected for this host
InjectedHeaderName string // Name of the injected header (for filtering)
RunID string // Run ID from per-run context (daemon mode)
}
RequestLogData contains all data for a logged request.
type RequestLogger ¶
type RequestLogger func(data RequestLogData)
RequestLogger is called for each proxied request.
type RunContextData ¶ added in v0.3.0
type RunContextData struct {
RunID string
Credentials map[string]credentialHeader
ExtraHeaders map[string][]extraHeader
RemoveHeaders map[string][]string
TokenSubstitutions map[string]*tokenSubstitution
ResponseTransformers map[string][]credential.ResponseTransformer
MCPServers []config.MCPServerConfig
Policy string
AllowedHosts []hostPattern
AWSHandler http.Handler
CredStore credential.Store
}
RunContextData holds per-run credential data resolved by ContextResolver.
type STSAssumeRoler ¶
type STSAssumeRoler interface {
AssumeRole(ctx context.Context, params *sts.AssumeRoleInput, optFns ...func(*sts.Options)) (*sts.AssumeRoleOutput, error)
}
STSAssumeRoler interface for STS AssumeRole operation (enables testing).
type Server ¶
type Server struct {
// contains filtered or unexported fields
}
Server wraps a Proxy in an HTTP server.
func (*Server) SetBindAddr ¶
SetBindAddr sets the address to bind to. Use "0.0.0.0" to bind to all interfaces (needed for Apple containers which access host via gateway IP). Must be called before Start().
func (*Server) SetPort ¶ added in v0.3.0
SetPort sets the port to bind to. Use 0 (default) for an OS-assigned port. Must be called before Start().
type TokenSubstitution ¶ added in v0.3.0
type TokenSubstitution = tokenSubstitution
TokenSubstitution is the exported version of tokenSubstitution for daemon use.
func NewTokenSubstitution ¶ added in v0.3.0
func NewTokenSubstitution(placeholder, realToken string) *TokenSubstitution
NewTokenSubstitution creates a TokenSubstitution with the given placeholder and real token.