Files
kubescape/scapepkg/exceptions/exceptionprocessor.go
2021-09-05 17:29:53 +03:00

137 lines
4.2 KiB
Go

package exceptions
import (
"github.com/armosec/kubescape/cautils/k8sinterface"
"github.com/armosec/kubescape/cautils/armotypes"
"github.com/armosec/kubescape/cautils/opapolicy"
"k8s.io/apimachinery/pkg/labels"
)
func ListRuleExceptions(exceptionPolicies []armotypes.PostureExceptionPolicy, frameworkName, controlName, ruleName string) []armotypes.PostureExceptionPolicy {
ruleExceptions := []armotypes.PostureExceptionPolicy{}
for i := range exceptionPolicies {
if ruleHasExceptions(&exceptionPolicies[i], frameworkName, controlName, ruleName) {
ruleExceptions = append(ruleExceptions, exceptionPolicies[i])
}
}
return ruleExceptions
}
func ruleHasExceptions(exceptionPolicy *armotypes.PostureExceptionPolicy, frameworkName, controlName, ruleName string) bool {
for _, posturePolicy := range exceptionPolicy.PosturePolicies {
if posturePolicy.FrameworkName == "" && posturePolicy.ControlName == "" && posturePolicy.RuleName == "" {
continue // empty policy -> ignore
}
if posturePolicy.FrameworkName != "" && posturePolicy.FrameworkName != frameworkName {
continue // policy does not match
}
if posturePolicy.ControlName != "" && posturePolicy.ControlName != controlName {
continue // policy does not match
}
if posturePolicy.RuleName != "" && posturePolicy.RuleName != ruleName {
continue // policy does not match
}
return true // policies match
}
return false
}
func AddExceptionsToRuleResponses(results []opapolicy.RuleResponse, ruleExceptions []armotypes.PostureExceptionPolicy) {
if len(ruleExceptions) == 0 {
return
}
for i := range results {
workloads := alertObjectToWorkloads(&results[i].AlertObject)
if len(workloads) == 0 {
continue
}
for w := range workloads {
if exception := getException(ruleExceptions, workloads[w]); exception != nil {
results[i].Exception = exception
}
}
results[i].RuleStatus = results[i].GetSingleResultStatus()
}
}
func alertObjectToWorkloads(obj *opapolicy.AlertObject) []k8sinterface.IWorkload {
resource := []k8sinterface.IWorkload{}
for i := range obj.K8SApiObjects {
r := k8sinterface.NewWorkloadObj(obj.K8SApiObjects[i])
if r == nil {
continue
}
resource = append(resource, r)
}
return resource
}
func getException(ruleExceptions []armotypes.PostureExceptionPolicy, workload k8sinterface.IWorkload) *armotypes.PostureExceptionPolicy {
for e := range ruleExceptions {
for _, resource := range ruleExceptions[e].Resources {
if hasException(&resource, workload) {
return &ruleExceptions[e] // TODO - return disable exception out of all exceptions
}
}
}
return nil
}
// compareMetadata - compare namespace and kind
func hasException(designator *armotypes.PortalDesignator, workload k8sinterface.IWorkload) bool {
cluster, namespace, kind, name, labels := designator.DigestPortalDesignator()
if cluster == "" && namespace == "" && kind == "" && name == "" && len(labels) == 0 {
return false // if designators are empty
}
// if cluster != "" && cluster != ClusterName { // TODO - where do we receive cluster name from?
// return false // cluster name does not match
// }
if namespace != "" && !compareNamespace(workload, namespace) {
return false // namespaces do not match
}
if kind != "" && !compareKind(workload, kind) {
return false // kinds do not match
}
if name != "" && !compareName(workload, name) {
return false // names do not match
}
if len(labels) > 0 && !compareLabels(workload, labels) {
return false // labels do not match
}
return true // no mismatch found -> the workload has an exception
}
func compareNamespace(workload k8sinterface.IWorkload, namespace string) bool {
if workload.GetKind() == "Namespace" {
return namespace == workload.GetName()
}
return namespace == workload.GetNamespace()
}
func compareKind(workload k8sinterface.IWorkload, kind string) bool {
return kind == workload.GetKind()
}
func compareName(workload k8sinterface.IWorkload, name string) bool {
return name == workload.GetName()
}
func compareLabels(workload k8sinterface.IWorkload, attributes map[string]string) bool {
workloadLabels := labels.Set(workload.GetLabels())
designators := labels.Set(attributes).AsSelector()
return designators.Matches(workloadLabels)
}