Skip to content

Commit 88d581f

Browse files
committed
flag(server): new flag format
1 parent 584c3eb commit 88d581f

File tree

13 files changed

+626
-431
lines changed

13 files changed

+626
-431
lines changed

cmd/tracee-ebpf/main.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ import (
1111
"github.com/aquasecurity/tracee/common/logger"
1212
"github.com/aquasecurity/tracee/pkg/cmd"
1313
"github.com/aquasecurity/tracee/pkg/cmd/flags"
14-
"github.com/aquasecurity/tracee/pkg/cmd/flags/server"
1514
"github.com/aquasecurity/tracee/pkg/cmd/initialize"
1615
"github.com/aquasecurity/tracee/pkg/cmd/urfave"
1716
)
@@ -123,7 +122,7 @@ func main() {
123122
Usage: "path where tracee will install or lookup it's resources",
124123
},
125124
&cli.StringSliceFlag{
126-
Name: server.ServerFlag,
125+
Name: flags.ServerFlag,
127126
Usage: "Configure server endpoints. Examples: http-address=:3366, metrics, healthz, pprof, pyroscope",
128127
},
129128
&cli.StringSliceFlag{

cmd/tracee-rules/main.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ import (
1616

1717
"github.com/aquasecurity/tracee/common/capabilities"
1818
"github.com/aquasecurity/tracee/common/logger"
19-
"github.com/aquasecurity/tracee/pkg/cmd/flags/server"
19+
"github.com/aquasecurity/tracee/pkg/cmd/flags"
2020
"github.com/aquasecurity/tracee/pkg/signatures/engine"
2121
"github.com/aquasecurity/tracee/pkg/signatures/signature"
2222
"github.com/aquasecurity/tracee/types/detect"
@@ -141,7 +141,7 @@ func main() {
141141
}
142142

143143
// Prepare HTTP server with new unified server flags
144-
serverRunner, err := server.PrepareServer(c.StringSlice(server.ServerFlag))
144+
serverRunner, err := flags.PrepareServer(c.StringSlice(flags.ServerFlag))
145145
if err != nil {
146146
return err
147147
}
@@ -196,7 +196,7 @@ func main() {
196196
Usage: "print a list of events that currently loaded signatures require",
197197
},
198198
&cli.StringSliceFlag{
199-
Name: server.ServerFlag,
199+
Name: flags.ServerFlag,
200200
Usage: "Configure server endpoints. Examples: metrics, healthz",
201201
},
202202
&cli.BoolFlag{

cmd/tracee/cmd/root.go

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ import (
1515
"github.com/aquasecurity/tracee/common/logger"
1616
cmdcobra "github.com/aquasecurity/tracee/pkg/cmd/cobra"
1717
"github.com/aquasecurity/tracee/pkg/cmd/flags"
18-
"github.com/aquasecurity/tracee/pkg/cmd/flags/server"
1918
"github.com/aquasecurity/tracee/pkg/cmd/initialize"
2019
"github.com/aquasecurity/tracee/pkg/version"
2120
)
@@ -246,11 +245,11 @@ func initCmd() error {
246245
// Server flags
247246

248247
rootCmd.Flags().StringArray(
249-
server.ServerFlag,
250-
[]string{server.DefaultServerFlagValue},
248+
flags.ServerFlag,
249+
[]string{flags.DefaultServerFlagValue},
251250
`Configure server options and endpoints. Examples: http-address=:3366, grpc-address=unix:/var/run/tracee.sock, grpc (defaults to unix:/var/run/tracee.sock), metrics, healthz, pprof, pyroscope`)
252251

253-
err = viper.BindPFlag(server.ServerFlag, rootCmd.Flags().Lookup(server.ServerFlag))
252+
err = viper.BindPFlag(flags.ServerFlag, rootCmd.Flags().Lookup(flags.ServerFlag))
254253
if err != nil {
255254
return errfmt.WrapError(err)
256255
}

pkg/cmd/cobra/cobra.go

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ import (
1111
"github.com/aquasecurity/tracee/common/logger"
1212
"github.com/aquasecurity/tracee/pkg/cmd"
1313
"github.com/aquasecurity/tracee/pkg/cmd/flags"
14-
"github.com/aquasecurity/tracee/pkg/cmd/flags/server"
1514
"github.com/aquasecurity/tracee/pkg/cmd/initialize"
1615
"github.com/aquasecurity/tracee/pkg/cmd/initialize/sigs"
1716
"github.com/aquasecurity/tracee/pkg/cmd/printer"
@@ -329,18 +328,21 @@ func GetTraceeRunner(c *cobra.Command, version string) (cmd.Runner, error) {
329328
if err != nil {
330329
return runner, err
331330
}
332-
serverRunner, err := server.PrepareServer(serverFlag)
331+
serverRunner, err := flags.PrepareServer(serverFlag)
333332
if err != nil {
334333
return runner, err
335334
}
336335

337336
runner.HTTP = serverRunner.HTTP
338337
runner.GRPC = serverRunner.GRPC
339-
cfg.MetricsEnabled = runner.HTTP.MetricsEndpointEnabled()
340338
runner.TraceeConfig = cfg
341339
runner.Printer = p
342340
runner.InstallPath = traceeInstallPath
343341

342+
if runner.HTTP != nil {
343+
cfg.MetricsEnabled = runner.HTTP.IsMetricsEnabled()
344+
}
345+
344346
noSignaturesMode := viper.GetBool("no-signatures")
345347
if noSignaturesMode {
346348
logger.Debugw("No-signatures mode enabled, using same signature selection as normal mode for fair comparison")

pkg/cmd/cobra/config.go

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import (
77
"github.com/spf13/viper"
88

99
"github.com/aquasecurity/tracee/common/errfmt"
10-
serverflag "github.com/aquasecurity/tracee/pkg/cmd/flags/server"
10+
"github.com/aquasecurity/tracee/pkg/cmd/flags"
1111
)
1212

1313
type cliFlagger interface {
@@ -22,7 +22,7 @@ func GetFlagsFromViper(key string) ([]string, error) {
2222
rawValue := viper.Get(key)
2323

2424
switch key {
25-
case serverflag.ServerFlag:
25+
case flags.ServerFlag:
2626
flagger = &ServerConfig{}
2727
case "proctree":
2828
flagger = &ProcTreeConfig{}
@@ -94,27 +94,27 @@ type ServerConfig struct {
9494
}
9595

9696
func (s *ServerConfig) flags() []string {
97-
flags := make([]string, 0)
97+
f := make([]string, 0)
9898

9999
if s.GrpcAddress != "" {
100-
flags = append(flags, fmt.Sprintf("%s=%s", serverflag.GRPCAddressFlag, s.GrpcAddress))
100+
f = append(f, fmt.Sprintf("%s=%s", flags.GRPCAddressFlag, s.GrpcAddress))
101101
}
102102
if s.HttpAddress != "" {
103-
flags = append(flags, fmt.Sprintf("%s=%s", serverflag.HTTPAddressFlag, s.HttpAddress))
103+
f = append(f, fmt.Sprintf("%s=%s", flags.HTTPAddressFlag, s.HttpAddress))
104104
}
105105
if s.Metrics {
106-
flags = append(flags, serverflag.MetricsEndpointFlag)
106+
f = append(f, flags.MetricsEndpointFlag)
107107
}
108108
if s.Pprof {
109-
flags = append(flags, serverflag.PProfEndpointFlag)
109+
f = append(f, flags.PProfEndpointFlag)
110110
}
111111
if s.Healthz {
112-
flags = append(flags, serverflag.HealthzEndpointFlag)
112+
f = append(f, flags.HealthzEndpointFlag)
113113
}
114114
if s.Pyroscope {
115-
flags = append(flags, serverflag.PyroscopeAgentEndpointFlag)
115+
f = append(f, flags.PyroscopeAgentEndpointFlag)
116116
}
117-
return flags
117+
return f
118118
}
119119

120120
type SocketConfig struct {

pkg/cmd/flags/server.go

Lines changed: 193 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,193 @@
1+
package flags
2+
3+
import (
4+
"net"
5+
"os"
6+
"strconv"
7+
"strings"
8+
9+
"github.com/aquasecurity/tracee/common/errfmt"
10+
"github.com/aquasecurity/tracee/pkg/server/grpc"
11+
"github.com/aquasecurity/tracee/pkg/server/http"
12+
)
13+
14+
const (
15+
ServerFlag = "server"
16+
HTTPAddressFlag = "http-address"
17+
GRPCAddressFlag = "grpc-address"
18+
GRPCEndpointFlag = "grpc"
19+
MetricsEndpointFlag = "metrics"
20+
HealthzEndpointFlag = "healthz"
21+
PProfEndpointFlag = "pprof"
22+
PyroscopeAgentEndpointFlag = "pyroscope"
23+
DefaultServerFlagValue = ""
24+
25+
defaultHTTPAddress = ":3366"
26+
defaultGRPCPort = "4466"
27+
defaultGRPCPath = "/var/run/tracee.sock"
28+
)
29+
30+
type Server struct {
31+
HTTP *http.Server
32+
GRPC *grpc.Server
33+
}
34+
35+
// PrepareServer prepares the server based on the server flags
36+
func PrepareServer(serverSlice []string) (*Server, error) {
37+
var err error
38+
var server Server
39+
var (
40+
enableMetrics = false
41+
enableHealthz = false
42+
enablePProf = false
43+
enablePyroscope = false
44+
)
45+
for _, endpoint := range serverSlice {
46+
values := strings.SplitN(endpoint, "=", 2)
47+
if len(values) != 2 {
48+
return nil, errfmt.Errorf("invalid server flag: '%s', use 'trace man server' for more info", endpoint)
49+
}
50+
51+
flagName := values[0]
52+
flagValue := values[1]
53+
54+
switch flagName {
55+
case HTTPAddressFlag: // http-address=<host:port>
56+
err = validateHTTPAddr(flagValue)
57+
if err != nil {
58+
return nil, err
59+
}
60+
server.HTTP = http.New(flagValue)
61+
case GRPCAddressFlag: // grpc-address=protocol:address
62+
protocol, address, err := parseAndValidateGRPCAddr(flagValue)
63+
if err != nil {
64+
return nil, err
65+
}
66+
server.GRPC = grpc.New(protocol, address)
67+
case MetricsEndpointFlag: // metrics
68+
enableMetrics, err = validateAndGetBool(flagName, flagValue)
69+
if err != nil {
70+
return nil, err
71+
}
72+
case HealthzEndpointFlag: // healthz
73+
enableHealthz, err = validateAndGetBool(flagName, flagValue)
74+
if err != nil {
75+
return nil, err
76+
}
77+
case PProfEndpointFlag: // pprof
78+
enablePProf, err = validateAndGetBool(flagName, flagValue)
79+
if err != nil {
80+
return nil, err
81+
}
82+
case PyroscopeAgentEndpointFlag: // pyroscope
83+
enablePyroscope, err = validateAndGetBool(flagName, flagValue)
84+
if err != nil {
85+
return nil, err
86+
}
87+
default:
88+
return nil, errfmt.Errorf("invalid server flag: '%s', use 'trace man server' for more info", flagName)
89+
}
90+
}
91+
92+
if enableMetrics || enableHealthz || enablePProf || enablePyroscope {
93+
// if a flag is set, but the server is not configured, set a default HTTP server
94+
if server.HTTP == nil {
95+
server.HTTP = http.New(defaultHTTPAddress)
96+
}
97+
if enableMetrics {
98+
server.HTTP.EnableMetricsEndpoint()
99+
}
100+
if enableHealthz {
101+
server.HTTP.EnableHealthzEndpoint()
102+
}
103+
if enablePProf {
104+
server.HTTP.EnablePProfEndpoint()
105+
}
106+
if enablePyroscope {
107+
err = server.HTTP.EnablePyroAgent()
108+
if err != nil {
109+
return nil, err
110+
}
111+
}
112+
}
113+
114+
return &server, nil
115+
}
116+
117+
func validateHTTPAddr(addr string) error {
118+
// Split the address into host and port.
119+
host, portStr, err := net.SplitHostPort(addr)
120+
if err != nil {
121+
return errfmt.Errorf("invalid http address: '%s', use 'trace man server' for more info", addr)
122+
}
123+
124+
// If a host is specified, do basic validation
125+
if host != "" {
126+
// Accept IP addresses and basic hostname formats
127+
// For CLI tools, we can be permissive and let network operations
128+
// handle detailed validation when the server actually starts
129+
if net.ParseIP(host) == nil {
130+
// Basic hostname validation: no spaces, reasonable length
131+
if len(host) > 253 || strings.Contains(host, " ") {
132+
return errfmt.Errorf("invalid http host: '%s', use 'trace man server' for more info", host)
133+
}
134+
}
135+
}
136+
137+
return validatePort(portStr)
138+
}
139+
140+
func parseAndValidateGRPCAddr(addr string) (string, string, error) {
141+
// Split the address into protocol and address.
142+
values := strings.SplitN(addr, ":", 2)
143+
protocol := values[0]
144+
145+
switch protocol {
146+
case "tcp":
147+
if len(values) == 2 {
148+
port := values[1]
149+
err := validatePort(port)
150+
if err != nil {
151+
return "", "", err
152+
}
153+
return protocol, port, nil
154+
}
155+
return protocol, defaultGRPCPort, nil
156+
case "unix":
157+
if len(values) == 2 {
158+
path := values[1]
159+
if _, err := os.Stat(path); err == nil {
160+
err = os.Remove(path)
161+
if err != nil {
162+
return "", "", errfmt.Errorf("failed to cleanup gRPC listening address (%s): %v", path, err)
163+
}
164+
}
165+
return protocol, path, nil
166+
}
167+
return protocol, defaultGRPCPath, nil
168+
}
169+
170+
return "", "", errfmt.Errorf("invalid grpc protocol: '%s', use 'trace man server' for more info", protocol)
171+
}
172+
173+
func validateAndGetBool(flagName, value string) (bool, error) {
174+
switch value {
175+
case "true":
176+
return true, nil
177+
case "false":
178+
return false, nil
179+
}
180+
181+
return false, errfmt.Errorf("invalid flag value '%s' for flag '%s', use 'trace man server' for more info", value, flagName)
182+
}
183+
184+
func validatePort(port string) error {
185+
portInt, err := strconv.Atoi(port)
186+
if err != nil {
187+
return errfmt.Errorf("invalid port number '%s', use 'trace man server' for more info", port)
188+
}
189+
if portInt < 0 || portInt > 65535 {
190+
return errfmt.Errorf("invalid port number '%s', value must be between 0 and 65535, use 'trace man server' for more info", port)
191+
}
192+
return nil
193+
}

0 commit comments

Comments
 (0)