diff --git a/cmd/tracee/cmd/man.go b/cmd/tracee/cmd/man.go index 41cc39f29b93..fbe61f48f7a1 100644 --- a/cmd/tracee/cmd/man.go +++ b/cmd/tracee/cmd/man.go @@ -61,6 +61,7 @@ func init() { scopeCmd, serverCmd, eventCmd, + storesCmd, ) } @@ -177,6 +178,15 @@ var eventCmd = &cobra.Command{ }, } +var storesCmd = &cobra.Command{ + Use: "stores", + Aliases: []string{}, + Short: "Show manual page for the --stores flag", + RunE: func(cmd *cobra.Command, args []string) error { + return runManForFlag("stores") + }, +} + // runManForFlag runs man for the specified flag name func runManForFlag(flagName string) error { // Read the embedded manual page diff --git a/cmd/tracee/cmd/root.go b/cmd/tracee/cmd/root.go index 5844f8e75030..f80264cca297 100644 --- a/cmd/tracee/cmd/root.go +++ b/cmd/tracee/cmd/root.go @@ -230,27 +230,14 @@ func initCmd() error { return errfmt.WrapError(err) } - // Process Tree flags - - rootCmd.Flags().StringArrayP( - "proctree", - "t", - []string{"source=none"}, - "[source=[events|signals|both]...]\tControl process tree options", - ) - err = viper.BindPFlag("proctree", rootCmd.Flags().Lookup("proctree")) - if err != nil { - return errfmt.WrapError(err) - } - - // DNS Cache flags + // Stores flags rootCmd.Flags().StringArray( - "dnscache", - []string{"none"}, - "\t\t\t\t\tEnable DNS Cache", + flags.StoresFlag, + []string{}, + "\t\t\t\t\tStores configurations", ) - err = viper.BindPFlag("dnscache", rootCmd.Flags().Lookup("dnscache")) + err = viper.BindPFlag(flags.StoresFlag, rootCmd.Flags().Lookup(flags.StoresFlag)) if err != nil { return errfmt.WrapError(err) } diff --git a/deploy/helm/tracee/templates/tracee-config.yaml b/deploy/helm/tracee/templates/tracee-config.yaml index 941df33b6f68..d0ae0222b279 100644 --- a/deploy/helm/tracee/templates/tracee-config.yaml +++ b/deploy/helm/tracee/templates/tracee-config.yaml @@ -53,4 +53,34 @@ data: {{- if .Values.config.blobPerfBufferSize }} blob-perf-buffer-size: {{ .Values.config.blobPerfBufferSize}} {{- end }} + {{- if or .Values.config.stores.dns.enabled .Values.config.stores.dns.maxEntries .Values.config.stores.process.enabled .Values.config.stores.process.maxProcesses .Values.config.stores.process.maxThreads .Values.config.stores.process.source .Values.config.stores.process.useProcfs }} + stores: + {{- if or .Values.config.stores.dns.enabled .Values.config.stores.dns.maxEntries }} + dns: + {{- if .Values.config.stores.dns.enabled }} + enabled: {{ .Values.config.stores.dns.enabled }} + {{- end }} + {{- if .Values.config.stores.dns.maxEntries }} + max-entries: {{ .Values.config.stores.dns.maxEntries }} + {{- end }} + {{- end }} + {{- if or .Values.config.stores.process.enabled .Values.config.stores.process.maxProcesses .Values.config.stores.process.maxThreads .Values.config.stores.process.source .Values.config.stores.process.useProcfs }} + process: + {{- if .Values.config.stores.process.enabled }} + enabled: {{ .Values.config.stores.process.enabled }} + {{- end }} + {{- if .Values.config.stores.process.maxProcesses }} + max-processes: {{ .Values.config.stores.process.maxProcesses }} + {{- end }} + {{- if .Values.config.stores.process.maxThreads }} + max-threads: {{ .Values.config.stores.process.maxThreads }} + {{- end }} + {{- if .Values.config.stores.process.source }} + source: {{ .Values.config.stores.process.source }} + {{- end }} + {{- if .Values.config.stores.process.useProcfs }} + use-procfs: {{ .Values.config.stores.process.useProcfs }} + {{- end }} + {{- end }} + {{- end }} {{- end }} diff --git a/deploy/helm/tracee/values.yaml b/deploy/helm/tracee/values.yaml index b3aebeb18834..f937582cbbf6 100644 --- a/deploy/helm/tracee/values.yaml +++ b/deploy/helm/tracee/values.yaml @@ -108,6 +108,16 @@ config: # port: "8080" # protocol: http # timeout: 3s + stores: + dns: + enabled: "" + maxEntries: "" + process: + enabled: "" + maxProcesses: "" + maxThreads: "" + source: "" + useProcfs: "" defaultPolicy: true diff --git a/docs/docs/advanced/data-sources/builtin/dns.md b/docs/docs/advanced/data-sources/builtin/dns.md index 7061193f418a..47d900132126 100644 --- a/docs/docs/advanced/data-sources/builtin/dns.md +++ b/docs/docs/advanced/data-sources/builtin/dns.md @@ -8,7 +8,7 @@ These relations can be queried in signatures through a data source. To switch on the `DNS Cache` feature, run the command: ```bash -sudo tracee --output option:sort-events --output json --output option:parse-arguments --dnscache enable --events +sudo tracee --output option:sort-events --output json --output option:parse-arguments --stores dns --events ``` The underlying structure is populated using the core [net_packet_dns](../../../events/builtin/man/network/net_packet_dns.md) event and its payload. @@ -16,16 +16,13 @@ The underlying structure is populated using the core [net_packet_dns](../../../e ## Command Line Option ```bash -$ tracee --dnscache help -Select different options for the DNS cache. - Example: - --dnscache enable | enable with default values (see below). - --dnscache size=X | will cache up to X dns query trees - further queries may be cached regardless (default: 5000). + --stores dns | enable the DNS cache with default settings. + --stores dns.max-entries=X | enable the DNS cache and cache up to X dns query trees - further queries may be cached regardless (default: 5000). + | Note: dns.max-entries automatically enables DNS, so --stores dns is not needed. -Use comma OR use the flag multiple times to choose multiple options: - --dnscache size=A - --dnscache enable +Use the flag multiple times to choose multiple options: + --stores dns.max-entries=5000 | This automatically enables DNS, no need for --stores dns ``` Consider for your usecase, how many query trees would you like to store? If you will frequently check only a few addresses, consider lowering the size. diff --git a/docs/docs/advanced/data-sources/builtin/process-tree.md b/docs/docs/advanced/data-sources/builtin/process-tree.md index cf369d8e6504..9f8722b6a64e 100644 --- a/docs/docs/advanced/data-sources/builtin/process-tree.md +++ b/docs/docs/advanced/data-sources/builtin/process-tree.md @@ -7,9 +7,11 @@ The `Process Tree` feature offers a structured view of processes and threads act To switch on the `Process Tree` feature, run the command: ```bash -sudo tracee --output option:sort-events --output json --output option:parse-arguments --proctree source=both --events +sudo tracee --output option:sort-events --output json --output option:parse-arguments --stores process.source=both --events ``` +Note: `process.source` automatically enables process, so `--stores process` is not needed. + The underlying structure is populated using the core `sched_process_fork`, `sched_process_exec`, and `sched_process_exit` events and their data. There's also an option to bootstrap the process tree through a secondary route using internal signal events. > Introducing this secondary event source is strategic: it reduces interference with actively traced events, leading to more accurate and granular updates in the process tree. @@ -27,19 +29,24 @@ The process tree query the procfs upon initialization and during runtime to fill ```bash Example: - --proctree source=[none|events|signals|both] - none | process tree is disabled (default). + --stores process | enable the process tree with default settings. + --stores process.source=[signals|events|both] + | enable the process tree and set the source. + | Note: process.source automatically enables process, so --stores process is not needed. + | If no source is specified, the default is 'signals'. + signals | process tree is built from signals (default). events | process tree is built from events. - signals | process tree is built from signals. both | process tree is built from both events and signals. - --proctree process-cache=8192 | will cache up to 8192 processes in the tree (LRU cache). - --proctree thread-cache=16384 | will cache up to 16384 threads in the tree (LRU cache). - --proctree disable-procfs | will disable procfs entirely. - --proctree disable-procfs-query | will disable procfs quering during runtime. - -Use comma OR use the flag multiple times to choose multiple options: - --proctree source=A,process-cache=B,thread-cache=C - --proctree process-cache=X --proctree thread-cache=Y + --stores process.max-processes=8192 | enable the process tree and cache up to 8192 processes (LRU cache). + | Note: process.max-processes automatically enables process, so --stores process is not needed. + --stores process.max-threads=16384 | enable the process tree and cache up to 16384 threads (LRU cache). + | Note: process.max-threads automatically enables process, so --stores process is not needed. + --stores process.use-procfs | enable the process tree and enable procfs initialization and querying. + | Note: process.use-procfs automatically enables process, so --stores process is not needed. + +Use the flag multiple times to choose multiple options: + --stores process.source=both --stores process.max-processes=8192 + | This automatically enables process, no need for --stores process ``` ## Internal Data Organization diff --git a/docs/docs/flags/stores.1.md b/docs/docs/flags/stores.1.md new file mode 100644 index 000000000000..3d107d106c9a --- /dev/null +++ b/docs/docs/flags/stores.1.md @@ -0,0 +1,109 @@ +--- +title: TRACEE-STORES +section: 1 +header: Tracee Stores Flag Manual +date: 2025/12 +... + +## NAME + +tracee **\-\-stores** - Configure data stores for DNS cache and process tree + +## SYNOPSIS + +tracee **\-\-stores** [dns|dns.max-entries=*size*|process|process.max-processes=*size*|process.max-threads=*size*|process.source=*source*|process.use-procfs] [**\-\-stores** ...] + +## DESCRIPTION + +The **\-\-stores** flag allows you to configure data stores for DNS cache and process tree functionality. + +### DNS Store Options + +- **dns**: Enable the DNS cache store with default settings. When enabled, Tracee will cache DNS query information for enrichment of network events. + +- **dns.max-entries**=*size*: Enable the DNS cache store and set the maximum number of DNS query trees to cache. Default is 5000. Further queries may be cached regardless once the limit is reached. **Note**: Using this option automatically enables DNS, so you don't need to also specify `--stores dns`. + +### Process Store Options + +- **process**: Enable the process tree store with default settings. When enabled, Tracee will maintain a tree of processes and threads for enrichment of events. + +- **process.max-processes**=*size*: Enable the process tree store and set the maximum number of processes to cache in the process tree. Default is 10928. This is an LRU cache that will evict least recently accessed entries when full. **Note**: Using this option automatically enables process, so you don't need to also specify `--stores process`. + +- **process.max-threads**=*size*: Enable the process tree store and set the maximum number of threads to cache in the process tree. Default is 21856. This is an LRU cache that will evict least recently accessed entries when full. **Note**: Using this option automatically enables process, so you don't need to also specify `--stores process`. + +- **process.source**=*source*: Enable the process tree store and set the source for process tree enrichment. Valid values are: + - **signals**: Process tree is built from signals (default). + - **events**: Process tree is built from events. + - **both**: Process tree is built from both events and signals. + + **Note**: Using this option automatically enables process, so you don't need to also specify `--stores process`. If no source is specified, the default is `signals`. + +- **process.use-procfs**: Enable the process tree store and enable procfs initialization and querying. When enabled, Tracee will: + - Scan procfs during initialization to fill all existing processes and threads. + - Query specific processes at runtime in case of missing information caused by missing events. + + **Note**: Using this option automatically enables process, so you don't need to also specify `--stores process`. The procfs query might increase the feature toll on CPU and memory. The runtime query might have a snowball effect on lost events, as it will reduce the system resources in the processes of filling missing information. + +## EXAMPLES + +1. Enable DNS cache: + ```console + --stores dns + ``` + +2. Enable DNS cache with custom size: + ```console + --stores dns.max-entries=10000 + ``` + + Note: `dns.max-entries` automatically enables DNS, so `--stores dns` is not needed. + +3. Enable process tree: + ```console + --stores process + ``` + +4. Enable process tree with custom cache sizes: + ```console + --stores process.max-processes=8192 --stores process.max-threads=16384 + ``` + + Note: `process.max-processes` and `process.max-threads` automatically enable process, so `--stores process` is not needed. + +5. Enable process tree with events source: + ```console + --stores process.source=events + ``` + + Note: `process.source` automatically enables process, so `--stores process` is not needed. + +6. Enable process tree with both events and signals sources: + ```console + --stores process.source=both + ``` + + Note: `process.source` automatically enables process, so `--stores process` is not needed. + +7. Enable process tree with procfs support: + ```console + --stores process.use-procfs + ``` + + Note: `process.use-procfs` automatically enables process, so `--stores process` is not needed. + +8. Combine DNS and process stores: + ```console + --stores dns.max-entries=5000 --stores process.source=both --stores process.max-processes=8192 + ``` + + Note: Since `dns.max-entries` and `process.source` automatically enable their respective stores, you don't need `--stores dns` or `--stores process`. + +9. Complete configuration example: + ```console + --stores dns.max-entries=5000 --stores process.max-processes=8192 --stores process.max-threads=16384 --stores process.source=both --stores process.use-procfs + ``` + + Note: All process options automatically enable process, and `dns.max-entries` automatically enables DNS, so you don't need `--stores dns` or `--stores process`. + +Please refer to the [DNS data source documentation](../advanced/data-sources/builtin/dns.md) and [Process Tree data source documentation](../advanced/data-sources/builtin/process-tree.md) for more information. + diff --git a/docs/docs/install/config/index.md b/docs/docs/install/config/index.md index 7f5398903b7a..b9b57594a6b7 100644 --- a/docs/docs/install/config/index.md +++ b/docs/docs/install/config/index.md @@ -50,17 +50,21 @@ A complete config file with all available options can be found [here](https://gi pyroscope: true ``` -### Process Tree +### Stores (Process Tree and DNS Cache) -- **`--proctree` (`-t`)**: Controls process tree options. +- **`--stores`**: Controls process tree and DNS cache options. - __NOTE__: You can view more in the [Process Tree section](../../advanced/data-sources/builtin/process-tree.md). + __NOTE__: You can view more in the [Process Tree section](../../advanced/data-sources/builtin/process-tree.md) and [DNS Cache section](../../advanced/data-sources/builtin/dns.md). YAML: ```yaml - proctree: - - process + stores: + process: + enabled: true + source: both + dns: + enabled: true ``` ### Runtime @@ -116,17 +120,6 @@ A complete config file with all available options can be found [here](https://gi socket: /var/run/docker.sock ``` -### DNS Cache - -- **`--dnscache`**: Enables DNS caching in Tracee. - - __NOTE__: You can view more in the [DNS Cache section](../../advanced/data-sources/builtin/dns.md). - - YAML: - ```yaml - dnscache: enable - ``` - ### Capabilities - **`--capabilities` (`-C`)**: Define specific capabilities for Tracee to run with. This allows you to either bypass, add, or drop certain capabilities based on your security and operational needs. diff --git a/docs/docs/policies/usage/cli.md b/docs/docs/policies/usage/cli.md index 96061d9d8911..d96371a0274b 100644 --- a/docs/docs/policies/usage/cli.md +++ b/docs/docs/policies/usage/cli.md @@ -68,11 +68,14 @@ signatures-dir: "" capabilities: bypass: false -proctree: - source: both - cache: - process: 8192 - thread: 8192 +stores: + process: + enabled: true + source: both + max-processes: 8192 + max-threads: 8192 + dns: + enabled: false # logging diff --git a/docs/man/stores.1 b/docs/man/stores.1 new file mode 100644 index 000000000000..8bd454a041c4 --- /dev/null +++ b/docs/man/stores.1 @@ -0,0 +1,183 @@ +.\" Automatically generated by Pandoc 3.2 +.\" +.TH "TRACEE\-STORES" "1" "2025/12" "" "Tracee Stores Flag Manual" +.SS NAME +tracee \f[B]\-\-stores\f[R] \- Configure data stores for DNS cache and +process tree +.SS SYNOPSIS +tracee \f[B]\-\-stores\f[R] +[dns|dns.max\-entries=\f[I]size\f[R]|process|process.max\-processes=\f[I]size\f[R]|process.max\-threads=\f[I]size\f[R]|process.source=\f[I]source\f[R]|process.use\-procfs] +[\f[B]\-\-stores\f[R] \&...] +.SS DESCRIPTION +The \f[B]\-\-stores\f[R] flag allows you to configure data stores for +DNS cache and process tree functionality. +.SS DNS Store Options +.IP \[bu] 2 +\f[B]dns\f[R]: Enable the DNS cache store with default settings. +When enabled, Tracee will cache DNS query information for enrichment of +network events. +.IP \[bu] 2 +\f[B]dns.max\-entries\f[R]=\f[I]size\f[R]: Enable the DNS cache store +and set the maximum number of DNS query trees to cache. +Default is 5000. +Further queries may be cached regardless once the limit is reached. +\f[B]Note\f[R]: Using this option automatically enables DNS, so you +don\[cq]t need to also specify \f[CR]\-\-stores dns\f[R]. +.SS Process Store Options +.IP \[bu] 2 +\f[B]process\f[R]: Enable the process tree store with default settings. +When enabled, Tracee will maintain a tree of processes and threads for +enrichment of events. +.IP \[bu] 2 +\f[B]process.max\-processes\f[R]=\f[I]size\f[R]: Enable the process tree +store and set the maximum number of processes to cache in the process +tree. +Default is 10928. +This is an LRU cache that will evict least recently accessed entries +when full. +\f[B]Note\f[R]: Using this option automatically enables process, so you +don\[cq]t need to also specify \f[CR]\-\-stores process\f[R]. +.IP \[bu] 2 +\f[B]process.max\-threads\f[R]=\f[I]size\f[R]: Enable the process tree +store and set the maximum number of threads to cache in the process +tree. +Default is 21856. +This is an LRU cache that will evict least recently accessed entries +when full. +\f[B]Note\f[R]: Using this option automatically enables process, so you +don\[cq]t need to also specify \f[CR]\-\-stores process\f[R]. +.IP \[bu] 2 +\f[B]process.source\f[R]=\f[I]source\f[R]: Enable the process tree store +and set the source for process tree enrichment. +Valid values are: +.RS 2 +.IP \[bu] 2 +\f[B]signals\f[R]: Process tree is built from signals (default). +.IP \[bu] 2 +\f[B]events\f[R]: Process tree is built from events. +.IP \[bu] 2 +\f[B]both\f[R]: Process tree is built from both events and signals. +.PP +\f[B]Note\f[R]: Using this option automatically enables process, so you +don\[cq]t need to also specify \f[CR]\-\-stores process\f[R]. +If no source is specified, the default is \f[CR]signals\f[R]. +.RE +.IP \[bu] 2 +\f[B]process.use\-procfs\f[R]: Enable the process tree store and enable +procfs initialization and querying. +When enabled, Tracee will: +.RS 2 +.IP \[bu] 2 +Scan procfs during initialization to fill all existing processes and +threads. +.IP \[bu] 2 +Query specific processes at runtime in case of missing information +caused by missing events. +.PP +\f[B]Note\f[R]: Using this option automatically enables process, so you +don\[cq]t need to also specify \f[CR]\-\-stores process\f[R]. +The procfs query might increase the feature toll on CPU and memory. +The runtime query might have a snowball effect on lost events, as it +will reduce the system resources in the processes of filling missing +information. +.RE +.SS EXAMPLES +.IP "1." 3 +Enable DNS cache: +.RS 4 +.IP +.EX +\-\-stores dns +.EE +.RE +.IP "2." 3 +Enable DNS cache with custom size: +.RS 4 +.IP +.EX +\-\-stores dns.max\-entries=10000 +.EE +.PP +Note: \f[CR]dns.max\-entries\f[R] automatically enables DNS, so +\f[CR]\-\-stores dns\f[R] is not needed. +.RE +.IP "3." 3 +Enable process tree: +.RS 4 +.IP +.EX +\-\-stores process +.EE +.RE +.IP "4." 3 +Enable process tree with custom cache sizes: +.RS 4 +.IP +.EX +\-\-stores process.max\-processes=8192 \-\-stores process.max\-threads=16384 +.EE +.PP +Note: \f[CR]process.max\-processes\f[R] and +\f[CR]process.max\-threads\f[R] automatically enable process, so +\f[CR]\-\-stores process\f[R] is not needed. +.RE +.IP "5." 3 +Enable process tree with events source: +.RS 4 +.IP +.EX +\-\-stores process.source=events +.EE +.PP +Note: \f[CR]process.source\f[R] automatically enables process, so +\f[CR]\-\-stores process\f[R] is not needed. +.RE +.IP "6." 3 +Enable process tree with both events and signals sources: +.RS 4 +.IP +.EX +\-\-stores process.source=both +.EE +.PP +Note: \f[CR]process.source\f[R] automatically enables process, so +\f[CR]\-\-stores process\f[R] is not needed. +.RE +.IP "7." 3 +Enable process tree with procfs support: +.RS 4 +.IP +.EX +\-\-stores process.use\-procfs +.EE +.PP +Note: \f[CR]process.use\-procfs\f[R] automatically enables process, so +\f[CR]\-\-stores process\f[R] is not needed. +.RE +.IP "8." 3 +Combine DNS and process stores: +.RS 4 +.IP +.EX +\-\-stores dns.max\-entries=5000 \-\-stores process.source=both \-\-stores process.max\-processes=8192 +.EE +.PP +Note: Since \f[CR]dns.max\-entries\f[R] and \f[CR]process.source\f[R] +automatically enable their respective stores, you don\[cq]t need +\f[CR]\-\-stores dns\f[R] or \f[CR]\-\-stores process\f[R]. +.RE +.IP "9." 3 +Complete configuration example: +.RS 4 +.IP +.EX +\-\-stores dns.max\-entries=5000 \-\-stores process.max\-processes=8192 \-\-stores process.max\-threads=16384 \-\-stores process.source=both \-\-stores process.use\-procfs +.EE +.PP +Note: All process options automatically enable process, and +\f[CR]dns.max\-entries\f[R] automatically enables DNS, so you don\[cq]t +need \f[CR]\-\-stores dns\f[R] or \f[CR]\-\-stores process\f[R]. +.RE +.PP +Please refer to the DNS data source documentation and Process Tree data +source documentation for more information. diff --git a/examples/config/global_config.json b/examples/config/global_config.json index 778440b03543..169db943d2ae 100644 --- a/examples/config/global_config.json +++ b/examples/config/global_config.json @@ -3,9 +3,15 @@ "cache": [ "none" ], - "proctree": [ - "none" - ], + "stores": { + "process": { + "enabled": false, + "source": "signals" + }, + "dns": { + "enabled": false + } + }, "capabilities": [], "containers": [], "healthz": false, @@ -24,4 +30,4 @@ "pprof": false, "pyroscope": false, "signatures-dir": "" -} +} \ No newline at end of file diff --git a/examples/config/global_config.yaml b/examples/config/global_config.yaml index 42e557cebd7e..fa399bb7df05 100644 --- a/examples/config/global_config.yaml +++ b/examples/config/global_config.yaml @@ -12,11 +12,15 @@ policy: - /path/to/policy.yaml #- /path/to/policy-directory -proctree: - source: none - # cache: - # process: 8192 - # thread: 4096 +stores: + process: + enabled: false + source: signals + # max-processes: 8192 + # max-threads: 4096 + dns: + enabled: false + # max-entries: 5000 capabilities: bypass: false @@ -35,7 +39,6 @@ server: healthz: true pprof: true pyroscope: true -dnscache: enable containers: enrich: false diff --git a/pkg/cmd/cobra/cobra.go b/pkg/cmd/cobra/cobra.go index 1294d18579f6..1bf8b9df0a3b 100644 --- a/pkg/cmd/cobra/cobra.go +++ b/pkg/cmd/cobra/cobra.go @@ -150,32 +150,19 @@ func GetTraceeRunner(c *cobra.Command, version string) (cmd.Runner, error) { cfg.CgroupFSPath = res.CgroupfsPath cfg.CgroupFSForce = res.CgroupfsForce - // Process Tree command line flags - - procTreeFlags, err := flags.GetFlagsFromViper("proctree") - if err != nil { - return runner, err - } - - procTree, err := flags.PrepareProcTree(procTreeFlags) - if err != nil { - return runner, err - } - cfg.ProcTree = procTree - - // DNS Cache command line flags - - dnsCacheFlags, err := flags.GetFlagsFromViper("dnscache") + // Stores command line flags + storesFlags, err := flags.GetFlagsFromViper(flags.StoresFlag) if err != nil { return runner, err } - dnsCache, err := flags.PrepareDnsCache(dnsCacheFlags) + stores, err := flags.PrepareStores(storesFlags) if err != nil { return runner, err } - cfg.DNSCacheConfig = dnsCache + cfg.ProcTree = stores.GetProcTreeConfig() + cfg.DNSCacheConfig = stores.GetDNSCacheConfig() // Capture command line flags - via cobra flag diff --git a/pkg/cmd/flags/config.go b/pkg/cmd/flags/config.go index ee91a2f4844e..b3fdb5b2881d 100644 --- a/pkg/cmd/flags/config.go +++ b/pkg/cmd/flags/config.go @@ -23,8 +23,6 @@ func GetFlagsFromViper(key string) ([]string, error) { switch key { case ServerFlag: flagger = &ServerConfig{} - case "proctree": - flagger = &ProcTreeConfig{} case "capabilities": flagger = &CapabilitiesConfig{} case "containers": @@ -33,10 +31,10 @@ func GetFlagsFromViper(key string) ([]string, error) { flagger = &LogConfig{} case "output": flagger = &OutputConfig{} - case "dnscache": - flagger = &DnsCacheConfig{} - case "runtime": + case RuntimeFlag: flagger = &RuntimeConfig{} + case StoresFlag: + flagger = &StoresConfig{} default: return nil, errfmt.Errorf("unrecognized key: %s", key) } @@ -124,64 +122,6 @@ func (c *SocketConfig) flags() []string { return flags } -// -// proctree flag -// - -type ProcTreeConfig struct { - Source string `mapstructure:"source"` - Cache ProcTreeCacheConfig `mapstructure:"cache"` -} - -type ProcTreeCacheConfig struct { - Process int `mapstructure:"process"` - Thread int `mapstructure:"thread"` -} - -func (c *ProcTreeConfig) flags() []string { - flags := make([]string, 0) - - if c.Source != "" { - if c.Source == "none" { - flags = append(flags, "none") - } else { - flags = append(flags, fmt.Sprintf("source=%s", c.Source)) - } - } - if c.Cache.Process != 0 { - flags = append(flags, fmt.Sprintf("process-cache=%d", c.Cache.Process)) - } - if c.Cache.Thread != 0 { - flags = append(flags, fmt.Sprintf("thread-cache=%d", c.Cache.Thread)) - } - - return flags -} - -// -// dnscache flag -// - -type DnsCacheConfig struct { - Enable bool `mapstructure:"enable"` - Size int `mapstructure:"size"` -} - -func (c *DnsCacheConfig) flags() []string { - flags := make([]string, 0) - - if !c.Enable { - flags = append(flags, "none") - return flags - } - - if c.Size != 0 { - flags = append(flags, fmt.Sprintf("size=%d", c.Size)) - } - - return flags -} - // // capabilities flag // diff --git a/pkg/cmd/flags/config_test.go b/pkg/cmd/flags/config_test.go index 7c4b14cab4ae..395ff1737eeb 100644 --- a/pkg/cmd/flags/config_test.go +++ b/pkg/cmd/flags/config_test.go @@ -23,34 +23,113 @@ func TestGetFlagsFromViper(t *testing.T) { expectedFlags []string }{ { - name: "Test proctree configuration (cli flags)", + name: "Test stores configuration (cli flags - process only)", yamlContent: ` -proctree: - - source=events - - process-cache=8192 - - thread-cache=4096 +stores: + - process + - process.source=events + - process.max-processes=8192 + - process.max-threads=4096 `, - key: "proctree", + key: "stores", expectedFlags: []string{ - "source=events", - "process-cache=8192", - "thread-cache=4096", + "process", + "process.source=events", + "process.max-processes=8192", + "process.max-threads=4096", }, }, { - name: "Test proctree configuration (structured flags)", + name: "Test stores configuration (structured flags - process only)", yamlContent: ` -proctree: - source: events - cache: - process: 8192 - thread: 4096 +stores: + process: + enabled: true + source: events + max-processes: 8192 + max-threads: 4096 +`, + key: "stores", + expectedFlags: []string{ + "process", + "process.source=events", + "process.max-processes=8192", + "process.max-threads=4096", + }, + }, + { + name: "Test stores configuration (cli flags - DNS only)", + yamlContent: ` +stores: + - dns + - dns.max-entries=1024 +`, + key: "stores", + expectedFlags: []string{ + "dns", + "dns.max-entries=1024", + }, + }, + { + name: "Test stores configuration (structured flags - DNS only)", + yamlContent: ` +stores: + dns: + enabled: true + max-entries: 1024 +`, + key: "stores", + expectedFlags: []string{ + "dns", + "dns.max-entries=1024", + }, + }, + { + name: "Test stores configuration (cli flags - all options)", + yamlContent: ` +stores: + - dns + - dns.max-entries=2048 + - process + - process.source=both + - process.max-processes=8192 + - process.max-threads=4096 + - process.use-procfs +`, + key: "stores", + expectedFlags: []string{ + "dns", + "dns.max-entries=2048", + "process", + "process.source=both", + "process.max-processes=8192", + "process.max-threads=4096", + "process.use-procfs", + }, + }, + { + name: "Test stores configuration (structured flags - all options)", + yamlContent: ` +stores: + dns: + enabled: true + max-entries: 2048 + process: + enabled: true + source: both + max-processes: 8192 + max-threads: 4096 + use-procfs: true `, - key: "proctree", + key: "stores", expectedFlags: []string{ - "source=events", - "process-cache=8192", - "thread-cache=4096", + "dns", + "dns.max-entries=2048", + "process", + "process.source=both", + "process.max-processes=8192", + "process.max-threads=4096", + "process.use-procfs", }, }, { @@ -407,105 +486,6 @@ runtime: } } -// -// proctree -// - -func TestProcTreeConfigFlags(t *testing.T) { - t.Parallel() - - tests := []struct { - name string - config ProcTreeConfig - expected []string - }{ - { - name: "empty config", - config: ProcTreeConfig{ - Source: "", - Cache: ProcTreeCacheConfig{}, - }, - expected: []string{}, - }, - { - name: "only source set", - config: ProcTreeConfig{ - Source: "events", - Cache: ProcTreeCacheConfig{}, - }, - expected: []string{ - "source=events", - }, - }, - { - name: "only process cache set", - config: ProcTreeConfig{ - Source: "", - Cache: ProcTreeCacheConfig{ - Process: 8192, - }, - }, - expected: []string{ - "process-cache=8192", - }, - }, - { - name: "only thread cache set", - config: ProcTreeConfig{ - Source: "", - Cache: ProcTreeCacheConfig{ - Thread: 4096, - }, - }, - expected: []string{ - "thread-cache=4096", - }, - }, - { - name: "both cache values set", - config: ProcTreeConfig{ - Source: "", - Cache: ProcTreeCacheConfig{ - Process: 8192, - Thread: 4096, - }, - }, - expected: []string{ - "process-cache=8192", - "thread-cache=4096", - }, - }, - { - name: "all fields set", - config: ProcTreeConfig{ - Source: "events", - Cache: ProcTreeCacheConfig{ - Process: 8192, - Thread: 4096, - }, - }, - expected: []string{ - "source=events", - "process-cache=8192", - "thread-cache=4096", - }, - }, - } - - for _, tt := range tests { - tt := tt - - t.Run(tt.name, func(t *testing.T) { - t.Parallel() - - got := tt.config.flags() - if !slicesEqualIgnoreOrder(got, tt.expected) { - t.Errorf("flags() = %v, want %v", got, tt.expected) - } - }) - } -} - // // capabilities // diff --git a/pkg/cmd/flags/dnscache.go b/pkg/cmd/flags/dnscache.go deleted file mode 100644 index 2e421467ec46..000000000000 --- a/pkg/cmd/flags/dnscache.go +++ /dev/null @@ -1,64 +0,0 @@ -package flags - -import ( - "errors" - "fmt" - "strconv" - "strings" - - "github.com/aquasecurity/tracee/pkg/datastores/dns" -) - -func dnsCacheHelp() string { - return `Select different options for the DNS cache. - -Example: - --dnscache enable | enable with default values (see below). - --dnscache size=X | will cache up to X dns query trees - further queries may be cached regardless (default: 5000). - -Use comma OR use the flag multiple times to choose multiple options: - --dnscache size=A - --dnscache enable -` -} - -func PrepareDnsCache(cacheSlice []string) (dns.Config, error) { - var err error - - config := dns.Config{ - Enable: true, // assume enabled and return disabled if no flag given - CacheSize: dns.DefaultCacheSize, - } - - for _, slice := range cacheSlice { - if strings.HasPrefix(slice, "help") { - return config, errors.New(dnsCacheHelp()) - } - if slice == "enable" { - continue - } - if slice == "none" { - // no flag given - config.Enable = false - return config, nil - } - - values := strings.Split(slice, ",") - - for _, value := range values { - if strings.HasPrefix(value, "size=") { - num := strings.TrimPrefix(value, "size=") - size, err := strconv.Atoi(num) - if err != nil { - return config, err - } - config.CacheSize = size - config.Enable = true - continue - } - err = fmt.Errorf("unrecognized dnscache option format: %v", value) - } - } - - return config, err -} diff --git a/pkg/cmd/flags/proctree.go b/pkg/cmd/flags/proctree.go deleted file mode 100644 index c8836cc07679..000000000000 --- a/pkg/cmd/flags/proctree.go +++ /dev/null @@ -1,123 +0,0 @@ -package flags - -import ( - "errors" - "fmt" - "strconv" - "strings" - - "github.com/aquasecurity/tracee/common/logger" - "github.com/aquasecurity/tracee/pkg/datastores/process" -) - -func procTreeHelp() string { - return `Select different options for the process tree. - -Example: - --proctree source=[none|events|signals|both] - none | process tree is disabled (default). - events | process tree is built from events. - signals | process tree is built from signals. - both | process tree is built from both events and signals. - --proctree process-cache=8192 | will cache up to 8192 processes in the tree (LRU cache). - --proctree thread-cache=4096 | will cache up to 4096 threads in the tree (LRU cache). - --proctree disable-procfs | will disable procfs entirely. - --proctree disable-procfs-query | will disable procfs quering during runtime. - -Use comma OR use the flag multiple times to choose multiple options: - --proctree source=A,process-cache=B,thread-cache=C - --proctree process-cache=X --proctree thread-cache=Y -` -} - -func PrepareProcTree(cacheSlice []string) (process.ProcTreeConfig, error) { - var err error - - config := process.ProcTreeConfig{ - Source: process.SourceNone, // disabled by default - ProcessCacheSize: process.DefaultProcessCacheSize, - ThreadCacheSize: process.DefaultThreadCacheSize, - ProcfsInitialization: true, - ProcfsQuerying: true, - } - - cacheSet := false - - for _, slice := range cacheSlice { - if strings.HasPrefix(slice, "help") { - return config, errors.New(procTreeHelp()) - } - if strings.HasPrefix(slice, "none") { - return config, nil - } - - values := strings.Split(slice, ",") - - for _, value := range values { - if strings.HasPrefix(value, "source=") { - option := strings.TrimPrefix(value, "source=") - switch option { - case "none": - config.Source = process.SourceNone - case "events": - config.Source = process.SourceEvents - case "signals": - config.Source = process.SourceSignals - case "both": - config.Source = process.SourceBoth - default: - return config, fmt.Errorf("unrecognized proctree source option: %v", option) - } - if config.Source != process.SourceNone { - cacheSet = true // at least the default ones - } - continue - } - if strings.HasPrefix(value, "process-cache=") { - num := strings.TrimPrefix(value, "process-cache=") - size, err := strconv.Atoi(num) - if err != nil { - return config, err - } - if size >= 4096 { // minimum size is 4096 (or the default is used) - config.ProcessCacheSize = size - } - cacheSet = true - continue - } - if strings.HasPrefix(value, "thread-cache=") { - num := strings.TrimPrefix(value, "thread-cache=") - size, err := strconv.Atoi(num) - if err != nil { - return config, err - } - if size >= 4096 { // minimum size is 4096 (or the default is used) - config.ThreadCacheSize = size - } - cacheSet = true - continue - } - if value == "disable-procfs" { - config.ProcfsInitialization = false - config.ProcfsQuerying = false - continue - } - if value == "disable-procfs-query" { - config.ProcfsQuerying = false - continue - } - err = fmt.Errorf("unrecognized proctree option format: %v", value) - } - } - - if cacheSet && config.Source == process.SourceNone { - return config, errors.New("proctree cache was set but no source was given") - } - - if config.Source != process.SourceNone { - logger.Debugw("proctree is enabled and it source is set to", "source", config.Source.String()) - logger.Debugw("proctree cache size", "process", config.ProcessCacheSize, "thread", config.ThreadCacheSize) - } - - return config, err -} diff --git a/pkg/cmd/flags/stores.go b/pkg/cmd/flags/stores.go new file mode 100644 index 000000000000..4f9ebfeb4f4d --- /dev/null +++ b/pkg/cmd/flags/stores.go @@ -0,0 +1,218 @@ +package flags + +import ( + "fmt" + "strconv" + "strings" + + "github.com/aquasecurity/tracee/common/errfmt" + "github.com/aquasecurity/tracee/pkg/datastores/dns" + "github.com/aquasecurity/tracee/pkg/datastores/process" +) + +const ( + StoresFlag = "stores" + + dnsFlag = "dns" + dnsMaxEntries = "dns.max-entries" + processFlag = "process" + processMaxProcs = "process.max-processes" + processMaxThreads = "process.max-threads" + processSource = "process.source" + processUseProcfs = "process.use-procfs" + + processSourceEvents = "events" + processSourceSignals = "signals" + processSourceBoth = "both" + + storesInvalidFlag = "invalid stores flag: %s, use 'trace man stores' for more info" +) + +// ProcessConfig is the config for the process tree +type ProcessConfig struct { + Enabled bool `mapstructure:"enabled"` + MaxProcesses int `mapstructure:"max-processes"` + MaxThreads int `mapstructure:"max-threads"` + Source string `mapstructure:"source"` + Procfs bool `mapstructure:"use-procfs"` +} + +// DNSConfig is the config for the DNS cache +type DNSConfig struct { + Enabled bool `mapstructure:"enabled"` + MaxEntries int `mapstructure:"max-entries"` +} + +// StoresConfig is the config for the stores +type StoresConfig struct { + DNS DNSConfig `mapstructure:"dns"` + Process ProcessConfig `mapstructure:"process"` +} + +// flags returns the flags for the stores config +func (s *StoresConfig) flags() []string { + flags := []string{} + + // DNS: if Enabled is true OR MaxEntries is set, add dns flag + if s.DNS.Enabled || s.DNS.MaxEntries != 0 { + flags = append(flags, dnsFlag) + } + if s.DNS.MaxEntries != 0 { + flags = append(flags, fmt.Sprintf("%s=%d", dnsMaxEntries, s.DNS.MaxEntries)) + } + + // Process: if Enabled is true OR any Process field is set, add process flag + if s.Process.Enabled || s.Process.MaxProcesses != 0 || s.Process.MaxThreads != 0 || s.Process.Source != "" || s.Process.Procfs { + flags = append(flags, processFlag) + } + if s.Process.MaxProcesses != 0 { + flags = append(flags, fmt.Sprintf("%s=%d", processMaxProcs, s.Process.MaxProcesses)) + } + if s.Process.MaxThreads != 0 { + flags = append(flags, fmt.Sprintf("%s=%d", processMaxThreads, s.Process.MaxThreads)) + } + if s.Process.Source != "" { + flags = append(flags, fmt.Sprintf("%s=%s", processSource, s.Process.Source)) + } + if s.Process.Procfs { + flags = append(flags, processUseProcfs) + } + + return flags +} + +// GetProcTreeConfig returns the process tree config +func (s *StoresConfig) GetProcTreeConfig() process.ProcTreeConfig { + // Default to SourceSignals if process is enabled but no source is specified + source := process.SourceSignals + + if s.Process.Enabled { + switch s.Process.Source { + case processSourceEvents: + source = process.SourceEvents + case processSourceSignals: + source = process.SourceSignals + case processSourceBoth: + source = process.SourceBoth + default: + // If source is empty or invalid, default to signals + source = process.SourceSignals + } + } else { + // If process is not enabled, use SourceNone internally + source = process.SourceNone + } + + return process.ProcTreeConfig{ + Enabled: s.Process.Enabled, + Source: source, + ProcessCacheSize: s.Process.MaxProcesses, + ThreadCacheSize: s.Process.MaxThreads, + ProcfsInitialization: s.Process.Procfs, + ProcfsQuerying: s.Process.Procfs, + } +} + +// GetDNSCacheConfig returns the DNS cache config +func (s *StoresConfig) GetDNSCacheConfig() dns.Config { + return dns.Config{ + Enable: s.DNS.Enabled, + CacheSize: s.DNS.MaxEntries, + } +} + +// PrepareStores prepares the stores config from the command line flags +// and returns the stores config and an error if the flags are invalid +func PrepareStores(storeSlice []string) (StoresConfig, error) { + config := StoresConfig{ + DNS: DNSConfig{ + Enabled: false, + MaxEntries: dns.DefaultCacheSize, + }, + Process: ProcessConfig{ + Enabled: false, + MaxProcesses: process.DefaultProcessCacheSize, + MaxThreads: process.DefaultThreadCacheSize, + Source: process.SourceSignals.String(), + Procfs: false, + }, + } + + for _, flag := range storeSlice { + values := strings.SplitN(flag, "=", 2) + + flagName := values[0] + + if len(values) != 2 && !isStoresBoolFlag(flagName) { + return config, errfmt.Errorf(storesInvalidFlag, flag) + } + + if len(values) != 1 && isStoresBoolFlag(flagName) { + return config, errfmt.Errorf(storesInvalidFlag, flag) + } + + switch flagName { + case dnsFlag: + config.DNS.Enabled = true + case dnsMaxEntries: + size, err := parseSize(values[1], flag) + if err != nil { + return config, err + } + config.DNS.MaxEntries = size + config.DNS.Enabled = true // Setting max-entries enables DNS + case processFlag: + config.Process.Enabled = true + case processMaxProcs: + size, err := parseSize(values[1], flag) + if err != nil { + return config, err + } + config.Process.MaxProcesses = size + config.Process.Enabled = true // Setting max-processes enables process + case processMaxThreads: + size, err := parseSize(values[1], flag) + if err != nil { + return config, err + } + config.Process.MaxThreads = size + config.Process.Enabled = true // Setting max-threads enables process + case processSource: + if values[1] == "" { + return config, errfmt.Errorf(storesInvalidFlag, flag) + } + // Validate that source is one of the supported values + if values[1] != processSourceSignals && values[1] != processSourceEvents && values[1] != processSourceBoth { + return config, errfmt.Errorf(storesInvalidFlag, flag) + } + config.Process.Source = values[1] + config.Process.Enabled = true // Setting source enables process + case processUseProcfs: + config.Process.Procfs = true + config.Process.Enabled = true // Setting use-procfs enables process + default: + return config, errfmt.Errorf(storesInvalidFlag, flag) + } + } + + return config, nil +} + +// parseSize parses a string value as a size and returns an error if the value is not a positive integer +func parseSize(value, flag string) (int, error) { + size, err := strconv.Atoi(value) + if err != nil || size <= 0 { + return 0, errfmt.Errorf(storesInvalidFlag, flag) + } + return size, nil +} + +// isStoresBoolFlag checks if a flag is a boolean flag for the stores config +func isStoresBoolFlag(flagName string) bool { + return flagName == dnsFlag || flagName == processFlag || flagName == processUseProcfs +} + +// invalidStoresFlagError formats the error message for an invalid stores flag. +func invalidStoresFlagError(flag string) string { + return fmt.Sprintf(storesInvalidFlag, flag) +} diff --git a/pkg/cmd/flags/stores_test.go b/pkg/cmd/flags/stores_test.go new file mode 100644 index 000000000000..498e971b5da0 --- /dev/null +++ b/pkg/cmd/flags/stores_test.go @@ -0,0 +1,509 @@ +package flags + +import ( + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "github.com/aquasecurity/tracee/pkg/datastores/dns" + "github.com/aquasecurity/tracee/pkg/datastores/process" +) + +func TestPrepareStores(t *testing.T) { + t.Parallel() + + testCases := []struct { + testName string + flags []string + expectedReturn StoresConfig + expectedError string + }{ + // default values (no flags) + { + testName: "default values", + flags: []string{}, + expectedReturn: StoresConfig{ + DNS: DNSConfig{ + Enabled: false, + MaxEntries: dns.DefaultCacheSize, + }, + Process: ProcessConfig{ + Enabled: false, + MaxProcesses: process.DefaultProcessCacheSize, + MaxThreads: process.DefaultThreadCacheSize, + Source: "signals", + Procfs: false, + }, + }, + }, + // valid single DNS flags + { + testName: "valid dns", + flags: []string{"dns"}, + expectedReturn: StoresConfig{ + DNS: DNSConfig{ + Enabled: true, + MaxEntries: dns.DefaultCacheSize, + }, + Process: ProcessConfig{ + Enabled: false, + MaxProcesses: process.DefaultProcessCacheSize, + MaxThreads: process.DefaultThreadCacheSize, + Source: "signals", + Procfs: false, + }, + }, + }, + { + testName: "valid dns.max-entries", + flags: []string{"dns.max-entries=2048"}, + expectedReturn: StoresConfig{ + DNS: DNSConfig{ + Enabled: true, // Setting max-entries enables DNS + MaxEntries: 2048, + }, + Process: ProcessConfig{ + Enabled: false, + MaxProcesses: process.DefaultProcessCacheSize, + MaxThreads: process.DefaultThreadCacheSize, + Source: "signals", + Procfs: false, + }, + }, + }, + // valid single Process flags + { + testName: "valid process", + flags: []string{"process"}, + expectedReturn: StoresConfig{ + DNS: DNSConfig{ + Enabled: false, + MaxEntries: dns.DefaultCacheSize, + }, + Process: ProcessConfig{ + Enabled: true, + MaxProcesses: process.DefaultProcessCacheSize, + MaxThreads: process.DefaultThreadCacheSize, + Source: "signals", + Procfs: false, + }, + }, + }, + { + testName: "valid process.max-processes", + flags: []string{"process.max-processes=100"}, + expectedReturn: StoresConfig{ + DNS: DNSConfig{ + Enabled: false, + MaxEntries: dns.DefaultCacheSize, + }, + Process: ProcessConfig{ + Enabled: true, // Setting max-processes enables process + MaxProcesses: 100, + MaxThreads: process.DefaultThreadCacheSize, + Source: "signals", + Procfs: false, + }, + }, + }, + { + testName: "valid process.max-threads", + flags: []string{"process.max-threads=50"}, + expectedReturn: StoresConfig{ + DNS: DNSConfig{ + Enabled: false, + MaxEntries: dns.DefaultCacheSize, + }, + Process: ProcessConfig{ + Enabled: true, // Setting max-threads enables process + MaxProcesses: process.DefaultProcessCacheSize, + MaxThreads: 50, + Source: "signals", + Procfs: false, + }, + }, + }, + { + testName: "invalid process.source=none", + flags: []string{"process.source=none"}, + expectedError: invalidStoresFlagError("process.source=none"), + }, + { + testName: "valid process.source=events", + flags: []string{"process.source=events"}, + expectedReturn: StoresConfig{ + DNS: DNSConfig{ + Enabled: false, + MaxEntries: dns.DefaultCacheSize, + }, + Process: ProcessConfig{ + Enabled: true, // Setting source enables process + MaxProcesses: process.DefaultProcessCacheSize, + MaxThreads: process.DefaultThreadCacheSize, + Source: "events", + Procfs: false, + }, + }, + }, + { + testName: "valid process.source=signals", + flags: []string{"process.source=signals"}, + expectedReturn: StoresConfig{ + DNS: DNSConfig{ + Enabled: false, + MaxEntries: dns.DefaultCacheSize, + }, + Process: ProcessConfig{ + Enabled: true, // Setting source enables process + MaxProcesses: process.DefaultProcessCacheSize, + MaxThreads: process.DefaultThreadCacheSize, + Source: "signals", + Procfs: false, + }, + }, + }, + { + testName: "valid process.source=both", + flags: []string{"process.source=both"}, + expectedReturn: StoresConfig{ + DNS: DNSConfig{ + Enabled: false, + MaxEntries: dns.DefaultCacheSize, + }, + Process: ProcessConfig{ + Enabled: true, // Setting source enables process + MaxProcesses: process.DefaultProcessCacheSize, + MaxThreads: process.DefaultThreadCacheSize, + Source: "both", + Procfs: false, + }, + }, + }, + { + testName: "valid process.use-procfs", + flags: []string{"process.use-procfs"}, + expectedReturn: StoresConfig{ + DNS: DNSConfig{ + Enabled: false, + MaxEntries: dns.DefaultCacheSize, + }, + Process: ProcessConfig{ + Enabled: true, // Setting use-procfs enables process + MaxProcesses: process.DefaultProcessCacheSize, + MaxThreads: process.DefaultThreadCacheSize, + Source: "signals", + Procfs: true, + }, + }, + }, + // valid multiple flags + { + testName: "valid multiple DNS flags", + flags: []string{"dns", "dns.max-entries=4096"}, + expectedReturn: StoresConfig{ + DNS: DNSConfig{ + Enabled: true, + MaxEntries: 4096, + }, + Process: ProcessConfig{ + Enabled: false, + MaxProcesses: process.DefaultProcessCacheSize, + MaxThreads: process.DefaultThreadCacheSize, + Source: "signals", + Procfs: false, + }, + }, + }, + { + testName: "valid multiple Process flags", + flags: []string{"process", "process.max-processes=200", "process.max-threads=100"}, + expectedReturn: StoresConfig{ + DNS: DNSConfig{ + Enabled: false, + MaxEntries: dns.DefaultCacheSize, + }, + Process: ProcessConfig{ + Enabled: true, + MaxProcesses: 200, + MaxThreads: 100, + Source: "signals", + Procfs: false, + }, + }, + }, + { + testName: "valid all flags", + flags: []string{"dns", "dns.max-entries=2048", "process", "process.max-processes=150", "process.max-threads=75", "process.source=both", "process.use-procfs"}, + expectedReturn: StoresConfig{ + DNS: DNSConfig{ + Enabled: true, + MaxEntries: 2048, + }, + Process: ProcessConfig{ + Enabled: true, + MaxProcesses: 150, + MaxThreads: 75, + Source: "both", + Procfs: true, + }, + }, + }, + { + testName: "valid flags in different order", + flags: []string{"process.use-procfs", "dns.max-entries=512", "process.source=events", "process.max-threads=25"}, + expectedReturn: StoresConfig{ + DNS: DNSConfig{ + Enabled: true, // Setting max-entries enables DNS + MaxEntries: 512, + }, + Process: ProcessConfig{ + Enabled: true, // Setting any process field enables process + MaxProcesses: process.DefaultProcessCacheSize, + MaxThreads: 25, + Source: "events", + Procfs: true, + }, + }, + }, + // invalid flag format + { + testName: "invalid flag format missing equals with value", + flags: []string{"dnstrue"}, + expectedReturn: StoresConfig{ + DNS: DNSConfig{ + Enabled: false, + MaxEntries: dns.DefaultCacheSize, + }, + Process: ProcessConfig{ + Enabled: false, + MaxProcesses: process.DefaultProcessCacheSize, + MaxThreads: process.DefaultThreadCacheSize, + Source: "signals", + Procfs: false, + }, + }, + expectedError: invalidStoresFlagError("dnstrue"), + }, + { + testName: "invalid dns.max-entries missing value", + flags: []string{"dns.max-entries"}, + expectedReturn: StoresConfig{ + DNS: DNSConfig{ + Enabled: false, + MaxEntries: dns.DefaultCacheSize, + }, + Process: ProcessConfig{ + Enabled: false, + MaxProcesses: process.DefaultProcessCacheSize, + MaxThreads: process.DefaultThreadCacheSize, + Source: "signals", + Procfs: false, + }, + }, + expectedError: invalidStoresFlagError("dns.max-entries"), + }, + { + testName: "invalid dns.max-entries empty value", + flags: []string{"dns.max-entries="}, + expectedReturn: StoresConfig{ + DNS: DNSConfig{ + Enabled: false, + MaxEntries: dns.DefaultCacheSize, + }, + Process: ProcessConfig{ + Enabled: false, + MaxProcesses: process.DefaultProcessCacheSize, + MaxThreads: process.DefaultThreadCacheSize, + Source: "signals", + Procfs: false, + }, + }, + expectedError: invalidStoresFlagError("dns.max-entries="), + }, + // invalid flag name + { + testName: "invalid flag name", + flags: []string{"invalid-flag=true"}, + expectedReturn: StoresConfig{ + DNS: DNSConfig{ + Enabled: false, + MaxEntries: dns.DefaultCacheSize, + }, + Process: ProcessConfig{ + Enabled: false, + MaxProcesses: process.DefaultProcessCacheSize, + MaxThreads: process.DefaultThreadCacheSize, + Source: "signals", + Procfs: false, + }, + }, + expectedError: invalidStoresFlagError("invalid-flag=true"), + }, + { + testName: "invalid flag name with typo", + flags: []string{"dns.enable=true"}, + expectedReturn: StoresConfig{ + DNS: DNSConfig{ + Enabled: false, + MaxEntries: dns.DefaultCacheSize, + }, + Process: ProcessConfig{ + Enabled: false, + MaxProcesses: process.DefaultProcessCacheSize, + MaxThreads: process.DefaultThreadCacheSize, + Source: "signals", + Procfs: false, + }, + }, + expectedError: invalidStoresFlagError("dns.enable=true"), + }, + // invalid DNS values + { + testName: "invalid dns.max-entries value non-numeric", + flags: []string{"dns.max-entries=invalid"}, + expectedReturn: StoresConfig{ + DNS: DNSConfig{ + Enabled: false, + MaxEntries: dns.DefaultCacheSize, + }, + Process: ProcessConfig{ + Enabled: false, + MaxProcesses: process.DefaultProcessCacheSize, + MaxThreads: process.DefaultThreadCacheSize, + Source: "signals", + Procfs: false, + }, + }, + expectedError: invalidStoresFlagError("dns.max-entries=invalid"), + }, + { + testName: "invalid dns.max-entries value negative", + flags: []string{"dns.max-entries=-100"}, + expectedReturn: StoresConfig{ + DNS: DNSConfig{ + Enabled: false, + MaxEntries: dns.DefaultCacheSize, + }, + Process: ProcessConfig{ + Enabled: false, + MaxProcesses: process.DefaultProcessCacheSize, + MaxThreads: process.DefaultThreadCacheSize, + Source: "signals", + Procfs: false, + }, + }, + expectedError: invalidStoresFlagError("dns.max-entries=-100"), + }, + // invalid Process values + { + testName: "invalid process.max-processes value non-numeric", + flags: []string{"process.max-processes=invalid"}, + expectedReturn: StoresConfig{ + DNS: DNSConfig{ + Enabled: false, + MaxEntries: dns.DefaultCacheSize, + }, + Process: ProcessConfig{ + Enabled: false, + MaxProcesses: process.DefaultProcessCacheSize, + MaxThreads: process.DefaultThreadCacheSize, + Source: "signals", + Procfs: false, + }, + }, + expectedError: invalidStoresFlagError("process.max-processes=invalid"), + }, + { + testName: "invalid process.max-threads value non-numeric", + flags: []string{"process.max-threads=invalid"}, + expectedReturn: StoresConfig{ + DNS: DNSConfig{ + Enabled: false, + MaxEntries: dns.DefaultCacheSize, + }, + Process: ProcessConfig{ + Enabled: false, + MaxProcesses: process.DefaultProcessCacheSize, + MaxThreads: process.DefaultThreadCacheSize, + Source: "signals", + Procfs: false, + }, + }, + expectedError: invalidStoresFlagError("process.max-threads=invalid"), + }, + // valid edge cases + { + testName: "invalid zero values", + flags: []string{"dns.max-entries=0", "process.max-processes=0", "process.max-threads=0"}, + expectedReturn: StoresConfig{ + DNS: DNSConfig{ + Enabled: false, + MaxEntries: dns.DefaultCacheSize, + }, + Process: ProcessConfig{ + Enabled: false, + MaxProcesses: process.DefaultProcessCacheSize, + MaxThreads: process.DefaultThreadCacheSize, + Source: "signals", + Procfs: false, + }, + }, + expectedError: invalidStoresFlagError("dns.max-entries=0"), + }, + { + testName: "valid large values", + flags: []string{"dns.max-entries=999999", "process.max-processes=999999", "process.max-threads=999999"}, + expectedReturn: StoresConfig{ + DNS: DNSConfig{ + Enabled: true, // Setting max-entries enables DNS + MaxEntries: 999999, + }, + Process: ProcessConfig{ + Enabled: true, // Setting max-processes or max-threads enables process + MaxProcesses: 999999, + MaxThreads: 999999, + Source: "signals", + Procfs: false, + }, + }, + }, + // mixed valid and invalid + { + testName: "mixed valid and invalid flag name", + flags: []string{"dns", "invalid-flag=value"}, + expectedReturn: StoresConfig{ + DNS: DNSConfig{ + Enabled: true, + MaxEntries: dns.DefaultCacheSize, + }, + Process: ProcessConfig{ + Enabled: false, + MaxProcesses: process.DefaultProcessCacheSize, + MaxThreads: process.DefaultThreadCacheSize, + Source: "signals", + Procfs: false, + }, + }, + expectedError: invalidStoresFlagError("invalid-flag=value"), + }, + } + + for _, tc := range testCases { + tc := tc + + t.Run(tc.testName, func(t *testing.T) { + t.Parallel() + + stores, err := PrepareStores(tc.flags) + if tc.expectedError != "" { + require.Error(t, err) + // Error can come from either PrepareStores or parseSize, check that it contains the expected message + assert.Contains(t, err.Error(), tc.expectedError) + } else { + require.NoError(t, err) + assert.Equal(t, tc.expectedReturn, stores) + } + }) + } +} diff --git a/pkg/datastores/dns/dnscache.go b/pkg/datastores/dns/dnscache.go index ef0ccbdc72f9..b6977a7fa8a7 100644 --- a/pkg/datastores/dns/dnscache.go +++ b/pkg/datastores/dns/dnscache.go @@ -31,8 +31,8 @@ type DNSCache struct { } type Config struct { - CacheSize int Enable bool + CacheSize int } func New(config Config) (*DNSCache, error) { diff --git a/pkg/datastores/process/proctree.go b/pkg/datastores/process/proctree.go index 5f5de5aff7e5..804e55fb9af4 100644 --- a/pkg/datastores/process/proctree.go +++ b/pkg/datastores/process/proctree.go @@ -64,6 +64,7 @@ func (s SourceType) String() string { } type ProcTreeConfig struct { + Enabled bool Source SourceType ProcessCacheSize int ThreadCacheSize int diff --git a/tests/e2e-inst-signatures/e2e-proctree_data_source.go b/tests/e2e-inst-signatures/e2e-proctree_data_source.go index 150bf05c8675..edba1c173051 100644 --- a/tests/e2e-inst-signatures/e2e-proctree_data_source.go +++ b/tests/e2e-inst-signatures/e2e-proctree_data_source.go @@ -84,7 +84,7 @@ func (sig *e2eProcessTreeDataSource) OnEvent(event protocol.Event) error { // this signature needs to have tracee running with the following flags: // // * --output option:sort-events - // * --proctree source=both + // * --stores process.source=both // * --events PROCTREE_DATA_SOURCE // Check that the event is from the tester diff --git a/tests/e2e-inst-test.sh b/tests/e2e-inst-test.sh index 6353f2b88030..0425fbe00a79 100755 --- a/tests/e2e-inst-test.sh +++ b/tests/e2e-inst-test.sh @@ -332,8 +332,8 @@ print_test_header "START TRACE" --signatures-dir "${SIG_DIR}" \ --output option:sort-events \ --output option:parse-arguments \ - --proctree source=both \ - --dnscache enable \ + --stores process --stores process.source=both \ + --stores dns \ --server grpc-address=unix:/tmp/tracee.sock \ --policy "${TRACEE_POLICY_PATH}"