Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

plugin system, events tester, and minor features #31

Merged
merged 20 commits into from
Jul 20, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
9a81a61
fix(pkg/runner): pass context to `Run()`
leogr Jun 3, 2020
ffb5f90
feat(pkg/runner): add plugin support
leogr Jun 3, 2020
6e487a1
feat(events): add `MatchRule` func
leogr Jun 3, 2020
2619a13
chore: add skip mechanism, container detection, and pass error to plugin
leogr Jun 4, 2020
dc72a23
new(pkg/tester): plugin to test actions in a running Falco instance
leogr Jun 4, 2020
23eb696
new(cmd): add `test` command
leogr Jun 4, 2020
ea59cca
feat(pkg/tester): add bidi gRPC support and test timeout
leogr Jun 19, 2020
7075a95
new(cmd): add `--test-timeout` flag to `test` command
leogr Jun 19, 2020
429cfe2
feat(events): add options to make actions disabled by default
leogr Jun 19, 2020
ce03660
new(pkg/runner): add `WithAllEnabled` option
leogr Jun 19, 2020
5a04ddc
new(cmd): add `--all` flag for all actions related commands
leogr Jun 19, 2020
aa3961e
new(deployment): add `run-test.yaml` resource
leogr Jun 23, 2020
0284d0f
update(events/syscall): `ScheduleCronJobs` skipped when crontab utili…
leogr Jun 4, 2020
837f7ff
update(events/syscall): `UserMgmtBinaries` skipped when running in a …
leogr Jun 4, 2020
c7c7b9a
update(events/syscall): `ScheduleCronJobs` is now disabled by default
leogr Jun 19, 2020
4ba5337
update(events/k8saudit): `CreateDisallowedPod` is now disabled by def…
leogr Jun 19, 2020
430557a
build: set client-go version to v0.2.0
leogr Jul 20, 2020
7a81146
build: upgrade dependencies
leogr Jul 20, 2020
6e0cd7f
docs: update documentation for `test` command
leogr Jul 20, 2020
e1fa9cd
chore(deployment): switch back to `latest`
leogr Jul 20, 2020
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
37 changes: 34 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ Useful options:
All other options are documented [here](./docs/event-generator_run.md).


### With Docker
#### With Docker

Run all events with the Docker image locally:

