Declarative Security Context Contraints Using RBAC
Posted: August 12th, 2020 | Author: sabre1041 | Filed under: Uncategorized | No Comments »OpenShift contains a number of included security features and pods running within the cluster are governed by Security Context Constraints (SCC’s) which specify the actions that can be achieved as well as the resources that it can access. For new users beginning to work with OpenShift, their first experience with SCC’s is that their container will not run as the designed user ID and instead be assigned a random ID from a range. This is the anyuid
SCC at work and it not only protects the container, but the underlying host.
There are circumstances where it may be necessary to modify the SCC the a pod is able to use (The restricted
SCC is the default associated to pods). Traditionally, granting access to an SCC was accomplished by specifying the user (Service Account in most cases as it is used to run a pod) or group within the SCC.
For example, if a Service Account named my-special-pod
was designated to run a particular workload in a namespace called example
, the following command can be used to grant the pod access to the anyuid SCC and allow it to leverage the UID as specified in the container image:
$ oc adm policy add-scc-to-user anyuid -z my-special-pod
As a result, the following is added to the anyuid SCC:
users:
- system:serviceaccount:example:my-special-pod
While this method for modifying SCC’s has been around since the beginning of OpenShift 3, more recent versions of OpenShift 4 have recommended against directly modifying the included set of SCC’s as challenges have been seen during upgrades as the expected state of the SCC does not match the actual state.
Instead, an alternate approach for managing SCC’s through Role Based Access Control can accomplish the same goal without requiring direct intervention. By incorporating RBAC, policies can be created declaratively and integrate into an existing GitOps process.
Using RBAC to manage access to SCC’s is similar to managing any other aspects of OpenShift/Kubernetes, such as rights to another namespace. It requires the combination of a Role/ClusterRole and a binding to a particular resource. Since SCC’s are used by pods, and pods are run using Service Accounts, a Service Account is the resource that needs to be bound to the role.
Implementing RBAC
The first step is to create a new ClusterRole
(since SCC’s are cluster scoped instead of namespace scoped) that will provide access to a given SCC. Roles/ClusterRoles make use of rules that allow access to resources and API verb operations. While the majority of roles that you will see leverage verbs, such as create
, list
, and delete
, RBAC for SCC’s leverage the use
verb for granting access. To provide access to the anyuid
SCC requires the combination of the use
verb, the anyuid
resourceName, the security.openshift.io
and the securitycontextconstraints
resource. Fortunately the OpenShift CLI can be use to generate a ClusterRole
with the combination of parameters previously:
$ oc create clusterrole allow-anyuid-scc --verb=use --resource=securitycontextconstraints.security.openshift.io --resource-name=anyuid
Take a look at the resource that was created:
$ oc get clusterrole allow-anyuid-scc -o yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: allow-anyuid-scc
rules:
- apiGroups:
- security.openshift.io
resourceNames:
- anyuid
resources:
- securitycontextconstraints
verbs:
- use
With the ClusterRole now in place, it can then be bound to the Service Account that is used to run the pod. If you have not done so already, create a the project and Service Account:
$ oc new-project example
$ oc create sa my-special-pod
To bind the my-special-pod
Service Account in the example
namespace with the allow-anyuid-scc
SCC, execute the following command:
$ oc create rolebinding anyuid-scc --clusterrole=allow-anyuid-scc --serviceaccount=my-special-pod
Take a look at the resource that was created:
$ oc get rolebinding anyuid-scc -o yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: anyuid-scc
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: allow-anyuid-scc
subjects:
- kind: ServiceAccount
name: my-special-pod
namespace: example
With the ClusterRole
and RoleBinding
now in place, newly created pods in the example
namespace using he my-special-pod
Service Account will run using the User ID as specified in the container. This can be confirmed by deploying a sample container within this namespace.
Create a sample application that starts up a basic RHEL8 based image using the my-special-pod service account which should enable the pod to run as the designated user ID.
$ oc run ubi8 --image=registry.redhat.io/ubi8/ubi --serviceaccount=my-special-pod --command -- /bin/bash -c 'while true; do sleep 3; done'
Since the pod was launched using the my-special-pod Service Account, confirm that is leveraging the anyuid
SCC as enabled through the use of RBAC policies:
$ oc get pod -l=run=ubi8 -o jsonpath="{ .items[*].metadata.annotations['openshift\.io/scc'] }"anyuid
The use of RBAC polices to manage access to Security Context Constraints avoids modifying the out-of-the-box policies that ship with OpenShift which could potentially compromise the stability of the platform, but more importantly aligns with the declarative nature of how OpenShift and Kubernetes is managed. Security has always been top of mind in OpenShift and it is great to see the management of the key features evolve with the platform.
Starting in OpenShift 4.5, RBAC ClusterRoles
are now automatically created for the included set of SCC’s:
system:openshift:scc:anyuid
system:openshift:scc:hostaccess
system:openshift:scc:hostmount
system:openshift:scc:hostnetwork
system:openshift:scc:nonroot
system:openshift:scc:privileged
system:openshift:scc:restricted
The inclusion of these resources now eliminates the need to create ClusterRoles for each of the Security Context Constraints that you require access.
Leave a Reply