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

.. _nubus-rate-limiting:

*************
Rate limiting
*************

Nubus doesn't provide rate limiting for its APIs and services.
If you expose an API or service to a network outside the Nubus deployment,
you're responsible for placing a reverse proxy, API gateway,
or comparable component in front of it that enforces rate limiting.

.. _nubus-rate-limiting-implementation-why:

What rate limiting protects against
====================================

Rate limiting in front of an exposed API is a security hardening measure
that reduces the risk of unauthorized automated use, such as:

Credential stuffing and password guessing
   Automated, high-volume attempts to authenticate,
   for example, against the Keycloak token endpoint or a sign-in page.

Scraping and data harvesting
   Automated, high-volume read requests against APIs that return directory or portal data.

Denial of service through resource exhaustion
   A high volume of requests, legitimate or not,
   that degrades the service for other users.

.. _nubus-rate-limiting-implementation-guide:

Generic implementation guide
============================

Implement rate limiting at the HTTP proxy or gateway layer
in front of the Nubus component.
This keeps the enforcement point independent of the application.
It also lets you apply the same mechanism consistently across exposed APIs.

Consider the following aspects when you design your rate limiting:

Identify the client
   Rate limit anonymous or pre-authentication traffic per client IP address.
   Examples include requests to a token or sign-in endpoint.
   For authenticated traffic, consider rate limiting per authenticated identity,
   such as an API client or subscription name,
   in addition to, or instead of, the client IP address.
   Per-identity limiting prevents a shared IP address, for example, behind a NAT gateway,
   from penalizing every user behind it.

Distinguish expensive and sensitive endpoints from cheap ones
   Apply stricter limits to endpoints that perform authentication,
   change state, or are computationally expensive,
   such as a token endpoint, a sign-in form, or a password reset request.
   Apply more permissive limits to inexpensive, read-only endpoints.

Allow for legitimate bursts
   A limit based only on a long-term average request rate
   can still allow a damaging short burst of requests.
   A limit that's too strict for short bursts
   can reject legitimate usage patterns.
   For example, a client might retry after a network interruption
   to catch up on pending requests.
   Most reverse proxies let you configure both a sustained rate and a burst allowance.

Respond consistently
   When you reject a request because it exceeds the limit,
   respond with the HTTP status code ``429 Too Many Requests``,
   and, where your proxy supports it,
   a ``Retry-After`` header that tells the client when to retry.
   This lets well-behaved clients back off correctly,
   instead of retrying immediately and adding to the load.

Exempt trusted, internal traffic where appropriate
   Some Nubus components already distinguish trusted internal callers
   from external callers for their built-in protections.
   For details, see :ref:`nubus-rate-limiting-umc`.
   Apply the same principle at your proxy.
   Use a policy for traffic from your infrastructure
   that differs from the policy for internet traffic.

Combine rate limiting with account lockout
   Rate limiting throttles request volume.
   It doesn't replace account lockout after repeated failed sign-in attempts.

   Nubus supports account lockout as a separate, opt-in mechanism in both deployments.
   For Keycloak-backed sign-in,
   see :ref:`nubus-rate-limiting-keycloak`.
   For the directory service in both deployments
   use the approach for OpenLDAP,
   see :ref:`nubus-rate-limiting-ldap`.

.. _nubus-rate-limiting-implementation-monitoring:

Monitor and alert on throttling
===============================

Configure your reverse proxy or API gateway to log rejected requests.
Monitor the resulting ``429`` responses.
Configure an alert for a sudden increase in throttled requests
against a specific API.
Such an increase can indicate an automated abuse attempt,
even when the rate limit protects the backing service.
Investigate and respond to the attempt.

.. _nubus-rate-limiting-implementation-configuration:

Configure rate limiting
=======================

For deployment-specific configuration guidance, see:

* For Nubus for Kubernetes:
  :external+uv-nubus-kubernetes-operation:ref:`conf-ingress-rate-limiting`
  in :cite:t:`uv-nubus-kubernetes-operation`.

* For Nubus for UCS:
  :external+uv-ucs-operation:ref:`system-administration-rate-limiting`
  in :cite:t:`uv-ucs-operation`.

.. _nubus-rate-limiting-implementation-apis:

Nubus APIs to consider for rate limiting
========================================

This section gives an overview of the APIs and services in scope,
whether Nubus exposes them externally by default,
and how each of them authenticates requests.

.. _nubus-rate-limiting-keycloak:

Keycloak authentication APIs
----------------------------

Keycloak is an identity provider.
It exposes OpenID Connect (OIDC) and Security Assertion Markup Language (SAML) endpoints.
Other components and third-party applications use these endpoints to sign in
and retrieve tokens.

The :samp:`/realms/{REALM_NAME}/protocol/openid-connect/token` endpoint provides tokens.
Replace :samp:`{REALM_NAME}` with the Keycloak realm name.

Wherever Keycloak is in use,
its token endpoint is intentionally reachable without an existing session.
Callers authenticate directly with client credentials or a username and password.
This makes the token endpoint a target for credential stuffing
and password-guessing at high request volume.