Expand All @@ -88,8 +88,7 @@ docker run -it --rm falcosecurity/event-generator run
```


### With Kubernetes

#### With Kubernetes

Run the following command to create the Service Account (`falco-event-generator`), Cluster Role, and Role that will allow the tool to create objects in the current namespace:

Expand Down Expand Up @@ -139,6 +138,37 @@ The above command loops forever, creating resources in the `falco-eg-sandbox` na
- the namespace must already exist
- to produce any effect the Kubernetes audit log must be enabled, see [here](https://falco.org/docs/event-sources/kubernetes-audit/)


## Test rules

Since `v0.4.0`, this tool introduces a convenient integration test suite for Falco rules. Basically the `event-generator test` command can run actions and test them against a running Falco instance.

> This feature requires Falco 0.24.0 or newer. Before using the command below, you need [Falco installed](https://falco.org/docs/installation/) and running with the [gRPC Output](https://falco.org/docs/grpc/) enabled.

#### Test locally (`syscall` only)

Run the following command to test `syscall` actions on a local Falco instance (connects via Unix socket to `/var/run/falco.sock` by default):

```shell
sudo ./event-generator test syscall
```

#### Test on Kubernetes

Then, run the following command to create the Service Account (`falco-event-generator`), Cluster Role, and Role that will allow the tool to create objects in the current namespace:

```shell
kubectl apply -f deployment/role-rolebinding-serviceaccount.yaml
```

Finally:

```shell
kubectl apply -f deployment/run-test.yaml
```

Note that to test `k8saudit` events, you need [Kubernetes audit log] enabled both in Kubernetes and Falco.

## FAQ

### What sample events can be generated by this tool?
Expand All @@ -148,6 +178,7 @@ See the [events registry](https://github.com/falcosecurity/event-generator/tree/
Sure!

Check out the [events registry](https://github.com/falcosecurity/event-generator/tree/master/events) conventions, then feel free to open a PR.

Your contribution is highly appreciated.

### Can I use this project as a library?
Expand Down
1 change: 1 addition & 0 deletions cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ func New(configOptions *ConfigOptions) *cobra.Command {

// Commands
rootCmd.AddCommand(NewRun())
rootCmd.AddCommand(NewTest())
rootCmd.AddCommand(NewList())

return rootCmd
Expand Down
73 changes: 50 additions & 23 deletions cmd/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,36 +9,55 @@ import (
_ "github.com/falcosecurity/event-generator/events/k8saudit"
_ "github.com/falcosecurity/event-generator/events/syscall"

"k8s.io/cli-runtime/pkg/genericclioptions"
cmdutil "k8s.io/kubectl/pkg/cmd/util"

// Initialize all k8s client auth plugins
_ "k8s.io/client-go/plugin/pkg/client/auth"

"github.com/falcosecurity/event-generator/events"
"github.com/falcosecurity/event-generator/pkg/runner"
logger "github.com/sirupsen/logrus"
"github.com/spf13/cobra"
"k8s.io/cli-runtime/pkg/genericclioptions"
_ "k8s.io/client-go/plugin/pkg/client/auth"
cmdutil "k8s.io/kubectl/pkg/cmd/util"
)

// DefaultNamespace const contains the name of the default Kubernetes namespace.
const DefaultNamespace = "default"

const runWarningMessage = `
Warning:
This command might alter your system. For example, some actions modify files and directories below
/bin, /etc, /dev, etc.
Make sure you fully understand what is the purpose of this tool before running any action.
`

// NewRun instantiates the run subcommand.
func NewRun() *cobra.Command {
c := &cobra.Command{
c, runEWithOpts := newRunTemplate()
c.RunE = func(c *cobra.Command, args []string) error {
return runEWithOpts(c, args)
}
return c
}

func newRunTemplate() (c *cobra.Command, runE func(c *cobra.Command, args []string, options ...runner.Option) error) {
c = &cobra.Command{
Use: "run [regexp]",
Short: "Run actions",
Long: `Performs a variety of suspect actions.
Without arguments it runs all actions, otherwise only those actions matching the given regular expression.

Warning:
This command might alter your system. For example, some actions modify files and directories below
/bin, /etc, /dev, etc.
Make sure you fully understand what is the purpose of this tool before running any action.
`,
` + runWarningMessage,
Args: cobra.MaximumNArgs(1),
DisableAutoGenTag: true,
}

flags := c.Flags()

flags.Duration("sleep", time.Second, "The length of time to wait before running an action. Non-zero values should contain a corresponding time unit (e.g. 1s, 2m, 3h). A value of zero means no sleep.")
flags.Bool("loop", false, "Run in a loop")
flags.Bool("all", false, "Run all actions, including those disabled by default")

kubeConfigFlags := genericclioptions.NewConfigFlags(false)
kubeConfigFlags.AddFlags(flags)
matchVersionKubeConfigFlags := cmdutil.NewMatchVersionFlags(kubeConfigFlags)
Expand All @@ -48,37 +67,48 @@ Warning:
ns.DefValue = DefaultNamespace
ns.Value.Set(DefaultNamespace)

