Skip to content

Instantly share code, notes, and snippets.

@bentito
Last active May 6, 2025 14:42
Show Gist options
  • Save bentito/aa3b38cceebb4b3319fb0d6809044ffd to your computer and use it in GitHub Desktop.
Save bentito/aa3b38cceebb4b3319fb0d6809044ffd to your computer and use it in GitHub Desktop.

Demo: Preflight RBAC Check in Action (OpenShift Example)

To solidify these concepts, let’s walk through a real example on OpenShift. We will attempt to install the OpenShift Pipelines Operator as a cluster extension, but we’ll initially misconfigure its RBAC to trigger the preflight checks. Then we’ll fix the permissions.

Step 1: Create a Service Account with limited RBAC. In this example, we create a service account pipelines-installer in the pipelines project, and give it a deliberately minimal ClusterRole that is missing some permissions we know the operator will need:

apiVersion: v1
kind: ServiceAccount
metadata:
  name: pipelines-installer
  namespace: pipelines
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: pipelines-installer-minimal
rules:
  - apiGroups: [""]
    resources: ["services"]
    verbs: ["get"]  # (Intentionally missing list/watch)
  - apiGroups: ["apiextensions.k8s.io"]
    resources: ["customresourcedefinitions"]
    verbs: []       # (Intentionally none, missing permission to create CRDs)
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: pipelines-installer-binding
subjects:
  - kind: ServiceAccount
    name: pipelines-installer
    namespace: pipelines
roleRef:
  kind: ClusterRole
  name: pipelines-installer-minimal
  apiGroup: rbac.authorization.k8s.io

This gives the pipelines-installer SA only a subset of the required permissions. Notably, it does not allow listing or watching Services (only get), and it gives no permission to create CustomResourceDefinitions. In a real scenario, the Pipelines Operator needs these capabilities (among others), but we’re purposefully leaving them out to see how the preflight check reports them.

Step 2: Create the ClusterExtension CR for the operator. We point it to the Red Hat Pipelines Operator package in the cluster’s catalog and specify our service account:

apiVersion: olm.operatorframework.io/v1alpha1
kind: ClusterExtension
metadata:
  name: pipelines-operator
spec:
  packageName: openshift-pipelines-operator-rh
  installNamespace: pipelines
  serviceAccount:
    name: pipelines-installer
  channel: stable

Apply this with oc apply -f pipelines-operator.yaml. This requests the operator-controller to install the Pipelines Operator using the pipelines-installer SA. The preflight permissions check will run immediately.

Step 3: Check the ClusterExtension status for errors. After a moment, describe the ClusterExtension to see its status:

oc describe clusterextension pipelines-operator

In the Conditions section of the output, you should see something like:

Conditions:
  Type:    Progressing
  Status:  False
  Reason:  Retrying
  Message: pre-authorization failed: service account requires the following permissions to manage cluster extension:
           Namespace:"" APIGroups:[] Resources:[services] Verbs:[list,watch]
           Namespace:"" APIGroups:["apiextensions.k8s.io"] Resources:[customresourcedefinitions] Verbs:[create]

Here we see the preflight check caught exactly the permissions we left out:

  • The service account is missing the ability to list,watch Services cluster-wide (the output shows Namespace:"" for Services) – we only gave it get on services, so this makes sense.
  • It also lacks permission to create CustomResourceDefinitions (CRDs) – indicated by the line for apiextensions.k8s.io group, resource customresourcedefinitions, verb create. We gave it no verbs for CRDs, which is why this is flagged.

Because of these, the extension installation has not proceeded. The controller is in a retry loop (as shown by Reason: Retrying), essentially waiting for us to fix the RBAC and will attempt again.

Step 4: Grant the missing permissions and retry. Let’s fix our ClusterRole to include the needed rules:

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: pipelines-installer-minimal
rules:
  - apiGroups: [""]
    resources: ["services"]
    verbs: ["get", "list", "watch"]   # Grant list/watch on services now
  - apiGroups: ["apiextensions.k8s.io"]
    resources: ["customresourcedefinitions"]
    verbs: ["get", "create"]          # Grant create (and get) on CRDs
  ... (other existing rules unchanged) ...

Apply the updated role with oc apply -f pipelines-installer-clusterrole.yaml. By adding list/watch on Services and create on CRDs, we’ve addressed the reported gaps. The operator-controller will notice these new permissions (you do not need to delete/recreate the ClusterExtension; it will automatically retry).

You can watch the ClusterExtension’s status again with oc get clusterextension pipelines-operator -o yaml -w. After the fix, the Progressing condition’s message should clear or change. Eventually, you should see a condition indicating a successful installation (for example, a Succeeded or Installed status condition).

Step 5: Verify the operator is running. With the RBAC corrected, the Pipelines Operator should install successfully. You can verify that the Operator’s components are running:

  • List pods in the pipelines namespace (or the appropriate namespace you installed into) – you should see the operator’s pod up and running, as well as any other pods it creates.
  • The ClusterExtension resource’s status should show that the extension is installed and available (no more “Retrying” errors). For instance, oc get clusterextension pipelines-operator -o yaml should now show a Status section with conditions indicating the extension is installed/up-to-date.

Key Takeaways:

The preflight permissions check is your friend when setting up Operators with OLM v1. Instead of guessing what RBAC an Operator needs, you can rely on this check to tell you exactly what’s missing. In our example, it pinpointed the absence of Service list/watch and CRD create permissions, which we promptly fixed.

By iterating in this way, you can grant only the minimum necessary privileges for the operator to function, following the principle of least privilege. (During development or testing, you might start with a broad, permissive role to get things running, but in production you should tighten it to only what’s required. The preflight output helps you identify that required set .)

Always remember to re-check the ClusterExtension status after adjusting RBAC. Once the preflight check passes (no more missing permissions), the extension installation will proceed and your Operator will be up and running.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment