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

cleanup(cmd,internal,pkg): move driver config options to be common to all driver commands #365

Merged
merged 2 commits into from
Dec 6, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
15 changes: 6 additions & 9 deletions cmd/driver/cleanup/cleanup.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,18 +19,19 @@ import (
"github.com/spf13/cobra"
"golang.org/x/net/context"

"github.com/falcosecurity/falcoctl/internal/config"
"github.com/falcosecurity/falcoctl/pkg/options"
)

type driverCleanupOptions struct {
*options.Common
*options.Driver
}

// NewDriverCleanupCmd cleans a driver up.
func NewDriverCleanupCmd(ctx context.Context, opt *options.Common) *cobra.Command {
func NewDriverCleanupCmd(ctx context.Context, opt *options.Common, driver *options.Driver) *cobra.Command {
o := driverCleanupOptions{
Common: opt,
Driver: driver,
}

cmd := &cobra.Command{
Expand All @@ -47,12 +48,8 @@ func NewDriverCleanupCmd(ctx context.Context, opt *options.Common) *cobra.Comman
}

func (o *driverCleanupOptions) RunDriverCleanup(_ context.Context) error {
driver, err := config.Driverer()
if err != nil {
return err
}
o.Printer.Logger.Info("Running falcoctl driver cleanup", o.Printer.Logger.Args(
"driver type", driver.Type,
"driver name", driver.Name))
return driver.Type.Cleanup(o.Printer, driver.Name)
"driver type", o.Driver.Type,
"driver name", o.Driver.Name))
return o.Driver.Type.Cleanup(o.Printer, o.Driver.Name)
}
103 changes: 10 additions & 93 deletions cmd/driver/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ import (
"path/filepath"
"strings"

"github.com/pterm/pterm"
"github.com/spf13/cobra"
"golang.org/x/net/context"
"gopkg.in/yaml.v3"
Expand All @@ -35,8 +34,6 @@ import (

"github.com/falcosecurity/falcoctl/internal/config"
"github.com/falcosecurity/falcoctl/internal/utils"
driverdistro "github.com/falcosecurity/falcoctl/pkg/driver/distro"
driverkernel "github.com/falcosecurity/falcoctl/pkg/driver/kernel"
drivertype "github.com/falcosecurity/falcoctl/pkg/driver/type"
"github.com/falcosecurity/falcoctl/pkg/options"
)
Expand All @@ -53,21 +50,17 @@ If engine.kind key is set to a non-driver driven engine, Falco configuration won

type driverConfigOptions struct {
*options.Common
Type *options.DriverTypes
Version string
Repos []string
Name string
HostRoot string
*options.Driver
Update bool
Namespace string
KubeConfig string
}

// NewDriverConfigCmd configures a driver and stores it in config.
func NewDriverConfigCmd(ctx context.Context, opt *options.Common) *cobra.Command {
func NewDriverConfigCmd(ctx context.Context, opt *options.Common, driver *options.Driver) *cobra.Command {
o := driverConfigOptions{
Common: opt,
Type: options.NewDriverTypes(),
Driver: driver,
}

cmd := &cobra.Command{
Expand All @@ -80,11 +73,6 @@ func NewDriverConfigCmd(ctx context.Context, opt *options.Common) *cobra.Command
},
}

cmd.Flags().Var(o.Type, "type", "Driver type to be configured "+o.Type.Allowed())
cmd.Flags().StringVar(&o.Version, "version", config.DefaultDriver.Version, "Driver version to be configured.")
cmd.Flags().StringSliceVar(&o.Repos, "repo", config.DefaultDriver.Repos, "Driver repo to be configured.")
cmd.Flags().StringVar(&o.Name, "name", config.DefaultDriver.Name, "Driver name to be configured.")
cmd.Flags().StringVar(&o.HostRoot, "host-root", config.DefaultDriver.HostRoot, "Driver host root to be configured.")
cmd.Flags().BoolVar(&o.Update, "update-falco", true, "Whether to update Falco config/configmap.")
cmd.Flags().StringVar(&o.Namespace, "namespace", "", "Kubernetes namespace.")
cmd.Flags().StringVar(&o.KubeConfig, "kubeconfig", "", "Kubernetes config.")
Expand All @@ -98,91 +86,20 @@ func (o *driverConfigOptions) RunDriverConfig(ctx context.Context, cmd *cobra.Co
err error
)

driverCfg, err := config.Driverer()
if err != nil {
return err
}

loggerArgs := make([]pterm.LoggerArgument, 0)
if f := cmd.Flags().Lookup("version"); f != nil && f.Changed {
driverCfg.Version = o.Version
loggerArgs = append(loggerArgs, pterm.LoggerArgument{
Key: "driver version",
Value: o.Version,
})
}
if f := cmd.Flags().Lookup("repo"); f != nil && f.Changed {
driverCfg.Repos = o.Repos
loggerArgs = append(loggerArgs, pterm.LoggerArgument{
Key: "driver repos",
Value: strings.Join(o.Repos, ","),
})
}
if f := cmd.Flags().Lookup("name"); f != nil && f.Changed {
driverCfg.Name = o.Name
loggerArgs = append(loggerArgs, pterm.LoggerArgument{
Key: "driver name",
Value: o.Name,
})
}
if f := cmd.Flags().Lookup("host-root"); f != nil && f.Changed {
if !filepath.IsAbs(o.HostRoot) {
return fmt.Errorf("host-root must be an absolute path: %s", o.HostRoot)
}
driverCfg.HostRoot = o.HostRoot
loggerArgs = append(loggerArgs, pterm.LoggerArgument{
Key: "driver host root",
Value: o.HostRoot,
})
}
if f := cmd.Flags().Lookup("type"); f != nil && f.Changed {
loggerArgs = append(loggerArgs, pterm.LoggerArgument{
Key: "driver type",
Value: o.Type.String(),
})
if o.Type.String() != "auto" {
// Ok driver type was enforced by the user
dType, err = drivertype.Parse(o.Type.String())
if err != nil {
return err
}
} else {
// automatic logic
info, err := driverkernel.FetchInfo("", "")
if err != nil {
return err
}
o.Printer.Logger.Debug("Fetched kernel info", o.Printer.Logger.Args(
"arch", info.Architecture.ToNonDeb(),
"kernel release", info.String(),
"kernel version", info.KernelVersion))

d, err := driverdistro.Discover(info, driverCfg.HostRoot)
if err != nil {
if !errors.Is(err, driverdistro.ErrUnsupported) {
return err
}
o.Printer.Logger.Info("Detected an unsupported target system; falling back at generic logic.")
}
o.Printer.Logger.Debug("Discovered distro", o.Printer.Logger.Args("target", d))

dType = d.PreferredDriver(info)
if dType == nil {
return fmt.Errorf("automatic driver selection failed")
}
}
driverCfg.Type = dType
}

o.Printer.Logger.Info("Running falcoctl driver config", loggerArgs)
o.Printer.Logger.Info("Running falcoctl driver config", o.Printer.Logger.Args(
"name", o.Driver.Name,
"version", o.Driver.Version,
"type", o.Driver.Type.String(),
"host-root", o.Driver.HostRoot,
"repos", strings.Join(o.Driver.Repos, ",")))

if o.Update {
err = o.commit(ctx, dType)
if err != nil {
return err
}
}
return config.StoreDriver(&driverCfg, o.ConfigFile)
return config.StoreDriver(o.Driver.ToDriverConfig(), o.ConfigFile)
}

func checkFalcoRunsWithDrivers(engineKind string) error {
Expand Down
10 changes: 5 additions & 5 deletions cmd/driver/config/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,19 +36,19 @@ Usage:

Flags:
-h, --help help for config
--host-root string Driver host root to be configured. (default "/")
--kubeconfig string Kubernetes config.
--name string Driver name to be configured. (default "falco")
--namespace string Kubernetes namespace.
--repo strings Driver repo to be configured. (default [https://download.falco.org/driver])
--type string Driver type to be configured (auto, ebpf, kmod, modern_ebpf) (default "kmod")
--update-falco Whether to update Falco config/configmap. (default true)
--version string Driver version to be configured.

Global Flags:
--config string config file to be used for falcoctl (default "/etc/falcoctl/falcoctl.yaml")
--host-root string Driver host root to be used. (default "/")
--log-format string Set formatting for logs (color, text, json) (default "color")
--log-level string Set level for logs (info, warn, debug, trace) (default "info")
--name string Driver name to be used. (default "falco")
--repo strings Driver repo to be used. (default [https://download.falco.org/driver])
--type string Driver type to be used (auto, ebpf, kmod, modern_ebpf) (default "kmod")
--version string Driver version to be used.
`

var addAssertFailedBehavior = func(specificError string) {
Expand Down
128 changes: 121 additions & 7 deletions cmd/driver/driver_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,19 +20,28 @@ package driver

import (
"context"
"errors"
"fmt"

"github.com/spf13/cobra"
"github.com/spf13/viper"

drivercleanup "github.com/falcosecurity/falcoctl/cmd/driver/cleanup"
driverconfig "github.com/falcosecurity/falcoctl/cmd/driver/config"
driverinstall "github.com/falcosecurity/falcoctl/cmd/driver/install"
driverprintenv "github.com/falcosecurity/falcoctl/cmd/driver/printenv"
"github.com/falcosecurity/falcoctl/internal/config"
commonoptions "github.com/falcosecurity/falcoctl/pkg/options"
driverdistro "github.com/falcosecurity/falcoctl/pkg/driver/distro"
driverkernel "github.com/falcosecurity/falcoctl/pkg/driver/kernel"
drivertype "github.com/falcosecurity/falcoctl/pkg/driver/type"
"github.com/falcosecurity/falcoctl/pkg/options"
)

// NewDriverCmd returns the driver command.
func NewDriverCmd(ctx context.Context, opt *commonoptions.Common) *cobra.Command {
func NewDriverCmd(ctx context.Context, opt *options.Common) *cobra.Command {
driver := &options.Driver{}
driverTypes := options.NewDriverTypes()

cmd := &cobra.Command{
Use: "driver",
DisableFlagsInUseLine: true,
Expand All @@ -41,13 +50,118 @@ func NewDriverCmd(ctx context.Context, opt *commonoptions.Common) *cobra.Command
** This command is in preview and under development. **`,
PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
opt.Initialize()
return config.Load(opt.ConfigFile)
if err := config.Load(opt.ConfigFile); err != nil {
return err
}

// Override "version" flag with viper config if not set by user.
f := cmd.Flags().Lookup("version")
if f == nil {
// should never happen
return fmt.Errorf("unable to retrieve flag version")
} else if !f.Changed && viper.IsSet(config.DriverVersionKey) {
val := viper.Get(config.DriverVersionKey)
if err := cmd.Flags().Set(f.Name, fmt.Sprintf("%v", val)); err != nil {
return fmt.Errorf("unable to overwrite \"version\" flag: %w", err)
}
}

// Override "repo" flag with viper config if not set by user.
f = cmd.Flags().Lookup("repo")
if f == nil {
// should never happen
return fmt.Errorf("unable to retrieve flag repo")
} else if !f.Changed && viper.IsSet(config.DriverReposKey) {
val, err := config.DriverRepos()
if err != nil {
return err
}
if err := cmd.Flags().Set(f.Name, fmt.Sprintf("%v", val)); err != nil {
return fmt.Errorf("unable to overwrite \"repo\" flag: %w", err)
}
}

// Override "name" flag with viper config if not set by user.
f = cmd.Flags().Lookup("name")
if f == nil {
// should never happen
return fmt.Errorf("unable to retrieve flag name")
} else if !f.Changed && viper.IsSet(config.DriverNameKey) {
val := viper.Get(config.DriverNameKey)
if err := cmd.Flags().Set(f.Name, fmt.Sprintf("%v", val)); err != nil {
return fmt.Errorf("unable to overwrite \"name\" flag: %w", err)
}
}

// Override "host-root" flag with viper config if not set by user.
f = cmd.Flags().Lookup("host-root")
if f == nil {
// should never happen
return fmt.Errorf("unable to retrieve flag host-root")
} else if !f.Changed && viper.IsSet(config.DriverHostRootKey) {
val := viper.Get(config.DriverHostRootKey)
if err := cmd.Flags().Set(f.Name, fmt.Sprintf("%v", val)); err != nil {
return fmt.Errorf("unable to overwrite \"host-root\" flag: %w", err)
}
}

// Override "type" flag with viper config if not set by user.
f = cmd.Flags().Lookup("type")
if f == nil {
// should never happen
return fmt.Errorf("unable to retrieve flag type")
} else if !f.Changed && viper.IsSet(config.DriverTypeKey) {
val := viper.Get(config.DriverTypeKey)
if err := cmd.Flags().Set(f.Name, fmt.Sprintf("%v", val)); err != nil {
return fmt.Errorf("unable to overwrite \"type\" flag: %w", err)
}
}

if driverTypes.String() != "auto" {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here we load driver.Type from given driverTypes enum parameter.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We now support auto logic for all driver commands.
This can be useful to eg: test with driver printenv which driver is being discovered for auto driver type.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or, to store driver config with correct driver built from automatic discovered one (when using driver config --type auto).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

const?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@FedeDP just nit

var err error
// Ok driver type was enforced by the user
driver.Type, err = drivertype.Parse(driverTypes.String())
if err != nil {
return err
}
} else {
// automatic logic
info, err := driverkernel.FetchInfo("", "")
if err != nil {
return err
}
opt.Printer.Logger.Debug("Fetched kernel info", opt.Printer.Logger.Args(
"arch", info.Architecture.ToNonDeb(),
"kernel release", info.String(),
"kernel version", info.KernelVersion))

d, err := driverdistro.Discover(info, driver.HostRoot)
if err != nil {
if !errors.Is(err, driverdistro.ErrUnsupported) {
return err
}
opt.Printer.Logger.Info("Detected an unsupported target system; falling back at generic logic.")
}
opt.Printer.Logger.Debug("Discovered distro", opt.Printer.Logger.Args("target", d))

driver.Type = d.PreferredDriver(info)
if driver.Type == nil {
return fmt.Errorf("automatic driver selection failed")
}
}
return driver.Validate()
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the end, we validate driver options.

},
}

cmd.AddCommand(driverinstall.NewDriverInstallCmd(ctx, opt))
cmd.AddCommand(driverconfig.NewDriverConfigCmd(ctx, opt))
cmd.AddCommand(drivercleanup.NewDriverCleanupCmd(ctx, opt))
cmd.AddCommand(driverprintenv.NewDriverPrintenvCmd(ctx, opt))
cmd.PersistentFlags().Var(driverTypes, "type", "Driver type to be used "+driverTypes.Allowed())
cmd.PersistentFlags().StringVar(&driver.Version, "version", config.DefaultDriver.Version, "Driver version to be used.")
cmd.PersistentFlags().StringSliceVar(&driver.Repos, "repo", config.DefaultDriver.Repos, "Driver repo to be used.")
cmd.PersistentFlags().StringVar(&driver.Name, "name", config.DefaultDriver.Name, "Driver name to be used.")
cmd.PersistentFlags().StringVar(&driver.HostRoot, "host-root", config.DefaultDriver.HostRoot, "Driver host root to be used.")

cmd.AddCommand(driverinstall.NewDriverInstallCmd(ctx, opt, driver))
cmd.AddCommand(driverconfig.NewDriverConfigCmd(ctx, opt, driver))
cmd.AddCommand(drivercleanup.NewDriverCleanupCmd(ctx, opt, driver))
cmd.AddCommand(driverprintenv.NewDriverPrintenvCmd(ctx, opt, driver))
return cmd
}