Skip to content

Commit d02ebf4

Browse files
blink-so[bot]f0ssel
andcommitted
Convert preparedEnv to map and implement SetEnv methods
- Convert preparedEnv from []string to map[string]string for better environment management - Implement SetEnv methods in both Linux and macOS namespace implementations - Add CommandExecutor accessor method to Jail for SetEnv access - Update CLI to use SetEnv method for CA certificate environment variables - Remove Env field from namespace.Config since SetEnv is used instead - Environment variables now properly managed through SetEnv interface - Allows dynamic environment variable setting after initialization - Better encapsulation and control over environment variables Co-authored-by: f0ssel <[email protected]>
1 parent 7d77eb2 commit d02ebf4

File tree

5 files changed

+54
-48
lines changed

5 files changed

+54
-48
lines changed

cli/cli.go

Lines changed: 15 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -147,14 +147,10 @@ func Run(config Config, args []string) error {
147147
tlsConfig = certManager.GetTLSConfig()
148148
}
149149

150-
// Create environment map for CA certificate
151-
var extraEnv map[string]string = make(map[string]string)
152-
153150
// Create network namespace configuration
154151
nsConfig := namespace.Config{
155152
HTTPPort: 8040,
156153
HTTPSPort: 8043,
157-
Env: extraEnv,
158154
}
159155

160156
// Create network namespace instance
@@ -212,6 +208,13 @@ func Run(config Config, args []string) error {
212208
}
213209
}()
214210

211+
// Open jail (starts network namespace and proxy server)
212+
err = jailInstance.Open()
213+
if err != nil {
214+
logger.Error("Failed to open jail", "error", err)
215+
return fmt.Errorf("failed to open jail: %v", err)
216+
}
217+
215218
// Setup CA certificate environment variables if TLS interception is enabled
216219
if !config.NoTLSIntercept && certManager != nil {
217220
// Get CA certificate for environment
@@ -231,20 +234,13 @@ func Run(config Config, args []string) error {
231234

232235
// Set standard CA certificate environment variables for common tools
233236
// This makes tools like curl, git, etc. trust our dynamically generated CA
234-
extraEnv["SSL_CERT_FILE"] = caCertPath // OpenSSL/LibreSSL-based tools
235-
extraEnv["SSL_CERT_DIR"] = configDir // OpenSSL certificate directory
236-
extraEnv["CURL_CA_BUNDLE"] = caCertPath // curl
237-
extraEnv["GIT_SSL_CAINFO"] = caCertPath // Git
238-
extraEnv["REQUESTS_CA_BUNDLE"] = caCertPath // Python requests
239-
extraEnv["NODE_EXTRA_CA_CERTS"] = caCertPath // Node.js
240-
extraEnv["JAIL_CA_CERT"] = string(caCertPEM) // Keep for backward compatibility
241-
}
242-
243-
// Open jail (starts network namespace and proxy server)
244-
err = jailInstance.Open()
245-
if err != nil {
246-
logger.Error("Failed to open jail", "error", err)
247-
return fmt.Errorf("failed to open jail: %v", err)
237+
jailInstance.CommandExecutor().SetEnv("SSL_CERT_FILE", caCertPath) // OpenSSL/LibreSSL-based tools
238+
jailInstance.CommandExecutor().SetEnv("SSL_CERT_DIR", configDir) // OpenSSL certificate directory
239+
jailInstance.CommandExecutor().SetEnv("CURL_CA_BUNDLE", caCertPath) // curl
240+
jailInstance.CommandExecutor().SetEnv("GIT_SSL_CAINFO", caCertPath) // Git
241+
jailInstance.CommandExecutor().SetEnv("REQUESTS_CA_BUNDLE", caCertPath) // Python requests
242+
jailInstance.CommandExecutor().SetEnv("NODE_EXTRA_CA_CERTS", caCertPath) // Node.js
243+
jailInstance.CommandExecutor().SetEnv("JAIL_CA_CERT", string(caCertPEM)) // Keep for backward compatibility
248244
}
249245

250246
// Create context for graceful shutdown
@@ -271,4 +267,4 @@ func Run(config Config, args []string) error {
271267
}
272268

273269
return nil
274-
}
270+
}

