7.4. SCIM Client#
Use the SCIM Client for a setup to provision user and user group information from Nubus for Kubernetes to an external target.
Important
The SCIM Client is experimental and intended for preliminary testing only. It isn’t yet recommended for production use.
This page describes how to deploy and configure the SCIM Client for Nubus for Kubernetes. The SCIM Client acts as a connector to provision users and user groups to a SCIM-compliant downstream application that’s external to Nubus for Kubernetes.
This page is for operators that want to integrate a downstream application with Nubus for Kubernetes through SCIM.
7.4.1. Installation#
This section describes how to install the SCIM Client through Helm.
7.4.1.1. Prerequisites#
Before you install the SCIM Client, you need to ensure the following prerequisites:
A Nubus for Kubernetes deployment. For installation, see Deployment.
A SCIM-compliant service provider, called the SCIM target on this page.
Connection details for the SCIM target, including endpoint URL and authentication credentials.
A separate PostgreSQL database for each SCIM Client and a dedicated database user with permission to create and modify its tables. See Database.
7.4.1.2. Installation through Helm#
To install the SCIM Client through Helm, use the commands in Listing 7.16. For the configuration of the SCIM Client, see Configuration.
You need to install the SCIM Client in the same namespace as Nubus for Kubernetes. The reason is that the SCIM Client needs internal access to the Provisioning API and the LDAP Server.
$ export NUBUS_NAMESPACE="<Your Nubus for Kubernetes namespace>"
$ helm install \
scim-client \
--namespace "$NUBUS_NAMESPACE" \
oci://artifacts.software-univention.de/nubus/charts/scim-client \
--values values.yaml
7.4.2. Configuration#
This section describes the configuration options for the SCIM Client.
To configure the SCIM Client,
you need to create a scim-client-values.yaml values file for the SCIM Client Helm Chart.
The Helm Chart comes with default values.
For a list of all possible values,
see the values.yaml file in the Helm Chart of the SCIM Client.
This section distinguishes between mandatory and optional values.
7.4.2.1. Mandatory values#
You must set the values in this section
in your scim-client-values.yaml values file.
Without these values, the SCIM Client doesn’t work as expected.
The SCIM Client always needs the following values:
scimServer.connection.url: The URL of the SCIM target.provisioningApi.auth.username: The username for the Provisioning API.provisioningApi.auth.password: The password for the Provisioning API.ldap.auth.bindDn: The bind DN for the LDAP Server.ldap.auth.existingSecret.name: The name of the existing secret for the LDAP Server.scimClient.config.dbConnectionString: The connection URL for the PostgreSQL database.
In addition, you must configure authentication for the SCIM target. The authentication method determines the required authentication values. For more information, see Authentication for the SCIM target.
Listing 7.17 shows a minimal configuration example with OIDC authentication.
scimClient:
config:
dbConnectionString: "postgresql+psycopg2://<DATABASE_USERNAME>:<PASSWORD>@<HOSTNAME>/<DATABASE_NAME>"
scimServer:
connection:
url: "https://scim.example.com/scim/v2/"
auth:
method: "oidc"
password: "your-client-secret"
oidc:
oidcTokenUrl: "https://auth.example.com/realms/nubus/protocol/openid-connect/token"
clientId: "scim-client"
provisioningApi:
auth:
username: "admin"
password: "your-provisioning-api-password"
ldap:
auth:
bindDn: "cn=admin,dc=swp-ldap,dc=internal"
existingSecret:
name: nubus-ldap-server-admin
7.4.2.2. Database#
The PostgreSQL database isn’t included in the Helm Chart. You are responsible for operating the database, including backups and upgrades. The SCIM Client creates its tables on startup.
- scimClient.config.dbConnectionString#
The SQLAlchemy connection URL for the PostgreSQL database. You must set this value in your
scim-client-values.yamlfile, as shown in Listing 7.17. The connection string uses the following pattern:postgresql+psycopg2://<DATABASE_USERNAME>:<PASSWORD>@<HOSTNAME>/<DATABASE_NAME>
Replace
<DATABASE_USERNAME>,<PASSWORD>,<HOSTNAME>, and<DATABASE_NAME>with the values for your database connection.Warning
Without the connection URL, a Helm installation or upgrade fails. The Helm Chart passes the value to the client through a Secret as
PROVISIONING_DB.
7.4.2.3. Authentication for the SCIM target#
The SCIM Client supports several authentication methods
for the SCIM target.
Set scimServer.auth.method
to one of the values in Table 7.1.
For all authentication methods except none,
the SCIM Client needs a secret value for authentication.
The required value scimServer.auth.password
can come either directly from the values file
or from an existing Kubernetes Secret configured with
scimServer.auth.existingSecret.name.
The value none sends no Authorization header.
Use this value only for testing, never in production.
Value |
Use case |
Required values |
|---|---|---|
|
Use OpenID Connect (OIDC) authentication. |
|
|
Use HTTP Basic authentication for SCIM targets that don’t support OIDC. |
|
|
Use static Bearer token authentication for SCIM targets that don’t support OIDC. |
|
|
Don’t send an |
No authentication values required. |
7.4.2.4. Optional values#
You can optionally override the following default values in your scim-client-values.yaml values file.
Listing 7.18 shows an example with all optional values.
scimClient.config.logLevelThe log level for the SCIM Client. The default value is
INFO.scimClient.config.prefillA boolean value to control if Nubus for Kubernetes shall provide existing user and user group data to the SCIM target through the provisioning subscription. The default value is
true.scimClient.config.groupSyncA boolean value to control if Nubus for Kubernetes shall synchronize user groups. The default value is
true.scimClient.config.externalIdUserMappingThe UDM attribute that UDM maps to the
externalIdfield of Users in SCIM. The default value isuniventionObjectIdentifier.scimClient.config.externalIdGroupMappingThe UDM attribute that UDM maps to the
externalIdfield of Groups in SCIM. The default value isuniventionObjectIdentifier.scimServer.auth.oidc.scopesOnly applies when
scimServer.auth.methodisoidc. A list of additional scopes to request when obtaining an OIDC access token for SCIM server authentication. The SCIM Client always automatically includes theopenidscope. Use this option if the downstream SCIM server requires specific scopes in the access token. The default value isnull, which means that the SCIM Client doesn’t use any additional scopes.
scimClient:
config:
logLevel: "DEBUG"
prefill: false
groupSync: false
externalIdUserMapping: "customUserId"
externalIdGroupMapping: "customGroupId"
scimServer:
auth:
oidc:
scopes:
- "additionalScope1"
- "additionalScope2"
Note
The default value for the mapping is univentionObjectIdentifier for both users and user groups.
If the SCIM target uses different attributes for user and user group IDs,
you need to adapt the values for
scimClient.config.externalIdUserMapping
and scimClient.config.externalIdGroupMapping.
7.4.3. Supported schemas#
The SCIM Client supports the following schemas for provisioning:
7.4.3.1. User schema#
The client supports the core User schema as defined in RFC 7643 and the following extensions:
urn:ietf:params:scim:schemas:core:2.0:Userurn:ietf:params:scim:schemas:extension:enterprise:2.0:Userurn:ietf:params:scim:schemas:extension:Univention:1.0:Userurn:ietf:params:scim:schemas:extension:DapUser:2.0:User
7.4.3.2. Group schema#
The client supports the core Group schema as defined in RFC 7643 and the following extensions:
urn:ietf:params:scim:schemas:core:2.0:Groupurn:ietf:params:scim:schemas:extension:Univention:1.0:Group
7.4.4. Provisioning subscription#
The SCIM Client is a consumer of the Provisioning Service in Nubus for Kubernetes. It requires a provisioning subscription to receive events about users and user groups. For each SCIM target, you need to configure a SCIM Client consumer by configuring a provisioning subscription for it.
To configure a provisioning subscription,
you need to register the consumer in the nubus-values.yaml values file of your Nubus for Kubernetes installation,
not the Helm Chart for the SCIM Client.
The separation ensures
that the subscription is idempotent
and that you can manage it as part of your Nubus for Kubernetes installation.
To add a subscription for the SCIM Client,
add the configuration in
Listing 7.19
to your nubus-values.yaml values file.
nubusProvisioning:
registerConsumers:
createUsers:
scimClient:
existingSecret:
name: scim-client-provisioning
keyMapping:
password: "registration"
7.4.5. Deployment#
You deploy the SCIM Client and Nubus for Kubernetes through independent Helm Charts.
After you have configured their respective values files—in the example on this page
the scim-client-values.yaml file and the nubus-values.yaml file—you
can deploy or upgrade the installations,
as shown in Listing 7.20.
Although you deploy the SCIM Client and Nubus for Kubernetes independently,
their configuration relates to each other.
For example, the provisioningApi and ldap sections in the SCIM Client's scim-client-values.yaml values file
must correctly point to Nubus for Kubernetes.
Likewise, the provisioning subscription in the Nubus nubus-values.yaml values file must match the SCIM
Client values.
$ export NUBUS_NAMESPACE="<Your Nubus for Kubernetes namespace>"
$ export RELEASE_NAME_FOR_NUBUS="<The release name of your Nubus installation>"
$ helm upgrade \
--install \
scim-client \
--namespace "$NUBUS_NAMESPACE" \
oci://artifacts.software-univention.de/nubus/charts/scim-client \
--values scim-client-values.yaml
$ helm upgrade \
--install \
"$RELEASE_NAME_FOR_NUBUS" \
--namespace "$NUBUS_NAMESPACE" \
oci://artifacts.software-univention.de/nubus/charts/nubus \
--values nubus-values.yaml
7.4.6. Troubleshooting#
Network errors leave the provisioning task pending and pause processing. The SCIM Client retries after 5 seconds, then 10 seconds, then 15 seconds, and so on, up to 20 minutes between attempts. For failures other than network errors, the client moves failed tasks and their errors to the morgue and continues processing. Unfinished tasks remain in the database, so processing continues after a restart, for example, following an update or a crash.
To troubleshoot, first check the container logs for warnings and errors,
as shown in Listing 7.21.
Replace <namespace> with your Nubus namespace
and <scim-client-pod> with the name of the SCIM Client pod.
$ kubectl logs -n <namespace> <scim-client-pod> -c main
7.4.6.1. Monitor the current state from the command line#
The SCIM Client includes a command-line interface to query and modify the database it uses to track provisioning:
tasks: Pending changes waiting to be synchronized.old: The state of an item at the moment it was successfully synchronized.morgue: Failed tasks and their errors. The client doesn’t actively process these tasks. You can examine them and decide how to proceed.
Run the tool inside the SCIM Client container,
where PROVISIONING_DB is already configured,
as shown in Listing 7.22.
$ kubectl exec -n <namespace> <scim-client-pod> -c main -- \
univention-scim-connector-task-management --help
Replace --help with one of the following actions.
Use <command> --help for its options.
OBJECT_ID:The UDM
univentionObjectIdentifier.TASK_ID:The numeric database ID shown by
search-tasks.
- show-item --obj-id OBJECT_ID#
Show an object’s entries in all three tables.
- summarize-tasks#
Summarize pending tasks.
- summarize-morgue#
Summarize failed tasks.
- search-tasks --first#
Show the first pending task. Omit
--firstto show all.
- search-old --obj-id OBJECT_ID#
Show the last successfully synchronized state.
- search-morgue#
Show failed tasks and tracebacks. Optionally filter with
--obj-id OBJECT_ID.
- retry-from-morgue --obj-id OBJECT_ID#
Copy matching failed changes back into the task queue.
- remove-from-morgue --obj-id OBJECT_ID#
Remove matching error entries, not objects in SCIM or UDM.
- move-task-to-morgue --task-id TASK_ID --error-msg "Manual investigation"#
Move a pending task aside for investigation.
7.4.6.2. Handling errors#
Listing 7.23 shows a stored failure caused by a username conflict. This example includes a shortened traceback. It’s the saved synchronization error, not a failure of the task-management command.
$ kubectl exec -n <namespace> <scim-client-pod> -c main -- \
univention-scim-connector-task-management search-morgue \
--obj-id 11111111-2222-4333-8444-555555555555
DN: uid=alice,cn=users,dc=example,dc=org
Object Identifier: 11111111-2222-4333-8444-555555555555
UDM module: users/user
ID (database): 1
Error occurred: 2026-09-09 10:15:00
Error: Traceback (most recent call last):
...
httpx.HTTPStatusError: Client error '400 Bad Request' for url 'https://scim.example.org/v2/Users'
...
Request argument "dn" Object exists: (uid): The username is already in use as username or as groupname: alice.
-
After you fix the cause, run the retry-from-morgue action for the object.
The action queues a retry that uses the item’s stored attributes,
not fresh LDAP data.
Check that retrying with these attributes doesn’t overwrite a more recent state.
Adding tasks to the queue keeps the morgue entries.
After a successful create or update,
the client removes all morgue entries for that object.
The client processes queued retries when it receives the next message,
starts, or reaches an active network-retry iteration.
To process them without waiting for a new message, restart an idle client.
Alternatively, use the remove-from-morgue action
to discard error entries you no longer need.
The client still processes later UDM changes to the object normally.
To check a retry, run show-item --obj-id OBJECT_ID.
After a successful create or update,
the output shows Synced as, Currently no pending tasks, and Currently no errors,
as in Listing 7.24.
$ kubectl exec -n <namespace> <scim-client-pod> -c main -- \
univention-scim-connector-task-management show-item \
--obj-id 11111111-2222-4333-8444-555555555555
Searching for 11111111-2222-4333-8444-555555555555
Synced as uid=alice,cn=users,dc=example,dc=org (11111111-2222-4333-8444-555555555555; users/user; old:1)
Currently no pending tasks
Currently no errors
Synced as alone describes the last successful synchronization.
Recent pending tasks or error entries may still exist for the same object.
Use search-old --obj-id OBJECT_ID
to verify that the stored attributes match the expected synchronized state.
Use the move-task-to-morgue action
to move a pending task to the morgue for manual investigation.
If the client has already sent a request to the SCIM target,
moving the task doesn’t cancel that request.
If the client is waiting before retrying,
it checks the task queue again only after that wait ends.
7.4.6.3. Information for support#
Before contacting support, collect the client version,
relevant logs and tracebacks,
the affected object’s show-item output,
and reproduction steps with the expected behavior.
Redact credentials and sensitive data before sharing.
7.4.7. Limitations#
Important
The SCIM Client is experimental and intended for preliminary testing only. It isn’t yet recommended for production use.
This section outlines the current limitations and considerations when using the SCIM Client.
7.4.7.1. Data synchronization#
Limitations on how the SCIM Client synchronizes user and user group data to the SCIM target.
- Group membership sync
The SCIM Client synchronizes the list of direct members of a
Group, but not the list of groups that include aUser.The SCIM Client lists only
Userobjects as members ofGroupobjects. It doesn’t synchronize other memberGroupobjects, such as nested groups.
7.4.7.2. Configuration#
Limitations on the configuration of the SCIM Client.
- Attribute mapping
Limited configuration for attribute mapping between UDM and SCIM schemas.
You can only customize the
externalIdfield mapping through theexternalIdUserMappingandexternalIdGroupMappingconfiguration options.Fixed attribute mapping for other SCIM fields, not customizable through configuration.
7.4.8. Reference values#
This section provides a reference for the Helm Chart values of the SCIM Client.
- Name:
scim-client- Version:
0.49.0- Description:
A Helm chart for the Nubus SCIM client
You find the configuration options for scim-client in the following sections.
7.4.8.1. additionalAnnotations#
- scim-client:additionalAnnotations#
Note
scim-clientis a prefix to avoid name clashes for documentation cross-references. In yourvalues.yamlfile, use the keyadditionalAnnotations.Additional custom annotations to add to all deployed objects.
Default value:
{}
7.4.8.2. additionalLabels#
- scim-client:additionalLabels#
Note
scim-clientis a prefix to avoid name clashes for documentation cross-references. In yourvalues.yamlfile, use the keyadditionalLabels.Additional custom labels to add to all deployed objects.
Default value:
{}
7.4.8.3. containerSecurityContext#
- containerSecurityContext.allowPrivilegeEscalation#
Enable container privileged escalation.
Default value:
false
- containerSecurityContext.capabilities.drop#
Default value:
["ALL"]
- containerSecurityContext.enabled#
Enable security context.
Default value:
true
- containerSecurityContext.privileged#
Default value:
false
- containerSecurityContext.readOnlyRootFilesystem#
Mounts the container’s root file system as read-only.
Default value:
true
- containerSecurityContext.runAsGroup#
Process group id.
Default value:
1000
- containerSecurityContext.runAsNonRoot#
Run container as a user.
Default value:
true
- containerSecurityContext.runAsUser#
Process user id.
Default value:
1000
- containerSecurityContext.seccompProfile.type#
Disallow custom Seccomp profile by setting it to RuntimeDefault.
Default value:
"RuntimeDefault"
7.4.8.4. extraEnvVars#
- extraEnvVars#
Array with extra environment variables to add to containers. # extraEnvVars: - name: FOO value: “bar”
Default value:
[]
7.4.8.5. extraVolumeMounts#
- extraVolumeMounts#
Optionally specify an extra list of additional volumeMounts.
Default value:
[]
7.4.8.6. extraVolumes#
- extraVolumes#
Optionally specify an extra list of additional volumes.
Default value:
[]
7.4.8.7. global#
- global.imagePullPolicy#
Define an ImagePullPolicy. # Ref.: https://kubernetes.io/docs/concepts/containers/images/#image-pull-policy #
Default value:
null
- global.imagePullSecrets#
Credentials to fetch images from private registry. Ref: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/ # imagePullSecrets: - “docker-registry”
Default value:
[]
- global.imageRegistry#
Container registry address.
Default value:
"artifacts.software-univention.de"
- scim-client:global.secrets.masterPassword#
Note
scim-clientis a prefix to avoid name clashes for documentation cross-references. In yourvalues.yamlfile, use the keyglobal.secrets.masterPassword.Default value:
null
7.4.8.8. ldap#
- ldap.auth.bindDn#
Bind distinguished name to authenticate with the LDAP Server.
Default value:
null
- ldap.auth.existingSecret.keyMapping.password#
The key to retrieve the password from. Setting this value allows to use a key with a different name.
Default value:
null
- ldap.auth.existingSecret.name#
The name of an existing Secret to use for retrieving the password to authenticate with the source LDAP directory. # “udm.auth.password” will be ignored if this value is set.
Default value:
null
- ldap.auth.password#
The password used to authenticate with the LDAP Server. Either this value or an existing Secret has to be specified.
Default value:
null
- ldap.connection.host#
LDAP Server hostname (e.g. “nubus-ldap-server”)
Default value:
null
7.4.8.9. podSecurityContext#
- podSecurityContext.enabled#
Enable security context.
Default value:
true
- podSecurityContext.fsGroup#
If specified, all processes of the container are also part of the supplementary group.
Default value:
1000
- podSecurityContext.fsGroupChangePolicy#
Change ownership and permission of the volume before being exposed inside a Pod.
Default value:
"Always"
- podSecurityContext.sysctls#
Allow binding to ports below 1024 without root access.
Default value:
[{"name": "net.ipv4.ip_unprivileged_port_start", "value": "1"}]
7.4.8.10. probes#
- probes.liveness.enabled#
Enable liveness probe
Default value:
true
- probes.liveness.exec.command#
Default value:
["/bin/sh", "-c", "pgrep -f scim-client"]
- probes.liveness.initialDelaySeconds#
Default value:
30
- probes.liveness.periodSeconds#
Default value:
10
- probes.readiness.enabled#
Enable readiness probe
Default value:
true
- probes.readiness.exec.command#
Default value:
["/bin/sh", "-c", "pgrep -f scim-client"]
- probes.readiness.initialDelaySeconds#
Default value:
5
- probes.readiness.periodSeconds#
Default value:
5
7.4.8.11. provisioningApi#
- provisioningApi.auth.existingSecret.keyMapping.password#
The key to retrieve the password from. Setting this value allows to use a key with a different name.
Default value:
null
- provisioningApi.auth.existingSecret.name#
The name of an existing Secret to use for retrieving the password to authenticate with the Provisioning API. # “provisioningApi.auth.password” will be ignored if this value is set.
Default value:
null
- provisioningApi.auth.password#
The password used to authenticate with the Provisioning API. Either this value or an existing Secret has to be specified.
Default value:
null
- provisioningApi.auth.username#
Username of the nubus provisioning subscription / this client For a given nubus deployment, all provisioning subscription names must be unique.
Default value:
null
- provisioningApi.config.maxAcknowledgementRetries#
The maximum number of retries for acknowledging a message
Default value:
3
- provisioningApi.connection.url#
The base URL the provisioning API is reachable at. (e.g. “http://provisioning-api”)
Default value:
null
7.4.8.12. resources#
- resources.limits.cpu#
Default value:
"4"
- resources.limits.memory#
Default value:
"4Gi"
- resources.requests.cpu#
Default value:
"250m"
- resources.requests.memory#
Default value:
"512Mi"
7.4.8.13. scimClient#
- scimClient.config.externalIdGroupMapping#
Define external_id UDM attribute for groups
Default value:
"univentionObjectIdentifier"
- scimClient.config.externalIdUserMapping#
Define external_id UDM attribute for users
Default value:
"univentionObjectIdentifier"
- scimClient.config.groupSync#
Default value:
true
- scimClient.config.logLevel#
The log level for the SCIM client. valid values are: ERROR WARNING, INFO, DEBUG
Default value:
"INFO"
- scimClient.config.prefill#
Toggle prefill for the provisioning subscription If activated, the client will receive a synthetic “create” event for all existing objects in the Domain before receiving live events.
Default value:
true
- scimClient.extraEnvVars#
Array with extra environment variables to add to containers. # extraEnvVars: - name: FOO value: “bar”
Default value:
[]
- scimClient.image.pullPolicy#
Default value:
""
- scimClient.image.registry#
Default value:
""
- scimClient.image.repository#
Default value:
"nubus/images/scim-client"
- scimClient.image.sha256#
Define image sha256 as an alternative to tag
Default value:
null
- scimClient.image.tag#
Default value:
"0.49.0@sha256:ac8ef92764b092bd5af45f086e896d62a170193efbe79fc704a59a3bcde1be9e"
7.4.8.14. scimServer#
- scimServer.auth.basic.username#
The username used to authenticate with the SCIM Server via HTTP Basic Auth. Only used when “scimServer.auth.method” is “basic”.
Default value:
null
- scimServer.auth.existingSecret.keyMapping.password#
The key to retrieve the password from. Setting this value allows to use a key with a different name.
Default value:
null
- scimServer.auth.existingSecret.name#
The name of an existing Secret to use for retrieving the password to authenticate with the SCIM Server. # “scimServer.auth.password” will be ignored if this value is set.
Default value:
null
- scimServer.auth.method#
Authentication method to use against the downstream SCIM server. One of: “none”, “oidc”, “basic”, “bearer”.
Default value:
null
- scimServer.auth.oidc.clientId#
Service account client ID (username). Only used when “scimServer.auth.method” is “oidc”.
Default value:
null
- scimServer.auth.oidc.oidcTokenUrl#
URL to obtain an OIDC access token from the Identity Provider using the client-credentials-flow. Only used when “scimServer.auth.method” is “oidc”.
Default value:
null
- scimServer.auth.oidc.scopes#
List of additional scopes to send when requesting an OIDC authentication token. The scope openid will always be added even if the value is null. Only used when “scimServer.auth.method” is “oidc”.
Default value:
null
- scimServer.auth.password#
The secret used to authenticate with the SCIM Server: the OIDC client secret when method is “oidc”, the password when method is “basic”, or the static token when method is “bearer”. Not used when method is “none”. Either this value or an existing Secret has to be specified.
Default value:
null
- scimServer.connection.url#
The base URL the SCIM server is reachable at. (e.g. “http://scim-server”)
Default value:
null
7.4.8.15. serviceAccount#
- serviceAccount.annotations#
Annotations to add to the service account
Default value:
{}
- serviceAccount.automountServiceAccountToken#
#@param serviceAccount.automountServiceAccountToken Allows auto mount of ServiceAccountToken on the serviceAccount created #Can be set to false if pods using this serviceAccount do not need to use K8s API ##
Default value:
false
- serviceAccount.create#
Specifies whether a service account should be created
Default value:
true
- serviceAccount.labels#
Additional custom labels for the ServiceAccount.
Default value:
{}
- serviceAccount.name#
The name of the service account to use. If not set and create is true, a name is generated using the full name template
Default value:
""
7.4.8.16. tolerations#
- tolerations#
Default value:
[]