OpenShift and Falco

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.