Esta é uma documentação não divulgada para Admission Controller 1.38-dev.

Migrate from Kubewarden Admission Controller 1.37 single chart to SUSE Security Admission Controller 1.37

This page describes how to migrate an existing Kubewarden installation based on the community admission-controller Helm chart (from https://charts.kubewarden.io) to the SUSE Security Admission Controller suse-security-admission-controller chart published in the SUSE Application Collection.

Both charts are single flat charts at appVersion 1.37, so there is no value reshaping. The main work is updating the image registry and pull-secret conventions to match the SUSE Security Admission Controller chart, and adopting the surviving CRDs into the new Helm release. Because both charts keep CRDs and preserve user policies on uninstall, this is largely an in-place migration in the same namespace.

As described in the upgrade path documentation, version jumping is not allowed. You must be running the community admission-controller chart at appVersion v1.37.0 before migrating to SUSE Security Admission Controller appVersion 1.37.0.

This migration involves a short window, between uninstalling the community chart and the SUSE Security Admission Controller chart becoming ready, when policies do not protect your cluster.

You can use the Audit Scanner after the migration completes to identify any resources that may have entered the cluster without being evaluated during that window.

What changes in this migration

Both charts are flat and share the same top-level key names, so only the image registry and pull-secret conventions differ.

Aspect Community chart (source) SUSE Security Admission Controller chart (target)

Chart source

admission-controller from https://charts.kubewarden.io

suse-security-admission-controller from oci://dp.apps.rancher.io/charts/suse-security-admission-controller

Image registry key

global.cattle.systemDefaultRegistry (default: ghcr.io)

global.imageRegistry (default: dp.apps.rancher.io)

Pull secrets key

imagePullSecrets (top-level list)

global.imagePullSecrets

Component images

ghcr.io/kubewarden/adm-controller/controller, ghcr.io/kubewarden/adm-controller/audit-scanner, ghcr.io/kubewarden/adm-controller/policy-server

dp.apps.rancher.io/containers/kubewarden-controller, dp.apps.rancher.io/containers/kubewarden-audit-scanner, dp.apps.rancher.io/containers/kubewarden-policy-server

Policy module registry

ghcr.io (via recommendedPolicies.defaultPoliciesRegistry or fallback)

ghcr.io (unchanged)

Values shape

Flat, top-level keys

Flat, identical key names

CRDs on uninstall

Kept (helm.sh/resource-policy: keep)

Kept (helm.sh/resource-policy: keep)

User policies on uninstall

Preserved by the cleanup hook

Preserved by the cleanup hook

The SUSE Security Admission Controller chart does not read global.cattle.systemDefaultRegistry or global.cattle.imagePullSecrets. Remove those keys from your values; the chart ignores them entirely.

For pull secrets, the SUSE Security Admission Controller chart reads both global.imagePullSecrets and a top-level imagePullSecrets list (with global.imagePullSecrets taking precedence when both are set). Use global.imagePullSecrets. The Step 3 yq transform moves the community top-level key there automatically.

PolicyServer resources may carry an explicit spec.image field pinned to the community policy-server image (for example, ghcr.io/kubewarden/adm-controller/policy-server:v1.37.0). The migration process in Step 8: Update PolicyServer images updates this field to the SUSE Security Admission Controller image ({default-policy-server-image-tag}) for any PolicyServer that has it set.

Policy spec.module references (Wasm policy module OCI images, e.g. ghcr.io/kubewarden/policies/…​) are served from ghcr.io in both charts and do not need to be changed.

Because the community chart keeps its CRDs and preserves user-defined PolicyServers and policies on uninstall, the migration is largely in place: the SUSE Security Admission Controller chart adopts the surviving CRDs using --take-ownership rather than recreating them from scratch. See CRD ownership adoption with --take-ownership for details.

Prerequisites

  • Helm v3.18 or later (required for --take-ownership).

  • kubectl with access to your cluster.

  • yq v4 (github.com/mikefarah/yq) for filtering backed-up resources and transforming your values file.

  • An access token or service account for the SUSE Application Collection. See the Application Collection authentication documentation for how to obtain credentials.

  • The community admission-controller chart installed at appVersion v1.37.0.

  • The SUSE Security Admission Controller chart version 1.0.0 available at oci://dp.apps.rancher.io/charts/suse-security-admission-controller.

Migration steps

Set a shell variable for the namespace where the community chart is installed. The SUSE Security Admission Controller chart is installed into the same namespace. Replace <your-namespace> with the actual namespace from your installation:

NAMESPACE=<your-namespace>

Step 1: Back up your policies and policy servers

Back up all your PolicyServer instances and policy custom resources. Because the community chart preserves user CRs on uninstall, this backup is a precaution rather than the primary recovery mechanism.

FILTER='del(.items[].metadata.uid, .items[].metadata.resourceVersion, .items[].metadata.creationTimestamp, .items[].metadata.generation, .items[].metadata.managedFields, .items[].status)'

kubectl get clusteradmissionpolicies  -A -o yaml | yq "$FILTER" > clusteradmissionpolicies-backup.yaml
kubectl get admissionpolicies -A -o yaml | yq "$FILTER" > admissionpolicies-backup.yaml
kubectl get clusteradmissionpolicygroups -A -o yaml | yq "$FILTER" > clusteradmissionpolicygroups-backup.yaml
kubectl get admissionpolicygroups -A -o yaml | yq "$FILTER" > admissionpolicygroups-backup.yaml
kubectl get policyservers  -A -o yaml | yq "$FILTER" > policyservers-backup.yaml

Step 2: Capture your existing values

Save your current user-supplied values from the community release for reference. You will transform this file in Step 3. Replace admission-controller with your actual Helm release name if it differs.

helm get values admission-controller \
  -n "$NAMESPACE" \
  -o yaml > old-values.yaml

Step 3: Transform your values for the SUSE Security Admission Controller conventions

The top-level key names are identical in both charts. Only the image registry and pull-secret keys differ. Use the following yq command to remove the global.cattle block and move the top-level imagePullSecrets to global.imagePullSecrets:

yq eval '
  del(.global.cattle) |
  (.global.imagePullSecrets = (.imagePullSecrets // [])) |
  del(.imagePullSecrets)
' old-values.yaml > new-values.yaml

Review new-values.yaml before proceeding. If you did not customise the registry or pull secrets in the community chart, the output may be nearly empty, which is fine, since the SUSE Security Admission Controller chart defaults cover all required settings.

The global.imagePullSecrets value in the SUSE Security Admission Controller chart is a list of secret name strings or {name: …​} objects. You create the pull secret itself in Step 5. If you add it by name here in new-values.yaml, make sure the name matches what you create in Step 5.

Step 4: Log in to the Application Collection registry

helm registry login dp.apps.rancher.io \
  --username <your-username> \
  --password <your-token>

Step 5: Create the image pull secret

The SUSE Security Admission Controller chart pulls its component images (controller, audit-scanner, policy-server) from dp.apps.rancher.io, which is a private registry. Create an image pull secret in the $NAMESPACE namespace so the cluster can authenticate when pulling these images:

kubectl create secret docker-registry application-collection \
  -n $NAMESPACE \
  --docker-server=dp.apps.rancher.io \
  --docker-username=<your-username> \
  --docker-password=<your-token>

You reference this secret when installing the chart in the next step. See also Image pull secrets for policy-server pods for how to make the secret available to policy-server pods, and the Application Collection Helm chart standardizations for background on how global.imagePullSecrets works across all Application Collection charts.

Step 6: Uninstall the community chart

Replace admission-controller with your actual Helm release name if it differs.

helm uninstall admission-controller -n "$NAMESPACE"

The community chart keeps its CRDs (helm.sh/resource-policy: keep). Its cleanup hook deletes the chart-managed resources — the default PolicyServer and the recommended ClusterAdmissionPolicies, identified by the kubewarden.io/managed-by: kubewarden-controller-defaults label — together with their backing resources (Deployments, webhooks, Services, Secrets). Your user-defined PolicyServers and policies are preserved.

The deleted chart-managed defaults are not lost: the SUSE Security Admission Controller chart’s controller recreates them on install (via server-side apply, field owner kubewarden-controller-defaults) when policyServer.enabled or recommendedPolicies.enabled is set in your values. After uninstall, the CRDs and your user CRs remain in the cluster for the SUSE Security Admission Controller chart to adopt. There is still a short enforcement gap until the SUSE Security Admission Controller chart is ready.

Step 7: Install the SUSE Security Admission Controller chart and adopt the CRDs

The CRDs surviving from the community release still carry its Helm ownership metadata (meta.helm.sh/release-name and meta.helm.sh/release-namespace). Installing the SUSE Security Admission Controller chart without --take-ownership fails with an error like this:

Error: ... invalid ownership metadata; annotation
meta.helm.sh/release-name must equal "suse-security-admission-controller":
current value is "admission-controller"

Pass --take-ownership to re-stamp the CRD ownership metadata for the new release. Because the install uses the same namespace as the community release, only the release-name dimension of the metadata changes.

helm install suse-security-admission-controller \
  oci://dp.apps.rancher.io/charts/suse-security-admission-controller \
  --version 1.0.0 \
  -n "$NAMESPACE" \
  --take-ownership \
  --set global.imagePullSecrets={application-collection} \
  --values new-values.yaml \
  --wait

Step 8: Update PolicyServer images

Because user CRs survived the community chart uninstall, they are already present in the cluster. The default PolicyServer was deleted during uninstall and recreated by the new chart’s controller, so patch the live PolicyServers in place rather than re-applying the backup — this updates both your user PolicyServers and the recreated default without creating duplicates. You only need to update any PolicyServer whose spec.image was pinned to the community image. The following command patches all live PolicyServers in place:

kubectl get policyservers -A -o yaml \
  | yq '.items[].spec.image = "{default-policy-server-image-tag}"' \
  | kubectl apply -f -

If a PolicyServer did not set spec.image, the controller uses the chart default and no change is needed. If any resource is unexpectedly missing after the uninstall, re-apply it from the Step 1 backup files, updating the PolicyServer image the same way:

yq eval '.items[].spec.image = "{default-policy-server-image-tag}"' \
  -i policyservers-backup.yaml
kubectl apply -f policyservers-backup.yaml

Do not re-apply the entire backup once the chart’s default resources have been recreated. kubectl create fails with AlreadyExists on the recreated defaults; kubectl apply (client-side) competes with the controller for field ownership of those resources (which the controller manages via server-side apply) and triggers a missing-annotation warning. Restore from backup only the individual user resources that are genuinely missing.

Step 9: Verify the migration

Check that the CRDs are now owned by the new release and the controller is running:

# CRDs owned by the new release
kubectl get crd policyservers.policies.kubewarden.io \
  -o jsonpath='{.metadata.annotations.meta\.helm\.sh/release-name}'

# Controller running
kubectl get deployment -n $NAMESPACE \
  -l app.kubernetes.io/component=controller

Confirm that every backed-up resource is present in the cluster by comparing counts from the backup files against live cluster state. The expected and actual counts must match for each type:

for kind in policyservers clusteradmissionpolicies admissionpolicies \
            clusteradmissionpolicygroups admissionpolicygroups; do
  expected=$(yq '.items | length' "${kind}-backup.yaml")
  actual=$(kubectl get "$kind" -A --no-headers 2>/dev/null | wc -l)
  echo "$kind: expected=$expected actual=$actual"
done

If any count does not match, apply the corresponding backup file and check the controller logs for errors.

Check that all policies have reached active status. The controller reconciles them automatically:

kubectl get clusteradmissionpolicies
kubectl get admissionpolicies -A
kubectl get clusteradmissionpolicygroups
kubectl get admissionpolicygroups -A

Confirm that every PolicyServer is using the SUSE Security Admission Controller policy-server image. Every IMAGE value must start with dp.apps.rancher.io:

kubectl get policyservers \
  -o custom-columns=NAME:.metadata.name,IMAGE:.spec.image

Mapping your community chart values to the SUSE Security Admission Controller chart

Both charts are flat and share identical top-level key names. Almost everything passes through unchanged. The only keys that differ are the image registry and the pull-secret key.

Community key SUSE Security Admission Controller key Notes

global.cattle.systemDefaultRegistry

global.imageRegistry

Rename; omit to use the SUSE Security Admission Controller default (dp.apps.rancher.io)

imagePullSecrets (top-level)

global.imagePullSecrets

Normalize under global; both keys are read by the SUSE Security Admission Controller chart (via coalesce), with global.imagePullSecrets taking precedence

All other top-level keys (logLevel, replicas, auditScanner., policyServer., telemetry., mTLS., recommendedPolicies.*, installOpenReportsCRDs, installPolicyReportCRDs, crdVersion, nameOverride, fullnameOverride, etc.)

Same key

Unchanged; carry over directly

Image registry and pull secrets

The registry convention changes from the Rancher-specific global.cattle.systemDefaultRegistry to the Application Collection standard global.imageRegistry. Do not carry global.cattle.* keys into the SUSE Security Admission Controller chart values; the chart ignores them.

If you pull images from the default Application Collection registry (dp.apps.rancher.io), you do not need a registry override.

If you pull images from a private mirror or an air-gapped registry:

global:
  imageRegistry: "my-private-registry.example.com"
  imagePullSecrets:
    - name: my-pull-secret

For pull secrets, the community chart used a top-level imagePullSecrets list. The SUSE Security Admission Controller chart reads both global.imagePullSecrets and a top-level imagePullSecrets (with global.imagePullSecrets taking precedence when both are set). The Step 3 yq command moves the list to global.imagePullSecrets (the preferred key) automatically.

In the community chart, recommendedPolicies.defaultPoliciesRegistry defaults to "", which falls back to global.cattle.systemDefaultRegistry (ghcr.io). In the SUSE Security Admission Controller chart, recommendedPolicies.defaultPoliciesRegistry defaults to ghcr.io directly. The net result is the same.

If you relied on global.cattle.systemDefaultRegistry to redirect policy modules to a private mirror, you must now set recommendedPolicies.defaultPoliciesRegistry explicitly in the SUSE Security Admission Controller chart values:

recommendedPolicies:
  defaultPoliciesRegistry: "my-private-registry.example.com"

The recommendedPolicies.enabled value defaults to false in both charts. If you had recommended policies enabled in the community setup, re-enable them explicitly in your new values.

CRD toggles

The two CRD installation toggles use the same top-level key names in both charts:

  • installOpenReportsCRDs

  • installPolicyReportCRDs

Carry them over unchanged.

Caveats

CRD ownership adoption with --take-ownership

The community chart keeps its CRDs on uninstall. When the SUSE Security Admission Controller chart installs into the same namespace under a different release name, the surviving CRDs still carry meta.helm.sh/release-name: admission-controller. Helm refuses to take over resources owned by another release without explicit consent.

The --take-ownership flag (Helm 3.18+) re-stamps the CRD ownership metadata for the new release name. Since the install uses the same namespace, only the release-name annotation changes, while the namespace annotation stays consistent.

The SUSE Security Admission Controller chart also annotates its CRDs with helm.sh/resource-policy: keep, so a future uninstall of the SUSE Security Admission Controller chart will leave the CRDs in place to protect any policies still running in the cluster.

Image pull secrets for policy-server pods

The SUSE Security Admission Controller chart pulls its component images from dp.apps.rancher.io, a private registry. The pull secret you create during installation is passed to the chart via global.imagePullSecrets. The controller reads this value and automatically adds those secrets to the imagePullSecrets field of every PolicyServer Deployment it manages, including any user-defined PolicyServer resources restored from a backup. No manual edit to individual PolicyServer resources is required.

All PolicyServer pods run in the same namespace as the controller, the namespace where the chart is installed. In this migration that namespace is $NAMESPACE. The pull secret you create when installing the chart already exists in that namespace, so restored PolicyServer resources can pull their images without any extra step.

PolicyServer.spec.imagePullSecret is a separate mechanism for providing credentials to the policy-server process when it fetches Wasm policy modules from a registry. It does not affect the pull secret used by the kubelet to pull the policy-server container image and will not resolve an ImagePullBackOff caused by a missing registry credential. Use global.imagePullSecrets (passed to the chart at install time) for container image pulls.

See the private registries how-to for policy servers and the Application Collection image verification how-to for more detail.

Policy enforcement gap

Between Step 6 (uninstall the community chart) and Step 7 (the SUSE Security Admission Controller chart becoming ready), no admission controller is running. The webhook configurations are deleted by the community chart cleanup hook, so no admission evaluation takes place during this window.

After the migration completes, run the Audit Scanner to identify any non-compliant resources that may have entered the cluster during the gap:

kubectl create job --from=cronjob/audit-scanner audit-scanner-manual -n "$NAMESPACE"

global.cattle.* keys are ignored

The SUSE Security Admission Controller chart does not read any key under global.cattle. In particular, global.cattle.systemDefaultRegistry and global.cattle.imagePullSecrets have no effect. Remove them from your values file and use global.imageRegistry and global.imagePullSecrets instead.