.. SPDX-FileCopyrightText: 2026 Univention GmbH
..
.. SPDX-License-Identifier: AGPL-3.0-only

.. _v1.22.x:

**************
Version 1.22.x
**************

Release notes for Nubus for Kubernetes 1.22.x:

* :ref:`v1.22.0`

.. _v1.22.0:

Version 1.22.0 - 2026-08-28
===========================

.. admonition:: Upgrade path

   For the upgrade to version 1.22.0,
   your deployment must run on version 1.21.x.
   For the general steps to upgrade an existing Nubus for Kubernetes deployment,
   see :external+uv-nubus-kubernetes-operation:ref:`nubus-upgrade`
   in :cite:t:`uv-nubus-kubernetes-operation`.

.. _v1.22.0-highlights:

Release highlights
------------------

Keycloak metrics
   Operators can now collect :program:`Keycloak` metrics with :program:`Prometheus`.
   The *Keycloak* Helm Chart exposes the management interface on port 9000
   and can create a ``ServiceMonitor`` resource for the Prometheus Operator.
   Optional metric groups for user events and HTTP request durations
   are configurable through new Helm Chart values.

Stronger security defaults
   Nubus for Kubernetes 1.22 ships two security hardening measures by default.

   The Samba NT password hash (``sambaNTPassword``) is no longer written
   for new objects or password changes.
   Existing hashes are removed at the next password change.
   A cleanup script is available to purge them immediately.

   Kerberos key generation is now restricted to strong AES encryption types.
   Weak types such as ``des3-cbc-sha1`` and ``arcfour-hmac-md5``
   are no longer permitted.
   A cleanup script is available to remove weak keys from existing accounts.

Structured logging is now the default
   As announced in 1.20 and 1.21,
   Nubus for Kubernetes 1.22 activates structured logging by default.
   Plain logging is deprecated and will be removed in a future release.
   For details,
   see :external+uv-nubus-manual:ref:`nubus-logging-structured-components`
   in :cite:t:`uv-nubus-manual`.

.. _v1.22.0-migration-steps:

Migration steps
---------------

This section lists necessary migration steps
that may apply to you.
You need to run them **before** the upgrade.

#. It's necessary for operators to trigger the generation of the
   ``univentionObjectIdentifier`` for existing *UDM* objects and directory objects,
   because future releases of Nubus for Kubernetes rely on it.

   **Recommendation**:
     The Helm chart already creates a migration job in a suspended state.
     Run the migration job
     as shown in listing :numref:`v1.22.0-univention-object-identifier-migration-listing`
     at a time with low system load on the cluster.
     It takes around 6 minutes per 100.000 LDAP objects.

     After a successful run,
     you can optionally deactivate the job by setting
     :envvar:`nubusUdmRestApi.ldapUpdateUniventionObjectIdentifier.enabled` to ``false``
     so that Kubernetes doesn't create the job again.
     If you keep the job activated, it doesn't have a negative impact.

   .. code-block:: console
      :caption: Run the migration job for ``univentionObjectIdentifier``
      :name: v1.22.0-univention-object-identifier-migration-listing

      $ kubectl patch job/<JOB_NAME> \
          --type=strategic \
          --patch '{"spec":{"suspend":false}}'

.. _v1.22.0-changes:

Changes
-------

This section lists the changes in 1.22.0 grouped by component in Nubus for Kubernetes.

.. _v1.22.0-changes-udm-rest-api:

UDM HTTP REST API
~~~~~~~~~~~~~~~~~

The migration job for the generation of the ``univentionObjectIdentifier`` during
the Nubus 1.10 upgrade did not necessarily run against the primary LDAP server.
Therefor it has to be executed again.
Additional error handling lets the job failing in case a LDAP entry could not be upgraded.

Nubus for Kubernetes is now secure by default with regard to the legacy Samba
NT password hash (``sambaNTPassword``).
The new setting ``password/samba/nthash`` controls whether UDM generates the
``sambaNTPassword`` attribute, mirroring the existing ``password/samba/lmhash``
mechanism. It is disabled by default: UDM no longer writes ``sambaNTPassword``
for new objects or password changes, and existing values are automatically
removed from an account during its next password change. If your environment
depends on the NT hash, you can activate it again by setting
``password/samba/nthash`` to ``true``.