sleep := time.Second
flags.DurationVar(&sleep, "sleep", sleep, "The length of time to wait before running an action. Non-zero values should contain a corresponding time unit (e.g. 1s, 2m, 3h). A value of zero means no sleep.")
return c, func(c *cobra.Command, args []string, options ...runner.Option) error {

var loop bool
flags.BoolVar(&loop, "loop", false, "Run in a loop")

c.RunE = func(c *cobra.Command, args []string) error {
flags := c.Flags()
ns, err := flags.GetString("namespace")
if err != nil {
return err
}
sleep, err := flags.GetDuration("sleep")
if err != nil {
return err
}
loop, err := flags.GetBool("loop")
if err != nil {
return err
}
all, err := flags.GetBool("all")
if err != nil {
return err
}

l := logger.StandardLogger()

r, err := runner.New(
runner.WithContext(c.Context()),
options = append(options,
runner.WithLogger(l),
runner.WithKubeFactory(cmdutil.NewFactory(matchVersionKubeConfigFlags)),
runner.WithKubeNamespace(ns),
runner.WithKubeFactory(cmdutil.NewFactory(matchVersionKubeConfigFlags)),
// todo(leogr): inherit other flags
runner.WithExecutable("", "--loglevel", l.GetLevel().String(), "run"),
runner.WithSleep(sleep),
runner.WithLoop(loop),
runner.WithAllEnabled(all),
)

r, err := runner.New(options...)
if err != nil {
return err
}

c.SilenceUsage = true

if len(args) == 0 {
return r.Run(events.All())
return r.Run(c.Context(), events.All())
}

reg, err := regexp.Compile(args[0])
Expand All @@ -91,9 +121,6 @@ Warning:
return fmt.Errorf(`no events matching '%s'`, args[0])
}

return r.Run(evts)

return r.Run(c.Context(), evts)
}

return c
}
51 changes: 51 additions & 0 deletions cmd/test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package cmd

import (

// register event collections
"time"

"github.com/falcosecurity/client-go/pkg/client"
_ "github.com/falcosecurity/event-generator/events/k8saudit"
_ "github.com/falcosecurity/event-generator/events/syscall"
"github.com/falcosecurity/event-generator/pkg/runner"
"github.com/falcosecurity/event-generator/pkg/tester"

"github.com/spf13/cobra"
_ "k8s.io/client-go/plugin/pkg/client/auth"
)

// NewTest instantiates the test subcommand.
func NewTest() *cobra.Command {
c, runEWithOpts := newRunTemplate()

c.Use = "test [regexp]"
c.Short = "Run and test actions"
c.Long = `Performs a variety of suspect actions and test them against a running Falco instance.
Without arguments it runs all actions, otherwise only those actions matching the given regular expression.

` + runWarningMessage

flags := c.Flags()

var testTimeout time.Duration
flags.DurationVar(&testTimeout, "test-timeout", tester.DefaultTestTimeout, "Test duration timeout")

grpcCfg := &client.Config{}
flags.StringVar(&grpcCfg.UnixSocketPath, "grpc-unix-socket", "unix:///var/run/falco.sock", "Unix socket path for connecting to a Falco gRPC server")
flags.StringVar(&grpcCfg.Hostname, "grpc-hostname", "localhost", "Hostname for connecting to a Falco gRPC server")
flags.Uint16Var(&grpcCfg.Port, "grpc-port", 5060, "Port for connecting to a Falco gRPC server")
flags.StringVar(&grpcCfg.CertFile, "grpc-cert", "/etc/falco/certs/client.crt", "Cert file path for connecting to a Falco gRPC server")
flags.StringVar(&grpcCfg.KeyFile, "grpc-key", "/etc/falco/certs/client.key", "Key file path for connecting to a Falco gRPC server")
flags.StringVar(&grpcCfg.CARootFile, "grpc-ca", "/etc/falco/certs/ca.crt", "CA root file path for connecting to a Falco gRPC server")

c.RunE = func(c *cobra.Command, args []string) error {
t, err := tester.New(grpcCfg, tester.WithTestTimeout(testTimeout))
if err != nil {
return err
}
return runEWithOpts(c, args, runner.WithPlugin(t))
}

return c
}
30 changes: 30 additions & 0 deletions deployment/run-test.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
apiVersion: batch/v1
kind: Job
metadata:
name: falco-event-generator
spec:
template:
spec:
serviceAccount: falco-event-generator
containers:
- name: falco-event-generator
image: falcosecurity/event-generator:latest
imagePullPolicy: IfNotPresent
command:
- /bin/event-generator
- test
- --grpc-unix-socket=unix:///var/run/falco/falco.sock
env:
- name: FALCO_EVENT_GENERATOR_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
volumeMounts:
- mountPath: /var/run/falco
name: unix-socket-dir
volumes:
- hostPath:
path: /var/run/falco
name: unix-socket-dir
restartPolicy: Never
backoffLimit: 1
1 change: 1 addition & 0 deletions docs/event-generator.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,5 @@ event-generator [flags]

