From 2f12c3879dc7995e693ae7639942985490f95e7e Mon Sep 17 00:00:00 2001 From: YiscahLevySilas1 Date: Tue, 2 Jan 2024 14:35:01 +0200 Subject: [PATCH 1/2] deprecate-old-rules Signed-off-by: YiscahLevySilas1 --- .../access-container-service-account/raw.rego | 333 ------------------ .../rule.metadata.json | 69 ---- rules/exec-into-container/raw.rego | 138 -------- rules/exec-into-container/rule.metadata.json | 33 -- rules/exposed-sensitive-interfaces/raw.rego | 113 ------ .../rule.metadata.json | 66 ---- rules/rule-access-dashboard/raw.rego | 119 ------- .../rule-access-dashboard/rule.metadata.json | 27 -- rules/rule-can-delete-k8s-events/raw.rego | 137 ------- .../rule.metadata.json | 33 -- .../raw.rego | 139 -------- .../rule.metadata.json | 33 -- rules/rule-can-list-get-secrets/raw.rego | 143 -------- .../rule.metadata.json | 33 -- rules/rule-can-portforward/raw.rego | 131 ------- rules/rule-can-portforward/rule.metadata.json | 32 -- rules/rule-can-ssh-to-pod/raw.rego | 104 ------ rules/rule-can-ssh-to-pod/rule.metadata.json | 52 --- rules/rule-can-update-configmap/raw.rego | 170 --------- .../rule.metadata.json | 34 -- rules/rule-excessive-delete-rights/raw.rego | 171 --------- .../rule.metadata.json | 29 -- rules/rule-list-all-cluster-admins/raw.rego | 132 ------- .../rule.metadata.json | 33 -- 24 files changed, 2304 deletions(-) delete mode 100644 rules/access-container-service-account/raw.rego delete mode 100644 rules/access-container-service-account/rule.metadata.json delete mode 100644 rules/exec-into-container/raw.rego delete mode 100644 rules/exec-into-container/rule.metadata.json delete mode 100644 rules/exposed-sensitive-interfaces/raw.rego delete mode 100644 rules/exposed-sensitive-interfaces/rule.metadata.json delete mode 100644 rules/rule-access-dashboard/raw.rego delete mode 100644 rules/rule-access-dashboard/rule.metadata.json delete mode 100644 rules/rule-can-delete-k8s-events/raw.rego delete mode 100644 rules/rule-can-delete-k8s-events/rule.metadata.json delete mode 100644 rules/rule-can-impersonate-users-groups/raw.rego delete mode 100644 rules/rule-can-impersonate-users-groups/rule.metadata.json delete mode 100644 rules/rule-can-list-get-secrets/raw.rego delete mode 100644 rules/rule-can-list-get-secrets/rule.metadata.json delete mode 100644 rules/rule-can-portforward/raw.rego delete mode 100644 rules/rule-can-portforward/rule.metadata.json delete mode 100644 rules/rule-can-ssh-to-pod/raw.rego delete mode 100644 rules/rule-can-ssh-to-pod/rule.metadata.json delete mode 100644 rules/rule-can-update-configmap/raw.rego delete mode 100644 rules/rule-can-update-configmap/rule.metadata.json delete mode 100644 rules/rule-excessive-delete-rights/raw.rego delete mode 100644 rules/rule-excessive-delete-rights/rule.metadata.json delete mode 100644 rules/rule-list-all-cluster-admins/raw.rego delete mode 100644 rules/rule-list-all-cluster-admins/rule.metadata.json diff --git a/rules/access-container-service-account/raw.rego b/rules/access-container-service-account/raw.rego deleted file mode 100644 index 37f5c0690..000000000 --- a/rules/access-container-service-account/raw.rego +++ /dev/null @@ -1,333 +0,0 @@ -package armo_builtins - - -# Returns for each Pod, what are the permission of its service account - -deny[msga] { - serviceAccounts := [serviceaccount | serviceaccount= input[_]; serviceaccount.kind == "ServiceAccount"] - serviceaccount := serviceAccounts[_] - serviceAccountName := serviceaccount.metadata.name - - pods := [pod | pod=input[_]; pod.kind =="Pod"] - pod := pods[_] - pod.spec.serviceAccountName == serviceAccountName - - not isNotAutoMount(serviceaccount, pod) - - rolebindings := [rolebinding | rolebinding = input[_]; rolebinding.kind == "RoleBinding"] - rolebinding := rolebindings[_] - rolesubject := rolebinding.subjects[_] - rolesubject.name == serviceAccountName - - roles := [role | role = input[_]; role.kind == "Role"] - role := roles[_] - role.metadata.name == rolebinding.roleRef.name - - msga := { - "alertMessage": sprintf("Pod: %v has the following permissions in the cluster: %v", [pod.metadata.name, rolebinding.roleRef.name]), - "packagename": "armo_builtins", - "failedPaths": [], - "alertScore": 7, - "alertObject": { - "k8sApiObjects": [rolebinding, role, pod] - } - } -} - -# Returns for each Pod, what are the permission of its service account - deny[msga] { - serviceAccounts := [serviceaccount | serviceaccount= input[_]; serviceaccount.kind == "ServiceAccount"] - serviceaccount := serviceAccounts[_] - serviceAccountName := serviceaccount.metadata.name - - pods := [pod | pod=input[_]; pod.kind =="Pod"] - pod := pods[_] - pod.spec.serviceAccountName == serviceAccountName - - not isNotAutoMount(serviceaccount, pod) - - rolebindings := [rolebinding | rolebinding = input[_]; rolebinding.kind == "RoleBinding"] - rolebinding := rolebindings[_] - rolesubject := rolebinding.subjects[_] - rolesubject.name == serviceAccountName - - roles := [role | role = input[_]; role.kind == "ClusterRole"] - role := roles[_] - role.metadata.name == rolebinding.roleRef.name - - msga := { - "alertMessage": sprintf("Pod: %v has the following permissions in the cluster: %v", [pod.metadata.name, rolebinding.roleRef.name]), - "packagename": "armo_builtins", - "alertScore": 7, - "failedPaths": [], - "alertObject": { - "k8sApiObjects": [rolebinding, role, pod] - } - } -} - -# Returns for each Pod, what are the permission of its service account - - deny[msga] { - serviceAccounts := [serviceaccount | serviceaccount= input[_]; serviceaccount.kind == "ServiceAccount"] - serviceaccount := serviceAccounts[_] - serviceAccountName := serviceaccount.metadata.name - - pods := [pod | pod=input[_]; pod.kind =="Pod"] - pod := pods[_] - pod.spec.serviceAccountName == serviceAccountName - - not isNotAutoMount(serviceaccount, pod) - - rolebindings := [rolebinding | rolebinding = input[_]; rolebinding.kind == "ClusterRoleBinding"] - rolebinding := rolebindings[_] - rolesubject := rolebinding.subjects[_] - rolesubject.name == serviceAccountName - - roles := [role | role = input[_]; role.kind == "ClusterRole"] - role := roles[_] - role.metadata.name == rolebinding.roleRef.name - - msga := { - "alertMessage": sprintf("Pod: %v has the following permissions in the cluster: %v", [pod.metadata.name, rolebinding.roleRef.name]), - "packagename": "armo_builtins", - "alertScore": 7, - "failedPaths": [], - "alertObject": { - "k8sApiObjects": [rolebinding, role, pod] - } - } -} - - - - -### ---------------- ##### - - - -# Returns for each Workloads, what are the permission of its service account -deny[msga] { - serviceAccounts := [serviceaccount | serviceaccount= input[_]; serviceaccount.kind == "ServiceAccount"] - serviceaccount := serviceAccounts[_] - serviceAccountName := serviceaccount.metadata.name - - wl := input[_] - spec_template_spec_patterns := {"Deployment","ReplicaSet","DaemonSet","StatefulSet","Job"} - spec_template_spec_patterns[wl.kind] - - wl.spec.template.spec.serviceAccountName == serviceAccountName - - not isNotAutoMount(serviceaccount, wl.spec.template) - - rolebindings := [rolebinding | rolebinding = input[_]; rolebinding.kind == "RoleBinding"] - rolebinding := rolebindings[_] - rolesubject := rolebinding.subjects[_] - rolesubject.name == serviceAccountName - - roles := [role | role = input[_]; role.kind == "Role"] - role := roles[_] - role.metadata.name == rolebinding.roleRef.name - - msga := { - "alertMessage": sprintf("%v: %v has the following permissions in the cluster: %v", [wl.kind, wl.metadata.name, rolebinding.roleRef.name]), - "packagename": "armo_builtins", - "alertScore": 7, - "failedPaths": [], - "alertObject": { - "k8sApiObjects": [rolebinding, role, wl] - } - } -} - - -# Returns for each Workloads, what are the permission of its service account -deny[msga] { - serviceAccounts := [serviceaccount | serviceaccount= input[_]; serviceaccount.kind == "ServiceAccount"] - serviceaccount := serviceAccounts[_] - serviceAccountName := serviceaccount.metadata.name - - wl := input[_] - spec_template_spec_patterns := {"Deployment","ReplicaSet","DaemonSet","StatefulSet","Job"} - spec_template_spec_patterns[wl.kind] - - wl.spec.template.spec.serviceAccountName == serviceAccountName - - not isNotAutoMount(serviceaccount, wl.spec.template) - - rolebindings := [rolebinding | rolebinding = input[_]; rolebinding.kind == "RoleBinding"] - rolebinding := rolebindings[_] - rolesubject := rolebinding.subjects[_] - rolesubject.name == serviceAccountName - - roles := [role | role = input[_]; role.kind == "ClusterRole"] - role := roles[_] - role.metadata.name == rolebinding.roleRef.name - - msga := { - "alertMessage": sprintf("%v: %v has the following permissions in the cluster: %v", [wl.kind, wl.metadata.name, rolebinding.roleRef.name]), - "packagename": "armo_builtins", - "alertScore": 7, - "failedPaths": [], - "alertObject": { - "k8sApiObjects": [rolebinding, role, wl] - } - } -} - - - -# Returns for each Workloads, what are the permission of its service account -deny[msga] { - serviceAccounts := [serviceaccount | serviceaccount= input[_]; serviceaccount.kind == "ServiceAccount"] - serviceaccount := serviceAccounts[_] - serviceAccountName := serviceaccount.metadata.name - - wl := input[_] - spec_template_spec_patterns := {"Deployment","ReplicaSet","DaemonSet","StatefulSet","Job"} - spec_template_spec_patterns[wl.kind] - - wl.spec.template.spec.serviceAccountName == serviceAccountName - - not isNotAutoMount(serviceaccount, wl.spec.template) - - rolebindings := [rolebinding | rolebinding = input[_]; rolebinding.kind == "ClusterRoleBinding"] - rolebinding := rolebindings[_] - rolesubject := rolebinding.subjects[_] - rolesubject.name == serviceAccountName - - roles := [role | role = input[_]; role.kind == "ClusterRole"] - role := roles[_] - role.metadata.name == rolebinding.roleRef.name - - - msga := { - "alertMessage": sprintf("%v: %v has the following permissions in the cluster: %v", [wl.kind, wl.metadata.name, rolebinding.roleRef.name]), - "packagename": "armo_builtins", - "alertScore": 7, - "failedPaths": [], - "alertObject": { - "k8sApiObjects": [rolebinding, role, wl] - } - } -} - - - - -### ---------------- ##### - - -# Returns for each Cronjob, what are the permission of its service account - -deny[msga] { - serviceAccounts := [serviceaccount | serviceaccount= input[_]; serviceaccount.kind == "ServiceAccount"] - serviceaccount := serviceAccounts[_] - serviceAccountName := serviceaccount.metadata.name - - wl := input[_] - wl.kind == "CronJob" - wl.spec.jobTemplate.spec.template.spec.serviceAccountName == serviceAccountName - - not isNotAutoMount(serviceaccount, wl.spec.jobTemplate.spec.template) - - rolebindings := [rolebinding | rolebinding = input[_]; rolebinding.kind == "RoleBinding"] - rolebinding := rolebindings[_] - rolesubject := rolebinding.subjects[_] - rolesubject.name == serviceAccountName - - roles := [role | role = input[_]; role.kind == "Role"] - role := roles[_] - role.metadata.name == rolebinding.roleRef.name - - msga := { - "alertMessage": sprintf("Cronjob: %v has the following permissions in the cluster: %v", [wl.metadata.name, rolebinding.roleRef.name]), - "packagename": "armo_builtins", - "alertScore": 7, - "failedPaths": [], - "alertObject": { - "k8sApiObjects": [rolebinding, role, wl] - } - } -} - - - -# Returns for each Cronjob, what are the permission of its service account -deny[msga] { - serviceAccounts := [serviceaccount | serviceaccount= input[_]; serviceaccount.kind == "ServiceAccount"] - serviceaccount := serviceAccounts[_] - serviceAccountName := serviceaccount.metadata.name - - - wl := input[_] - wl.kind == "CronJob" - wl.spec.jobTemplate.spec.template.spec.serviceAccountName == serviceAccountName - - not isNotAutoMount(serviceaccount, wl.spec.jobTemplate.spec.template) - - rolebindings := [rolebinding | rolebinding = input[_]; rolebinding.kind == "RoleBinding"] - rolebinding := rolebindings[_] - rolesubject := rolebinding.subjects[_] - rolesubject.name == serviceAccountName - - roles := [role | role = input[_]; role.kind == "ClusterRole"] - role := roles[_] - role.metadata.name == rolebinding.roleRef.name - - msga := { - "alertMessage": sprintf("Cronjob: %v has the following permissions in the cluster: %v", [wl.metadata.name, rolebinding.roleRef.name]), - "packagename": "armo_builtins", - "alertScore": 7, - "failedPaths": [], - "alertObject": { - "k8sApiObjects": [rolebinding, role, wl] - } - } -} - - -# Returns for each Cronjob, what are the permission of its service account -deny[msga] { - serviceAccounts := [serviceaccount | serviceaccount= input[_]; serviceaccount.kind == "ServiceAccount"] - serviceaccount := serviceAccounts[_] - serviceAccountName := serviceaccount.metadata.name - - - wl := input[_] - wl.kind == "CronJob" - wl.spec.jobTemplate.spec.template.spec.serviceAccountName == serviceAccountName - - not isNotAutoMount(serviceaccount, wl.spec.jobTemplate.spec.template) - - rolebindings := [rolebinding | rolebinding = input[_]; rolebinding.kind == "ClusterRoleBinding"] - rolebinding := rolebindings[_] - rolesubject := rolebinding.subjects[_] - rolesubject.name == serviceAccountName - - roles := [role | role = input[_]; role.kind == "ClusterRole"] - role := roles[_] - role.metadata.name == rolebinding.roleRef.name - - - msga := { - "alertMessage": sprintf("Cronjob: %v has the following permissions in the cluster: %v", [wl.metadata.name, rolebinding.roleRef.name]), - "packagename": "armo_builtins", - "alertScore": 7, - "failedPaths": [], - "alertObject": { - "k8sApiObjects": [rolebinding, role, wl] - } - } -} - -# =============================================================== - -isNotAutoMount(serviceaccount, pod) { - pod.spec.automountServiceAccountToken == false -} -isNotAutoMount(serviceaccount, pod) { - serviceaccount.automountServiceAccountToken == false - not pod.spec["automountServiceAccountToken"] -} - diff --git a/rules/access-container-service-account/rule.metadata.json b/rules/access-container-service-account/rule.metadata.json deleted file mode 100644 index c29218196..000000000 --- a/rules/access-container-service-account/rule.metadata.json +++ /dev/null @@ -1,69 +0,0 @@ -{ - "name": "access-container-service-account", - "attributes": { - "m$K8sThreatMatrix": "Credential Access::Access container service account, Lateral Movement::Container service account", - "useUntilKubescapeVersion": "v1.0.133" - }, - "ruleLanguage": "Rego", - "match": [ - { - "apiGroups": [ - "" - ], - "apiVersions": [ - "v1" - ], - "resources": [ - "Pod", - "ServiceAccount" - ] - }, - { - "apiGroups": [ - "apps" - ], - "apiVersions": [ - "v1" - ], - "resources": [ - "Deployment", - "ReplicaSet", - "DaemonSet", - "StatefulSet" - ] - }, - { - "apiGroups": [ - "batch" - ], - "apiVersions": [ - "*" - ], - "resources": [ - "Job", - "CronJob" - ] - }, - { - "apiGroups": [ - "rbac.authorization.k8s.io" - ], - "apiVersions": [ - "v1" - ], - "resources": [ - "RoleBinding", - "ClusterRoleBinding", - "Role", - "ClusterRole" - ] - } - ], - "ruleDependencies": [ - - ], - "description": "determines which service accounts can be used to access other resources in the cluster", - "remediation": "", - "ruleQuery": "armo_builtins", - "resourceCount": "subjects" -} diff --git a/rules/exec-into-container/raw.rego b/rules/exec-into-container/raw.rego deleted file mode 100644 index c09d77250..000000000 --- a/rules/exec-into-container/raw.rego +++ /dev/null @@ -1,138 +0,0 @@ -package armo_builtins - -import data.cautils - -# input: clusterrolebindings + rolebindings -# apiversion: rbac.authorization.k8s.io/v1 -# returns subjects that can exec into container - -deny[msga] { - roles := [role | role= input[_]; role.kind == "Role"] - rolebindings := [rolebinding | rolebinding = input[_]; rolebinding.kind == "RoleBinding"] - role:= roles[_] - rolebinding := rolebindings[_] - - rule:= role.rules[_] - can_exec_to_pod_resource(rule) - can_exec_to_pod_verb(rule) - - rolebinding.roleRef.kind == "Role" - rolebinding.roleRef.name == role.metadata.name - - subject := rolebinding.subjects[i] - path := sprintf("subjects[%v]", [format_int(i, 10)]) - - msga := { - "alertMessage": sprintf("the following %v: %v, can exec into containers", [subject.kind, subject.name]), - "alertScore": 9, - "deletePaths": [path], - "failedPaths": [path], - "packagename": "armo_builtins", - "alertObject": { - "k8sApiObjects": [role, rolebinding], - "externalObjects": { - "subject" : [subject] - } - } - } -} - - -# input: clusterrolebindings + rolebindings -# apiversion: rbac.authorization.k8s.io/v1 -# returns subjects that can exec into container - -deny[msga] { - roles := [role | role= input[_]; role.kind == "ClusterRole"] - rolebindings := [rolebinding | rolebinding = input[_]; rolebinding.kind == "RoleBinding"] - role:= roles[_] - rolebinding := rolebindings[_] - - rule:= role.rules[_] - can_exec_to_pod_resource(rule) - can_exec_to_pod_verb(rule) - - rolebinding.roleRef.kind == "ClusterRole" - rolebinding.roleRef.name == role.metadata.name - - subject := rolebinding.subjects[i] - path := sprintf("subjects[%v]", [format_int(i, 10)]) - - msga := { - "alertMessage": sprintf("the following %v: %v, can exec into containers", [subject.kind, subject.name]), - "alertScore": 9, - "deletePaths": [path], - "failedPaths": [path], - "packagename": "armo_builtins", - "alertObject": { - "k8sApiObjects": [role, rolebinding], - "externalObjects": { - "subject" : [subject] - } - } - } -} - -# input: clusterrolebindings + rolebindings -# apiversion: rbac.authorization.k8s.io/v1 -# returns subjects that can exec into container - -deny[msga] { - roles := [role | role= input[_]; role.kind == "ClusterRole"] - rolebindings := [rolebinding | rolebinding = input[_]; rolebinding.kind == "ClusterRoleBinding"] - role:= roles[_] - rolebinding := rolebindings[_] - - rule:= role.rules[_] - can_exec_to_pod_resource(rule) - can_exec_to_pod_verb(rule) - - rolebinding.roleRef.kind == "ClusterRole" - rolebinding.roleRef.name == role.metadata.name - - subject := rolebinding.subjects[i] - path := sprintf("subjects[%v]", [format_int(i, 10)]) - - msga := { - "alertMessage": sprintf("the following %v: %v, can exec into containers", [subject.kind, subject.name]), - "alertScore": 9, - "deletePaths": [path], - "failedPaths": [path], - "packagename": "armo_builtins", - "alertObject": { - "k8sApiObjects": [role, rolebinding], - "externalObjects": { - "subject" : [subject] - } - } - } -} - -can_exec_to_pod_verb(rule) { - cautils.list_contains(rule.verbs, "create") -} -can_exec_to_pod_verb(rule) { - cautils.list_contains(rule.verbs, "*") -} - -can_exec_to_pod_resource(rule) { - cautils.list_contains(rule.resources, "pods/exec") - -} -can_exec_to_pod_resource(rule) { - cautils.list_contains(rule.resources, "pods/*") -} -can_exec_to_pod_resource(rule) { - is_api_group(rule) - cautils.list_contains(rule.resources, "*") -} - -is_api_group(rule) { - apiGroup := rule.apiGroups[_] - apiGroup == "" -} - -is_api_group(rule) { - apiGroup := rule.apiGroups[_] - apiGroup == "*" -} \ No newline at end of file diff --git a/rules/exec-into-container/rule.metadata.json b/rules/exec-into-container/rule.metadata.json deleted file mode 100644 index 17e089973..000000000 --- a/rules/exec-into-container/rule.metadata.json +++ /dev/null @@ -1,33 +0,0 @@ -{ - "name": "exec-into-container", - "attributes": { - "m$K8sThreatMatrix": "Privilege Escalation::Exec into container", - "useUntilKubescapeVersion": "v1.0.133" - }, - "ruleLanguage": "Rego", - "match": [ - { - "apiGroups": [ - "rbac.authorization.k8s.io" - ], - "apiVersions": [ - "v1" - ], - "resources": [ - "RoleBinding", - "ClusterRoleBinding", - "Role", - "ClusterRole" - ] - } - ], - "ruleDependencies": [ - { - "packageName": "cautils" - } - ], - "description": "determines which users have permissions to exec into pods", - "remediation": "", - "ruleQuery": "armo_builtins", - "resourceCount": "subjects" -} \ No newline at end of file diff --git a/rules/exposed-sensitive-interfaces/raw.rego b/rules/exposed-sensitive-interfaces/raw.rego deleted file mode 100644 index 2dccc002d..000000000 --- a/rules/exposed-sensitive-interfaces/raw.rego +++ /dev/null @@ -1,113 +0,0 @@ -package armo_builtins - -import data.kubernetes.api.client - -# loadbalancer -deny[msga] { - service := input[_] - service.kind == "Service" - service.spec.type == "LoadBalancer" - - wl := input[_] - workload_types = {"Deployment", "ReplicaSet", "DaemonSet", "StatefulSet", "Job", "Pod", "CronJob"} - workload_types[wl.kind] - result := wl_connectedto_service(wl, service) - - # see default-config-inputs.json for list values - services_names := data.postureControlInputs.servicesNames - services_names[service.metadata.name] - # externalIP := service.spec.externalIPs[_] - externalIP := service.status.loadBalancer.ingress[0].ip - - - msga := { - "alertMessage": sprintf("service: %v is exposed", [service.metadata.name]), - "packagename": "armo_builtins", - "alertScore": 7, - "reviewPaths": result, - "failedPaths": result, - "alertObject": { - "k8sApiObjects": [wl, service] - } - } -} - - -# nodePort -# get a pod connected to that service, get nodeIP (hostIP?) -# use ip + nodeport -deny[msga] { - service := input[_] - service.kind == "Service" - service.spec.type == "NodePort" - - # see default-config-inputs.json for list values - services_names := data.postureControlInputs.servicesNames - services_names[service.metadata.name] - - pod := input[_] - pod.kind == "Pod" - - result := wl_connectedto_service(pod, service) - - - - msga := { - "alertMessage": sprintf("service: %v is exposed", [service.metadata.name]), - "packagename": "armo_builtins", - "alertScore": 7, - "reviewPaths": result, - "failedPaths": result, - "alertObject": { - "k8sApiObjects": [pod, service] - } - } -} - -# nodePort -# get a workload connected to that service, get nodeIP (hostIP?) -# use ip + nodeport -deny[msga] { - service := input[_] - service.kind == "Service" - service.spec.type == "NodePort" - - # see default-config-inputs.json for list values - services_names := data.postureControlInputs.servicesNames - services_names[service.metadata.name] - - wl := input[_] - spec_template_spec_patterns := {"Deployment", "ReplicaSet", "DaemonSet", "StatefulSet", "Job", "CronJob"} - spec_template_spec_patterns[wl.kind] - - result := wl_connectedto_service(wl, service) - - pods_resource := client.query_all("pods") - pod := pods_resource.body.items[_] - my_pods := [pod | startswith(pod.metadata.name, wl.metadata.name)] - - - - msga := { - "alertMessage": sprintf("service: %v is exposed", [service.metadata.name]), - "packagename": "armo_builtins", - "alertScore": 7, - "reviewPaths": result, - "failedPaths": result, - "alertObject": { - "k8sApiObjects": [wl, service] - } - } -} - -# ==================================================================================== - -wl_connectedto_service(wl, service) = paths{ - count({x | service.spec.selector[x] == wl.metadata.labels[x]}) == count(service.spec.selector) - paths = ["spec.selector.matchLabels","spec.selector"] -} - -wl_connectedto_service(wl, service) = paths { - wl.spec.selector.matchLabels == service.spec.selector - paths = ["spec.selector.matchLabels", "spec.selector"] -} diff --git a/rules/exposed-sensitive-interfaces/rule.metadata.json b/rules/exposed-sensitive-interfaces/rule.metadata.json deleted file mode 100644 index 47b74abb7..000000000 --- a/rules/exposed-sensitive-interfaces/rule.metadata.json +++ /dev/null @@ -1,66 +0,0 @@ -{ - "name": "exposed-sensitive-interfaces", - "attributes": { - "microsoftK8sThreatMatrix": "Initial access::Exposed sensitive interfaces", - "useUntilKubescapeVersion": "v1.0.133" - }, - "ruleLanguage": "Rego", - "match": [ - { - "apiGroups": [ - "" - ], - "apiVersions": [ - "v1" - ], - "resources": [ - "Pod", - "Service" - ] - }, - { - "apiGroups": [ - "apps" - ], - "apiVersions": [ - "v1" - ], - "resources": [ - "Deployment", - "ReplicaSet", - "DaemonSet", - "StatefulSet" - ] - }, - { - "apiGroups": [ - "batch" - ], - "apiVersions": [ - "*" - ], - "resources": [ - "Job", - "CronJob" - ] - } - ], - "ruleDependencies": [ - { - "packageName": "kubernetes.api.client" - } - ], - "configInputs": [ - "settings.postureControlInputs.servicesNames" - ], - "controlConfigInputs": [ - { - "path": "settings.postureControlInputs.servicesNames", - "name": "Service names", - "description": "List of services relating to known software interfaces that should not generally be exposed to the Internet." - } - ], - "description": "fails if known interfaces have exposed services", - "remediation": "", - "ruleQuery": "armo_builtins" -} \ No newline at end of file diff --git a/rules/rule-access-dashboard/raw.rego b/rules/rule-access-dashboard/raw.rego deleted file mode 100644 index 228aaaaff..000000000 --- a/rules/rule-access-dashboard/raw.rego +++ /dev/null @@ -1,119 +0,0 @@ -package armo_builtins - -# input: roleBinding -# apiversion: v1 -# fails if a subject that is not dashboard service account is bound to dashboard role - -deny[msga] { - roleBinding := input[_] - roleBinding.kind == "RoleBinding" - roleBinding.roleRef.name == "kubernetes-dashboard" - subject := roleBinding.subjects[_] - subject.name != "kubernetes-dashboard" - subject.kind != "ServiceAccount" - - msga := { - "alertMessage": sprintf("the following subjects: %s are bound to dashboard role/clusterrole", [subject.name]), - "alertScore": 9, - "failedPaths": [], - "packagename": "armo_builtins", - "alertObject": { - "k8sApiObjects": [roleBinding], - "externalObjects": { - "subject" : [subject] - } - } - } -} - -# input: clusterRoleBinding -# apiversion: v1 -# fails if a subject that is not dashboard service account is bound to dashboard role - -deny[msga] { - roleBinding := input[_] - roleBinding.kind == "ClusterRoleBinding" - roleBinding.roleRef.name == "kubernetes-dashboard" - subject := roleBinding.subjects[_] - subject.name != "kubernetes-dashboard" - subject.kind != "ServiceAccount" - - msga := { - "alertMessage": sprintf("the following subjects: %s are bound to dashboard role/clusterrole", [subject.name]), - "alertScore": 9, - "failedPaths": [], - "packagename": "armo_builtins", - "alertObject": { - "k8sApiObjects": [roleBinding], - "externalObjects": { - "subject" : [subject] - } - } - } -} - -# input: -# apiversion: -# fails if pod that is not dashboard is associated to dashboard service account - -deny[msga] { - pod := input[_] - pod.spec.serviceAccountName == "kubernetes-dashboard" - not startswith(pod.metadata.name, "kubernetes-dashboard") - path := "spec.serviceAccountName" - msga := { - "alertMessage": sprintf("the following pods: %s are associated with dashboard service account", [pod.metadata.name]), - "packagename": "armo_builtins", - "alertScore": 7, - "deletePaths": [path], - "failedPaths": [path], - "alertObject": { - "k8sApiObjects": [pod] - } - } -} - -# input: -# apiversion: -# fails if workload that is not dashboard is associated to dashboard service account - -deny[msga] { - wl := input[_] - spec_template_spec_patterns := {"Deployment","ReplicaSet","DaemonSet","StatefulSet","Job"} - spec_template_spec_patterns[wl.kind] - wl.spec.template.spec.serviceAccountName == "kubernetes-dashboard" - not startswith(wl.metadata.name, "kubernetes-dashboard") - path := "spec.template.spec.serviceAccountName" - msga := { - "alertMessage": sprintf("%v: %v is associated with dashboard service account", [wl.kind, wl.metadata.name]), - "packagename": "armo_builtins", - "alertScore": 7, - "deletePaths": [path], - "failedPaths": [path], - "alertObject": { - "k8sApiObjects": [wl] - } - } -} - -# input: -# apiversion: -# fails if CronJob that is not dashboard is associated to dashboard service account - -deny[msga] { - wl := input[_] - wl.kind == "CronJob" - wl.spec.jobTemplate.spec.template.spec.serviceAccountName == "kubernetes-dashboard" - not startswith(wl.metadata.name, "kubernetes-dashboard") - path := "spec.jobTemplate.spec.template.spec.serviceAccountName" - msga := { - "alertMessage": sprintf("the following cronjob: %s is associated with dashboard service account", [wl.metadata.name]), - "packagename": "armo_builtins", - "alertScore": 7, - "deletePaths": [path], - "failedPaths": [path], - "alertObject": { - "k8sApiObjects": [wl] - } - } -} \ No newline at end of file diff --git a/rules/rule-access-dashboard/rule.metadata.json b/rules/rule-access-dashboard/rule.metadata.json deleted file mode 100644 index 5378febee..000000000 --- a/rules/rule-access-dashboard/rule.metadata.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "name": "rule-access-dashboard", - "attributes": { - "m$K8sThreatMatrix": "Lateral Movement::Access Kubernetes dashboard, Discovery::Access Kubernetes dashboard", - "useUntilKubescapeVersion": "v1.0.133" - }, - "ruleLanguage": "Rego", - "match": [ - { - "apiGroups": [ - "*" - ], - "apiVersions": [ - "*" - ], - "resources": [ - "RoleBinding", - "ClusterRoleBinding" - ] - } - ], - "ruleDependencies": [], - "description": "fails if subject that is not dashboard service account is bound to dashboard role/clusterrole, or- if anyone that is not dashboard pod is associated with its service account.", - "remediation": "", - "ruleQuery": "armo_builtins", - "resourceCount": "subjects" - } \ No newline at end of file diff --git a/rules/rule-can-delete-k8s-events/raw.rego b/rules/rule-can-delete-k8s-events/raw.rego deleted file mode 100644 index a586984fc..000000000 --- a/rules/rule-can-delete-k8s-events/raw.rego +++ /dev/null @@ -1,137 +0,0 @@ -package armo_builtins - -import data.cautils - -# fails if user can delete events -# RoleBinding to Role -deny [msga] { - roles := [role | role= input[_]; role.kind == "Role"] - rolebindings := [rolebinding | rolebinding = input[_]; rolebinding.kind == "RoleBinding"] - role:= roles[_] - rolebinding := rolebindings[_] - - rule:= role.rules[_] - canDeleteEventsResource(rule) - canDeleteEventsVerb(rule) - - rolebinding.roleRef.kind == "Role" - rolebinding.roleRef.name == role.metadata.name - - subject := rolebinding.subjects[i] - path := sprintf("subjects[%v]", [format_int(i, 10)]) - - msga := { - "alertMessage": sprintf("The following %v: %v can delete events", [subject.kind, subject.name]), - "alertScore": 6, - "deletePaths": [path], - "failedPaths": [path], - "packagename": "armo_builtins", - "alertObject": { - "k8sApiObjects": [role,rolebinding], - "externalObjects": { - "subject" : [subject] - } - } - } -} - - -# fails if user can delete events -# RoleBinding to ClusterRole -deny[msga] { - roles := [role | role= input[_]; role.kind == "ClusterRole"] - rolebindings := [rolebinding | rolebinding = input[_]; rolebinding.kind == "RoleBinding"] - role:= roles[_] - rolebinding := rolebindings[_] - - rule:= role.rules[_] - canDeleteEventsResource(rule) - canDeleteEventsVerb(rule) - - rolebinding.roleRef.kind == "ClusterRole" - rolebinding.roleRef.name == role.metadata.name - - - subject := rolebinding.subjects[i] - path := sprintf("subjects[%v]", [format_int(i, 10)]) - - msga := { - "alertMessage": sprintf("The following %v: %v can delete events", [subject.kind, subject.name]), - "alertScore": 6, - "deletePaths": [path], - "failedPaths": [path], - "packagename": "armo_builtins", - "alertObject": { - "k8sApiObjects": [role,rolebinding], - "externalObjects": { - "subject" : [subject] - } - } - } -} - - -# fails if user can delete events -# ClusterRoleBinding to ClusterRole -deny[msga] { - roles := [role | role= input[_]; role.kind == "ClusterRole"] - clusterrolebindings := [rolebinding | rolebinding = input[_]; rolebinding.kind == "ClusterRoleBinding"] - role:= roles[_] - clusterrolebinding := clusterrolebindings[_] - - rule:= role.rules[_] - canDeleteEventsResource(rule) - canDeleteEventsVerb(rule) - - clusterrolebinding.roleRef.kind == "ClusterRole" - clusterrolebinding.roleRef.name == role.metadata.name - - - subject := clusterrolebinding.subjects[i] - path := sprintf("subjects[%v]", [format_int(i, 10)]) - - msga := { - "alertMessage": sprintf("The following %v: %v can delete events", [subject.kind, subject.name]), - "alertScore": 6, - "deletePaths": [path], - "failedPaths": [path], - "packagename": "armo_builtins", - "alertObject": { - "k8sApiObjects": [role,clusterrolebinding], - "externalObjects": { - "subject" : [subject] - } - } - } -} - - -canDeleteEventsResource(rule) { - cautils.list_contains(rule.resources,"events") -} -canDeleteEventsResource(rule) { - is_api_group(rule) - cautils.list_contains(rule.resources,"*") -} - -is_api_group(rule) { - apiGroup := rule.apiGroups[_] - apiGroup == "*" -} - -is_api_group(rule) { - apiGroup := rule.apiGroups[_] - apiGroup == "" -} - -canDeleteEventsVerb(rule) { - cautils.list_contains(rule.verbs,"delete") -} - -canDeleteEventsVerb(rule) { - cautils.list_contains(rule.verbs,"deletecollection") -} - -canDeleteEventsVerb(rule) { - cautils.list_contains(rule.verbs,"*") -} \ No newline at end of file diff --git a/rules/rule-can-delete-k8s-events/rule.metadata.json b/rules/rule-can-delete-k8s-events/rule.metadata.json deleted file mode 100644 index 797eb1ea8..000000000 --- a/rules/rule-can-delete-k8s-events/rule.metadata.json +++ /dev/null @@ -1,33 +0,0 @@ -{ - "name": "rule-can-delete-k8s-events", - "attributes": { - "microsoftK8sThreatMatrix": "Defense Evasion::Delete K8S events", - "useUntilKubescapeVersion": "v1.0.133" - }, - "ruleLanguage": "Rego", - "match": [ - { - "apiGroups": [ - "rbac.authorization.k8s.io" - ], - "apiVersions": [ - "v1" - ], - "resources": [ - "Role", - "ClusterRole", - "ClusterRoleBinding", - "RoleBinding" - ] - } - ], - "ruleDependencies": [ - { - "packageName": "cautils" - } - ], - "description": "determines which users can delete events", - "remediation": "", - "ruleQuery": "armo_builtins", - "resourceCount": "subjects" - } \ No newline at end of file diff --git a/rules/rule-can-impersonate-users-groups/raw.rego b/rules/rule-can-impersonate-users-groups/raw.rego deleted file mode 100644 index 8fe4e0589..000000000 --- a/rules/rule-can-impersonate-users-groups/raw.rego +++ /dev/null @@ -1,139 +0,0 @@ -package armo_builtins - -import data.cautils - -deny[msga] { - roles := [role | role= input[_]; role.kind == "Role"] - rolebindings := [rolebinding | rolebinding = input[_]; rolebinding.kind == "RoleBinding"] - role:= roles[_] - rolebinding := rolebindings[_] - - rule:= role.rules[_] - canImpersonateVerb(rule) - canImpersonateResource(rule) - - rolebinding.roleRef.kind == "Role" - rolebinding.roleRef.name == role.metadata.name - - subject := rolebinding.subjects[i] - path := sprintf("subjects[%v]", [format_int(i, 10)]) - - msga := { - "alertMessage": sprintf("the following %v: %v, can impersonate users", [subject.kind, subject.name]), - "alertScore": 9, - "deletePaths": [path], - "failedPaths": [path], - "packagename": "armo_builtins", - "alertObject": { - "k8sApiObjects": [role, rolebinding], - "externalObjects": { - "subject" : [subject] - } - } - } -} - - -deny[msga] { - roles := [role | role= input[_]; role.kind == "ClusterRole"] - rolebindings := [rolebinding | rolebinding = input[_]; rolebinding.kind == "RoleBinding"] - role:= roles[_] - rolebinding := rolebindings[_] - - rule:= role.rules[_] - canImpersonateVerb(rule) - canImpersonateResource(rule) - - rolebinding.roleRef.kind == "ClusterRole" - rolebinding.roleRef.name == role.metadata.name - - subject := rolebinding.subjects[i] - path := sprintf("subjects[%v]", [format_int(i, 10)]) - - msga := { - "alertMessage": sprintf("the following %v: %v, can impersonate users", [subject.kind, subject.name]), - "alertScore": 9, - "deletePaths": [path], - "failedPaths": [path], - "packagename": "armo_builtins", - "alertObject": { - "k8sApiObjects": [role, rolebinding], - "externalObjects": { - "subject" : [subject] - } - } - } -} - - - -deny[msga] { - roles := [role | role= input[_]; role.kind == "ClusterRole"] - rolebindings := [rolebinding | rolebinding = input[_]; rolebinding.kind == "ClusterRoleBinding"] - role:= roles[_] - rolebinding := rolebindings[_] - - rule:= role.rules[_] - canImpersonateVerb(rule) - canImpersonateResource(rule) - - rolebinding.roleRef.kind == "ClusterRole" - rolebinding.roleRef.name == role.metadata.name - - subject := rolebinding.subjects[i] - path := sprintf("subjects[%v]", [format_int(i, 10)]) - - msga := { - "alertMessage": sprintf("the following %v: %v, can impersonate users", [subject.kind, subject.name]), - "alertScore": 9, - "deletePaths": [path], - "failedPaths": [path], - "packagename": "armo_builtins", - "alertObject": { - "k8sApiObjects": [role, rolebinding], - "externalObjects": { - "subject" : [subject] - } - } - } -} - - -canImpersonateVerb(rule) { - cautils.list_contains(rule.verbs, "impersonate") -} -canImpersonateVerb(rule) { - cautils.list_contains(rule.verbs, "*") -} - - -canImpersonateResource(rule) { - cautils.list_contains(rule.resources,"users") -} - -canImpersonateResource(rule) { - cautils.list_contains(rule.resources,"serviceaccounts") -} - -canImpersonateResource(rule) { - cautils.list_contains(rule.resources,"groups") -} - -canImpersonateResource(rule) { - cautils.list_contains(rule.resources,"uids") -} - -canImpersonateResource(rule) { - is_api_group(rule) - cautils.list_contains(rule.resources,"*") -} - -is_api_group(rule) { - apiGroup := rule.apiGroups[_] - apiGroup == "*" -} - -is_api_group(rule) { - apiGroup := rule.apiGroups[_] - apiGroup == "" -} \ No newline at end of file diff --git a/rules/rule-can-impersonate-users-groups/rule.metadata.json b/rules/rule-can-impersonate-users-groups/rule.metadata.json deleted file mode 100644 index 88ba455c0..000000000 --- a/rules/rule-can-impersonate-users-groups/rule.metadata.json +++ /dev/null @@ -1,33 +0,0 @@ -{ - "name": "rule-can-impersonate-users-groups", - "attributes": { - "microsoftK8sThreatMatrix": "Discovery::Access the K8s API server", - "useUntilKubescapeVersion": "v1.0.133" - }, - "ruleLanguage": "Rego", - "match": [ - { - "apiGroups": [ - "rbac.authorization.k8s.io" - ], - "apiVersions": [ - "v1" - ], - "resources": [ - "Role", - "ClusterRole", - "ClusterRoleBinding", - "RoleBinding" - ] - } - ], - "ruleDependencies": [ - { - "packageName": "cautils" - } - ], - "description": "determines which users can impersonate users/groups", - "remediation": "", - "ruleQuery": "armo_builtins", - "resourceCount": "subjects" - } \ No newline at end of file diff --git a/rules/rule-can-list-get-secrets/raw.rego b/rules/rule-can-list-get-secrets/raw.rego deleted file mode 100644 index f94f31ab1..000000000 --- a/rules/rule-can-list-get-secrets/raw.rego +++ /dev/null @@ -1,143 +0,0 @@ -package armo_builtins - -import data.cautils - -# fails if user can list/get secrets -# RoleBinding to Role -deny[msga] { - roles := [role | role= input[_]; role.kind == "Role"] - rolebindings := [rolebinding | rolebinding = input[_]; rolebinding.kind == "RoleBinding"] - role:= roles[_] - rolebinding := rolebindings[_] - - rule:= role.rules[_] - canViewSecretsResource(rule) - canViewSecretsVerb(rule) - - rolebinding.roleRef.kind == "Role" - rolebinding.roleRef.name == role.metadata.name - - subject := rolebinding.subjects[i] - path := sprintf("subjects[%v]", [format_int(i, 10)]) - - msga := { - "alertMessage": sprintf("The following %v: %v can read secrets", [subject.kind, subject.name]), - "alertScore": 9, - "packagename": "armo_builtins", - "deletePaths": [path], - "failedPaths": [path], - "alertObject": { - "k8sApiObjects": [role,rolebinding], - "externalObjects": { - "subject" : [subject] - } - } - } -} - - -# fails if user can list/get secrets -# RoleBinding to ClusterRole -deny[msga] { - roles := [role | role= input[_]; role.kind == "ClusterRole"] - rolebindings := [rolebinding | rolebinding = input[_]; rolebinding.kind == "RoleBinding"] - role:= roles[_] - rolebinding := rolebindings[_] - - rule:= role.rules[_] - canViewSecretsResource(rule) - canViewSecretsVerb(rule) - - rolebinding.roleRef.kind == "ClusterRole" - rolebinding.roleRef.name == role.metadata.name - - - subject := rolebinding.subjects[i] - path := sprintf("subjects[%v]", [format_int(i, 10)]) - - msga := { - "alertMessage": sprintf("The following %v: %v can read secrets", [subject.kind, subject.name]), - "alertScore": 9, - "packagename": "armo_builtins", - "deletePaths": [path], - "failedPaths": [path], - "alertObject": { - "k8sApiObjects": [role,rolebinding], - "externalObjects": { - "subject" : [subject] - } - } - } -} - -# fails if user can list/get secrets -# ClusterRoleBinding to ClusterRole -deny[msga] { - roles := [role | role= input[_]; role.kind == "ClusterRole"] - clusterrolebindings := [rolebinding | rolebinding = input[_]; rolebinding.kind == "ClusterRoleBinding"] - role:= roles[_] - clusterrolebinding := clusterrolebindings[_] - - rule:= role.rules[_] - canViewSecretsResource(rule) - canViewSecretsVerb(rule) - - clusterrolebinding.roleRef.kind == "ClusterRole" - clusterrolebinding.roleRef.name == role.metadata.name - - subject := clusterrolebinding.subjects[i] - path := sprintf("subjects[%v]", [format_int(i, 10)]) - - msga := { - "alertMessage": sprintf("The following %v: %v can read secrets", [subject.kind, subject.name]), - "alertScore": 9, - "packagename": "armo_builtins", - "deletePaths": [path], - "failedPaths": [path], - "alertObject": { - "k8sApiObjects": [role,clusterrolebinding], - "externalObjects": { - "subject" : [subject] - } - } - } -} - - - - -canViewSecretsVerb(rule) { - cautils.list_contains(rule.verbs,"get") -} - -canViewSecretsVerb(rule) { - cautils.list_contains(rule.verbs,"list") -} - -canViewSecretsVerb(rule) { - cautils.list_contains(rule.verbs,"watch") -} - - -canViewSecretsVerb(rule) { - cautils.list_contains(rule.verbs,"*") -} - - -canViewSecretsResource(rule) { - cautils.list_contains(rule.resources,"secrets") -} - -canViewSecretsResource(rule) { - is_api_group(rule) - cautils.list_contains(rule.resources,"*") -} - -is_api_group(rule) { - apiGroup := rule.apiGroups[_] - apiGroup == "*" -} -is_api_group(rule) { - apiGroup := rule.apiGroups[_] - apiGroup == "" -} \ No newline at end of file diff --git a/rules/rule-can-list-get-secrets/rule.metadata.json b/rules/rule-can-list-get-secrets/rule.metadata.json deleted file mode 100644 index a6824d60f..000000000 --- a/rules/rule-can-list-get-secrets/rule.metadata.json +++ /dev/null @@ -1,33 +0,0 @@ -{ - "name": "rule-can-list-get-secrets", - "attributes": { - "microsoftK8sThreatMatrix": "Discovery::Access the K8s API server", - "useUntilKubescapeVersion": "v1.0.133" - }, - "ruleLanguage": "Rego", - "match": [ - { - "apiGroups": [ - "rbac.authorization.k8s.io" - ], - "apiVersions": [ - "v1" - ], - "resources": [ - "Role", - "ClusterRole", - "ClusterRoleBinding", - "RoleBinding" - ] - } - ], - "ruleDependencies": [ - { - "packageName": "cautils" - } - ], - "description": "determines which users can list/get secrets", - "remediation": "", - "ruleQuery": "armo_builtins", - "resourceCount": "subjects" - } \ No newline at end of file diff --git a/rules/rule-can-portforward/raw.rego b/rules/rule-can-portforward/raw.rego deleted file mode 100644 index b5fa53bf3..000000000 --- a/rules/rule-can-portforward/raw.rego +++ /dev/null @@ -1,131 +0,0 @@ -package armo_builtins - -import data.cautils - -deny[msga] { - roles := [role | role= input[_]; role.kind == "Role"] - rolebindings := [rolebinding | rolebinding = input[_]; rolebinding.kind == "RoleBinding"] - role:= roles[_] - rolebinding := rolebindings[_] - - rule:= role.rules[_] - canForwardToPodResource(rule) - canForwardToPodVerb(rule) - - rolebinding.roleRef.kind == "Role" - rolebinding.roleRef.name == role.metadata.name - - subject := rolebinding.subjects[i] - path := sprintf("subjects[%v]", [format_int(i, 10)]) - - msga := { - "alertMessage": sprintf("the following %v: %v, can do port forwarding", [subject.kind, subject.name]), - "alertScore": 9, - "deletePaths": [path], - "failedPaths": [path], - "packagename": "armo_builtins", - "alertObject": { - "k8sApiObjects": [role, rolebinding], - "externalObjects": { - "subject" : [subject] - } - } - } -} - - -deny[msga] { - roles := [role | role= input[_]; role.kind == "ClusterRole"] - rolebindings := [rolebinding | rolebinding = input[_]; rolebinding.kind == "RoleBinding"] - role:= roles[_] - rolebinding := rolebindings[_] - - rule:= role.rules[_] - canForwardToPodResource(rule) - canForwardToPodVerb(rule) - - rolebinding.roleRef.kind == "ClusterRole" - rolebinding.roleRef.name == role.metadata.name - - subject := rolebinding.subjects[i] - path := sprintf("subjects[%v]", [format_int(i, 10)]) - - msga := { - "alertMessage": sprintf("the following %v: %v, can do port forwarding", [subject.kind, subject.name]), - "alertScore": 9, - "deletePaths": [path], - "failedPaths": [path], - "packagename": "armo_builtins", - "alertObject": { - "k8sApiObjects": [role, rolebinding], - "externalObjects": { - "subject" : [subject] - } - } - } -} - - - -deny[msga] { - roles := [role | role= input[_]; role.kind == "ClusterRole"] - rolebindings := [rolebinding | rolebinding = input[_]; rolebinding.kind == "ClusterRoleBinding"] - role:= roles[_] - rolebinding := rolebindings[_] - - rule:= role.rules[_] - canForwardToPodResource(rule) - canForwardToPodVerb(rule) - - rolebinding.roleRef.kind == "ClusterRole" - rolebinding.roleRef.name == role.metadata.name - - subject := rolebinding.subjects[i] - path := sprintf("subjects[%v]", [format_int(i, 10)]) - - msga := { - "alertMessage": sprintf("the following %v: %v, can do port forwarding", [subject.kind, subject.name]), - "alertScore": 9, - "deletePaths": [path], - "failedPaths": [path], - "packagename": "armo_builtins", - "alertObject": { - "k8sApiObjects": [role, rolebinding], - "externalObjects": { - "subject" : [subject] - } - } - } -} - -canForwardToPodVerb(rule) { - cautils.list_contains(rule.verbs, "create") -} - -canForwardToPodVerb(rule) { - cautils.list_contains(rule.verbs, "get") -} -canForwardToPodVerb(rule) { - cautils.list_contains(rule.verbs, "*") -} - -canForwardToPodResource(rule) { - cautils.list_contains(rule.resources,"pods/portforward") -} -canForwardToPodResource(rule) { - cautils.list_contains(rule.resources,"pods/*") -} -canForwardToPodResource(rule) { - is_api_group(rule) - cautils.list_contains(rule.resources,"*") -} - -is_api_group(rule) { - apiGroup := rule.apiGroups[_] - apiGroup == "" -} - -is_api_group(rule) { - apiGroup := rule.apiGroups[_] - apiGroup == "*" -} diff --git a/rules/rule-can-portforward/rule.metadata.json b/rules/rule-can-portforward/rule.metadata.json deleted file mode 100644 index 6fe58a54e..000000000 --- a/rules/rule-can-portforward/rule.metadata.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "name": "rule-can-portforward", - "attributes": { - "useUntilKubescapeVersion": "v1.0.133" - }, - "ruleLanguage": "Rego", - "match": [ - { - "apiGroups": [ - "rbac.authorization.k8s.io" - ], - "apiVersions": [ - "v1" - ], - "resources": [ - "Role", - "ClusterRole", - "ClusterRoleBinding", - "RoleBinding" - ] - } - ], - "ruleDependencies": [ - { - "packageName": "cautils" - } - ], - "description": "", - "remediation": "", - "ruleQuery": "armo_builtins", - "resourceCount": "subjects" - } \ No newline at end of file diff --git a/rules/rule-can-ssh-to-pod/raw.rego b/rules/rule-can-ssh-to-pod/raw.rego deleted file mode 100644 index 34699995d..000000000 --- a/rules/rule-can-ssh-to-pod/raw.rego +++ /dev/null @@ -1,104 +0,0 @@ -package armo_builtins - -# input: pod -# apiversion: v1 -# does: returns the external facing services of that pod - -deny[msga] { - pod := input[_] - pod.kind == "Pod" - podns := pod.metadata.namespace - podname := pod.metadata.name - labels := pod.metadata.labels - filtered_labels := json.remove(labels, ["pod-template-hash"]) - path := "metadata.labels" - service := input[_] - service.kind == "Service" - service.metadata.namespace == podns - service.spec.selector == filtered_labels - - hasSSHPorts(service) - - msga := { - "alertMessage": sprintf("pod %v/%v exposed by SSH services: %v", [podns, podname, service]), - "packagename": "armo_builtins", - "alertScore": 7, - "deletePaths": [path], - "failedPaths": [path], - "fixPaths": [], - "alertObject": { - "k8sApiObjects": [pod,service] - } - } -} - -deny[msga] { - wl := input[_] - spec_template_spec_patterns := {"Deployment","ReplicaSet","DaemonSet","StatefulSet","Job"} - spec_template_spec_patterns[wl.kind] - labels := wl.spec.template.metadata.labels - path := "spec.template.metadata.labels" - service := input[_] - service.kind == "Service" - service.metadata.namespace == wl.metadata.namespace - service.spec.selector == labels - - hasSSHPorts(service) - - msga := { - "alertMessage": sprintf("%v: %v is exposed by SSH services: %v", [wl.kind, wl.metadata.name, service]), - "packagename": "armo_builtins", - "alertScore": 7, - "deletePaths": [path], - "failedPaths": [path], - "alertObject": { - "k8sApiObjects": [wl,service] - } - } -} - -deny[msga] { - wl := input[_] - wl.kind == "CronJob" - labels := wl.spec.jobTemplate.spec.template.metadata.labels - path := "spec.jobTemplate.spec.template.metadata.labels" - service := input[_] - service.kind == "Service" - service.metadata.namespace == wl.metadata.namespace - service.spec.selector == labels - - hasSSHPorts(service) - - msga := { - "alertMessage": sprintf("%v: %v is exposed by SSH services: %v", [wl.kind, wl.metadata.name, service]), - "packagename": "armo_builtins", - "alertScore": 7, - "deletePaths": [path], - "failedPaths": [path], - "alertObject": { - "k8sApiObjects": [wl,service] - } - } -} - -hasSSHPorts(service) { - port := service.spec.ports[_] - port.port == 22 -} - - -hasSSHPorts(service) { - port := service.spec.ports[_] - port.port == 2222 -} - -hasSSHPorts(service) { - port := service.spec.ports[_] - port.targetPort == 22 -} - - -hasSSHPorts(service) { - port := service.spec.ports[_] - port.targetPort == 2222 -} diff --git a/rules/rule-can-ssh-to-pod/rule.metadata.json b/rules/rule-can-ssh-to-pod/rule.metadata.json deleted file mode 100644 index 5d2cc8311..000000000 --- a/rules/rule-can-ssh-to-pod/rule.metadata.json +++ /dev/null @@ -1,52 +0,0 @@ -{ - "name": "rule-can-ssh-to-pod", - "attributes": { - "microsoftK8sThreatMatrix": "Execution::SSH server running inside container", - "useUntilKubescapeVersion": "v1.0.133" - }, - "ruleLanguage": "Rego", - "match": [ - { - "apiGroups": [ - "" - ], - "apiVersions": [ - "v1" - ], - "resources": [ - "Pod", - "Service" - ] - }, - { - "apiGroups": [ - "apps" - ], - "apiVersions": [ - "v1" - ], - "resources": [ - "Deployment", - "ReplicaSet", - "DaemonSet", - "StatefulSet" - ] - }, - { - "apiGroups": [ - "batch" - ], - "apiVersions": [ - "*" - ], - "resources": [ - "Job", - "CronJob" - ] - } - ], - "ruleDependencies": [], - "description": "denies pods with SSH ports opened(22/222)", - "remediation": "", - "ruleQuery": "armo_builtins" -} \ No newline at end of file diff --git a/rules/rule-can-update-configmap/raw.rego b/rules/rule-can-update-configmap/raw.rego deleted file mode 100644 index 305e000d0..000000000 --- a/rules/rule-can-update-configmap/raw.rego +++ /dev/null @@ -1,170 +0,0 @@ -package armo_builtins - -import data.cautils - -# Fails if user can modify all configmaps, or if he can modify the 'coredns' configmap (default for coredns) -# RoleBinding to Role -deny [msga] { - configmaps := [configmap | configmap = input[_]; configmap.kind == "ConfigMap"] - configmap := configmaps[_] - configmap.metadata.name == "coredns" - - roles := [role | role= input[_]; role.kind == "Role"] - rolebindings := [rolebinding | rolebinding = input[_]; rolebinding.kind == "RoleBinding"] - role:= roles[_] - rolebinding := rolebindings[_] - - rule:= role.rules[_] - - canModifyConfigMapResource(rule) - canModifyConfigMapVerb(rule) - - rolebinding.roleRef.kind == "Role" - rolebinding.roleRef.name == role.metadata.name - rolebinding.metadata.namespace == "kube-system" - - - subject := rolebinding.subjects[i] - path := sprintf("subjects[%v]", [format_int(i, 10)]) - - msga := { - "alertMessage": sprintf("The following %v: %v can modify 'coredns' configmap", [subject.kind, subject.name]), - "alertScore": 6, - "deletePaths": [path], - "failedPaths": [path], - "packagename": "armo_builtins", - "alertObject": { - "k8sApiObjects": [role,rolebinding], - "externalObjects": { - "subject" : [subject] - } - } - } -} - - -# Fails if user can modify all configmaps, or if he can modify the 'coredns' configmap (default for coredns) -# RoleBinding to ClusterRole -deny[msga] { - configmaps := [configmap | configmap = input[_]; configmap.kind == "ConfigMap"] - configmap := configmaps[_] - configmap.metadata.name == "coredns" - - roles := [role | role= input[_]; role.kind == "ClusterRole"] - rolebindings := [rolebinding | rolebinding = input[_]; rolebinding.kind == "RoleBinding"] - role:= roles[_] - rolebinding := rolebindings[_] - - rule:= role.rules[_] - canModifyConfigMapResource(rule) - canModifyConfigMapVerb(rule) - - rolebinding.roleRef.kind == "ClusterRole" - rolebinding.roleRef.name == role.metadata.name - rolebinding.metadata.namespace == "kube-system" - - - - subject := rolebinding.subjects[i] - path := sprintf("subjects[%v]", [format_int(i, 10)]) - - msga := { - "alertMessage": sprintf("The following %v: %v can modify 'coredns' configmap", [subject.kind, subject.name]), - "alertScore": 6, - "deletePaths": [path], - "failedPaths": [path], - "packagename": "armo_builtins", - "alertObject": { - "k8sApiObjects": [role,rolebinding], - "externalObjects": { - "subject" : [subject] - } - } - } - -} - - -# Fails if user can modify all configmaps, or if he can modify the 'coredns' configmap (default for coredns) -# ClusterRoleBinding to ClusterRole -deny[msga] { - configmaps := [configmap | configmap = input[_]; configmap.kind == "ConfigMap"] - configmap := configmaps[_] - configmap.metadata.name == "coredns" - - roles := [role | role= input[_]; role.kind == "ClusterRole"] - clusterrolebindings := [rolebinding | rolebinding = input[_]; rolebinding.kind == "ClusterRoleBinding"] - role:= roles[_] - clusterrolebinding := clusterrolebindings[_] - - rule:= role.rules[_] - canModifyConfigMapResource(rule) - canModifyConfigMapVerb(rule) - - - clusterrolebinding.roleRef.kind == "ClusterRole" - clusterrolebinding.roleRef.name == role.metadata.name - - - - subject := clusterrolebinding.subjects[i] - path := sprintf("subjects[%v]", [format_int(i, 10)]) - - msga := { - "alertMessage": sprintf("The following %v: %v can modify 'coredns' configmap", [subject.kind, subject.name]), - "alertScore": 6, - "deletePaths": [path], - "failedPaths": [path], - "packagename": "armo_builtins", - "alertObject": { - "k8sApiObjects": [role,clusterrolebinding], - "externalObjects": { - "subject" : [subject] - } - } - } -} - - - - - - canModifyConfigMapResource(rule) { - not rule.resourceNames - cautils.list_contains(rule.resources,"configmaps") - } - - canModifyConfigMapResource(rule) { - not rule.resourceNames - is_api_group(rule) - cautils.list_contains(rule.resources,"*") - } - - canModifyConfigMapResource(rule) { - cautils.list_contains(rule.resources,"configmaps") - cautils.list_contains(rule.resourceNames,"coredns") - } - - canModifyConfigMapVerb(rule) { - cautils.list_contains(rule.verbs,"update") - } - - - canModifyConfigMapVerb(rule) { - cautils.list_contains(rule.verbs,"patch") - } - - canModifyConfigMapVerb(rule) { - cautils.list_contains(rule.verbs,"*") - } - - -is_api_group(rule) { - apiGroup := rule.apiGroups[_] - apiGroup == "*" -} - -is_api_group(rule) { - apiGroup := rule.apiGroups[_] - apiGroup == "" -} \ No newline at end of file diff --git a/rules/rule-can-update-configmap/rule.metadata.json b/rules/rule-can-update-configmap/rule.metadata.json deleted file mode 100644 index bfd5344e4..000000000 --- a/rules/rule-can-update-configmap/rule.metadata.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "name": "rule-can-update-configmap", - "attributes": { - "microsoftK8sThreatMatrix": "Lateral Movement::CoreDNS poisoning", - "useUntilKubescapeVersion": "v1.0.133" - }, - "ruleLanguage": "Rego", - "match": [ - { - "apiGroups": [ - "*" - ], - "apiVersions": [ - "*" - ], - "resources": [ - "Role", - "ClusterRole", - "ClusterRoleBinding", - "RoleBinding", - "ConfigMap" - ] - } - ], - "ruleDependencies": [ - { - "packageName": "cautils" - } - ], - "description": "determines which users can update/patch the 'coredns' configmap", - "remediation": "", - "ruleQuery": "armo_builtins", - "resourceCount": "subjects" - } \ No newline at end of file diff --git a/rules/rule-excessive-delete-rights/raw.rego b/rules/rule-excessive-delete-rights/raw.rego deleted file mode 100644 index a5560634f..000000000 --- a/rules/rule-excessive-delete-rights/raw.rego +++ /dev/null @@ -1,171 +0,0 @@ -package armo_builtins - -import data.cautils - -# fails if user can can delete important resources -# RoleBinding to Role -deny[msga] { - roles := [role | role= input[_]; role.kind == "Role"] - rolebindings := [rolebinding | rolebinding = input[_]; rolebinding.kind == "RoleBinding"] - role:= roles[_] - rolebinding := rolebindings[_] - - rule:= role.rules[_] - canDeleteResource(rule) - canDeleteVerb(rule) - - rolebinding.roleRef.kind == "Role" - rolebinding.roleRef.name == role.metadata.name - - subject := rolebinding.subjects[i] - path := sprintf("subjects[%v]", [format_int(i, 10)]) - - msga := { - "alertMessage": sprintf("The following %v: %v can delete important resources", [subject.kind, subject.name]), - "alertScore": 9, - "fixPaths": [], - "deletePaths": [path], - "failedPaths": [path], - "packagename": "armo_builtins", - "alertObject": { - "k8sApiObjects": [role,rolebinding], - "externalObjects": { - "subject" : [subject] - } - } - } -} - - -# fails if user can can delete important resources -# RoleBinding to ClusterRole -deny[msga] { - roles := [role | role= input[_]; role.kind == "ClusterRole"] - rolebindings := [rolebinding | rolebinding = input[_]; rolebinding.kind == "RoleBinding"] - role:= roles[_] - rolebinding := rolebindings[_] - - rule:= role.rules[_] - canDeleteResource(rule) - canDeleteVerb(rule) - - rolebinding.roleRef.kind == "ClusterRole" - rolebinding.roleRef.name == role.metadata.name - - subject := rolebinding.subjects[i] - path := sprintf("subjects[%v]", [format_int(i, 10)]) - - msga := { - "alertMessage": sprintf("The following %v: %v can delete important resources", [subject.kind, subject.name]), - "alertScore": 9, - "fixPaths": [], - "deletePaths": [path], - "failedPaths": [path], - "packagename": "armo_builtins", - "alertObject": { - "k8sApiObjects": [role,rolebinding], - "externalObjects": { - "subject" : [subject] - } - } - } -} - -# fails if user can can delete important resources -# ClusterRoleBinding to ClusterRole -deny[msga] { - roles := [role | role= input[_]; role.kind == "ClusterRole"] - clusterrolebindings := [rolebinding | rolebinding = input[_]; rolebinding.kind == "ClusterRoleBinding"] - role:= roles[_] - clusterrolebinding := clusterrolebindings[_] - - rule:= role.rules[_] - canDeleteResource(rule) - canDeleteVerb(rule) - - clusterrolebinding.roleRef.kind == "ClusterRole" - clusterrolebinding.roleRef.name == role.metadata.name - - - subject := clusterrolebinding.subjects[i] - path := sprintf("subjects[%v]", [format_int(i, 10)]) - - msga := { - "alertMessage": sprintf("The following %v: %v can delete important resources", [subject.kind, subject.name]), - "alertScore": 9, - "fixPaths": [], - "deletePaths": [path], - "failedPaths": [path], - "packagename": "armo_builtins", - "alertObject": { - "k8sApiObjects": [role,clusterrolebinding], - "externalObjects": { - "subject" : [subject] - } - } - } -} - - -canDeleteVerb(rule) { - cautils.list_contains(rule.verbs, "delete") -} - -canDeleteVerb(rule) { - cautils.list_contains(rule.verbs, "deletecollection") -} - -canDeleteVerb(rule) { - cautils.list_contains(rule.verbs, "*") -} - -canDeleteResource(rule) { - cautils.list_contains(rule.resources, "secrets") -} -canDeleteResource(rule) { - cautils.list_contains(rule.resources, "pods") -} -canDeleteResource(rule) { - cautils.list_contains(rule.resources, "services") -} -canDeleteResource(rule) { - cautils.list_contains(rule.resources, "deployments") -} -canDeleteResource(rule) { - cautils.list_contains(rule.resources, "replicasets") -} -canDeleteResource(rule) { - cautils.list_contains(rule.resources, "daemonsets") -} -canDeleteResource(rule) { - cautils.list_contains(rule.resources, "statefulsets") -} -canDeleteResource(rule) { - cautils.list_contains(rule.resources, "jobs") -} -canDeleteResource(rule) { - cautils.list_contains(rule.resources, "cronjobs") -} -canDeleteResource(rule) { - is_api_group(rule) - cautils.list_contains(rule.resources, "*") -} - - -is_api_group(rule) { - apiGroup := rule.apiGroups[_] - apiGroup == "" -} -is_api_group(rule) { - apiGroup := rule.apiGroups[_] - apiGroup == "*" -} -is_api_group(rule) { - apiGroup := rule.apiGroups[_] - apiGroup == "apps" -} -is_api_group(rule) { - apiGroup := rule.apiGroups[_] - apiGroup == "batch" -} - diff --git a/rules/rule-excessive-delete-rights/rule.metadata.json b/rules/rule-excessive-delete-rights/rule.metadata.json deleted file mode 100644 index dc33d12d8..000000000 --- a/rules/rule-excessive-delete-rights/rule.metadata.json +++ /dev/null @@ -1,29 +0,0 @@ -{ - "name": "rule-excessive-delete-rights", - "attributes": { - "m$K8sThreatMatrix": "Impact::Data Destruction", - "useUntilKubescapeVersion": "v1.0.133" - }, - "ruleLanguage": "Rego", - "match": [ - { - "apiGroups": [ - "rbac.authorization.k8s.io" - ], - "apiVersions": [ - "v1" - ], - "resources": [ - "Role", - "ClusterRole", - "ClusterRoleBinding", - "RoleBinding" - ] - } - ], - "ruleDependencies": [], - "description": "fails if user can delete important resources", - "remediation": "", - "ruleQuery": "armo_builtins", - "resourceCount": "subjects" - } \ No newline at end of file diff --git a/rules/rule-list-all-cluster-admins/raw.rego b/rules/rule-list-all-cluster-admins/raw.rego deleted file mode 100644 index fffa8bfa8..000000000 --- a/rules/rule-list-all-cluster-admins/raw.rego +++ /dev/null @@ -1,132 +0,0 @@ -package armo_builtins - -import data.cautils - -# input: roles -# apiversion: v1 -# does: returns roles+ related subjects in rolebinding - -deny[msga] { - roles := [role | role= input[_]; role.kind == "Role"] - rolebindings := [rolebinding | rolebinding = input[_]; rolebinding.kind == "RoleBinding"] - role:= roles[_] - rolebinding := rolebindings[_] - - rule:= role.rules[i] - canCreate(rule, i) - canCreateResources(rule, i) - - rolebinding.roleRef.kind == "Role" - rolebinding.roleRef.name == role.metadata.name - subject := rolebinding.subjects[i] - path := sprintf("subjects[%v]", [format_int(i, 10)]) - - msga := { - "alertMessage": sprintf("The following %v: %v have high privileges, such as cluster-admin", [subject.kind, subject.name]), - "alertScore": 9, - "fixPaths": [], - "deletePaths": [path], - "failedPaths": [path], - "packagename": "armo_builtins", - "alertObject": { - "k8sApiObjects": [role,rolebinding], - "externalObjects": { - "subject" : [subject] - } - } - } -} - -# input: ClusterRole -# apiversion: v1 -# does: returns clusterroles+ related subjects in rolebinding - -deny[msga] { - roles := [role | role= input[_]; role.kind == "ClusterRole"] - rolebindings := [rolebinding | rolebinding = input[_]; rolebinding.kind == "RoleBinding"] - role:= roles[_] - rolebinding := rolebindings[_] - - rule:= role.rules[i] - canCreate(rule, i) - canCreateResources(rule, i) - - rolebinding.roleRef.kind == "ClusterRole" - rolebinding.roleRef.name == role.metadata.name - - subject := rolebinding.subjects[i] - path := sprintf("subjects[%v]", [format_int(i, 10)]) - - msga := { - "alertMessage": sprintf("The following %v: %v have high privileges, such as cluster-admin", [subject.kind, subject.name]), - "alertScore": 9, - "fixPaths": [], - "deletePaths": [path], - "failedPaths": [path], - "packagename": "armo_builtins", - "alertObject": { - "k8sApiObjects": [role,rolebinding], - "externalObjects": { - "subject" : [subject] - } - } - } -} - -# input: ClusterRole -# apiversion: v1 -# does: returns clusterroles+ related subjects in clusterrolebinding - -deny[msga] { - roles := [role | role= input[_]; role.kind == "ClusterRole"] - rolebindings := [rolebinding | rolebinding = input[_]; rolebinding.kind == "ClusterRoleBinding"] - role:= roles[_] - rolebinding := rolebindings[_] - - rule:= role.rules[i] - canCreate(rule, i) - canCreateResources(rule, i) - - rolebinding.roleRef.kind == "ClusterRole" - rolebinding.roleRef.name == role.metadata.name - - subject := rolebinding.subjects[i] - path := sprintf("subjects[%v]", [format_int(i, 10)]) - - msga := { - "alertMessage": sprintf("The following %v: %v have high privileges, such as cluster-admin", [subject.kind, subject.name]), - "alertScore": 9, - "fixPaths": [], - "deletePaths": [path], - "failedPaths": [path], - "packagename": "armo_builtins", - "alertObject": { - "k8sApiObjects": [role,rolebinding], - "externalObjects": { - "subject" : [subject] - } - } - } -} - - -canCreate(rule, i) { - verb := rule.verbs[j] - verb == "*" -} - -canCreateResources(rule, i){ - is_api_group(rule) - resource := rule.resources[j] - resource == "*" -} - -is_api_group(rule) { - apiGroup := rule.apiGroups[_] - apiGroup == "" -} - -is_api_group(rule) { - apiGroup := rule.apiGroups[_] - apiGroup == "*" -} diff --git a/rules/rule-list-all-cluster-admins/rule.metadata.json b/rules/rule-list-all-cluster-admins/rule.metadata.json deleted file mode 100644 index 3cf574f7e..000000000 --- a/rules/rule-list-all-cluster-admins/rule.metadata.json +++ /dev/null @@ -1,33 +0,0 @@ -{ - "name": "rule-list-all-cluster-admins", - "attributes": { - "m$K8sThreatMatrix": "Privilege Escalation::Cluster-admin binding", - "useUntilKubescapeVersion": "v1.0.133" - }, - "ruleLanguage": "Rego", - "match": [ - { - "apiGroups": [ - "rbac.authorization.k8s.io" - ], - "apiVersions": [ - "v1" - ], - "resources": [ - "Role", - "ClusterRole", - "ClusterRoleBinding", - "RoleBinding" - ] - } - ], - "ruleDependencies": [ - { - "packageName": "cautils" - } - ], - "description": "determines which users have cluster admin permissions", - "remediation": "", - "ruleQuery": "armo_builtins", - "resourceCount": "subjects" -} \ No newline at end of file From 27745cc366cbc1db9ff5236f896e285de07f129b Mon Sep 17 00:00:00 2001 From: YiscahLevySilas1 Date: Tue, 2 Jan 2024 14:48:58 +0200 Subject: [PATCH 2/2] deprecate-old-rules Signed-off-by: YiscahLevySilas1 --- controls/C-0002-execintocontainer.json | 1 - controls/C-0007-datadestruction.json | 1 - controls/C-0014-accesskubernetesdashboard.json | 1 - controls/C-0015-listkubernetessecrets.json | 1 - controls/C-0021-exposedsensitiveinterfaces.json | 1 - controls/C-0031-deletekubernetesevents.json | 1 - controls/C-0035-clusteradminbinding.json | 1 - controls/C-0037-corednspoisoning.json | 1 - controls/C-0042-sshserverrunninginsidecontainer.json | 1 - controls/C-0053-accesscontainerserviceaccount.json | 1 - controls/C-0063-portforwardingprivileges.json | 1 - controls/C-0065-noimpersonation.json | 1 - 12 files changed, 12 deletions(-) diff --git a/controls/C-0002-execintocontainer.json b/controls/C-0002-execintocontainer.json index 9c0902c31..39c9b93f3 100644 --- a/controls/C-0002-execintocontainer.json +++ b/controls/C-0002-execintocontainer.json @@ -13,7 +13,6 @@ "description": "Attackers with relevant permissions can run malicious commands in the context of legitimate containers in the cluster using \u201ckubectl exec\u201d command. This control determines which subjects have permissions to use this command.", "remediation": "It is recommended to prohibit \u201ckubectl exec\u201d command in production environments. It is also recommended not to use subjects with this permission for daily cluster operations.", "rulesNames": [ - "exec-into-container", "exec-into-container-v1" ], "long_description": "Attackers who have permissions, can run malicious commands in containers in the cluster using exec command (\u201ckubectl exec\u201d). In this method, attackers can use legitimate images, such as an OS image (e.g., Ubuntu) as a backdoor container, and run their malicious code remotely by using \u201ckubectl exec\u201d.", diff --git a/controls/C-0007-datadestruction.json b/controls/C-0007-datadestruction.json index 984200f71..ae5fb367f 100644 --- a/controls/C-0007-datadestruction.json +++ b/controls/C-0007-datadestruction.json @@ -12,7 +12,6 @@ "description": "Attackers may attempt to destroy data and resources in the cluster. This includes deleting deployments, configurations, storage, and compute resources. This control identifies all subjects that can delete resources.", "remediation": "You should follow the least privilege principle and minimize the number of subjects that can delete resources.", "rulesNames": [ - "rule-excessive-delete-rights", "rule-excessive-delete-rights-v1" ], "long_description": "Attackers may attempt to destroy data and resources in the cluster. This includes deleting deployments, configurations, storage, and compute resources.", diff --git a/controls/C-0014-accesskubernetesdashboard.json b/controls/C-0014-accesskubernetesdashboard.json index 05740d557..84b01cfa3 100644 --- a/controls/C-0014-accesskubernetesdashboard.json +++ b/controls/C-0014-accesskubernetesdashboard.json @@ -13,7 +13,6 @@ "description": "Attackers who gain access to the dashboard service account or have its RBAC permissions can use its network access to retrieve information about resources in the cluster or change them. This control checks if a subject that is not dashboard service account is bound to dashboard role/clusterrole, or - if anyone that is not the dashboard pod is associated with dashboard service account.", "remediation": "Make sure that the \u201cKubernetes Dashboard\u201d service account is only bound to the Kubernetes dashboard following the least privilege principle.", "rulesNames": [ - "rule-access-dashboard", "rule-access-dashboard-subject-v1", "rule-access-dashboard-wl-v1" ], diff --git a/controls/C-0015-listkubernetessecrets.json b/controls/C-0015-listkubernetessecrets.json index 1f0203802..6474e7b85 100644 --- a/controls/C-0015-listkubernetessecrets.json +++ b/controls/C-0015-listkubernetessecrets.json @@ -13,7 +13,6 @@ "description": "Attackers who have permissions to access secrets can access sensitive information that might include credentials to various services. This control determines which user, group or service account can list/get secrets.", "remediation": "Monitor and approve list of users, groups and service accounts that can access secrets. Use exception mechanism to prevent repetitive the notifications.", "rulesNames": [ - "rule-can-list-get-secrets", "rule-can-list-get-secrets-v1" ], "long_description": "A Kubernetes secret is an object that lets users store and manage sensitive information, such as passwords and connection strings in the cluster. Secrets can be consumed by reference in the pod configuration. Attackers who have permissions to retrieve the secrets from the API server (by using the pod service account, for example) can access sensitive information that might include credentials to various services.", diff --git a/controls/C-0021-exposedsensitiveinterfaces.json b/controls/C-0021-exposedsensitiveinterfaces.json index d606eee15..8d51908b0 100644 --- a/controls/C-0021-exposedsensitiveinterfaces.json +++ b/controls/C-0021-exposedsensitiveinterfaces.json @@ -12,7 +12,6 @@ "description": "Exposing a sensitive interface to the internet poses a security risk. It might enable attackers to run malicious code or deploy containers in the cluster. This control checks if known components (e.g. Kubeflow, Argo Workflows, etc.) are deployed and exposed services externally.", "remediation": "Consider blocking external interfaces or protect them with appropriate security tools.", "rulesNames": [ - "exposed-sensitive-interfaces", "exposed-sensitive-interfaces-v1" ], "long_description": "Exposing a sensitive interface to the internet poses a security risk. Some popular frameworks were not intended to be exposed to the internet, and therefore don\u2019t require authentication by default. Thus, exposing them to the internet allows unauthenticated access to a sensitive interface which might enable running code or deploying containers in the cluster by a malicious actor. Examples of such interfaces that were seen exploited include Apache NiFi, Kubeflow, Argo Workflows, Weave Scope, and the Kubernetes dashboard.", diff --git a/controls/C-0031-deletekubernetesevents.json b/controls/C-0031-deletekubernetesevents.json index f862b18fd..7f76c856e 100644 --- a/controls/C-0031-deletekubernetesevents.json +++ b/controls/C-0031-deletekubernetesevents.json @@ -13,7 +13,6 @@ "description": "Attackers may delete Kubernetes events to avoid detection of their activity in the cluster. This control identifies all the subjects that can delete Kubernetes events.", "remediation": "You should follow the least privilege principle. Minimize the number of subjects who can delete Kubernetes events. Avoid using these subjects in the daily operations.", "rulesNames": [ - "rule-can-delete-k8s-events", "rule-can-delete-k8s-events-v1" ], "long_description": "A Kubernetes event is a Kubernetes object that logs state changes and failures of the resources in the cluster. Example events are a container creation, an image pull, or a pod scheduling on a node. Kubernetes events can be very useful for identifying changes that occur in the cluster. Therefore, attackers may want to delete these events (e.g., by using: \u201ckubectl delete events\u2013all\u201d) in an attempt to avoid detection of their activity in the cluster.", diff --git a/controls/C-0035-clusteradminbinding.json b/controls/C-0035-clusteradminbinding.json index 8e6cebce6..ef6cf7da4 100644 --- a/controls/C-0035-clusteradminbinding.json +++ b/controls/C-0035-clusteradminbinding.json @@ -13,7 +13,6 @@ "description": "Attackers who have cluster admin permissions (can perform any action on any resource), can take advantage of their privileges for malicious activities. This control determines which subjects have cluster admin permissions.", "remediation": "You should apply least privilege principle. Make sure cluster admin permissions are granted only when it is absolutely necessary. Don't use subjects with such high permissions for daily operations.", "rulesNames": [ - "rule-list-all-cluster-admins", "rule-list-all-cluster-admins-v1" ], "long_description": "Role-based access control (RBAC) is a key security feature in Kubernetes. RBAC can restrict the allowed actions of the various identities in the cluster. Cluster-admin is a built-in high privileged role in Kubernetes. Attackers who have permissions to create bindings and cluster-bindings in the cluster can create a binding to the cluster-admin ClusterRole or to other high privileges roles.", diff --git a/controls/C-0037-corednspoisoning.json b/controls/C-0037-corednspoisoning.json index 3eb69d04b..2ff4a9ce1 100644 --- a/controls/C-0037-corednspoisoning.json +++ b/controls/C-0037-corednspoisoning.json @@ -11,7 +11,6 @@ "description": "If attackers have permissions to modify the coredns ConfigMap they can change the behavior of the cluster\u2019s DNS, poison it, and override the network identity of other services. This control identifies all subjects allowed to update the 'coredns' configmap.", "remediation": "You should follow the least privilege principle. Monitor and approve all the subjects allowed to modify the 'coredns' configmap. It is also recommended to remove this permission from the users/service accounts used in the daily operations.", "rulesNames": [ - "rule-can-update-configmap", "rule-can-update-configmap-v1" ], "long_description": "CoreDNS is a modular Domain Name System (DNS) server written in Go, hosted by Cloud Native Computing Foundation (CNCF). CoreDNS is the main DNS service that is being used in Kubernetes. The configuration of CoreDNS can be modified by a file named corefile. In Kubernetes, this file is stored in a ConfigMap object, located at the kube-system namespace. If attackers have permissions to modify the ConfigMap, for example by using the container\u2019s service account, they can change the behavior of the cluster\u2019s DNS, poison it, and take the network identity of other services.", diff --git a/controls/C-0042-sshserverrunninginsidecontainer.json b/controls/C-0042-sshserverrunninginsidecontainer.json index 2163c6961..44d723272 100644 --- a/controls/C-0042-sshserverrunninginsidecontainer.json +++ b/controls/C-0042-sshserverrunninginsidecontainer.json @@ -11,7 +11,6 @@ "description": "An SSH server that is running inside a container may be used by attackers to get remote access to the container. This control checks if pods have an open SSH port (22/2222).", "remediation": "Remove SSH from the container image or limit the access to the SSH server using network policies.", "rulesNames": [ - "rule-can-ssh-to-pod", "rule-can-ssh-to-pod-v1" ], "long_description": "SSH server that is running inside a container may be used by attackers. If attackers gain valid credentials to a container, whether by brute force attempts or by other methods (such as phishing), they can use it to get remote access to the container by SSH.", diff --git a/controls/C-0053-accesscontainerserviceaccount.json b/controls/C-0053-accesscontainerserviceaccount.json index 4586605fa..a3a503532 100644 --- a/controls/C-0053-accesscontainerserviceaccount.json +++ b/controls/C-0053-accesscontainerserviceaccount.json @@ -13,7 +13,6 @@ "description": "Attackers who obtain access to a pod can use its SA token to communicate with KubeAPI server. All pods with SA token mounted (if such token has a Role or a ClusterRole binding) are considerred potentially dangerous.", "remediation": "Verify that RBAC is enabled. Follow the least privilege principle and ensure that only necessary pods have SA token mounted into them.", "rulesNames": [ - "access-container-service-account", "access-container-service-account-v1" ], "long_description": "Service account (SA) represents an application identity in Kubernetes. By default, an SA is mounted to every created pod in the cluster. Using the SA, containers in the pod can send requests to the Kubernetes API server. Attackers who get access to a pod can access the SA token (located in /var/run/secrets/kubernetes.io/serviceaccount/token) and perform actions in the cluster, according to the SA permissions. If RBAC is not enabled, the SA has unlimited permissions in the cluster. If RBAC is enabled, its permissions are determined by the RoleBindings\\\\ClusterRoleBindings that are associated with it.", diff --git a/controls/C-0063-portforwardingprivileges.json b/controls/C-0063-portforwardingprivileges.json index 905759773..dc93dc1aa 100644 --- a/controls/C-0063-portforwardingprivileges.json +++ b/controls/C-0063-portforwardingprivileges.json @@ -10,7 +10,6 @@ "description": "Attackers with relevant RBAC permission can use \u201ckubectl portforward\u201d command to establish direct communication with pods from within the cluster or even remotely. Such communication will most likely bypass existing security measures in the cluster. This control determines which subjects have permissions to use this command.", "remediation": "It is recommended to prohibit \u201ckubectl portforward\u201d command in production environments. It is also recommended not to use subjects with this permission for daily cluster operations.", "rulesNames": [ - "rule-can-portforward", "rule-can-portforward-v1" ], "long_description": "Attackers who have relevant RBAC permissions, can run open a backdoor communication channel directly to the sockets inside target container using exec command \u201ckubectl portforward\u201d command. Using this method, attackers can bypass network security restrictions and communicate directly with software in the containers.", diff --git a/controls/C-0065-noimpersonation.json b/controls/C-0065-noimpersonation.json index e1e872cf8..efa09b17c 100644 --- a/controls/C-0065-noimpersonation.json +++ b/controls/C-0065-noimpersonation.json @@ -12,7 +12,6 @@ "long_description": "Impersonation is an explicit RBAC permission to use other roles rather than the one assigned to a user, group or service account. This is sometimes needed for testing purposes. However, it is highly recommended not to use this capability in the production environments for daily operations. This control identifies all subjects whose roles include impersonate verb.", "test": "Check for RBACs giving 'impersonate' verb to users/groups/uids/serviceaccounts", "rulesNames": [ - "rule-can-impersonate-users-groups", "rule-can-impersonate-users-groups-v1" ], "controlID": "C-0065",