In the process of getting Falco working on OpenShift on the IBM Cloud I had my first experience with Open Shift Security Context Constraints. These are limits you can use to secure your clusters and the applications that run within them. They go beyond Pod Security Policies and are unique to Red Hat Open Shift.
While installing Falco, I was getting messages like this when running kubectl describe ds falco-daemonset
:
Warning FailedCreate 0s (x13 over 21s) daemonset-controller Error creating: pods "falco-daemonset-" is forbidden: unable to validate against any security context constraint: [spec.volumes[0]: Invalid value: "hostPath": hostPath volumes are not allowed to be used spec.volumes[1]: Invalid value: "hostPath": hostPath volumes are not allowed to be used spec.volumes[2]: Invalid value: "hostPath": hostPath volumes are not allowed to be used spec.volumes[3]: Invalid value: "hostPath": hostPath volumes are not allowed to be used spec.volumes[4]: Invalid value: "hostPath": hostPath volumes are not allowed to be used spec.volumes[5]: Invalid value: "hostPath": hostPath volumes are not allowed to be used spec.volumes[6]: Invalid value: "hostPath": hostPath volumes are not allowed to be used spec.containers[0].securityContext.privileged: Invalid value: true: Privileged containers are not allowed]
This is two errors actually, Privileged containers are being blocked and mounting directories from the host in are being blocked. Both issues are resolved by adding the privileged
security context constraint to the falco-account
service account I created earlier.
View available security contexts (note some IBM specific ones):
$ oc get scc
NAME PRIV CAPS SELINUX RUNASUSER FSGROUP SUPGROUP PRIORITY READONLYROOTFS VOLUMES
anyuid false [] MustRunAs RunAsAny RunAsAny RunAsAny 10 false [configMap downwardAPI emptyDir persistentVolumeClaim projected secret]
hostaccess false [] MustRunAs MustRunAsRange MustRunAs RunAsAny <none> false [configMap downwardAPI emptyDir hostPath persistentVolumeClaim projected secret]
hostmount-anyuid false [] MustRunAs RunAsAny RunAsAny RunAsAny <none> false [configMap downwardAPI emptyDir hostPath nfs persistentVolumeClaim projected secret]
hostnetwork false [] MustRunAs MustRunAsRange MustRunAs MustRunAs <none> false [configMap downwardAPI emptyDir persistentVolumeClaim projected secret]
ibm-anyuid-hostaccess-scc false [SETPCAP AUDIT_WRITE CHOWN NET_RAW DAC_OVERRIDE FOWNER FSETID KILL SETUID SETGID NET_BIND_SERVICE SYS_CHROOT SETFCAP] MustRunAs RunAsAny RunAsAny RunAsAny <none> false [*]
ibm-anyuid-hostpath-scc false [SETPCAP AUDIT_WRITE CHOWN NET_RAW DAC_OVERRIDE FOWNER FSETID KILL SETUID SETGID NET_BIND_SERVICE SYS_CHROOT SETFCAP] MustRunAs RunAsAny RunAsAny RunAsAny <none> false [*]
ibm-anyuid-scc false [SETPCAP AUDIT_WRITE CHOWN NET_RAW DAC_OVERRIDE FOWNER FSETID KILL SETUID SETGID NET_BIND_SERVICE SYS_CHROOT SETFCAP] MustRunAs RunAsAny RunAsAny RunAsAny <none> false [configMap downwardAPI emptyDir persistentVolumeClaim projected secret]
ibm-privileged-scc true [*] RunAsAny RunAsAny RunAsAny RunAsAny <none> false [*]
kube-state-metrics false [] RunAsAny RunAsAny RunAsAny RunAsAny <none> false [*]
node-exporter false [] RunAsAny RunAsAny RunAsAny RunAsAny <none> false [*]
nonroot false [] MustRunAs MustRunAsNonRoot RunAsAny RunAsAny <none> false [configMap downwardAPI emptyDir persistentVolumeClaim projected secret]
privileged true [*] RunAsAny RunAsAny RunAsAny RunAsAny <none> false [*]
restricted false [] MustRunAs MustRunAsRange MustRunAs RunAsAny <none> false
Then add the policy to the account
$ oc adm policy add-scc-to-user privileged -z falco-account
scc "privileged" added to: ["system:serviceaccount:default:falco-account"]
The -z
argument is specifying the kubernetes service account we created earlier. See details here
It is probably possible and useful to use a less privileged account to start the Falco daemonset but I wanted to get this out when it was fresh. I’ll make a follow up post if/when I figure that out.