diff --git a/internal/builtins/cis/M-500_default_namespace.yaml b/internal/builtins/cis/M-500_default_namespace.yaml index 8576a15..72115e8 100644 --- a/internal/builtins/cis/M-500_default_namespace.yaml +++ b/internal/builtins/cis/M-500_default_namespace.yaml @@ -40,7 +40,4 @@ match: version: v1 resource: jobs validations: - - expression: > - has(object.metadata.namespace) - && (type(object.metadata.namespace) == string) - && !(object.metadata.namespace == 'default') + - expression: object.metadata.?namespace.orValue("default") != "default" diff --git a/internal/builtins/general/M-401_unmanaged_pod.yaml b/internal/builtins/general/M-401_unmanaged_pod.yaml index 9c3e102..db80a3c 100644 --- a/internal/builtins/general/M-401_unmanaged_pod.yaml +++ b/internal/builtins/general/M-401_unmanaged_pod.yaml @@ -21,9 +21,9 @@ match: - group: "" version: v1 resource: pods +variables: + - name: owners + expression: object.metadata.?ownerReferences.orValue([]) validations: - expression: > - has(object.metadata.ownerReferences) && - object.metadata.ownerReferences != null && - object.metadata.ownerReferences.size() > 0 && - object.metadata.ownerReferences.exists(o, has(o.controller) && o.controller == true) + variables.owners != null && variables.owners.exists(o, o.?controller.orValue(false) == true) diff --git a/internal/builtins/general/M-402_readiness_probe.yaml b/internal/builtins/general/M-402_readiness_probe.yaml index 6e24c4a..440af5e 100644 --- a/internal/builtins/general/M-402_readiness_probe.yaml +++ b/internal/builtins/general/M-402_readiness_probe.yaml @@ -33,14 +33,15 @@ match: - group: apps version: v1 resource: replicasets +variables: + - name: owners + expression: object.metadata.?ownerReferences.orValue([]) validations: - expression: > ( object.kind == "Pod" && - has(object.metadata.ownerReferences) && - object.metadata.ownerReferences != null && - object.metadata.ownerReferences.size() > 0 && - object.metadata.ownerReferences.exists(o, has(o.kind) && has(o.apiVersion) && o.kind == "Job" && o.apiVersion == "batch/v1") + variables.owners != null && + variables.owners.exists(o, o.?kind.orValue("") == "Job" && o.?apiVersion.orValue("") == "batch/v1") ) || - podSpec.containers.all(container, has(container.readinessProbe) || has(container.startupProbe)) + podSpec.containers.all(c, has(c.readinessProbe) || has(c.startupProbe)) diff --git a/internal/builtins/general/M-403_liveness_probe.yaml b/internal/builtins/general/M-403_liveness_probe.yaml index 5aab4d1..69b70d9 100644 --- a/internal/builtins/general/M-403_liveness_probe.yaml +++ b/internal/builtins/general/M-403_liveness_probe.yaml @@ -33,12 +33,15 @@ match: - group: apps version: v1 resource: replicasets +variables: + - name: owners + expression: object.metadata.?ownerReferences.orValue([]) validations: - expression: > ( object.kind == "Pod" && - has(object.metadata.ownerReferences) && - object.metadata.ownerReferences.exists(o, has(o.kind) && has(o.apiVersion) && o.kind == "Job" && o.apiVersion == "batch/v1") + variables.owners != null && + variables.owners.exists(o, o.?kind.orValue("") == "Job" && o.?apiVersion.orValue("") == "batch/v1") ) || - podSpec.containers.all(container, has(container.livenessProbe)) + podSpec.containers.all(c, has(c.livenessProbe)) diff --git a/internal/builtins/general/M-404_memory_requests.yaml b/internal/builtins/general/M-404_memory_requests.yaml index d05c1cc..7e0151c 100644 --- a/internal/builtins/general/M-404_memory_requests.yaml +++ b/internal/builtins/general/M-404_memory_requests.yaml @@ -41,8 +41,4 @@ match: resource: jobs validations: - expression: > - allContainers.all(container, - has(container.resources) && - has(container.resources.requests) && - has(container.resources.requests.memory) - ) + allContainers.all(c, c.?resources.?requests.?memory.orValue("") != "") diff --git a/internal/builtins/general/M-405_cpu_requests.yaml b/internal/builtins/general/M-405_cpu_requests.yaml index 9d036f3..3917e83 100644 --- a/internal/builtins/general/M-405_cpu_requests.yaml +++ b/internal/builtins/general/M-405_cpu_requests.yaml @@ -41,8 +41,4 @@ match: resource: jobs validations: - expression: > - allContainers.all(container, - has(container.resources) && - has(container.resources.requests) && - has(container.resources.requests.cpu) - ) + allContainers.all(c, c.?resources.?requests.?cpu.orValue("") != "") diff --git a/internal/builtins/general/M-406_memory_limit.yaml b/internal/builtins/general/M-406_memory_limit.yaml index 20b1fa1..0777610 100644 --- a/internal/builtins/general/M-406_memory_limit.yaml +++ b/internal/builtins/general/M-406_memory_limit.yaml @@ -41,8 +41,4 @@ match: resource: jobs validations: - expression: > - allContainers.all(container, - has(container.resources) && - has(container.resources.limits) && - has(container.resources.limits.memory) - ) + allContainers.all(c, c.?resources.?limits.?memory.orValue("") != "") diff --git a/internal/builtins/general/M-407_cpu_limit.yaml b/internal/builtins/general/M-407_cpu_limit.yaml index 84146f3..ee72488 100644 --- a/internal/builtins/general/M-407_cpu_limit.yaml +++ b/internal/builtins/general/M-407_cpu_limit.yaml @@ -41,8 +41,4 @@ match: resource: jobs validations: - expression: > - allContainers.all(container, - has(container.resources) && - has(container.resources.limits) && - has(container.resources.limits.cpu) - ) + allContainers.all(c, c.?resources.?limits.?cpu.orValue("") != "") diff --git a/internal/builtins/general/M-408_sudo_container_entrypoint.yaml b/internal/builtins/general/M-408_sudo_container_entrypoint.yaml index b575f4e..cfae784 100644 --- a/internal/builtins/general/M-408_sudo_container_entrypoint.yaml +++ b/internal/builtins/general/M-408_sudo_container_entrypoint.yaml @@ -41,9 +41,6 @@ match: 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 + allContainers.all(c, + c.?command.orValue([]).all(cmd, !cmd.contains("sudo")) + ) diff --git a/internal/builtins/general/M-409_deprecated_image_registry.yaml b/internal/builtins/general/M-409_deprecated_image_registry.yaml index 12baf38..b6276cf 100644 --- a/internal/builtins/general/M-409_deprecated_image_registry.yaml +++ b/internal/builtins/general/M-409_deprecated_image_registry.yaml @@ -41,5 +41,4 @@ match: resource: jobs validations: - expression: > - allContainers.all(container, - !container.image.contains("k8s.grc.io")) \ No newline at end of file + allContainers.all(c, !c.image.contains("k8s.grc.io")) diff --git a/internal/builtins/general/M-410_resource_using_invalid_restartpolicy.yaml b/internal/builtins/general/M-410_resource_using_invalid_restartpolicy.yaml index 6cbd2f4..de3a4b2 100644 --- a/internal/builtins/general/M-410_resource_using_invalid_restartpolicy.yaml +++ b/internal/builtins/general/M-410_resource_using_invalid_restartpolicy.yaml @@ -29,6 +29,4 @@ match: resource: replicasets validations: - expression: > - !has(podSpec.restartPolicy) || - has(podSpec.restartPolicy) && - (podSpec.restartPolicy =='Always') \ No newline at end of file + podSpec.?restartPolicy.orValue("Always") == 'Always' \ No newline at end of file diff --git a/internal/builtins/mitre/M-202_auto_mount_service_account.yml b/internal/builtins/mitre/M-202_auto_mount_service_account.yml index 5290b30..a49900a 100644 --- a/internal/builtins/mitre/M-202_auto_mount_service_account.yml +++ b/internal/builtins/mitre/M-202_auto_mount_service_account.yml @@ -41,5 +41,5 @@ match: resource: jobs validations: - expression: > - has(podSpec.automountServiceAccountToken) && podSpec.automountServiceAccountToken == false + podSpec.?automountServiceAccountToken.orValue(true) == false message: "Pod with Service Account token mounted automatically" diff --git a/internal/builtins/mitre/M-203_ssh.yml b/internal/builtins/mitre/M-203_ssh.yml index 817726f..aee6eba 100644 --- a/internal/builtins/mitre/M-203_ssh.yml +++ b/internal/builtins/mitre/M-203_ssh.yml @@ -50,7 +50,7 @@ validations: !has(object.spec.ports) || object.spec.ports.all(p, !(p.port in params.sshPorts) && - (!has(p.targetPort) || !(p.targetPort in params.sshPorts)) + !(p.?targetPort.orValue(0) in params.sshPorts) ) message: "Service could be routing to SSH server" diff --git a/internal/builtins/nsa/M-300_read_only_root_filesystem.yml b/internal/builtins/nsa/M-300_read_only_root_filesystem.yml index ffff934..8bed9bd 100644 --- a/internal/builtins/nsa/M-300_read_only_root_filesystem.yml +++ b/internal/builtins/nsa/M-300_read_only_root_filesystem.yml @@ -41,9 +41,5 @@ match: resource: jobs validations: - expression: > - allContainers.all(container, - has(container.securityContext) && - has(container.securityContext.readOnlyRootFilesystem) && - container.securityContext.readOnlyRootFilesystem == true - ) + allContainers.all(c, c.?securityContext.?readOnlyRootFilesystem.orValue(false) == true) message: "Container is able to write to the root filesystem" diff --git a/internal/builtins/pss/baseline/M-100_host_process.yml b/internal/builtins/pss/baseline/M-100_host_process.yml index 522f0a2..2877828 100644 --- a/internal/builtins/pss/baseline/M-100_host_process.yml +++ b/internal/builtins/pss/baseline/M-100_host_process.yml @@ -44,15 +44,8 @@ match: resource: jobs validations: - expression: > - !has(podSpec.securityContext) || - !has(podSpec.securityContext.windowsOptions) || - !has(podSpec.securityContext.windowsOptions.hostProcess) || - podSpec.securityContext.windowsOptions.hostProcess == false + podSpec.?securityContext.?windowsOptions.?hostProcess.orValue(false) == false message: "Pod with privileged access to the Windows node" - expression: > - allContainers.all(container, - !has(container.securityContext) || - !has(container.securityContext.windowsOptions) || - !has(container.securityContext.windowsOptions.hostProcess) || - container.securityContext.windowsOptions.hostProcess == false) + allContainers.all(c, c.?securityContext.?windowsOptions.?hostProcess.orValue(false) == false) message: "Container with privileged access to the Windows node" diff --git a/internal/builtins/pss/baseline/M-101_host_namespaces.yml b/internal/builtins/pss/baseline/M-101_host_namespaces.yml index 9dc366d..cbee988 100644 --- a/internal/builtins/pss/baseline/M-101_host_namespaces.yml +++ b/internal/builtins/pss/baseline/M-101_host_namespaces.yml @@ -44,7 +44,7 @@ match: resource: jobs validations: - expression: > - (!has(podSpec.hostNetwork) || podSpec.hostNetwork == false) && - (!has(podSpec.hostPID) || podSpec.hostPID == false) && - (!has(podSpec.hostIPC) || podSpec.hostIPC == false) + podSpec.?hostNetwork.orValue(false) == false && + podSpec.?hostPID.orValue(false) == false && + podSpec.?hostIPC.orValue(false) == false message: "Pod sharing host namespace" diff --git a/internal/builtins/pss/baseline/M-102_privileged_containers.yml b/internal/builtins/pss/baseline/M-102_privileged_containers.yml index 8772600..862417a 100644 --- a/internal/builtins/pss/baseline/M-102_privileged_containers.yml +++ b/internal/builtins/pss/baseline/M-102_privileged_containers.yml @@ -44,8 +44,5 @@ match: resource: jobs validations: - expression: > - allContainers.all(container, - !has(container.securityContext) || - !has(container.securityContext.privileged) || - container.securityContext.privileged == false) + allContainers.all(c, c.?securityContext.?privileged.orValue(false) == false) message: "Container running in privileged mode" diff --git a/internal/builtins/pss/baseline/M-103_capabilities.yml b/internal/builtins/pss/baseline/M-103_capabilities.yml index ad12d4f..2520c9e 100644 --- a/internal/builtins/pss/baseline/M-103_capabilities.yml +++ b/internal/builtins/pss/baseline/M-103_capabilities.yml @@ -59,10 +59,5 @@ params: - SYS_CHROOT validations: - expression: > - allContainers.all(container, - !has(container.securityContext) || - !has(container.securityContext.capabilities) || - !has(container.securityContext.capabilities.add) || - container.securityContext.capabilities.add.all(cap, cap in params.allowedCapabilities) - ) + allContainers.all(c, c.?securityContext.?capabilities.?add.orValue([]).all(cap, cap in params.allowedCapabilities)) message: "Container running with not allowed capabilities" diff --git a/internal/builtins/pss/baseline/M-104_host_path_volumes.yml b/internal/builtins/pss/baseline/M-104_host_path_volumes.yml index 4b69f8e..2d4ea19 100644 --- a/internal/builtins/pss/baseline/M-104_host_path_volumes.yml +++ b/internal/builtins/pss/baseline/M-104_host_path_volumes.yml @@ -44,5 +44,5 @@ match: resource: jobs validations: - expression: > - !has(podSpec.volumes) || podSpec.volumes.all(vol, !has(vol.hostPath)) + podSpec.?volumes.orValue([]).all(v, !has(v.hostPath)) message: "Pod with mounted host volume" diff --git a/internal/builtins/pss/baseline/M-105_host_ports.yml b/internal/builtins/pss/baseline/M-105_host_ports.yml index 814136e..52d7e07 100644 --- a/internal/builtins/pss/baseline/M-105_host_ports.yml +++ b/internal/builtins/pss/baseline/M-105_host_ports.yml @@ -43,15 +43,8 @@ match: version: v1 resource: jobs params: - allowedHostPorts: [] + allowedHostPorts: [0] validations: - expression: > - allContainers.all(container, - !has(container.ports) || - container.ports.all(port, - !has(port.hostPort) || - port.hostPort == 0 || - port.hostPort in params.allowedHostPorts - ) - ) + allContainers.all(c, c.?ports.orValue([]).all(p, p.?hostPort.orValue(0) in params.allowedHostPorts)) message: "Container exposing not allowed port on the host" diff --git a/internal/builtins/pss/baseline/M-107_selinux.yml b/internal/builtins/pss/baseline/M-107_selinux.yml index 3007e13..ab2adc6 100644 --- a/internal/builtins/pss/baseline/M-107_selinux.yml +++ b/internal/builtins/pss/baseline/M-107_selinux.yml @@ -47,48 +47,23 @@ params: - container_t - container_init_t - container_kvm_t + - "" validations: - expression: > - !has(podSpec.securityContext) || - !has(podSpec.securityContext.seLinuxOptions) || - !has(podSpec.securityContext.seLinuxOptions.type) || - podSpec.securityContext.seLinuxOptions.type == '' || - podSpec.securityContext.seLinuxOptions.type in params.allowedSELinuxTypes + podSpec.?securityContext.?seLinuxOptions.?type.orValue("") in params.allowedSELinuxTypes message: "Pod with not allowed SELinux type" - expression: > - allContainers.all(container, - !has(container.securityContext) || - !has(container.securityContext.seLinuxOptions) || - !has(container.securityContext.seLinuxOptions.type) || - container.securityContext.seLinuxOptions.type == '' || - container.securityContext.seLinuxOptions.type in params.allowedSELinuxTypes - ) + allContainers.all(c, c.?securityContext.?seLinuxOptions.?type.orValue("") in params.allowedSELinuxTypes) message: "Container with not allowed SELinux type" - expression: > - !has(podSpec.securityContext) || - !has(podSpec.securityContext.seLinuxOptions) || - !has(podSpec.securityContext.seLinuxOptions.user) || - podSpec.securityContext.seLinuxOptions.user == '' + podSpec.?securityContext.?seLinuxOptions.?user.orValue("") == "" message: "Pod with forbidden SELinux user" - expression: > - allContainers.all(container, - !has(container.securityContext) || - !has(container.securityContext.seLinuxOptions) || - !has(container.securityContext.seLinuxOptions.user) || - container.securityContext.seLinuxOptions.user == '' - ) + allContainers.all(c, c.?securityContext.?seLinuxOptions.?user.orValue("") == "") message: "Container with forbidden SELinux user" - expression: > - !has(podSpec.securityContext) || - !has(podSpec.securityContext.seLinuxOptions) || - !has(podSpec.securityContext.seLinuxOptions.role) || - podSpec.securityContext.seLinuxOptions.role == '' + podSpec.?securityContext.?seLinuxOptions.?role.orValue("") == "" message: "Pod with forbidden SELinux role" - expression: > - allContainers.all(container, - !has(container.securityContext) || - !has(container.securityContext.seLinuxOptions) || - !has(container.securityContext.seLinuxOptions.role) || - container.securityContext.seLinuxOptions.role == '' - ) + allContainers.all(c, c.?securityContext.?seLinuxOptions.?role.orValue("") == "") message: "Container with forbidden SELinux role" diff --git a/internal/builtins/pss/baseline/M-108_proc_mount.yml b/internal/builtins/pss/baseline/M-108_proc_mount.yml index 6835bf9..36b3080 100644 --- a/internal/builtins/pss/baseline/M-108_proc_mount.yml +++ b/internal/builtins/pss/baseline/M-108_proc_mount.yml @@ -44,9 +44,5 @@ match: resource: jobs validations: - expression: > - allContainers.all(container, - !has(container.securityContext) || - !has(container.securityContext.procMount) || - container.securityContext.procMount == 'Default' - ) + allContainers.all(c, c.?securityContext.?procMount.orValue("Default") == "Default") message: "Container using forbidden proc mount type" diff --git a/internal/builtins/pss/baseline/M-109_seccomp.yml b/internal/builtins/pss/baseline/M-109_seccomp.yml index b45dd29..f360cfa 100644 --- a/internal/builtins/pss/baseline/M-109_seccomp.yml +++ b/internal/builtins/pss/baseline/M-109_seccomp.yml @@ -44,16 +44,8 @@ match: resource: jobs validations: - expression: > - !has(podSpec.securityContext) || - !has(podSpec.securityContext.seccompProfile) || - !has(podSpec.securityContext.seccompProfile.type) || - podSpec.securityContext.seccompProfile.type != 'Unconfined' + podSpec.?securityContext.?seccompProfile.?type.orValue("") != "Unconfined" message: "Pod using forbidden seccomp profile" - expression: > - allContainers.all(container, - !has(container.securityContext) || - !has(container.securityContext.seccompProfile) || - !has(container.securityContext.seccompProfile.type) || - container.securityContext.seccompProfile.type != 'Unconfined' - ) + allContainers.all(c, c.?securityContext.?seccompProfile.?type.orValue("") != "Unconfined") message: "Container using forbidden seccomp profile" diff --git a/internal/builtins/pss/baseline/M-110_sysctls.yml b/internal/builtins/pss/baseline/M-110_sysctls.yml index 411820b..b526cc4 100644 --- a/internal/builtins/pss/baseline/M-110_sysctls.yml +++ b/internal/builtins/pss/baseline/M-110_sysctls.yml @@ -49,11 +49,12 @@ params: - net.ipv4.ip_unprivileged_port_start - net.ipv4.tcp_syncookies - net.ipv4.ping_group_range +variables: + - name: sysctls + expression: podSpec.?securityContext.?sysctls.orValue([]) validations: - expression: > - !has(podSpec.securityContext) || - !has(podSpec.securityContext.sysctls) || - podSpec.securityContext.sysctls.all(s, + variables.sysctls.size() == 0 || variables.sysctls.all(s, s.name == null || s.name in params.allowedSysctls ) diff --git a/internal/builtins/pss/restricted/M-111_volume_types.yml b/internal/builtins/pss/restricted/M-111_volume_types.yml index 497df82..3079a34 100644 --- a/internal/builtins/pss/restricted/M-111_volume_types.yml +++ b/internal/builtins/pss/restricted/M-111_volume_types.yml @@ -52,10 +52,12 @@ params: - persistentVolumeClaim - projected - secret +variables: + - name: volumes + expression: podSpec.?volumes.orValue([]) validations: - expression: > - !has(podSpec.volumes) || - podSpec.volumes.all(volume, - volume.exists(key, key in params.allowedVolumeTypes) + variables.volumes.size() == 0 || variables.volumes.all(v, + v.exists(key, key in params.allowedVolumeTypes) ) message: "Not allowed volume type used" diff --git a/internal/builtins/pss/restricted/M-112_privilege_escalation.yml b/internal/builtins/pss/restricted/M-112_privilege_escalation.yml index 6642f52..70fefd5 100644 --- a/internal/builtins/pss/restricted/M-112_privilege_escalation.yml +++ b/internal/builtins/pss/restricted/M-112_privilege_escalation.yml @@ -42,11 +42,9 @@ match: - group: batch version: v1 resource: jobs +variables: + - name: isWindows + expression: podSpec.?os.?name.orValue("") == "windows" validations: - expression: > - allContainers.all(container, - !has(container.securityContext) || - !has(container.securityContext.allowPrivilegeEscalation) || - container.securityContext.allowPrivilegeEscalation == false - ) - message: "Container with allowed privilege escalation" + variables.isWindows || allContainers.all(c, c.?securityContext.?allowPrivilegeEscalation.orValue(true) == false) diff --git a/internal/builtins/pss/restricted/M-112_privilege_escalation_test.yml b/internal/builtins/pss/restricted/M-112_privilege_escalation_test.yml index 729490f..f4992e7 100644 --- a/internal/builtins/pss/restricted/M-112_privilege_escalation_test.yml +++ b/internal/builtins/pss/restricted/M-112_privilege_escalation_test.yml @@ -13,7 +13,7 @@ # limitations under the License. - name: "securityContext not specified" - pass: true + pass: false input: | apiVersion: apps/v1 kind: Deployment @@ -34,7 +34,7 @@ app: nginx - name: "securityContext.allowPrivilegeEscalation not specified" - pass: true + pass: false input: | apiVersion: apps/v1 kind: Deployment @@ -81,7 +81,6 @@ - name: "securityContext.allowPrivilegeEscalation set to true" pass: false - message: "Container with allowed privilege escalation" input: | apiVersion: apps/v1 kind: Deployment @@ -102,3 +101,21 @@ selector: matchLabels: app: nginx + +- name: "windows" + pass: true + input: | + apiVersion: v1 + kind: Pod + metadata: + name: nginx + labels: + app: nginx + spec: + os: + name: windows + containers: + - name: nginx + image: nginx + securityContext: + allowPrivilegeEscalation: true diff --git a/internal/builtins/pss/restricted/M-113_run_as_non_root.yml b/internal/builtins/pss/restricted/M-113_run_as_non_root.yml index a53abfa..6b446cb 100644 --- a/internal/builtins/pss/restricted/M-113_run_as_non_root.yml +++ b/internal/builtins/pss/restricted/M-113_run_as_non_root.yml @@ -47,6 +47,10 @@ variables: - name: podRunAsNonRoot expression: podSpec.?securityContext.?runAsNonRoot.orValue(false) + # pod-level runAsNonRoot is explicitly set to false + - name: podRunAsRoot + expression: podSpec.?securityContext.?runAsNonRoot.orValue(true) == false + # pod-level runAsUser is explicitly set to non-zero - name: podRunAsNonZeroUser expression: podSpec.?securityContext.?runAsUser.orValue(0) != 0 @@ -71,4 +75,5 @@ variables: ) validations: - - expression: variables.explicitlyBadContainers.size() == 0 && variables.implicitlyBadContainers.size() == 0 + - expression: > + !variables.podRunAsRoot && variables.explicitlyBadContainers.size() == 0 && variables.implicitlyBadContainers.size() == 0 diff --git a/internal/builtins/pss/restricted/M-113_run_as_non_root_test.yml b/internal/builtins/pss/restricted/M-113_run_as_non_root_test.yml index f3af73f..6fb16de 100644 --- a/internal/builtins/pss/restricted/M-113_run_as_non_root_test.yml +++ b/internal/builtins/pss/restricted/M-113_run_as_non_root_test.yml @@ -57,7 +57,7 @@ app: nginx - name: "Pod set runAsNonRoot to false and container to true" - pass: true + pass: false input: | apiVersion: apps/v1 kind: Deployment diff --git a/internal/builtins/pss/restricted/M-114_run_as_user.yml b/internal/builtins/pss/restricted/M-114_run_as_user.yml index 91fa9cc..2a03754 100644 --- a/internal/builtins/pss/restricted/M-114_run_as_user.yml +++ b/internal/builtins/pss/restricted/M-114_run_as_user.yml @@ -44,9 +44,6 @@ match: resource: jobs validations: - expression: > - (!has(podSpec.securityContext) || !has(podSpec.securityContext.runAsUser) || podSpec.securityContext.runAsUser != 0) - && - allContainers.all(container, - !has(container.securityContext) || !has(container.securityContext.runAsUser) || container.securityContext.runAsUser != 0 - ) + podSpec.?securityContext.?runAsUser.orValue(-1) != 0 && + allContainers.all(c, c.?securityContext.?runAsUser.orValue(-1) != 0) message: "Container running as root UID" diff --git a/internal/builtins/pss/restricted/M-115_seccomp.yml b/internal/builtins/pss/restricted/M-115_seccomp.yml index f44da59..59512d5 100644 --- a/internal/builtins/pss/restricted/M-115_seccomp.yml +++ b/internal/builtins/pss/restricted/M-115_seccomp.yml @@ -42,34 +42,33 @@ match: - group: batch version: v1 resource: jobs -validations: - # Pod or Containers must set `securityContext.seccompProfile.type` - - expression: > - ( - has(podSpec.securityContext) && - has(podSpec.securityContext.seccompProfile) && - has(podSpec.securityContext.seccompProfile.type) - ) || - allContainers.all(container, - has(container.securityContext) && - has(container.securityContext.seccompProfile) && - has(container.securityContext.seccompProfile.type) +variables: + # pod-level seccompProfile is explicitly different to Unconfined + - name: podSeccompSet + expression: podSpec.?securityContext.?seccompProfile.?type.orValue("Unconfined") != "Unconfined" + + # pod-level seccompProfile is explicitly Unconfined + - name: podSeccompUnconfined + expression: podSpec.?securityContext.?seccompProfile.?type.orValue("") == "Unconfined" + + # containers that explicitly set seccompProfile.type to Unconfined + - name: explicitlyBadContainers + expression: allContainers.filter(c, c.?securityContext.?seccompProfile.?type.orValue("") == "Unconfined") + + # containers that didn't set seccompProfile and aren't caught by a pod-level seccompProfile + - name: implicitlyBadContainers + expression: > + allContainers.filter(c, + !variables.podSeccompSet && c.?securityContext.?seccompProfile.orValue(null) == null ) - message: "Seccomp profile not set" - # Neither Pod nor Containers should set `securityContext.seccompProfile.type` to Unconfined + - name: isWindows + expression: podSpec.?os.?name.orValue("") == "windows" +validations: - expression: > - ( - !has(podSpec.securityContext) || - !has(podSpec.securityContext.seccompProfile) || - !has(podSpec.securityContext.seccompProfile.type) || - podSpec.securityContext.seccompProfile.type != 'Unconfined' - ) - && - allContainers.all(container, - !has(container.securityContext) || - !has(container.securityContext.seccompProfile) || - !has(container.securityContext.seccompProfile.type) || - container.securityContext.seccompProfile.type != 'Unconfined' + variables.isWindows || + ( + !variables.podSeccompUnconfined && + variables.explicitlyBadContainers.size() == 0 && + variables.implicitlyBadContainers.size() == 0 ) - message: "Forbidden seccomp profile" diff --git a/internal/builtins/pss/restricted/M-115_seccomp_test.yml b/internal/builtins/pss/restricted/M-115_seccomp_test.yml index 2734b80..bf2fbb5 100644 --- a/internal/builtins/pss/restricted/M-115_seccomp_test.yml +++ b/internal/builtins/pss/restricted/M-115_seccomp_test.yml @@ -14,7 +14,6 @@ - name: "securityContext not specified" pass: false - message: "Seccomp profile not set" input: | apiVersion: apps/v1 kind: Deployment @@ -36,7 +35,6 @@ - name: "securityContext.seccompProfile not specified" pass: false - message: "Seccomp profile not set" input: | apiVersion: apps/v1 kind: Deployment @@ -110,7 +108,6 @@ - name: "Container securityContext.seccompProfile.type set to Unconfined" pass: false - message: "Forbidden seccomp profile" input: | apiVersion: apps/v1 kind: Deployment @@ -138,7 +135,6 @@ - name: "Pod securityContext.seccompProfile.type set to Unconfined" pass: false - message: "Forbidden seccomp profile" input: | apiVersion: apps/v1 kind: Deployment @@ -163,3 +159,22 @@ selector: matchLabels: app: nginx + +- name: "windows" + pass: true + input: | + apiVersion: v1 + kind: Pod + metadata: + name: nginx + labels: + app: nginx + spec: + os: + name: windows + containers: + - name: nginx + image: nginx + securityContext: + seccompProfile: + type: Unconfined diff --git a/internal/builtins/pss/restricted/M-116_capabilities.yml b/internal/builtins/pss/restricted/M-116_capabilities.yml index 1de5f42..eeb878f 100644 --- a/internal/builtins/pss/restricted/M-116_capabilities.yml +++ b/internal/builtins/pss/restricted/M-116_capabilities.yml @@ -45,21 +45,13 @@ match: params: allowedCapabilities: - NET_BIND_SERVICE +variables: + - name: isWindows + expression: podSpec.?os.?name.orValue("") == "windows" validations: - expression: > - allContainers.all(container, - has(container.securityContext) && - has(container.securityContext.capabilities) && - has(container.securityContext.capabilities.drop) && - size(container.securityContext.capabilities.drop) >= 1 && - container.securityContext.capabilities.drop.exists(c, c == 'ALL') - ) + variables.isWindows || allContainers.all(c, c.?securityContext.?capabilities.?drop.orValue([]).exists(ca, ca == 'ALL')) message: "Containers must drop ALL capabilities" - expression: > - allContainers.all(container, - !has(container.securityContext) || - !has(container.securityContext.capabilities) || - !has(container.securityContext.capabilities.add) || - container.securityContext.capabilities.add.all(cap, cap in params.allowedCapabilities) - ) + variables.isWindows || allContainers.all(c, c.?securityContext.?capabilities.?add.orValue([]).all(ca, ca in params.allowedCapabilities)) message: "Container running with not allowed capabilities" diff --git a/internal/builtins/pss/restricted/M-116_capabilities_test.yml b/internal/builtins/pss/restricted/M-116_capabilities_test.yml index bb743c9..6cf60de 100644 --- a/internal/builtins/pss/restricted/M-116_capabilities_test.yml +++ b/internal/builtins/pss/restricted/M-116_capabilities_test.yml @@ -157,3 +157,20 @@ selector: matchLabels: app: nginx + +- name: "windows" + pass: true + input: | + apiVersion: v1 + kind: Pod + metadata: + name: nginx + labels: + app: nginx + spec: + os: + name: windows + containers: + - name: nginx + image: nginx + securityContext: {}