In this demo we are going to show a few basic scenarios of SCCs access and prioritization that will help you understand how SCCs are accessed, ordered and prioritized.
In this demo we will see how a ServiceAccount (SA) can get access to use an SCC by directly granting access to the SCC to the SA.
-
Create a namespace for running the demo
NAMESPACE="scc-fun" oc create ns ${NAMESPACE}
-
Create a ServiceAccount
oc -n ${NAMESPACE} create serviceaccount testsa1
-
Grant access to the
anyuid
SCC directly to the SAoc -n ${NAMESPACE} adm policy add-scc-to-user anyuid system:serviceaccount:${NAMESPACE}:testsa1
-
Check who can use the
anyuid
SCCoc -n ${NAMESPACE} adm policy who-can use scc anyuid
NOTE: As you can see the SA testsa1 has access to use the scc.
Namespace: scc-fun Verb: use Resource: securitycontextconstraints.security.openshift.io Users: system:admin <OUTPUT_OMITTED> system:serviceaccount:scc-fun:testsa1 Groups: system:cluster-admins system:masters
In this demo we will see how a ServiceAccount can get access to use an SCC (anyuid). This can be done by creating a Role that allow to use the security.openshift.io API, the resource securityContextConstraint and the specific name of the resource: anyuid. Then, bind the Role to the SA by means of a Rolebinding.
-
Create a new ServiceAccount
oc -n ${NAMESPACE} create serviceaccount testsa2
-
Create a Role that grants access to use the anyuid scc
cat <<EOF | oc -n ${NAMESPACE} create -f - apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: name: use-anyuid rules: - apiGroups: - security.openshift.io resources: - securitycontextconstraints resourceNames: - anyuid verbs: - use EOF
-
Create a RoleBinding that grants
use-anyuid
role to our SAtestsa2
cat <<EOF | oc -n ${NAMESPACE} create -f - apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: use-anyuid-rb roleRef: apiGroup: rbac.authorization.k8s.io kind: Role name: use-anyuid subjects: - kind: ServiceAccount name: testsa2 namespace: ${NAMESPACE} EOF
-
Check who can use the
anyuid
SCCoc -n ${NAMESPACE} adm policy who-can use scc anyuid
NOTE: As you can see the SA testsa2 has access to use the scc.
Namespace: scc-fun Verb: use Resource: securitycontextconstraints.security.openshift.io Users: system:admin <OUTPUT_OMITTED> system:serviceaccount:scc-fun:testsa1 system:serviceaccount:scc-fun:testsa2 Groups: system:cluster-admins system:masters
-
Assigning SCCs to SAs using Roles is the prefered way to go. During the upcoming demos we will grant direct access to make things easier though.
-
Create a service account that will be used as our unprivileged user (we will impersonate it)
oc -n ${NAMESPACE} create sa testuser
-
Give edit role to the
testuser
SA in the namespaceoc -n ${NAMESPACE} adm policy add-role-to-user edit system:serviceaccount:${NAMESPACE}:testuser
-
Give the SA access to the SCC
restricted-v2
NOTE: All authenticated users have access to the
restricted-v2
SCC, since it's the default one. We're only giving the SA this access so the SCC gets reported back when usingscc-review
commands. Scc-review command doesn't take into account access to SCCs inherited via a user group, such assystem:authenticated
.oc -n ${NAMESPACE} adm policy add-scc-to-user restricted-v2 system:serviceaccount:${NAMESPACE}:testuser
-
Create a pod definition and store it on /tmp
cat <<EOF > /tmp/pod-scc-1.yaml apiVersion: v1 kind: Pod metadata: name: pod-scc-1 spec: serviceAccountName: testuser containers: - image: quay.io/mavazque/reversewords:latest name: test-pod resources: {} dnsPolicy: ClusterFirst restartPolicy: Always status: {} EOF
-
Run the scc-review command to see which SCC will be assigned to the pod
oc -n ${NAMESPACE} policy scc-review -z system:serviceaccount:${NAMESPACE}:testuser -f /tmp/pod-scc-1.yaml
-
As you can see it will be granted the
restricted
SCCRESOURCE SERVICE ACCOUNT ALLOWED BY Pod/pod-scc-1 testuser restricted-v2
-
-
Create the pod (as the non-admin user) and check the SCC assigned to it
oc -n ${NAMESPACE} create -f /tmp/pod-scc-1.yaml --as=system:serviceaccount:${NAMESPACE}:testuser oc -n ${NAMESPACE} get pod pod-scc-1 -o yaml | grep "openshift.io/scc"
-
As you can see, the
restricted-v2
SCC was grantedopenshift.io/scc: restricted-v2
-
-
Let's give access to the
anyuid
SCC to the unprivileged useroc -n ${NAMESPACE} adm policy add-scc-to-user anyuid system:serviceaccount:${NAMESPACE}:testuser
-
What happens if we run the scc-review again?
oc -n ${NAMESPACE} policy scc-review -z system:serviceaccount:${NAMESPACE}:testuser -f /tmp/pod-scc-1.yaml
-
The
anyuid
was placed before therestricted-v2
SCCRESOURCE SERVICE ACCOUNT ALLOWED BY Pod/pod-scc-1 testuser anyuid Pod/pod-scc-1 testuser restricted-v2
-
Our pod spec doesn't have anything that will require it to run with
anyuid
, whyanyuid
has preference over restricted?oc get scc restricted-v2 anyuid
NAME PRIV CAPS SELINUX RUNASUSER FSGROUP SUPGROUP PRIORITY READONLYROOTFS VOLUMES restricted-v2 false ["NET_BIND_SERVICE"] MustRunAs MustRunAsRange MustRunAs RunAsAny <no value> false ["configMap","downwardAPI","emptyDir","persistentVolumeClaim","projected","secret"] anyuid false <no value> MustRunAs RunAsAny RunAsAny RunAsAny 10 false ["configMap","downwardAPI","emptyDir","persistentVolumeClaim","projected","secret"]
-
The SCC
anyuid
has a priority of 10 while restricted-v2 has no priority, that meansanyuid
will be preferred even if the pods doesn't need it.
-
-
Let's create the pod again to see what SCC does it get this time
oc -n ${NAMESPACE} delete pod pod-scc-1 oc -n ${NAMESPACE} create -f /tmp/pod-scc-1.yaml --as=system:serviceaccount:${NAMESPACE}:testuser
oc -n ${NAMESPACE} get pod pod-scc-1 -o yaml | grep "openshift.io/scc"
NOTE: The
anyuid
SCC was grantedopenshift.io/scc: anyuid
NOTE: An easier way to check the SCC assigned to your pod, specially if you have multiple pods with likely different SCC assigned to it, it is formatting the output using custom-columns. For instance, you can just show the name of the pod and the SCC applied without require access to the yaml definition or even the name of the pod:
oc -n ${NAMESPACE} get pod -o 'custom-columns=NAME:metadata.name,APPLIED SCC:metadata.annotations.openshift\.io/scc'
NAME APPLIED SCC pod-scc-1 anyuid
-
In the previous step we have seen how priorities will decide which SCC is used to admit the pod in the cluster, starting in OpenShift 4.14 there is a new annotation that we can use to force the use of a specific SCC without having to edit SCC priorities, let's learn how to use it:
NOTE: The
openshift.io/required-scc
annotation can only be used in workload resources like Deployments, StatefulSets, etc. If you try to use it directly on Pods you will get an admission error.-
Create a Deployment without specifying the
required-scc
annotation:cat <<EOF | oc -n ${NAMESPACE} create --as=system:serviceaccount:${NAMESPACE}:testuser -f - apiVersion: apps/v1 kind: Deployment metadata: creationTimestamp: null labels: app: deployment-scc-1 name: deployment-scc-1 spec: replicas: 1 selector: matchLabels: app: deployment-scc-1 strategy: {} template: metadata: creationTimestamp: null labels: app: deployment-scc-1 spec: serviceAccountName: testuser containers: - image: quay.io/mavazque/reversewords:latest name: reversewords resources: {} EOF
-
If we check the SCC assigned to the resulting Pod we can see that
anyuid
was assigned:oc -n ${NAMESPACE} get pod -l app=deployment-scc-1 -o yaml | grep "openshift.io/scc"
openshift.io/scc: anyuid
-
Our workload doesn't require
anyuid
so let's specify that we want it to userestricted-v2
:oc -n ${NAMESPACE} patch deployment deployment-scc-1 -p '{"spec":{"template":{"metadata":{"annotations":{"openshift.io/required-scc":"restricted-v2"}}}}}' --type merge
-
The new pod will be admitted by
restricted-v2
:oc -n ${NAMESPACE} get pod -l app=deployment-scc-1 -o yaml | grep "openshift.io/scc"
openshift.io/scc: restricted-v2
-
If we try to select an SCC that the workload doesn't have access to, the admission will fail:
oc -n ${NAMESPACE} patch deployment deployment-scc-1 -p '{"spec":{"template":{"metadata":{"annotations":{"openshift.io/required-scc":"privileged"}}}}}' --type merge
oc -n ${NAMESPACE} get deployment deployment-scc-1 -o yaml
<OUTPUT_OMITTED> - lastTransitionTime: "2023-10-17T14:00:09Z" lastUpdateTime: "2023-10-17T14:00:09Z" message: 'pods "deployment-scc-1-664898bd47-" is forbidden: unable to validate against any security context constraint: provider "privileged": Forbidden: not usable by user or serviceaccount' reason: FailedCreate status: "True" type: ReplicaFailure
-