From ef308b7ece0b0058a761265352489f09d40ab2bf Mon Sep 17 00:00:00 2001 From: Johannes Feichtner Date: Wed, 27 Apr 2022 23:31:39 +0200 Subject: [PATCH] feat(query): add new k8s rule to detect port-forwarding into containers (RBAC) --- .../metadata.json | 10 ++++++++ .../query.rego | 24 +++++++++++++++++++ .../test/negative.yaml | 23 ++++++++++++++++++ .../test/positive.yaml | 23 ++++++++++++++++++ .../test/positive_expected_result.json | 7 ++++++ 5 files changed, 87 insertions(+) create mode 100644 assets/queries/k8s/rbac_roles_with_portforwarding_permissions/metadata.json create mode 100644 assets/queries/k8s/rbac_roles_with_portforwarding_permissions/query.rego create mode 100644 assets/queries/k8s/rbac_roles_with_portforwarding_permissions/test/negative.yaml create mode 100644 assets/queries/k8s/rbac_roles_with_portforwarding_permissions/test/positive.yaml create mode 100644 assets/queries/k8s/rbac_roles_with_portforwarding_permissions/test/positive_expected_result.json diff --git a/assets/queries/k8s/rbac_roles_with_portforwarding_permissions/metadata.json b/assets/queries/k8s/rbac_roles_with_portforwarding_permissions/metadata.json new file mode 100644 index 00000000000..afea388f930 --- /dev/null +++ b/assets/queries/k8s/rbac_roles_with_portforwarding_permissions/metadata.json @@ -0,0 +1,10 @@ +{ + "id": "38fa11ef-dbcc-4da8-9680-7e1fd855b6fb", + "queryName": "RBAC Roles with Port-Forwarding Permission", + "severity": "MEDIUM", + "category": "Access Control", + "descriptionText": "Roles or ClusterRoles with RBAC permissions to port-forward into pods can open socket-level communication channels to containers. In case of compromise, attackers may abuse this for direct communication that bypasses network security restrictions", + "descriptionUrl": "https://kubernetes.io/docs/reference/access-authn-authz/rbac/", + "platform": "Kubernetes", + "descriptionID": "38fa11ef" +} diff --git a/assets/queries/k8s/rbac_roles_with_portforwarding_permissions/query.rego b/assets/queries/k8s/rbac_roles_with_portforwarding_permissions/query.rego new file mode 100644 index 00000000000..81beac907c0 --- /dev/null +++ b/assets/queries/k8s/rbac_roles_with_portforwarding_permissions/query.rego @@ -0,0 +1,24 @@ +package Cx + +import data.generic.common as common_lib + +CxPolicy[result] { + document := input.document[i] + metadata := document.metadata + + kinds := {"Role", "ClusterRole"} + document.kind == kinds[_] + + verbs := {"update", "patch", "create", "*"} + document.rules[j].resources[_] == "pods/portforward" + document.rules[j].verbs[_] == verbs[_] + + result := { + "documentId": document.id, + "searchKey": sprintf("metadata.name={{%s}}.rules", [metadata.name]), + "issueType": "IncorrectValue", + "keyExpectedValue": sprintf("metadata.name={{%s}}.rules[%d].resources should not include the 'pods/portforward' resource", [metadata.name, j]), + "keyActualValue": sprintf("metadata.name={{%s}}.rules[%d].resources includes the 'pods/portforward' resource", [metadata.name, j]), + "searchLine": common_lib.build_search_line(["rules", j], ["resources"]) + } +} diff --git a/assets/queries/k8s/rbac_roles_with_portforwarding_permissions/test/negative.yaml b/assets/queries/k8s/rbac_roles_with_portforwarding_permissions/test/negative.yaml new file mode 100644 index 00000000000..1e242b37140 --- /dev/null +++ b/assets/queries/k8s/rbac_roles_with_portforwarding_permissions/test/negative.yaml @@ -0,0 +1,23 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + namespace: my-namespace + name: allow-port-forward-neg +rules: +- apiGroups: [""] + resources: ["pods"] + verbs: ["get", "list", "create"] +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: allow-port-forward-neg + namespace: my-namespace +subjects: +- kind: User + name: bob + apiGroup: rbac.authorization.k8s.io +roleRef: + kind: Role + name: allow-port-forward-neg + apiGroup: "" \ No newline at end of file diff --git a/assets/queries/k8s/rbac_roles_with_portforwarding_permissions/test/positive.yaml b/assets/queries/k8s/rbac_roles_with_portforwarding_permissions/test/positive.yaml new file mode 100644 index 00000000000..7ffc711a44c --- /dev/null +++ b/assets/queries/k8s/rbac_roles_with_portforwarding_permissions/test/positive.yaml @@ -0,0 +1,23 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + namespace: my-namespace + name: allow-port-forward +rules: +- apiGroups: [""] + resources: ["pods", "pods/portforward"] + verbs: ["get", "list", "create"] +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: allow-port-forward + namespace: my-namespace +subjects: +- kind: User + name: bob + apiGroup: rbac.authorization.k8s.io +roleRef: + kind: Role + name: allow-port-forward + apiGroup: "" \ No newline at end of file diff --git a/assets/queries/k8s/rbac_roles_with_portforwarding_permissions/test/positive_expected_result.json b/assets/queries/k8s/rbac_roles_with_portforwarding_permissions/test/positive_expected_result.json new file mode 100644 index 00000000000..d5deff99de9 --- /dev/null +++ b/assets/queries/k8s/rbac_roles_with_portforwarding_permissions/test/positive_expected_result.json @@ -0,0 +1,7 @@ +[ + { + "queryName": "RBAC Roles with Port-Forwarding Permission", + "severity": "MEDIUM", + "line": 8 + } +]