Skip to content

Commit

Permalink
chore(cmd/driver,pkg/driver,internal/config): use a context for Downl…
Browse files Browse the repository at this point in the history
…oad and Build long-running actions.

Use an Enum to wrap supported drivertypes in driver.config command.

Signed-off-by: Federico Di Pierro <nierro92@gmail.com>

Co-authored-by: alacuku <aldo.lacu@live.it>
  • Loading branch information
FedeDP and alacuku committed Nov 15, 2023
1 parent b12e367 commit d831e84
Show file tree
Hide file tree
Showing 11 changed files with 113 additions and 64 deletions.
105 changes: 65 additions & 40 deletions cmd/driver/config/config.go
Expand Up @@ -16,17 +16,18 @@
package driverconfig

import (
"encoding/json"
"fmt"
"os"
"strings"

"github.com/pterm/pterm"
"github.com/spf13/cobra"
"golang.org/x/net/context"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/rest"
"k8s.io/client-go/tools/clientcmd"

"github.com/falcosecurity/falcoctl/internal/config"
"github.com/falcosecurity/falcoctl/internal/utils"
Expand All @@ -36,18 +37,24 @@ import (
"github.com/falcosecurity/falcoctl/pkg/options"
)

const (
configMapDriverTypeKey = "driver_mode"
)

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

Check failure on line 46 in cmd/driver/config/config.go

View workflow job for this annotation

GitHub Actions / Lint golang files

undefined: options.DriverTypes (typecheck)

Check failure on line 46 in cmd/driver/config/config.go

View workflow job for this annotation

GitHub Actions / Lint golang files

undefined: options.DriverTypes) (typecheck)

Check failure on line 46 in cmd/driver/config/config.go

View workflow job for this annotation

GitHub Actions / build (linux, amd64)

undefined: options.DriverTypes
Version string
Repos []string
Name string
HostRoot string
Update bool
Namespace string
KubeConfig string
}

