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(*): extended VM support #1448

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion KubeArmor/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ run: build
.PHONY: run-container
run-container: build
cd $(CURDIR); sudo rm -f /tmp/kubearmor.log
cd $(CURDIR); sudo -E ./kubearmor -logPath=/tmp/kubearmor.log -enableKubeArmorHostPolicy -enableKubeArmorPolicy -k8s=false
cd $(CURDIR); DEBUG=true sudo -E ./kubearmor -logPath=/tmp/kubearmor.log -enableKubeArmorHostPolicy -enableKubeArmorPolicy -k8s=false -criSocket=unix:///var/run/docker.sock

.PHONY: run-host-only
run-host-only: build
Expand Down
67 changes: 66 additions & 1 deletion KubeArmor/common/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
"fmt"
"io"
"net"
"net/url"
"os"
"os/exec"
"path/filepath"
Expand All @@ -19,6 +20,9 @@

kc "github.com/kubearmor/KubeArmor/KubeArmor/config"
kg "github.com/kubearmor/KubeArmor/KubeArmor/log"
"golang.org/x/sys/unix"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

Expand Down Expand Up @@ -92,7 +96,7 @@
func ObjCommaExpandFirstDupOthers(objptr interface{}) {
if ObjCommaCanBeExpanded(objptr) {
old := reflect.ValueOf(objptr).Elem()
new := reflect.New(reflect.TypeOf(objptr).Elem()).Elem()

Check warning on line 99 in KubeArmor/common/common.go

View workflow job for this annotation

GitHub Actions / go-lint

redefinition of the built-in function new

for i := 0; i < old.Len(); i++ {
for _, f := range ObjCommaExpand(old.Index(i)) {
Expand Down Expand Up @@ -375,6 +379,9 @@
return false
}

// ContainerRuntimeSocketKeys contains FIFO ordered keys of container runtimes
var ContainerRuntimeSocketKeys = []string{"docker", "containerd", "cri-o"}

// ContainerRuntimeSocketMap Structure
var ContainerRuntimeSocketMap = map[string][]string{
"docker": {
Expand All @@ -396,7 +403,7 @@

// GetCRISocket Function
func GetCRISocket(ContainerRuntime string) string {
for k := range ContainerRuntimeSocketMap {
for _, k := range ContainerRuntimeSocketKeys {
if ContainerRuntime != "" && k != ContainerRuntime {
continue
}
Expand Down Expand Up @@ -456,3 +463,61 @@
}
return nil
}

// ParseURL with/without scheme and return host, port or error
func ParseURL(address string) (string, string, error) {
var host string
port := "80"

addr, err := url.Parse(address)
if err != nil || addr.Host == "" {
// URL without scheme
u, repErr := url.ParseRequestURI("http://" + address)
if repErr != nil {
return "", "", fmt.Errorf("Error while parsing URL: %s", err)
}

addr = u
}

host = addr.Hostname()
if addr.Port() != "" {
port = addr.Port()
}

return host, port, nil
}

// handle gRPC errors

Check warning on line 491 in KubeArmor/common/common.go

View workflow job for this annotation

GitHub Actions / go-lint

comment on exported function HandleGRPCErrors should be of the form "HandleGRPCErrors ..."
func HandleGRPCErrors(err error) error {
if err == nil {
return nil
}

if status, ok := status.FromError(err); ok {
switch status.Code() {
case codes.OK:
// noop
return nil
//case codes.Unavailable, codes.Canceled, codes.DeadlineExceeded:
// return status.Err()
default:
return status.Err()
}
}

return nil
}

// get boot time

Check warning on line 512 in KubeArmor/common/common.go

View workflow job for this annotation

GitHub Actions / go-lint

comment on exported function GetBootTime should be of the form "GetBootTime ..."
// credits: https://github.com/kubernetes/kubernetes/blob/master/pkg/kubelet/util/boottime_util_linux.go
func GetBootTime() string {
currentTime := time.Now()

var info unix.Sysinfo_t
if err := unix.Sysinfo(&info); err != nil {
return ""
}

return currentTime.Add(-time.Duration(info.Uptime) * time.Second).Truncate(time.Second).UTC().String()
}
11 changes: 11 additions & 0 deletions KubeArmor/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ type KubearmorConfig struct {
EnforcerAlerts bool // policy enforcer
DefaultPostureLogs bool // Enable/Disable Default Posture logs for AppArmor LSM

StateAgent bool // enable KubeArmor state agent
}

// GlobalCfg Global configuration for Kubearmor
Expand Down Expand Up @@ -84,6 +85,7 @@ const (
BPFFsPath string = "bpfFsPath"
EnforcerAlerts string = "enforcerAlerts"
ConfigDefaultPostureLogs string = "defaultPostureLogs"
ConfigStateAgent string = "enableKubeArmorStateAgent"
)

func readCmdLineParams() {
Expand Down Expand Up @@ -125,6 +127,8 @@ func readCmdLineParams() {

defaultPostureLogs := flag.Bool(ConfigDefaultPostureLogs, true, "Default Posture Alerts (for Apparmor only)")

stateAgent := flag.Bool(ConfigStateAgent, false, "enabling KubeArmor State Agent client")

flags := []string{}
flag.VisitAll(func(f *flag.Flag) {
kv := fmt.Sprintf("%s:%v", f.Name, f.Value)
Expand Down Expand Up @@ -171,6 +175,8 @@ func readCmdLineParams() {
viper.SetDefault(EnforcerAlerts, *enforcerAlerts)

viper.SetDefault(ConfigDefaultPostureLogs, *defaultPostureLogs)

viper.SetDefault(ConfigStateAgent, *stateAgent)
}

// LoadConfig Load configuration
Expand Down Expand Up @@ -198,6 +204,9 @@ func LoadConfig() error {

GlobalCfg.Cluster = viper.GetString(ConfigCluster)
GlobalCfg.Host = viper.GetString(ConfigHost)
if hostname, err := os.Hostname(); GlobalCfg.Host == "" && err == nil {
GlobalCfg.Host = strings.Split(hostname, ".")[0]
}

GlobalCfg.GRPC = viper.GetString(ConfigGRPC)
GlobalCfg.LogPath = viper.GetString(ConfigLogPath)
Expand Down Expand Up @@ -256,6 +265,8 @@ func LoadConfig() error {

GlobalCfg.DefaultPostureLogs = viper.GetBool(ConfigDefaultPostureLogs)

GlobalCfg.StateAgent = viper.GetBool(ConfigStateAgent)

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

return nil
Expand Down
33 changes: 33 additions & 0 deletions KubeArmor/core/containerdHandler.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,13 @@ import (
"fmt"
"os"
"strconv"
"strings"
"time"

kl "github.com/kubearmor/KubeArmor/KubeArmor/common"
cfg "github.com/kubearmor/KubeArmor/KubeArmor/config"
kg "github.com/kubearmor/KubeArmor/KubeArmor/log"
"github.com/kubearmor/KubeArmor/KubeArmor/state"
tp "github.com/kubearmor/KubeArmor/KubeArmor/types"

pb "github.com/containerd/containerd/api/services/containers/v1"
Expand Down Expand Up @@ -132,6 +134,10 @@ func (ch *ContainerdHandler) GetContainerInfo(ctx context.Context, containerID s
if val, ok := containerLabels["io.kubernetes.pod.name"]; ok {
container.EndPointName = val
}
} else if val, ok := containerLabels["kubearmor.io/namespace"]; ok {
container.NamespaceName = val
} else {
container.NamespaceName = "container_namespace"
}

iface, err := typeurl.UnmarshalAny(res.Container.Spec)
Expand Down Expand Up @@ -169,6 +175,23 @@ func (ch *ContainerdHandler) GetContainerInfo(ctx context.Context, containerID s

// == //

if cfg.GlobalCfg.StateAgent && !cfg.GlobalCfg.K8sEnv {
container.ContainerImage = res.Container.Image //+ kl.GetSHA256ofImage(inspect.Image)

container.NodeName = cfg.GlobalCfg.Host

labels := []string{}
for k, v := range res.Container.Labels {
labels = append(labels, k+"="+v)
}
for k, v := range spec.Annotations {
labels = append(labels, k+"="+v)
}
container.Labels = strings.Join(labels, ",")
}

// == //

return container, nil
}

Expand Down Expand Up @@ -305,6 +328,11 @@ func (dm *KubeArmorDaemon) UpdateContainerdContainer(ctx context.Context, contai
dm.ContainersLock.Unlock()
}

if cfg.GlobalCfg.StateAgent {
container.Status = "running"
go dm.StateAgent.PushContainerEvent(container, state.EventAdded)
}

dm.Logger.Printf("Detected a container (added/%.12s/pidns=%d/mntns=%d)", containerID, container.PidNS, container.MntNS)

} else if action == "destroy" {
Expand Down Expand Up @@ -345,6 +373,11 @@ func (dm *KubeArmorDaemon) UpdateContainerdContainer(ctx context.Context, contai
dm.RuntimeEnforcer.UnregisterContainer(containerID)
}

if cfg.GlobalCfg.StateAgent {
container.Status = "terminated"
go dm.StateAgent.PushContainerEvent(container, state.EventDeleted)
}

dm.Logger.Printf("Detected a container (removed/%.12s/pidns=%d/mntns=%d)", containerID, container.PidNS, container.MntNS)
}

Expand Down
79 changes: 79 additions & 0 deletions KubeArmor/core/dockerHandler.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"os"
"strconv"
"strings"
"time"

"github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/events"
Expand All @@ -18,6 +19,7 @@ import (
kl "github.com/kubearmor/KubeArmor/KubeArmor/common"
cfg "github.com/kubearmor/KubeArmor/KubeArmor/config"
kg "github.com/kubearmor/KubeArmor/KubeArmor/log"
"github.com/kubearmor/KubeArmor/KubeArmor/state"
tp "github.com/kubearmor/KubeArmor/KubeArmor/types"
)

Expand All @@ -37,6 +39,9 @@ type DockerVersion struct {
type DockerHandler struct {
DockerClient *client.Client
Version DockerVersion

// needed for container info
NodeIP string
}

// NewDockerHandler Function
Expand Down Expand Up @@ -65,6 +70,8 @@ func NewDockerHandler() (*DockerHandler, error) {

docker.DockerClient = DockerClient

docker.NodeIP = kl.GetExternalIPAddr()

kg.Printf("Initialized Docker Handler (version: %s)", clientVersion)

return docker, nil
Expand Down Expand Up @@ -112,6 +119,10 @@ func (dh *DockerHandler) GetContainerInfo(containerID string) (tp.Container, err
if val, ok := containerLabels["io.kubernetes.pod.name"]; ok {
container.EndPointName = val
}
} else if val, ok := containerLabels["kubearmor.io/namespace"]; ok {
container.NamespaceName = val
} else {
container.NamespaceName = "container_namespace"
}

container.AppArmorProfile = inspect.AppArmorProfile
Expand All @@ -134,6 +145,48 @@ func (dh *DockerHandler) GetContainerInfo(containerID string) (tp.Container, err

// == //

if cfg.GlobalCfg.StateAgent && !cfg.GlobalCfg.K8sEnv {
container.ContainerImage = inspect.Config.Image //+ kl.GetSHA256ofImage(inspect.Image)

container.NodeName = cfg.GlobalCfg.Host

labels := []string{}
for k, v := range inspect.Config.Labels {
labels = append(labels, k+"="+v)
}

if _, ok := containerLabels["kubearmor.io/container.name"]; !ok {
labels = append(labels, "kubearmor.io/container.name="+container.ContainerName)
}

container.Labels = strings.Join(labels, ",")

var podIP string
if inspect.HostConfig.NetworkMode.IsNone() || inspect.HostConfig.NetworkMode.IsContainer() {
podIP = ""
} else if inspect.HostConfig.NetworkMode.IsHost() {
podIP = dh.NodeIP
} else if inspect.HostConfig.NetworkMode.IsDefault() {
podIP = inspect.NetworkSettings.Networks["bridge"].IPAddress
} else {
networkName := inspect.HostConfig.NetworkMode.NetworkName()
podIP = inspect.NetworkSettings.Networks[networkName].IPAddress
}
DelusionalOptimist marked this conversation as resolved.
Show resolved Hide resolved
container.ContainerIP = podIP

// time format used by docker engine is RFC3339Nano
lastUpdatedAt, err := time.Parse(time.RFC3339Nano, inspect.State.StartedAt)
if err == nil {
container.LastUpdatedAt = lastUpdatedAt.UTC().String()
}
// finished at is IsZero until a container exits
timeFinished, err := time.Parse(time.RFC3339Nano, inspect.State.FinishedAt)
if err == nil && !timeFinished.IsZero() && timeFinished.After(lastUpdatedAt) {
lastUpdatedAt = timeFinished
}

}

return container, nil
}

Expand Down Expand Up @@ -258,6 +311,10 @@ func (dm *KubeArmorDaemon) GetAlreadyDeployedDockerContainers() {
dm.ContainersLock.Unlock()
}

if cfg.GlobalCfg.StateAgent {
go dm.StateAgent.PushContainerEvent(container, state.EventAdded)
}

if dm.SystemMonitor != nil && cfg.GlobalCfg.Policy {
// update NsMap
dm.SystemMonitor.AddContainerIDToNsMap(container.ContainerID, container.NamespaceName, container.PidNS, container.MntNS)
Expand Down Expand Up @@ -358,6 +415,11 @@ func (dm *KubeArmorDaemon) UpdateDockerContainer(containerID, action string) {
dm.ContainersLock.Unlock()
}

if cfg.GlobalCfg.StateAgent {
container.Status = "running"
go dm.StateAgent.PushContainerEvent(container, state.EventAdded)
}

dm.Logger.Printf("Detected a container (added/%.12s)", containerID)

} else if action == "stop" || action == "destroy" {
Expand Down Expand Up @@ -399,13 +461,30 @@ func (dm *KubeArmorDaemon) UpdateDockerContainer(containerID, action string) {
}
dm.EndPointsLock.Unlock()

if cfg.GlobalCfg.StateAgent {
container.Status = "terminated"
go dm.StateAgent.PushContainerEvent(container, state.EventDeleted)
}

if dm.SystemMonitor != nil && cfg.GlobalCfg.Policy {
// update NsMap
dm.SystemMonitor.DeleteContainerIDFromNsMap(containerID, container.NamespaceName, container.PidNS, container.MntNS)
dm.RuntimeEnforcer.UnregisterContainer(containerID)
}

dm.Logger.Printf("Detected a container (removed/%.12s)", containerID)
} else if action == "die" && cfg.GlobalCfg.StateAgent {
// handle die - keep map but update state
dm.ContainersLock.Lock()
container, ok := dm.Containers[containerID]
if !ok {
dm.ContainersLock.Unlock()
return
}
dm.ContainersLock.Unlock()

container.Status = "waiting"
go dm.StateAgent.PushContainerEvent(container, state.EventUpdated)
}
}

Expand Down
Loading
Loading