@@ -6,8 +6,10 @@ import (
6
6
"log/slog"
7
7
"os"
8
8
"os/signal"
9
+ "path/filepath"
9
10
"strings"
10
11
"syscall"
12
+ "time"
11
13
12
14
"github.com/coder/boundary"
13
15
"github.com/coder/boundary/audit"
@@ -22,6 +24,7 @@ import (
22
24
type Config struct {
23
25
AllowStrings []string
24
26
LogLevel string
27
+ LogDir string
25
28
Unprivileged bool
26
29
}
27
30
@@ -56,20 +59,26 @@ func BaseCommand() *serpent.Command {
56
59
Short : "Network isolation tool for monitoring and restricting HTTP/HTTPS requests" ,
57
60
Long : `boundary creates an isolated network environment for target processes, intercepting HTTP/HTTPS traffic through a transparent proxy that enforces user-defined allow rules.` ,
58
61
Options : []serpent.Option {
59
- serpent. Option {
62
+ {
60
63
Flag : "allow" ,
61
64
Env : "BOUNDARY_ALLOW" ,
62
65
Description : "Allow rule (repeatable). Format: \" pattern\" or \" METHOD[,METHOD] pattern\" ." ,
63
66
Value : serpent .StringArrayOf (& config .AllowStrings ),
64
67
},
65
- serpent. Option {
68
+ {
66
69
Flag : "log-level" ,
67
70
Env : "BOUNDARY_LOG_LEVEL" ,
68
71
Description : "Set log level (error, warn, info, debug)." ,
69
72
Default : "warn" ,
70
73
Value : serpent .StringOf (& config .LogLevel ),
71
74
},
72
- serpent.Option {
75
+ {
76
+ Flag : "log-dir" ,
77
+ Env : "BOUNDARY_LOG_DIR" ,
78
+ Description : "Set a directory to write logs to rather than stderr." ,
79
+ Value : serpent .StringOf (& config .LogDir ),
80
+ },
81
+ {
73
82
Flag : "unprivileged" ,
74
83
Env : "BOUNDARY_UNPRIVILEGED" ,
75
84
Description : "Run in unprivileged mode (no network isolation, uses proxy environment variables)." ,
@@ -87,7 +96,11 @@ func BaseCommand() *serpent.Command {
87
96
func Run (ctx context.Context , config Config , args []string ) error {
88
97
ctx , cancel := context .WithCancel (ctx )
89
98
defer cancel ()
90
- logger := setupLogging (config .LogLevel )
99
+
100
+ logger , err := setupLogging (config )
101
+ if err != nil {
102
+ return fmt .Errorf ("could not set up logging: %v" , err )
103
+ }
91
104
username , uid , gid , homeDir , configDir := util .GetUserInfo ()
92
105
93
106
// Get command arguments
@@ -204,9 +217,9 @@ func Run(ctx context.Context, config Config, args []string) error {
204
217
}
205
218
206
219
// setupLogging creates a slog logger with the specified level
207
- func setupLogging (logLevel string ) * slog.Logger {
220
+ func setupLogging (config Config ) ( * slog.Logger , error ) {
208
221
var level slog.Level
209
- switch strings .ToLower (logLevel ) {
222
+ switch strings .ToLower (config . LogLevel ) {
210
223
case "error" :
211
224
level = slog .LevelError
212
225
case "warn" :
@@ -219,12 +232,34 @@ func setupLogging(logLevel string) *slog.Logger {
219
232
level = slog .LevelWarn // Default to warn if invalid level
220
233
}
221
234
235
+ logTarget := os .Stderr
236
+
237
+ if config .LogDir != "" {
238
+ // Set up the logging directory if it doesn't exist yet
239
+ if err := os .MkdirAll (config .LogDir , 0755 ); err != nil {
240
+ return nil , fmt .Errorf ("could not set up log dir %s: %v" , config .LogDir , err )
241
+ }
242
+
243
+ // Create a logfile (timestamp and pid to avoid race conditions with multiple boundary calls running)
244
+ logFilePath := fmt .Sprintf ("boundary-%s-%d.log" ,
245
+ time .Now ().Format ("2006-01-02_15-04-05" ),
246
+ os .Getpid ())
247
+
248
+ logFile , err := os .Create (filepath .Join (config .LogDir , logFilePath ))
249
+ if err != nil {
250
+ return nil , fmt .Errorf ("could not create log file %s: %v" , logFilePath , err )
251
+ }
252
+
253
+ // Set the log target to the file rather than stderr.
254
+ logTarget = logFile
255
+ }
256
+
222
257
// Create a standard slog logger with the appropriate level
223
- handler := slog .NewTextHandler (os . Stderr , & slog.HandlerOptions {
258
+ handler := slog .NewTextHandler (logTarget , & slog.HandlerOptions {
224
259
Level : level ,
225
260
})
226
261
227
- return slog .New (handler )
262
+ return slog .New (handler ), nil
228
263
}
229
264
230
265
// createJailer creates a new jail instance for the current platform
0 commit comments