.. dropdown:: Overview
   :open:
   :icon: checklist
   :color: info

   Authentication
      OpenID Connect (OIDC) or Security Assertion Markup Language (SAML) identity provider.
      The token endpoint itself accepts client credentials
      or a resource owner password without a prior session.

   Built-in abuse protection
      No protection by default.

   Exposed by default
      .. tab-set::

         .. tab-item:: Nubus for Kubernetes
            :sync: kubernetes

            Yes, exposure by default.

            Nubus for Kubernetes deploys Keycloak as the domain's identity provider by default
            and exposes it externally by default.

            .. important::

               Nubus for Kubernetes deploys with the optional *Keycloak Extensions* deactivated by default.
               Without them, Keycloak has no brute force protection at all beyond a basic,
               username-only lockout counter.
               With them enabled, brute force protection still only covers the interactive sign-in page,
               not direct requests to the token endpoint.

         .. tab-item:: Nubus for UCS
            :sync: ucs

            No exposure by default.
            Nubus for UCS has single sign-on deactivated by default.

            If you install the optional :program:`Keycloak` app,
            it activates single sign-on.

.. seealso::

   :external+uv-ucs-operation:ref:`management-interface-auth-sso`
      in :cite:t:`uv-ucs-operation`
      for information about single sign-on and the Keycloak app in Nubus for UCS.

   :external+uv-nubus-kubernetes-architecture:ref:`component-identity-provider-keycloak-extensions-brute-force-protection`
      in :cite:t:`uv-nubus-kubernetes-architecture`
      for information about the brute force protection for the Keycloak sign-in page,
      and why it doesn't cover direct token endpoint requests.

   :external+uv-nubus-kubernetes-operation:ref:`conf-keycloak-extensions`
      in :cite:t:`uv-nubus-kubernetes-operation`
      for how to enable the *Keycloak Extensions*.

.. _nubus-rate-limiting-udm-rest:

UDM HTTP REST API
-----------------

For the full description of the *UDM HTTP REST API*,
see :external+uv-nubus-customization:ref:`customization-api-udm-rest`
in :cite:t:`uv-nubus-customization`

For API exposure and rate-limiting requirements, see
:external+uv-nubus-customization:ref:`customization-api-udm-rest`
in :cite:t:`uv-nubus-customization`.

.. dropdown:: Overview
   :open:
   :icon: checklist
   :color: info


   Authentication
      HTTP Basic authentication against a directory account.

   Built-in abuse protection
      None.

   Exposed by default
      .. tab-set::

         .. tab-item:: Nubus for Kubernetes
            :sync: kubernetes

            No exposure by default.
            You can activate it through
            :external+uv-nubus-kubernetes-operation:envvar:`nubusUdmRestApi.ingress.enabled`.

         .. tab-item:: Nubus for UCS
            :sync: ucs

            Follows the exposure of the Primary Directory Node.

.. _nubus-rate-limiting-provisioning:

Provisioning API
----------------

For the full description of the *Provisioning API*,
see :external+uv-nubus-customization:ref:`customization-api-provisioning`
in :cite:t:`uv-nubus-customization`.

For API access and rate-limiting requirements, see
:external+uv-nubus-customization:ref:`customization-api-provisioning-endpoint-access`
in :cite:t:`uv-nubus-customization`.

.. dropdown:: Overview
   :open:
   :icon: checklist
   :color: info


   Authentication
      HTTP Basic authentication with subscription or administrator credentials.

   Built-in abuse protection
      None.

   Exposed by default
      .. tab-set::

         .. tab-item:: Nubus for Kubernetes
            :sync: kubernetes

            No exposure by default,
            because ingress is deactivated.

         .. tab-item:: Nubus for UCS
            :sync: ucs

            No exposure by default.
            After you install the *Provisioning API* app
            it follows the exposure of the Directory Node
            that has the app installed.

.. _nubus-rate-limiting-ldap:

Directory Service
-----------------

Nubus provides directory access through LDAP,
served by OpenLDAP.
It isn't an HTTP API,
so the generic HTTP-proxy rate limiting guide in
:ref:`nubus-rate-limiting-implementation-guide`
doesn't apply to it directly.

.. dropdown:: Overview
   :open:
   :icon: checklist
   :color: info


   Authentication
      LDAP simple bind.

   Built-in abuse protection
     None by default.
     Optionally, an OpenLDAP password policy locks out an account after repeated failed binds.

   Exposed by default
      .. tab-set::

         .. tab-item:: Nubus for Kubernetes
            :sync: kubernetes

            No exposure by default,
            The cluster-internal ``ClusterIP`` service by default.

            Univention recommends that third-party services connect through the *LDAP proxy* instances
            rather than directly to the primary LDAP instances.
            See :external+uv-nubus-kubernetes-operation:ref:`conf-ldap-scalability`
            in :cite:t:`uv-nubus-kubernetes-operation`.

         .. tab-item:: Nubus for UCS
            :sync: ucs

            It follows the exposure of the Directory Node
            that provides the directory service.

            Nubus for UCS optionally supports account lockout after repeated failed LDAP binds
            through an OpenLDAP password policy.
            This is a lockout, not rate limiting:
            it blocks an account after a threshold of failures instead of throttling request volume,
            and it's off by default.

