All Policies
Ensure Read Only hostPath
Pods which are allowed to mount hostPath volumes in read/write mode pose a security risk even if confined to a "safe" file system on the host and may escape those confines (see https://blog.aquasec.com/kubernetes-security-pod-escape-log-mounts). The only true way to ensure safety is to enforce that all Pods mounting hostPath volumes do so in read only mode. This policy checks all containers for any hostPath volumes and ensures they are explicitly mounted in readOnly mode.
Policy Definition
/other/ensure-readonly-hostpath/ensure-readonly-hostpath.yaml
1apiVersion: kyverno.io/v1
2kind: ClusterPolicy
3metadata:
4 name: ensure-readonly-hostpath
5 annotations:
6 policies.kyverno.io/title: Ensure Read Only hostPath
7 policies.kyverno.io/category: Other
8 policies.kyverno.io/severity: medium
9 policies.kyverno.io/minversion: 1.6.0
10 kyverno.io/kyverno-version: 1.6.2
11 kyverno.io/kubernetes-version: "1.23"
12 policies.kyverno.io/subject: Pod
13 policies.kyverno.io/description: >-
14 Pods which are allowed to mount hostPath volumes in read/write mode pose a security risk
15 even if confined to a "safe" file system on the host and may escape those confines (see
16 https://blog.aquasec.com/kubernetes-security-pod-escape-log-mounts). The only true way
17 to ensure safety is to enforce that all Pods mounting hostPath volumes do so in read only
18 mode. This policy checks all containers for any hostPath volumes and ensures they are
19 explicitly mounted in readOnly mode.
20spec:
21 background: false
22 validationFailureAction: audit
23 rules:
24 - name: ensure-hostpaths-readonly
25 match:
26 any:
27 - resources:
28 kinds:
29 - Pod
30 preconditions:
31 all:
32 - key: "{{ request.operation || 'BACKGROUND' }}"
33 operator: AnyIn
34 value:
35 - CREATE
36 - UPDATE
37 validate:
38 message: All hostPath volumes must be mounted as readOnly.
39 foreach:
40 # Fetch all volumes in the Pod which are a hostPath. Store the names in an array. There could be multiple in a Pod so can't assume just one.
41 - list: "request.object.spec.volumes[?hostPath][]"
42 deny:
43 conditions:
44 # For every name found for a hostPath volume (stored as `{{element}}`), check all containers, initContainers, and ephemeralContainers which mount this volume and
45 # total up the number of them. Compare that to the ones with that same name which explicitly specify that `readOnly: true`. If these two
46 # counts aren't equal, deny the Pod because at least one is attempting to mount that hostPath in read/write mode. Note that the absence of
47 # the `readOnly: true` field implies read/write access. Therefore, every hostPath volume must explicitly specify that it should be mounted
48 # in readOnly mode, regardless of where that occurs in a Pod.
49 any:
50 - key: "{{ request.object.spec.[containers, initContainers, ephemeralContainers][].volumeMounts[?name == '{{element.name}}'][] | length(@) }}"
51 operator: NotEquals
52 value: "{{ request.object.spec.[containers, initContainers, ephemeralContainers][].volumeMounts[?name == '{{element.name}}' && readOnly] [] | length(@) }}"