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

.. _conf-import-external-iam:

************************
Import from external IAM
************************

This section describes the *Nubus Directory Importer*
and how you use it to run a complete import
on the entirety of user accounts from a subtree in an external IAM system.
It describes the general steps to connect external IAM systems
and single sign-on through the protocols SAML and OpenID Connect
to Univention Nubus.
The setup is for a unidirectional **import** of directory objects,
such as user accounts and user groups.

If you need all user accounts from a subtree in an external IAM system
in the *Directory Service* of Nubus for Kubernetes,
and also want to regularly transfer user updates
from your external IAM system,
this section and the *Nubus Directory Importer* is for you.

If you only need those user accounts
that actually use the system,
or if you want to save time on the import procedure,
or if you don't care about modifications to user accounts
in your external IAM system after the initial import,
then the federation between the *Identity Provider* in Nubus with an external IAM system is for you.
Refer to :ref:`conf-ad-hoc-provisioning`.

For your understanding, this how-to uses the following definitions:

Source IAM system
   is the external IAM system
   that has directory objects designated for import to Nubus.
   Nubus can use it as source for user account objects, user group objects,
   and as identity provider for user sign-in.

Target
   The target of the import is the *Identity Provider* component in Nubus for Kubernetes.

The connection uses the following processes:

Import
   During import,
   the connector reads user account objects and user group objects through LDAP
   from the source and the target,
   calculates the differences
   and adds them to the target using the *UDM HTTP REST API*
   from the *Directory Manager* in Univention Nubus.

Single sign-on
   For single sign-on, Nubus uses the external IAM system as
   *SAML Identity Provider* or as *OpenID Connect Relying Party*.
   The *Identity Provider* from Univention Nubus becomes a client to the external IAM system.

.. seealso::

   :external+uv-nubus-kubernetes-architecture:ref:`component-nubus-directory-importer` in the functional components section
      in :cite:t:`uv-nubus-kubernetes-architecture`
      for information about the architecture of the :program:`Nubus Directory Importer`.

.. _conf-import-external-iam-prerequisites:

Prerequisites
=============

Before you begin, you need to fulfill the following requirements:

#. The source must provide access to user account objects and user group objects through LDAP.

#. The source must provide an identity provider that supports the protocols SAML or OpenID Connect.

#. You have a running instance of Univention Nubus for Kubernetes.
   For installation, see :ref:`nubus-deployment`.

#. For the synchronization of user accounts and user groups
   between the source and the target
   you need the :program:`Nubus Directory Importer`.

#. The Nubus for Kubernetes environment needs appropriate amounts of memory and disk space.

   Memory
     Appropriate amounts of memory needed for the following pods:

     :``ldap-primary``: :envvar:`nubusLdapServer.resourcesPrimary.limits.memory`
     :``ldap-secondary``: :envvar:`nubusLdapServer.resourcesSecondary.limits.memory`
     :``provisioning-listener``: :envvar:`nubusUdmListener.resources.limits.memory`
     :``udm-rest-api``: :envvar:`nubusUdmRestApi.resources.limits.memory`

   Disk space
     Appropriate amounts of disk space needed for the following pods:

     :``ldap-primary``: :envvar:`nubusLdapServer.persistence.size`
     :``ldap-secondary``: :envvar:`nubusLdapServer.persistence.size`
     :``provisioning-listener``: :envvar:`nubusUdmListener.persistence.size`

#. Before you set up the :program:`Nubus Directory Importer`,
   you must complete the following prerequisites.

   Service accounts
      #. The source system requires a service account
         with the permissions in the respective subtree
         to search and read all user objects and user group objects.

      #. The target system Nubus for Kubernetes
         needs a service account
         with the permission to write
         user account objects and user group objects
         to the respective OU
         and the permission
         to use the *UDM HTTP REST API*.

         For information about authentication groups,
         :external+uv-nubus-customization:ref:`customization-api-udm-rest-auth-group`
         in :cite:t:`uv-nubus-customization`.

   Network
      The Nubus Directory Importer:

      * Must reach the UDM HTTP REST API in the *Directory Manager* component in Univention Nubus for Kubernetes
        on port ``443/tcp``.

      * Must reach the source system.
        The port depends on the source system
        and typically is ``636/tcp``.

      * Doesn't need inbound connections.

   Encrypted connections with TLS
      The Nubus Directory Importer sends clear text passwords
      to authenticate with the source and target through LDAP.
      You need to ensure that all source and target systems have properly configured encrypted connections through TLS.
      An encrypted connection is especially important,
      if the *Nubus Directory Importer* runs on a **different network**
      than the Kubernetes cluster with the *UDM HTTP REST API*.

      For Nubus for Kubernetes being the target system,
      the TLS configuration is already in place in the default setup.
      For the URL of the API, see :ref:`conf-import-external-iam-authentication-udm-rest`.

   .. note::

      The Nubus Directory Importer doesn't read and synchronize user account passwords,
      or their hashes from the directories.

      To complete the setup and allow the synchronized user accounts to authenticate,
      you need to :ref:`conf-import-external-iam-sso-setup`.