* [event-generator list](event-generator_list.md) - List available actions
* [event-generator run](event-generator_run.md) - Run actions
* [event-generator test](event-generator_test.md) - Run and test actions

2 changes: 2 additions & 0 deletions docs/event-generator_run.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ Run actions
Performs a variety of suspect actions.
Without arguments it runs all actions, otherwise only those actions matching the given regular expression.


Warning:
This command might alter your system. For example, some actions modify files and directories below
/bin, /etc, /dev, etc.
Expand All @@ -20,6 +21,7 @@ event-generator run [regexp] [flags]
### Options

```
--all Run all actions, including those disabled by default
--as string Username to impersonate for the operation
--as-group stringArray Group to impersonate for the operation, this flag can be repeated to specify multiple groups.
--cache-dir string Default HTTP cache directory (default "$HOME/.kube/http-cache")
Expand Down
63 changes: 63 additions & 0 deletions docs/event-generator_test.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
## event-generator test

Run and test actions

### Synopsis

Performs a variety of suspect actions and test them against a running Falco instance.
Without arguments it runs all actions, otherwise only those actions matching the given regular expression.


Warning:
This command might alter your system. For example, some actions modify files and directories below
/bin, /etc, /dev, etc.
Make sure you fully understand what is the purpose of this tool before running any action.


```
event-generator test [regexp] [flags]
```

### Options

```
--all Run all actions, including those disabled by default
--as string Username to impersonate for the operation
--as-group stringArray Group to impersonate for the operation, this flag can be repeated to specify multiple groups.
--cache-dir string Default HTTP cache directory (default "$HOME/.kube/http-cache")
--certificate-authority string Path to a cert file for the certificate authority
--client-certificate string Path to a client certificate file for TLS
--client-key string Path to a client key file for TLS
--cluster string The name of the kubeconfig cluster to use
--context string The name of the kubeconfig context to use
--grpc-ca string CA root file path for connecting to a Falco gRPC server (default "/etc/falco/certs/ca.crt")
--grpc-cert string Cert file path for connecting to a Falco gRPC server (default "/etc/falco/certs/client.crt")
--grpc-hostname string Hostname for connecting to a Falco gRPC server (default "localhost")
--grpc-key string Key file path for connecting to a Falco gRPC server (default "/etc/falco/certs/client.key")
--grpc-port uint16 Port for connecting to a Falco gRPC server (default 5060)
--grpc-unix-socket string Unix socket path for connecting to a Falco gRPC server (default "unix:///var/run/falco.sock")
-h, --help help for test
--insecure-skip-tls-verify If true, the server's certificate will not be checked for validity. This will make your HTTPS connections insecure
--kubeconfig string Path to the kubeconfig file to use for CLI requests.
--loop Run in a loop
--match-server-version Require server version to match client version
-n, --namespace string If present, the namespace scope for this CLI request (default "default")
--request-timeout string The length of time to wait before giving up on a single server request. Non-zero values should contain a corresponding time unit (e.g. 1s, 2m, 3h). A value of zero means don't timeout requests. (default "0")
-s, --server string The address and port of the Kubernetes API server
--sleep duration The length of time to wait before running an action. Non-zero values should contain a corresponding time unit (e.g. 1s, 2m, 3h). A value of zero means no sleep. (default 1s)
--test-timeout duration Test duration timeout (default 1m0s)
--token string Bearer token for authentication to the API server
--user string The name of the kubeconfig user to use
```

### Options inherited from parent commands

```
-c, --config string Config file path (default $HOME/.falco-event-generator.yaml if exists)
-l, --loglevel string Log level (default "info")
```

### SEE ALSO

* [event-generator](event-generator.md) - A command line tool to perform a variety of suspect actions.

Loading