In this submission (Day 59), we will walk through the process of deploying a sample MongoDB application to a newly deployed Red Hat OpenShift cluster. However, this deployment will fail due to the default security context constraints (SCC) in OpenShift. We will explain why the deployment fails, how to resolve the issue, and provide a brief overview of SCC in OpenShift with examples.
Security context constraints in OpenShift are a security feature that allows administrators to control various aspects of the container runtime, such as user and group IDs, SELinux context, and the use of host resources. In Short, SCCs determine which security settings are allowed or disallowed for containerized applications. By default, OpenShift comes with several predefined SCCs, such as ```restricted```, ```anyuid```, and ```hostaccess```. These SCCs serve as templates for creating custom SCCs to meet specific security requirements.
> Warning: Do not modify the default SCCs. Customizing the default SCCs can lead to issues when some of the platform pods deploy or OpenShift Container Platform is upgraded. Additionally, the default SCC values are reset to the defaults during some cluster upgrades, which discards all customizations to those SCCs. Instead of modifying the default SCCs, create and modify your own SCCs as needed.
For example, the restricted SCC (default for most deployments, or restricted-v2 for new installs of OCP 4.11 and later) does not allow containers to run as root or with privileged access, while the ```anyuid``` SCC permits containers to run with any user ID, including root. By creating custom SCCs and granting them to service accounts or users, administrators can ensure that applications adhere to the desired security policies without compromising functionality.
To learn more details about what each of the out-of-the-box default security context constraints does, see [this official documentation page](https://docs.openshift.com/container-platform/4.12/authentication/managing-security-context-constraints.html#default-sccs_configuring-internal-oauth).
- Fields of this type default to the most restrictive value. For example;
- ```AllowPrivilegedContainer``` is always set to ```false``` if unspecified.
- Controlled by an allowable set
- Fields of this type are checked against the set to ensure their value is allowed.
- Controlled by a strategy
- Items that have a strategy to generate a value provide:
- A mechanism to generate the value, and
- A mechanism to ensure that a specified value falls into the set of allowable values.
CRI-O has the following [default list of capabilities](https://github.com/cri-o/cri-o/blob/main/docs/crio.conf.5.md#crioruntime-table) that are allowed for each container of a pod:
````
default_capabilities = [
"CHOWN",
"DAC_OVERRIDE",
"FSETID",
"FOWNER",
"SETGID",
"SETUID",
"SETPCAP",
"NET_BIND_SERVICE",
"KILL",
]
````
You can learn more about Linux capabilities [here](https://linuxera.org/container-security-capabilities-seccomp/) and [here](https://man7.org/linux/man-pages/man7/capabilities.7.html). The containers use the capabilities from this default list, but pod manifest authors (the person writing the application YAML for Kubernetes) can alter the list by requesting additional capabilities or removing some of the default behaviors. To control the capabilities allowed or denied for Pods running in the cluster, use the ```allowedCapabilities```, ```defaultAddCapabilities```, and ```requiredDropCapabilities``` parameters in your SCC to control such requests from the pods.
#### Quick Snippet: configuring a pod with capabilities
You can [specify additional capabilities for your pod](https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-capabilities-for-a-container) as per the below example.
- **allowedCapabilities:** - A list of capabilities that a pod can request. An empty list means that none of the capabilities can be requested while the special symbol * allows any capabilities.
- **volumes:** - The allowable volume types for the security context. In the example, * allows the use of all volume types.
The users and groups fields on the SCC control which users can access the SCC. By default, cluster administrators, nodes, and the build controller are granted access to the privileged SCC. All authenticated users are granted access to the restricted-v2 SCC.
## Let's deploy a sample application
I'm going to deploy some of the basic components of my [trusty Pac-Man application for Kubernetes](https://github.com/saintdle/pacman-tanzu). The MongoDB deployment, PVC and Secret.
First, I need to create the namespace to place the components in, ```oc create ns pacman```.
Now I apply the below YAML file ```oc apply -f mongo-test.yaml```
>Warning: would violate PodSecurity "restricted:v1.24": allowPrivilegeEscalation != false (containers "volume-permissions", "mongo" must set securityContext.allowPrivilegeEscalation=false), unrestricted capabilities (containers "volume-permissions", "mongo" must set securityContext.capabilities.drop=["ALL"]), runAsNonRoot != true (pod or containers "volume-permissions", "mongo" must set securityContext.runAsNonRoot=true), runAsUser=0 (container "volume-permissions" must not set runAsUser=0), seccompProfile (pod or containers "volume-permissions", "mongo" must set securityContext.seccompProfile.type to "RuntimeDefault" or "Localhost")
>
>deployment.apps/mongo created
>
>secret/mongodb-users-secret created
If I now inspect the deployment and replicaset in the ```pacman``` namespace, we'll see that's stuck, I have no pods running.
````
# oc get all -n pacman
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/mongo 0/1 0 0 3m9s
NAME DESIRED CURRENT READY AGE
replicaset.apps/mongo-56cc764fb 1 0 0 3m9s
````
## Why the Deployment Fails
The provided Kubernetes application includes an initContainer with the following security context:
This configuration means that the initContainer will attempt to run as the root user (UID 0). However, OpenShift's default SCCs restrict the use of the root user for security reasons. As a result, the deployment fails because it violates the default security context constraints. The same is true of the other configuration settings mentioned in the above output as well. Remember in OCP 4.11 and later (new installs), the default SCC is the restricted-v2 policy.
## How to Resolve the Issue
To resolve this issue, we need to modify the deployment configuration to comply with the SCC policies in OpenShift. There are several ways to achieve this, but in this example, we will create a custom SCC that allows the initContainer to run as root. Follow these steps:
In the real world, the first port of call should always be to work to ensure your containers and applications run with the least privileges necessary and therefore don't need to run as root.
In this post, we discussed how the default security context constraints in OpenShift can prevent deployments from running as expected. We provided a solution to the specific issue of running an initContainer as root for a MongoDB application. Understanding and managing SCCs in OpenShift is essential for maintaining secure and compliant applications within your cluster.
On [Day 60](/day60.md)](/day60.md), we will look at OpenShift Projects Creation, Configuration and Governance, for example consuming SCC via the project level, and other features of Red Hat OpenShift.
- Red Hat OpenShift - [Managing security context constraints](https://docs.openshift.com/container-platform/4.12/authentication/managing-security-context-constraints.html)
- Red Hat OpenShift - [Important OpenShift changes to Pod Security Standards](https://connect.redhat.com/en/blog/important-openshift-changes-pod-security-standards)
- OCP 4.11 and later - With the introduction of a new built-in admission controller that enforces the [Pod Security Standards](https://kubernetes.io/docs/concepts/security/pod-security-standards/), namespaces and pods can be defined with three different policies: Privileged, Baseline and Restricted. Therefore, pods not configured according to the enforced security standards defined globally, or on the namespace level, will not be admitted and will not run.
- [Pods fail to create due to "allowPrivilegeEscalation: true" in OpenShift 4.11](https://access.redhat.com/solutions/6976492)
- [Using the legacy restricted SCC in OCP 4.11+](https://access.redhat.com/articles/6973044)
- [Role-based access to security context constraints](https://docs.openshift.com/container-platform/4.12/authentication/managing-security-context-constraints.html#role-based-access-to-ssc_configuring-internal-oauth)
- You can specify SCCs as resources that are handled by RBAC. This allows you to scope access to your SCCs to a certain project or to the entire cluster.
- Kubernetes.io - [Configure a Security Context for a Pod or Container](https://kubernetes.io/docs/tasks/configure-pod-container/security-context/)