To purge legacy hashes from existing accounts immediately, without waiting for
the next password change, two cleanup scripts are now shipped in the
*UDM HTTP REST API* container image below
``/usr/share/univention-directory-manager-tools/``:

``remove_sambantpassword``
   Removes the ``sambaNTPassword`` attribute from all accounts.

``remove_krb5key_keytypes``
   Strips the weak, deprecated Kerberos encryption types from the ``krb5Key``
   attribute of all accounts, leaving modern AES keys intact.

.. _v1.22.0-changes-kerberos-enctypes:

Kerberos encryption types
~~~~~~~~~~~~~~~~~~~~~~~~~

Nubus for Kubernetes now uses strong Kerberos encryption types
exclusively when writing the ``krb5Key`` attribute.

Earlier versions shipped no Kerberos configuration file.
The *UDM HTTP REST API* and the *UMC server* therefore used the built-in
defaults of the Kerberos library,
which included weak encryption types such as ``des3-cbc-sha1`` and ``arcfour-hmac-md5``.
Both containers now render a minimal Kerberos configuration file at startup
and use it through the ``KRB5_CONFIG`` environment variable.

The following encryption types are permitted by default:

* ``aes256-cts-hmac-sha1-96``
* ``aes128-cts-hmac-sha1-96``
* ``aes256-cts-hmac-sha384-192``
* ``aes128-cts-hmac-sha256-128``

The following UCR variables define the secure defaults:

``global.configUcr.kerberos.defaults.enctypes.permitted``
   The encryption types that Nubus uses to generate Kerberos keys.

``global.configUcr.kerberos.defaults.enctypes.tgs``
   The encryption types for ticket-granting service requests.

``global.configUcr.kerberos.defaults.enctypes.tkt``
   The encryption types for ticket requests.

``global.configUcr.kerberos.allow.weak.crypto``
   Weak cryptography. The default value is ``false``.

Existing accounts keep their Kerberos keys until their next password change.
To remove the weak keys from all accounts at once,
use the ``remove_krb5key_keytypes`` script in the *UDM HTTP REST API*.

.. code-block:: console
   :caption: Dry run command to remove existing weak keys
   :name: v1.22.kerberos-remove-keytypes

   $ kubectl exec -n <ns> deploy/<release>-udm-rest-api -- \
       /usr/share/univention-directory-manager-tools/remove_krb5key_keytypes --dry-run

.. _v1.22.0-changes-provisioning-service:

Provisioning Service
~~~~~~~~~~~~~~~~~~~~

This release fixes an issue where the *Provisioning Service*
could stop delivering directory updates to some consumers.
When subscriptions were registered or removed in quick succession,
the service could read an incomplete list of subscriptions
and then skip the missing consumers until it refreshed the list.
The service now always reads the complete list of subscriptions.

.. _v1.22.0-changes-portal-frontend:

Portal Frontend
~~~~~~~~~~~~~~~

The *Portal Frontend* pod no longer crash loops on slow hardware
or after an import.
The portal asset loader sidecar container exited when its initial synchronization
against a slow or cold *UDM HTTP REST API* or *LDAP Server* timed out.
It now retries the initial synchronization instead of exiting,
and the request timeout is configurable and defaults to 120 seconds.

Added Helm Chart value:

* :envvar:`nubusPortalFrontend.assetLoader.config.requestTimeout`

.. _v1.22.0-changes-keycloak-service:

Keycloak service
~~~~~~~~~~~~~~~~

Operators can now collect metrics from :program:`Keycloak`
with :program:`Prometheus`.
:program:`Keycloak` serves its metrics endpoint
on a separate management interface on port 9000.
The *Keycloak* Helm Chart now exposes this port
on the container and on the service,
so that :program:`Prometheus` can reach the ``/metrics`` endpoint.

The chart can also create a ``ServiceMonitor`` resource
for the Prometheus Operator.
The chart doesn't create the resource by default.
To create it, set :envvar:`keycloak.serviceMonitor.enabled` to ``true``.
Use :envvar:`keycloak.serviceMonitor.labels`
to match the selector of your :program:`Prometheus` installation.

Added Helm Chart values:

* :envvar:`keycloak.serviceMonitor.enabled`
* :envvar:`keycloak.serviceMonitor.interval`
* :envvar:`keycloak.serviceMonitor.scrapeTimeout`
* :envvar:`keycloak.serviceMonitor.labels`

Two groups of optional metrics are now configurable.
Nubus for Kubernetes deactivates both groups by default:

* :envvar:`keycloak.config.userEventMetrics.enabled` activates metrics
  for user events, such as sign-in and sign-out.
  Use :envvar:`keycloak.config.userEventMetrics.tags`
  and :envvar:`keycloak.config.userEventMetrics.events`
  to select the labels and the events that :program:`Keycloak` collects.

* :envvar:`keycloak.config.httpMetrics.histograms` activates a histogram
  for the duration of HTTP requests.
  Use :envvar:`keycloak.config.httpMetrics.slos`
  to define the buckets of the histogram in milliseconds.

The setting :envvar:`keycloak.config.enableMetrics` now works as documented.
Earlier versions always activated the metrics endpoint,
even after you set the value to ``false``.
The metrics endpoint stays active by default.

* Upgrade Keycloak to version 26.7.2.
  This includes fixes for the following security findings:

  * :uv:cve:`2026-45292`
  * :uv:cve:`2026-14613`
  * :uv:cve:`2026-59888`
  * :uv:cve:`2026-15945`
  * :uv:cve:`2026-17048`
  * :uv:cve:`2026-15571`
  * :uv:cve:`2026-18963`

.. _v1.22.0-changes-keycloak-extensions:

Keycloak Extensions
~~~~~~~~~~~~~~~~~~~

The *Keycloak Extensions* proxy no longer writes its logs to a log file
in addition to standard output.
Older versions tried to write a log file to a read-only location,
which failed and kept the log data in memory,
leading to a memory leak and an eventual ``OOMKilled`` event.

The default log level of the *Keycloak Extensions*
changes from ``debug`` to ``info``.

.. _v1.22.0-structured-logging:

Structured logging
~~~~~~~~~~~~~~~~~~~

Nubus for Kubernetes now activates structured logging by default.
Plain logging is deprecated and will be removed in a future Nubus release.
For details,
see :external+uv-nubus-manual:ref:`nubus-logging-structured-components`
in :cite:t:`uv-nubus-manual`.

Included errata updates
-----------------------

The errata updates contain fixes for the following CVEs:

:program:`Mako`
  * :uv:cve:`2026-44307` (high)

:program:`PyJWT`
  * :uv:cve:`2026-48526` (high)
  * :uv:cve:`2026-48523` (medium)

:program:`aiohttp`
  * :uv:cve:`2026-34993` (high)
  * :uv:cve:`2026-69244` (high)
  * :uv:cve:`2026-34515` (medium)
  * :uv:cve:`2026-34525` (medium)
  * :uv:cve:`2026-47265` (medium)
  * :uv:cve:`2026-54273` (medium)
  * :uv:cve:`2026-54274` (medium)
  * :uv:cve:`2026-54276` (medium)
  * :uv:cve:`2026-54277` (medium)
  * :uv:cve:`2026-54278` (medium)
  * :uv:cve:`2026-59881` (medium)
  * :uv:cve:`2026-69243` (medium)
  * :uv:cve:`2026-34513` (low)
  * :uv:cve:`2026-34514` (low)
  * :uv:cve:`2026-34517` (low)
  * :uv:cve:`2026-34518` (low)
  * :uv:cve:`2026-34519` (low)
  * :uv:cve:`2026-50269` (low)
  * :uv:cve:`2026-54275` (low)
  * :uv:cve:`2026-54279` (low)
  * :uv:cve:`2026-54280` (low)

