Skip to content

Commit

Permalink
implement NRI handler
Browse files Browse the repository at this point in the history
In operator, for NRI detection, once it is known that containerd is available as runtime then rather setting it as runtime we go further and try to check for NRI availability using the same process/method. If NRI is not found then containerd would be set as the runtime. In implementation I've used the same logic which was used to detect containerd in case docker was available and then we were trying to see if containerd is available or not.

Signed-off-by: Prateek <[email protected]>
  • Loading branch information
Prateeknandle committed Jan 17, 2025
1 parent 503b97d commit 410f8f2
Show file tree
Hide file tree
Showing 8 changed files with 543 additions and 11 deletions.
18 changes: 18 additions & 0 deletions KubeArmor/common/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -442,6 +442,24 @@ var ContainerRuntimeSocketMap = map[string][]string{
},
}

// NRISocketMap Structure
var NRISocketMap = map[string][]string{
"nri": {
"/var/run/nri/nri.sock",
"/run/nri/nri.sock",
},
}

// GetNRISocket Function
func GetNRISocket(ContainerRuntime string) string {
for _, candidate := range NRISocketMap["nri"] {
if _, err := os.Stat(candidate); err == nil {
return candidate
}
}
return ""
}

// GetCRISocket Function
func GetCRISocket(ContainerRuntime string) string {
for _, k := range ContainerRuntimeSocketKeys {
Expand Down
14 changes: 14 additions & 0 deletions KubeArmor/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ type KubearmorConfig struct {
LogPath string // Log file to use
SELinuxProfileDir string // Directory to store SELinux profiles
CRISocket string // Container runtime to use
NRISocket string // NRI socket to use
NRIIndex string // NRI socket to use

Visibility string // Container visibility to use
HostVisibility string // Host visibility to use
Expand Down Expand Up @@ -82,6 +84,8 @@ const (
ConfigLogPath string = "logPath"
ConfigSELinuxProfileDir string = "seLinuxProfileDir"
ConfigCRISocket string = "criSocket"
ConfigNRISocket string = "nriSocket"
ConfigNRIIndex string = "nriIndex"
ConfigVisibility string = "visibility"
ConfigHostVisibility string = "hostVisibility"
ConfigKubearmorPolicy string = "enableKubeArmorPolicy"
Expand Down Expand Up @@ -122,6 +126,8 @@ func readCmdLineParams() {
logStr := flag.String(ConfigLogPath, "none", "log file path, {path|stdout|none}")
seLinuxProfileDirStr := flag.String(ConfigSELinuxProfileDir, "/tmp/kubearmor.selinux", "SELinux profile directory")
criSocket := flag.String(ConfigCRISocket, "", "path to CRI socket (format: unix:///path/to/file.sock)")
nriSocket := flag.String(ConfigNRISocket, "", "path to NRI socket (format: /path/to/file.sock)")
nriIndex := flag.String(ConfigNRIIndex, "99", "NRI plugin index")

visStr := flag.String(ConfigVisibility, "process,file,network,capabilities", "Container Visibility to use [process,file,network,capabilities,none]")
hostVisStr := flag.String(ConfigHostVisibility, "default", "Host Visibility to use [process,file,network,capabilities,none] (default \"none\" for k8s, \"process,file,network,capabilities\" for VM)")
Expand Down Expand Up @@ -185,6 +191,8 @@ func readCmdLineParams() {
viper.SetDefault(ConfigLogPath, *logStr)
viper.SetDefault(ConfigSELinuxProfileDir, *seLinuxProfileDirStr)
viper.SetDefault(ConfigCRISocket, *criSocket)
viper.SetDefault(ConfigNRISocket, *nriSocket)
viper.SetDefault(ConfigNRIIndex, *nriIndex)

viper.SetDefault(ConfigVisibility, *visStr)
viper.SetDefault(ConfigHostVisibility, *hostVisStr)
Expand Down Expand Up @@ -278,6 +286,12 @@ func LoadConfig() error {
return fmt.Errorf("CRI socket must start with 'unix://' (%s is invalid)", GlobalCfg.CRISocket)
}

GlobalCfg.NRISocket = os.Getenv("NRI_SOCKET")
if GlobalCfg.NRISocket == "" {
GlobalCfg.NRISocket = viper.GetString(ConfigNRISocket)
}
GlobalCfg.NRIIndex = viper.GetString(ConfigNRIIndex)

GlobalCfg.Policy = viper.GetBool(ConfigKubearmorPolicy)
GlobalCfg.HostPolicy = viper.GetBool(ConfigKubearmorHostPolicy)
GlobalCfg.KVMAgent = viper.GetBool(ConfigKubearmorVM)
Expand Down
37 changes: 32 additions & 5 deletions KubeArmor/core/kubeArmor.go
Original file line number Diff line number Diff line change
Expand Up @@ -597,7 +597,6 @@ func KubeArmor() {

// Un-orchestrated workloads
if !dm.K8sEnabled && cfg.GlobalCfg.Policy {

// Check if cri socket set, if not then auto detect
if cfg.GlobalCfg.CRISocket == "" {
if kl.GetCRISocket("") == "" {
Expand Down Expand Up @@ -626,8 +625,14 @@ func KubeArmor() {
// monitor docker events
go dm.MonitorDockerEvents()
} else if strings.Contains(cfg.GlobalCfg.CRISocket, "containerd") {
// monitor containerd events
go dm.MonitorContainerdEvents()
// insuring NRI monitoring only in case containerd is present
if dm.checkNRIAvailability() {
// monitor NRI events
go dm.MonitorNRIEvents()
} else {
// monitor containerd events
go dm.MonitorContainerdEvents()
}
} else if strings.Contains(cfg.GlobalCfg.CRISocket, "cri-o") {
// monitor crio events
go dm.MonitorCrioEvents()
Expand All @@ -642,8 +647,10 @@ func KubeArmor() {
}

if dm.K8sEnabled && cfg.GlobalCfg.Policy {
// check if the CRI socket set while executing kubearmor exists
if cfg.GlobalCfg.CRISocket != "" {
if dm.checkNRIAvailability() {
// monitor NRI events
go dm.MonitorNRIEvents()
} else if cfg.GlobalCfg.CRISocket != "" { // check if the CRI socket set while executing kubearmor exists
trimmedSocket := strings.TrimPrefix(cfg.GlobalCfg.CRISocket, "unix://")
if _, err := os.Stat(trimmedSocket); err != nil {
dm.Logger.Warnf("Error while looking for CRI socket file: %s", err.Error())
Expand Down Expand Up @@ -892,3 +899,23 @@ func KubeArmor() {
// destroy the daemon
dm.DestroyKubeArmorDaemon()
}

func (dm *KubeArmorDaemon) checkNRIAvailability() bool {
// Check if nri socket is set, if not then auto detect
if cfg.GlobalCfg.NRISocket == "" {
if kl.GetNRISocket("") != "" {
cfg.GlobalCfg.NRISocket = kl.GetNRISocket("")
} else {
dm.Logger.Warnf("Error while looking for NRI socket file")
return false
}
} else {
// NRI socket supplied by user, check for existence
_, err := os.Stat(cfg.GlobalCfg.NRISocket)
if err != nil {
dm.Logger.Warnf("Error while looking for NRI socket file %s", err.Error())
return false
}
}
return true
}
Loading

0 comments on commit 410f8f2

Please sign in to comment.