.. _conf-import-external-iam-authentication-udm-rest:

Connection setup for UDM HTTP REST API
======================================

To import user accounts and user groups to Nubus for Kubernetes,
you use the *UDM HTTP REST API*.
This section describes
how you connect to it.
For the *Nubus Directory Importer* you need the following sections:

#. For the URL to the API,
   :external+uv-nubus-customization:ref:`customization-api-udm-rest-location`.

#. For authentication,
   :external+uv-nubus-customization:ref:`customization-api-udm-rest-auth`.

.. seealso::

   :external+uv-nubus-customization:ref:`customization-api-udm-rest`
     in :cite:t:`uv-nubus-customization`
     for information about the *UDM HTTP REST API*.

.. _conf-import-external-iam-installation:

Nubus Directory Importer installation
=====================================

:program:`Nubus Directory Importer` is an application,
that searches for user account objects and user group objects in the source and the target through LDAP.
It synchronizes the found objects to the *Directory Manager* in Nubus through the *UDM HTTP REST API*.

Nubus Directory Importer reads both source and target directory services
and determines the differences as a basis for the modification.
The connector doesn't store local states.

The synchronization process writes the complete OU structure of the source directory service
to a dedicated OU in the target directory service, meaning Nubus.
The connector uses the preconfigured UDM property ``univentionObjectIdentifier`` as primary key in the target system
to identify user objects and user group objects.

.. note::

   Renaming a group, that references a nested group,
   may require two runs of Nubus Directory Importer
   to update the entries on the target system.

.. seealso::

   :external+uv-nubus-kubernetes-architecture:ref:`component-nubus-directory-importer`
      for information on the architecture of the *Nubus Directory Importer*
      in :cite:t:`uv-nubus-kubernetes-architecture`.

The :program:`Nubus Directory Importer` is available as container image.
You can deploy it
either in Docker with the help of Docker Compose,
or in Kubernetes using the Helm Chart.
This section covers both methods.

For either installation method,
use the following preparation steps:

0. Ensure that you fulfill the
   :ref:`conf-import-external-iam-prerequisites`.

#. On your local machine,
   create a directory for the configuration of the *Nubus Directory Importer*,
   for example :file:`nubus-directory-importer`.

#. Depending on your preferred installation method for the *Nubus Directory Importer*,
   continue with either one of the following sections:

   * :ref:`conf-import-external-iam-install-importer-docker-compose`
   * :ref:`conf-import-external-iam-install-importer-helm`

.. tip::

   The example configuration is
   for using a Microsoft Active Directory as external IAM system.
   For other external IAM products,
   adjust the file accordingly.

.. seealso::

   `Git Repository for Nubus Directory Importer <https://github.com/univention/nubus-directory-importer>`_
      for more information about the importer.

.. _conf-import-external-iam-install-importer-docker-compose:

Docker Compose
--------------

This section describes how to run :program:`Nubus Directory Importer`
through Docker Compose.
Describing installation and setup of Docker Compose is beyond the scope of this documentation.

.. warning::

   Only one instance of *Nubus Directory Importer* must run at a time.
   Running multiple instances simultaneously can cause data inconsistencies
   in the target directory service.

   Unlike the Helm Chart deployment,
   Docker Compose doesn't enforce a single instance automatically.
   You must ensure that only one instance runs at all times,
   including in failover scenarios.
   Before starting a new instance,
   confirm that any previous instance has fully stopped.

To run *Nubus Directory Importer* through Docker Compose,
continue after the steps outlined in :ref:`conf-import-external-iam-installation`
and use the following steps:

3. Inside the directory for the importer,
   create the :file:`config` directory
   to save the configuration.

