From 34f4171061df8ae1ea2f6d74127b63e59aabd273 Mon Sep 17 00:00:00 2001 From: Saurabh Pandit Date: Thu, 11 Jun 2020 22:36:12 +1000 Subject: [PATCH 1/3] CIS Policy 5.1.1 - disallow clusterrole binding to cluster-admin Signed-off-by: Saurabh Pandit --- policies/CIS.5.1.1.rego | 16 ++++++++++++++++ policies/CIS.5.1.1_test.rego | 31 +++++++++++++++++++++++++++++++ policies/lib/kubernetes.rego | 13 +++++++++++++ 3 files changed, 60 insertions(+) create mode 100644 policies/CIS.5.1.1.rego create mode 100644 policies/CIS.5.1.1_test.rego diff --git a/policies/CIS.5.1.1.rego b/policies/CIS.5.1.1.rego new file mode 100644 index 0000000000..39f5e7b050 --- /dev/null +++ b/policies/CIS.5.1.1.rego @@ -0,0 +1,16 @@ +package cis_5_1_1 + +import data.lib.kubernetes + +violation[msg] { + kubernetes.clusterrolebindings[clusterrolebinding] + not is_clusterrole_admin(clusterrolebinding) + msg = kubernetes.format(sprintf("ClusterRoleBinding %v - Binding to cluster-admin role is not allowed", [clusterrolebinding.metadata.name])) +} + +is_clusterrole_admin(clusterrolebinding) { + trace(sprintf("clusterroleRoleRefname: %v", [clusterrolebinding.roleRef.name])) + clusterrolebinding.roleRef.name == "cluster-admin" + trace(sprintf("clusterrolename: %v", [clusterrolebinding.metadata.name])) + startswith(clusterrolebinding.metadata.name, "system:") +} diff --git a/policies/CIS.5.1.1_test.rego b/policies/CIS.5.1.1_test.rego new file mode 100644 index 0000000000..12bc6a0df9 --- /dev/null +++ b/policies/CIS.5.1.1_test.rego @@ -0,0 +1,31 @@ +package cis_5_1_1 + +import data.lib.test + +test_violation { + test.violations(violation) with input as policy_input("example:view:binding", "cluster-admin") +} + +test_no_violation { + test.no_violations(violation) with input as policy_input("system:cluster-admin", "cluster-admin") +} + +policy_input(name, ref) = { + "apiVersion": "rbac.authorization.k8s.io/v1", + "kind": "ClusterRoleBinding", + "metadata": { + "name": name + }, + "roleRef": { + "apiGroup": "rbac.authorization.k8s.io", + "kind": "ClusterRole", + "name": ref + }, + "subjects": [ + { + "apiGroup": "rbac.authorization.k8s.io", + "kind": "Group", + "name": "system:masters" + } + ] +} diff --git a/policies/lib/kubernetes.rego b/policies/lib/kubernetes.rego index c2bf667077..c734dc2289 100644 --- a/policies/lib/kubernetes.rego +++ b/policies/lib/kubernetes.rego @@ -149,6 +149,19 @@ clusterroles[clusterrole] { clusterrole = object } +is_clusterrole_binding { + kind = "ClusterRoleBinding" +} + +is_clusterrole_binding { + kind = "ClusterRoleBindings" +} + +clusterrolebindings[clusterrolebinding] { + is_clusterrole_binding + clusterrolebinding = object +} + pod_containers(pod) = all_containers { keys = {"containers", "initContainers"} all_containers = [c | keys[k]; c = pod.spec[k][_]] From d4a74d7fe7830d386ea1ac471f5a0514595fa1ac Mon Sep 17 00:00:00 2001 From: Saurabh Pandit Date: Thu, 11 Jun 2020 22:55:00 +1000 Subject: [PATCH 2/3] Removed traces, added missing test case Signed-off-by: Saurabh Pandit --- policies/CIS.5.1.1.rego | 6 ++---- policies/CIS.5.1.1_test.rego | 4 ++++ 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/policies/CIS.5.1.1.rego b/policies/CIS.5.1.1.rego index 39f5e7b050..83c88bda8c 100644 --- a/policies/CIS.5.1.1.rego +++ b/policies/CIS.5.1.1.rego @@ -4,13 +4,11 @@ import data.lib.kubernetes violation[msg] { kubernetes.clusterrolebindings[clusterrolebinding] - not is_clusterrole_admin(clusterrolebinding) + is_clusterrole_admin(clusterrolebinding) msg = kubernetes.format(sprintf("ClusterRoleBinding %v - Binding to cluster-admin role is not allowed", [clusterrolebinding.metadata.name])) } is_clusterrole_admin(clusterrolebinding) { - trace(sprintf("clusterroleRoleRefname: %v", [clusterrolebinding.roleRef.name])) clusterrolebinding.roleRef.name == "cluster-admin" - trace(sprintf("clusterrolename: %v", [clusterrolebinding.metadata.name])) - startswith(clusterrolebinding.metadata.name, "system:") + startswith(clusterrolebinding.metadata.name, "system:") == false } diff --git a/policies/CIS.5.1.1_test.rego b/policies/CIS.5.1.1_test.rego index 12bc6a0df9..127032df4c 100644 --- a/policies/CIS.5.1.1_test.rego +++ b/policies/CIS.5.1.1_test.rego @@ -10,6 +10,10 @@ test_no_violation { test.no_violations(violation) with input as policy_input("system:cluster-admin", "cluster-admin") } +test_no_violation_2 { + test.no_violations(violation) with input as policy_input("stackdriver:fluentd-gcp", "stackdriver:fluentd-gcp") +} + policy_input(name, ref) = { "apiVersion": "rbac.authorization.k8s.io/v1", "kind": "ClusterRoleBinding", From 694c5b56d3c57ef7222af05ea7738de5f645f7aa Mon Sep 17 00:00:00 2001 From: Saurabh Pandit Date: Fri, 12 Jun 2020 10:53:07 +1000 Subject: [PATCH 3/3] Policy also applies to rolebinding binding cluster-admin clusterrole Signed-off-by: Saurabh Pandit --- policies/CIS.5.1.1.rego | 12 +++++++++--- policies/CIS.5.1.1_test.rego | 22 +++++++++++++++++----- 2 files changed, 26 insertions(+), 8 deletions(-) diff --git a/policies/CIS.5.1.1.rego b/policies/CIS.5.1.1.rego index 83c88bda8c..ac08402f4e 100644 --- a/policies/CIS.5.1.1.rego +++ b/policies/CIS.5.1.1.rego @@ -8,7 +8,13 @@ violation[msg] { msg = kubernetes.format(sprintf("ClusterRoleBinding %v - Binding to cluster-admin role is not allowed", [clusterrolebinding.metadata.name])) } -is_clusterrole_admin(clusterrolebinding) { - clusterrolebinding.roleRef.name == "cluster-admin" - startswith(clusterrolebinding.metadata.name, "system:") == false +violation[msg] { + kubernetes.rolebindings[rolebinding] + is_clusterrole_admin(rolebinding) + msg = kubernetes.format(sprintf("RoleBinding %v - Binding to cluster-admin role is not allowed", [rolebinding.metadata.name])) +} + +is_clusterrole_admin(rolebinding) { + rolebinding.roleRef.name == "cluster-admin" + startswith(rolebinding.metadata.name, "system:") == false } diff --git a/policies/CIS.5.1.1_test.rego b/policies/CIS.5.1.1_test.rego index 127032df4c..bda66cd622 100644 --- a/policies/CIS.5.1.1_test.rego +++ b/policies/CIS.5.1.1_test.rego @@ -3,20 +3,32 @@ package cis_5_1_1 import data.lib.test test_violation { - test.violations(violation) with input as policy_input("example:view:binding", "cluster-admin") + test.violations(violation) with input as policy_input("ClusterRoleBinding", "example:view:binding", "cluster-admin") +} + +test_violation_2 { + test.violations(violation) with input as policy_input("RoleBinding", "example:view:binding", "cluster-admin") } test_no_violation { - test.no_violations(violation) with input as policy_input("system:cluster-admin", "cluster-admin") + test.no_violations(violation) with input as policy_input("ClusterRoleBinding", "system:cluster-admin", "cluster-admin") } test_no_violation_2 { - test.no_violations(violation) with input as policy_input("stackdriver:fluentd-gcp", "stackdriver:fluentd-gcp") + test.no_violations(violation) with input as policy_input("RoleBinding", "system:cluster-admin", "cluster-admin") +} + +test_no_violation_3 { + test.no_violations(violation) with input as policy_input("ClusterRoleBinding", "stackdriver:fluentd-gcp", "stackdriver:fluentd-gcp") +} + +test_no_violation_4 { + test.no_violations(violation) with input as policy_input("RoleBinding", "stackdriver:fluentd-gcp", "stackdriver:fluentd-gcp") } -policy_input(name, ref) = { +policy_input(rolebindingkind, name, ref) = { "apiVersion": "rbac.authorization.k8s.io/v1", - "kind": "ClusterRoleBinding", + "kind": rolebindingkind, "metadata": { "name": name },