proxy

package
v0.1.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 14, 2026 License: MIT Imports: 40 Imported by: 0

Documentation

Overview

Package proxy implements Veil's HTTPS MITM proxy.

Index

Constants

View Source
const (
	LocationAWSSigV4Resigned     = "aws_sigv4_resigned"
	LocationGitHubAppJWTResigned = "github_app_jwt_resigned"
	LocationSchemeUnmediated     = "scheme_unmediated"
	LocationSignerFailed         = "signer_failed"
)

Signer Location values emitted into audit records.

View Source
const (
	SignerErrUnknownAccessKeyID             = "unknown_access_key_id"
	SignerErrUnknownGitHubAppID             = "unknown_github_app_id"
	SignerErrUnexpectedSessionToken         = "unexpected_session_token"
	SignerErrMissingSessionToken            = "missing_session_token"
	SignerErrAuthorizationMalformed         = "authorization_malformed"
	SignerErrCanonicalRequestReconstruction = "canonical_request_reconstruction_failed"
	SignerErrRSASignFailed                  = "rsa_sign_failed"
	SignerErrJWTMalformed                   = "jwt_malformed"
)

Signer error classes recorded in Injection.SignerError.

Variables

View Source
var (
	// ErrCAGenerate indicates generation of a fresh root CA failed.
	ErrCAGenerate = errors.New("proxy: generate CA failed")

	// ErrCALoad indicates loading the CA cert or key from disk failed.
	ErrCALoad = errors.New("proxy: load CA failed")

	// ErrCABundle indicates building/writing the combined CA bundle failed.
	ErrCABundle = errors.New("proxy: build CA bundle failed")

	// ErrListen indicates the proxy could not bind its loopback listener.
	ErrListen = errors.New("proxy: listen failed")

	// ErrBodyRead indicates reading the outbound request body failed.
	ErrBodyRead = errors.New("proxy: body read failed")

	// ErrPlaceholderLeak indicates the fail-closed guard detected a
	// placeholder sentinel in the final outbound bytes and refused to
	// forward the request.
	ErrPlaceholderLeak = errors.New("proxy: placeholder leak detected")

	// ErrCompressedBody indicates an outbound request body used a
	// Content-Encoding Veil cannot safely inject into, so the request was
	// rejected rather than forwarded with potentially-unreplaced placeholders.
	ErrCompressedBody = errors.New("proxy: compressed request body rejected")
)

Sentinel errors for the proxy package.

Functions

func BuildCABundle

func BuildCABundle(veilCAPEM []byte) (string, error)

BuildCABundle creates a combined PEM file containing the system CA certificates plus the provided Veil CA PEM. Returns the path to the bundle file. Call RemoveCABundle to clean up.

func BuildCABundleIn

func BuildCABundleIn(sessionDir string, veilCAPEM []byte) (string, error)

BuildCABundleIn writes the combined CA bundle into sessionDir and returns the full file path. Prefer this over BuildCABundle in new code; the latter is preserved for callers still using the shared location.

func BuildJavaTruststoreIn

func BuildJavaTruststoreIn(sessionDir string, bundlePEM []byte) (path, password string, err error)

BuildJavaTruststoreIn writes a PKCS12 truststore to sessionDir containing every CERTIFICATE block in bundlePEM as a trust anchor. Returns the full path to the written file and the per-session random password used to encode it.

The password is generated fresh on every call. The same password is what JavaToolOptionsFlags must receive — callers should thread both values through to the child environment together. The truststore lives in a 0700 session dir and is written 0600.

Unlike BuildCABundleIn, this function hard-fails on any error. A missing or malformed truststore breaks TLS for every JVM host — there is no useful degraded mode.

func JavaToolOptionsFlags

func JavaToolOptionsFlags(p12Path, password string) string

JavaToolOptionsFlags returns the JVM -D flags that point JAVA_TOOL_OPTIONS at a Veil per-session PKCS12 truststore. The password must be the value BuildJavaTruststoreIn returned alongside the path; keeping them threaded together is the caller's responsibility.

The path is double-quoted (via strconv.Quote) so a session dir containing whitespace — common on macOS under "~/Library/Application Support/..." — is parsed as a single argument by the JVM launcher, which splits JAVA_TOOL_OPTIONS on whitespace but respects "..." and '...' quoting. The password is double-quoted via the same path for symmetry, even though newTruststorePassword guarantees a whitespace-free, quote-free string.