#. Download
   `ad-domain-config.yaml.example <https://github.com/univention/nubus-directory-importer/blob/main/config/ad-domain-config.yaml.example>`_
   from the project repository.
   In your local project directory,
   create the :file:`config` directory.
   Move and rename the example configuration file to :file:`config/ad-domain-config.yaml`.

#. Download the
   `docker-compose.yml <https://github.com/univention/nubus-directory-importer/blob/main/docker-compose.yml>`_
   file from the project repository
   and save it to your local project directory.

#. For a TLS configuration with custom certificates,
   see :ref:`conf-import-external-iam-tls`.

#. To start the importer,
   run the command in :numref:`conf-import-external-iam-install-importer-docker-compose-run-listing`.

   .. code-block:: console
      :caption: Run the *Nubus Directory Importer* with Docker Compose
      :name: conf-import-external-iam-install-importer-docker-compose-run-listing

      $ docker compose up --detach

.. _conf-import-external-iam-install-importer-helm:

Helm Chart and Kubernetes
-------------------------

This section describes how to install :program:`Nubus Directory Importer`
to a Kubernetes cluster through Helm with a Helm Chart.

To install *Nubus Directory Importer* through a Helm Chart,
continue after the steps outlined in :ref:`conf-import-external-iam-installation`
and use the following steps:

3. Download the
   `tilt-values.yaml <https://github.com/univention/nubus-directory-importer/blob/main/tilt-values.yaml>`_
   file,
   rename it to :file:`custom-values.yaml`
   and save it to your local project directory.
   The file is a minimal example.

   The settings below ``configFile`` correspond to the available values described at :ref:`conf-import-external-iam-configure-importer`.

#. Install *Nubus Directory Importer* with the command in :numref:`conf-import-external-iam-install-importer-helm-listing`.

   .. code-block:: console
      :caption: Install *Nubus Directory Importer* through Helm Chart
      :name: conf-import-external-iam-install-importer-helm-listing

      $ export YOUR_DESIRED_NAMESPACE="Your preferred namespace for the importer"
      $ helm upgrade \
          --namespace "$YOUR_DESIRED_NAMESPACE" \
          --version "$VERSION_IMPORTER" \
          --values custom_values.yaml \
          oci://artifacts.software-univention.de/nubus-dev/charts/directory-importer

.. seealso::

   For a complete reference of the Helm Chart values of the *Nubus Directory Importer*,
   see the Helm Chart README file and the :file:`values.yaml` file:

   * `README.md <https://github.com/univention/nubus-directory-importer/blob/main/helm/directory-importer/README.md>`_
   * `values.yaml <https://github.com/univention/nubus-directory-importer/blob/main/helm/directory-importer/values.yaml>`_

.. _conf-import-external-iam-tls:

TLS in Nubus Directory Importer
-------------------------------

For secure connections between *Nubus Directory Importer*
and the source and the target IAM systems,
the strong recommendation is to use TLS.

.. important::

   The following steps are only necessary,
   if the certificates in the source or the target system
   aren't signed by a well-known public certificate authority,
   such as *Let's Encrypt*.

.. tab-set::

   .. tab-item:: Docker Compose

      To provide the custom CA certificate in the Docker Compose setup,
      use the following steps:

      #. For the connection to the external IAM system,
         save the CA certificate to the :file:`config/ca_ad.crt` file in your project directory.

      #. For the connection to Nubus,
         save the CA certificate to the :file:`config/ca-nubus.crt` file in your project directory.

      #. In your :file:`docker-compose.yml`,
         remove the comments from the respective lines in the ``services.directory-importer.volumes`` section
         that mount the certificates for the *Nubus Directory Importer*.

   .. tab-item:: Helm Chart and Kubernetes

      To provide the custom CA certificate in the Kubernetes setup,
      use the following steps:

      #. For the connection to the external IAM system,
         create a secret that contains the CA certificate of the external IAM system.

      #. Optional: If you additionally want to secure the connection
         to Nubus inside the Kubernetes cluster,
         create a secret that contains the CA certificate of Nubus.

      #. Add the secrets references and mount points
         to your :file:`custom_values.yaml` file
         as shown in :numref:`conf-import-external-iam-tls-listing`.

         .. code-block:: yaml
            :caption: Add CA certificates to values file
            :name: conf-import-external-iam-tls-listing

            configFile:
              source:
                ca_cert: "/etc/ssl/certs/ca-certificates-ad.crt"
              # Optional
              udm:
                ca_cert: "/etc/ssl/certs/ca-certificates-nubus.crt"
            extraVolumes:
              - name: "certificates"
                secret:
                  secretName: "Your custom secret name of CA certificate for external IAM system"
              # Optional
              - name: "nubus-certificates"
                secret:
                  secretName: "Your custom secret name of CA certificate for Nubus"
            extraVolumeMounts:
              - name: "certificates"
                mountPath: "/etc/ssl/certs/ca-certificates-ad.crt"
              # Optional
              - name: "nubus-certificates"
                mountPath: "/etc/ssl/certs/ca-certificates-nubus.crt"

