diff --git a/cmd/driver/config/config.go b/cmd/driver/config/config.go index 215972c3..c3a915f6 100644 --- a/cmd/driver/config/config.go +++ b/cmd/driver/config/config.go @@ -17,13 +17,19 @@ package driverconfig import ( "fmt" + "os" "strings" "github.com/spf13/cobra" "github.com/spf13/viper" "golang.org/x/net/context" + v1 "k8s.io/api/core/v1" + v12 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/client-go/kubernetes" + "k8s.io/client-go/rest" "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" @@ -125,10 +131,69 @@ func (o *driverConfigOptions) RunDriverConfig(_ context.Context) error { driverCfg.Type = dType if o.Update { - err = drivertype.Commit(driverCfg.HostRoot, dType) + err = commit(driverCfg.HostRoot, dType) if err != nil { return err } } return config.StoreDriver(&driverCfg, o.ConfigFile) } + +func replaceDriverTypeInFalcoConfig(filePath string, driverType drivertype.DriverType) error { + return utils.ReplaceLineInFile(filePath, "driver_mode:", "driver_mode: "+driverType.String(), 1) +} + +// commit saves the updated driver type to Falco config, +// either to the local falco.yaml or updating the deployment configmap. +func commit(hostRoot string, driverType drivertype.DriverType) error { + err := replaceDriverTypeInFalcoConfig(hostRoot+"/etc/falco/falco.yaml", driverType) + if err == nil { + return nil + } + if !os.IsNotExist(err) { + return err + } + // falco config does not exist; try K8S. + + // TODO double check + // creates the in-cluster config + cfg, err := rest.InClusterConfig() + if err != nil { + return err + } + + cl, err := kubernetes.NewForConfig(cfg) + if err != nil { + return err + } + + configMapList, err := cl.CoreV1().ConfigMaps(v1.NamespaceAll).List(context.TODO(), v12.ListOptions{ + LabelSelector: "app.kubernetes.io/instance: falco", + }) + if err != nil { + return err + } + if configMapList.Size() == 0 { + return fmt.Errorf(`no configmaps matching "app.kubernetes.io/instance: falco" label were found`) + } + + for i := 0; i < configMapList.Size(); i++ { + configMap := configMapList.Items[i] + // Modify the data in the ConfigMap ONLY if driver_mode is NOT set to plugin + // TODO: we must be sure that we are modifying the configmap for a Falco + // that is running with drivers, and not plugins. + // Scenario: user has multiple Falco pods deployed in its cluster, one running with driver, + // other running with plugins. We must only touch the one running with driver. + if val, ok := configMap.Data["driver_mode"]; !ok || val == "plugin" { + continue + } + configMap.Data["driver_mode"] = driverType.String() + + // Update the ConfigMap + _, loopErr := cl.CoreV1().ConfigMaps(configMap.Namespace).Update(context.TODO(), &configMap, v12.UpdateOptions{}) + if loopErr != nil { + return loopErr + } + } + return nil +} diff --git a/pkg/driver/distro/distro.go b/pkg/driver/distro/distro.go index 287d1f27..cc2ce560 100644 --- a/pkg/driver/distro/distro.go +++ b/pkg/driver/distro/distro.go @@ -167,6 +167,7 @@ func Build(d Distro, // be loaded directly by dkms. driverFileName := toFilename(d, &kr, driverName, driverType) filePath := toLocalPath(driverVer, driverFileName, kr.Architecture.ToNonDeb()) + printer.Logger.Info("Copying built driver to its destination.", printer.Logger.Args("src", path, "dst", filePath)) f, err := os.Open(path) //nolint:gosec // false positive if err != nil { return "", err diff --git a/pkg/driver/type/bpf.go b/pkg/driver/type/bpf.go index 6c246baa..bd6baa1f 100644 --- a/pkg/driver/type/bpf.go +++ b/pkg/driver/type/bpf.go @@ -76,6 +76,12 @@ func (b *bpf) Build(printer *output.Printer, for key, val := range env { makeCmd.Env = append(makeCmd.Env, fmt.Sprintf("%s=%s", key, val)) } - _, err := makeCmd.Output() - return srcPath + "/probe.o", err + err := runCmdPipingStdout(printer, makeCmd) + outProbe := fmt.Sprintf("%s/probe.o", srcPath) + if err == nil { + printer.Logger.Info("Probe successfully built.", printer.Logger.Args("file", outProbe)) + } else { + printer.Logger.Info("Failed to build probe.", printer.Logger.Args("err", err)) + } + return outProbe, err } diff --git a/pkg/driver/type/kmod.go b/pkg/driver/type/kmod.go index 7febb50c..754919b4 100644 --- a/pkg/driver/type/kmod.go +++ b/pkg/driver/type/kmod.go @@ -19,7 +19,6 @@ import ( "bufio" "bytes" "fmt" - "io" "os" "os/exec" "path/filepath" @@ -229,26 +228,7 @@ func (k *kmod) Build(printer *output.Printer, // Try the build through dkms dkmsCmd := exec.Command("bash", "-c", dkmsCmdArgs) //nolint:gosec // false positive - var stdout io.ReadCloser - stdout, err = dkmsCmd.StdoutPipe() - if err != nil { - printer.Logger.Warn("Failed to pipe dkms output. Trying without piping.", printer.Logger.Args("err", err)) - _, err = dkmsCmd.Output() - } else { - err = dkmsCmd.Start() - if err != nil { - printer.Logger.Warn("Failed to execute dkms.", printer.Logger.Args("err", err)) - continue - } - - // print the output of the subprocess line by line - scanner := bufio.NewScanner(stdout) - for scanner.Scan() { - m := scanner.Text() - fmt.Println(m) - } - err = dkmsCmd.Wait() - } + err = runCmdPipingStdout(printer, dkmsCmd) if err == nil { koGlob := fmt.Sprintf("/var/lib/dkms/%s/%s/%s/%s/module/%s", driverName, driverVersion, kr.String(), kr.Architecture.ToNonDeb(), driverName) var koFiles []string diff --git a/pkg/driver/type/type.go b/pkg/driver/type/type.go index 7587bbe8..6d076304 100644 --- a/pkg/driver/type/type.go +++ b/pkg/driver/type/type.go @@ -17,17 +17,12 @@ package drivertype import ( + "bufio" "fmt" - "os" + "os/exec" "github.com/falcosecurity/driverkit/pkg/kernelrelease" - "golang.org/x/net/context" - v1 "k8s.io/api/core/v1" - v12 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/client-go/kubernetes" - "k8s.io/client-go/rest" - "github.com/falcosecurity/falcoctl/internal/utils" "github.com/falcosecurity/falcoctl/pkg/output" ) @@ -66,61 +61,25 @@ func Parse(driverType string) (DriverType, error) { return nil, fmt.Errorf("wrong driver type specified: %s", driverType) } -func replaceDriverTypeInFalcoConfig(filePath string, driverType DriverType) error { - return utils.ReplaceLineInFile(filePath, "driver_mode:", "driver_mode: "+driverType.String(), 1) -} - -// Commit saves the updated driver type to Falco config, -// either to the local falco.yaml or updating the deployment configmap. -func Commit(hostRoot string, driverType DriverType) error { - err := replaceDriverTypeInFalcoConfig(hostRoot+"/etc/falco/falco.yaml", driverType) - if err == nil { - return nil - } - if !os.IsNotExist(err) { - return err - } - // falco config does not exist; try K8S. - - // TODO double check - // creates the in-cluster config - config, err := rest.InClusterConfig() - if err != nil { - return err - } - - cl, err := kubernetes.NewForConfig(config) +func runCmdPipingStdout(printer *output.Printer, cmd *exec.Cmd) error { + stdout, err := cmd.StdoutPipe() if err != nil { - return err - } - - configMapList, err := cl.CoreV1().ConfigMaps(v1.NamespaceAll).List(context.TODO(), v12.ListOptions{ - LabelSelector: "app.kubernetes.io/instance: falco", - }) - if err != nil { - return err - } - if configMapList.Size() == 0 { - return fmt.Errorf(`no configmaps matching "app.kubernetes.io/instance: falco" label were found`) - } - - for i := 0; i < configMapList.Size(); i++ { - configMap := configMapList.Items[i] - // Modify the data in the ConfigMap ONLY if driver_mode is NOT set to plugin - // TODO: we must be sure that we are modifying the configmap for a Falco - // that is running with drivers, and not plugins. - // Scenario: user has multiple Falco pods deployed in its cluster, one running with driver, - // other running with plugins. We must only touch the one running with driver. - if val, ok := configMap.Data["driver_mode"]; !ok || val == "plugin" { - continue - } - configMap.Data["driver_mode"] = driverType.String() - - // Update the ConfigMap - _, loopErr := cl.CoreV1().ConfigMaps(configMap.Namespace).Update(context.TODO(), &configMap, v12.UpdateOptions{}) - if loopErr != nil { - return loopErr + printer.Logger.Warn("Failed to pipe output. Trying without piping.", printer.Logger.Args("err", err)) + _, err = cmd.Output() + } else { + defer stdout.Close() + err = cmd.Start() + if err != nil { + printer.Logger.Warn("Failed to execute command.", printer.Logger.Args("err", err)) + } else { + // print the output of the subprocess line by line + scanner := bufio.NewScanner(stdout) + for scanner.Scan() { + m := scanner.Text() + fmt.Println(m) + } + err = cmd.Wait() } } - return nil + return err }