From b29405fa940d98f12b9e5b3cde2eada9b15007c6 Mon Sep 17 00:00:00 2001 From: Prateek Nandle Date: Fri, 31 May 2024 01:27:00 +0530 Subject: [PATCH] feat:Adding support for KubeArmorClusterPolicy Signed-off-by: Prateek Nandle --- KubeArmor/Makefile | 1 + KubeArmor/core/kubeArmor.go | 10 + KubeArmor/core/kubeUpdate.go | 410 +++++- KubeArmor/types/types.go | 12 + README.md | 1 + SUMMARY.md | 2 + deployments/CRD/KubeArmorClusterPolicy.yaml | 1196 +++++++++++++++++ deployments/get/objects.go | 6 +- .../helm/KubeArmor/templates/RBAC/roles.yaml | 3 + .../helm/KubeArmor/templates/crds/csp.yaml | 1196 +++++++++++++++++ ...erator.kubearmor.com_kubearmorconfigs.yaml | 32 +- .../templates/clusterrole-rbac.yaml | 3 + deployments/main.go | 1 + deployments/operator/operator.yaml | 39 +- .../csp-in-operator-block-file-access.yaml | 25 + .../csp-in-operator-block-process.yaml | 23 + ...csp-not-in-operator-block-file-access.yaml | 25 + .../csp-not-in-operator-block-process.yaml | 23 + .../nginx-csp/nginx-nginx1-deployment.yaml | 27 + .../nginx-csp/nginx-nginx2-deployment.yaml | 27 + .../cluster_security_policy_examples.md | 117 ++ .../cluster_security_policy_specification.md | 311 +++++ pkg/KubeArmorController/Makefile | 3 + .../v1/kubearmorclusterpolicy_types.go | 80 ++ .../v1/zz_generated.deepcopy.go | 142 ++ .../v1/fake/fake_kubearmorclusterpolicy.go | 120 ++ .../fake_security.kubearmor.com_client.go | 4 + .../v1/generated_expansion.go | 2 + .../v1/kubearmorclusterpolicy.go | 171 +++ .../v1/security.kubearmor.com_client.go | 5 + .../informers/externalversions/generic.go | 2 + .../security.kubearmor.com/v1/interface.go | 7 + .../v1/kubearmorclusterpolicy.go | 76 ++ .../v1/expansion_generated.go | 4 + .../v1/kubearmorclusterpolicy.go | 55 + ...ubearmor.com_kubearmorclusterpolicies.yaml | 1196 +++++++++++++++++ .../rbac/kubearmorpolicy_editor_role.yaml | 4 +- .../rbac/kubearmorpolicy_viewer_role.yaml | 4 +- pkg/KubeArmorController/config/rbac/role.yaml | 20 + .../kubearmorclusterpolicy_controller.go | 36 + .../crd/KubeArmorClusterPolicy.yaml | 1196 +++++++++++++++++ pkg/KubeArmorController/crd/crd.go | 12 + pkg/KubeArmorController/main.go | 10 + ...erator.kubearmor.com_kubearmorconfigs.yaml | 33 +- .../config/rbac/clusterrole.yaml | 3 + .../internal/controller/resources.go | 8 + tests/k8s_env/csp/csp_suite_test.go | 16 + tests/k8s_env/csp/csp_test.go | 293 ++++ .../csp-in-operator-block-file-access.yaml | 19 + .../res/csp-in-operator-block-process.yaml | 18 + ...csp-not-in-operator-block-file-access.yaml | 19 + .../csp-not-in-operator-block-process.yaml | 17 + .../res/nginx-later-nginx1-deployment.yaml | 30 + .../csp/res/nginx-nginx1-deployment.yaml | 30 + .../csp/res/nginx-nginx2-deployment.yaml | 30 + tests/util/karmorlog.go | 1 + tests/util/kartutil.go | 39 + 57 files changed, 7067 insertions(+), 128 deletions(-) create mode 100644 deployments/CRD/KubeArmorClusterPolicy.yaml create mode 100644 deployments/helm/KubeArmor/templates/crds/csp.yaml create mode 100644 examples/nginx-csp/cluster-security-policies/csp-in-operator-block-file-access.yaml create mode 100644 examples/nginx-csp/cluster-security-policies/csp-in-operator-block-process.yaml create mode 100644 examples/nginx-csp/cluster-security-policies/csp-not-in-operator-block-file-access.yaml create mode 100644 examples/nginx-csp/cluster-security-policies/csp-not-in-operator-block-process.yaml create mode 100644 examples/nginx-csp/nginx-nginx1-deployment.yaml create mode 100644 examples/nginx-csp/nginx-nginx2-deployment.yaml create mode 100644 getting-started/cluster_security_policy_examples.md create mode 100644 getting-started/cluster_security_policy_specification.md create mode 100644 pkg/KubeArmorController/api/security.kubearmor.com/v1/kubearmorclusterpolicy_types.go create mode 100644 pkg/KubeArmorController/client/clientset/versioned/typed/security.kubearmor.com/v1/fake/fake_kubearmorclusterpolicy.go create mode 100644 pkg/KubeArmorController/client/clientset/versioned/typed/security.kubearmor.com/v1/kubearmorclusterpolicy.go create mode 100644 pkg/KubeArmorController/client/informers/externalversions/security.kubearmor.com/v1/kubearmorclusterpolicy.go create mode 100644 pkg/KubeArmorController/client/listers/security.kubearmor.com/v1/kubearmorclusterpolicy.go create mode 100644 pkg/KubeArmorController/config/crd/bases/security.kubearmor.com_kubearmorclusterpolicies.yaml create mode 100644 pkg/KubeArmorController/controllers/kubearmorclusterpolicy_controller.go create mode 100644 pkg/KubeArmorController/crd/KubeArmorClusterPolicy.yaml create mode 100644 tests/k8s_env/csp/csp_suite_test.go create mode 100644 tests/k8s_env/csp/csp_test.go create mode 100644 tests/k8s_env/csp/res/csp-in-operator-block-file-access.yaml create mode 100644 tests/k8s_env/csp/res/csp-in-operator-block-process.yaml create mode 100644 tests/k8s_env/csp/res/csp-not-in-operator-block-file-access.yaml create mode 100644 tests/k8s_env/csp/res/csp-not-in-operator-block-process.yaml create mode 100644 tests/k8s_env/csp/res/nginx-later-nginx1-deployment.yaml create mode 100644 tests/k8s_env/csp/res/nginx-nginx1-deployment.yaml create mode 100644 tests/k8s_env/csp/res/nginx-nginx2-deployment.yaml diff --git a/KubeArmor/Makefile b/KubeArmor/Makefile index 6f46bc960a..d550ec8ca1 100644 --- a/KubeArmor/Makefile +++ b/KubeArmor/Makefile @@ -46,6 +46,7 @@ build-test: testall .PHONY: run run: build cd $(CRDDIR); kubectl apply -f KubeArmorPolicy.yaml + cd $(CRDDIR); kubectl apply -f KubeArmorClusterPolicy.yaml cd $(CRDDIR); kubectl apply -f KubeArmorHostPolicy.yaml cd $(CURDIR); sudo rm -f /tmp/kubearmor.log cd $(CURDIR)/BPF; make clean diff --git a/KubeArmor/core/kubeArmor.go b/KubeArmor/core/kubeArmor.go index 5537e0869e..261d86a1d2 100644 --- a/KubeArmor/core/kubeArmor.go +++ b/KubeArmor/core/kubeArmor.go @@ -725,6 +725,16 @@ func KubeArmor() { } dm.Logger.Print("Started to monitor security policies") + // watch cluster security policies + clusterSecurityPoliciesSynced := dm.WatchClusterSecurityPolicies() + if clusterSecurityPoliciesSynced == nil { + // destroy the daemon + dm.DestroyKubeArmorDaemon() + + return + } + dm.Logger.Print("Started to monitor cluster security policies") + // watch default posture defaultPostureSynced := dm.WatchDefaultPosture() if defaultPostureSynced == nil { diff --git a/KubeArmor/core/kubeUpdate.go b/KubeArmor/core/kubeUpdate.go index 80b9bf0c98..c05e2122c4 100644 --- a/KubeArmor/core/kubeUpdate.go +++ b/KubeArmor/core/kubeUpdate.go @@ -29,6 +29,11 @@ import ( "k8s.io/client-go/tools/cache" ) +const ( + KubeArmorPolicy string = "KubeArmorPolicy" + KubeArmorClusterPolicy string = "KubeArmorClusterPolicy" +) + // ================= // // == Node Update == // // ================= // @@ -296,7 +301,7 @@ func (dm *KubeArmorDaemon) UpdateEndPointWithPod(action string, pod tp.K8sPod) { dm.DefaultPosturesLock.Unlock() // update security policies with the identities - newPoint.SecurityPolicies = dm.GetSecurityPolicies(newPoint.Identities) + newPoint.SecurityPolicies = dm.GetSecurityPolicies(newPoint.Identities, newPoint.NamespaceName) endpoints := []tp.EndPoint{} for k, v := range pod.Containers { @@ -468,7 +473,7 @@ func (dm *KubeArmorDaemon) UpdateEndPointWithPod(action string, pod tp.K8sPod) { dm.DefaultPosturesLock.Unlock() // get security policies according to the updated identities - newEndPoint.SecurityPolicies = dm.GetSecurityPolicies(newEndPoint.Identities) + newEndPoint.SecurityPolicies = dm.GetSecurityPolicies(newEndPoint.Identities, newEndPoint.NamespaceName) newendpoints := []tp.EndPoint{} for k, v := range pod.Containers { @@ -933,19 +938,61 @@ func (dm *KubeArmorDaemon) WatchK8sPods() { } } +func matchClusterSecurityPolicyRule(policy tp.SecurityPolicy) bool { + hasInOperator := false + excludedNamespaces := make(map[string]bool) + + for _, matchExpression := range policy.Spec.Selector.MatchExpressions { + if matchExpression.Key == "namespace" { + if matchExpression.Operator == "In" { + hasInOperator = true + for _, value := range matchExpression.Values { + if !kl.ContainsElement(policy.Spec.Selector.NamespaceList, value) { + policy.Spec.Selector.NamespaceList = append(policy.Spec.Selector.NamespaceList, value) + return true + } + + } + + } else if matchExpression.Operator == "NotIn" && !hasInOperator { + for _, value := range matchExpression.Values { + excludedNamespaces[value] = true + } + } + } + } + + // this logic will also work when selector is not defined, and policy rule will be applied across all the namespaces + if !hasInOperator { + nsList, err := K8s.K8sClient.CoreV1().Namespaces().List(context.Background(), metav1.ListOptions{}) + if err != nil { + kg.Err("unable to fetch namespace list") + return false + } + + for _, ns := range nsList.Items { + if _, ok := excludedNamespaces[ns.Name]; !ok && !kl.ContainsElement(policy.Spec.Selector.NamespaceList, ns.Name) { + policy.Spec.Selector.NamespaceList = append(policy.Spec.Selector.NamespaceList, ns.Name) + return true + } + } + } + return false +} + // ============================ // // == Security Policy Update == // // ============================ // // GetSecurityPolicies Function -func (dm *KubeArmorDaemon) GetSecurityPolicies(identities []string) []tp.SecurityPolicy { +func (dm *KubeArmorDaemon) GetSecurityPolicies(identities []string, namespaceName string) []tp.SecurityPolicy { dm.SecurityPoliciesLock.Lock() defer dm.SecurityPoliciesLock.Unlock() secPolicies := []tp.SecurityPolicy{} for _, policy := range dm.SecurityPolicies { - if kl.MatchIdentities(policy.Spec.Selector.Identities, identities) { + if kl.MatchIdentities(policy.Spec.Selector.Identities, identities) || kl.ContainsElement(policy.Spec.Selector.NamespaceList, namespaceName) || matchClusterSecurityPolicyRule(policy) { secPolicy := tp.SecurityPolicy{} if err := kl.Clone(policy, &secPolicy); err != nil { dm.Logger.Errf("Failed to clone a policy (%s)", err.Error()) @@ -957,51 +1004,120 @@ func (dm *KubeArmorDaemon) GetSecurityPolicies(identities []string) []tp.Securit return secPolicies } +func containsPolicy(endPointPolicies []tp.SecurityPolicy, secPolicy tp.SecurityPolicy) bool { + for _, policy := range endPointPolicies { + if policy.Metadata["policyName"] == secPolicy.Metadata["policyName"] { + return true + } + } + return false +} + // UpdateSecurityPolicy Function -func (dm *KubeArmorDaemon) UpdateSecurityPolicy(action string, secPolicy tp.SecurityPolicy) { +func (dm *KubeArmorDaemon) UpdateSecurityPolicy(action string, secPolicyType string, secPolicy tp.SecurityPolicy) { dm.EndPointsLock.Lock() defer dm.EndPointsLock.Unlock() for idx, endPoint := range dm.EndPoints { // update a security policy - if kl.MatchIdentities(secPolicy.Spec.Selector.Identities, endPoint.Identities) && (len(secPolicy.Spec.Selector.Containers) == 0 || kl.ContainsElement(secPolicy.Spec.Selector.Containers, endPoint.ContainerName)) { - if action == "ADDED" { - // add a new security policy if it doesn't exist - new := true - for _, policy := range endPoint.SecurityPolicies { - if policy.Metadata["namespaceName"] == secPolicy.Metadata["namespaceName"] && policy.Metadata["policyName"] == secPolicy.Metadata["policyName"] { - new = false - break + if secPolicyType == KubeArmorPolicy { + if kl.MatchIdentities(secPolicy.Spec.Selector.Identities, endPoint.Identities) && (len(secPolicy.Spec.Selector.Containers) == 0 || kl.ContainsElement(secPolicy.Spec.Selector.Containers, endPoint.ContainerName)) { + if action == "ADDED" { + // add a new security policy if it doesn't exist + new := true + for _, policy := range endPoint.SecurityPolicies { + if policy.Metadata["namespaceName"] == secPolicy.Metadata["namespaceName"] && policy.Metadata["policyName"] == secPolicy.Metadata["policyName"] { + new = false + break + } } - } - if new { - dm.EndPoints[idx].SecurityPolicies = append(dm.EndPoints[idx].SecurityPolicies, secPolicy) - } - } else if action == "MODIFIED" { - for idxP, policy := range endPoint.SecurityPolicies { - if policy.Metadata["namespaceName"] == secPolicy.Metadata["namespaceName"] && policy.Metadata["policyName"] == secPolicy.Metadata["policyName"] { - dm.EndPoints[idx].SecurityPolicies[idxP] = secPolicy - break + if new { + dm.EndPoints[idx].SecurityPolicies = append(dm.EndPoints[idx].SecurityPolicies, secPolicy) + } + } else if action == "MODIFIED" { + for idxP, policy := range endPoint.SecurityPolicies { + if policy.Metadata["namespaceName"] == secPolicy.Metadata["namespaceName"] && policy.Metadata["policyName"] == secPolicy.Metadata["policyName"] { + dm.EndPoints[idx].SecurityPolicies[idxP] = secPolicy + break + } + } + } else if action == "DELETED" { + // remove the given policy from the security policy list of this endpoint + for idxP, policy := range endPoint.SecurityPolicies { + if policy.Metadata["namespaceName"] == secPolicy.Metadata["namespaceName"] && policy.Metadata["policyName"] == secPolicy.Metadata["policyName"] { + dm.EndPoints[idx].SecurityPolicies = append(dm.EndPoints[idx].SecurityPolicies[:idxP], dm.EndPoints[idx].SecurityPolicies[idxP+1:]...) + break + } } } - } else if action == "DELETED" { - // remove the given policy from the security policy list of this endpoint - for idxP, policy := range endPoint.SecurityPolicies { - if policy.Metadata["namespaceName"] == secPolicy.Metadata["namespaceName"] && policy.Metadata["policyName"] == secPolicy.Metadata["policyName"] { - dm.EndPoints[idx].SecurityPolicies = append(dm.EndPoints[idx].SecurityPolicies[:idxP], dm.EndPoints[idx].SecurityPolicies[idxP+1:]...) - break + + if cfg.GlobalCfg.Policy { + // update security policies + dm.Logger.UpdateSecurityPolicies("UPDATED", dm.EndPoints[idx]) + + if dm.RuntimeEnforcer != nil { + if dm.EndPoints[idx].PolicyEnabled == tp.KubeArmorPolicyEnabled { + // enforce security policies + dm.RuntimeEnforcer.UpdateSecurityPolicies(dm.EndPoints[idx]) + } } } } + } else if secPolicyType == KubeArmorClusterPolicy { + // additional OR check added with containsPolicy() is when this endPoint's ns is removed from secPolicy.Spec.Selector.MatchExpressions[i].Values + // due to which secPolicy.Spec.Selector.NamespaceList will not have the removed ns + if kl.ContainsElement(secPolicy.Spec.Selector.NamespaceList, endPoint.NamespaceName) || containsPolicy(endPoint.SecurityPolicies, secPolicy) { + if action == "ADDED" { + // add a new security policy if it doesn't exist + new := true + for _, policy := range endPoint.SecurityPolicies { + if policy.Metadata["policyName"] == secPolicy.Metadata["policyName"] { + new = false + break + } + } + if new { + dm.EndPoints[idx].SecurityPolicies = append(dm.EndPoints[idx].SecurityPolicies, secPolicy) + } + } else if action == "MODIFIED" { + // when policy is modified and new ns is added in secPolicy.Spec.Selector.MatchExpressions[i].Values + addNewPolicy := true + + for idxP, policy := range endPoint.SecurityPolicies { + if policy.Metadata["policyName"] == secPolicy.Metadata["policyName"] { + if !kl.ContainsElement(secPolicy.Spec.Selector.NamespaceList, endPoint.NamespaceName) { + // when policy is modified and this endPoint's ns is removed from secPolicy.Spec.Selector.MatchExpressions[i].Values + dm.EndPoints[idx].SecurityPolicies = append(dm.EndPoints[idx].SecurityPolicies[:idxP], dm.EndPoints[idx].SecurityPolicies[idxP+1:]...) + addNewPolicy = false + break + } + dm.EndPoints[idx].SecurityPolicies[idxP] = secPolicy + addNewPolicy = false + break + } + } + if addNewPolicy { + dm.EndPoints[idx].SecurityPolicies = append(dm.EndPoints[idx].SecurityPolicies, secPolicy) + } + } else if action == "DELETED" { + // remove the given policy from the security policy list of this endpoint + for idxP, policy := range endPoint.SecurityPolicies { + if policy.Metadata["policyName"] == secPolicy.Metadata["policyName"] { + dm.EndPoints[idx].SecurityPolicies = append(dm.EndPoints[idx].SecurityPolicies[:idxP], dm.EndPoints[idx].SecurityPolicies[idxP+1:]...) + break + } + } + } - if cfg.GlobalCfg.Policy { - // update security policies - dm.Logger.UpdateSecurityPolicies("UPDATED", dm.EndPoints[idx]) + if cfg.GlobalCfg.Policy { + // update security policies + dm.Logger.UpdateSecurityPolicies("UPDATED", dm.EndPoints[idx]) - if dm.RuntimeEnforcer != nil { - if dm.EndPoints[idx].PolicyEnabled == tp.KubeArmorPolicyEnabled { - // enforce security policies - dm.RuntimeEnforcer.UpdateSecurityPolicies(dm.EndPoints[idx]) + if dm.RuntimeEnforcer != nil { + if dm.EndPoints[idx].PolicyEnabled == tp.KubeArmorPolicyEnabled { + // enforce security policies + dm.RuntimeEnforcer.UpdateSecurityPolicies(dm.EndPoints[idx]) + } } } } @@ -1009,17 +1125,90 @@ func (dm *KubeArmorDaemon) UpdateSecurityPolicy(action string, secPolicy tp.Secu } } -// CreateSecurityPolicy object from a policy CRD -func (dm *KubeArmorDaemon) CreateSecurityPolicy(policy ksp.KubeArmorPolicy) (secPolicy tp.SecurityPolicy, err error) { - secPolicy.Metadata = map[string]string{} - secPolicy.Metadata["namespaceName"] = policy.Namespace - secPolicy.Metadata["policyName"] = policy.Name +// CreateSecurityPolicy - creates `KubeArmorPolicy` & `KubeArmorClusterPolicy` object from crd +func (dm *KubeArmorDaemon) CreateSecurityPolicy(policyType string, securityPolicy interface{}) (secPolicy tp.SecurityPolicy, err error) { + var namespace, name string - if err := kl.Clone(policy.Spec, &secPolicy.Spec); err != nil { - dm.Logger.Errf("Failed to clone a spec (%s)", err.Error()) - return tp.SecurityPolicy{}, err + if policyType == KubeArmorPolicy { + kubearmorPolicy := securityPolicy.(ksp.KubeArmorPolicy) + + namespace = kubearmorPolicy.Namespace + name = kubearmorPolicy.Name + if err := kl.Clone(kubearmorPolicy.Spec, &secPolicy.Spec); err != nil { + dm.Logger.Errf("Failed to clone a spec (%s)", err.Error()) + return tp.SecurityPolicy{}, err + } + + // add identities + secPolicy.Spec.Selector.Identities = []string{"namespaceName=" + namespace} + + for k, v := range secPolicy.Spec.Selector.MatchLabels { + if k == "kubearmor.io/container.name" { + if len(v) > 2 { + containerArray := v[1 : len(v)-1] + containers := strings.Split(containerArray, ",") + for _, container := range containers { + if len(container) > 0 { + secPolicy.Spec.Selector.Containers = append(secPolicy.Spec.Selector.Containers, strings.TrimSpace(container)) + } + + } + } + } else { + secPolicy.Spec.Selector.Identities = append(secPolicy.Spec.Selector.Identities, k+"="+v) + } + } + + sort.Slice(secPolicy.Spec.Selector.Identities, func(i, j int) bool { + return secPolicy.Spec.Selector.Identities[i] < secPolicy.Spec.Selector.Identities[j] + }) + + } else if policyType == KubeArmorClusterPolicy { + kubearmorClusterPolicy := securityPolicy.(ksp.KubeArmorClusterPolicy) + + namespace = kubearmorClusterPolicy.Namespace + name = kubearmorClusterPolicy.Name + if err := kl.Clone(kubearmorClusterPolicy.Spec, &secPolicy.Spec); err != nil { + dm.Logger.Errf("Failed to clone a spec (%s)", err.Error()) + return tp.SecurityPolicy{}, err + } + + hasInOperator := false + excludedNamespaces := make(map[string]bool) + + for _, matchExpression := range secPolicy.Spec.Selector.MatchExpressions { + if matchExpression.Key == "namespace" { + if matchExpression.Operator == "In" { + hasInOperator = true + secPolicy.Spec.Selector.NamespaceList = append(secPolicy.Spec.Selector.NamespaceList, matchExpression.Values...) + } else if matchExpression.Operator == "NotIn" && !hasInOperator { + for _, value := range matchExpression.Values { + excludedNamespaces[value] = true + } + } + } + } + + // this logic will also work when selector is not defined, and policy rule will be applied across all the namespaces + if !hasInOperator { + nsList, err := K8s.K8sClient.CoreV1().Namespaces().List(context.Background(), metav1.ListOptions{}) + if err != nil { + kg.Err("unable to fetch namespace list") + return tp.SecurityPolicy{}, err + } + + for _, ns := range nsList.Items { + if _, ok := excludedNamespaces[ns.Name]; !ok { + secPolicy.Spec.Selector.NamespaceList = append(secPolicy.Spec.Selector.NamespaceList, ns.Name) + } + } + } } + secPolicy.Metadata = map[string]string{} + secPolicy.Metadata["namespaceName"] = namespace + secPolicy.Metadata["policyName"] = name + kl.ObjCommaExpandFirstDupOthers(&secPolicy.Spec.Network.MatchProtocols) kl.ObjCommaExpandFirstDupOthers(&secPolicy.Spec.Capabilities.MatchCapabilities) @@ -1038,31 +1227,6 @@ func (dm *KubeArmorDaemon) CreateSecurityPolicy(policy ksp.KubeArmorPolicy) (sec secPolicy.Spec.Action = "Block" // by default } - // add identities - - secPolicy.Spec.Selector.Identities = []string{"namespaceName=" + policy.Namespace} - - for k, v := range secPolicy.Spec.Selector.MatchLabels { - if k == "kubearmor.io/container.name" { - if len(v) > 2 { - containerArray := v[1 : len(v)-1] - containers := strings.Split(containerArray, ",") - for _, container := range containers { - if len(container) > 0 { - secPolicy.Spec.Selector.Containers = append(secPolicy.Spec.Selector.Containers, strings.TrimSpace(container)) - } - - } - } - } else { - secPolicy.Spec.Selector.Identities = append(secPolicy.Spec.Selector.Identities, k+"="+v) - } - } - - sort.Slice(secPolicy.Spec.Selector.Identities, func(i, j int) bool { - return secPolicy.Spec.Selector.Identities[i] < secPolicy.Spec.Selector.Identities[j] - }) - // add severities, tags, messages, and actions if len(secPolicy.Spec.Process.MatchPaths) > 0 { @@ -1433,7 +1597,7 @@ func (dm *KubeArmorDaemon) WatchSecurityPolicies() cache.InformerSynced { // create a security policy if policy, ok := obj.(*ksp.KubeArmorPolicy); ok { - secPolicy, err := dm.CreateSecurityPolicy(*policy) + secPolicy, err := dm.CreateSecurityPolicy(KubeArmorPolicy, *policy) if err != nil { dm.Logger.Warnf("Error ADD, %s", err) return @@ -1453,13 +1617,13 @@ func (dm *KubeArmorDaemon) WatchSecurityPolicies() cache.InformerSynced { dm.Logger.Printf("Detected a Security Policy (added/%s/%s)", secPolicy.Metadata["namespaceName"], secPolicy.Metadata["policyName"]) // apply security policies to pods - dm.UpdateSecurityPolicy("ADDED", secPolicy) + dm.UpdateSecurityPolicy("ADDED", KubeArmorPolicy, secPolicy) } }, UpdateFunc: func(oldObj, newObj interface{}) { if policy, ok := newObj.(*ksp.KubeArmorPolicy); ok { - secPolicy, err := dm.CreateSecurityPolicy(*policy) + secPolicy, err := dm.CreateSecurityPolicy(KubeArmorPolicy, *policy) if err != nil { return } @@ -1476,12 +1640,12 @@ func (dm *KubeArmorDaemon) WatchSecurityPolicies() cache.InformerSynced { dm.Logger.Printf("Detected a Security Policy (modified/%s/%s)", secPolicy.Metadata["namespaceName"], secPolicy.Metadata["policyName"]) // apply security policies to pods - dm.UpdateSecurityPolicy("MODIFIED", secPolicy) + dm.UpdateSecurityPolicy("MODIFIED", KubeArmorPolicy, secPolicy) } }, DeleteFunc: func(obj interface{}) { if policy, ok := obj.(*ksp.KubeArmorPolicy); ok { - secPolicy, err := dm.CreateSecurityPolicy(*policy) + secPolicy, err := dm.CreateSecurityPolicy(KubeArmorPolicy, *policy) if err != nil { return } @@ -1497,7 +1661,105 @@ func (dm *KubeArmorDaemon) WatchSecurityPolicies() cache.InformerSynced { dm.Logger.Printf("Detected a Security Policy (deleted/%s/%s)", secPolicy.Metadata["namespaceName"], secPolicy.Metadata["policyName"]) // apply security policies to pods - dm.UpdateSecurityPolicy("DELETED", secPolicy) + dm.UpdateSecurityPolicy("DELETED", KubeArmorPolicy, secPolicy) + } + }, + }, + ) + if err != nil { + dm.Logger.Err("Couldn't start watching KubeArmor Security Policies") + return nil + } + + go factory.Start(wait.NeverStop) + return registration.HasSynced +} + +// WatchClusterSecurityPolicies Function +func (dm *KubeArmorDaemon) WatchClusterSecurityPolicies() cache.InformerSynced { + for { + if !K8s.CheckCustomResourceDefinition("kubearmorclusterpolicies") { + time.Sleep(time.Second * 1) + continue + } else { + break + } + } + + factory := kspinformer.NewSharedInformerFactory(K8s.KSPClient, 0) + + informer := factory.Security().V1().KubeArmorClusterPolicies().Informer() + registration, err := informer.AddEventHandler( + cache.ResourceEventHandlerFuncs{ + AddFunc: func(obj interface{}) { + // create a security policy + if policy, ok := obj.(*ksp.KubeArmorClusterPolicy); ok { + + secPolicy, err := dm.CreateSecurityPolicy(KubeArmorClusterPolicy, *policy) + if err != nil { + dm.Logger.Warnf("Error ADD, %s", err) + return + } + dm.SecurityPoliciesLock.Lock() + new := true + for _, policy := range dm.SecurityPolicies { + if policy.Metadata["policyName"] == secPolicy.Metadata["policyName"] { + new = false + break + } + } + if new { + dm.SecurityPolicies = append(dm.SecurityPolicies, secPolicy) + } + dm.SecurityPoliciesLock.Unlock() + dm.Logger.Printf("Detected a Cluster Security Policy (added/%s)", secPolicy.Metadata["policyName"]) + + // apply security policies to pods + dm.UpdateSecurityPolicy("ADDED", KubeArmorClusterPolicy, secPolicy) + + } + }, + UpdateFunc: func(oldObj, newObj interface{}) { + if policy, ok := newObj.(*ksp.KubeArmorClusterPolicy); ok { + secPolicy, err := dm.CreateSecurityPolicy(KubeArmorClusterPolicy, *policy) + if err != nil { + return + } + + dm.SecurityPoliciesLock.Lock() + for idx, policy := range dm.SecurityPolicies { + if policy.Metadata["policyName"] == secPolicy.Metadata["policyName"] { + dm.SecurityPolicies[idx] = secPolicy + break + } + } + dm.SecurityPoliciesLock.Unlock() + + dm.Logger.Printf("Detected a Cluster Security Policy (modified/%s/%s)", secPolicy.Metadata["namespaceName"], secPolicy.Metadata["policyName"]) + + // apply security policies to pods + dm.UpdateSecurityPolicy("MODIFIED", KubeArmorClusterPolicy, secPolicy) + } + }, + DeleteFunc: func(obj interface{}) { + if policy, ok := obj.(*ksp.KubeArmorClusterPolicy); ok { + secPolicy, err := dm.CreateSecurityPolicy(KubeArmorClusterPolicy, *policy) + if err != nil { + return + } + dm.SecurityPoliciesLock.Lock() + for idx, policy := range dm.SecurityPolicies { + if policy.Metadata["policyName"] == secPolicy.Metadata["policyName"] { + dm.SecurityPolicies = append(dm.SecurityPolicies[:idx], dm.SecurityPolicies[idx+1:]...) + break + } + } + dm.SecurityPoliciesLock.Unlock() + + dm.Logger.Printf("Detected a Cluster Security Policy (deleted/%s/%s)", secPolicy.Metadata["namespaceName"], secPolicy.Metadata["policyName"]) + + // apply security policies to pods + dm.UpdateSecurityPolicy("DELETED", KubeArmorClusterPolicy, secPolicy) } }, }, diff --git a/KubeArmor/types/types.go b/KubeArmor/types/types.go index 31767cdcdc..1b6046f18d 100644 --- a/KubeArmor/types/types.go +++ b/KubeArmor/types/types.go @@ -321,11 +321,23 @@ const ( KubeArmorPolicyAudited = 2 ) +// MatchExpressionType Structure +type MatchExpressionType struct { + Key string `json:"key,omitempty"` + Operator string `json:"operator,omitempty"` + Values []string `json:"values,omitempty"` +} + // SelectorType Structure type SelectorType struct { + // for KubeArmorPolicy MatchLabels map[string]string `json:"matchLabels,omitempty"` Containers []string `json:"containers,omitempty"` Identities []string `json:"identities,omitempty"` // set during policy update + + // for KubeArmorClusterPolicy + MatchExpressions []MatchExpressionType `json:"matchExpressions,omitempty"` + NamespaceList []string `json:"namespaceList,omitempty"` // set during policy update } // MatchSourceType Structure diff --git a/README.md b/README.md index 2f08249ec3..4502349e0a 100644 --- a/README.md +++ b/README.md @@ -31,6 +31,7 @@ KubeArmor leverages [Linux security modules \(LSMs\)](https://en.wikipedia.org/w * :heavy_check_mark: [KubeArmor Support Matrix](getting-started/support_matrix.md) * :chess_pawn: [How is KubeArmor different?](getting-started/differentiation.md) * :scroll: Security Policy for Pods/Containers [[Spec](getting-started/security_policy_specification.md)] [[Examples](getting-started/security_policy_examples.md)] +* :scroll: Cluster level security Policy for Pods/Containers [[Spec](getting-started/cluster_security_policy_specification.md)] [[Examples](getting-started/cluster_security_policy_examples.md)] * :scroll: Security Policy for Hosts/Nodes [[Spec](getting-started/host_security_policy_specification.md)] [[Examples](getting-started/host_security_policy_examples.md)]
... [detailed documentation](https://docs.kubearmor.io/kubearmor/) diff --git a/SUMMARY.md b/SUMMARY.md index 2411107b28..4b5981fc08 100644 --- a/SUMMARY.md +++ b/SUMMARY.md @@ -22,6 +22,8 @@ * [Security Posture](getting-started/default_posture.md) * [Policy Spec for Containers](getting-started/security_policy_specification.md) * [Policy Examples for Containers](getting-started/security_policy_examples.md) +* [Cluster Policy Spec for Containers](getting-started/cluster_security_policy_specification.md) +* [Cluster Policy Examples for Containers](getting-started/cluster_security_policy_examples.md) * [Policy Spec for Nodes/VMs](getting-started/host_security_policy_specification.md) * [Policy Examples for Nodes/VMs](getting-started/host_security_policy_examples.md) * [FAQs](getting-started/FAQ.md) diff --git a/deployments/CRD/KubeArmorClusterPolicy.yaml b/deployments/CRD/KubeArmorClusterPolicy.yaml new file mode 100644 index 0000000000..75bfcced26 --- /dev/null +++ b/deployments/CRD/KubeArmorClusterPolicy.yaml @@ -0,0 +1,1196 @@ + +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.4.1 + creationTimestamp: null + name: kubearmorclusterpolicies.security.kubearmor.com +spec: + group: security.kubearmor.com + names: + kind: KubeArmorClusterPolicy + listKind: KubeArmorClusterPolicyList + plural: kubearmorclusterpolicies + shortNames: + - csp + singular: kubearmorclusterpolicy + scope: Cluster + versions: + - additionalPrinterColumns: + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + - jsonPath: .spec.action + name: Action + priority: 10 + type: string + - jsonPath: .spec.selector.matchExpressions + name: Selector + priority: 10 + type: string + name: v1 + schema: + openAPIV3Schema: + description: KubeArmorClusterPolicy is the Schema for the kubearmorclusterpolicies + API + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: KubeArmorClusterPolicySpec defines the desired state of KubeArmorClusterPolicy + properties: + action: + enum: + - Allow + - Audit + - Block + type: string + apparmor: + type: string + capabilities: + properties: + action: + enum: + - Allow + - Audit + - Block + type: string + matchCapabilities: + items: + properties: + action: + enum: + - Allow + - Audit + - Block + type: string + capability: + pattern: (chown|dac_override|dac_read_search|fowner|fsetid|kill|setgid|setuid|setpcap|linux_immutable|net_bind_service|net_broadcast|net_admin|net_raw|ipc_lock|ipc_owner|sys_module|sys_rawio|sys_chroot|sys_ptrace|sys_pacct|sys_admin|sys_boot|sys_nice|sys_resource|sys_time|sys_tty_config|mknod|lease|audit_write|audit_control|setfcap|mac_override|mac_admin)$ + type: string + fromSource: + items: + properties: + path: + pattern: ^\/+.*[^\/]$ + type: string + type: object + type: array + message: + type: string + severity: + maximum: 10 + minimum: 1 + type: integer + tags: + items: + type: string + type: array + required: + - capability + type: object + type: array + message: + type: string + severity: + maximum: 10 + minimum: 1 + type: integer + tags: + items: + type: string + type: array + type: object + file: + properties: + action: + enum: + - Allow + - Audit + - Block + type: string + matchDirectories: + items: + properties: + action: + enum: + - Allow + - Audit + - Block + type: string + dir: + pattern: ^\/$|^\/.*\/$ + type: string + fromSource: + items: + properties: + path: + pattern: ^\/+.*[^\/]$ + type: string + type: object + type: array + message: + type: string + ownerOnly: + type: boolean + readOnly: + type: boolean + recursive: + type: boolean + severity: + maximum: 10 + minimum: 1 + type: integer + tags: + items: + type: string + type: array + required: + - dir + type: object + type: array + matchPaths: + items: + properties: + action: + enum: + - Allow + - Audit + - Block + type: string + fromSource: + items: + properties: + path: + pattern: ^\/+.*[^\/]$ + type: string + type: object + type: array + message: + type: string + ownerOnly: + type: boolean + path: + pattern: ^\/+.*[^\/]$ + type: string + readOnly: + type: boolean + severity: + maximum: 10 + minimum: 1 + type: integer + tags: + items: + type: string + type: array + required: + - path + type: object + type: array + matchPatterns: + items: + properties: + action: + enum: + - Allow + - Audit + - Block + type: string + message: + type: string + ownerOnly: + type: boolean + pattern: + type: string + readOnly: + type: boolean + severity: + maximum: 10 + minimum: 1 + type: integer + tags: + items: + type: string + type: array + required: + - pattern + type: object + type: array + message: + type: string + severity: + maximum: 10 + minimum: 1 + type: integer + tags: + items: + type: string + type: array + type: object + message: + type: string + network: + properties: + action: + enum: + - Allow + - Audit + - Block + type: string + matchProtocols: + items: + properties: + action: + enum: + - Allow + - Audit + - Block + type: string + fromSource: + items: + properties: + path: + pattern: ^\/+.*[^\/]$ + type: string + type: object + type: array + message: + type: string + protocol: + pattern: (icmp|ICMP|tcp|TCP|udp|UDP|raw|RAW)$ + type: string + severity: + maximum: 10 + minimum: 1 + type: integer + tags: + items: + type: string + type: array + required: + - protocol + type: object + type: array + message: + type: string + severity: + maximum: 10 + minimum: 1 + type: integer + tags: + items: + type: string + type: array + type: object + process: + properties: + action: + enum: + - Allow + - Audit + - Block + type: string + matchDirectories: + items: + properties: + action: + enum: + - Allow + - Audit + - Block + type: string + dir: + pattern: ^\/$|^\/.*\/$ + type: string + fromSource: + items: + properties: + path: + pattern: ^\/+.*[^\/]$ + type: string + type: object + type: array + message: + type: string + ownerOnly: + type: boolean + recursive: + type: boolean + severity: + maximum: 10 + minimum: 1 + type: integer + tags: + items: + type: string + type: array + required: + - dir + type: object + type: array + matchPaths: + items: + properties: + action: + enum: + - Allow + - Audit + - Block + type: string + execname: + pattern: ^[^\/]+$ + type: string + fromSource: + items: + properties: + path: + pattern: ^\/+.*[^\/]$ + type: string + type: object + type: array + message: + type: string + ownerOnly: + type: boolean + path: + pattern: ^\/+.*[^\/]$ + type: string + severity: + maximum: 10 + minimum: 1 + type: integer + tags: + items: + type: string + type: array + type: object + type: array + matchPatterns: + items: + properties: + action: + enum: + - Allow + - Audit + - Block + type: string + message: + type: string + ownerOnly: + type: boolean + pattern: + type: string + severity: + maximum: 10 + minimum: 1 + type: integer + tags: + items: + type: string + type: array + required: + - pattern + type: object + type: array + message: + type: string + severity: + maximum: 10 + minimum: 1 + type: integer + tags: + items: + type: string + type: array + type: object + selector: + properties: + matchExpressions: + items: + properties: + key: + enum: + - namespace + type: string + operator: + enum: + - In + - NotIn + type: string + values: + items: + type: string + type: array + type: object + type: array + type: object + severity: + maximum: 10 + minimum: 1 + type: integer + syscalls: + properties: + matchPaths: + items: + properties: + fromSource: + items: + properties: + dir: + type: string + path: + pattern: ^\/+.*[^\/]$ + type: string + recursive: + type: boolean + type: object + type: array + path: + pattern: (^\/+.*[^\/]$)|(^\/$|^\/.*\/$) + type: string + recursive: + type: boolean + syscall: + items: + enum: + - read + - write + - open + - close + - stat + - fstat + - lstat + - poll + - lseek + - mmap + - mprotect + - munmap + - brk + - rt_sigaction + - rt_sigprocmask + - rt_sigreturn + - ioctl + - pread64 + - pwrite64 + - readv + - writev + - access + - pipe + - select + - sched_yield + - mremap + - msync + - mincore + - madvise + - shmget + - shmat + - shmctl + - dup + - dup2 + - pause + - nanosleep + - getitimer + - alarm + - setitimer + - getpid + - sendfile + - socket + - connect + - accept + - sendto + - recvfrom + - sendmsg + - recvmsg + - shutdown + - bind + - listen + - getsockname + - getpeername + - socketpair + - setsockopt + - getsockopt + - clone + - fork + - vfork + - execve + - exit + - wait4 + - kill + - uname + - semget + - semop + - semctl + - shmdt + - msgget + - msgsnd + - msgrcv + - msgctl + - fcntl + - flock + - fsync + - fdatasync + - truncate + - ftruncate + - getdents + - getcwd + - chdir + - fchdir + - rename + - mkdir + - rmdir + - creat + - link + - unlink + - symlink + - readlink + - chmod + - fchmod + - chown + - fchown + - lchown + - umask + - gettimeofday + - getrlimit + - getrusage + - sysinfo + - times + - ptrace + - getuid + - syslog + - getgid + - setuid + - setgid + - geteuid + - getegid + - setpgid + - getppid + - getpgrp + - setsid + - setreuid + - setregid + - getgroups + - setgroups + - setresuid + - getresuid + - setresgid + - getresgid + - getpgid + - setfsuid + - setfsgid + - getsid + - capget + - capset + - rt_sigpending + - rt_sigtimedwait + - rt_sigqueueinfo + - rt_sigsuspend + - sigaltstack + - utime + - mknod + - uselib + - personality + - ustat + - statfs + - fstatfs + - sysfs + - getpriority + - setpriority + - sched_setparam + - sched_getparam + - sched_setscheduler + - sched_getscheduler + - sched_get_priority_max + - sched_get_priority_min + - sched_rr_get_interval + - mlock + - munlock + - mlockall + - munlockall + - vhangup + - modify_ldt + - pivot_root + - _sysctl + - prctl + - arch_prctl + - adjtimex + - setrlimit + - chroot + - sync + - acct + - settimeofday + - mount + - umount2 + - swapon + - swapoff + - reboot + - sethostname + - setdomainname + - iopl + - ioperm + - create_module + - init_module + - delete_module + - get_kernel_syms + - query_module + - quotactl + - nfsservctl + - getpmsg + - putpmsg + - afs_syscall + - tuxcall + - security + - gettid + - readahead + - setxattr + - lsetxattr + - fsetxattr + - getxattr + - lgetxattr + - fgetxattr + - listxattr + - llistxattr + - flistxattr + - removexattr + - lremovexattr + - fremovexattr + - tkill + - time + - futex + - sched_setaffinity + - sched_getaffinity + - set_thread_area + - io_setup + - io_destroy + - io_getevents + - io_submit + - io_cancel + - get_thread_area + - lookup_dcookie + - epoll_create + - epoll_ctl_old + - epoll_wait_old + - remap_file_pages + - getdents64 + - set_tid_address + - restart_syscall + - semtimedop + - fadvise64 + - timer_create + - timer_settime + - timer_gettime + - timer_getoverrun + - timer_delete + - clock_settime + - clock_gettime + - clock_getres + - clock_nanosleep + - exit_group + - epoll_wait + - epoll_ctl + - tgkill + - utimes + - vserver + - mbind + - set_mempolicy + - get_mempolicy + - mq_open + - mq_unlink + - mq_timedsend + - mq_timedreceive + - mq_notify + - mq_getsetattr + - kexec_load + - waitid + - add_key + - request_key + - keyctl + - ioprio_set + - ioprio_get + - inotify_init + - inotify_add_watch + - inotify_rm_watch + - migrate_pages + - openat + - mkdirat + - mknodat + - fchownat + - futimesat + - newfstatat + - unlinkat + - renameat + - linkat + - symlinkat + - readlinkat + - fchmodat + - faccessat + - pselect6 + - ppoll + - unshare + - set_robust_list + - get_robust_list + - splice + - tee + - sync_file_range + - vmsplice + - move_pages + - utimensat + - epoll_pwait + - signalfd + - timerfd_create + - eventfd + - fallocate + - timerfd_settime + - timerfd_gettime + - accept4 + - signalfd4 + - eventfd2 + - epoll_create1 + - dup3 + - pipe2 + - inotify_init1 + - preadv + - pwritev + - rt_tgsigqueueinfo + - perf_event_open + - recvmmsg + - fanotify_init + - fanotify_mark + - prlimit64 + - name_to_handle_at + - open_by_handle_at + - clock_adjtime + - syncfs + - sendmmsg + - setns + - getcpu + - process_vm_readv + - process_vm_writev + - kcmp + - finit_module + - sched_setattr + - sched_getattr + - renameat2 + - seccomp + - getrandom + - memfd_create + - kexec_file_load + - bpf + - execveat + - userfaultfd + - membarrier + - mlock2 + - copy_file_range + - preadv2 + - pwritev2 + - pkey_mprotect + - pkey_alloc + - pkey_free + - statx + - io_pgetevents + - rseq + type: string + type: array + type: object + type: array + matchSyscalls: + items: + properties: + fromSource: + items: + properties: + dir: + type: string + path: + pattern: ^\/+.*[^\/]$ + type: string + recursive: + type: boolean + type: object + type: array + syscall: + items: + enum: + - read + - write + - open + - close + - stat + - fstat + - lstat + - poll + - lseek + - mmap + - mprotect + - munmap + - brk + - rt_sigaction + - rt_sigprocmask + - rt_sigreturn + - ioctl + - pread64 + - pwrite64 + - readv + - writev + - access + - pipe + - select + - sched_yield + - mremap + - msync + - mincore + - madvise + - shmget + - shmat + - shmctl + - dup + - dup2 + - pause + - nanosleep + - getitimer + - alarm + - setitimer + - getpid + - sendfile + - socket + - connect + - accept + - sendto + - recvfrom + - sendmsg + - recvmsg + - shutdown + - bind + - listen + - getsockname + - getpeername + - socketpair + - setsockopt + - getsockopt + - clone + - fork + - vfork + - execve + - exit + - wait4 + - kill + - uname + - semget + - semop + - semctl + - shmdt + - msgget + - msgsnd + - msgrcv + - msgctl + - fcntl + - flock + - fsync + - fdatasync + - truncate + - ftruncate + - getdents + - getcwd + - chdir + - fchdir + - rename + - mkdir + - rmdir + - creat + - link + - unlink + - symlink + - readlink + - chmod + - fchmod + - chown + - fchown + - lchown + - umask + - gettimeofday + - getrlimit + - getrusage + - sysinfo + - times + - ptrace + - getuid + - syslog + - getgid + - setuid + - setgid + - geteuid + - getegid + - setpgid + - getppid + - getpgrp + - setsid + - setreuid + - setregid + - getgroups + - setgroups + - setresuid + - getresuid + - setresgid + - getresgid + - getpgid + - setfsuid + - setfsgid + - getsid + - capget + - capset + - rt_sigpending + - rt_sigtimedwait + - rt_sigqueueinfo + - rt_sigsuspend + - sigaltstack + - utime + - mknod + - uselib + - personality + - ustat + - statfs + - fstatfs + - sysfs + - getpriority + - setpriority + - sched_setparam + - sched_getparam + - sched_setscheduler + - sched_getscheduler + - sched_get_priority_max + - sched_get_priority_min + - sched_rr_get_interval + - mlock + - munlock + - mlockall + - munlockall + - vhangup + - modify_ldt + - pivot_root + - _sysctl + - prctl + - arch_prctl + - adjtimex + - setrlimit + - chroot + - sync + - acct + - settimeofday + - mount + - umount2 + - swapon + - swapoff + - reboot + - sethostname + - setdomainname + - iopl + - ioperm + - create_module + - init_module + - delete_module + - get_kernel_syms + - query_module + - quotactl + - nfsservctl + - getpmsg + - putpmsg + - afs_syscall + - tuxcall + - security + - gettid + - readahead + - setxattr + - lsetxattr + - fsetxattr + - getxattr + - lgetxattr + - fgetxattr + - listxattr + - llistxattr + - flistxattr + - removexattr + - lremovexattr + - fremovexattr + - tkill + - time + - futex + - sched_setaffinity + - sched_getaffinity + - set_thread_area + - io_setup + - io_destroy + - io_getevents + - io_submit + - io_cancel + - get_thread_area + - lookup_dcookie + - epoll_create + - epoll_ctl_old + - epoll_wait_old + - remap_file_pages + - getdents64 + - set_tid_address + - restart_syscall + - semtimedop + - fadvise64 + - timer_create + - timer_settime + - timer_gettime + - timer_getoverrun + - timer_delete + - clock_settime + - clock_gettime + - clock_getres + - clock_nanosleep + - exit_group + - epoll_wait + - epoll_ctl + - tgkill + - utimes + - vserver + - mbind + - set_mempolicy + - get_mempolicy + - mq_open + - mq_unlink + - mq_timedsend + - mq_timedreceive + - mq_notify + - mq_getsetattr + - kexec_load + - waitid + - add_key + - request_key + - keyctl + - ioprio_set + - ioprio_get + - inotify_init + - inotify_add_watch + - inotify_rm_watch + - migrate_pages + - openat + - mkdirat + - mknodat + - fchownat + - futimesat + - newfstatat + - unlinkat + - renameat + - linkat + - symlinkat + - readlinkat + - fchmodat + - faccessat + - pselect6 + - ppoll + - unshare + - set_robust_list + - get_robust_list + - splice + - tee + - sync_file_range + - vmsplice + - move_pages + - utimensat + - epoll_pwait + - signalfd + - timerfd_create + - eventfd + - fallocate + - timerfd_settime + - timerfd_gettime + - accept4 + - signalfd4 + - eventfd2 + - epoll_create1 + - dup3 + - pipe2 + - inotify_init1 + - preadv + - pwritev + - rt_tgsigqueueinfo + - perf_event_open + - recvmmsg + - fanotify_init + - fanotify_mark + - prlimit64 + - name_to_handle_at + - open_by_handle_at + - clock_adjtime + - syncfs + - sendmmsg + - setns + - getcpu + - process_vm_readv + - process_vm_writev + - kcmp + - finit_module + - sched_setattr + - sched_getattr + - renameat2 + - seccomp + - getrandom + - memfd_create + - kexec_file_load + - bpf + - execveat + - userfaultfd + - membarrier + - mlock2 + - copy_file_range + - preadv2 + - pwritev2 + - pkey_mprotect + - pkey_alloc + - pkey_free + - statx + - io_pgetevents + - rseq + type: string + type: array + type: object + type: array + message: + type: string + severity: + maximum: 10 + minimum: 1 + type: integer + tags: + items: + type: string + type: array + type: object + tags: + items: + type: string + type: array + type: object + status: + description: KubeArmorClusterPolicyStatus defines the observed state of + KubeArmorCLusterPolicy + properties: + status: + type: string + type: object + type: object + served: true + storage: true + subresources: + status: {} +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] diff --git a/deployments/get/objects.go b/deployments/get/objects.go index 6ead7f5d63..24cef66797 100644 --- a/deployments/get/objects.go +++ b/deployments/get/objects.go @@ -58,7 +58,7 @@ func GetClusterRole() *rbacv1.ClusterRole { }, { APIGroups: []string{"security.kubearmor.com"}, - Resources: []string{"kubearmorpolicies", "kubearmorhostpolicies"}, + Resources: []string{"kubearmorpolicies", "kubearmorclusterpolicies", "kubearmorhostpolicies"}, Verbs: []string{"get", "list", "watch", "update", "delete"}, }, { @@ -676,12 +676,12 @@ func GetKubeArmorControllerClusterRole() *rbacv1.ClusterRole { }, { APIGroups: []string{"security.kubearmor.com"}, - Resources: []string{"kubearmorpolicies", "kubearmorhostpolicies"}, + Resources: []string{"kubearmorpolicies", "kubearmorclusterpolicies", "kubearmorhostpolicies"}, Verbs: []string{"create", "delete", "get", "patch", "list", "watch", "update"}, }, { APIGroups: []string{"security.kubearmor.com"}, - Resources: []string{"kubearmorpolicies/status", "kubearmorhostpolicies/status"}, + Resources: []string{"kubearmorpolicies/status", "kubearmorclusterpolicies/status", "kubearmorhostpolicies/status"}, Verbs: []string{"get", "patch", "update"}, }, }, diff --git a/deployments/helm/KubeArmor/templates/RBAC/roles.yaml b/deployments/helm/KubeArmor/templates/RBAC/roles.yaml index 96ceac7b4e..ff219b5636 100644 --- a/deployments/helm/KubeArmor/templates/RBAC/roles.yaml +++ b/deployments/helm/KubeArmor/templates/RBAC/roles.yaml @@ -44,6 +44,7 @@ rules: - security.kubearmor.com resources: - kubearmorpolicies + - kubearmorclusterpolicies - kubearmorhostpolicies verbs: - get @@ -91,6 +92,7 @@ rules: - security.kubearmor.com resources: - kubearmorpolicies + - kubearmorclusterpolicies - kubearmorhostpolicies verbs: - create @@ -104,6 +106,7 @@ rules: - security.kubearmor.com resources: - kubearmorpolicies/status + - kubearmorclusterpolicies/status - kubearmorhostpolicies/status verbs: - get diff --git a/deployments/helm/KubeArmor/templates/crds/csp.yaml b/deployments/helm/KubeArmor/templates/crds/csp.yaml new file mode 100644 index 0000000000..75bfcced26 --- /dev/null +++ b/deployments/helm/KubeArmor/templates/crds/csp.yaml @@ -0,0 +1,1196 @@ + +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.4.1 + creationTimestamp: null + name: kubearmorclusterpolicies.security.kubearmor.com +spec: + group: security.kubearmor.com + names: + kind: KubeArmorClusterPolicy + listKind: KubeArmorClusterPolicyList + plural: kubearmorclusterpolicies + shortNames: + - csp + singular: kubearmorclusterpolicy + scope: Cluster + versions: + - additionalPrinterColumns: + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + - jsonPath: .spec.action + name: Action + priority: 10 + type: string + - jsonPath: .spec.selector.matchExpressions + name: Selector + priority: 10 + type: string + name: v1 + schema: + openAPIV3Schema: + description: KubeArmorClusterPolicy is the Schema for the kubearmorclusterpolicies + API + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: KubeArmorClusterPolicySpec defines the desired state of KubeArmorClusterPolicy + properties: + action: + enum: + - Allow + - Audit + - Block + type: string + apparmor: + type: string + capabilities: + properties: + action: + enum: + - Allow + - Audit + - Block + type: string + matchCapabilities: + items: + properties: + action: + enum: + - Allow + - Audit + - Block + type: string + capability: + pattern: (chown|dac_override|dac_read_search|fowner|fsetid|kill|setgid|setuid|setpcap|linux_immutable|net_bind_service|net_broadcast|net_admin|net_raw|ipc_lock|ipc_owner|sys_module|sys_rawio|sys_chroot|sys_ptrace|sys_pacct|sys_admin|sys_boot|sys_nice|sys_resource|sys_time|sys_tty_config|mknod|lease|audit_write|audit_control|setfcap|mac_override|mac_admin)$ + type: string + fromSource: + items: + properties: + path: + pattern: ^\/+.*[^\/]$ + type: string + type: object + type: array + message: + type: string + severity: + maximum: 10 + minimum: 1 + type: integer + tags: + items: + type: string + type: array + required: + - capability + type: object + type: array + message: + type: string + severity: + maximum: 10 + minimum: 1 + type: integer + tags: + items: + type: string + type: array + type: object + file: + properties: + action: + enum: + - Allow + - Audit + - Block + type: string + matchDirectories: + items: + properties: + action: + enum: + - Allow + - Audit + - Block + type: string + dir: + pattern: ^\/$|^\/.*\/$ + type: string + fromSource: + items: + properties: + path: + pattern: ^\/+.*[^\/]$ + type: string + type: object + type: array + message: + type: string + ownerOnly: + type: boolean + readOnly: + type: boolean + recursive: + type: boolean + severity: + maximum: 10 + minimum: 1 + type: integer + tags: + items: + type: string + type: array + required: + - dir + type: object + type: array + matchPaths: + items: + properties: + action: + enum: + - Allow + - Audit + - Block + type: string + fromSource: + items: + properties: + path: + pattern: ^\/+.*[^\/]$ + type: string + type: object + type: array + message: + type: string + ownerOnly: + type: boolean + path: + pattern: ^\/+.*[^\/]$ + type: string + readOnly: + type: boolean + severity: + maximum: 10 + minimum: 1 + type: integer + tags: + items: + type: string + type: array + required: + - path + type: object + type: array + matchPatterns: + items: + properties: + action: + enum: + - Allow + - Audit + - Block + type: string + message: + type: string + ownerOnly: + type: boolean + pattern: + type: string + readOnly: + type: boolean + severity: + maximum: 10 + minimum: 1 + type: integer + tags: + items: + type: string + type: array + required: + - pattern + type: object + type: array + message: + type: string + severity: + maximum: 10 + minimum: 1 + type: integer + tags: + items: + type: string + type: array + type: object + message: + type: string + network: + properties: + action: + enum: + - Allow + - Audit + - Block + type: string + matchProtocols: + items: + properties: + action: + enum: + - Allow + - Audit + - Block + type: string + fromSource: + items: + properties: + path: + pattern: ^\/+.*[^\/]$ + type: string + type: object + type: array + message: + type: string + protocol: + pattern: (icmp|ICMP|tcp|TCP|udp|UDP|raw|RAW)$ + type: string + severity: + maximum: 10 + minimum: 1 + type: integer + tags: + items: + type: string + type: array + required: + - protocol + type: object + type: array + message: + type: string + severity: + maximum: 10 + minimum: 1 + type: integer + tags: + items: + type: string + type: array + type: object + process: + properties: + action: + enum: + - Allow + - Audit + - Block + type: string + matchDirectories: + items: + properties: + action: + enum: + - Allow + - Audit + - Block + type: string + dir: + pattern: ^\/$|^\/.*\/$ + type: string + fromSource: + items: + properties: + path: + pattern: ^\/+.*[^\/]$ + type: string + type: object + type: array + message: + type: string + ownerOnly: + type: boolean + recursive: + type: boolean + severity: + maximum: 10 + minimum: 1 + type: integer + tags: + items: + type: string + type: array + required: + - dir + type: object + type: array + matchPaths: + items: + properties: + action: + enum: + - Allow + - Audit + - Block + type: string + execname: + pattern: ^[^\/]+$ + type: string + fromSource: + items: + properties: + path: + pattern: ^\/+.*[^\/]$ + type: string + type: object + type: array + message: + type: string + ownerOnly: + type: boolean + path: + pattern: ^\/+.*[^\/]$ + type: string + severity: + maximum: 10 + minimum: 1 + type: integer + tags: + items: + type: string + type: array + type: object + type: array + matchPatterns: + items: + properties: + action: + enum: + - Allow + - Audit + - Block + type: string + message: + type: string + ownerOnly: + type: boolean + pattern: + type: string + severity: + maximum: 10 + minimum: 1 + type: integer + tags: + items: + type: string + type: array + required: + - pattern + type: object + type: array + message: + type: string + severity: + maximum: 10 + minimum: 1 + type: integer + tags: + items: + type: string + type: array + type: object + selector: + properties: + matchExpressions: + items: + properties: + key: + enum: + - namespace + type: string + operator: + enum: + - In + - NotIn + type: string + values: + items: + type: string + type: array + type: object + type: array + type: object + severity: + maximum: 10 + minimum: 1 + type: integer + syscalls: + properties: + matchPaths: + items: + properties: + fromSource: + items: + properties: + dir: + type: string + path: + pattern: ^\/+.*[^\/]$ + type: string + recursive: + type: boolean + type: object + type: array + path: + pattern: (^\/+.*[^\/]$)|(^\/$|^\/.*\/$) + type: string + recursive: + type: boolean + syscall: + items: + enum: + - read + - write + - open + - close + - stat + - fstat + - lstat + - poll + - lseek + - mmap + - mprotect + - munmap + - brk + - rt_sigaction + - rt_sigprocmask + - rt_sigreturn + - ioctl + - pread64 + - pwrite64 + - readv + - writev + - access + - pipe + - select + - sched_yield + - mremap + - msync + - mincore + - madvise + - shmget + - shmat + - shmctl + - dup + - dup2 + - pause + - nanosleep + - getitimer + - alarm + - setitimer + - getpid + - sendfile + - socket + - connect + - accept + - sendto + - recvfrom + - sendmsg + - recvmsg + - shutdown + - bind + - listen + - getsockname + - getpeername + - socketpair + - setsockopt + - getsockopt + - clone + - fork + - vfork + - execve + - exit + - wait4 + - kill + - uname + - semget + - semop + - semctl + - shmdt + - msgget + - msgsnd + - msgrcv + - msgctl + - fcntl + - flock + - fsync + - fdatasync + - truncate + - ftruncate + - getdents + - getcwd + - chdir + - fchdir + - rename + - mkdir + - rmdir + - creat + - link + - unlink + - symlink + - readlink + - chmod + - fchmod + - chown + - fchown + - lchown + - umask + - gettimeofday + - getrlimit + - getrusage + - sysinfo + - times + - ptrace + - getuid + - syslog + - getgid + - setuid + - setgid + - geteuid + - getegid + - setpgid + - getppid + - getpgrp + - setsid + - setreuid + - setregid + - getgroups + - setgroups + - setresuid + - getresuid + - setresgid + - getresgid + - getpgid + - setfsuid + - setfsgid + - getsid + - capget + - capset + - rt_sigpending + - rt_sigtimedwait + - rt_sigqueueinfo + - rt_sigsuspend + - sigaltstack + - utime + - mknod + - uselib + - personality + - ustat + - statfs + - fstatfs + - sysfs + - getpriority + - setpriority + - sched_setparam + - sched_getparam + - sched_setscheduler + - sched_getscheduler + - sched_get_priority_max + - sched_get_priority_min + - sched_rr_get_interval + - mlock + - munlock + - mlockall + - munlockall + - vhangup + - modify_ldt + - pivot_root + - _sysctl + - prctl + - arch_prctl + - adjtimex + - setrlimit + - chroot + - sync + - acct + - settimeofday + - mount + - umount2 + - swapon + - swapoff + - reboot + - sethostname + - setdomainname + - iopl + - ioperm + - create_module + - init_module + - delete_module + - get_kernel_syms + - query_module + - quotactl + - nfsservctl + - getpmsg + - putpmsg + - afs_syscall + - tuxcall + - security + - gettid + - readahead + - setxattr + - lsetxattr + - fsetxattr + - getxattr + - lgetxattr + - fgetxattr + - listxattr + - llistxattr + - flistxattr + - removexattr + - lremovexattr + - fremovexattr + - tkill + - time + - futex + - sched_setaffinity + - sched_getaffinity + - set_thread_area + - io_setup + - io_destroy + - io_getevents + - io_submit + - io_cancel + - get_thread_area + - lookup_dcookie + - epoll_create + - epoll_ctl_old + - epoll_wait_old + - remap_file_pages + - getdents64 + - set_tid_address + - restart_syscall + - semtimedop + - fadvise64 + - timer_create + - timer_settime + - timer_gettime + - timer_getoverrun + - timer_delete + - clock_settime + - clock_gettime + - clock_getres + - clock_nanosleep + - exit_group + - epoll_wait + - epoll_ctl + - tgkill + - utimes + - vserver + - mbind + - set_mempolicy + - get_mempolicy + - mq_open + - mq_unlink + - mq_timedsend + - mq_timedreceive + - mq_notify + - mq_getsetattr + - kexec_load + - waitid + - add_key + - request_key + - keyctl + - ioprio_set + - ioprio_get + - inotify_init + - inotify_add_watch + - inotify_rm_watch + - migrate_pages + - openat + - mkdirat + - mknodat + - fchownat + - futimesat + - newfstatat + - unlinkat + - renameat + - linkat + - symlinkat + - readlinkat + - fchmodat + - faccessat + - pselect6 + - ppoll + - unshare + - set_robust_list + - get_robust_list + - splice + - tee + - sync_file_range + - vmsplice + - move_pages + - utimensat + - epoll_pwait + - signalfd + - timerfd_create + - eventfd + - fallocate + - timerfd_settime + - timerfd_gettime + - accept4 + - signalfd4 + - eventfd2 + - epoll_create1 + - dup3 + - pipe2 + - inotify_init1 + - preadv + - pwritev + - rt_tgsigqueueinfo + - perf_event_open + - recvmmsg + - fanotify_init + - fanotify_mark + - prlimit64 + - name_to_handle_at + - open_by_handle_at + - clock_adjtime + - syncfs + - sendmmsg + - setns + - getcpu + - process_vm_readv + - process_vm_writev + - kcmp + - finit_module + - sched_setattr + - sched_getattr + - renameat2 + - seccomp + - getrandom + - memfd_create + - kexec_file_load + - bpf + - execveat + - userfaultfd + - membarrier + - mlock2 + - copy_file_range + - preadv2 + - pwritev2 + - pkey_mprotect + - pkey_alloc + - pkey_free + - statx + - io_pgetevents + - rseq + type: string + type: array + type: object + type: array + matchSyscalls: + items: + properties: + fromSource: + items: + properties: + dir: + type: string + path: + pattern: ^\/+.*[^\/]$ + type: string + recursive: + type: boolean + type: object + type: array + syscall: + items: + enum: + - read + - write + - open + - close + - stat + - fstat + - lstat + - poll + - lseek + - mmap + - mprotect + - munmap + - brk + - rt_sigaction + - rt_sigprocmask + - rt_sigreturn + - ioctl + - pread64 + - pwrite64 + - readv + - writev + - access + - pipe + - select + - sched_yield + - mremap + - msync + - mincore + - madvise + - shmget + - shmat + - shmctl + - dup + - dup2 + - pause + - nanosleep + - getitimer + - alarm + - setitimer + - getpid + - sendfile + - socket + - connect + - accept + - sendto + - recvfrom + - sendmsg + - recvmsg + - shutdown + - bind + - listen + - getsockname + - getpeername + - socketpair + - setsockopt + - getsockopt + - clone + - fork + - vfork + - execve + - exit + - wait4 + - kill + - uname + - semget + - semop + - semctl + - shmdt + - msgget + - msgsnd + - msgrcv + - msgctl + - fcntl + - flock + - fsync + - fdatasync + - truncate + - ftruncate + - getdents + - getcwd + - chdir + - fchdir + - rename + - mkdir + - rmdir + - creat + - link + - unlink + - symlink + - readlink + - chmod + - fchmod + - chown + - fchown + - lchown + - umask + - gettimeofday + - getrlimit + - getrusage + - sysinfo + - times + - ptrace + - getuid + - syslog + - getgid + - setuid + - setgid + - geteuid + - getegid + - setpgid + - getppid + - getpgrp + - setsid + - setreuid + - setregid + - getgroups + - setgroups + - setresuid + - getresuid + - setresgid + - getresgid + - getpgid + - setfsuid + - setfsgid + - getsid + - capget + - capset + - rt_sigpending + - rt_sigtimedwait + - rt_sigqueueinfo + - rt_sigsuspend + - sigaltstack + - utime + - mknod + - uselib + - personality + - ustat + - statfs + - fstatfs + - sysfs + - getpriority + - setpriority + - sched_setparam + - sched_getparam + - sched_setscheduler + - sched_getscheduler + - sched_get_priority_max + - sched_get_priority_min + - sched_rr_get_interval + - mlock + - munlock + - mlockall + - munlockall + - vhangup + - modify_ldt + - pivot_root + - _sysctl + - prctl + - arch_prctl + - adjtimex + - setrlimit + - chroot + - sync + - acct + - settimeofday + - mount + - umount2 + - swapon + - swapoff + - reboot + - sethostname + - setdomainname + - iopl + - ioperm + - create_module + - init_module + - delete_module + - get_kernel_syms + - query_module + - quotactl + - nfsservctl + - getpmsg + - putpmsg + - afs_syscall + - tuxcall + - security + - gettid + - readahead + - setxattr + - lsetxattr + - fsetxattr + - getxattr + - lgetxattr + - fgetxattr + - listxattr + - llistxattr + - flistxattr + - removexattr + - lremovexattr + - fremovexattr + - tkill + - time + - futex + - sched_setaffinity + - sched_getaffinity + - set_thread_area + - io_setup + - io_destroy + - io_getevents + - io_submit + - io_cancel + - get_thread_area + - lookup_dcookie + - epoll_create + - epoll_ctl_old + - epoll_wait_old + - remap_file_pages + - getdents64 + - set_tid_address + - restart_syscall + - semtimedop + - fadvise64 + - timer_create + - timer_settime + - timer_gettime + - timer_getoverrun + - timer_delete + - clock_settime + - clock_gettime + - clock_getres + - clock_nanosleep + - exit_group + - epoll_wait + - epoll_ctl + - tgkill + - utimes + - vserver + - mbind + - set_mempolicy + - get_mempolicy + - mq_open + - mq_unlink + - mq_timedsend + - mq_timedreceive + - mq_notify + - mq_getsetattr + - kexec_load + - waitid + - add_key + - request_key + - keyctl + - ioprio_set + - ioprio_get + - inotify_init + - inotify_add_watch + - inotify_rm_watch + - migrate_pages + - openat + - mkdirat + - mknodat + - fchownat + - futimesat + - newfstatat + - unlinkat + - renameat + - linkat + - symlinkat + - readlinkat + - fchmodat + - faccessat + - pselect6 + - ppoll + - unshare + - set_robust_list + - get_robust_list + - splice + - tee + - sync_file_range + - vmsplice + - move_pages + - utimensat + - epoll_pwait + - signalfd + - timerfd_create + - eventfd + - fallocate + - timerfd_settime + - timerfd_gettime + - accept4 + - signalfd4 + - eventfd2 + - epoll_create1 + - dup3 + - pipe2 + - inotify_init1 + - preadv + - pwritev + - rt_tgsigqueueinfo + - perf_event_open + - recvmmsg + - fanotify_init + - fanotify_mark + - prlimit64 + - name_to_handle_at + - open_by_handle_at + - clock_adjtime + - syncfs + - sendmmsg + - setns + - getcpu + - process_vm_readv + - process_vm_writev + - kcmp + - finit_module + - sched_setattr + - sched_getattr + - renameat2 + - seccomp + - getrandom + - memfd_create + - kexec_file_load + - bpf + - execveat + - userfaultfd + - membarrier + - mlock2 + - copy_file_range + - preadv2 + - pwritev2 + - pkey_mprotect + - pkey_alloc + - pkey_free + - statx + - io_pgetevents + - rseq + type: string + type: array + type: object + type: array + message: + type: string + severity: + maximum: 10 + minimum: 1 + type: integer + tags: + items: + type: string + type: array + type: object + tags: + items: + type: string + type: array + type: object + status: + description: KubeArmorClusterPolicyStatus defines the observed state of + KubeArmorCLusterPolicy + properties: + status: + type: string + type: object + type: object + served: true + storage: true + subresources: + status: {} +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] diff --git a/deployments/helm/KubeArmorOperator/crds/operator.kubearmor.com_kubearmorconfigs.yaml b/deployments/helm/KubeArmorOperator/crds/operator.kubearmor.com_kubearmorconfigs.yaml index f1dac2062b..c45e8100c6 100644 --- a/deployments/helm/KubeArmorOperator/crds/operator.kubearmor.com_kubearmorconfigs.yaml +++ b/deployments/helm/KubeArmorOperator/crds/operator.kubearmor.com_kubearmorconfigs.yaml @@ -3,7 +3,8 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.4.1 + creationTimestamp: null name: kubearmorconfigs.operator.kubearmor.com spec: group: operator.kubearmor.com @@ -24,19 +25,14 @@ spec: description: KubeArmorConfig is the Schema for the KubeArmorConfigs API properties: apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' type: string kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' type: string metadata: type: object @@ -160,9 +156,9 @@ spec: message: type: string phase: - description: |- - INSERT ADDITIONAL STATUS FIELD - define observed state of cluster - Important: Run "make" to regenerate code after modifying this file + description: 'INSERT ADDITIONAL STATUS FIELD - define observed state + of cluster Important: Run "make" to regenerate code after modifying + this file' type: string type: object type: object @@ -170,3 +166,9 @@ spec: storage: true subresources: status: {} +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] diff --git a/deployments/helm/KubeArmorOperator/templates/clusterrole-rbac.yaml b/deployments/helm/KubeArmorOperator/templates/clusterrole-rbac.yaml index 8075210e26..8d97e87ea7 100644 --- a/deployments/helm/KubeArmorOperator/templates/clusterrole-rbac.yaml +++ b/deployments/helm/KubeArmorOperator/templates/clusterrole-rbac.yaml @@ -144,6 +144,7 @@ rules: - security.kubearmor.com resources: - kubearmorpolicies + - kubearmorclusterpolicies - kubearmorhostpolicies verbs: - get @@ -179,6 +180,7 @@ rules: - security.kubearmor.com resources: - kubearmorpolicies + - kubearmorclusterpolicies - kubearmorhostpolicies verbs: - create @@ -192,6 +194,7 @@ rules: - security.kubearmor.com resources: - kubearmorpolicies/status + - kubearmorclusterpolicies/status - kubearmorhostpolicies/status verbs: - get diff --git a/deployments/main.go b/deployments/main.go index 99a1525f5b..dd41a18973 100644 --- a/deployments/main.go +++ b/deployments/main.go @@ -40,6 +40,7 @@ func main() { // CRDs kcrd.GetHspCRD(), kcrd.GetKspCRD(), + kcrd.GetCspCRD(), // ClusterRoles dp.GetClusterRole(), diff --git a/deployments/operator/operator.yaml b/deployments/operator/operator.yaml index 4bf8da1485..997f2376b7 100644 --- a/deployments/operator/operator.yaml +++ b/deployments/operator/operator.yaml @@ -2,7 +2,8 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.4.1 + creationTimestamp: null name: kubearmorconfigs.operator.kubearmor.com spec: group: operator.kubearmor.com @@ -23,19 +24,14 @@ spec: description: KubeArmorConfig is the Schema for the KubeArmorConfigs API properties: apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' type: string kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' type: string metadata: type: object @@ -159,9 +155,9 @@ spec: message: type: string phase: - description: |- - INSERT ADDITIONAL STATUS FIELD - define observed state of cluster - Important: Run "make" to regenerate code after modifying this file + description: 'INSERT ADDITIONAL STATUS FIELD - define observed state + of cluster Important: Run "make" to regenerate code after modifying + this file' type: string type: object type: object @@ -169,6 +165,12 @@ spec: storage: true subresources: status: {} +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] --- apiVersion: v1 kind: ServiceAccount @@ -292,6 +294,7 @@ rules: - security.kubearmor.com resources: - kubearmorpolicies + - kubearmorclusterpolicies - kubearmorhostpolicies verbs: - create @@ -305,6 +308,7 @@ rules: - security.kubearmor.com resources: - kubearmorpolicies/status + - kubearmorclusterpolicies/status - kubearmorhostpolicies/status verbs: - get @@ -384,14 +388,11 @@ rules: - cronjobs verbs: - get - - patch - - list - - watch - - update - apiGroups: - security.kubearmor.com resources: - kubearmorpolicies + - kubearmorclusterpolicies - kubearmorhostpolicies verbs: - get diff --git a/examples/nginx-csp/cluster-security-policies/csp-in-operator-block-file-access.yaml b/examples/nginx-csp/cluster-security-policies/csp-in-operator-block-file-access.yaml new file mode 100644 index 0000000000..453de059a9 --- /dev/null +++ b/examples/nginx-csp/cluster-security-policies/csp-in-operator-block-file-access.yaml @@ -0,0 +1,25 @@ +apiVersion: security.kubearmor.com/v1 +kind: KubeArmorClusterPolicy +metadata: + name: csp-in-operator-block-file-access +spec: + severity: 8 + selector: + matchExpressions: + - key: namespace + operator: In + values: + - nginx2 + file: + matchPaths: + - path: /etc/host.conf + fromSource: + - path: /usr/bin/cat + action: + Block + +# cluster_policy_test_3 + +# test +# $ dash -c cat /etc/host.conf +# dash: 1: cat /etc/host.conf: Permission denied \ No newline at end of file diff --git a/examples/nginx-csp/cluster-security-policies/csp-in-operator-block-process.yaml b/examples/nginx-csp/cluster-security-policies/csp-in-operator-block-process.yaml new file mode 100644 index 0000000000..3cc01e7037 --- /dev/null +++ b/examples/nginx-csp/cluster-security-policies/csp-in-operator-block-process.yaml @@ -0,0 +1,23 @@ +apiVersion: security.kubearmor.com/v1 +kind: KubeArmorClusterPolicy +metadata: + name: csp-in-operator-block-process +spec: + severity: 8 + selector: + matchExpressions: + - key: namespace + operator: In + values: + - nginx1 + process: + matchPaths: + - path: /usr/bin/apt + action: + Block + +# cluster_policy_test_1 + +# test +# $ dash -c apt +# dash: 1: apt: Permission denied \ No newline at end of file diff --git a/examples/nginx-csp/cluster-security-policies/csp-not-in-operator-block-file-access.yaml b/examples/nginx-csp/cluster-security-policies/csp-not-in-operator-block-file-access.yaml new file mode 100644 index 0000000000..2f8a476bd0 --- /dev/null +++ b/examples/nginx-csp/cluster-security-policies/csp-not-in-operator-block-file-access.yaml @@ -0,0 +1,25 @@ +apiVersion: security.kubearmor.com/v1 +kind: KubeArmorClusterPolicy +metadata: + name: csp-not-in-operator-block-file-access +spec: + severity: 8 + selector: + matchExpressions: + - key: namespace + operator: NotIn + values: + - nginx2 + file: + matchPaths: + - path: /etc/host.conf + fromSource: + - path: /usr/bin/cat + action: + Block + +# cluster_policy_test_4 + +# test +# $ dash -c cat /etc/host.conf +# multi on \ No newline at end of file diff --git a/examples/nginx-csp/cluster-security-policies/csp-not-in-operator-block-process.yaml b/examples/nginx-csp/cluster-security-policies/csp-not-in-operator-block-process.yaml new file mode 100644 index 0000000000..bf101586cf --- /dev/null +++ b/examples/nginx-csp/cluster-security-policies/csp-not-in-operator-block-process.yaml @@ -0,0 +1,23 @@ +apiVersion: security.kubearmor.com/v1 +kind: KubeArmorClusterPolicy +metadata: + name: csp-not-in-operator-block-process +spec: + severity: 8 + selector: + matchExpressions: + - key: namespace + operator: NotIn + values: + - nginx1 + process: + matchPaths: + - path: /usr/bin/apt + action: + Block + +# cluster_policy_test_2 + +# test +# $ dash -c apt +# apt 2.6.1 (amd64)*. \ No newline at end of file diff --git a/examples/nginx-csp/nginx-nginx1-deployment.yaml b/examples/nginx-csp/nginx-nginx1-deployment.yaml new file mode 100644 index 0000000000..efe3ac8603 --- /dev/null +++ b/examples/nginx-csp/nginx-nginx1-deployment.yaml @@ -0,0 +1,27 @@ +apiVersion: v1 +kind: Namespace +metadata: + name: nginx1 +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: nginx + namespace: nginx1 + labels: + app: nginx +spec: + replicas: 1 + selector: + matchLabels: + app: nginx + template: + metadata: + labels: + app: nginx + spec: + containers: + - name: nginx + image: nginx + ports: + - containerPort: 80 diff --git a/examples/nginx-csp/nginx-nginx2-deployment.yaml b/examples/nginx-csp/nginx-nginx2-deployment.yaml new file mode 100644 index 0000000000..99296e4d18 --- /dev/null +++ b/examples/nginx-csp/nginx-nginx2-deployment.yaml @@ -0,0 +1,27 @@ +apiVersion: v1 +kind: Namespace +metadata: + name: nginx2 +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: nginx + namespace: nginx2 + labels: + app: nginx +spec: + replicas: 1 + selector: + matchLabels: + app: nginx + template: + metadata: + labels: + app: nginx + spec: + containers: + - name: nginx + image: nginx + ports: + - containerPort: 80 diff --git a/getting-started/cluster_security_policy_examples.md b/getting-started/cluster_security_policy_examples.md new file mode 100644 index 0000000000..21069d1977 --- /dev/null +++ b/getting-started/cluster_security_policy_examples.md @@ -0,0 +1,117 @@ +# Examples of Cluster Security Policy + +Here, we demonstrate how to define a cluster security policies. + +* Process Execution Restriction + * Block a specific executable - In operator \([csp-in-operator-block-process.yaml](../examples/nginx-csp/cluster-security-policies/csp-in-operator-block-process.yaml)\) + + ```yaml + apiVersion: security.kubearmor.com/v1 + kind: KubeArmorClusterPolicy + metadata: + name: csp-in-operator-block-process + spec: + severity: 8 + selector: + matchExpressions: + - key: namespace + operator: In + values: + - nginx1 + process: + matchPaths: + - path: /usr/bin/apt + action: + Block + ``` + + * Explanation: The purpose of this policy is to block the execution of '/usr/bin/apt' in the containers present in the namespace nginx1. For this, we define the 'nginx1' value and operator as 'In' in selector -> matchExpressions and the specific path \('/usr/bin/apt'\) in process -> matchPaths. Also, we put 'Block' as the action of this policy. + + * Verification: After applying this policy, please get into one of the containers in the namespace 'nginx1' \(using "kubectl -n nginx1 exec -it nginx-X-... -- bash"\) and run '/usr/bin/apt'. You will see that /usr/bin/apt is blocked. + + * Block a specific executable - NotIn operator\([csp-not-in-operator-block-process.yaml](../examples/nginx-csp/cluster-security-policies/csp-not-in-operator-block-process.yaml)\) + + ```yaml + apiVersion: security.kubearmor.com/v1 + kind: KubeArmorClusterPolicy + metadata: + name: csp-in-operator-block-process + spec: + severity: 8 + selector: + matchExpressions: + - key: namespace + operator: NotIn + values: + - nginx1 + process: + matchPaths: + - path: /usr/bin/apt + action: + Block + ``` + + * Explanation: The purpose of this policy is to block the execution of '/usr/bin/apt' in all containers present in the cluster except that are in the namespace nginx1. For this, we define the 'nginx1' value and operator as 'NotIn' in selector -> matchExpressions and the specific path \('/usr/bin/apt'\) in process -> matchPaths. Also, we put 'Block' as the action of this policy. + + * Verification: After applying this policy, please get into one of the containers in the namespace 'nginx1' \(using "kubectl -n nginx1 exec -it nginx-X-... -- bash"\) and run '/usr/bin/apt'. You will see that /usr/bin/apt is not blocked. Now try running same command in container inside 'nginx2' namespace and it should not be blocked. + +* File Access Restriction + * Block accessing specific file \([csp-in-operator-block-file-access.yaml](../examples/nginx-csp/cluster-security-policies/csp-in-operator-block-file-access.yaml)\) + + ```yaml + apiVersion: security.kubearmor.com/v1 + kind: KubeArmorClusterPolicy + metadata: + name: csp-in-operator-block-file-access + spec: + severity: 8 + selector: + matchExpressions: + - key: namespace + operator: In + values: + - nginx2 + file: + matchPaths: + - path: /etc/host.conf + fromSource: + - path: /usr/bin/cat + action: + Block + + ``` + + * Explanation: The purpose of this policy is to block the container within the namespace 'nginx2' to read '/etc/host.conf'. + + * Verification: After applying this policy, please get into the container within the namespace 'nginx2' and run 'cat /etc/host.conf'. You can see the operation is blocked. + + * Block accessing specific file \([csp-in-operator-block-file-access.yaml](../examples/nginx-csp/cluster-security-policies/csp-in-operator-block-file-access.yaml)\) + + ```yaml + apiVersion: security.kubearmor.com/v1 + kind: KubeArmorClusterPolicy + metadata: + name: csp-in-operator-block-file-access + spec: + severity: 8 + selector: + matchExpressions: + - key: namespace + operator: NotIn + values: + - nginx2 + file: + matchPaths: + - path: /etc/host.conf + fromSource: + - path: /usr/bin/cat + action: + Block + + ``` + + * Explanation: The purpose of this policy is to block read access for '/etc/host.conf' in all the containers except the namespace 'bginx2'. + + * Verification: After applying this policy, please get into the container within the namespace 'nginx2' and run 'cat /etc/host.conf'. You can see the operation is not blocked and can see the content of the file. Now try to run 'cat /etc/host.conf' in container of 'nginx1' namespace, this operation should be blocked. + +> **Note** Other operations like Network, Capabilities, Syscalls also behave in same way as in security policy. The difference only lies in how we match the cluster policy with the namespaces. diff --git a/getting-started/cluster_security_policy_specification.md b/getting-started/cluster_security_policy_specification.md new file mode 100644 index 0000000000..2be295fd94 --- /dev/null +++ b/getting-started/cluster_security_policy_specification.md @@ -0,0 +1,311 @@ +# Specification of Cluster Security Policy for Containers + +## Cluster Policy Specification + +Here is the specification of a Cluster security policy. + +```text +apiVersion: security.kubearmor.com/v1 +kind:KubeArmorClusterPolicy +metadata: + name: [policy name] + namespace: [namespace name] # --> optional + +spec: + severity: [1-10] # --> optional (1 by default) + tags: ["tag", ...] # --> optional + message: [message] # --> optional + + selector: + matchExpressions: + - key: [namespace] + operator: [In|NotIn] + values: + - [namespaces] + + process: + matchPaths: + - path: [absolute executable path] + ownerOnly: [true|false] # --> optional + fromSource: # --> optional + - path: [absolute exectuable path] + matchDirectories: + - dir: [absolute directory path] + recursive: [true|false] # --> optional + ownerOnly: [true|false] # --> optional + fromSource: # --> optional + - path: [absolute exectuable path] + matchPatterns: + - pattern: [regex pattern] + ownerOnly: [true|false] # --> optional + + file: + matchPaths: + - path: [absolute file path] + readOnly: [true|false] # --> optional + ownerOnly: [true|false] # --> optional + fromSource: # --> optional + - path: [absolute exectuable path] + matchDirectories: + - dir: [absolute directory path] + recursive: [true|false] # --> optional + readOnly: [true|false] # --> optional + ownerOnly: [true|false] # --> optional + fromSource: # --> optional + - path: [absolute exectuable path] + matchPatterns: + - pattern: [regex pattern] + readOnly: [true|false] # --> optional + ownerOnly: [true|false] # --> optional + + network: + matchProtocols: + - protocol: [TCP|tcp|UDP|udp|ICMP|icmp] + fromSource: # --> optional + - path: [absolute exectuable path] + + capabilities: + matchCapabilities: + - capability: [capability name] + fromSource: # --> optional + - path: [absolute exectuable path] + + syscalls: + matchSyscalls: + - syscall: + - syscallX + - syscallY + fromSource: # --> optional + - path: [absolute exectuable path] + - dir: [absolute directory path] + recursive: [true|false] # --> optional + matchPaths: + - path: [absolute directory path | absolute exectuable path] + recursive: [true|false] # --> optional + - syscall: + - syscallX + - syscallY + fromSource: # --> optional + - path: [absolute exectuable path] + - dir: [absolute directory path] + recursive: [true|false] # --> optional + + action: [Allow|Audit|Block] (Block by default) +``` + +> **Note** Please note that for system calls monitoring we only support audit action no matter what the value of action is + +## Policy Spec Description + +Now, we will briefly explain how to define a cluster security policy. + +### Common + + A cluster security policy starts with the base information such as apiVersion, kind, and metadata. The apiVersion would be the same in any security policies. In the case of metadata, you need to specify the names of a policy and a namespace where you want to apply the policy and kind would be KubeArmorClusterPolicy. + + ```text + apiVersion: security.kubearmor.com/v1 + kind:KubeArmorClusterPolicy + metadata: + name: [policy name] + namespace: [namespace name] + ``` + +### Severity + + The severity part is somewhat important. You can specify the severity of a given policy from 1 to 10. This severity will appear in alerts when policy violations happen. + + ```text + severity: [1-10] + ``` + +### Tags + + The tags part is optional. You can define multiple tags (e.g., WARNING, SENSITIVE, MITRE, STIG, etc.) to categorize security policies. + + ```text + tags: ["tag1", ..., "tagN"] + ``` + +### Message + + The message part is optional. You can add an alert message, and then the message will be presented in alert logs. + + ```text + message: [message] + ``` + +### Selector + + In the selector section for cluster-based policies, we use matchExpressions to define the namespaces where the policy should be applied. Currently, only namespaces can be matched, so the key should be 'namespace'. The operator will determine whether the policy should apply to the namespaces specified in the values field or not. + + Operator: In + When the operator is set to In, the policy will be applied only to the namespaces listed in the values field. + + Operator: NotIn + When the operator is set to NotIn, the policy will be applied to all other namespaces except those listed in the values field. + + ```text + selector: + matchExpressions: + - key: [namespace] + operator: [In|NotIn] + values: + - [namespaces] + ``` + + > **TIP** If the selector operator is omitted in the policy, it will be applied across all namespaces. + +### Process + + In the process section, there are three types of matches: matchPaths, matchDirectories, and matchPatterns. You can define specific executables using matchPaths or all executables in specific directories using matchDirectories. In the case of matchPatterns, advanced operators may be able to determine particular patterns for executables by using regular expressions. However, the coverage of regular expressions is highly dependent on AppArmor \([Policy Core Reference](https://gitlab.com/apparmor/apparmor/-/wikis/AppArmor_Core_Policy_Reference)\). Thus, we generally do not recommend using this match. + + ```text + process: + matchPaths: + - path: [absolute executable path] + ownerOnly: [true|false] # --> optional + fromSource: # --> optional + - path: [absolute executable path] + matchDirectories: + - dir: [absolute directory path] + recursive: [true|false] # --> optional + ownerOnly: [true|false] # --> optional + fromSource: # --> optional + - path: [absolute exectuable path] + matchPatterns: + - pattern: [regex pattern] + ownerOnly: [true|false] # --> optional + ``` + + In each match, there are three options. + + * ownerOnly \(static action: allow owner only; otherwise block all\) + + If this is enabled, the owners of the executable\(s\) defined with matchPaths and matchDirectories will be only allowed to execute. + + * recursive + + If this is enabled, the coverage will extend to the subdirectories of the directory defined with matchDirectories. + + * fromSource + + If a path is specified in fromSource, the executable at the path will be allowed/blocked to execute the executables defined with matchPaths or matchDirectories. For better understanding, let us say that an operator defines a policy as follows. Then, /bin/bash will be only allowed (blocked) to execute /bin/sleep. Otherwise, the execution of /bin/sleep will be blocked (allowed). + + ```text + process: + matchPaths: + - path: /bin/sleep + fromSource: + - path: /bin/bash + ``` + +### File + + The file section is quite similar to the process section. + + ```text + file: + matchPaths: + - path: [absolute file path] + readOnly: [true|false] # --> optional + ownerOnly: [true|false] # --> optional + fromSource: # --> optional + - path: [absolute file path] + matchDirectories: + - dir: [absolute directory path] + recursive: [true|false] # --> optional + readOnly: [true|false] # --> optional + ownerOnly: [true|false] # --> optional + fromSource: # --> optional + - path: [absolute file path] + matchPatterns: + - pattern: [regex pattern] + readOnly: [true|false] # --> optional + ownerOnly: [true|false] # --> optional + ``` + + The only difference between 'process' and 'file' is the readOnly option. + + * readOnly \(static action: allow to read only; otherwise block all\) + + If this is enabled, the read operation will be only allowed, and any other operations \(e.g., write\) will be blocked. + +### Network + + In the case of network, there is currently one match type: matchProtocols. You can define specific protocols among TCP, UDP, and ICMP. + + ```text + network: + matchProtocols: + - protocol: [protocol] # --> [ TCP | tcp | UDP | udp | ICMP | icmp ] + fromSource: # --> optional + - path: [absolute file path] + ``` + +### Capabilities + + In the case of capabilities, there is currently one match type: matchCapabilities. You can define specific capability names to allow or block using matchCapabilities. You can check available capabilities in [Capability List](supported_capability_list.md). + + ```text + capabilities: + matchCapabilities: + - capability: [capability name] + fromSource: # --> optional + - path: [absolute file path] + ``` + +### Syscalls + + In the case of syscalls, there are two types of matches, matchSyscalls and matchPaths. matchPaths can be used to target system calls targeting specific binary path or anything under a specific directory, additionally you can slice based on syscalls generated by a binary or a group of binaries in a directory. You can use matchSyscall as a more general rule to match syscalls from all sources or from specific binaries. + +``` +syscalls: + matchSyscalls: + - syscall: + - syscallX + - syscallY + fromSource: # --> optional + - path: [absolute exectuable path] + - dir: [absolute directory path] + recursive: [true|false] # --> optional + matchPaths: + - path: [absolute directory path | absolute exectuable path] + recursive: [true|false] # --> optional + - syscall: + - syscallX + - syscallY + fromSource: # --> optional + - path: [absolute exectuable path] + - dir: [absolute directory path] + recursive: [true|false] # --> optional +``` + +There is one options in each match. + + * fromSource + + If a path is specified in fromSource, kubearmor will match only syscalls generated by the defined source. For better undrestanding, lets take the example below. Only unlink system calls generated by `/bin/bash` will be matched. + + ```text + process: + matchPaths: + - path: /bin/sleep + - syscall: + - unlink + fromSource: + - path: /bin/bash + ``` + + * recursive + + If this is enabled, the coverage will extend to the subdirectories of the directory. + +* Action + + The action could be Allow, Audit, or Block. Security policies would be handled in a blacklist manner or a whitelist manner according to the action. Thus, you need to define the action carefully. You can refer to [Consideration in Policy Action](consideration_in_policy_action.md) for more details. In the case of the Audit action, we can use this action for policy verification before applying a security policy with the Block action. + For System calls monitoring, we only support audit mode no matter what the action is set to. + + ```text + action: [Allow|Audit|Block] + ``` diff --git a/pkg/KubeArmorController/Makefile b/pkg/KubeArmorController/Makefile index 01345921f3..e7c5638589 100644 --- a/pkg/KubeArmorController/Makefile +++ b/pkg/KubeArmorController/Makefile @@ -53,6 +53,9 @@ manifests: controller-gen ## Generate WebhookConfiguration, ClusterRole and Cust cp config/crd/bases/security.kubearmor.com_kubearmorpolicies.yaml ../../deployments/CRD/KubeArmorPolicy.yaml cp config/crd/bases/security.kubearmor.com_kubearmorpolicies.yaml crd/KubeArmorPolicy.yaml cp config/crd/bases/security.kubearmor.com_kubearmorpolicies.yaml ../../deployments/helm/KubeArmor/templates/crds/ksp.yaml + cp config/crd/bases/security.kubearmor.com_kubearmorclusterpolicies.yaml ../../deployments/CRD/KubeArmorClusterPolicy.yaml + cp config/crd/bases/security.kubearmor.com_kubearmorclusterpolicies.yaml crd/KubeArmorClusterPolicy.yaml + cp config/crd/bases/security.kubearmor.com_kubearmorclusterpolicies.yaml ../../deployments/helm/KubeArmor/templates/crds/csp.yaml cp config/crd/bases/security.kubearmor.com_kubearmorhostpolicies.yaml ../../deployments/CRD/KubeArmorHostPolicy.yaml cp config/crd/bases/security.kubearmor.com_kubearmorhostpolicies.yaml crd/KubeArmorHostPolicy.yaml cp config/crd/bases/security.kubearmor.com_kubearmorhostpolicies.yaml ../../deployments/helm/KubeArmor/templates/crds/hsp.yaml diff --git a/pkg/KubeArmorController/api/security.kubearmor.com/v1/kubearmorclusterpolicy_types.go b/pkg/KubeArmorController/api/security.kubearmor.com/v1/kubearmorclusterpolicy_types.go new file mode 100644 index 0000000000..006a8efe13 --- /dev/null +++ b/pkg/KubeArmorController/api/security.kubearmor.com/v1/kubearmorclusterpolicy_types.go @@ -0,0 +1,80 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright 2024 Authors of KubeArmor + +package v1 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +type MatchExpressionsType struct { + // +kubebuilder:validation:Enum=namespace + Key string `json:"key,omitempty"` + + // +kubebuilder:validation:Enum=In;NotIn + Operator string `json:"operator,omitempty"` + + Values []string `json:"values,omitempty"` +} + +type NsSelectorType struct { + MatchExpressions []MatchExpressionsType `json:"matchExpressions,omitempty"` +} + +// KubeArmorClusterPolicySpec defines the desired state of KubeArmorClusterPolicy +type KubeArmorClusterPolicySpec struct { + Selector NsSelectorType `json:"selector,omitempty"` + + Process ProcessType `json:"process,omitempty"` + File FileType `json:"file,omitempty"` + Network NetworkType `json:"network,omitempty"` + Capabilities CapabilitiesType `json:"capabilities,omitempty"` + Syscalls SyscallsType `json:"syscalls,omitempty"` + + AppArmor string `json:"apparmor,omitempty"` + + // +kubebuilder:validation:optional + Severity SeverityType `json:"severity,omitempty"` + // +kubebuilder:validation:optional + Tags []string `json:"tags,omitempty"` + // +kubebuilder:validation:optional + Message string `json:"message,omitempty"` + // +kubebuilder:validation:optional + Action ActionType `json:"action,omitempty"` +} + +// KubeArmorClusterPolicyStatus defines the observed state of KubeArmorCLusterPolicy +type KubeArmorClusterPolicyStatus struct { + PolicyStatus string `json:"status,omitempty"` +} + +// +kubebuilder:object:root=true + +// KubeArmorClusterPolicy is the Schema for the kubearmorclusterpolicies API +// +genclient +// +genclient:nonNamespaced +// +kubebuilder:resource:shortName=csp,scope="Cluster" +// +kubebuilder:subresource:status +// +kubebuilder:printcolumn:name="Age",type=date,JSONPath=`.metadata.creationTimestamp` +// +kubebuilder:printcolumn:name="Action",type=string,JSONPath=`.spec.action`,priority=10 +// +kubebuilder:printcolumn:name="Selector",type=string,JSONPath=`.spec.selector.matchExpressions`,priority=10 +type KubeArmorClusterPolicy struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + Spec KubeArmorClusterPolicySpec `json:"spec,omitempty"` + Status KubeArmorClusterPolicyStatus `json:"status,omitempty"` +} + +// +kubebuilder:object:root=true + +// KubeArmorClusterPolicyList contains a list of KubeArmorClusterPolicy +type KubeArmorClusterPolicyList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []KubeArmorClusterPolicy `json:"items"` +} + +func init() { + SchemeBuilder.Register(&KubeArmorClusterPolicy{}, &KubeArmorClusterPolicyList{}) +} diff --git a/pkg/KubeArmorController/api/security.kubearmor.com/v1/zz_generated.deepcopy.go b/pkg/KubeArmorController/api/security.kubearmor.com/v1/zz_generated.deepcopy.go index 8d51c9be26..c0fc44008c 100644 --- a/pkg/KubeArmorController/api/security.kubearmor.com/v1/zz_generated.deepcopy.go +++ b/pkg/KubeArmorController/api/security.kubearmor.com/v1/zz_generated.deepcopy.go @@ -204,6 +204,106 @@ func (in *HostNetworkType) DeepCopy() *HostNetworkType { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *KubeArmorClusterPolicy) DeepCopyInto(out *KubeArmorClusterPolicy) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + out.Status = in.Status +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KubeArmorClusterPolicy. +func (in *KubeArmorClusterPolicy) DeepCopy() *KubeArmorClusterPolicy { + if in == nil { + return nil + } + out := new(KubeArmorClusterPolicy) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *KubeArmorClusterPolicy) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *KubeArmorClusterPolicyList) DeepCopyInto(out *KubeArmorClusterPolicyList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]KubeArmorClusterPolicy, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KubeArmorClusterPolicyList. +func (in *KubeArmorClusterPolicyList) DeepCopy() *KubeArmorClusterPolicyList { + if in == nil { + return nil + } + out := new(KubeArmorClusterPolicyList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *KubeArmorClusterPolicyList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *KubeArmorClusterPolicySpec) DeepCopyInto(out *KubeArmorClusterPolicySpec) { + *out = *in + in.Selector.DeepCopyInto(&out.Selector) + in.Process.DeepCopyInto(&out.Process) + in.File.DeepCopyInto(&out.File) + in.Network.DeepCopyInto(&out.Network) + in.Capabilities.DeepCopyInto(&out.Capabilities) + in.Syscalls.DeepCopyInto(&out.Syscalls) + if in.Tags != nil { + in, out := &in.Tags, &out.Tags + *out = make([]string, len(*in)) + copy(*out, *in) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KubeArmorClusterPolicySpec. +func (in *KubeArmorClusterPolicySpec) DeepCopy() *KubeArmorClusterPolicySpec { + if in == nil { + return nil + } + out := new(KubeArmorClusterPolicySpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *KubeArmorClusterPolicyStatus) DeepCopyInto(out *KubeArmorClusterPolicyStatus) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KubeArmorClusterPolicyStatus. +func (in *KubeArmorClusterPolicyStatus) DeepCopy() *KubeArmorClusterPolicyStatus { + if in == nil { + return nil + } + out := new(KubeArmorClusterPolicyStatus) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *KubeArmorHostPolicy) DeepCopyInto(out *KubeArmorHostPolicy) { *out = *in @@ -429,6 +529,26 @@ func (in *MatchCapabilitiesType) DeepCopy() *MatchCapabilitiesType { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *MatchExpressionsType) DeepCopyInto(out *MatchExpressionsType) { + *out = *in + if in.Values != nil { + in, out := &in.Values, &out.Values + *out = make([]string, len(*in)) + copy(*out, *in) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MatchExpressionsType. +func (in *MatchExpressionsType) DeepCopy() *MatchExpressionsType { + if in == nil { + return nil + } + out := new(MatchExpressionsType) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *MatchHostCapabilitiesType) DeepCopyInto(out *MatchHostCapabilitiesType) { *out = *in @@ -588,6 +708,28 @@ func (in *NodeSelectorType) DeepCopy() *NodeSelectorType { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *NsSelectorType) DeepCopyInto(out *NsSelectorType) { + *out = *in + if in.MatchExpressions != nil { + in, out := &in.MatchExpressions, &out.MatchExpressions + *out = make([]MatchExpressionsType, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NsSelectorType. +func (in *NsSelectorType) DeepCopy() *NsSelectorType { + if in == nil { + return nil + } + out := new(NsSelectorType) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ProcessDirectoryType) DeepCopyInto(out *ProcessDirectoryType) { *out = *in diff --git a/pkg/KubeArmorController/client/clientset/versioned/typed/security.kubearmor.com/v1/fake/fake_kubearmorclusterpolicy.go b/pkg/KubeArmorController/client/clientset/versioned/typed/security.kubearmor.com/v1/fake/fake_kubearmorclusterpolicy.go new file mode 100644 index 0000000000..151bb9a772 --- /dev/null +++ b/pkg/KubeArmorController/client/clientset/versioned/typed/security.kubearmor.com/v1/fake/fake_kubearmorclusterpolicy.go @@ -0,0 +1,120 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright 2022 Authors of KubeArmor + +// Code generated by client-gen. DO NOT EDIT. + +package fake + +import ( + "context" + + securitykubearmorcomv1 "github.com/kubearmor/KubeArmor/pkg/KubeArmorController/api/security.kubearmor.com/v1" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + labels "k8s.io/apimachinery/pkg/labels" + schema "k8s.io/apimachinery/pkg/runtime/schema" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" + testing "k8s.io/client-go/testing" +) + +// FakeKubeArmorClusterPolicies implements KubeArmorClusterPolicyInterface +type FakeKubeArmorClusterPolicies struct { + Fake *FakeSecurityV1 +} + +var kubearmorclusterpoliciesResource = schema.GroupVersionResource{Group: "security.kubearmor.com", Version: "v1", Resource: "kubearmorclusterpolicies"} + +var kubearmorclusterpoliciesKind = schema.GroupVersionKind{Group: "security.kubearmor.com", Version: "v1", Kind: "KubeArmorClusterPolicy"} + +// Get takes name of the kubeArmorClusterPolicy, and returns the corresponding kubeArmorClusterPolicy object, and an error if there is any. +func (c *FakeKubeArmorClusterPolicies) Get(ctx context.Context, name string, options v1.GetOptions) (result *securitykubearmorcomv1.KubeArmorClusterPolicy, err error) { + obj, err := c.Fake. + Invokes(testing.NewRootGetAction(kubearmorclusterpoliciesResource, name), &securitykubearmorcomv1.KubeArmorClusterPolicy{}) + if obj == nil { + return nil, err + } + return obj.(*securitykubearmorcomv1.KubeArmorClusterPolicy), err +} + +// List takes label and field selectors, and returns the list of KubeArmorClusterPolicies that match those selectors. +func (c *FakeKubeArmorClusterPolicies) List(ctx context.Context, opts v1.ListOptions) (result *securitykubearmorcomv1.KubeArmorClusterPolicyList, err error) { + obj, err := c.Fake. + Invokes(testing.NewRootListAction(kubearmorclusterpoliciesResource, kubearmorclusterpoliciesKind, opts), &securitykubearmorcomv1.KubeArmorClusterPolicyList{}) + if obj == nil { + return nil, err + } + + label, _, _ := testing.ExtractFromListOptions(opts) + if label == nil { + label = labels.Everything() + } + list := &securitykubearmorcomv1.KubeArmorClusterPolicyList{ListMeta: obj.(*securitykubearmorcomv1.KubeArmorClusterPolicyList).ListMeta} + for _, item := range obj.(*securitykubearmorcomv1.KubeArmorClusterPolicyList).Items { + if label.Matches(labels.Set(item.Labels)) { + list.Items = append(list.Items, item) + } + } + return list, err +} + +// Watch returns a watch.Interface that watches the requested kubeArmorClusterPolicies. +func (c *FakeKubeArmorClusterPolicies) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) { + return c.Fake. + InvokesWatch(testing.NewRootWatchAction(kubearmorclusterpoliciesResource, opts)) +} + +// Create takes the representation of a kubeArmorClusterPolicy and creates it. Returns the server's representation of the kubeArmorClusterPolicy, and an error, if there is any. +func (c *FakeKubeArmorClusterPolicies) Create(ctx context.Context, kubeArmorClusterPolicy *securitykubearmorcomv1.KubeArmorClusterPolicy, opts v1.CreateOptions) (result *securitykubearmorcomv1.KubeArmorClusterPolicy, err error) { + obj, err := c.Fake. + Invokes(testing.NewRootCreateAction(kubearmorclusterpoliciesResource, kubeArmorClusterPolicy), &securitykubearmorcomv1.KubeArmorClusterPolicy{}) + if obj == nil { + return nil, err + } + return obj.(*securitykubearmorcomv1.KubeArmorClusterPolicy), err +} + +// Update takes the representation of a kubeArmorClusterPolicy and updates it. Returns the server's representation of the kubeArmorClusterPolicy, and an error, if there is any. +func (c *FakeKubeArmorClusterPolicies) Update(ctx context.Context, kubeArmorClusterPolicy *securitykubearmorcomv1.KubeArmorClusterPolicy, opts v1.UpdateOptions) (result *securitykubearmorcomv1.KubeArmorClusterPolicy, err error) { + obj, err := c.Fake. + Invokes(testing.NewRootUpdateAction(kubearmorclusterpoliciesResource, kubeArmorClusterPolicy), &securitykubearmorcomv1.KubeArmorClusterPolicy{}) + if obj == nil { + return nil, err + } + return obj.(*securitykubearmorcomv1.KubeArmorClusterPolicy), err +} + +// UpdateStatus was generated because the type contains a Status member. +// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). +func (c *FakeKubeArmorClusterPolicies) UpdateStatus(ctx context.Context, kubeArmorClusterPolicy *securitykubearmorcomv1.KubeArmorClusterPolicy, opts v1.UpdateOptions) (*securitykubearmorcomv1.KubeArmorClusterPolicy, error) { + obj, err := c.Fake. + Invokes(testing.NewRootUpdateSubresourceAction(kubearmorclusterpoliciesResource, "status", kubeArmorClusterPolicy), &securitykubearmorcomv1.KubeArmorClusterPolicy{}) + if obj == nil { + return nil, err + } + return obj.(*securitykubearmorcomv1.KubeArmorClusterPolicy), err +} + +// Delete takes name of the kubeArmorClusterPolicy and deletes it. Returns an error if one occurs. +func (c *FakeKubeArmorClusterPolicies) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error { + _, err := c.Fake. + Invokes(testing.NewRootDeleteAction(kubearmorclusterpoliciesResource, name), &securitykubearmorcomv1.KubeArmorClusterPolicy{}) + return err +} + +// DeleteCollection deletes a collection of objects. +func (c *FakeKubeArmorClusterPolicies) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error { + action := testing.NewRootDeleteCollectionAction(kubearmorclusterpoliciesResource, listOpts) + + _, err := c.Fake.Invokes(action, &securitykubearmorcomv1.KubeArmorClusterPolicyList{}) + return err +} + +// Patch applies the patch and returns the patched kubeArmorClusterPolicy. +func (c *FakeKubeArmorClusterPolicies) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *securitykubearmorcomv1.KubeArmorClusterPolicy, err error) { + obj, err := c.Fake. + Invokes(testing.NewRootPatchSubresourceAction(kubearmorclusterpoliciesResource, name, pt, data, subresources...), &securitykubearmorcomv1.KubeArmorClusterPolicy{}) + if obj == nil { + return nil, err + } + return obj.(*securitykubearmorcomv1.KubeArmorClusterPolicy), err +} diff --git a/pkg/KubeArmorController/client/clientset/versioned/typed/security.kubearmor.com/v1/fake/fake_security.kubearmor.com_client.go b/pkg/KubeArmorController/client/clientset/versioned/typed/security.kubearmor.com/v1/fake/fake_security.kubearmor.com_client.go index b8e820b00a..d7b34ca9ef 100644 --- a/pkg/KubeArmorController/client/clientset/versioned/typed/security.kubearmor.com/v1/fake/fake_security.kubearmor.com_client.go +++ b/pkg/KubeArmorController/client/clientset/versioned/typed/security.kubearmor.com/v1/fake/fake_security.kubearmor.com_client.go @@ -15,6 +15,10 @@ type FakeSecurityV1 struct { *testing.Fake } +func (c *FakeSecurityV1) KubeArmorClusterPolicies() v1.KubeArmorClusterPolicyInterface { + return &FakeKubeArmorClusterPolicies{c} +} + func (c *FakeSecurityV1) KubeArmorHostPolicies() v1.KubeArmorHostPolicyInterface { return &FakeKubeArmorHostPolicies{c} } diff --git a/pkg/KubeArmorController/client/clientset/versioned/typed/security.kubearmor.com/v1/generated_expansion.go b/pkg/KubeArmorController/client/clientset/versioned/typed/security.kubearmor.com/v1/generated_expansion.go index cca5fb3f68..6ebcc18002 100644 --- a/pkg/KubeArmorController/client/clientset/versioned/typed/security.kubearmor.com/v1/generated_expansion.go +++ b/pkg/KubeArmorController/client/clientset/versioned/typed/security.kubearmor.com/v1/generated_expansion.go @@ -5,6 +5,8 @@ package v1 +type KubeArmorClusterPolicyExpansion interface{} + type KubeArmorHostPolicyExpansion interface{} type KubeArmorPolicyExpansion interface{} diff --git a/pkg/KubeArmorController/client/clientset/versioned/typed/security.kubearmor.com/v1/kubearmorclusterpolicy.go b/pkg/KubeArmorController/client/clientset/versioned/typed/security.kubearmor.com/v1/kubearmorclusterpolicy.go new file mode 100644 index 0000000000..c163cd6c01 --- /dev/null +++ b/pkg/KubeArmorController/client/clientset/versioned/typed/security.kubearmor.com/v1/kubearmorclusterpolicy.go @@ -0,0 +1,171 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright 2022 Authors of KubeArmor + +// Code generated by client-gen. DO NOT EDIT. + +package v1 + +import ( + "context" + "time" + + v1 "github.com/kubearmor/KubeArmor/pkg/KubeArmorController/api/security.kubearmor.com/v1" + scheme "github.com/kubearmor/KubeArmor/pkg/KubeArmorController/client/clientset/versioned/scheme" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" + rest "k8s.io/client-go/rest" +) + +// KubeArmorClusterPoliciesGetter has a method to return a KubeArmorClusterPolicyInterface. +// A group's client should implement this interface. +type KubeArmorClusterPoliciesGetter interface { + KubeArmorClusterPolicies() KubeArmorClusterPolicyInterface +} + +// KubeArmorClusterPolicyInterface has methods to work with KubeArmorClusterPolicy resources. +type KubeArmorClusterPolicyInterface interface { + Create(ctx context.Context, kubeArmorClusterPolicy *v1.KubeArmorClusterPolicy, opts metav1.CreateOptions) (*v1.KubeArmorClusterPolicy, error) + Update(ctx context.Context, kubeArmorClusterPolicy *v1.KubeArmorClusterPolicy, opts metav1.UpdateOptions) (*v1.KubeArmorClusterPolicy, error) + UpdateStatus(ctx context.Context, kubeArmorClusterPolicy *v1.KubeArmorClusterPolicy, opts metav1.UpdateOptions) (*v1.KubeArmorClusterPolicy, error) + Delete(ctx context.Context, name string, opts metav1.DeleteOptions) error + DeleteCollection(ctx context.Context, opts metav1.DeleteOptions, listOpts metav1.ListOptions) error + Get(ctx context.Context, name string, opts metav1.GetOptions) (*v1.KubeArmorClusterPolicy, error) + List(ctx context.Context, opts metav1.ListOptions) (*v1.KubeArmorClusterPolicyList, error) + Watch(ctx context.Context, opts metav1.ListOptions) (watch.Interface, error) + Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts metav1.PatchOptions, subresources ...string) (result *v1.KubeArmorClusterPolicy, err error) + KubeArmorClusterPolicyExpansion +} + +// kubeArmorClusterPolicies implements KubeArmorClusterPolicyInterface +type kubeArmorClusterPolicies struct { + client rest.Interface +} + +// newKubeArmorClusterPolicies returns a KubeArmorClusterPolicies +func newKubeArmorClusterPolicies(c *SecurityV1Client) *kubeArmorClusterPolicies { + return &kubeArmorClusterPolicies{ + client: c.RESTClient(), + } +} + +// Get takes name of the kubeArmorClusterPolicy, and returns the corresponding kubeArmorClusterPolicy object, and an error if there is any. +func (c *kubeArmorClusterPolicies) Get(ctx context.Context, name string, options metav1.GetOptions) (result *v1.KubeArmorClusterPolicy, err error) { + result = &v1.KubeArmorClusterPolicy{} + err = c.client.Get(). + Resource("kubearmorclusterpolicies"). + Name(name). + VersionedParams(&options, scheme.ParameterCodec). + Do(ctx). + Into(result) + return +} + +// List takes label and field selectors, and returns the list of KubeArmorClusterPolicies that match those selectors. +func (c *kubeArmorClusterPolicies) List(ctx context.Context, opts metav1.ListOptions) (result *v1.KubeArmorClusterPolicyList, err error) { + var timeout time.Duration + if opts.TimeoutSeconds != nil { + timeout = time.Duration(*opts.TimeoutSeconds) * time.Second + } + result = &v1.KubeArmorClusterPolicyList{} + err = c.client.Get(). + Resource("kubearmorclusterpolicies"). + VersionedParams(&opts, scheme.ParameterCodec). + Timeout(timeout). + Do(ctx). + Into(result) + return +} + +// Watch returns a watch.Interface that watches the requested kubeArmorClusterPolicies. +func (c *kubeArmorClusterPolicies) Watch(ctx context.Context, opts metav1.ListOptions) (watch.Interface, error) { + var timeout time.Duration + if opts.TimeoutSeconds != nil { + timeout = time.Duration(*opts.TimeoutSeconds) * time.Second + } + opts.Watch = true + return c.client.Get(). + Resource("kubearmorclusterpolicies"). + VersionedParams(&opts, scheme.ParameterCodec). + Timeout(timeout). + Watch(ctx) +} + +// Create takes the representation of a kubeArmorClusterPolicy and creates it. Returns the server's representation of the kubeArmorClusterPolicy, and an error, if there is any. +func (c *kubeArmorClusterPolicies) Create(ctx context.Context, kubeArmorClusterPolicy *v1.KubeArmorClusterPolicy, opts metav1.CreateOptions) (result *v1.KubeArmorClusterPolicy, err error) { + result = &v1.KubeArmorClusterPolicy{} + err = c.client.Post(). + Resource("kubearmorclusterpolicies"). + VersionedParams(&opts, scheme.ParameterCodec). + Body(kubeArmorClusterPolicy). + Do(ctx). + Into(result) + return +} + +// Update takes the representation of a kubeArmorClusterPolicy and updates it. Returns the server's representation of the kubeArmorClusterPolicy, and an error, if there is any. +func (c *kubeArmorClusterPolicies) Update(ctx context.Context, kubeArmorClusterPolicy *v1.KubeArmorClusterPolicy, opts metav1.UpdateOptions) (result *v1.KubeArmorClusterPolicy, err error) { + result = &v1.KubeArmorClusterPolicy{} + err = c.client.Put(). + Resource("kubearmorclusterpolicies"). + Name(kubeArmorClusterPolicy.Name). + VersionedParams(&opts, scheme.ParameterCodec). + Body(kubeArmorClusterPolicy). + Do(ctx). + Into(result) + return +} + +// UpdateStatus was generated because the type contains a Status member. +// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). +func (c *kubeArmorClusterPolicies) UpdateStatus(ctx context.Context, kubeArmorClusterPolicy *v1.KubeArmorClusterPolicy, opts metav1.UpdateOptions) (result *v1.KubeArmorClusterPolicy, err error) { + result = &v1.KubeArmorClusterPolicy{} + err = c.client.Put(). + Resource("kubearmorclusterpolicies"). + Name(kubeArmorClusterPolicy.Name). + SubResource("status"). + VersionedParams(&opts, scheme.ParameterCodec). + Body(kubeArmorClusterPolicy). + Do(ctx). + Into(result) + return +} + +// Delete takes name of the kubeArmorClusterPolicy and deletes it. Returns an error if one occurs. +func (c *kubeArmorClusterPolicies) Delete(ctx context.Context, name string, opts metav1.DeleteOptions) error { + return c.client.Delete(). + Resource("kubearmorclusterpolicies"). + Name(name). + Body(&opts). + Do(ctx). + Error() +} + +// DeleteCollection deletes a collection of objects. +func (c *kubeArmorClusterPolicies) DeleteCollection(ctx context.Context, opts metav1.DeleteOptions, listOpts metav1.ListOptions) error { + var timeout time.Duration + if listOpts.TimeoutSeconds != nil { + timeout = time.Duration(*listOpts.TimeoutSeconds) * time.Second + } + return c.client.Delete(). + Resource("kubearmorclusterpolicies"). + VersionedParams(&listOpts, scheme.ParameterCodec). + Timeout(timeout). + Body(&opts). + Do(ctx). + Error() +} + +// Patch applies the patch and returns the patched kubeArmorClusterPolicy. +func (c *kubeArmorClusterPolicies) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts metav1.PatchOptions, subresources ...string) (result *v1.KubeArmorClusterPolicy, err error) { + result = &v1.KubeArmorClusterPolicy{} + err = c.client.Patch(pt). + Resource("kubearmorclusterpolicies"). + Name(name). + SubResource(subresources...). + VersionedParams(&opts, scheme.ParameterCodec). + Body(data). + Do(ctx). + Into(result) + return +} diff --git a/pkg/KubeArmorController/client/clientset/versioned/typed/security.kubearmor.com/v1/security.kubearmor.com_client.go b/pkg/KubeArmorController/client/clientset/versioned/typed/security.kubearmor.com/v1/security.kubearmor.com_client.go index 64c6e77040..e8a73add39 100644 --- a/pkg/KubeArmorController/client/clientset/versioned/typed/security.kubearmor.com/v1/security.kubearmor.com_client.go +++ b/pkg/KubeArmorController/client/clientset/versioned/typed/security.kubearmor.com/v1/security.kubearmor.com_client.go @@ -13,6 +13,7 @@ import ( type SecurityV1Interface interface { RESTClient() rest.Interface + KubeArmorClusterPoliciesGetter KubeArmorHostPoliciesGetter KubeArmorPoliciesGetter } @@ -22,6 +23,10 @@ type SecurityV1Client struct { restClient rest.Interface } +func (c *SecurityV1Client) KubeArmorClusterPolicies() KubeArmorClusterPolicyInterface { + return newKubeArmorClusterPolicies(c) +} + func (c *SecurityV1Client) KubeArmorHostPolicies() KubeArmorHostPolicyInterface { return newKubeArmorHostPolicies(c) } diff --git a/pkg/KubeArmorController/client/informers/externalversions/generic.go b/pkg/KubeArmorController/client/informers/externalversions/generic.go index 08f2fa5d64..e4df879505 100644 --- a/pkg/KubeArmorController/client/informers/externalversions/generic.go +++ b/pkg/KubeArmorController/client/informers/externalversions/generic.go @@ -40,6 +40,8 @@ func (f *genericInformer) Lister() cache.GenericLister { func (f *sharedInformerFactory) ForResource(resource schema.GroupVersionResource) (GenericInformer, error) { switch resource { // Group=security.kubearmor.com, Version=v1 + case v1.SchemeGroupVersion.WithResource("kubearmorclusterpolicies"): + return &genericInformer{resource: resource.GroupResource(), informer: f.Security().V1().KubeArmorClusterPolicies().Informer()}, nil case v1.SchemeGroupVersion.WithResource("kubearmorhostpolicies"): return &genericInformer{resource: resource.GroupResource(), informer: f.Security().V1().KubeArmorHostPolicies().Informer()}, nil case v1.SchemeGroupVersion.WithResource("kubearmorpolicies"): diff --git a/pkg/KubeArmorController/client/informers/externalversions/security.kubearmor.com/v1/interface.go b/pkg/KubeArmorController/client/informers/externalversions/security.kubearmor.com/v1/interface.go index eccde71b5b..643f8c7474 100644 --- a/pkg/KubeArmorController/client/informers/externalversions/security.kubearmor.com/v1/interface.go +++ b/pkg/KubeArmorController/client/informers/externalversions/security.kubearmor.com/v1/interface.go @@ -11,6 +11,8 @@ import ( // Interface provides access to all the informers in this group version. type Interface interface { + // KubeArmorClusterPolicies returns a KubeArmorClusterPolicyInformer. + KubeArmorClusterPolicies() KubeArmorClusterPolicyInformer // KubeArmorHostPolicies returns a KubeArmorHostPolicyInformer. KubeArmorHostPolicies() KubeArmorHostPolicyInformer // KubeArmorPolicies returns a KubeArmorPolicyInformer. @@ -28,6 +30,11 @@ func New(f internalinterfaces.SharedInformerFactory, namespace string, tweakList return &version{factory: f, namespace: namespace, tweakListOptions: tweakListOptions} } +// KubeArmorClusterPolicies returns a KubeArmorClusterPolicyInformer. +func (v *version) KubeArmorClusterPolicies() KubeArmorClusterPolicyInformer { + return &kubeArmorClusterPolicyInformer{factory: v.factory, tweakListOptions: v.tweakListOptions} +} + // KubeArmorHostPolicies returns a KubeArmorHostPolicyInformer. func (v *version) KubeArmorHostPolicies() KubeArmorHostPolicyInformer { return &kubeArmorHostPolicyInformer{factory: v.factory, tweakListOptions: v.tweakListOptions} diff --git a/pkg/KubeArmorController/client/informers/externalversions/security.kubearmor.com/v1/kubearmorclusterpolicy.go b/pkg/KubeArmorController/client/informers/externalversions/security.kubearmor.com/v1/kubearmorclusterpolicy.go new file mode 100644 index 0000000000..2f26ed784d --- /dev/null +++ b/pkg/KubeArmorController/client/informers/externalversions/security.kubearmor.com/v1/kubearmorclusterpolicy.go @@ -0,0 +1,76 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright 2022 Authors of KubeArmor + +// Code generated by informer-gen. DO NOT EDIT. + +package v1 + +import ( + "context" + time "time" + + securitykubearmorcomv1 "github.com/kubearmor/KubeArmor/pkg/KubeArmorController/api/security.kubearmor.com/v1" + versioned "github.com/kubearmor/KubeArmor/pkg/KubeArmorController/client/clientset/versioned" + internalinterfaces "github.com/kubearmor/KubeArmor/pkg/KubeArmorController/client/informers/externalversions/internalinterfaces" + v1 "github.com/kubearmor/KubeArmor/pkg/KubeArmorController/client/listers/security.kubearmor.com/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + runtime "k8s.io/apimachinery/pkg/runtime" + watch "k8s.io/apimachinery/pkg/watch" + cache "k8s.io/client-go/tools/cache" +) + +// KubeArmorClusterPolicyInformer provides access to a shared informer and lister for +// KubeArmorClusterPolicies. +type KubeArmorClusterPolicyInformer interface { + Informer() cache.SharedIndexInformer + Lister() v1.KubeArmorClusterPolicyLister +} + +type kubeArmorClusterPolicyInformer struct { + factory internalinterfaces.SharedInformerFactory + tweakListOptions internalinterfaces.TweakListOptionsFunc +} + +// NewKubeArmorClusterPolicyInformer constructs a new informer for KubeArmorClusterPolicy type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewKubeArmorClusterPolicyInformer(client versioned.Interface, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer { + return NewFilteredKubeArmorClusterPolicyInformer(client, resyncPeriod, indexers, nil) +} + +// NewFilteredKubeArmorClusterPolicyInformer constructs a new informer for KubeArmorClusterPolicy type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewFilteredKubeArmorClusterPolicyInformer(client versioned.Interface, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer { + return cache.NewSharedIndexInformer( + &cache.ListWatch{ + ListFunc: func(options metav1.ListOptions) (runtime.Object, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.SecurityV1().KubeArmorClusterPolicies().List(context.TODO(), options) + }, + WatchFunc: func(options metav1.ListOptions) (watch.Interface, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.SecurityV1().KubeArmorClusterPolicies().Watch(context.TODO(), options) + }, + }, + &securitykubearmorcomv1.KubeArmorClusterPolicy{}, + resyncPeriod, + indexers, + ) +} + +func (f *kubeArmorClusterPolicyInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { + return NewFilteredKubeArmorClusterPolicyInformer(client, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions) +} + +func (f *kubeArmorClusterPolicyInformer) Informer() cache.SharedIndexInformer { + return f.factory.InformerFor(&securitykubearmorcomv1.KubeArmorClusterPolicy{}, f.defaultInformer) +} + +func (f *kubeArmorClusterPolicyInformer) Lister() v1.KubeArmorClusterPolicyLister { + return v1.NewKubeArmorClusterPolicyLister(f.Informer().GetIndexer()) +} diff --git a/pkg/KubeArmorController/client/listers/security.kubearmor.com/v1/expansion_generated.go b/pkg/KubeArmorController/client/listers/security.kubearmor.com/v1/expansion_generated.go index c171557e62..998996b4e0 100644 --- a/pkg/KubeArmorController/client/listers/security.kubearmor.com/v1/expansion_generated.go +++ b/pkg/KubeArmorController/client/listers/security.kubearmor.com/v1/expansion_generated.go @@ -5,6 +5,10 @@ package v1 +// KubeArmorClusterPolicyListerExpansion allows custom methods to be added to +// KubeArmorClusterPolicyLister. +type KubeArmorClusterPolicyListerExpansion interface{} + // KubeArmorHostPolicyListerExpansion allows custom methods to be added to // KubeArmorHostPolicyLister. type KubeArmorHostPolicyListerExpansion interface{} diff --git a/pkg/KubeArmorController/client/listers/security.kubearmor.com/v1/kubearmorclusterpolicy.go b/pkg/KubeArmorController/client/listers/security.kubearmor.com/v1/kubearmorclusterpolicy.go new file mode 100644 index 0000000000..b0237b71d0 --- /dev/null +++ b/pkg/KubeArmorController/client/listers/security.kubearmor.com/v1/kubearmorclusterpolicy.go @@ -0,0 +1,55 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright 2022 Authors of KubeArmor + +// Code generated by lister-gen. DO NOT EDIT. + +package v1 + +import ( + v1 "github.com/kubearmor/KubeArmor/pkg/KubeArmorController/api/security.kubearmor.com/v1" + "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/client-go/tools/cache" +) + +// KubeArmorClusterPolicyLister helps list KubeArmorClusterPolicies. +// All objects returned here must be treated as read-only. +type KubeArmorClusterPolicyLister interface { + // List lists all KubeArmorClusterPolicies in the indexer. + // Objects returned here must be treated as read-only. + List(selector labels.Selector) (ret []*v1.KubeArmorClusterPolicy, err error) + // Get retrieves the KubeArmorClusterPolicy from the index for a given name. + // Objects returned here must be treated as read-only. + Get(name string) (*v1.KubeArmorClusterPolicy, error) + KubeArmorClusterPolicyListerExpansion +} + +// kubeArmorClusterPolicyLister implements the KubeArmorClusterPolicyLister interface. +type kubeArmorClusterPolicyLister struct { + indexer cache.Indexer +} + +// NewKubeArmorClusterPolicyLister returns a new KubeArmorClusterPolicyLister. +func NewKubeArmorClusterPolicyLister(indexer cache.Indexer) KubeArmorClusterPolicyLister { + return &kubeArmorClusterPolicyLister{indexer: indexer} +} + +// List lists all KubeArmorClusterPolicies in the indexer. +func (s *kubeArmorClusterPolicyLister) List(selector labels.Selector) (ret []*v1.KubeArmorClusterPolicy, err error) { + err = cache.ListAll(s.indexer, selector, func(m interface{}) { + ret = append(ret, m.(*v1.KubeArmorClusterPolicy)) + }) + return ret, err +} + +// Get retrieves the KubeArmorClusterPolicy from the index for a given name. +func (s *kubeArmorClusterPolicyLister) Get(name string) (*v1.KubeArmorClusterPolicy, error) { + obj, exists, err := s.indexer.GetByKey(name) + if err != nil { + return nil, err + } + if !exists { + return nil, errors.NewNotFound(v1.Resource("kubearmorclusterpolicy"), name) + } + return obj.(*v1.KubeArmorClusterPolicy), nil +} diff --git a/pkg/KubeArmorController/config/crd/bases/security.kubearmor.com_kubearmorclusterpolicies.yaml b/pkg/KubeArmorController/config/crd/bases/security.kubearmor.com_kubearmorclusterpolicies.yaml new file mode 100644 index 0000000000..75bfcced26 --- /dev/null +++ b/pkg/KubeArmorController/config/crd/bases/security.kubearmor.com_kubearmorclusterpolicies.yaml @@ -0,0 +1,1196 @@ + +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.4.1 + creationTimestamp: null + name: kubearmorclusterpolicies.security.kubearmor.com +spec: + group: security.kubearmor.com + names: + kind: KubeArmorClusterPolicy + listKind: KubeArmorClusterPolicyList + plural: kubearmorclusterpolicies + shortNames: + - csp + singular: kubearmorclusterpolicy + scope: Cluster + versions: + - additionalPrinterColumns: + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + - jsonPath: .spec.action + name: Action + priority: 10 + type: string + - jsonPath: .spec.selector.matchExpressions + name: Selector + priority: 10 + type: string + name: v1 + schema: + openAPIV3Schema: + description: KubeArmorClusterPolicy is the Schema for the kubearmorclusterpolicies + API + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: KubeArmorClusterPolicySpec defines the desired state of KubeArmorClusterPolicy + properties: + action: + enum: + - Allow + - Audit + - Block + type: string + apparmor: + type: string + capabilities: + properties: + action: + enum: + - Allow + - Audit + - Block + type: string + matchCapabilities: + items: + properties: + action: + enum: + - Allow + - Audit + - Block + type: string + capability: + pattern: (chown|dac_override|dac_read_search|fowner|fsetid|kill|setgid|setuid|setpcap|linux_immutable|net_bind_service|net_broadcast|net_admin|net_raw|ipc_lock|ipc_owner|sys_module|sys_rawio|sys_chroot|sys_ptrace|sys_pacct|sys_admin|sys_boot|sys_nice|sys_resource|sys_time|sys_tty_config|mknod|lease|audit_write|audit_control|setfcap|mac_override|mac_admin)$ + type: string + fromSource: + items: + properties: + path: + pattern: ^\/+.*[^\/]$ + type: string + type: object + type: array + message: + type: string + severity: + maximum: 10 + minimum: 1 + type: integer + tags: + items: + type: string + type: array + required: + - capability + type: object + type: array + message: + type: string + severity: + maximum: 10 + minimum: 1 + type: integer + tags: + items: + type: string + type: array + type: object + file: + properties: + action: + enum: + - Allow + - Audit + - Block + type: string + matchDirectories: + items: + properties: + action: + enum: + - Allow + - Audit + - Block + type: string + dir: + pattern: ^\/$|^\/.*\/$ + type: string + fromSource: + items: + properties: + path: + pattern: ^\/+.*[^\/]$ + type: string + type: object + type: array + message: + type: string + ownerOnly: + type: boolean + readOnly: + type: boolean + recursive: + type: boolean + severity: + maximum: 10 + minimum: 1 + type: integer + tags: + items: + type: string + type: array + required: + - dir + type: object + type: array + matchPaths: + items: + properties: + action: + enum: + - Allow + - Audit + - Block + type: string + fromSource: + items: + properties: + path: + pattern: ^\/+.*[^\/]$ + type: string + type: object + type: array + message: + type: string + ownerOnly: + type: boolean + path: + pattern: ^\/+.*[^\/]$ + type: string + readOnly: + type: boolean + severity: + maximum: 10 + minimum: 1 + type: integer + tags: + items: + type: string + type: array + required: + - path + type: object + type: array + matchPatterns: + items: + properties: + action: + enum: + - Allow + - Audit + - Block + type: string + message: + type: string + ownerOnly: + type: boolean + pattern: + type: string + readOnly: + type: boolean + severity: + maximum: 10 + minimum: 1 + type: integer + tags: + items: + type: string + type: array + required: + - pattern + type: object + type: array + message: + type: string + severity: + maximum: 10 + minimum: 1 + type: integer + tags: + items: + type: string + type: array + type: object + message: + type: string + network: + properties: + action: + enum: + - Allow + - Audit + - Block + type: string + matchProtocols: + items: + properties: + action: + enum: + - Allow + - Audit + - Block + type: string + fromSource: + items: + properties: + path: + pattern: ^\/+.*[^\/]$ + type: string + type: object + type: array + message: + type: string + protocol: + pattern: (icmp|ICMP|tcp|TCP|udp|UDP|raw|RAW)$ + type: string + severity: + maximum: 10 + minimum: 1 + type: integer + tags: + items: + type: string + type: array + required: + - protocol + type: object + type: array + message: + type: string + severity: + maximum: 10 + minimum: 1 + type: integer + tags: + items: + type: string + type: array + type: object + process: + properties: + action: + enum: + - Allow + - Audit + - Block + type: string + matchDirectories: + items: + properties: + action: + enum: + - Allow + - Audit + - Block + type: string + dir: + pattern: ^\/$|^\/.*\/$ + type: string + fromSource: + items: + properties: + path: + pattern: ^\/+.*[^\/]$ + type: string + type: object + type: array + message: + type: string + ownerOnly: + type: boolean + recursive: + type: boolean + severity: + maximum: 10 + minimum: 1 + type: integer + tags: + items: + type: string + type: array + required: + - dir + type: object + type: array + matchPaths: + items: + properties: + action: + enum: + - Allow + - Audit + - Block + type: string + execname: + pattern: ^[^\/]+$ + type: string + fromSource: + items: + properties: + path: + pattern: ^\/+.*[^\/]$ + type: string + type: object + type: array + message: + type: string + ownerOnly: + type: boolean + path: + pattern: ^\/+.*[^\/]$ + type: string + severity: + maximum: 10 + minimum: 1 + type: integer + tags: + items: + type: string + type: array + type: object + type: array + matchPatterns: + items: + properties: + action: + enum: + - Allow + - Audit + - Block + type: string + message: + type: string + ownerOnly: + type: boolean + pattern: + type: string + severity: + maximum: 10 + minimum: 1 + type: integer + tags: + items: + type: string + type: array + required: + - pattern + type: object + type: array + message: + type: string + severity: + maximum: 10 + minimum: 1 + type: integer + tags: + items: + type: string + type: array + type: object + selector: + properties: + matchExpressions: + items: + properties: + key: + enum: + - namespace + type: string + operator: + enum: + - In + - NotIn + type: string + values: + items: + type: string + type: array + type: object + type: array + type: object + severity: + maximum: 10 + minimum: 1 + type: integer + syscalls: + properties: + matchPaths: + items: + properties: + fromSource: + items: + properties: + dir: + type: string + path: + pattern: ^\/+.*[^\/]$ + type: string + recursive: + type: boolean + type: object + type: array + path: + pattern: (^\/+.*[^\/]$)|(^\/$|^\/.*\/$) + type: string + recursive: + type: boolean + syscall: + items: + enum: + - read + - write + - open + - close + - stat + - fstat + - lstat + - poll + - lseek + - mmap + - mprotect + - munmap + - brk + - rt_sigaction + - rt_sigprocmask + - rt_sigreturn + - ioctl + - pread64 + - pwrite64 + - readv + - writev + - access + - pipe + - select + - sched_yield + - mremap + - msync + - mincore + - madvise + - shmget + - shmat + - shmctl + - dup + - dup2 + - pause + - nanosleep + - getitimer + - alarm + - setitimer + - getpid + - sendfile + - socket + - connect + - accept + - sendto + - recvfrom + - sendmsg + - recvmsg + - shutdown + - bind + - listen + - getsockname + - getpeername + - socketpair + - setsockopt + - getsockopt + - clone + - fork + - vfork + - execve + - exit + - wait4 + - kill + - uname + - semget + - semop + - semctl + - shmdt + - msgget + - msgsnd + - msgrcv + - msgctl + - fcntl + - flock + - fsync + - fdatasync + - truncate + - ftruncate + - getdents + - getcwd + - chdir + - fchdir + - rename + - mkdir + - rmdir + - creat + - link + - unlink + - symlink + - readlink + - chmod + - fchmod + - chown + - fchown + - lchown + - umask + - gettimeofday + - getrlimit + - getrusage + - sysinfo + - times + - ptrace + - getuid + - syslog + - getgid + - setuid + - setgid + - geteuid + - getegid + - setpgid + - getppid + - getpgrp + - setsid + - setreuid + - setregid + - getgroups + - setgroups + - setresuid + - getresuid + - setresgid + - getresgid + - getpgid + - setfsuid + - setfsgid + - getsid + - capget + - capset + - rt_sigpending + - rt_sigtimedwait + - rt_sigqueueinfo + - rt_sigsuspend + - sigaltstack + - utime + - mknod + - uselib + - personality + - ustat + - statfs + - fstatfs + - sysfs + - getpriority + - setpriority + - sched_setparam + - sched_getparam + - sched_setscheduler + - sched_getscheduler + - sched_get_priority_max + - sched_get_priority_min + - sched_rr_get_interval + - mlock + - munlock + - mlockall + - munlockall + - vhangup + - modify_ldt + - pivot_root + - _sysctl + - prctl + - arch_prctl + - adjtimex + - setrlimit + - chroot + - sync + - acct + - settimeofday + - mount + - umount2 + - swapon + - swapoff + - reboot + - sethostname + - setdomainname + - iopl + - ioperm + - create_module + - init_module + - delete_module + - get_kernel_syms + - query_module + - quotactl + - nfsservctl + - getpmsg + - putpmsg + - afs_syscall + - tuxcall + - security + - gettid + - readahead + - setxattr + - lsetxattr + - fsetxattr + - getxattr + - lgetxattr + - fgetxattr + - listxattr + - llistxattr + - flistxattr + - removexattr + - lremovexattr + - fremovexattr + - tkill + - time + - futex + - sched_setaffinity + - sched_getaffinity + - set_thread_area + - io_setup + - io_destroy + - io_getevents + - io_submit + - io_cancel + - get_thread_area + - lookup_dcookie + - epoll_create + - epoll_ctl_old + - epoll_wait_old + - remap_file_pages + - getdents64 + - set_tid_address + - restart_syscall + - semtimedop + - fadvise64 + - timer_create + - timer_settime + - timer_gettime + - timer_getoverrun + - timer_delete + - clock_settime + - clock_gettime + - clock_getres + - clock_nanosleep + - exit_group + - epoll_wait + - epoll_ctl + - tgkill + - utimes + - vserver + - mbind + - set_mempolicy + - get_mempolicy + - mq_open + - mq_unlink + - mq_timedsend + - mq_timedreceive + - mq_notify + - mq_getsetattr + - kexec_load + - waitid + - add_key + - request_key + - keyctl + - ioprio_set + - ioprio_get + - inotify_init + - inotify_add_watch + - inotify_rm_watch + - migrate_pages + - openat + - mkdirat + - mknodat + - fchownat + - futimesat + - newfstatat + - unlinkat + - renameat + - linkat + - symlinkat + - readlinkat + - fchmodat + - faccessat + - pselect6 + - ppoll + - unshare + - set_robust_list + - get_robust_list + - splice + - tee + - sync_file_range + - vmsplice + - move_pages + - utimensat + - epoll_pwait + - signalfd + - timerfd_create + - eventfd + - fallocate + - timerfd_settime + - timerfd_gettime + - accept4 + - signalfd4 + - eventfd2 + - epoll_create1 + - dup3 + - pipe2 + - inotify_init1 + - preadv + - pwritev + - rt_tgsigqueueinfo + - perf_event_open + - recvmmsg + - fanotify_init + - fanotify_mark + - prlimit64 + - name_to_handle_at + - open_by_handle_at + - clock_adjtime + - syncfs + - sendmmsg + - setns + - getcpu + - process_vm_readv + - process_vm_writev + - kcmp + - finit_module + - sched_setattr + - sched_getattr + - renameat2 + - seccomp + - getrandom + - memfd_create + - kexec_file_load + - bpf + - execveat + - userfaultfd + - membarrier + - mlock2 + - copy_file_range + - preadv2 + - pwritev2 + - pkey_mprotect + - pkey_alloc + - pkey_free + - statx + - io_pgetevents + - rseq + type: string + type: array + type: object + type: array + matchSyscalls: + items: + properties: + fromSource: + items: + properties: + dir: + type: string + path: + pattern: ^\/+.*[^\/]$ + type: string + recursive: + type: boolean + type: object + type: array + syscall: + items: + enum: + - read + - write + - open + - close + - stat + - fstat + - lstat + - poll + - lseek + - mmap + - mprotect + - munmap + - brk + - rt_sigaction + - rt_sigprocmask + - rt_sigreturn + - ioctl + - pread64 + - pwrite64 + - readv + - writev + - access + - pipe + - select + - sched_yield + - mremap + - msync + - mincore + - madvise + - shmget + - shmat + - shmctl + - dup + - dup2 + - pause + - nanosleep + - getitimer + - alarm + - setitimer + - getpid + - sendfile + - socket + - connect + - accept + - sendto + - recvfrom + - sendmsg + - recvmsg + - shutdown + - bind + - listen + - getsockname + - getpeername + - socketpair + - setsockopt + - getsockopt + - clone + - fork + - vfork + - execve + - exit + - wait4 + - kill + - uname + - semget + - semop + - semctl + - shmdt + - msgget + - msgsnd + - msgrcv + - msgctl + - fcntl + - flock + - fsync + - fdatasync + - truncate + - ftruncate + - getdents + - getcwd + - chdir + - fchdir + - rename + - mkdir + - rmdir + - creat + - link + - unlink + - symlink + - readlink + - chmod + - fchmod + - chown + - fchown + - lchown + - umask + - gettimeofday + - getrlimit + - getrusage + - sysinfo + - times + - ptrace + - getuid + - syslog + - getgid + - setuid + - setgid + - geteuid + - getegid + - setpgid + - getppid + - getpgrp + - setsid + - setreuid + - setregid + - getgroups + - setgroups + - setresuid + - getresuid + - setresgid + - getresgid + - getpgid + - setfsuid + - setfsgid + - getsid + - capget + - capset + - rt_sigpending + - rt_sigtimedwait + - rt_sigqueueinfo + - rt_sigsuspend + - sigaltstack + - utime + - mknod + - uselib + - personality + - ustat + - statfs + - fstatfs + - sysfs + - getpriority + - setpriority + - sched_setparam + - sched_getparam + - sched_setscheduler + - sched_getscheduler + - sched_get_priority_max + - sched_get_priority_min + - sched_rr_get_interval + - mlock + - munlock + - mlockall + - munlockall + - vhangup + - modify_ldt + - pivot_root + - _sysctl + - prctl + - arch_prctl + - adjtimex + - setrlimit + - chroot + - sync + - acct + - settimeofday + - mount + - umount2 + - swapon + - swapoff + - reboot + - sethostname + - setdomainname + - iopl + - ioperm + - create_module + - init_module + - delete_module + - get_kernel_syms + - query_module + - quotactl + - nfsservctl + - getpmsg + - putpmsg + - afs_syscall + - tuxcall + - security + - gettid + - readahead + - setxattr + - lsetxattr + - fsetxattr + - getxattr + - lgetxattr + - fgetxattr + - listxattr + - llistxattr + - flistxattr + - removexattr + - lremovexattr + - fremovexattr + - tkill + - time + - futex + - sched_setaffinity + - sched_getaffinity + - set_thread_area + - io_setup + - io_destroy + - io_getevents + - io_submit + - io_cancel + - get_thread_area + - lookup_dcookie + - epoll_create + - epoll_ctl_old + - epoll_wait_old + - remap_file_pages + - getdents64 + - set_tid_address + - restart_syscall + - semtimedop + - fadvise64 + - timer_create + - timer_settime + - timer_gettime + - timer_getoverrun + - timer_delete + - clock_settime + - clock_gettime + - clock_getres + - clock_nanosleep + - exit_group + - epoll_wait + - epoll_ctl + - tgkill + - utimes + - vserver + - mbind + - set_mempolicy + - get_mempolicy + - mq_open + - mq_unlink + - mq_timedsend + - mq_timedreceive + - mq_notify + - mq_getsetattr + - kexec_load + - waitid + - add_key + - request_key + - keyctl + - ioprio_set + - ioprio_get + - inotify_init + - inotify_add_watch + - inotify_rm_watch + - migrate_pages + - openat + - mkdirat + - mknodat + - fchownat + - futimesat + - newfstatat + - unlinkat + - renameat + - linkat + - symlinkat + - readlinkat + - fchmodat + - faccessat + - pselect6 + - ppoll + - unshare + - set_robust_list + - get_robust_list + - splice + - tee + - sync_file_range + - vmsplice + - move_pages + - utimensat + - epoll_pwait + - signalfd + - timerfd_create + - eventfd + - fallocate + - timerfd_settime + - timerfd_gettime + - accept4 + - signalfd4 + - eventfd2 + - epoll_create1 + - dup3 + - pipe2 + - inotify_init1 + - preadv + - pwritev + - rt_tgsigqueueinfo + - perf_event_open + - recvmmsg + - fanotify_init + - fanotify_mark + - prlimit64 + - name_to_handle_at + - open_by_handle_at + - clock_adjtime + - syncfs + - sendmmsg + - setns + - getcpu + - process_vm_readv + - process_vm_writev + - kcmp + - finit_module + - sched_setattr + - sched_getattr + - renameat2 + - seccomp + - getrandom + - memfd_create + - kexec_file_load + - bpf + - execveat + - userfaultfd + - membarrier + - mlock2 + - copy_file_range + - preadv2 + - pwritev2 + - pkey_mprotect + - pkey_alloc + - pkey_free + - statx + - io_pgetevents + - rseq + type: string + type: array + type: object + type: array + message: + type: string + severity: + maximum: 10 + minimum: 1 + type: integer + tags: + items: + type: string + type: array + type: object + tags: + items: + type: string + type: array + type: object + status: + description: KubeArmorClusterPolicyStatus defines the observed state of + KubeArmorCLusterPolicy + properties: + status: + type: string + type: object + type: object + served: true + storage: true + subresources: + status: {} +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] diff --git a/pkg/KubeArmorController/config/rbac/kubearmorpolicy_editor_role.yaml b/pkg/KubeArmorController/config/rbac/kubearmorpolicy_editor_role.yaml index 8bef5dde12..5adf72d04e 100644 --- a/pkg/KubeArmorController/config/rbac/kubearmorpolicy_editor_role.yaml +++ b/pkg/KubeArmorController/config/rbac/kubearmorpolicy_editor_role.yaml @@ -1,4 +1,4 @@ -# permissions for end users to edit kubearmorpolicies. +# permissions for end users to edit kubearmorpolicies and kubearmorclusterpolicies apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: @@ -8,6 +8,7 @@ rules: - security.kubearmor.com resources: - kubearmorpolicies + - kubearmorclusterpolicies verbs: - create - delete @@ -20,5 +21,6 @@ rules: - security.kubearmor.com resources: - kubearmorpolicies/status + - kubearmorclusterpolicies/status verbs: - get diff --git a/pkg/KubeArmorController/config/rbac/kubearmorpolicy_viewer_role.yaml b/pkg/KubeArmorController/config/rbac/kubearmorpolicy_viewer_role.yaml index 3c10218373..2a0608e474 100644 --- a/pkg/KubeArmorController/config/rbac/kubearmorpolicy_viewer_role.yaml +++ b/pkg/KubeArmorController/config/rbac/kubearmorpolicy_viewer_role.yaml @@ -1,4 +1,4 @@ -# permissions for end users to view kubearmorpolicies. +# permissions for end users to view kubearmorpolicies and kubearmorclusterpolicies apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: @@ -8,6 +8,7 @@ rules: - security.kubearmor.com resources: - kubearmorpolicies + - kubearmorclusterpolicies verbs: - get - list @@ -16,5 +17,6 @@ rules: - security.kubearmor.com resources: - kubearmorpolicies/status + - kubearmorclusterpolicies/status verbs: - get diff --git a/pkg/KubeArmorController/config/rbac/role.yaml b/pkg/KubeArmorController/config/rbac/role.yaml index fe35fc556f..2dfb1f17c6 100644 --- a/pkg/KubeArmorController/config/rbac/role.yaml +++ b/pkg/KubeArmorController/config/rbac/role.yaml @@ -17,6 +17,26 @@ rules: - list - update - watch +- apiGroups: + - security.kubearmor.com + resources: + - kubearmorclusterpolicies + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - security.kubearmor.com + resources: + - kubearmorclusterpolicies/status + verbs: + - get + - patch + - update - apiGroups: - security.kubearmor.com resources: diff --git a/pkg/KubeArmorController/controllers/kubearmorclusterpolicy_controller.go b/pkg/KubeArmorController/controllers/kubearmorclusterpolicy_controller.go new file mode 100644 index 0000000000..67bdef101d --- /dev/null +++ b/pkg/KubeArmorController/controllers/kubearmorclusterpolicy_controller.go @@ -0,0 +1,36 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright 2024 Authors of KubeArmor + +package controllers + +import ( + "context" + + "github.com/go-logr/logr" + ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/client" + + securityv1 "github.com/kubearmor/KubeArmor/pkg/KubeArmorController/api/security.kubearmor.com/v1" + "k8s.io/apimachinery/pkg/runtime" +) + +// KubeArmorClusterPolicyReconciler reconciles a KubeArmorClusterPolicy object +type KubeArmorClusterPolicyReconciler struct { + client.Client + Log logr.Logger + Scheme *runtime.Scheme +} + +// +kubebuilder:rbac:groups=security.kubearmor.com,resources=kubearmorclusterpolicies,verbs=get;list;watch;create;update;patch;delete +// +kubebuilder:rbac:groups=security.kubearmor.com,resources=kubearmorclusterpolicies/status,verbs=get;update;patch + +func (r *KubeArmorClusterPolicyReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { + + return ctrl.Result{}, nil +} + +func (r *KubeArmorClusterPolicyReconciler) SetupWithManager(mgr ctrl.Manager) error { + return ctrl.NewControllerManagedBy(mgr). + For(&securityv1.KubeArmorClusterPolicy{}). + Complete(r) +} diff --git a/pkg/KubeArmorController/crd/KubeArmorClusterPolicy.yaml b/pkg/KubeArmorController/crd/KubeArmorClusterPolicy.yaml new file mode 100644 index 0000000000..75bfcced26 --- /dev/null +++ b/pkg/KubeArmorController/crd/KubeArmorClusterPolicy.yaml @@ -0,0 +1,1196 @@ + +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.4.1 + creationTimestamp: null + name: kubearmorclusterpolicies.security.kubearmor.com +spec: + group: security.kubearmor.com + names: + kind: KubeArmorClusterPolicy + listKind: KubeArmorClusterPolicyList + plural: kubearmorclusterpolicies + shortNames: + - csp + singular: kubearmorclusterpolicy + scope: Cluster + versions: + - additionalPrinterColumns: + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + - jsonPath: .spec.action + name: Action + priority: 10 + type: string + - jsonPath: .spec.selector.matchExpressions + name: Selector + priority: 10 + type: string + name: v1 + schema: + openAPIV3Schema: + description: KubeArmorClusterPolicy is the Schema for the kubearmorclusterpolicies + API + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: KubeArmorClusterPolicySpec defines the desired state of KubeArmorClusterPolicy + properties: + action: + enum: + - Allow + - Audit + - Block + type: string + apparmor: + type: string + capabilities: + properties: + action: + enum: + - Allow + - Audit + - Block + type: string + matchCapabilities: + items: + properties: + action: + enum: + - Allow + - Audit + - Block + type: string + capability: + pattern: (chown|dac_override|dac_read_search|fowner|fsetid|kill|setgid|setuid|setpcap|linux_immutable|net_bind_service|net_broadcast|net_admin|net_raw|ipc_lock|ipc_owner|sys_module|sys_rawio|sys_chroot|sys_ptrace|sys_pacct|sys_admin|sys_boot|sys_nice|sys_resource|sys_time|sys_tty_config|mknod|lease|audit_write|audit_control|setfcap|mac_override|mac_admin)$ + type: string + fromSource: + items: + properties: + path: + pattern: ^\/+.*[^\/]$ + type: string + type: object + type: array + message: + type: string + severity: + maximum: 10 + minimum: 1 + type: integer + tags: + items: + type: string + type: array + required: + - capability + type: object + type: array + message: + type: string + severity: + maximum: 10 + minimum: 1 + type: integer + tags: + items: + type: string + type: array + type: object + file: + properties: + action: + enum: + - Allow + - Audit + - Block + type: string + matchDirectories: + items: + properties: + action: + enum: + - Allow + - Audit + - Block + type: string + dir: + pattern: ^\/$|^\/.*\/$ + type: string + fromSource: + items: + properties: + path: + pattern: ^\/+.*[^\/]$ + type: string + type: object + type: array + message: + type: string + ownerOnly: + type: boolean + readOnly: + type: boolean + recursive: + type: boolean + severity: + maximum: 10 + minimum: 1 + type: integer + tags: + items: + type: string + type: array + required: + - dir + type: object + type: array + matchPaths: + items: + properties: + action: + enum: + - Allow + - Audit + - Block + type: string + fromSource: + items: + properties: + path: + pattern: ^\/+.*[^\/]$ + type: string + type: object + type: array + message: + type: string + ownerOnly: + type: boolean + path: + pattern: ^\/+.*[^\/]$ + type: string + readOnly: + type: boolean + severity: + maximum: 10 + minimum: 1 + type: integer + tags: + items: + type: string + type: array + required: + - path + type: object + type: array + matchPatterns: + items: + properties: + action: + enum: + - Allow + - Audit + - Block + type: string + message: + type: string + ownerOnly: + type: boolean + pattern: + type: string + readOnly: + type: boolean + severity: + maximum: 10 + minimum: 1 + type: integer + tags: + items: + type: string + type: array + required: + - pattern + type: object + type: array + message: + type: string + severity: + maximum: 10 + minimum: 1 + type: integer + tags: + items: + type: string + type: array + type: object + message: + type: string + network: + properties: + action: + enum: + - Allow + - Audit + - Block + type: string + matchProtocols: + items: + properties: + action: + enum: + - Allow + - Audit + - Block + type: string + fromSource: + items: + properties: + path: + pattern: ^\/+.*[^\/]$ + type: string + type: object + type: array + message: + type: string + protocol: + pattern: (icmp|ICMP|tcp|TCP|udp|UDP|raw|RAW)$ + type: string + severity: + maximum: 10 + minimum: 1 + type: integer + tags: + items: + type: string + type: array + required: + - protocol + type: object + type: array + message: + type: string + severity: + maximum: 10 + minimum: 1 + type: integer + tags: + items: + type: string + type: array + type: object + process: + properties: + action: + enum: + - Allow + - Audit + - Block + type: string + matchDirectories: + items: + properties: + action: + enum: + - Allow + - Audit + - Block + type: string + dir: + pattern: ^\/$|^\/.*\/$ + type: string + fromSource: + items: + properties: + path: + pattern: ^\/+.*[^\/]$ + type: string + type: object + type: array + message: + type: string + ownerOnly: + type: boolean + recursive: + type: boolean + severity: + maximum: 10 + minimum: 1 + type: integer + tags: + items: + type: string + type: array + required: + - dir + type: object + type: array + matchPaths: + items: + properties: + action: + enum: + - Allow + - Audit + - Block + type: string + execname: + pattern: ^[^\/]+$ + type: string + fromSource: + items: + properties: + path: + pattern: ^\/+.*[^\/]$ + type: string + type: object + type: array + message: + type: string + ownerOnly: + type: boolean + path: + pattern: ^\/+.*[^\/]$ + type: string + severity: + maximum: 10 + minimum: 1 + type: integer + tags: + items: + type: string + type: array + type: object + type: array + matchPatterns: + items: + properties: + action: + enum: + - Allow + - Audit + - Block + type: string + message: + type: string + ownerOnly: + type: boolean + pattern: + type: string + severity: + maximum: 10 + minimum: 1 + type: integer + tags: + items: + type: string + type: array + required: + - pattern + type: object + type: array + message: + type: string + severity: + maximum: 10 + minimum: 1 + type: integer + tags: + items: + type: string + type: array + type: object + selector: + properties: + matchExpressions: + items: + properties: + key: + enum: + - namespace + type: string + operator: + enum: + - In + - NotIn + type: string + values: + items: + type: string + type: array + type: object + type: array + type: object + severity: + maximum: 10 + minimum: 1 + type: integer + syscalls: + properties: + matchPaths: + items: + properties: + fromSource: + items: + properties: + dir: + type: string + path: + pattern: ^\/+.*[^\/]$ + type: string + recursive: + type: boolean + type: object + type: array + path: + pattern: (^\/+.*[^\/]$)|(^\/$|^\/.*\/$) + type: string + recursive: + type: boolean + syscall: + items: + enum: + - read + - write + - open + - close + - stat + - fstat + - lstat + - poll + - lseek + - mmap + - mprotect + - munmap + - brk + - rt_sigaction + - rt_sigprocmask + - rt_sigreturn + - ioctl + - pread64 + - pwrite64 + - readv + - writev + - access + - pipe + - select + - sched_yield + - mremap + - msync + - mincore + - madvise + - shmget + - shmat + - shmctl + - dup + - dup2 + - pause + - nanosleep + - getitimer + - alarm + - setitimer + - getpid + - sendfile + - socket + - connect + - accept + - sendto + - recvfrom + - sendmsg + - recvmsg + - shutdown + - bind + - listen + - getsockname + - getpeername + - socketpair + - setsockopt + - getsockopt + - clone + - fork + - vfork + - execve + - exit + - wait4 + - kill + - uname + - semget + - semop + - semctl + - shmdt + - msgget + - msgsnd + - msgrcv + - msgctl + - fcntl + - flock + - fsync + - fdatasync + - truncate + - ftruncate + - getdents + - getcwd + - chdir + - fchdir + - rename + - mkdir + - rmdir + - creat + - link + - unlink + - symlink + - readlink + - chmod + - fchmod + - chown + - fchown + - lchown + - umask + - gettimeofday + - getrlimit + - getrusage + - sysinfo + - times + - ptrace + - getuid + - syslog + - getgid + - setuid + - setgid + - geteuid + - getegid + - setpgid + - getppid + - getpgrp + - setsid + - setreuid + - setregid + - getgroups + - setgroups + - setresuid + - getresuid + - setresgid + - getresgid + - getpgid + - setfsuid + - setfsgid + - getsid + - capget + - capset + - rt_sigpending + - rt_sigtimedwait + - rt_sigqueueinfo + - rt_sigsuspend + - sigaltstack + - utime + - mknod + - uselib + - personality + - ustat + - statfs + - fstatfs + - sysfs + - getpriority + - setpriority + - sched_setparam + - sched_getparam + - sched_setscheduler + - sched_getscheduler + - sched_get_priority_max + - sched_get_priority_min + - sched_rr_get_interval + - mlock + - munlock + - mlockall + - munlockall + - vhangup + - modify_ldt + - pivot_root + - _sysctl + - prctl + - arch_prctl + - adjtimex + - setrlimit + - chroot + - sync + - acct + - settimeofday + - mount + - umount2 + - swapon + - swapoff + - reboot + - sethostname + - setdomainname + - iopl + - ioperm + - create_module + - init_module + - delete_module + - get_kernel_syms + - query_module + - quotactl + - nfsservctl + - getpmsg + - putpmsg + - afs_syscall + - tuxcall + - security + - gettid + - readahead + - setxattr + - lsetxattr + - fsetxattr + - getxattr + - lgetxattr + - fgetxattr + - listxattr + - llistxattr + - flistxattr + - removexattr + - lremovexattr + - fremovexattr + - tkill + - time + - futex + - sched_setaffinity + - sched_getaffinity + - set_thread_area + - io_setup + - io_destroy + - io_getevents + - io_submit + - io_cancel + - get_thread_area + - lookup_dcookie + - epoll_create + - epoll_ctl_old + - epoll_wait_old + - remap_file_pages + - getdents64 + - set_tid_address + - restart_syscall + - semtimedop + - fadvise64 + - timer_create + - timer_settime + - timer_gettime + - timer_getoverrun + - timer_delete + - clock_settime + - clock_gettime + - clock_getres + - clock_nanosleep + - exit_group + - epoll_wait + - epoll_ctl + - tgkill + - utimes + - vserver + - mbind + - set_mempolicy + - get_mempolicy + - mq_open + - mq_unlink + - mq_timedsend + - mq_timedreceive + - mq_notify + - mq_getsetattr + - kexec_load + - waitid + - add_key + - request_key + - keyctl + - ioprio_set + - ioprio_get + - inotify_init + - inotify_add_watch + - inotify_rm_watch + - migrate_pages + - openat + - mkdirat + - mknodat + - fchownat + - futimesat + - newfstatat + - unlinkat + - renameat + - linkat + - symlinkat + - readlinkat + - fchmodat + - faccessat + - pselect6 + - ppoll + - unshare + - set_robust_list + - get_robust_list + - splice + - tee + - sync_file_range + - vmsplice + - move_pages + - utimensat + - epoll_pwait + - signalfd + - timerfd_create + - eventfd + - fallocate + - timerfd_settime + - timerfd_gettime + - accept4 + - signalfd4 + - eventfd2 + - epoll_create1 + - dup3 + - pipe2 + - inotify_init1 + - preadv + - pwritev + - rt_tgsigqueueinfo + - perf_event_open + - recvmmsg + - fanotify_init + - fanotify_mark + - prlimit64 + - name_to_handle_at + - open_by_handle_at + - clock_adjtime + - syncfs + - sendmmsg + - setns + - getcpu + - process_vm_readv + - process_vm_writev + - kcmp + - finit_module + - sched_setattr + - sched_getattr + - renameat2 + - seccomp + - getrandom + - memfd_create + - kexec_file_load + - bpf + - execveat + - userfaultfd + - membarrier + - mlock2 + - copy_file_range + - preadv2 + - pwritev2 + - pkey_mprotect + - pkey_alloc + - pkey_free + - statx + - io_pgetevents + - rseq + type: string + type: array + type: object + type: array + matchSyscalls: + items: + properties: + fromSource: + items: + properties: + dir: + type: string + path: + pattern: ^\/+.*[^\/]$ + type: string + recursive: + type: boolean + type: object + type: array + syscall: + items: + enum: + - read + - write + - open + - close + - stat + - fstat + - lstat + - poll + - lseek + - mmap + - mprotect + - munmap + - brk + - rt_sigaction + - rt_sigprocmask + - rt_sigreturn + - ioctl + - pread64 + - pwrite64 + - readv + - writev + - access + - pipe + - select + - sched_yield + - mremap + - msync + - mincore + - madvise + - shmget + - shmat + - shmctl + - dup + - dup2 + - pause + - nanosleep + - getitimer + - alarm + - setitimer + - getpid + - sendfile + - socket + - connect + - accept + - sendto + - recvfrom + - sendmsg + - recvmsg + - shutdown + - bind + - listen + - getsockname + - getpeername + - socketpair + - setsockopt + - getsockopt + - clone + - fork + - vfork + - execve + - exit + - wait4 + - kill + - uname + - semget + - semop + - semctl + - shmdt + - msgget + - msgsnd + - msgrcv + - msgctl + - fcntl + - flock + - fsync + - fdatasync + - truncate + - ftruncate + - getdents + - getcwd + - chdir + - fchdir + - rename + - mkdir + - rmdir + - creat + - link + - unlink + - symlink + - readlink + - chmod + - fchmod + - chown + - fchown + - lchown + - umask + - gettimeofday + - getrlimit + - getrusage + - sysinfo + - times + - ptrace + - getuid + - syslog + - getgid + - setuid + - setgid + - geteuid + - getegid + - setpgid + - getppid + - getpgrp + - setsid + - setreuid + - setregid + - getgroups + - setgroups + - setresuid + - getresuid + - setresgid + - getresgid + - getpgid + - setfsuid + - setfsgid + - getsid + - capget + - capset + - rt_sigpending + - rt_sigtimedwait + - rt_sigqueueinfo + - rt_sigsuspend + - sigaltstack + - utime + - mknod + - uselib + - personality + - ustat + - statfs + - fstatfs + - sysfs + - getpriority + - setpriority + - sched_setparam + - sched_getparam + - sched_setscheduler + - sched_getscheduler + - sched_get_priority_max + - sched_get_priority_min + - sched_rr_get_interval + - mlock + - munlock + - mlockall + - munlockall + - vhangup + - modify_ldt + - pivot_root + - _sysctl + - prctl + - arch_prctl + - adjtimex + - setrlimit + - chroot + - sync + - acct + - settimeofday + - mount + - umount2 + - swapon + - swapoff + - reboot + - sethostname + - setdomainname + - iopl + - ioperm + - create_module + - init_module + - delete_module + - get_kernel_syms + - query_module + - quotactl + - nfsservctl + - getpmsg + - putpmsg + - afs_syscall + - tuxcall + - security + - gettid + - readahead + - setxattr + - lsetxattr + - fsetxattr + - getxattr + - lgetxattr + - fgetxattr + - listxattr + - llistxattr + - flistxattr + - removexattr + - lremovexattr + - fremovexattr + - tkill + - time + - futex + - sched_setaffinity + - sched_getaffinity + - set_thread_area + - io_setup + - io_destroy + - io_getevents + - io_submit + - io_cancel + - get_thread_area + - lookup_dcookie + - epoll_create + - epoll_ctl_old + - epoll_wait_old + - remap_file_pages + - getdents64 + - set_tid_address + - restart_syscall + - semtimedop + - fadvise64 + - timer_create + - timer_settime + - timer_gettime + - timer_getoverrun + - timer_delete + - clock_settime + - clock_gettime + - clock_getres + - clock_nanosleep + - exit_group + - epoll_wait + - epoll_ctl + - tgkill + - utimes + - vserver + - mbind + - set_mempolicy + - get_mempolicy + - mq_open + - mq_unlink + - mq_timedsend + - mq_timedreceive + - mq_notify + - mq_getsetattr + - kexec_load + - waitid + - add_key + - request_key + - keyctl + - ioprio_set + - ioprio_get + - inotify_init + - inotify_add_watch + - inotify_rm_watch + - migrate_pages + - openat + - mkdirat + - mknodat + - fchownat + - futimesat + - newfstatat + - unlinkat + - renameat + - linkat + - symlinkat + - readlinkat + - fchmodat + - faccessat + - pselect6 + - ppoll + - unshare + - set_robust_list + - get_robust_list + - splice + - tee + - sync_file_range + - vmsplice + - move_pages + - utimensat + - epoll_pwait + - signalfd + - timerfd_create + - eventfd + - fallocate + - timerfd_settime + - timerfd_gettime + - accept4 + - signalfd4 + - eventfd2 + - epoll_create1 + - dup3 + - pipe2 + - inotify_init1 + - preadv + - pwritev + - rt_tgsigqueueinfo + - perf_event_open + - recvmmsg + - fanotify_init + - fanotify_mark + - prlimit64 + - name_to_handle_at + - open_by_handle_at + - clock_adjtime + - syncfs + - sendmmsg + - setns + - getcpu + - process_vm_readv + - process_vm_writev + - kcmp + - finit_module + - sched_setattr + - sched_getattr + - renameat2 + - seccomp + - getrandom + - memfd_create + - kexec_file_load + - bpf + - execveat + - userfaultfd + - membarrier + - mlock2 + - copy_file_range + - preadv2 + - pwritev2 + - pkey_mprotect + - pkey_alloc + - pkey_free + - statx + - io_pgetevents + - rseq + type: string + type: array + type: object + type: array + message: + type: string + severity: + maximum: 10 + minimum: 1 + type: integer + tags: + items: + type: string + type: array + type: object + tags: + items: + type: string + type: array + type: object + status: + description: KubeArmorClusterPolicyStatus defines the observed state of + KubeArmorCLusterPolicy + properties: + status: + type: string + type: object + type: object + served: true + storage: true + subresources: + status: {} +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] diff --git a/pkg/KubeArmorController/crd/crd.go b/pkg/KubeArmorController/crd/crd.go index a43cd578b4..2a47d71cf7 100644 --- a/pkg/KubeArmorController/crd/crd.go +++ b/pkg/KubeArmorController/crd/crd.go @@ -18,6 +18,9 @@ var kspCrdBytes []byte //go:embed KubeArmorHostPolicy.yaml var hspCrdBytes []byte +//go:embed KubeArmorClusterPolicy.yaml +var cspCrdBytes []byte + // GetCRD returns the generated CRD. The CRD is generated by controller-gen // which is embedded at compile time using go:embed. func GetKspCRD() apiextensionsv1.CustomResourceDefinition { @@ -37,3 +40,12 @@ func GetHspCRD() apiextensionsv1.CustomResourceDefinition { } return hsp } + +func GetCspCRD() apiextensionsv1.CustomResourceDefinition { + csp := apiextensionsv1.CustomResourceDefinition{} + err := yaml.Unmarshal(cspCrdBytes, &csp) + if err != nil { + log.Fatal("Error unmarshalling pregenerated CRD") + } + return csp +} diff --git a/pkg/KubeArmorController/main.go b/pkg/KubeArmorController/main.go index 2fe01b17fa..a72fcf1d53 100644 --- a/pkg/KubeArmorController/main.go +++ b/pkg/KubeArmorController/main.go @@ -131,6 +131,16 @@ func main() { os.Exit(1) } + setupLog.Info("Adding KubeArmor Cluster policy controller") + if err = (&controllers.KubeArmorClusterPolicyReconciler{ + Client: mgr.GetClient(), + Log: ctrl.Log.WithName("controllers").WithName("KubeArmorClusterPolicy"), + Scheme: mgr.GetScheme(), + }).SetupWithManager(mgr); err != nil { + setupLog.Error(err, "unable to create controller", "controller", "KubeArmorClusterPolicy") + os.Exit(1) + } + //+kubebuilder:scaffold:builder setupLog.Info("starting manager") diff --git a/pkg/KubeArmorOperator/config/crd/bases/operator.kubearmor.com_kubearmorconfigs.yaml b/pkg/KubeArmorOperator/config/crd/bases/operator.kubearmor.com_kubearmorconfigs.yaml index f1dac2062b..1e1c4434ec 100644 --- a/pkg/KubeArmorOperator/config/crd/bases/operator.kubearmor.com_kubearmorconfigs.yaml +++ b/pkg/KubeArmorOperator/config/crd/bases/operator.kubearmor.com_kubearmorconfigs.yaml @@ -1,9 +1,11 @@ + --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.4.1 + creationTimestamp: null name: kubearmorconfigs.operator.kubearmor.com spec: group: operator.kubearmor.com @@ -24,19 +26,14 @@ spec: description: KubeArmorConfig is the Schema for the KubeArmorConfigs API properties: apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' type: string kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' type: string metadata: type: object @@ -160,9 +157,9 @@ spec: message: type: string phase: - description: |- - INSERT ADDITIONAL STATUS FIELD - define observed state of cluster - Important: Run "make" to regenerate code after modifying this file + description: 'INSERT ADDITIONAL STATUS FIELD - define observed state + of cluster Important: Run "make" to regenerate code after modifying + this file' type: string type: object type: object @@ -170,3 +167,9 @@ spec: storage: true subresources: status: {} +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] diff --git a/pkg/KubeArmorOperator/config/rbac/clusterrole.yaml b/pkg/KubeArmorOperator/config/rbac/clusterrole.yaml index 5a6a99e91e..7d91fe7466 100644 --- a/pkg/KubeArmorOperator/config/rbac/clusterrole.yaml +++ b/pkg/KubeArmorOperator/config/rbac/clusterrole.yaml @@ -138,6 +138,7 @@ rules: - security.kubearmor.com resources: - kubearmorpolicies + - kubearmorclusterpolicies - kubearmorhostpolicies verbs: - get @@ -173,6 +174,7 @@ rules: - security.kubearmor.com resources: - kubearmorpolicies + - kubearmorclusterpolicies - kubearmorhostpolicies verbs: - create @@ -186,6 +188,7 @@ rules: - security.kubearmor.com resources: - kubearmorpolicies/status + - kubearmorclusterpolicies/status - kubearmorhostpolicies/status verbs: - get diff --git a/pkg/KubeArmorOperator/internal/controller/resources.go b/pkg/KubeArmorOperator/internal/controller/resources.go index 6f342190d4..dca58b2f50 100644 --- a/pkg/KubeArmorOperator/internal/controller/resources.go +++ b/pkg/KubeArmorOperator/internal/controller/resources.go @@ -533,6 +533,14 @@ func (clusterWatcher *ClusterWatcher) WatchRequiredResources() { clusterWatcher.Log.Warnf("Cannot install Hsp CRD, error=%s", err.Error()) } } + csp := crds.GetCspCRD() + csp = addOwnership(csp).(extv1.CustomResourceDefinition) + if _, err := clusterWatcher.ExtClient.ApiextensionsV1().CustomResourceDefinitions().Create(context.Background(), &csp, metav1.CreateOptions{}); err != nil && !metav1errors.IsAlreadyExists(err) { + if !isAlreadyExists(err) { + installErr = err + clusterWatcher.Log.Warnf("Cannot install Csp CRD, error=%s", err.Error()) + } + } // kubearmor-controller and relay-server deployments controller := deployments.GetKubeArmorControllerDeployment(common.Namespace) relayServer := deployments.GetRelayDeployment(common.Namespace) diff --git a/tests/k8s_env/csp/csp_suite_test.go b/tests/k8s_env/csp/csp_suite_test.go new file mode 100644 index 0000000000..ddf87503b8 --- /dev/null +++ b/tests/k8s_env/csp/csp_suite_test.go @@ -0,0 +1,16 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright 2024 Authors of KubeArmor + +package csp_test + +import ( + "testing" + + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" +) + +func TestCsp(t *testing.T) { + RegisterFailHandler(Fail) + RunSpecs(t, "Csp Suite") +} diff --git a/tests/k8s_env/csp/csp_test.go b/tests/k8s_env/csp/csp_test.go new file mode 100644 index 0000000000..fb68ea1048 --- /dev/null +++ b/tests/k8s_env/csp/csp_test.go @@ -0,0 +1,293 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright 2024 Authors of KubeArmor + +package csp + +import ( + "time" + + "github.com/kubearmor/KubeArmor/protobuf" + . "github.com/kubearmor/KubeArmor/tests/util" + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" +) + +var _ = BeforeSuite(func() { + // install nginx deployment in nginx1 ns + err := K8sApply([]string{"res/nginx-nginx1-deployment.yaml"}) + Expect(err).To(BeNil()) + + // install nginx deployment in nginx2 ns + err = K8sApply([]string{"res/nginx-nginx2-deployment.yaml"}) + Expect(err).To(BeNil()) + + // delete all CSPs + err = DeleteAllCsp() + Expect(err).To(BeNil()) +}) + +var _ = AfterSuite(func() { + // Delete nginx deployment in nginx1 ns + err := K8sDelete([]string{"res/nginx-nginx1-deployment.yaml"}) + Expect(err).To(BeNil()) + + // Delete nginx deployment in nginx2 ns + err = K8sDelete([]string{"res/nginx-nginx2-deployment.yaml"}) + Expect(err).To(BeNil()) + + // Delete nginx-later-deploy deployment in nginx1 ns + err = K8sDelete([]string{"res/nginx-later-nginx1-deployment.yaml"}) + Expect(err).To(BeNil()) +}) + +func getNginxPod(name, namespace, ant string) string { + pods, err := K8sGetPods(name, namespace, []string{ant}, 60) + Expect(err).To(BeNil()) + Expect(len(pods)).To(Equal(1)) + return pods[0] +} + +var _ = Describe("csp", func() { + var n1 string + var n2 string + + BeforeEach(func() { + n1 = getNginxPod("nginx1-", "nginx1", "kubearmor-policy: enabled") + n2 = getNginxPod("nginx2-", "nginx2", "kubearmor-policy: enabled") + }) + + AfterEach(func() { + KarmorLogStop() + err := DeleteAllCsp() + Expect(err).To(BeNil()) + // wait for policy deletion + time.Sleep(5 * time.Second) + }) + + Describe("Policy Apply", func() { + It("can block execution of pkg mgmt tools apt, In operator", func() { + // Apply policy + err := K8sApplyFile("res/csp-in-operator-block-process.yaml") + Expect(err).To(BeNil()) + + // cluster_policy_test_1 + + // Test 1 - should block apt for ns nginx1 + // Start Kubearmor Logs + err = KarmorLogStart("policy", "nginx1", "Process", n1) + Expect(err).To(BeNil()) + + // wait for policy creation + time.Sleep(5 * time.Second) + + AssertCommand(n1, "nginx1", []string{"bash", "-c", "apt"}, + MatchRegexp("apt.*Permission denied"), true, + ) + + expect := protobuf.Alert{ + PolicyName: "csp-in-operator-block-process", + Severity: "8", + Action: "Block", + Result: "Permission denied", + } + + res, err := KarmorGetTargetAlert(5*time.Second, &expect) + Expect(err).To(BeNil()) + Expect(res.Found).To(BeTrue()) + + // Test 2 - should not block apt for ns nginx2 + // Start Kubearmor Logs + err = KarmorLogStart("system", "nginx2", "Process", n2) + Expect(err).To(BeNil()) + + AssertCommand(n2, "nginx2", []string{"bash", "-c", "apt"}, + MatchRegexp(".*"), true, + ) + + expectedLog := protobuf.Log{ + Result: "Passed", + Resource: "/usr/bin/apt", + } + + res, err = KarmorGetTargetLogs(5*time.Second, &expectedLog) + Expect(err).To(BeNil()) + Expect(res.Found).To(BeTrue()) + + // Test 3 - should block apt for ns nginx1 (deployment is added after applying the cluster policy) + + // install nginx-later deployment in nginx1 ns + err = K8sApply([]string{"res/nginx-later-nginx1-deployment.yaml"}) + Expect(err).To(BeNil()) + + nl := getNginxPod("nginx-later-deploy", "nginx-later", "kubearmor-policy: enabled") + + // Start Kubearmor Logs + err = KarmorLogStart("policy", "nginx-later", "Process", nl) + Expect(err).To(BeNil()) + + AssertCommand(nl, "nginx-later", []string{"bash", "-c", "apt"}, + MatchRegexp("apt.*Permission denied"), true, + ) + + expect = protobuf.Alert{ + PolicyName: "csp-in-operator-block-process", + Severity: "8", + Action: "Block", + Result: "Permission denied", + } + + res, err = KarmorGetTargetAlert(5*time.Second, &expect) + Expect(err).To(BeNil()) + Expect(res.Found).To(BeTrue()) + }) + + It("can block execution of access to file, In operator", func() { + // Apply policy + err := K8sApplyFile("res/csp-in-operator-block-file-access.yaml") + Expect(err).To(BeNil()) + + // cluster_policy_test_2 + + // Test 1 - should block file access for ns nginx2 + // Start Kubearmor Logs + err = KarmorLogStart("policy", "nginx2", "File", n2) + Expect(err).To(BeNil()) + + // wait for policy creation + time.Sleep(5 * time.Second) + + AssertCommand(n2, "nginx2", []string{"bash", "-c", "cat /etc/host.conf"}, + MatchRegexp("host.conf.*Permission denied"), true, + ) + + expect := protobuf.Alert{ + PolicyName: "csp-in-operator-block-file-access", + Severity: "8", + Action: "Block", + Result: "Permission denied", + } + + res, err := KarmorGetTargetAlert(5*time.Second, &expect) + Expect(err).To(BeNil()) + Expect(res.Found).To(BeTrue()) + + // Test 2 - should not block file access for ns nginx1 + // Start Kubearmor Logs + err = KarmorLogStart("system", "nginx1", "File", n1) + Expect(err).To(BeNil()) + + AssertCommand(n1, "nginx1", []string{"bash", "-c", "cat /etc/host.conf"}, + ContainSubstring("multi on"), true, + ) + + expectedLog := protobuf.Log{ + Result: "Passed", + Source: "/usr/bin/cat /etc/host.conf", + } + + res, err = KarmorGetTargetLogs(5*time.Second, &expectedLog) + Expect(err).To(BeNil()) + Expect(res.Found).To(BeTrue()) + }) + + It("can block execution of pkg mgmt tools apt, NotIn operator", func() { + // Apply policy + err := K8sApplyFile("res/csp-not-in-operator-block-process.yaml") + Expect(err).To(BeNil()) + + // cluster_policy_test_3 + + // Test 1 - should block apt in other then nginx1 ns + // Start Kubearmor Logs + err = KarmorLogStart("policy", "nginx2", "Process", n2) + Expect(err).To(BeNil()) + + // wait for policy creation + time.Sleep(5 * time.Second) + + AssertCommand(n2, "nginx2", []string{"bash", "-c", "apt"}, + MatchRegexp("apt.*Permission denied"), true, + ) + + expect := protobuf.Alert{ + PolicyName: "csp-not-in-operator-block-process", + Severity: "8", + Action: "Block", + Result: "Permission denied", + } + + res, err := KarmorGetTargetAlert(5*time.Second, &expect) + Expect(err).To(BeNil()) + Expect(res.Found).To(BeTrue()) + + // Test 2 - should not block apt for ns nginx1 + // Start Kubearmor Logs + err = KarmorLogStart("system", "nginx1", "Process", n1) + Expect(err).To(BeNil()) + + AssertCommand(n1, "nginx1", []string{"bash", "-c", "apt"}, + MatchRegexp(".*"), false, + ) + + expectedLog := protobuf.Log{ + Result: "Passed", + Resource: "/usr/bin/apt", + } + + res, err = KarmorGetTargetLogs(5*time.Second, &expectedLog) + Expect(err).To(BeNil()) + Expect(res.Found).To(BeTrue()) + }) + + It("can block execution of access to file, NotIn operator", func() { + // Apply policy + err := K8sApplyFile("res/csp-not-in-operator-block-file-access.yaml") + Expect(err).To(BeNil()) + + // cluster_policy_test_4 + + // Test 1 - should block file access for ns nginx1 + // Start Kubearmor Logs + err = KarmorLogStart("policy", "nginx1", "File", n1) + Expect(err).To(BeNil()) + + // wait for policy creation + time.Sleep(5 * time.Second) + + AssertCommand(n1, "nginx1", []string{"bash", "-c", "cat /etc/host.conf"}, + MatchRegexp("host.conf.*Permission denied"), true, + ) + + expect := protobuf.Alert{ + PolicyName: "csp-not-in-operator-block-file-access", + Severity: "8", + Action: "Block", + Result: "Permission denied", + } + + res, err := KarmorGetTargetAlert(5*time.Second, &expect) + Expect(err).To(BeNil()) + Expect(res.Found).To(BeTrue()) + + // Test 2 - should not block file access for ns nginx2 + // Start Kubearmor Logs + err = KarmorLogStart("system", "nginx2", "File", n2) + Expect(err).To(BeNil()) + + AssertCommand(n2, "nginx2", []string{"bash", "-c", "cat /etc/host.conf"}, + ContainSubstring("multi on"), false, + ) + + expectedLog := protobuf.Log{ + Result: "Passed", + Source: "/usr/bin/cat /etc/host.conf", + } + + res, err = KarmorGetTargetLogs(5*time.Second, &expectedLog) + Expect(err).To(BeNil()) + Expect(res.Found).To(BeTrue()) + }) + + }) + +}) diff --git a/tests/k8s_env/csp/res/csp-in-operator-block-file-access.yaml b/tests/k8s_env/csp/res/csp-in-operator-block-file-access.yaml new file mode 100644 index 0000000000..8be63d0295 --- /dev/null +++ b/tests/k8s_env/csp/res/csp-in-operator-block-file-access.yaml @@ -0,0 +1,19 @@ +apiVersion: security.kubearmor.com/v1 +kind: KubeArmorClusterPolicy +metadata: + name: csp-in-operator-block-file-access +spec: + severity: 8 + selector: + matchExpressions: + - key: namespace + operator: In + values: + - nginx2 + file: + matchPaths: + - path: /etc/host.conf + fromSource: + - path: /usr/bin/cat + action: + Block diff --git a/tests/k8s_env/csp/res/csp-in-operator-block-process.yaml b/tests/k8s_env/csp/res/csp-in-operator-block-process.yaml new file mode 100644 index 0000000000..dd51dffa14 --- /dev/null +++ b/tests/k8s_env/csp/res/csp-in-operator-block-process.yaml @@ -0,0 +1,18 @@ +apiVersion: security.kubearmor.com/v1 +kind: KubeArmorClusterPolicy +metadata: + name: csp-in-operator-block-process +spec: + severity: 8 + selector: + matchExpressions: + - key: namespace + operator: In + values: + - nginx1 + - nginx-later + process: + matchPaths: + - path: /usr/bin/apt + action: + Block diff --git a/tests/k8s_env/csp/res/csp-not-in-operator-block-file-access.yaml b/tests/k8s_env/csp/res/csp-not-in-operator-block-file-access.yaml new file mode 100644 index 0000000000..e7c35efb3b --- /dev/null +++ b/tests/k8s_env/csp/res/csp-not-in-operator-block-file-access.yaml @@ -0,0 +1,19 @@ +apiVersion: security.kubearmor.com/v1 +kind: KubeArmorClusterPolicy +metadata: + name: csp-not-in-operator-block-file-access +spec: + severity: 8 + selector: + matchExpressions: + - key: namespace + operator: NotIn + values: + - nginx2 + file: + matchPaths: + - path: /etc/host.conf + fromSource: + - path: /usr/bin/cat + action: + Block diff --git a/tests/k8s_env/csp/res/csp-not-in-operator-block-process.yaml b/tests/k8s_env/csp/res/csp-not-in-operator-block-process.yaml new file mode 100644 index 0000000000..1b73f76eb0 --- /dev/null +++ b/tests/k8s_env/csp/res/csp-not-in-operator-block-process.yaml @@ -0,0 +1,17 @@ +apiVersion: security.kubearmor.com/v1 +kind: KubeArmorClusterPolicy +metadata: + name: csp-not-in-operator-block-process +spec: + severity: 8 + selector: + matchExpressions: + - key: namespace + operator: NotIn + values: + - nginx1 + process: + matchPaths: + - path: /usr/bin/apt + action: + Block diff --git a/tests/k8s_env/csp/res/nginx-later-nginx1-deployment.yaml b/tests/k8s_env/csp/res/nginx-later-nginx1-deployment.yaml new file mode 100644 index 0000000000..651d326410 --- /dev/null +++ b/tests/k8s_env/csp/res/nginx-later-nginx1-deployment.yaml @@ -0,0 +1,30 @@ +apiVersion: v1 +kind: Namespace +metadata: + name: nginx-later +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: nginx-later-deploy + namespace: nginx-later + labels: + app: nginx + deployment: nginx-later +spec: + replicas: 1 + selector: + matchLabels: + app: nginx + deployment: nginx-later + template: + metadata: + labels: + app: nginx + deployment: nginx-later + spec: + containers: + - name: nginx + image: nginx + ports: + - containerPort: 80 diff --git a/tests/k8s_env/csp/res/nginx-nginx1-deployment.yaml b/tests/k8s_env/csp/res/nginx-nginx1-deployment.yaml new file mode 100644 index 0000000000..aec5c5bd13 --- /dev/null +++ b/tests/k8s_env/csp/res/nginx-nginx1-deployment.yaml @@ -0,0 +1,30 @@ +apiVersion: v1 +kind: Namespace +metadata: + name: nginx1 +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: nginx1 + namespace: nginx1 + labels: + app: nginx + deployment: nginx-1 +spec: + replicas: 1 + selector: + matchLabels: + app: nginx + deployment: nginx-1 + template: + metadata: + labels: + app: nginx + deployment: nginx-1 + spec: + containers: + - name: nginx + image: nginx + ports: + - containerPort: 80 diff --git a/tests/k8s_env/csp/res/nginx-nginx2-deployment.yaml b/tests/k8s_env/csp/res/nginx-nginx2-deployment.yaml new file mode 100644 index 0000000000..c5e622a71e --- /dev/null +++ b/tests/k8s_env/csp/res/nginx-nginx2-deployment.yaml @@ -0,0 +1,30 @@ +apiVersion: v1 +kind: Namespace +metadata: + name: nginx2 +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: nginx2 + namespace: nginx2 + labels: + app: nginx + deployment: nginx-2 +spec: + replicas: 1 + selector: + matchLabels: + app: nginx + deployment: nginx-2 + template: + metadata: + labels: + app: nginx + deployment: nginx-2 + spec: + containers: + - name: nginx + image: nginx + ports: + - containerPort: 80 diff --git a/tests/util/karmorlog.go b/tests/util/karmorlog.go index 8188c4613d..3a3de3b929 100644 --- a/tests/util/karmorlog.go +++ b/tests/util/karmorlog.go @@ -159,6 +159,7 @@ func KarmorGetTargetAlert(timeout time.Duration, target *pb.Alert) (EventResult, } else if evtin.Type != "Log" { log.Errorf("UNKNOWN EVT type %s", evtin.Type) } + fmt.Println(res.Alerts) if getAlertWithInfo(&alert, target) { log.Printf("Found Target Alert") diff --git a/tests/util/kartutil.go b/tests/util/kartutil.go index 467c10fa58..5c3c1d599a 100644 --- a/tests/util/kartutil.go +++ b/tests/util/kartutil.go @@ -426,6 +426,26 @@ func DeleteAllHsp() error { return nil } +// DeleteAllCsp delete all the kubearmorclusterpolicies +func DeleteAllCsp() error { + csp, err := k8sClient.KSPClientset.KubeArmorClusterPolicies().List(context.TODO(), metav1.ListOptions{}) + if err != nil { + if strings.Contains(err.Error(), "No resource found") { + log.Printf("err %v", err) + } + return err + } + for _, k := range csp.Items { + err = k8sClient.KSPClientset.KubeArmorClusterPolicies().Delete(context.TODO(), k.Name, metav1.DeleteOptions{}) + if err != nil { + log.Errorf("error deleting csp %s", k.Name) + return err + } + log.Printf("deleted csp %s ", k.Name) + } + return nil +} + // DeleteAllKsp delete all the kubearmorpolicies from all namespaces func DeleteAllKsp() error { namespaces, err := k8sClient.K8sClientset.CoreV1().Namespaces().List(context.TODO(), metav1.ListOptions{}) @@ -520,6 +540,25 @@ func K8sApplyFile(fileName string) error { return err } log.Printf("Created policy %q", result.GetObjectMeta().GetName()) + case *kcV1.KubeArmorClusterPolicy: + csp := obj + + csp.Spec.Capabilities = kcV1.CapabilitiesType{ + MatchCapabilities: append([]kcV1.MatchCapabilitiesType{}, csp.Spec.Capabilities.MatchCapabilities...), + } + csp.Spec.Network = kcV1.NetworkType{ + MatchProtocols: append([]kcV1.MatchNetworkProtocolType{}, csp.Spec.Network.MatchProtocols...), + } + + result, err := k8sClient.KSPClientset.KubeArmorClusterPolicies().Create(context.TODO(), csp, metav1.CreateOptions{}) + if err != nil { + if strings.Contains(err.Error(), "already exists") { + log.Printf("Policy %s already exists ...", csp.Name) + continue + } + return err + } + log.Printf("Created policy %q", result.GetObjectMeta().GetName()) case *corev1.Service: svc := obj ns := svc.Namespace