.. _conf-import-external-iam-configure-importer:

Configuration of Nubus Directory Importer
=========================================

For the configuration of the :program:`Nubus Directory Importer`,
you use a text file in YAML format.
At the top-level hierarchy it has the following configuration dictionaries:

:``udm``: Configuration parameters that define the connection to UDM.

:``source``: Configuration parameters that define the connection to the source
             and rules for transformation.

Example configuration
---------------------

You find a configuration example in the repository of the *Nubus Directory Importer*,
see `ad-domain-config.yaml.example <https://github.com/univention/nubus-directory-importer/blob/main/config/ad-domain-config.yaml.example>`_.

For a configuration example
that extends the standard properties with additional user attributes,
refer to `ad-domain-config-extended.yaml.example <https://github.com/univention/nubus-directory-importer/blob/main/config/ad-domain-config-extended.yaml.example>`_

.. important::

    To extend properties on the destination system,
    you must include *all default user properties* in your configuration
    along with your custom properties.

    For the complete list of default properties,
    refer to `CFG_USER_PROPS_DEFAULT
    <https://github.com/univention/nubus-directory-importer/blob/main/univention/directory_importer/config.py#L56-L85>`_
    variable
    that contains the default synchronization properties.

.. _conf-import-external-iam-importer-configuration-reference:

Configuration reference
-----------------------

This section provides a reference for the configuration values of the :program:`Nubus Directory Importer`.

.. To reference the following content, use :py:data:`udm.uri`, for example.

Section: ``udm``
~~~~~~~~~~~~~~~~

.. py:module:: udm

.. py:data:: uri

   URI including base path for accessing UDM HTTP REST API.

.. py:data:: user

   Username used for authenticating to UDM.

.. py:data:: password

   User password used for authenticating to UDM.

.. py:data:: ca_cert (optional)

   Path of the trusted CA certificate bundle file. Defaults to your platform-specific CA bundle file.

.. py:data:: skip_writes (optional)

   If ``true``, skip write operations to UDM. Default: ``false``.

.. py:data:: connect_timeout (optional)

   Timeout in seconds to wait for connection to UDM.
   Default: ``6.0`` seconds.

.. py:data:: read_timeout (optional)

   Timeout in seconds to wait for UDM results.
   Default: ``1800`` seconds.

.. py:data:: user_ou

   Name of the OU used as target container for user entries.

.. py:data:: user_primary_key_property (optional)

   UDM property to use for storing the remote primary key for users.

.. py:data:: user_properties (optional)

   List of user property names the directory importer writes to.

.. py:data:: group_ou

   Name of the OU used as target container for group entries.

.. py:data:: group_primary_key_property (optional)

   UDM property to use for storing the remote primary key for groups.

.. py:data:: group_properties (optional)

   List of group property names the connector writes to.

Section ``source``
~~~~~~~~~~~~~~~~~~

.. py:module:: source

.. py:data:: ldap_uri

   LDAP URI of the source directory to connect to.
   Configure an URI starting with ``ldaps://``
   to ensure that the connector uses LDAP over TLS right from the beginning.

.. py:data:: bind_dn

   The bind DN to use authenticate to the source directory through LDAP simple bind operation.

.. py:data:: password

   The clear-text password to use with LDAP simple bind operation.

.. py:data:: ca_cert (optional)

   Path of the trusted CA certificate bundle file.
   Defaults to your platform-specific CA bundle file.

.. py:data:: timeout (optional)

   Timeout in seconds to wait for network. Default: ``5`` seconds.