:program:`apache2-bin`
  * :uv:cve:`2026-29170` (medium)
  * :uv:cve:`2026-43951` (medium)
  * :uv:cve:`2026-44119` (medium)

:program:`axios`
  * :uv:cve:`2026-44486` (high)
  * :uv:cve:`2026-44487` (high)
  * :uv:cve:`2026-44488` (high)
  * :uv:cve:`2026-44490` (high)
  * :uv:cve:`2026-44492` (high)
  * :uv:cve:`2026-44494` (high)
  * :uv:cve:`2026-44496` (high)
  * :uv:cve:`2026-44489` (medium)
  * :uv:cve:`2026-67314` (medium)

:program:`bind9-dnsutils`
  * :uv:cve:`2026-10723` (medium)
  * :uv:cve:`2026-10822` (medium)
  * :uv:cve:`2026-3592` (medium)
  * :uv:cve:`2026-5950` (medium)

:program:`bind9-host`
  * :uv:cve:`2026-10723` (medium)
  * :uv:cve:`2026-10822` (medium)
  * :uv:cve:`2026-3592` (medium)
  * :uv:cve:`2026-5950` (medium)

:program:`bind9-libs`
  * :uv:cve:`2026-10723` (medium)
  * :uv:cve:`2026-10822` (medium)
  * :uv:cve:`2026-3592` (medium)
  * :uv:cve:`2026-5950` (medium)

:program:`brace-expansion`
  * :uv:cve:`2026-13149` (high)
  * :uv:cve:`2026-69152` (high)

:program:`cryptography`
  * :uv:cve:`2026-69247` (high)
  * :uv:cve:`2026-69249` (high)

:program:`dmsetup`
  * :uv:cve:`2026-19617` (medium)

:program:`form-data`
  * :uv:cve:`2026-12143` (high)

:program:`immutable`
  * :uv:cve:`2026-59879` (high)
  * :uv:cve:`2026-59880` (high)

:program:`jackson-databind`
  * :uv:cve:`2026-54512` (high)
  * :uv:cve:`2026-54513` (high)
  * :uv:cve:`2026-54514` (medium)
  * :uv:cve:`2026-54515` (medium)
  * :uv:cve:`2026-54516` (medium)
  * :uv:cve:`2026-54517` (medium)
  * :uv:cve:`2026-54518` (medium)
  * :uv:cve:`2026-59888` (medium)
  * :uv:cve:`2026-59889` (medium)

:program:`js-yaml`
  * :uv:cve:`2026-59869` (high)
  * :uv:cve:`2026-53550` (medium)

:program:`libasound2`
  * :uv:cve:`2026-25068` (medium)

:program:`libasound2-data`
  * :uv:cve:`2026-25068` (medium)

:program:`libavahi-client3`
  * :uv:cve:`2024-52615` (medium)
  * :uv:cve:`2024-52616` (medium)
  * :uv:cve:`2025-59529` (medium)
  * :uv:cve:`2025-68276` (medium)
  * :uv:cve:`2025-68468` (medium)
  * :uv:cve:`2025-68471` (medium)
  * :uv:cve:`2026-24401` (medium)
  * :uv:cve:`2026-34933` (medium)

:program:`libavahi-common-data`
  * :uv:cve:`2024-52615` (medium)
  * :uv:cve:`2024-52616` (medium)
  * :uv:cve:`2025-59529` (medium)
  * :uv:cve:`2025-68276` (medium)
  * :uv:cve:`2025-68468` (medium)
  * :uv:cve:`2025-68471` (medium)
  * :uv:cve:`2026-24401` (medium)
  * :uv:cve:`2026-34933` (medium)

:program:`libavahi-common3`
  * :uv:cve:`2024-52615` (medium)
  * :uv:cve:`2024-52616` (medium)
  * :uv:cve:`2025-59529` (medium)
  * :uv:cve:`2025-68276` (medium)
  * :uv:cve:`2025-68468` (medium)
  * :uv:cve:`2025-68471` (medium)
  * :uv:cve:`2026-24401` (medium)
  * :uv:cve:`2026-34933` (medium)

:program:`libc-bin`
  * :uv:cve:`2026-4438` (medium)

