OpenShift
Security Context Constraints
OpenShift enforces Security Context Constraints (SCCs) to control the actions that pods can perform and the resources they can access. Under the default restricted SCC, containers are not allowed to run as a fixed user ID. Instead, OpenShift assigns an arbitrary UID from a range that is unique to each namespace.
As described in the OpenShift image creation guidelines:
By default, OpenShift Container Platform runs containers using an arbitrarily assigned user ID. This provides additional security against processes escaping the container due to a container engine vulnerability and thereby achieving escalated permissions on the host node.
This means that specifying a fixed runAsUser, runAsGroup, or
fsGroup in a pod's security context is rejected by the restricted
SCC unless the value falls within the namespace's allocated range.
How Klio handles this
The Klio Operator detects OpenShift at startup by querying the
Kubernetes discovery API for the securitycontextconstraints
resource in the security.openshift.io/v1 API group.
When running on OpenShift:
- Server pods: The operator omits
runAsUser,runAsGroup, andfsGroupfrom the pod security context, allowing the restricted SCC to assign a UID from the namespace's range. - Plugin sidecar containers: The operator omits
runAsUserandrunAsGroupfrom the container security context for the same reason.
On vanilla Kubernetes, the operator continues to set explicit UIDs (1000 for server pods, 26 for plugin sidecars) as before.
No user configuration is required. The detection is automatic and logged at startup:
INFO setup Cluster capabilities detected {"haveSecurityContextConstraints": true}
Testing on OpenShift with OLM
This guide explains how to install a test build of the Klio operator on an OpenShift cluster using OLM (Operator Lifecycle Manager).
This procedure is for development and testing only. It requires a catalog image built from the branch under test.
Prerequisites
- An OpenShift cluster with
ocCLI configured - Cluster admin privileges
- cert-manager installed in the cluster (for TLS certificate creation)
- A catalog image built with
task olm:catalog ENVIRONMENT=testing
The Klio operator, bundle, catalog and operand images are public
on ghcr.io, so no pull secret is needed.
1. Apply the CatalogSource
A CI run creates a catalog image, tagged with the branch name or the PR number:
Examples:
ghcr.io/cloudnative-pg/klio-operator-testing:main-catalog
ghcr.io/cloudnative-pg/klio-operator-testing:pr-1325-catalog
Create an openshift_catalogsource.yaml file pointing to the
catalog image built from your branch:
apiVersion: operators.coreos.com/v1alpha1
kind: CatalogSource
metadata:
name: klio-catalog
namespace: openshift-marketplace
spec:
sourceType: grpc
image: <catalog-image>
Then apply it:
oc apply -f openshift_catalogsource.yaml
Wait for the catalog pod to become ready:
oc get pods -n openshift-marketplace -w | grep klio
2. Subscribe to the operator
Create an openshift_subscription.yaml file:
apiVersion: operators.coreos.com/v1alpha1
kind: Subscription
metadata:
name: klio-operator
namespace: openshift-operators
spec:
channel: stable-v0
name: klio-operator
source: klio-catalog
sourceNamespace: openshift-marketplace
installPlanApproval: Automatic
Apply it:
oc apply -f openshift_subscription.yaml
OLM will create an InstallPlan and deploy the operator into
the openshift-operators namespace.
The Klio sidecar (operand) image is baked into the operator
Deployment by the bundle as the SIDECAR_IMAGE environment
variable. It uses the same registry and tag as the operator
image by default, with the klio repository instead of
klio-operator. The Subscription can override it.
3. Create TLS certificates
The Klio plugin requires two TLS secrets to establish mutual TLS with the CNPG operator:
klio-plugin-server-tls— presented by the plugin gRPC serverklio-plugin-client-tls— used by CNPG to authenticate to the plugin
They can be created manually, but the recommended method is to use cert-manager to automatically generate and manage the certificates.
Create a file openshift_certificates.yaml with the following
content, adjusting the namespace if the operator was installed
outside of openshift-operators:
---
apiVersion: cert-manager.io/v1
kind: Issuer
metadata:
name: klio-operator-selfsigned-issuer
namespace: openshift-operators
spec:
selfSigned: {}
---
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: klio-plugin-server
namespace: openshift-operators
spec:
secretName: klio-plugin-server-tls
dnsNames:
- klio-operator-plugin
usages:
- server auth
issuerRef:
name: klio-operator-selfsigned-issuer
kind: Issuer
group: cert-manager.io
duration: 2160h
renewBefore: 360h
---
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: klio-plugin-client
namespace: openshift-operators
spec:
secretName: klio-plugin-client-tls
commonName: klio-plugin-client
usages:
- client auth
issuerRef:
name: klio-operator-selfsigned-issuer
kind: Issuer
group: cert-manager.io
duration: 2160h
renewBefore: 360h
Apply it:
oc apply -f openshift_certificates.yaml
Verify that the secrets have been created by cert-manager:
oc get secrets -n openshift-operators \
klio-plugin-server-tls klio-plugin-client-tls
4. Verify the installation
The installation is complete when the CSV reaches the
Succeeded phase. You can check its status with:
oc get csv -n openshift-operators -w
Red Hat certification
Klio's operator image and OLM bundle are validated against Red Hat's Preflight certification policies. Two checks cover the two artifacts:
check container— static policy checks on the operator image (labels, layers, license, base image). It needs no cluster and runs in the Dagger engine viatask olm:preflight-container.check operator— installs the bundle through OLM into a live OpenShift cluster and verifies it is deployable. Because it needs a real OpenShift cluster (OLM and Security Context Constraints), it runs viatask olm:preflight-operator, against the CRC cluster the OpenShift E2E job starts or against a local CRC. The bundle and catalog images are multi-arch (linux/amd64andlinux/arm64), so the check runs natively on either architecture — including CRC on an Apple Silicon Mac.
Both checks are currently disabled in CI. The operator and operand
images are built on Debian instead of Red Hat UBI, which the
check container base-image policy rejects, and check operator is
parked alongside it. The steps are commented out in
.github/workflows/ci.yml and .github/workflows/openshift-e2e.yml,
ready to be restored once a UBI-based image variant is built again — see
issue #85. Both
tasks still work when run manually, as described below.
Run check operator against CRC
Point EXTERNAL_KUBECONFIG at an OpenShift (CRC) cluster and run the
task. The bundle and catalog (index) images must already be published
for the build under test — build them first with
task olm:catalog ENVIRONMENT=testing if needed; the certification runs
against the existing bundle rather than rebuilding it.
export EXTERNAL_KUBECONFIG=/path/to/crc/kubeconfig
task olm:preflight-operator ENVIRONMENT=testing
preflight installs the operator through OLM, runs the operator policy,
and the Dagger preflight module evaluates the pass/fail verdict
in-engine. Raw artifacts are written to operator/preflight-artifacts/.
The task never contacts Red Hat: the checks are always evaluated locally.