Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion audit/logging_auditor.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ func NewLoggingAuditor(logger *slog.Logger) *LoggingAuditor {
}

// AuditRequest logs the request using structured logging
func (a *LoggingAuditor) AuditRequest(req *Request) {
func (a *LoggingAuditor) AuditRequest(req Request) {
if req.Allowed {
a.logger.Info("ALLOW",
"method", req.Method,
Expand Down
48 changes: 24 additions & 24 deletions audit/logging_auditor_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,13 @@ import (
func TestLoggingAuditor(t *testing.T) {
tests := []struct {
name string
request *Request
request Request
expectedLevel string
expectedFields []string
}{
{
name: "allow request",
request: &Request{
request: Request{
Method: "GET",
URL: "https://github.com",
Allowed: true,
Expand All @@ -28,7 +28,7 @@ func TestLoggingAuditor(t *testing.T) {
},
{
name: "deny request",
request: &Request{
request: Request{
Method: "POST",
URL: "https://example.com",
Allowed: false,
Expand All @@ -38,7 +38,7 @@ func TestLoggingAuditor(t *testing.T) {
},
{
name: "allow with empty rule",
request: &Request{
request: Request{
Method: "PUT",
URL: "https://api.github.com/repos",
Allowed: true,
Expand All @@ -49,7 +49,7 @@ func TestLoggingAuditor(t *testing.T) {
},
{
name: "deny HTTPS request",
request: &Request{
request: Request{
Method: "GET",
URL: "https://malware.bad.com/payload",
Allowed: false,
Expand All @@ -59,7 +59,7 @@ func TestLoggingAuditor(t *testing.T) {
},
{
name: "allow with wildcard rule",
request: &Request{
request: Request{
Method: "POST",
URL: "https://api.github.com/graphql",
Allowed: true,
Expand All @@ -70,7 +70,7 @@ func TestLoggingAuditor(t *testing.T) {
},
{
name: "deny HTTP request",
request: &Request{
request: Request{
Method: "GET",
URL: "http://insecure.example.com",
Allowed: false,
Expand All @@ -80,7 +80,7 @@ func TestLoggingAuditor(t *testing.T) {
},
{
name: "allow HEAD request",
request: &Request{
request: Request{
Method: "HEAD",
URL: "https://cdn.jsdelivr.net/health",
Allowed: true,
Expand All @@ -91,7 +91,7 @@ func TestLoggingAuditor(t *testing.T) {
},
{
name: "deny OPTIONS request",
request: &Request{
request: Request{
Method: "OPTIONS",
URL: "https://restricted.api.com/cors",
Allowed: false,
Expand All @@ -101,7 +101,7 @@ func TestLoggingAuditor(t *testing.T) {
},
{
name: "allow with port number",
request: &Request{
request: Request{
Method: "GET",
URL: "https://localhost:3000/api/health",
Allowed: true,
Expand All @@ -112,7 +112,7 @@ func TestLoggingAuditor(t *testing.T) {
},
{
name: "deny DELETE request",
request: &Request{
request: Request{
Method: "DELETE",
URL: "https://api.production.com/users/admin",
Allowed: false,
Expand Down Expand Up @@ -153,13 +153,13 @@ func TestLoggingAuditor(t *testing.T) {
func TestLoggingAuditor_EdgeCases(t *testing.T) {
tests := []struct {
name string
request *Request
request Request
expectedLevel string
expectedFields []string
}{
{
name: "empty fields",
request: &Request{
request: Request{
Method: "",
URL: "",
Allowed: true,
Expand All @@ -170,7 +170,7 @@ func TestLoggingAuditor_EdgeCases(t *testing.T) {
},
{
name: "special characters in URL",
request: &Request{
request: Request{
Method: "POST",
URL: "https://api.example.com/users?name=John%20Doe&id=123",
Allowed: true,
Expand All @@ -181,7 +181,7 @@ func TestLoggingAuditor_EdgeCases(t *testing.T) {
},
{
name: "very long URL",
request: &Request{
request: Request{
Method: "GET",
URL: "https://example.com/" + strings.Repeat("a", 1000),
Allowed: false,
Expand All @@ -191,7 +191,7 @@ func TestLoggingAuditor_EdgeCases(t *testing.T) {
},
{
name: "deny with custom URL",
request: &Request{
request: Request{
Method: "DELETE",
URL: "https://malicious.com",
Allowed: false,
Expand Down Expand Up @@ -233,13 +233,13 @@ func TestLoggingAuditor_DifferentLogLevels(t *testing.T) {
tests := []struct {
name string
logLevel slog.Level
request *Request
request Request
expectOutput bool
}{
{
name: "info level allows info logs",
logLevel: slog.LevelInfo,
request: &Request{
request: Request{
Method: "GET",
URL: "https://github.com",
Allowed: true,
Expand All @@ -250,7 +250,7 @@ func TestLoggingAuditor_DifferentLogLevels(t *testing.T) {
{
name: "warn level blocks info logs",
logLevel: slog.LevelWarn,
request: &Request{
request: Request{
Method: "GET",
URL: "https://github.com",
Allowed: true,
Expand All @@ -261,7 +261,7 @@ func TestLoggingAuditor_DifferentLogLevels(t *testing.T) {
{
name: "warn level allows warn logs",
logLevel: slog.LevelWarn,
request: &Request{
request: Request{
Method: "POST",
URL: "https://example.com",
Allowed: false,
Expand All @@ -271,7 +271,7 @@ func TestLoggingAuditor_DifferentLogLevels(t *testing.T) {
{
name: "error level blocks warn logs",
logLevel: slog.LevelError,
request: &Request{
request: Request{
Method: "POST",
URL: "https://example.com",
Allowed: false,
Expand Down Expand Up @@ -312,7 +312,7 @@ func TestLoggingAuditor_NilLogger(t *testing.T) {
}()

auditor := &LoggingAuditor{logger: nil}
req := &Request{
req := Request{
Method: "GET",
URL: "https://example.com",
Allowed: true,
Expand All @@ -331,7 +331,7 @@ func TestLoggingAuditor_JSONHandler(t *testing.T) {
}))

auditor := NewLoggingAuditor(logger)
req := &Request{
req := Request{
Method: "GET",
URL: "https://github.com",
Allowed: true,
Expand Down Expand Up @@ -364,7 +364,7 @@ func TestLoggingAuditor_DiscardHandler(t *testing.T) {
logger := slog.New(slog.NewTextHandler(io.Discard, &slog.HandlerOptions{}))

auditor := NewLoggingAuditor(logger)
req := &Request{
req := Request{
Method: "GET",
URL: "https://example.com",
Allowed: true,
Expand Down
4 changes: 1 addition & 3 deletions audit/request.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
package audit

import (
"net/http"
)
import "net/http"

// Request represents information about an HTTP request for auditing
type Request struct {
Expand Down
57 changes: 10 additions & 47 deletions cli/cli.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,6 @@ import (

"github.com/coder/jail"
"github.com/coder/jail/audit"
"github.com/coder/jail/namespace"
"github.com/coder/jail/proxy"
"github.com/coder/jail/rules"
"github.com/coder/jail/tls"
"github.com/coder/serpent"
Expand Down Expand Up @@ -115,20 +113,7 @@ func Run(config Config, args []string) error {
ruleEngine := rules.NewRuleEngine(allowRules, logger)

// Create auditor
auditor := audit.NewLoggingAuditor(logger)

// Create network namespace configuration
nsConfig := namespace.Config{
HTTPPort: 8040,
HTTPSPort: 8043,
}

// Create commander
commander, err := namespace.New(nsConfig, logger)
if err != nil {
logger.Error("Failed to create network namespace", "error", err)
return fmt.Errorf("failed to create network namespace: %v", err)
}
// auditor := audit.NewLoggingAuditor(logger)

// Create certificate manager
certManager, err := tls.NewCertificateManager(logger)
Expand All @@ -137,39 +122,17 @@ func Run(config Config, args []string) error {
return fmt.Errorf("failed to create certificate manager: %v", err)
}

// Setup TLS config and write CA certificate to file
var caCertPath, configDir string
tlsConfig, caCertPath, configDir, err := certManager.SetupTLSAndWriteCACert()
if err != nil {
logger.Error("Failed to setup TLS and CA certificate", "error", err)
return fmt.Errorf("failed to setup TLS and CA certificate: %v", err)
}

// Set standard CA certificate environment variables for common tools
// This makes tools like curl, git, etc. trust our dynamically generated CA
commander.SetEnv("SSL_CERT_FILE", caCertPath) // OpenSSL/LibreSSL-based tools
commander.SetEnv("SSL_CERT_DIR", configDir) // OpenSSL certificate directory
commander.SetEnv("CURL_CA_BUNDLE", caCertPath) // curl
commander.SetEnv("GIT_SSL_CAINFO", caCertPath) // Git
commander.SetEnv("REQUESTS_CA_BUNDLE", caCertPath) // Python requests
commander.SetEnv("NODE_EXTRA_CA_CERTS", caCertPath) // Node.js

// Create proxy server
proxyServer := proxy.NewProxyServer(proxy.Config{
HTTPPort: 8040,
HTTPSPort: 8043,
RuleEngine: ruleEngine,
Auditor: auditor,
Logger: logger,
TLSConfig: tlsConfig,
})

// Create jail instance
jailInstance := jail.New(jail.Config{
Commander: commander,
ProxyServer: proxyServer,
jailInstance, err := jail.New(context.Background(), jail.Config{
RuleEngine: ruleEngine,
Auditor: audit.NewLoggingAuditor(logger),
Logger: logger,
CertManager: certManager,
})
if err != nil {
logger.Error("Failed to create jail instance", "error", err)
return fmt.Errorf("failed to create jail instance: %v", err)
}

// Setup signal handling BEFORE any setup
sigChan := make(chan os.Signal, 1)
Expand Down Expand Up @@ -198,7 +161,7 @@ func Run(config Config, args []string) error {
}()

// Open jail (starts network namespace and proxy server)
err = jailInstance.Open()
err = jailInstance.Start()
if err != nil {
logger.Error("Failed to open jail", "error", err)
return fmt.Errorf("failed to open jail: %v", err)
Expand Down
Loading
Loading