:program:`libc6`
  * :uv:cve:`2026-4438` (medium)

:program:`libcups2`
  * :uv:cve:`2025-58436` (medium)
  * :uv:cve:`2025-61915` (medium)
  * :uv:cve:`2026-27447` (medium)
  * :uv:cve:`2026-34978` (medium)
  * :uv:cve:`2026-34979` (medium)
  * :uv:cve:`2026-39314` (medium)
  * :uv:cve:`2026-39316` (medium)
  * :uv:cve:`2026-41079` (medium)

:program:`libdevmapper1.02.1`
  * :uv:cve:`2026-19617` (medium)

:program:`libgcrypt20`
  * :uv:cve:`2026-41989` (medium)

:program:`libgnutls30`
  * :uv:cve:`2026-42014` (medium)
  * :uv:cve:`2026-42015` (medium)
  * :uv:cve:`2026-5419` (low)

:program:`libnss3`
  * :uv:cve:`2023-5388` (medium)
  * :uv:cve:`2023-6135` (medium)
  * :uv:cve:`2024-7531` (medium)
  * :uv:cve:`2026-6767` (medium)

:program:`libpython3.11-minimal`
  * :uv:cve:`2025-11468` (medium)
  * :uv:cve:`2025-12084` (medium)
  * :uv:cve:`2025-15282` (medium)
  * :uv:cve:`2025-4516` (medium)
  * :uv:cve:`2025-6069` (medium)
  * :uv:cve:`2025-8291` (medium)
  * :uv:cve:`2026-0672` (medium)
  * :uv:cve:`2026-0865` (medium)
  * :uv:cve:`2026-1299` (medium)
  * :uv:cve:`2025-13837` (low)
  * :uv:cve:`2025-6075` (low)

:program:`libpython3.11-stdlib`
  * :uv:cve:`2025-11468` (medium)
  * :uv:cve:`2025-12084` (medium)
  * :uv:cve:`2025-15282` (medium)
  * :uv:cve:`2025-4516` (medium)
  * :uv:cve:`2025-6069` (medium)
  * :uv:cve:`2025-8291` (medium)
  * :uv:cve:`2026-0672` (medium)
  * :uv:cve:`2026-0865` (medium)
  * :uv:cve:`2026-1299` (medium)
  * :uv:cve:`2025-13837` (low)
  * :uv:cve:`2025-6075` (low)

:program:`libssl3`
  * :uv:cve:`2026-42766` (medium)
  * :uv:cve:`2026-45446` (medium)
  * :uv:cve:`2026-42770` (low)

:program:`libssl3t64`
  * :uv:cve:`2026-42766` (medium)
  * :uv:cve:`2026-42769` (medium)
  * :uv:cve:`2026-45446` (medium)
  * :uv:cve:`2026-42768` (low)
  * :uv:cve:`2026-42770` (low)

:program:`libsystemd0`
  * :uv:cve:`2026-29111` (medium)
  * :uv:cve:`2026-40225` (medium)
  * :uv:cve:`2026-40226` (medium)
  * :uv:cve:`2026-4105` (medium)

:program:`libudev1`
  * :uv:cve:`2026-29111` (medium)
  * :uv:cve:`2026-40225` (medium)
  * :uv:cve:`2026-40226` (medium)
  * :uv:cve:`2026-4105` (medium)

:program:`libxml2`
  * :uv:cve:`2026-0990` (medium)
  * :uv:cve:`2026-1757` (medium)
  * :uv:cve:`2025-8732` (low)
  * :uv:cve:`2026-0989` (low)
  * :uv:cve:`2026-0992` (low)

:program:`micrometer-core`
  * :uv:cve:`2026-40983` (high)
  * :uv:cve:`2026-40984` (high)

:program:`nanoid`
  * :uv:cve:`2026-67213` (high)
  * :uv:cve:`2026-67214` (high)

:program:`net-tools`
  * :uv:cve:`2002-1976` (low)

:program:`netty-codec`
  * :uv:cve:`2026-59901` (high)

:program:`netty-codec-dns`
  * :uv:cve:`2026-73508` (medium)

