-
Notifications
You must be signed in to change notification settings - Fork 60
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
new(cmd,pkg,internal): implemented new
driver
command.
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
- Loading branch information
Showing
40 changed files
with
2,659 additions
and
41 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
Oops, something went wrong.