jail.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,10 @@ func (j *Jail) Command(command []string) *exec.Cmd {
6868
return j.commandExecutor.Command(command)
6969
}
7070

71+
func (j *Jail) CommandExecutor() Commander {
72+
return j.commandExecutor
73+
}
74+
7175
func (j *Jail) Close() error {
7276
// Cancel context to stop proxy server
7377
if j.cancel != nil {

namespace/linux.go

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99
"os/exec"
1010
"os/user"
1111
"strconv"
12+
"strings"
1213
"syscall"
1314
"time"
1415
)
@@ -18,7 +19,7 @@ type Linux struct {
1819
config Config
1920
namespace string
2021
logger *slog.Logger
21-
preparedEnv []string
22+
preparedEnv map[string]string
2223
procAttr *syscall.SysProcAttr
2324
}
2425

@@ -62,11 +63,13 @@ func (l *Linux) Open() error {
6263

6364
// Prepare environment once during setup
6465
l.logger.Debug("Preparing environment")
65-
env := os.Environ()
66+
l.preparedEnv = make(map[string]string)
6667

67-
// Add extra environment variables from config
68-
for key, value := range l.config.Env {
69-
env = append(env, fmt.Sprintf("%s=%s", key, value))
68+
// Start with current environment
69+
for _, envVar := range os.Environ() {
70+
if parts := strings.SplitN(envVar, "=", 2); len(parts) == 2 {
71+
l.preparedEnv[parts[0]] = parts[1]
72+
}
7073
}
7174

7275
// When running under sudo, restore essential user environment variables
@@ -75,18 +78,15 @@ func (l *Linux) Open() error {
7578
user, err := user.Lookup(sudoUser)
7679
if err == nil {
7780
// Set HOME to original user's home directory
78-
env = append(env, fmt.Sprintf("HOME=%s", user.HomeDir))
81+
l.preparedEnv["HOME"] = user.HomeDir
7982
// Set USER to original username
80-
env = append(env, fmt.Sprintf("USER=%s", sudoUser))
83+
l.preparedEnv["USER"] = sudoUser
8184
// Set LOGNAME to original username (some tools check this instead of USER)
82-
env = append(env, fmt.Sprintf("LOGNAME=%s", sudoUser))
85+
l.preparedEnv["LOGNAME"] = sudoUser
8386
l.logger.Debug("Restored user environment", "home", user.HomeDir, "user", sudoUser)
8487
}
8588
}
8689

87-
// Store prepared environment for use in Command method
88-
l.preparedEnv = env
89-
9090
// Prepare process credentials once during setup
9191
l.logger.Debug("Preparing process credentials")
9292
var gid, uid int
@@ -117,7 +117,7 @@ func (l *Linux) Open() error {
117117

118118
// SetEnv sets an environment variable for commands run in the namespace
119119
func (l *Linux) SetEnv(key string, value string) {
120-
120+
l.preparedEnv[key] = value
121121
}
122122

123123
// Command returns an exec.Cmd configured to run within the network namespace
@@ -133,7 +133,11 @@ func (l *Linux) Command(command []string) *exec.Cmd {
133133
cmd := exec.Command("ip", cmdArgs[1:]...)
134134

135135
// Use prepared environment from Open method
136-
cmd.Env = l.preparedEnv
136+
env := make([]string, 0, len(l.preparedEnv))
137+
for key, value := range l.preparedEnv {
138+
env = append(env, fmt.Sprintf("%s=%s", key, value))
139+
}
140+
cmd.Env = env
137141
cmd.Stdin = os.Stdin
138142
cmd.Stdout = os.Stdout
139143
cmd.Stderr = os.Stderr

namespace/macos.go

Lines changed: 17 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ type MacOSNetJail struct {
2525
pfRulesPath string
2626
mainRulesPath string
2727
logger *slog.Logger
28-
preparedEnv []string
28+
preparedEnv map[string]string
2929
procAttr *syscall.SysProcAttr
3030
}
3131

@@ -63,11 +63,13 @@ func (m *MacOSNetJail) Open() error {
6363

6464
// Prepare environment once during setup
6565
m.logger.Debug("Preparing environment")
66-
env := os.Environ()
66+
m.preparedEnv = make(map[string]string)
6767

68-
// Add extra environment variables from config
69-
for key, value := range m.config.Env {
70-
env = append(env, fmt.Sprintf("%s=%s", key, value))
68+
// Start with current environment
69+
for _, envVar := range os.Environ() {
70+
if parts := strings.SplitN(envVar, "=", 2); len(parts) == 2 {
71+
m.preparedEnv[parts[0]] = parts[1]
72+
}
7173
}
7274

7375
// When running under sudo, restore essential user environment variables
@@ -76,18 +78,15 @@ func (m *MacOSNetJail) Open() error {
7678
user, err := user.Lookup(sudoUser)
7779
if err == nil {
7880
// Set HOME to original user's home directory
79-
env = append(env, fmt.Sprintf("HOME=%s", user.HomeDir))
81+
m.preparedEnv["HOME"] = user.HomeDir
8082
// Set USER to original username
81-
env = append(env, fmt.Sprintf("USER=%s", sudoUser))
83+
m.preparedEnv["USER"] = sudoUser
8284
// Set LOGNAME to original username (some tools check this instead of USER)
83-
env = append(env, fmt.Sprintf("LOGNAME=%s", sudoUser))
85+
m.preparedEnv["LOGNAME"] = sudoUser
8486
m.logger.Debug("Restored user environment", "home", user.HomeDir, "user", sudoUser)
8587
}
8688
}
8789

88-
// Store prepared environment for use in Command method
89-
m.preparedEnv = env
90-
9190
// Prepare process credentials once during setup
9291
m.logger.Debug("Preparing process credentials")
9392
procAttr := &syscall.SysProcAttr{
@@ -123,7 +122,7 @@ func (m *MacOSNetJail) Open() error {
123122

124123
// SetEnv sets an environment variable for commands run in the namespace
125124
func (m *MacOSNetJail) SetEnv(key string, value string) {
126-
125+
m.preparedEnv[key] = value
127126
}
128127

129128
// Execute runs the command with the network jail group membership
@@ -136,7 +135,11 @@ func (m *MacOSNetJail) Command(command []string) *exec.Cmd {
136135
m.logger.Debug("Full command args", "args", command)
137136

138137
// Use prepared environment from Open method
139-
cmd.Env = m.preparedEnv
138+
env := make([]string, 0, len(m.preparedEnv))
139+
for key, value := range m.preparedEnv {
140+
env = append(env, fmt.Sprintf("%s=%s", key, value))
141+
}
142+
cmd.Env = env
140143
cmd.Stdout = os.Stdout
141144
cmd.Stderr = os.Stderr
142145
cmd.Stdin = os.Stdin
@@ -362,4 +365,4 @@ func (m *MacOSNetJail) cleanupTempFiles() {
362365
if m.mainRulesPath != "" {
363366
os.Remove(m.mainRulesPath)
364367
}
365-
}
368+
}

namespace/namespace.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ const (
1717
type Config struct {
1818
HTTPPort int
1919
HTTPSPort int
20-
Env map[string]string
2120
}
2221

2322
// NewJail creates a new NetJail instance for the current platform
@@ -34,4 +33,4 @@ func New(config Config, logger *slog.Logger) (jail.Commander, error) {
3433

3534
func newNamespaceName() string {
3635
return fmt.Sprintf("%s_%d", namespacePrefix, time.Now().UnixNano()%10000000)
37-
}
36+
}

0 commit comments

Comments
 (0)