func RemoveCABundle

func RemoveCABundle(path string)

RemoveCABundle deletes the combined CA bundle file.

func SaveCA

func SaveCA(ca *CA, certPath, keyPath string) error

SaveCA writes the CA certificate and key to disk atomically.

func ShouldInjectBody

func ShouldInjectBody(contentType string) bool

ShouldInjectBody reports whether the proxy should scan and rewrite the body for a request with the given Content-Type header value. Matching is case-insensitive and strict (allowlist): missing or unknown Content-Types return false. Media-type parameters (charset, boundary, etc.) are ignored.

Types

type CA

type CA struct {
	Cert    *x509.Certificate
	Key     crypto.PrivateKey
	CertPEM []byte
	KeyPEM  []byte
}

CA holds a root certificate authority used for signing leaf certificates.

func GenerateCA

func GenerateCA() (*CA, error)

GenerateCA creates a new self-signed root CA with a P-256 ECDSA key.

func LoadCA

func LoadCA(certPath, keyPath string) (*CA, error)

LoadCA reads a CA certificate and private key from PEM files on disk.

func LoadOrCreateCA

func LoadOrCreateCA() (*CA, error)

LoadOrCreateCA loads an existing CA from disk or generates a new one. It returns an error if only one of the cert/key files exists (inconsistent state).

type Injector

type Injector struct {
	// contains filtered or unexported fields
}

Injector performs Aho-Corasick multi-pattern matching to replace placeholder strings with real secret values in HTTP requests.

func NewInjector

func NewInjector(placeholderMap map[string]*vault.Credential, auditStore *audit.Store, agentPID int, agentCmd string) *Injector

NewInjector creates an Injector from a placeholder map. The auditStore may be nil to disable audit recording.

func (*Injector) ProcessRequest

func (inj *Injector) ProcessRequest(
	requestID string,
	method string,
	rawURL string,
	header http.Header,
	body []byte,
) (newURL string, newHeader http.Header, newBody []byte, injections []audit.Injection)

ProcessRequest scans a request's URL, headers, and body for placeholder strings and replaces them with real secret values. It returns the modified components and a slice of audit injection records.

func (*Injector) Reload

func (inj *Injector) Reload(placeholderMap map[string]*vault.Credential)

Reload rebuilds the AC matcher and credential map for vault reload during runtime.

func (*Injector) Replace

func (inj *Injector) Replace(input string) string

Replace performs placeholder replacement on a single string and returns the result. It uses the AC matcher for detection, then strings.ReplaceAll for each matched pattern.

type LeafCache

type LeafCache struct {
	// contains filtered or unexported fields
}

LeafCache caches per-host TLS leaf certificates signed by a root CA.

func NewLeafCache

func NewLeafCache(ca *CA) *LeafCache

NewLeafCache creates a new leaf certificate cache backed by the given CA.

func (*LeafCache) GetOrCreate

func (lc *LeafCache) GetOrCreate(sniHost string) (*tls.Certificate, error)

GetOrCreate returns a cached TLS certificate for the given SNI host, generating and caching a new one if needed.

func (*LeafCache) Size

func (lc *LeafCache) Size() int

Size returns the current number of cached leaf certificates.

type Server

type Server struct {
	// contains filtered or unexported fields
}

Server is a local MITM proxy that intercepts HTTP/HTTPS traffic, replacing placeholder strings with real secrets via the Injector.

func New

func New(ca *CA, vlt *vault.Vault, auditStore *audit.Store, agentPID int, agentCmd string) (*Server, error)

New creates a new proxy Server wired with goproxy MITM, the injector, and audit store. The server is not yet listening; call Start().

func (*Server) Addr

func (s *Server) Addr() string

Addr returns the host:port string the proxy is listening on.

func (*Server) Port

func (s *Server) Port() int

Port returns just the port number the proxy is listening on.

func (*Server) Start

func (s *Server) Start() error

Start begins listening on a random loopback port and serving requests.

func (*Server) Stop

func (s *Server) Stop() error

Stop closes the listener and signals shutdown.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL