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

feat(config): reload global config when config file is updated #1862

Open
wants to merge 9 commits into
base: main
Choose a base branch
from
60 changes: 33 additions & 27 deletions KubeArmor/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,7 @@ func LoadConfig() error {
if cfgfile == "" {
cfgfile = "kubearmor.yaml"
}

if _, err := os.Stat(cfgfile); err == nil {
kg.Printf("setting config from file [%s]", cfgfile)
viper.SetConfigFile(cfgfile)
Expand All @@ -247,6 +248,8 @@ func LoadConfig() error {
}
}

kg.Printf("Configuration [%+v]", GlobalCfg)

GlobalCfg.Cluster = viper.GetString(ConfigCluster)
GlobalCfg.Host = viper.GetString(ConfigHost)
if hostname, err := os.Hostname(); GlobalCfg.Host == "" && err == nil {
Expand All @@ -268,16 +271,41 @@ func LoadConfig() error {
return fmt.Errorf("CRI socket must start with 'unix://' (%s is invalid)", GlobalCfg.CRISocket)
}

GlobalCfg.Visibility = viper.GetString(ConfigVisibility)
GlobalCfg.HostVisibility = viper.GetString(ConfigHostVisibility)

GlobalCfg.Policy = viper.GetBool(ConfigKubearmorPolicy)
GlobalCfg.HostPolicy = viper.GetBool(ConfigKubearmorHostPolicy)
GlobalCfg.KVMAgent = viper.GetBool(ConfigKubearmorVM)
GlobalCfg.K8sEnv = viper.GetBool(ConfigK8sEnv)

GlobalCfg.Debug = viper.GetBool(ConfigDebug)

if GlobalCfg.KVMAgent {
GlobalCfg.Policy = false
GlobalCfg.HostPolicy = true
}

GlobalCfg.CoverageTest = viper.GetBool(ConfigCoverageTest)

GlobalCfg.ConfigUntrackedNs = strings.Split(viper.GetString(ConfigUntrackedNs), ",")

GlobalCfg.LsmOrder = strings.Split(viper.GetString(LsmOrder), ",")

GlobalCfg.BPFFsPath = viper.GetString(BPFFsPath)

GlobalCfg.InitTimeout = viper.GetString(ConfigInitTimeout)

GlobalCfg.StateAgent = viper.GetBool(ConfigStateAgent)

GlobalCfg.AnnotateResources = viper.GetBool(ConfigAnnotateResources)

LoadDynamicConfig()

kg.Printf("Final Configuration [%+v]", GlobalCfg)

return nil
}

// LoadDynamicConfig set dynamic configuration which can be updated at runtime without restarting kubearmor
func LoadDynamicConfig() {
GlobalCfg.DefaultFilePosture = viper.GetString(ConfigDefaultFilePosture)
GlobalCfg.DefaultNetworkPosture = viper.GetString(ConfigDefaultNetworkPosture)
GlobalCfg.DefaultCapabilitiesPosture = viper.GetString(ConfigDefaultCapabilitiesPosture)
Expand All @@ -286,12 +314,8 @@ func LoadConfig() error {
GlobalCfg.HostDefaultNetworkPosture = viper.GetString(ConfigHostDefaultNetworkPosture)
GlobalCfg.HostDefaultCapabilitiesPosture = viper.GetString(ConfigHostDefaultCapabilitiesPosture)

kg.Printf("Configuration [%+v]", GlobalCfg)

if GlobalCfg.KVMAgent {
GlobalCfg.Policy = false
GlobalCfg.HostPolicy = true
}
GlobalCfg.Visibility = viper.GetString(ConfigVisibility)
GlobalCfg.HostVisibility = viper.GetString(ConfigHostVisibility)

if GlobalCfg.HostVisibility == "default" {
if GlobalCfg.KVMAgent || (!GlobalCfg.K8sEnv && GlobalCfg.HostPolicy) {
Expand All @@ -301,28 +325,10 @@ func LoadConfig() error {
}
}

GlobalCfg.CoverageTest = viper.GetBool(ConfigCoverageTest)

GlobalCfg.ConfigUntrackedNs = strings.Split(viper.GetString(ConfigUntrackedNs), ",")

GlobalCfg.LsmOrder = strings.Split(viper.GetString(LsmOrder), ",")

GlobalCfg.BPFFsPath = viper.GetString(BPFFsPath)

GlobalCfg.EnforcerAlerts = viper.GetBool(EnforcerAlerts)

GlobalCfg.DefaultPostureLogs = viper.GetBool(ConfigDefaultPostureLogs)

GlobalCfg.InitTimeout = viper.GetString(ConfigInitTimeout)

GlobalCfg.StateAgent = viper.GetBool(ConfigStateAgent)

GlobalCfg.AlertThrottling = viper.GetBool(ConfigAlertThrottling)
GlobalCfg.MaxAlertPerSec = viper.GetInt(ConfigMaxAlertPerSec)
GlobalCfg.ThrottleSec = viper.GetInt(ConfigThrottleSec)
GlobalCfg.AnnotateResources = viper.GetBool(ConfigAnnotateResources)

kg.Printf("Final Configuration [%+v]", GlobalCfg)

return nil
}
2 changes: 2 additions & 0 deletions KubeArmor/core/kubeArmor.go
Original file line number Diff line number Diff line change
Expand Up @@ -413,6 +413,8 @@ func KubeArmor() {
dm.Node.KernelVersion = kl.GetCommandOutputWithoutErr("uname", []string{"-r"})
dm.Node.KernelVersion = strings.TrimSuffix(dm.Node.KernelVersion, "\n")

dm.WatchConfigChanges()

dm.NodeLock.Unlock()

} else if cfg.GlobalCfg.K8sEnv {
Expand Down
46 changes: 46 additions & 0 deletions KubeArmor/core/unorchestratedUpdates.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ package core

import (
"encoding/json"
"github.com/fsnotify/fsnotify"
"github.com/spf13/viper"
"os"
"regexp"
"sort"
Expand Down Expand Up @@ -38,6 +40,50 @@ func (dm *KubeArmorDaemon) SetContainerNSVisibility() {
dm.UpdateVisibility("ADDED", "container_namespace", visibility)
}

// =================== //
// == Config Update == //
// =================== //

// WatchConfigChanges watches for configuration changes and updates the default posture
func (dm *KubeArmorDaemon) WatchConfigChanges() {
viper.OnConfigChange(func(e fsnotify.Event) {
dm.Logger.Printf("Config file changed: %s", e.Name)
cfg.LoadDynamicConfig()

// Update the default posture
globalPosture := tp.DefaultPosture{
FileAction: validateGlobalDefaultPosture(cfg.GlobalCfg.DefaultFilePosture),
NetworkAction: validateGlobalDefaultPosture(cfg.GlobalCfg.DefaultNetworkPosture),
CapabilitiesAction: validateGlobalDefaultPosture(cfg.GlobalCfg.DefaultCapabilitiesPosture),
}
// Update the visibility
visibility := tp.Visibility{
File: dm.validateVisibility("file", cfg.GlobalCfg.Visibility),
Process: dm.validateVisibility("process", cfg.GlobalCfg.Visibility),
Network: dm.validateVisibility("network", cfg.GlobalCfg.Visibility),
Capabilities: dm.validateVisibility("capabilities", cfg.GlobalCfg.Visibility),
}

// Apply the changes to the daemon
dm.UpdateGlobalPosture(globalPosture)

// Update default posture for endpoints
for _, ep := range dm.EndPoints {
dm.Logger.Printf("Updating Default Posture for endpoint %s", ep.EndPointName)
dm.UpdateDefaultPosture("MODIFIED", ep.NamespaceName, globalPosture, false)
dm.UpdateVisibility("MODIFIED", ep.NamespaceName, visibility)
}

// Update throttling configs
dm.SystemMonitor.UpdateThrottlingConfig()

// Update the default posture and visibility for the unorchestrated containers
dm.SystemMonitor.UpdateVisibility()
dm.UpdateHostSecurityPolicies()
})
viper.WatchConfig()
}

// ====================================== //
// == Container Security Policy Update == //
// ====================================== //
Expand Down
2 changes: 1 addition & 1 deletion KubeArmor/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ require (
github.com/containerd/containerd v1.7.13
github.com/containerd/typeurl/v2 v2.1.1
github.com/docker/docker v25.0.5+incompatible
github.com/fsnotify/fsnotify v1.7.0
github.com/golang/protobuf v1.5.4
github.com/google/uuid v1.6.0
github.com/kubearmor/KubeArmor/pkg/KubeArmorController v0.0.0-20240110164432-c2c1b121cd94
Expand Down Expand Up @@ -64,7 +65,6 @@ require (
github.com/emicklei/go-restful/v3 v3.11.2 // indirect
github.com/evanphx/json-patch/v5 v5.7.0 // indirect
github.com/felixge/httpsnoop v1.0.4 // indirect
github.com/fsnotify/fsnotify v1.7.0 // indirect
github.com/go-logr/logr v1.4.2 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/go-openapi/jsonpointer v0.20.2 // indirect
Expand Down
Loading