Skip to content

Commit

Permalink
new(cmd,pkg,internal): implemented new driver command.
Browse files Browse the repository at this point in the history
It exposes 4 subcmds:
* `install` to install (ie: either download or build) kmod or eBPF probe
* `cleanup` to cleanup a driver
* `printenv` to print environment variables about driver-loader
* `config` to configure the driver-loader feature

Signed-off-by: Federico Di Pierro <nierro92@gmail.com>
  • Loading branch information
FedeDP authored and poiana committed Nov 21, 2023
1 parent 1ad11db commit 4228e71
Show file tree
Hide file tree
Showing 40 changed files with 2,660 additions and 41 deletions.
2 changes: 1 addition & 1 deletion cmd/artifact/install/install.go
Original file line number Diff line number Diff line change
Expand Up @@ -327,7 +327,7 @@ func (o *artifactInstallOptions) RunArtifactInstall(ctx context.Context, args []
return err
}
// Extract artifact and move it to its destination directory
_, err = utils.ExtractTarGz(f, destDir)
_, err = utils.ExtractTarGz(f, destDir, 0)
if err != nil {
return fmt.Errorf("cannot extract %q to %q: %w", result.Filename, destDir, err)
}
Expand Down
57 changes: 57 additions & 0 deletions cmd/driver/cleanup/cleanup.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
// SPDX-License-Identifier: Apache-2.0
// Copyright (C) 2023 The Falco Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package drivercleanup

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
}

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

cmd := &cobra.Command{
Use: "cleanup [flags]",
DisableFlagsInUseLine: true,
Short: "Cleanup a driver",
Long: "Cleans a driver up, eg for kmod, by removing it from dkms.",
RunE: func(cmd *cobra.Command, args []string) error {
return o.RunDriverCleanup(ctx)
},
}
return cmd
}

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)
}
17 changes: 17 additions & 0 deletions cmd/driver/cleanup/doc.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// SPDX-License-Identifier: Apache-2.0
// Copyright (C) 2023 The Falco Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// Package drivercleanup defines the cleanup logic for the driver cmd.
package drivercleanup
246 changes: 246 additions & 0 deletions cmd/driver/config/config.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,246 @@
// SPDX-License-Identifier: Apache-2.0
// Copyright (C) 2023 The Falco Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package driverconfig

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

"github.com/pterm/pterm"
"github.com/spf13/cobra"
"golang.org/x/net/context"
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"
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"
)

const (
configMapDriverTypeKey = "driver_mode"
)

type driverConfigOptions struct {
*options.Common
Type *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(ctx context.Context, opt *options.Common) *cobra.Command {
o := driverConfigOptions{
Common: opt,
Type: options.NewDriverTypes(),
}

cmd := &cobra.Command{
Use: "config [flags]",
DisableFlagsInUseLine: true,
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(ctx, cmd)
},
}

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.")
return cmd
}

// RunDriverConfig implements the driver configuration command.
func (o *driverConfigOptions) RunDriverConfig(ctx context.Context, cmd *cobra.Command) error {
var (
dType drivertype.DriverType
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 {
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.DiscoverDistro(info, driverCfg.HostRoot)
if err != nil {
return err
}
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)

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

func replaceDriverTypeInFalcoConfig(hostRoot string, driverType drivertype.DriverType) error {
return utils.ReplaceLineInFile(hostRoot+"/etc/falco/falco.yaml", "driver_mode:", "driver_mode: "+driverType.String(), 1)
}

func replaceDriverTypeInK8SConfigMap(ctx context.Context, namespace, kubeconfig string, driverType drivertype.DriverType) error {
var (
err error
cfg *rest.Config
)

if kubeconfig != "" {
cfg, err = clientcmd.BuildConfigFromFlags("", kubeconfig)
} else {
cfg, err = rest.InClusterConfig()
}
if err != nil {
return err
}

cl, err := kubernetes.NewForConfig(cfg)
if err != nil {
return err
}

configMapList, err := cl.CoreV1().ConfigMaps(namespace).List(ctx, metav1.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`)
}

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[configMapDriverTypeKey]; !ok || val == "none" {
continue
}

// 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)
}
17 changes: 17 additions & 0 deletions cmd/driver/config/doc.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// SPDX-License-Identifier: Apache-2.0
// Copyright (C) 2023 The Falco Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// Package driverconfig defines the configure logic for the driver cmd.
package driverconfig

0 comments on commit 4228e71

Please sign in to comment.