:program:`netty-codec-haproxy`
  * :uv:cve:`2026-55851` (high)
  * :uv:cve:`2026-59919` (medium)

:program:`netty-codec-http`
  * :uv:cve:`2026-55831` (high)
  * :uv:cve:`2026-55833` (high)
  * :uv:cve:`2026-56745` (high)
  * :uv:cve:`2026-56746` (medium)
  * :uv:cve:`2026-59898` (medium)
  * :uv:cve:`2026-59899` (medium)
  * :uv:cve:`2026-59921` (medium)

:program:`netty-codec-http2`
  * :uv:cve:`2026-56819` (high)
  * :uv:cve:`2026-59900` (medium)

:program:`openjdk-17-jre-headless`
  * :uv:cve:`2026-41254` (high)
  * :uv:cve:`2026-47063` (high)
  * :uv:cve:`2026-46917` (medium)
  * :uv:cve:`2026-46968` (medium)
  * :uv:cve:`2026-47021` (medium)
  * :uv:cve:`2026-47027` (medium)
  * :uv:cve:`2026-60147` (medium)
  * :uv:cve:`2026-47010` (low)
  * :uv:cve:`2026-47059` (low)

:program:`openssh-client`
  * :uv:cve:`2026-35387` (medium)
  * :uv:cve:`2026-35388` (low)

:program:`openssl`
  * :uv:cve:`2026-42766` (medium)
  * :uv:cve:`2026-42769` (medium)
  * :uv:cve:`2026-45446` (medium)
  * :uv:cve:`2026-42768` (low)
  * :uv:cve:`2026-42770` (low)

:program:`openssl-provider-legacy`
  * :uv:cve:`2026-42766` (medium)
  * :uv:cve:`2026-42769` (medium)
  * :uv:cve:`2026-45446` (medium)
  * :uv:cve:`2026-42768` (low)
  * :uv:cve:`2026-42770` (low)

:program:`postcss`
  * :uv:cve:`2026-73646` (high)

:program:`postgresql`
  * :uv:cve:`2026-54291` (high)

:program:`python-multipart`
  * :uv:cve:`2026-53539` (high)
  * :uv:cve:`2026-53537` (medium)
  * :uv:cve:`2026-53538` (low)
  * :uv:cve:`2026-53540` (low)

:program:`python3.11`
  * :uv:cve:`2025-11468` (medium)
  * :uv:cve:`2025-12084` (medium)
  * :uv:cve:`2025-15282` (medium)
  * :uv:cve:`2025-4516` (medium)
  * :uv:cve:`2025-6069` (medium)
  * :uv:cve:`2025-8291` (medium)
  * :uv:cve:`2026-0672` (medium)
  * :uv:cve:`2026-0865` (medium)
  * :uv:cve:`2026-1299` (medium)
  * :uv:cve:`2025-13837` (low)
  * :uv:cve:`2025-6075` (low)

:program:`python3.11-minimal`
  * :uv:cve:`2025-11468` (medium)
  * :uv:cve:`2025-12084` (medium)
  * :uv:cve:`2025-15282` (medium)
  * :uv:cve:`2025-4516` (medium)
  * :uv:cve:`2025-6069` (medium)
  * :uv:cve:`2025-8291` (medium)
  * :uv:cve:`2026-0672` (medium)
  * :uv:cve:`2026-0865` (medium)
  * :uv:cve:`2026-1299` (medium)
  * :uv:cve:`2025-13837` (low)
  * :uv:cve:`2025-6075` (low)

:program:`rsyslog`
  * :uv:cve:`2026-19654` (high)
  * :uv:cve:`2015-3243` (medium)
  * :uv:cve:`2026-55556` (low)
  * :uv:cve:`2026-61548` (unknown)

:program:`sed`
  * :uv:cve:`2026-5958` (low)

:program:`starlette`
  * :uv:cve:`2024-47874` (high)
  * :uv:cve:`2025-54121` (medium)

:program:`tornado`
  * :uv:cve:`2026-49853` (high)
  * :uv:cve:`2026-49855` (high)
