From b8ac7be26585cdb125502d6eeae05554de65762a Mon Sep 17 00:00:00 2001 From: Lucas Teixeira Date: Tue, 5 Dec 2023 09:41:37 -0300 Subject: [PATCH] checks for sudo in entrypoint & registry deprecated --- checks.md | 67 ++++++++------- .../M-408_sudo_container_entrypoint.yaml | 49 +++++++++++ .../M-408_sudo_container_entrypoint_test.yaml | 64 ++++++++++++++ .../M-409_deprecated_image_registry.yaml | 45 ++++++++++ .../M-409_deprecated_image_registry_test.yaml | 85 +++++++++++++++++++ pkg/loader/builtin_test.go | 2 +- 6 files changed, 279 insertions(+), 33 deletions(-) create mode 100644 internal/builtins/general/M-408_sudo_container_entrypoint.yaml create mode 100644 internal/builtins/general/M-408_sudo_container_entrypoint_test.yaml create mode 100644 internal/builtins/general/M-409_deprecated_image_registry.yaml create mode 100644 internal/builtins/general/M-409_deprecated_image_registry_test.yaml diff --git a/checks.md b/checks.md index 66f0807..7af890f 100644 --- a/checks.md +++ b/checks.md @@ -2,36 +2,39 @@ In the table below, you can view all checks present on Marvin. Click on the #ID column item for more details about each check. -| Framework | # ID | Severity | Message | -|------------------|---------------------------------------------------------------------------|----------|--------------------------------------------------------| -| CIS Benchmarks | [M-500](/internal/builtins/cis/M-500_default_namespace.yaml) | Medium | Workloads in default namespace | -| General | [M-400](/internal/builtins/general/M-400_image_tag_latest.yaml) | Medium | Image tagged latest | -| | [M-401](/internal/builtins/general/M-401_unmanaged_pod.yaml) | Low | Unmanaged Pod | -| | [M-402](/internal/builtins/general/M-402_readiness_probe.yaml) | Medium | Readiness and startup probe not configured | -| | [M-403](/internal/builtins/general/M-403_liveness_probe.yaml) | Medium | Liveness probe not configured | -| | [M-404](/internal/builtins/general/M-404_memory_requests.yaml) | Medium | Memory requests not specified | -| | [M-405](/internal/builtins/general/M-405_cpu_requests.yaml) | Medium | CPU requests not specified | -| | [M-406](/internal/builtins/general/M-406_memory_limit.yaml) | Medium | Memory not limited | -| | [M-407](/internal/builtins/general/M-407_cpu_limit.yaml) | Medium | CPU not limited | -| NSA-CISA | [M-300](/internal/builtins/nsa/M-300_read_only_root_filesystem.yml) | Low | Root filesystem write allowed | -| MITRE ATT&CK | [M-200](/internal/builtins/mitre/M-200_allowed_registries.yml) | Medium | Image registry not allowed | + +| Framework | #ID | Severity | Message | +|------------------|--------------------------------------------------------------------------|---------- |------------------------------------------------------| +| CIS Benchmarks | [M-500](/internal/builtins/cis/M-500_default_namespace.yaml) | Medium | Workloads in default namespace | +| General | [M-400](/internal/builtins/general/M-400_image_tag_latest.yaml) | Medium | Image tagged latest | +| | [M-401](/internal/builtins/general/M-401_unmanaged_pod.yaml) | Low | Unmanaged Pod | +| | [M-402](/internal/builtins/general/M-402_readiness_probe.yaml) | Medium | Readiness and startup probe not configured | +| | [M-403](/internal/builtins/general/M-403_liveness_probe.yaml) | Medium | Liveness probe not configured | +| | [M-404](/internal/builtins/general/M-404_memory_requests.yaml) | Medium | Memory requests not specified | +| | [M-405](/internal/builtins/general/M-405_cpu_requests.yaml) | Medium | CPU requests not specified | +| | [M-406](/internal/builtins/general/M-406_memory_limit.yaml) | Medium | Memory not limited | +| | [M-407](/internal/builtins/general/M-407_cpu_limit.yaml) | Medium | CPU not limited | +| | [M-408](/internal/builtins/general/M-408_sudo_container_entrypoint.yaml) | Medium | Sudo in container entrypoint | +| | [M-409](/internal/builtins/general/M-409_deprecated_image_registry.yaml) | Medium | Deprecated image registry | +| NSA-CISA | [M-300](/internal/builtins/nsa/M-300_read_only_root_filesystem.yml) | Low | Root filesystem write allowed | +| MITRE ATT&CK | [M-200](/internal/builtins/mitre/M-200_allowed_registries.yml) | Medium | Image registry not allowed | | | [M-201](/internal/builtins/mitre/M-201_app_credentials.yml) | High | Application credentials stored in configuration files | -| | [M-202](/internal/builtins/mitre/M-202_auto_mount_service_account.yml) | Low | Automounted service account token | -| | [M-203](/internal/builtins/mitre/M-203_ssh.yml) | Low | SSH server running inside container | -| PSS - Baseline | [M-100](/internal/builtins/pss/baseline/M-100_host_process.yml) | High | Privileged access to the Windows node | -| | [M-101](/internal/builtins/pss/baseline/M-101_host_namespaces.yml) | High | Host namespaces | -| | [M-102](/internal/builtins/pss/baseline/M-102_privileged_containers.yml) | High | Privileged container | -| | [M-103](/internal/builtins/pss/baseline/M-103_capabilities.yml) | High | Insecure capabilities | -| | [M-104](/internal/builtins/pss/baseline/M-104_host_path_volumes.yml) | High | HostPath volume | -| | [M-105](/internal/builtins/pss/baseline/M-105_host_ports.yml) | High | Not allowed hostPort | -| | [M-106](/internal/builtins/pss/baseline/M-106_apparmor.yml) | Medium | Forbidden AppArmor profile | -| | [M-107](/internal/builtins/pss/baseline/M-107_selinux.yml) | Medium | Forbidden SELinux options | -| | [M-108](/internal/builtins/pss/baseline/M-108_proc_mount.yml) | Medium | Forbidden proc mount type | -| | [M-109](/internal/builtins/pss/baseline/M-109_seccomp.yml) | Medium | Forbidden seccomp profile | -| | [M-110](/internal/builtins/pss/baseline/M-110_sysctls.yml) | Medium | Unsafe sysctls | -| PSS - Restricted | [M-111](/internal/builtins/pss/restricted/M-111_volume_types.yml) | Low | Not allowed volume type | -| | [M-112](/internal/builtins/pss/restricted/M-112_privilege_escalation.yml)| Medium | Allowed privilege escalation | -| | [M-113](/internal/builtins/pss/restricted/M-113_run_as_non_root.yml) | Medium | Container could be running as root user | -| | [M-114](/internal/builtins/pss/restricted/M-114_run_as_user.yml) | Low | Container running as root UID | -| | [M-115](/internal/builtins/pss/restricted/M-115_seccomp.yml) | Low | Not allowed seccomp profile | -| | [M-116](/internal/builtins/pss/restricted/M-116_capabilities.yml) | Low | Not allowed added/dropped capabilities | +| | [M-202](/internal/builtins/mitre/M-202_auto_mount_service_account.yml) | Low | Automounted service account token | +| | [M-203](/internal/builtins/mitre/M-203_ssh.yml) | Low | SSH server running inside container | +| PSS - Baseline | [M-100](/internal/builtins/pss/baseline/M-100_host_process.yml) | High | Privileged access to the Windows node | +| | [M-101](/internal/builtins/pss/baseline/M-101_host_namespaces.yml) | High | Host namespaces | +| | [M-102](/internal/builtins/pss/baseline/M-102_privileged_containers.yml) | High | Privileged container | +| | [M-103](/internal/builtins/pss/baseline/M-103_capabilities.yml) | High | Insecure capabilities | +| | [M-104](/internal/builtins/pss/baseline/M-104_host_path_volumes.yml) | High | HostPath volume | +| | [M-105](/internal/builtins/pss/baseline/M-105_host_ports.yml) | High | Not allowed hostPort | +| | [M-106](/internal/builtins/pss/baseline/M-106_apparmor.yml) | Medium | Forbidden AppArmor profile | +| | [M-107](/internal/builtins/pss/baseline/M-107_selinux.yml) | Medium | Forbidden SELinux options | +| | [M-108](/internal/builtins/pss/baseline/M-108_proc_mount.yml) | Medium | Forbidden proc mount type | +| | [M-109](/internal/builtins/pss/baseline/M-109_seccomp.yml) | Medium | Forbidden seccomp profile | +| | [M-110](/internal/builtins/pss/baseline/M-110_sysctls.yml) | Medium | Unsafe sysctls | +| PSS - Restricted | [M-111](/internal/builtins/pss/restricted/M-111_volume_types.yml) | Low | Not allowed volume type | +| | [M-112](/internal/builtins/pss/restricted/M-112_privilege_escalation.yml)| Medium | Allowed privilege escalation | +| | [M-113](/internal/builtins/pss/restricted/M-113_run_as_non_root.yml) | Medium | Container could be running as root user | +| | [M-114](/internal/builtins/pss/restricted/M-114_run_as_user.yml) | Low | Container running as root UID | +| | [M-115](/internal/builtins/pss/restricted/M-115_seccomp.yml) | Low | Not allowed seccomp profile | +| | [M-116](/internal/builtins/pss/restricted/M-116_capabilities.yml) | Low | Not allowed added/dropped capabilities | diff --git a/internal/builtins/general/M-408_sudo_container_entrypoint.yaml b/internal/builtins/general/M-408_sudo_container_entrypoint.yaml new file mode 100644 index 0000000..b575f4e --- /dev/null +++ b/internal/builtins/general/M-408_sudo_container_entrypoint.yaml @@ -0,0 +1,49 @@ +# Copyright 2023 Undistro Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +id: M-408 +slug: sudo-container-entrypoint +severity: Medium +message: "Sudo in container entrypoint" +match: + resources: + - group: "" + version: v1 + resource: pods + - group: apps + version: v1 + resource: deployments + - group: apps + version: v1 + resource: daemonsets + - group: apps + version: v1 + resource: statefulsets + - group: apps + version: v1 + resource: replicasets + - group: batch + version: v1 + resource: cronjobs + - group: batch + version: v1 + resource: jobs +validations: + - expression: > + allContainers.all(container, + !has(container.command) || + size(container.command) == 0 || + container.command.all(cmd, + !cmd.contains("sudo")) + ) \ No newline at end of file diff --git a/internal/builtins/general/M-408_sudo_container_entrypoint_test.yaml b/internal/builtins/general/M-408_sudo_container_entrypoint_test.yaml new file mode 100644 index 0000000..18cfc29 --- /dev/null +++ b/internal/builtins/general/M-408_sudo_container_entrypoint_test.yaml @@ -0,0 +1,64 @@ +# Copyright 2023 Undistro Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +- name: "command not set" + pass: true + input: | + apiVersion: v1 + kind: Pod + metadata: + name: nginx + labels: + app: nginx + spec: + containers: + - name: nginx + image: nginx + +- name: "command without sudo" + pass: true + input: | + apiVersion: v1 + kind: Pod + metadata: + name: nginx + labels: + app: nginx + spec: + containers: + - name: nginx + image: nginx + command: ["printenv"] + resources: + requests: + cpu: 5m + + +- name: "command with sudo on entrypoint" + pass: false + input: | + apiVersion: v1 + kind: Pod + metadata: + name: nginx + labels: + app: nginx + spec: + containers: + - name: nginx + image: nginx + command: ["sudo printenv"] + resources: + limits: + memory: 128Mi \ No newline at end of file diff --git a/internal/builtins/general/M-409_deprecated_image_registry.yaml b/internal/builtins/general/M-409_deprecated_image_registry.yaml new file mode 100644 index 0000000..12baf38 --- /dev/null +++ b/internal/builtins/general/M-409_deprecated_image_registry.yaml @@ -0,0 +1,45 @@ +# Copyright 2023 Undistro Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +id: M-409 +slug: depŕecated image registry +severity: Medium +message: "Deprecated image registry" +match: + resources: + - group: "" + version: v1 + resource: pods + - group: apps + version: v1 + resource: deployments + - group: apps + version: v1 + resource: daemonsets + - group: apps + version: v1 + resource: statefulsets + - group: apps + version: v1 + resource: replicasets + - group: batch + version: v1 + resource: cronjobs + - group: batch + version: v1 + resource: jobs +validations: + - expression: > + allContainers.all(container, + !container.image.contains("k8s.grc.io")) \ No newline at end of file diff --git a/internal/builtins/general/M-409_deprecated_image_registry_test.yaml b/internal/builtins/general/M-409_deprecated_image_registry_test.yaml new file mode 100644 index 0000000..868a65f --- /dev/null +++ b/internal/builtins/general/M-409_deprecated_image_registry_test.yaml @@ -0,0 +1,85 @@ +# Copyright 2023 Undistro Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +- name: "registry not defined" + pass: true + input: | + apiVersion: v1 + kind: Pod + metadata: + name: nginx + labels: + app: nginx + spec: + containers: + - name: nginx + image: nginx + + + +- name: "registry deprecated" + pass: false + input: | + apiVersion: v1 + kind: Pod + metadata: + name: nginx + labels: + app: nginx + spec: + containers: + - name: registry + image: registry.com:80/nginx@sha256:asdf + - name: ok2 + image: registry.com:80/nginx@sha256:asdf + - name: wrong + image: k8s.grc.io/pause + +- name: "registry deprecated middle" + pass: false + input: | + apiVersion: v1 + kind: Pod + metadata: + name: nginx + labels: + app: nginx + spec: + containers: + - name: registry + image: registry.com:80/nginx@sha256:asdf + - name: wrong + image: k8s.grc.io/pause + - name: ok2 + image: registry.com:80/nginx@sha256:asdf + + + +- name: "registry deprecated" + pass: false + input: | + apiVersion: v1 + kind: Pod + metadata: + name: nginx + labels: + app: nginx + spec: + containers: + - name: registry + image: registry.com:80/nginx@sha256:asdf + - name: registryOK + image: registry.com:80/nginx@sha256:asdf + - name: wrong + image: k8s.grc.io/pause \ No newline at end of file diff --git a/pkg/loader/builtin_test.go b/pkg/loader/builtin_test.go index 771284d..4186b8b 100644 --- a/pkg/loader/builtin_test.go +++ b/pkg/loader/builtin_test.go @@ -23,5 +23,5 @@ import ( func TestBuiltins(t *testing.T) { assert.NotNil(t, Builtins) assert.Greater(t, len(Builtins), 0) - assert.Equal(t, len(Builtins), 31) + assert.Equal(t, len(Builtins), 33) }