.. py:data:: search_pagesize (optional)

   Number of entries the LDAP server returns per page
   when using the *Simple Paged Results* control.
   For more information, see :rfc:`2696`.
   Default: ``500``.

   Set to ``0`` to deactivate paged search
   and retrieve all results in a single request.

   .. warning::

      Don't set this value to ``0`` in large environments.
      If the result set exceeds the LDAP server's size limit,
      the importer aborts and doesn't write any results.

.. py:data:: user_base

   search base used when searching user entries.

.. py:data:: user_scope

   Search scope used when searching user entries.

   Default: ``"sub"``.

   Possible values: ``"one"``, ``"sub"``.

.. py:data:: user_filter (optional)

   LDAP filter used when searching user entries.

.. py:data:: user_attrs (optional)

   Request LDAP attributes while searching for users.
   Recommendation: only list the attributes actually used in the transformation and mapping later.

.. py:data:: user_range_attrs (optional)

   LDAP user attributes for which values are optionally retrieved
   by *Range Retrieval* for Microsoft Active Directory.

.. py:data:: user_trans

   Data transformation configuration applied to user entries.

.. py:data:: group_base

   search base used when searching group entries.

.. py:data:: group_scope

   Search scope used when searching group entries.

   Default: ``"sub"``.

   Possible values: ``"one"``, ``"sub"``.

.. py:data:: group_filter (optional)

   LDAP filter used when searching group entries.

.. py:data:: group_attrs (optional)

   Request LDAP attributes while searching for groups.
   Recommendation: only list the attributes actually used in the transformation and mapping later.

.. py:data:: group_range_attrs (optional)

   LDAP group attributes for which values are optionally retrieved by
   *Range Retrieval* for Microsoft Active Directory.

.. py:data:: group_trans

   Data transformation configuration applied to group entries.

.. note::

   :program:`python-ldap` uses the OpenLDAP client library :program:`libldap`.
   And :program:`libldap` implements a TLS hostname verification
   that strictly requires the hostname in the LDAP URI
   to match one of the DNS values of X.509v3 extension ``_subjectAltName_``
   in the source directory's TLS server certificate.

.. _conf-import-external-iam-performance:

Performance optimizations
=========================

If your *Directory Service* in Nubus for Kubernetes
would contain more than 25,000 user accounts
after the synchronization with the external IAM system,
the primary user group has more than 5,000 user accounts,
and you want to synchronize with an external IAM system,
you need to apply the recommended optimizations in this section
to run the import in an acceptable amount of time.

.. _conf-import-external-iam-performance-group-updates:

Deactivate primary group updates
--------------------------------

By default,
the *Directory Manager* assigns the ``Domain Users`` user group
as the primary user group to imported user accounts.
Having many group members in the primary user group
degrades the performance of user account creation exponentially.
Deactivating the *Directory Manager's* default behavior
of adding created user accounts to the primary group mitigates the performance degradation.

To deactivate the primary group updates in the *Directory Service*,
add the lines from
:numref:`conf-import-external-iam-performance-group-updates-helm-listing`
to your :file:`custom_values.yaml` file of your *Nubus for Kubernetes* installation.

In consequence, the permissions derived from a membership in the ``Domain Users`` no longer apply.
You need to manage them separately, for example through memberships in other user groups.
Keep in mind that those user groups shouldn't extend 5,000 user members, as well.

.. code-block:: yaml
   :caption: Deactivate primary group updates in *Directory Service* of Nubus for Kubernetes
   :name: conf-import-external-iam-performance-group-updates-helm-listing

   global:
     configUcr:
       directory:
         manager:
           user:
             primarygroup:
               update: false

.. _conf-import-external-iam-performance-index-univentionobjectidentifier:

Index for ``univentionObjectIdentifier``
----------------------------------------

``univentionObjectIdentifier`` is an LDAP attribute
that stores the primary identifier of an object from the source directory.
The *Directory Manager* in Nubus enforces the uniqueness of this attribute
by searching for existing occurrences in the *Directory Service*.
If the *Directory Service* doesn't have an index on the ``univentionObjectIdentifier`` attribute,
searches for the attribute lead to an exponential performance degradation
in environments with many user account objects.

Since Nubus for Kubernetes 1.9.0,
the ``univentionObjectIdentifier`` LDAP attribute
has an index for better performance.
For more information, see
:external+uv-navigation:ref:`nubus-kubernetes-release-notes`.

.. _conf-import-external-iam-sso-setup:

Setup single sign-on
====================

