Open the door for root users in Red Hat OpenShift (example StatefulSet)¶

This “blog post"/"cheat sheet” is about “Open the door for root users in OpenShift (example StatefulSet)”. The topic is in context of two blog posts I wrote called Run a PostgreSQL container as a non-root user in OpenShift and Open the door for root users in Red Hat OpenShift¶.

If you want to get an overview of the existing Default OpenShift security context constraints visit the IBM Cloud documentation.

In this blog post, once more we don’t want to take advantage of the Out Of The Box provided security in Red Hat OpenShift. We are going to run a PostgreSQL container as root.

To do this, we will do the following:

  1. We will deploy a PostgreSQL container as a very simple StatefulSet and notify that this container will not start, because by default the container is designed to run as root and that doesn’t work by default in Red Hat OpenShift.
  2. We will investigate the problem and find that the container cannot create a temporary database when the container starts.
  3. We will create a service account and we add the policy anyuid.
  4. We will add this service account to our project.
  5. Then will modify the existing StatefulSet to use the service account and we “open the door for root usage” with the policy anyuid.
  6. We will delete the actual pod.
  7. We will check the newly created pod.
  8. In the last step we verify the changes we made in the StatefulSet.

Provide a container that uses root privileges

Step 1: Log in to the cluster as a user with cluster administrator rights

Step 2: Create a project called postgres

oc new-project postgres

Step 3: Create a yaml file for following StatefulSet and Service definition

Here you see the StatefulSet and the Service to deploy a simple example postgres container.

---
apiVersion: v1
kind: Service
metadata:
  labels:
    app: database-articles
  name: database-articles-service
spec:
  ports:
  - name: http
    port: 5432
    protocol: TCP
  selector:
    app: database-articles
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: database-articles
  namespace: postgres
  labels:
    app: database-articles   
spec:
  serviceName: "database-articles-service"
  selector:
    matchLabels:
      app: database-articles
  template:
    metadata:
      labels:
        app: database-articles
    spec:
      containers:
      - env:
        - name: POSTGRES_DB
          value: postgres
        - name: POSTGRES_USER
          value: postgres
        - name: POSTGRES_PASSWORD
          value: postgres
        - name: PGDATA
          value: /temp/data
        image: docker.io/postgres:latest
        imagePullPolicy: Always
        name: postgres-pod
        ports:
        - containerPort: 5432
          protocol: TCP
        resources:
          limits:
            cpu: 60m
            memory: 512Mi
          requests:
            cpu: 30m
            memory: 128Mi
      restartPolicy: Always

Step 4: Apply your deployment and service configuration

oc apply -f postgres-statefulset.yaml

Example output:

service/database-articles-service created
statefulset.apps/database-articles created

Step 5: Verify that the pod is running

oc get pod

Example output:

vend-tmp % oc get pod
NAME                  READY   STATUS   RESTARTS   AGE
database-articles-0   0/1     Error    3          56s

Step 6: Get logs for the pod

oc logs -f -p database-articles-0

Example output:

mkdir: cannot create directory ‘/temp’: Permission denied

Open the door for root usage

Step 1: Create a service account?

oc create sa postgres-sa

Example output:

serviceaccount/postgres-sa created

Step 2: Verify the created service account

oc get sa

Example output:

NAME          SECRETS   AGE
builder       2         2m25s
default       2         2m25s
deployer      2         2m25s
postgres-sa   2         17s

Step 3: Add policy add-scc-to-user anyuid to service account

oc adm policy add-scc-to-user anyuid -z postgres-sa

Example output:

clusterrole.rbac.authorization.k8s.io/system:openshift:scc:anyuid added: "postgres-sa"

Step 4: Add service account and policy to project

oc adm policy add-scc-to-user anyuid -z postgres-sa -n postgres

Example output:

clusterrole.rbac.authorization.k8s.io/system:openshift:scc:anyuid added: "postgres-sa"

Step 5: Get the statefulset

oc get statefulset

Example output:

NAME                READY   AGE
database-articles   0/1     3m29s

Step 6: Add service account to statefulset

oc set sa statefulset database-articles postgres-sa

Example output:

statefulset.apps/database-articles serviceaccount updated

Step 7: Delete existing pod

oc delete pod database-articles-0

Example output:

pod "database-articles-0" deleted

Step 8: Get running pod

oc get pod database-articles-0

Example output:

NAME READY STATUS RESTARTS AGE
database-articles-0 1/1 Running 0 4m36s

Step 9: Access to running pod

  • Access the running pod
oc exec database-articles-0 -i -t -- bash
  • Verify the temp folder contains now a data folder inside the container.
root@database-articles-56c9977c7-vstgp:/# ls
bin   docker-entrypoint-initdb.d  lib    mnt   root  srv   tmp
boot  etc                         lib64  opt   run   sys   usr
dev   home                        media  proc  sbin  temp  var
root@database-articles-56c9977c7-vstgp:/# cd temp
root@database-articles-56c9977c7-vstgp:/temp# ls
data
root@database-articles-56c9977c7-vstgp:/temp#

Step 10: Verify the changes in the statefulset

oc describe statefulset 

Example output:

We will notice that a the Service Account: postgres-sa was added.

Name:               database-articles
Namespace:          postgres
CreationTimestamp:  Tue, 14 Dec 2021 09:51:45 +0100
Selector:           app=database-articles
Labels:             app=database-articles
Annotations:        <none>
Replicas:           1 desired | 1 total
Update Strategy:    RollingUpdate
  Partition:        0
Pods Status:        1 Running / 0 Waiting / 0 Succeeded / 0 Failed
Pod Template:
  Labels:           app=database-articles
  Service Account:  postgres-sa
  Containers:
   postgres-pod:
    Image:      docker.io/postgres:latest
    Port:       5432/TCP
    Host Port:  0/TCP
    Limits:
      cpu:     60m
      memory:  512Mi
    Requests:
      cpu:     30m
      memory:  128Mi
    Environment:
      POSTGRES_DB:        postgres
      POSTGRES_USER:      postgres
      POSTGRES_PASSWORD:  postgres
      PGDATA:             /temp/data
    Mounts:               <none>
  Volumes:                <none>
Volume Claims:            <none>
Events:
  Type    Reason            Age                From                    Message
  ----    ------            ----               ----                    -------
  Normal  SuccessfulCreate  10m (x2 over 17m)  statefulset-controller  create Pod database-articles-0 in StatefulSet database-articles successful

Here are two useful blog posts and a YouTube video:


Summary

It works once more pretty easily to enable root privileges for a container in OpenShift (it worked in the same way for the StatefulSet as it worked for the Deployment), but I would recommend using the “Out Of The Box” security provided by Red Hat OpenShift.


I hope this was useful to you and let’s see what’s next?

Greetings,

Thomas

#redhat, #openshift, #yaml, #security, #statefulset

One thought on “Open the door for root users in Red Hat OpenShift (example StatefulSet)¶

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.