CRITICAL: Keycloak Bootstrap Failure During Nubus 1.9.x Upgrade Leads to Authentication System Instability Bug Report Severity: Critical Reported By: User Date Reported: 2025-07-10 Product/Module: openDesk / UMS Keycloak Bootstrap Version Affected: openDesk 1.5.0 (Nubus 1.9.x) when upgrading from openDesk 1.4.x 1. Description During the upgrade of openDesk from version 1.4.x to 1.5.0 (Nubus 1.9.x), the UMS Keycloak bootstrap process fails. This issue was observed in two production instances, despite not occurring during pre-production upgrade tests. The failure prevents the correct setup of Keycloak, specifically impacting the activation of Two-Factor Authentication (2FA). The bootstrap job eventually needs to be triggered again, but it consistently fails due to an existing configuration. 2. Steps to Reproduce Initiate an upgrade of openDesk from version 1.4.x to 1.5.0 (Nubus 1.9.x). Allow the UMS Keycloak bootstrap job to run as part of the upgrade process. Observe the execution of the Ansible playbook for Keycloak Bootstrap. 3. Expected Behavior The UMS Keycloak bootstrap process should complete successfully and idempotently, configuring Keycloak without errors, even if re-run or if certain configurations already exist. The 2FA setup should be enabled without conflict. 4. Actual Behavior The UMS Keycloak bootstrap job fails during the "Enable Two-Factor-Authentication" task. The Ansible output shows a fatal error with a non-zero return code (1). The underlying error message from Keycloak is a 409 Conflict, stating: "Authentication execution configuration 2fa-role-mapping already exists". This prevents the successful completion of the bootstrap and requires manual intervention. 5. Logs/Error Messages TASK [Enable Two-Factor-Authentication] **************************************** fatal: [localhost]: FAILED! => {"changed": false, "cmd": "univention-keycloak --keycloak-url http://ums-keycloak:8080 --realm opendesk --binduser kcadmin --bindpwdfile /credentials/keycloak.secret 2fa enable --group-2fa=\"2fa-users\" --ldap-base=\"dc=swp-ldap,dc=internal\"\n", "delta": "0:00:02.067930", "end": "2025-07-08 05:05:24.087799", "msg": "non-zero return code", "rc": 1, "start": "2025-07-08 05:05:22.019869", "stderr": "Traceback (most recent call last):\n File \"/usr/sbin/univention-keycloak\", line 3436, in <module>\n sys.exit(main())\n ^^^^^^\n File \"/usr/sbin/univention-keycloak\", line 3432, in main\n return opt.func(opt) or 0\n ^^^^^^^^^^^^^\n File \"/usr/sbin/univention-keycloak\", line 2715, in enable_2fa\n create_conditional_2fa_flow(kc_admin, opt.realm, realm_2fa_role, flow_name)\n File \"/usr/sbin/univention-keycloak\", line 2979, in create_conditional_2fa_flow\n create_config_for_execution(kc_admin, config, condition_user_role_id)\n File \"/usr/sbin/univention-keycloak\", line 3009, in create_config_for_execution\n return raise_error_from_response(data_raw, KeycloakGetError, expected_codes=[204, 201])\n ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n File \"/usr/lib/python3/dist-packages/keycloak/exceptions.py\", line 192, in raise_error_from_response\n raise error(\nkeycloak.exceptions.KeycloakGetError: 409: b'{\"errorMessage\":\"Authentication execution configuration 2fa-role-mapping already exists\"}'", "stderr_lines": ["Traceback (most recent call last):", " File \"/usr/sbin/univention-keycloak\", line 3436, in <module>", " sys.exit(main())", " ^^^^^^", " File \"/usr/sbin/univention-keycloak\", line 3432, in main", " return opt.func(opt) or 0", " ^^^^^^^^^^^^^", " File \"/usr/sbin/univention-keycloak\", line 2715, in enable_2fa", " create_conditional_2fa_flow(kc_admin, opt.realm, realm_2fa_role, flow_name)", " File \"/usr/sbin/univention-keycloak\", line 2979, in create_conditional_2fa_flow", " create_config_for_execution(kc_admin, config, condition_user_role_id)", " File \"/usr/sbin/univention-keycloak\", line 3009, in create_config_for_execution", " return raise_error_from_response(data_raw, KeycloakGetError, expected_codes=[204, 201])", " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^", " File \"/usr/lib/python3/dist-packages/keycloak/exceptions.py\", line 192, in raise_error_from_response", " raise error(", "keycloak.exceptions.KeycloakGetError: 409: b'{\"errorMessage\":\"Authentication execution configuration 2fa-role-mapping already exists\"}'"], "stdout": "Enabling 2FA ...\nUsing KC_URL: http://ums-keycloak:8080\nGroup already exists\nGroup already exists", "stdout_lines": ["Enabling 2FA ...", "Using KC_URL: http://ums-keycloak:8080", "Group already exists", "Group already exists"]}
It was determined that this behavior is triggered by a stale 2FA flow in the Keycloak realm (the bootstrap script does not automatically overwrite existing flows). To get unstuck: 1. Log into the Keycloak Admin Console for your `opendesk` realm. 2. Go to the Authentication Flows and search on **every** login flow for one an execution with the name 2fa-role-mapping -> delete that flow. This error only appears when the environment contains additional login flows with the same name as ours. Automatically deleting customer-created flows does not feel right, either.