The *Identity Provider* within Nubus uses :program:`Keycloak`
and supports both SAML and OpenID Connect protocols.
The *Nubus Directory Importer* imports user account and group account data
from an external IAM system.
The import process doesn't copy user account credentials
for compliance, security, and operational reasons.
To allow the users to sign in to Nubus with their user accounts
from the external IAM system,
you need to set up *Keycloak* to delegate the authentication
through its broker functionality to other identity providers.
Depending on the configuration of the identity broker,
end users can choose the identity provider in the Keycloak login dialog.
Keycloak acts as a proxy service,
forwarding the user's sign-in request to the source IAM system
and translating between SAML and OpenID Connect, if necessary.

This section describes how to set up single sign-on between
the external source IAM system as identity provider
and the *Identity Provider* within Univention Nubus for Kubernetes as service provider.
You need to configure Keycloak as an *Identity Broker* to use the source system
as a source for identities.

Before you start, make sure
that the external IAM system and Keycloak communicate through port ``443``.

.. _conf-import-external-iam-sso-keycloak-source:

Add source system to Keycloak
-----------------------------

To add the source system to Keycloak, use the following steps:

#. Sign in to the *Keycloak Admin Console*,
   as described in :ref:`getting-started-keycloak-admin-console`.

#. Go to the section :guilabel:`Identity Provider`.

#. Select a user-defined identity provider based on
   either :guilabel:`OpenID Connect v1.0` or :guilabel:`SAML v2.0`.

#. Provide the information about the source system.

   .. tab-set::

      .. tab-item:: *OpenID Connect v1.0*
         :sync: oidc

         For OpenID Connect you need to provide the following values:

         * *Alias*
         * *Discovery endpoint*
         * *Client ID*
         * *Client Secret*
         * Other optional values

      .. tab-item:: *SAML v2.0*
         :sync: saml

         For SAML you need to provide the following values:

         * *Alias*
         * *Service provider entity ID*
         * *SAML entity descriptor*
         * Other optional values

#. Go to the section :guilabel:`Authentication` to configure different login flows.
   For the use case in this how-to, select the default flow *browser*.

#. Copy the login flow *browser*, provide a name and customize it to your needs.

   .. important::

      Change the parameter *Identity Provider Redirector* to ``Required``.
      The parameter enforces the redirection to the source system
      and end users don't have to select the source system in the login dialog.

#. In the step *Identity Provider Redirector*,
   click the cog wheel and
   select your previously created identity provider for your source system.

.. seealso::

   Refer to the following resources from :cite:t:`keycloak-latest`.
   Make sure to select the documentation that matches the Keycloak version in Univention Nubus for Kubernetes.

   `Integrating identity providers <https://www.keycloak.org/docs/latest/server_admin/index.html#_identity_broker>`_
      for the Keycloak documentation about external identity providers.

   `OpenID Connect v1.0 identity providers <https://www.keycloak.org/docs/latest/server_admin/index.html#_identity_broker_oidc>`_
      for the procedure to add a user-defined *OpenID Connect v1.0* identity provider.

   `SAML v2.0 identity providers <https://www.keycloak.org/docs/latest/server_admin/index.html#saml-v2-0-identity-providers>`_
      for the procedure to add a user-defined *SAML v2.0* identity provider.

   `Authentication flows <https://www.keycloak.org/docs/latest/server_admin/index.html#_authentication-flows>`_
      for the description of authentication flows.

.. _conf-import-external-iam-sso-keycloak-client-source:

Add Keycloak as client to source system
---------------------------------------

To add Keycloak as client in the source system, use the following steps:

#. Create a client configuration for Keycloak in the source system.

   .. tab-set::

      .. tab-item:: *OpenID Connect v1.0*
         :sync: oidc

         For OpenID Connect you need to provide the following values:

         * *Client ID*
         * *Client Secret*
         * *Redirect URI*

      .. tab-item:: *SAML v2.0*
         :sync: saml

         For SAML you need to provide the XML metadata from Keycloak.

#. Finally, you need to define the attributes that the source system forwards to Keycloak.

.. _conf-import-external-iam-sso-verify:

Verify the sign-in
==================

After you configured all pieces,
you can sign in to Univention Nubus for Kubernetes with credentials for user accounts from the source system.

In the browser, Keycloak redirects the end user to the login dialog of the source system.
The end users sign in one-time.
Further browser-based access to the same application then no longer requires an additional sign-in.