.. important::

   If you need to expose LDAP to a network outside Nubus,
   for example, for an external directory synchronization,
   use network-level controls instead of an HTTP proxy.
   Use one of the following controls:

   * Firewall rules that allow only a limited set of remote networks.

   * A virtual private network (VPN).

   * Connection-count and rate limiting at the load balancer or an LDAP-aware proxy.

.. seealso::

   :external+uv-ucs-operation:ref:`iam-user-lockout-openldap`
      in :cite:t:`uv-ucs-operation`
      for how to configure the OpenLDAP password policy lockout.

.. _nubus-rate-limiting-umc:

Management UI
-------------

The *Management UI*
is the core management interface of Nubus.
Nubus exposes the *Management UI* externally by default
in Nubus for Kubernetes and Nubus for UCS.

.. dropdown:: Overview
   :open:
   :icon: checklist
   :color: info

   Authentication
      .. tab-set::

         .. tab-item:: Nubus for Kubernetes
            :sync: kubernetes

            OIDC sign-in through Keycloak, then a server-side session.

         .. tab-item:: Nubus for UCS
            :sync: ucs

            Local sign-in by default,
            or SAML through Keycloak if you install and activate it.

   Built-in abuse protection
      The self-service management module,
      used for actions such as password reset and contact verification,
      already has built-in rate limiting for repeated requests from the same client,
      backed by Memcached.
      See :external+uv-nubus-kubernetes-operation:ref:`conf-self-service`
      in :cite:t:`uv-nubus-kubernetes-operation`.


      Sign-in: No protection by default.
      Optionally, a PAM account lockout.

   Exposed by default
      .. tab-set::

         .. tab-item:: Nubus for Kubernetes
            :sync: kubernetes

            Yes, exposure by default.

            Nubus for Kubernetes authenticates UMC users through Keycloak,
            followed by a server-side session.

         .. tab-item:: Nubus for UCS
            :sync: ucs

            Yes, exposure by default.
            The *Management UI* is the core UCS management interface.

            Nubus for UCS signs users in locally by default,
            or through Keycloak if you install and activate single sign-on,
            see :ref:`nubus-rate-limiting-keycloak`.

            Nubus for UCS optionally supports an account lockout after repeated failed sign-in attempts,
            through the PAM stack that UMC authenticates against.
            As with the :ref:`OpenLDAP lockout <nubus-rate-limiting-ldap>`,
            this blocks an account after a threshold of failures instead of throttling request volume,
            and it's off by default.

.. important::

   The self-service rate limiting only covers the self-service module.
   The rest of the UMC API surface, including its sign-in and session endpoints,
   has no rate limiting of its own.

.. seealso::

   :external+uv-ucs-operation:ref:`iam-user-lockout`
      in :cite:t:`uv-ucs-operation`
      for how to configure account lockout after failed sign-in attempts,
      including for the PAM stack that UMC uses.

.. _nubus-rate-limiting-portal:

Portal
------

The Portal is the domain's landing page in Nubus.
It exposes anonymous, static content and endpoints that reflect the signed-in user's session,
such as personalized navigation.

.. dropdown:: Overview
   :open:
   :icon: checklist
   :color: info


   Authentication
      Session cookie for personalized content.
      Most static content is anonymous.

   Built-in abuse protection
      None.

   Exposed by default
      .. tab-set::

         .. tab-item:: Nubus for Kubernetes
            :sync: kubernetes

            Yes, exposure by default.

         .. tab-item:: Nubus for UCS
            :sync: ucs

            Yes, exposure by default.
            The Portal is the domain's default landing page.

Consider rate limiting for the Univention Portal for the following reasons:

* Protect authenticated, session-bound endpoints against abuse.

* Protect anonymous, static endpoints against scraping and high-volume automated requests.

.. _nubus-rate-limiting-guardian:

Guardian
--------

The Guardian is the authorization engine for Nubus.
It runs *Cerbos* as the policy decision point,
and Nubus doesn't expose it externally by default.

.. dropdown:: Overview
   :open:
   :icon: checklist
   :color: info


   Authentication
      No authentication on its own.

   Built-in abuse protection
      None.

   Exposed by default
      .. tab-set::

         .. tab-item:: Nubus for Kubernetes
            :sync: kubernetes

            No exposure by default.

         .. tab-item:: Nubus for UCS
            :sync: ucs

            No, exposure by default.

.. important::

   Cerbos trusts every caller that can reach it
   and has no authentication of its own.
   If you build custom infrastructure to expose the Guardian
   outside its trusted network,
   add both authentication and rate limiting in front of it.


.. spelling:word-list::

   Cerbos
   OIDC
