|
| 1 | +--- |
| 2 | +date: 2025-02-10T17:06:39+01:00 |
| 3 | +title: "Duplicate users in the Grafana database" |
| 4 | +linkTitle: "duplicate-grafana-users" |
| 5 | +author: Gerhard Lausser |
| 6 | +tags: |
| 7 | + - grafana |
| 8 | +--- |
| 9 | +This issue occurred on an OMD 5.40 system running Grafana 10.4.2. A customer reported that embedded Grafana panels in the Service Detail View of Thruk were not working. Instead of a graph, they were presented with the Grafana login page. |
| 10 | + |
| 11 | +In the *~/var/log/grafana/grafana.log*, the following messages appeared: |
| 12 | + |
| 13 | +``` |
| 14 | +logger=user.sync t=2025-02-06T15:38:43.735173011+01:00 level=error msg="Failed to fetch user" error="Found a conflict in user login information. 3 users already exist with either the same login or email: [Sepp (email:Sepp, id:124), SEPP (email:SEPP, id:152), sepp (email:sepp, id:182)]." auth_module=authproxy auth_id=SEPP |
| 15 | +logger=authn.service t=2025-02-06T15:38:43.735241811+01:00 level=error msg="Failed to run post auth hook" client=auth.client.proxy id= error="[user.sync.internal] unable to retrieve user" |
| 16 | +``` |
| 17 | + |
| 18 | +From the Thruk logs, we determined that users were logging in using different variations of their usernames - sometimes in lowercase, sometimes in uppercase, and occasionally mixed case. This was possible because Apache authenticated users via an LDAP backend that was case-insensitive. |
| 19 | + |
| 20 | +However, starting with Grafana 9.3, the software no longer treated differently cased usernames as the same user. (This issue had gone unnoticed for some time and was likely introduced with an OMD update.) |
| 21 | + |
| 22 | +### Enforcing Lowercase Usernames in Thruk |
| 23 | + |
| 24 | +To address this, we enforced lowercase usernames in Thruk by setting: |
| 25 | + |
| 26 | +``` |
| 27 | +make_auth_user_lowercase = 1 |
| 28 | +``` |
| 29 | +_File: `~/etc/thruk/thruk_local.d/users_lowercase.conf`_ |
| 30 | + |
| 31 | +After restarting Thruk (`omd restart thruk`), all usernames were internally converted to lowercase, regardless of how users entered them. |
| 32 | +> **Note:** Login to an OMD monitoring system is done through a Thruk login page. If authentication is successful, the username (now converted to lowercase) is passed to Grafana via the HTTP header `X-WEBAUTH-USER`, and the user is even created in Grafana on the fly. |
| 33 | +
|
| 34 | + |
| 35 | +### Cleaning Up Conflicting Users in Grafana |
| 36 | + |
| 37 | +Next, we needed to sanitize the Grafana database by removing redundant user entries that contained uppercase letters. We followed the workflow documented [here](https://grafana.com/blog/2022/12/12/guide-to-using-the-new-grafana-cli-user-identity-conflict-tool-in-grafana-9.3/). |
| 38 | + |
| 39 | +First, we listed all conflicting user accounts: |
| 40 | + |
| 41 | +```bash |
| 42 | +OMD[site1@tmonmuc]:~$ grafana cli \ |
| 43 | + --config=/omd/sites/site1/etc/grafana/grafana.ini \ |
| 44 | + --homepath=$HOME/share/grafana \ |
| 45 | + admin user-manager conflicts list |
| 46 | +``` |
| 47 | + |
| 48 | +This displayed all users with login conflicts. *SEPP/Sepp/sepp* was one of them. The next step was to generate a conflict resolution file: |
| 49 | + |
| 50 | +```bash |
| 51 | +OMD[site1@tmonmuc]:~$ grafana cli \ |
| 52 | + --config=/omd/sites/site1/etc/grafana/grafana.ini \ |
| 53 | + --homepath=$HOME/share/grafana \ |
| 54 | + admin user-manager conflicts generate-file |
| 55 | +``` |
| 56 | + |
| 57 | +The generated file appeared as: |
| 58 | + |
| 59 | +``` |
| 60 | +/tmp/conflicting_user_1310352894.diff |
| 61 | +``` |
| 62 | + |
| 63 | +This file contained user conflicts in the following format: |
| 64 | + |
| 65 | +``` |
| 66 | +conflict: sepp |
| 67 | +- id: 124, email: Sepp, login: Sepp, last_seen_at: 2024-11-15T11:15:42Z, auth_module: authproxy, conflict_email: true, conflict_login: true |
| 68 | ++ id: 152, email: SEPP, login: SEPP, last_seen_at: 2024-10-22T05:43:19Z, auth_module: authproxy, conflict_email: true, conflict_login: true |
| 69 | +- id: 182, email: sepp, login: sepp, last_seen_at: 2024-10-22T05:43:19Z, auth_module: authproxy, conflict_email: true, conflict_login: true |
| 70 | +``` |
| 71 | + |
| 72 | +We needed to edit this file so that each *conflict:* block contained exactly one line with a plus sign (`+`) for the user we wanted to keep (in our case, the lowercase entry with ID 182). The other entries were marked with a minus sign (`-`) to be deleted. |
| 73 | + |
| 74 | +Before applying changes, we validated the file: |
| 75 | + |
| 76 | +```bash |
| 77 | +OMD[site1@tmonmuc]:~$ grafana cli \ |
| 78 | + --config=/omd/sites/site1/etc/grafana/grafana.ini \ |
| 79 | + --homepath=$HOME/share/grafana \ |
| 80 | + admin user-manager conflicts validate-file \ |
| 81 | + /tmp/conflicting_user_1310352894.diff |
| 82 | +``` |
| 83 | + |
| 84 | +No errors were found, so we proceeded with the `ingest-file` command: |
| 85 | + |
| 86 | +```bash |
| 87 | +OMD[site1@tmonmuc]:~$ grafana cli \ |
| 88 | + --config=/omd/sites/site1/etc/grafana/grafana.ini \ |
| 89 | + --homepath=$HOME/share/grafana \ |
| 90 | + admin user-manager conflicts ingest-file \ |
| 91 | + /tmp/conflicting_user_1310352894.diff |
| 92 | +``` |
| 93 | + |
| 94 | +### Unexpected Error and Solution |
| 95 | + |
| 96 | +However, after confirming *Proceed with operation?* with *Y*, we encountered an error: |
| 97 | + |
| 98 | +``` |
| 99 | +Error: ✗ not able to merge with &{%!e(string=could not find intoUser: Found conflict in user login information. 3 users already exist with either the same login or email: [Sepp (email:Sepp, id:124), SEPP (email:SEPP, id:152), sepp (email:sepp, id:182)]}) |
| 100 | +``` |
| 101 | + |
| 102 | +This indicated that Grafana still treated `sepp`, `Sepp`, and `SEPP` as the same user, likely due to internal case-insensitive handling. |
| 103 | + |
| 104 | +To resolve this, we explicitly configured Grafana to respect case differences by adding the following line to *grafana.ini*: |
| 105 | + |
| 106 | +```ini |
| 107 | +[users] |
| 108 | +case_insensitive_login = false # Temporarily enforce case sensitivity |
| 109 | +allow_sign_up = false |
| 110 | +default_theme = light |
| 111 | +``` |
| 112 | +_File: `~/etc/grafana/grafana.ini`_ |
| 113 | + |
| 114 | +With this setting in place, we successfully ingested the conflict resolution file: |
| 115 | + |
| 116 | +```bash |
| 117 | +OMD[site1@tmonmuc]:~$ grafana cli \ |
| 118 | + --config=/omd/sites/site1/etc/grafana/grafana.ini \ |
| 119 | + --homepath=$HOME/share/grafana \ |
| 120 | + admin user-manager conflicts ingest-file \ |
| 121 | + /tmp/conflicting_user_1310352894.diff |
| 122 | +... |
| 123 | +conflicts resolved. |
| 124 | +``` |
| 125 | +After the `ingest-file` command ran successfully, we removed the `case_insensitive_login = false` line from `grafana.ini` to restore the original setting. |
| 126 | + |
| 127 | + |
| 128 | +### Conclusion |
| 129 | + |
| 130 | +By enforcing lowercase usernames in Thruk and making Grafana temporarily case-sensitive, we successfully eliminated duplicate user entries and restored embedded panel functionality. This issue highlights the importance of consistent username handling across authentication layers to avoid unexpected conflicts. |
| 131 | + |
| 132 | + |
0 commit comments