// NewDriverConfigCmd configures a driver and stores it in config.
func NewDriverConfigCmd(_ context.Context, opt *options.Common) *cobra.Command {
func NewDriverConfigCmd(ctx context.Context, opt *options.Common) *cobra.Command {
o := driverConfigOptions{
Common: opt,
}
Expand All @@ -58,22 +65,23 @@ func NewDriverConfigCmd(_ context.Context, opt *options.Common) *cobra.Command {
Short: "Configure a driver",
Long: "Configure a driver for future usages with other driver subcommands",
RunE: func(cmd *cobra.Command, args []string) error {
return o.RunDriverConfig(cmd)
return o.RunDriverConfig(ctx, cmd)
},
}

cmd.Flags().StringVar(&o.Type, "type", config.DefaultDriver.Type,
"Driver type to be configured. Allowed: "+strings.Join(drivertype.GetDriverTypes(), ",")+",auto")
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().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.")
return cmd
}

// RunDriverConfig implements the driver configuration command.
func (o *driverConfigOptions) RunDriverConfig(cmd *cobra.Command) error {
func (o *driverConfigOptions) RunDriverConfig(ctx context.Context, cmd *cobra.Command) error {
var (
dType drivertype.DriverType
err error
Expand Down Expand Up @@ -118,9 +126,9 @@ func (o *driverConfigOptions) RunDriverConfig(cmd *cobra.Command) error {
Key: "driver type",
Value: o.Type,
})
if o.Type != "auto" {
if o.Type.String() != "auto" {
// Ok driver type was enforced by the user
dType, err = drivertype.Parse(o.Type)
dType, err = drivertype.Parse(o.Type.String())
if err != nil {
return err
}
Expand Down Expand Up @@ -152,33 +160,29 @@ func (o *driverConfigOptions) RunDriverConfig(cmd *cobra.Command) error {
o.Printer.Logger.Info("Running falcoctl driver config", loggerArgs)

if o.Update {
err = commit(driverCfg.HostRoot, dType)
err = commit(ctx, dType, driverCfg.HostRoot, o.Namespace, o.KubeConfig)
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)
func replaceDriverTypeInFalcoConfig(hostRoot string, driverType drivertype.DriverType) error {
return utils.ReplaceLineInFile(hostRoot+"/etc/falco/falco.yaml", "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.
func replaceDriverTypeInK8SConfigMap(ctx context.Context, namespace, kubeconfig string, driverType drivertype.DriverType) error {
var (
err error
cfg *rest.Config
)

// TODO double check
// creates the in-cluster config
cfg, err := rest.InClusterConfig()
if kubeconfig != "" {
cfg, err = clientcmd.BuildConfigFromFlags("", kubeconfig)
} else {
cfg, err = rest.InClusterConfig()
}
if err != nil {
return err
}
Expand All @@ -188,7 +192,7 @@ func commit(hostRoot string, driverType drivertype.DriverType) error {
return err
}

configMapList, err := cl.CoreV1().ConfigMaps(corev1.NamespaceAll).List(context.TODO(), metav1.ListOptions{
configMapList, err := cl.CoreV1().ConfigMaps(namespace).List(ctx, metav1.ListOptions{
LabelSelector: "app.kubernetes.io/instance: falco",
})
if err != nil {
Expand All @@ -198,23 +202,44 @@ func commit(hostRoot string, driverType drivertype.DriverType) error {
return fmt.Errorf(`no configmaps matching "app.kubernetes.io/instance: falco" label were found`)
}

type patchDriverTypeValue struct {
Op string `json:"op"`
Path string `json:"path"`
Value string `json:"value"`
}
payload := []patchDriverTypeValue{{
Op: "replace",
Path: "/data/" + configMapDriverTypeKey,
Value: driverType.String(),
}}
plBytes, _ := json.Marshal(payload)

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" {
if val, ok := configMap.Data[configMapDriverTypeKey]; !ok || val == "none" {
continue
}
configMap.Data["driver_mode"] = driverType.String()

// Update the ConfigMap
_, loopErr := cl.CoreV1().ConfigMaps(configMap.Namespace).Update(context.TODO(), &configMap, metav1.UpdateOptions{})
if loopErr != nil {
return loopErr
// Patch the configMap
if _, err = cl.CoreV1().ConfigMaps(configMap.Namespace).Patch(
ctx, configMap.Name, types.JSONPatchType, plBytes, metav1.PatchOptions{}); err != nil {
return err
}
}
return nil
}

// commit saves the updated driver type to Falco config,
// either to the local falco.yaml or updating the deployment configmap.
func commit(ctx context.Context, driverType drivertype.DriverType, hostroot, namespace, kubeconfig string) error {
if namespace != "" {
// Ok we are on k8s
return replaceDriverTypeInK8SConfigMap(ctx, namespace, kubeconfig, driverType)
}
return replaceDriverTypeInFalcoConfig(hostroot, driverType)
}
6 changes: 3 additions & 3 deletions cmd/driver/install/install.go
Expand Up @@ -133,7 +133,7 @@ func setDefaultHTTPClientOpts(downloadOptions driverDownloadOptions) {
}

// RunDriverInstall implements the driver install command.
func (o *driverInstallOptions) RunDriverInstall(_ context.Context, driver *config.Driver) (string, error) {
func (o *driverInstallOptions) RunDriverInstall(ctx context.Context, driver *config.Driver) (string, error) {
kr, err := driverkernel.FetchInfo(o.DriverKernelRelease, o.DriverKernelVersion)
if err != nil {
return "", err
Expand Down Expand Up @@ -180,7 +180,7 @@ func (o *driverInstallOptions) RunDriverInstall(_ context.Context, driver *confi

var dest string
if o.Download {
dest, err = driverdistro.Download(d, o.Printer, kr, driver.Name, driver.Type, driver.Version, driver.Repos)
dest, err = driverdistro.Download(ctx, d, o.Printer, kr, driver.Name, driver.Type, driver.Version, driver.Repos)
if err == nil {
return dest, nil
}
Expand All @@ -190,7 +190,7 @@ func (o *driverInstallOptions) RunDriverInstall(_ context.Context, driver *confi
}

if o.Compile {
dest, err = driverdistro.Build(d, o.Printer, kr, driver.Name, driver.Type, driver.Version, driver.HostRoot)
dest, err = driverdistro.Build(ctx, d, o.Printer, kr, driver.Name, driver.Type, driver.Version, driver.HostRoot)
if err == nil {
return dest, nil
}
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Expand Up @@ -30,7 +30,6 @@ require (
google.golang.org/api v0.149.0
gopkg.in/ini.v1 v1.67.0
gopkg.in/yaml.v3 v3.0.1
k8s.io/api v0.28.3
k8s.io/apimachinery v0.28.3
k8s.io/client-go v0.28.3
k8s.io/utils v0.0.0-20230726121419-3b25d923346b
Expand Down Expand Up @@ -284,6 +283,7 @@ require (
gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/square/go-jose.v2 v2.6.0 // indirect
inet.af/netaddr v0.0.0-20230525184311-b8eac61e914a // indirect
k8s.io/api v0.28.3 // indirect
k8s.io/klog/v2 v2.100.1 // indirect
k8s.io/kube-openapi v0.0.0-20231010175941-2dd684a91f00 // indirect
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect
Expand Down
5 changes: 3 additions & 2 deletions internal/config/config.go
Expand Up @@ -124,7 +124,8 @@ const (
// DriverNameKey is the Viper key for the driver name.
DriverNameKey = "driver.name"
// DriverHostRootKey is the Viper key for the driver host root.
DriverHostRootKey = "driver.hostRoot"
DriverHostRootKey = "driver.hostRoot"
falcoHostRootEnvKey = "HOST_ROOT"
)

// Index represents a configured index.
Expand Down Expand Up @@ -562,7 +563,7 @@ func Driverer() (Driver, error) {

// Bind FALCOCTL_DRIVER_HOSTROOT key to HOST_ROOT,
// so that we manage Falco HOST_ROOT variable too.
_ = viper.BindEnv(DriverHostRootKey, "HOST_ROOT")
_ = viper.BindEnv(DriverHostRootKey, falcoHostRootEnvKey)

drvCfg := Driver{
Type: drvType,
Expand Down
19 changes: 14 additions & 5 deletions pkg/driver/distro/distro.go
Expand Up @@ -28,6 +28,7 @@ import (

"github.com/docker/docker/pkg/homedir"
"github.com/falcosecurity/driverkit/pkg/kernelrelease"
"golang.org/x/net/context"
"gopkg.in/ini.v1"

"github.com/falcosecurity/falcoctl/internal/utils"
Expand Down Expand Up @@ -146,7 +147,8 @@ func copyDataToLocalPath(destination string, src io.Reader) error {
// Build will try to build the desired driver for the specified distro and kernel release.
//
//nolint:gocritic // the method shall not be able to modify kr
func Build(d Distro,
func Build(ctx context.Context,
d Distro,
printer *output.Printer,
kr kernelrelease.KernelRelease,
driverName string,
Expand All @@ -158,7 +160,7 @@ func Build(d Distro,
if err != nil {
return "", err
}
path, err := driverType.Build(printer, d.FixupKernel(kr), driverName, driverVer, env)
path, err := driverType.Build(ctx, printer, d.FixupKernel(kr), driverName, driverVer, env)
if err != nil {
return "", err
}
Expand All @@ -179,7 +181,8 @@ func Build(d Distro,
// Download will try to download drivers for a distro trying specified repos.
//
//nolint:gocritic // the method shall not be able to modify kr
func Download(d Distro,
func Download(ctx context.Context,
d Distro,
printer *output.Printer,
kr kernelrelease.KernelRelease,
driverName string,
Expand All @@ -198,13 +201,19 @@ func Download(d Distro,
// stopping at first successful http GET.
for _, repo := range repos {
url := toURL(repo, driverVer, driverFileName, kr.Architecture.ToNonDeb())
printer.Logger.Info("Trying to download a driver", printer.Logger.Args("url", url))
printer.Logger.Info("Trying to download a driver.", printer.Logger.Args("url", url))

resp, err := http.Get(url) //nolint:gosec,noctx // false positive
req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil)
if err != nil {
printer.Logger.Warn("Error creating http request.", printer.Logger.Args("err", err))
continue
}
resp, err := http.DefaultClient.Do(req)
if err != nil || resp.StatusCode != 200 {
if err == nil {
_ = resp.Body.Close()
}
printer.Logger.Warn("Error GETting url.", printer.Logger.Args("err", err))
continue
}
return destination, copyDataToLocalPath(destination, resp.Body)
Expand Down
6 changes: 4 additions & 2 deletions pkg/driver/type/bpf.go
Expand Up @@ -20,6 +20,7 @@ import (
"os/exec"

"github.com/falcosecurity/driverkit/pkg/kernelrelease"
"golang.org/x/net/context"
"k8s.io/utils/mount"

"github.com/falcosecurity/falcoctl/pkg/output"
Expand Down Expand Up @@ -61,7 +62,8 @@ func (b *bpf) HasArtifacts() bool {
}

//nolint:gocritic // the method shall not be able to modify kr
func (b *bpf) Build(printer *output.Printer,
func (b *bpf) Build(ctx context.Context,
printer *output.Printer,
_ kernelrelease.KernelRelease,
driverName, driverVersion string,
env map[string]string,
Expand All @@ -71,7 +73,7 @@ func (b *bpf) Build(printer *output.Printer,
srcPath := fmt.Sprintf("/usr/src/%s-%s/bpf", driverName, driverVersion)

makeCmdArgs := fmt.Sprintf(`make -C %q`, srcPath)
makeCmd := exec.Command("bash", "-c", makeCmdArgs) //nolint:gosec // false positive
makeCmd := exec.CommandContext(ctx, "bash", "-c", makeCmdArgs) //nolint:gosec // false positive
// Append requested env variables to the command env
for key, val := range env {
makeCmd.Env = append(makeCmd.Env, fmt.Sprintf("%s=%s", key, val))
Expand Down
9 changes: 5 additions & 4 deletions pkg/driver/type/kmod.go
Expand Up @@ -26,6 +26,7 @@ import (
"time"

"github.com/falcosecurity/driverkit/pkg/kernelrelease"
"golang.org/x/net/context"

"github.com/falcosecurity/falcoctl/pkg/output"
)
Expand Down Expand Up @@ -183,7 +184,8 @@ func createDKMSMakeFile(gcc string) error {
}

//nolint:gocritic // the method shall not be able to modify kr
func (k *kmod) Build(printer *output.Printer,
func (k *kmod) Build(ctx context.Context,
printer *output.Printer,
kr kernelrelease.KernelRelease,
driverName, driverVersion string,
_ map[string]string,
Expand Down Expand Up @@ -212,7 +214,6 @@ func (k *kmod) Build(printer *output.Printer,
// Only gcc compiler has `-print-search-dirs` option.
gccSearchArgs := fmt.Sprintf(`%s -print-search-dirs 2>&1 | grep "install:"`, gcc)
_, err = exec.Command("bash", "-c", gccSearchArgs).Output() //nolint:gosec // false positive

if err != nil {
continue
}
Expand All @@ -227,7 +228,7 @@ func (k *kmod) Build(printer *output.Printer,
driverName, driverVersion, kr.String())

// Try the build through dkms
dkmsCmd := exec.Command("bash", "-c", dkmsCmdArgs) //nolint:gosec // false positive
dkmsCmd := exec.CommandContext(ctx, "bash", "-c", dkmsCmdArgs) //nolint:gosec // false positive
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)
Expand All @@ -251,7 +252,7 @@ func (k *kmod) Build(printer *output.Printer,
scanner := bufio.NewScanner(logBuf)
for scanner.Scan() {
m := scanner.Text()
fmt.Println(m)
printer.DefaultText.Println(m)
}
}
}
Expand Down

0 comments on commit d831e84

Please sign in to comment.