diff --git a/examples/namespaced/escape-to-host-si-sib.yaml b/examples/namespaced/escape-to-host-si-sib.yaml index 8bd147a2..ce2a38b9 100644 --- a/examples/namespaced/escape-to-host-si-sib.yaml +++ b/examples/namespaced/escape-to-host-si-sib.yaml @@ -23,4 +23,8 @@ spec: kind: Pod namespace: default matchLabels: - app: nginx \ No newline at end of file +<<<<<<< Updated upstream + app: nginx +======= + app: nginx +>>>>>>> Stashed changes diff --git a/pkg/adapter/idpool/idpool.go b/pkg/adapter/idpool/idpool.go index 0edf1864..9f49805c 100644 --- a/pkg/adapter/idpool/idpool.go +++ b/pkg/adapter/idpool/idpool.go @@ -17,11 +17,22 @@ const ( NetPortExec = "netPortExec" SysPathExec = "sysPathExec" EscapeToHost = "escapeToHost" + DisallowChRoot = "disallowChRoot" + DisallowCapabilities = "disallowCapabilities" ) // KaIds are IDs supported by KubeArmor. var KaIds = []string{ - SwDeploymentTools, UnAuthorizedSaTokenAccess, DNSManipulation, + SwDeploymentTools, UnAuthorizedSaTokenAccess, DNSManipulation, EscapeToHost, +} + +// list of policies which satisfies the given ID by Kubearmor +var KaIDPolicies = map[string][]string{ + EscapeToHost: { + DisallowChRoot, + DisallowCapabilities, + SwDeploymentTools, + }, } // NetPolIDs are IDs supported by Network Policy adapter. diff --git a/pkg/adapter/nimbus-kubearmor/Dockerfile b/pkg/adapter/nimbus-kubearmor/Dockerfile index fd207301..31493915 100644 --- a/pkg/adapter/nimbus-kubearmor/Dockerfile +++ b/pkg/adapter/nimbus-kubearmor/Dockerfile @@ -6,19 +6,33 @@ FROM golang:1.22 as builder ARG TARGETOS ARG TARGETARCH -WORKDIR /workspace -# Copy the Go Modules manifests -COPY go.mod go.mod -COPY go.sum go.sum +WORKDIR /nimbus + + +# relative deps requried by the adapter + +ADD api/ api/ +ADD pkg/ pkg/ +ADD go.mod go.mod +ADD go.sum go.sum + +# nimbus-kubearmor directory +ARG ADAPTER_DIR=pkg/adapter/nimbus-kubearmor +WORKDIR /nimbus/$ADAPTER_DIR + +# # Copy Go modules and manifests +COPY $ADAPTER_DIR/go.mod go.mod +COPY $ADAPTER_DIR/go.sum go.sum + # cache deps before building and copying source so that we don't need to re-download as much # and so that source changes don't invalidate our downloaded layer RUN go mod download -# Copy the go source -COPY main.go main.go -COPY manager/ manager/ -COPY processor/ processor/ -COPY watcher/ watcher/ +COPY $ADAPTER_DIR/manager manager +COPY $ADAPTER_DIR/processor processor +COPY $ADAPTER_DIR/watcher watcher +COPY $ADAPTER_DIR/main.go main.go + # Build # the GOARCH has not a default value to allow the binary be built according to the host where the command @@ -29,7 +43,7 @@ RUN CGO_ENABLED=0 GOOS=${TARGETOS:-linux} GOARCH=${TARGETARCH} go build -ldflags FROM gcr.io/distroless/static:nonroot WORKDIR / -COPY --from=builder /workspace/nimbus-kubearmor . +COPY --from=builder /nimbus/pkg/adapter/nimbus-kubearmor . USER 65532:65532 ENTRYPOINT ["/nimbus-kubearmor"] diff --git a/pkg/adapter/nimbus-kubearmor/Makefile b/pkg/adapter/nimbus-kubearmor/Makefile index f504aac8..dcfe1adf 100644 --- a/pkg/adapter/nimbus-kubearmor/Makefile +++ b/pkg/adapter/nimbus-kubearmor/Makefile @@ -17,7 +17,7 @@ run: build .PHONY: docker-build docker-build: - $(CONTAINER_TOOL) build -t ${IMG}:${TAG} -t ${IMG}:latest --build-arg VERSION=${TAG} . + $(CONTAINER_TOOL) build -t ${IMG}:${TAG} -t ${IMG}:latest --build-arg VERSION=${TAG} -f ./Dockerfile ../../../ .PHONY: docker-push docker-push: @@ -31,6 +31,6 @@ docker-buildx: sed -e '1 s/\(^FROM\)/FROM --platform=\$$\{BUILDPLATFORM\}/; t' -e ' 1,// s//FROM --platform=\$$\{BUILDPLATFORM\}/' Dockerfile > Dockerfile.cross - $(CONTAINER_TOOL) buildx create --name project-v3-builder $(CONTAINER_TOOL) buildx use project-v3-builder - - $(CONTAINER_TOOL) buildx build --push --platform=$(PLATFORMS) --build-arg VERSION=${TAG} --tag ${IMG}:${TAG} -f Dockerfile.cross . || { $(CONTAINER_TOOL) buildx rm project-v3-builder; rm Dockerfile.cross; exit 1; } + - $(CONTAINER_TOOL) buildx build --push --platform=$(PLATFORMS) --build-arg VERSION=${TAG} --tag ${IMG}:${TAG} -f Dockerfile.cross ../../../ || { $(CONTAINER_TOOL) buildx rm project-v3-builder; rm Dockerfile.cross; exit 1; } - $(CONTAINER_TOOL) buildx rm project-v3-builder rm Dockerfile.cross diff --git a/pkg/adapter/nimbus-kubearmor/go.mod b/pkg/adapter/nimbus-kubearmor/go.mod index b1e46f73..689d2ebc 100644 --- a/pkg/adapter/nimbus-kubearmor/go.mod +++ b/pkg/adapter/nimbus-kubearmor/go.mod @@ -2,8 +2,10 @@ module github.com/5GSEC/nimbus/pkg/adapter/nimbus-kubearmor go 1.22 + +replace github.com/5GSEC/nimbus => ../../../../nimbus require ( - github.com/5GSEC/nimbus v0.0.0-20240305043055-359d519c1d9f + github.com/5GSEC/nimbus v0.0.0-20240313065715-b91563b0ccd3 github.com/go-logr/logr v1.4.1 github.com/kubearmor/KubeArmor/pkg/KubeArmorController v0.0.0-20240125171707-8e6641511fe3 k8s.io/apimachinery v0.29.1 diff --git a/pkg/adapter/nimbus-kubearmor/go.sum b/pkg/adapter/nimbus-kubearmor/go.sum index 19ed9597..4d78de60 100644 --- a/pkg/adapter/nimbus-kubearmor/go.sum +++ b/pkg/adapter/nimbus-kubearmor/go.sum @@ -1,5 +1,3 @@ -github.com/5GSEC/nimbus v0.0.0-20240305043055-359d519c1d9f h1:FOwBcqhGFm8RXXjgJTdBhjhb3k5UbaDOJ6TpK+5Zmvk= -github.com/5GSEC/nimbus v0.0.0-20240305043055-359d519c1d9f/go.mod h1:FflBHoOu8LpzZJucobgLdGG4j+22A97JX8cXlNY1fXc= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= diff --git a/pkg/adapter/nimbus-kubearmor/processor/kspbuilder.go b/pkg/adapter/nimbus-kubearmor/processor/kspbuilder.go index b4f2bf82..1732ed17 100644 --- a/pkg/adapter/nimbus-kubearmor/processor/kspbuilder.go +++ b/pkg/adapter/nimbus-kubearmor/processor/kspbuilder.go @@ -16,18 +16,33 @@ import ( func BuildKspsFrom(logger logr.Logger, np *v1.NimbusPolicy) []kubearmorv1.KubeArmorPolicy { // Build KSPs based on given IDs var ksps []kubearmorv1.KubeArmorPolicy + var ksp kubearmorv1.KubeArmorPolicy for _, nimbusRule := range np.Spec.NimbusRules { id := nimbusRule.ID if idpool.IsIdSupportedBy(id, "kubearmor") { - ksp := buildKspFor(id) - ksp.Name = np.Name + "-" + strings.ToLower(id) - ksp.Namespace = np.Namespace - ksp.Spec.Message = nimbusRule.Description - ksp.Spec.Selector.MatchLabels = np.Spec.Selector.MatchLabels - ksp.Spec.Action = kubearmorv1.ActionType(nimbusRule.Rule.RuleAction) - processRuleParams(&ksp, nimbusRule.Rule) - addManagedByAnnotation(&ksp) - ksps = append(ksps, ksp) + if _, ok := idpool.KaIDPolicies[id]; ok { + for _, policyName := range idpool.KaIDPolicies[id] { + ksp = buildKspFor(policyName) + ksp.Name = np.Name + "-" + strings.ToLower(id) + "-" + strings.ToLower(policyName) + ksp.Namespace = np.Namespace + ksp.Spec.Message = nimbusRule.Description + ksp.Spec.Selector.MatchLabels = np.Spec.Selector.MatchLabels + ksp.Spec.Action = kubearmorv1.ActionType(nimbusRule.Rule.RuleAction) + processRuleParams(&ksp, nimbusRule.Rule) + addManagedByAnnotation(&ksp) + ksps = append(ksps, ksp) + } + } else { + ksp = buildKspFor(id) + ksp.Name = np.Name + "-" + strings.ToLower(id) + ksp.Namespace = np.Namespace + ksp.Spec.Message = nimbusRule.Description + ksp.Spec.Selector.MatchLabels = np.Spec.Selector.MatchLabels + ksp.Spec.Action = kubearmorv1.ActionType(nimbusRule.Rule.RuleAction) + processRuleParams(&ksp, nimbusRule.Rule) + addManagedByAnnotation(&ksp) + ksps = append(ksps, ksp) + } } else { logger.Info("KubeArmor does not support this ID", "ID", id, "NimbusPolicy", np.Name, "NimbusPolicy.Namespace", np.Namespace) @@ -45,6 +60,10 @@ func buildKspFor(id string) kubearmorv1.KubeArmorPolicy { return unAuthorizedSaTokenAccessKsp() case idpool.DNSManipulation: return dnsManipulationKsp() + case idpool.DisallowChRoot: + return disallowChRoot() + case idpool.DisallowCapabilities: + return disallowCapabilities() default: return kubearmorv1.KubeArmorPolicy{} } @@ -178,12 +197,74 @@ func swDeploymentToolsKsp() kubearmorv1.KubeArmorPolicy { { Path: "/bin/zypper", }, + { + Path: "/usr/bin/curl", + }, + { + Path: "/bin/curl", + }, + { + Path: "/usr/local/bin/curl", + }, + { + Path: "/usr/bin/wget", + }, + { + Path: "/bin/wget", + }, + { + Path: "/usr/local/bin/curl", + }, }, }, }, } } +func disallowCapabilities() kubearmorv1.KubeArmorPolicy { + return kubearmorv1.KubeArmorPolicy{ + Spec: kubearmorv1.KubeArmorPolicySpec{ + Capabilities: kubearmorv1.CapabilitiesType{ + MatchCapabilities: []kubearmorv1.MatchCapabilitiesType{ + { + Capability: "sys_admin", + }, + { + Capability: "sys_ptrace", + }, + { + Capability: "sys_module", + }, + { + Capability: "dac_read_search", + }, + { + Capability: "dac_override", + }, + }, + }, + }, + } +} + +func disallowChRoot() kubearmorv1.KubeArmorPolicy { + return kubearmorv1.KubeArmorPolicy{ + Spec: kubearmorv1.KubeArmorPolicySpec{ + Process: kubearmorv1.ProcessType{ + MatchPaths: []kubearmorv1.ProcessPathType{ + { + Path: "/usr/sbin/chroot", + }, + { + Path: "/sbin/chroot", + }, + }, + }, + }, + } +} + + func addManagedByAnnotation(ksp *kubearmorv1.KubeArmorPolicy) { ksp.Annotations = make(map[string]string) ksp.Annotations["app.kubernetes.io/managed-by"] = "nimbus-kubearmor"