duplicate usernames/accounts: Usernames or accounts having usernames that are only different in their capitalization. E.g.: johndoe
and JohnDoe
. While no true duplicates, they will be referred to as duplicates for readability.
external IDs: Gerrit uses (generic) user names in different externalId schemes which are used for different authentication systems.
Currently the following externalId schemes exist (defined in ExternalId.java):
gerrit
(LDAP)username
(authentication REST and git endpoints)external
(external authentication e.g. oauth, saml)gpgkey
(gpg keys)mailto
(email addresses)uuid
(randomly created identities constructed by a UUID)http
(used by OpenID)https
(used by OpenID)xri
(used by OpenID)The schemes relevant for authentication are: gerrit
, username
.
JohnDoe
is used during account registration this form should appear if mentioned in the UI, regardless of how the username is represented internally.Gerrit by default treats usernames case sensitive, i.e. there can be the usernames johndoe
and JohnDoe
identifying different accounts. There are currently options in Gerrit‘s configuration influencing that aim to achieve case insensitivity by storing and matching usernames in all lowercase, regardless of the capitalization used by the client. However, these options don’t allow to handle accounts with mixed- or uppercase usernames created before being set and currently do not handle all ways to create accounts in Gerrit. Gerrit provides a tool to convert usernames stored in the gerrit
external ID to all lowercase to solve part of the issue. However, this misses accounts created in Gerrit itself, which use the username
external ID. The username
external ID cannot be converted to all lowercase, since this would break the sandbox branches feature, which uses the username in the branch name (e.g. refs/heads/sandbox/${username}/*
).
The existing behavior can lead to issues, when trying to migrate to a different identity provider. The scenario encountered by SAP can be taken as an example: The identity provider is supposed to be switched from LDAP to SAML. This has to happen with minimal disruption for the users, i.e. the username should not change. The Gerrit instance has three types of users:
create-account
SSH command or via the serviceuser-plugin)Usernames of accounts managed by LDAP are stored in all lowercase (ldap.localUsernameToLowerCase = true
). Other account types are allowed to use uppercase letters in the username stored in NoteDB. Some usernames are duplicates. The new identity provider does not allow technical users, thus technical users managed by LDAP were registered as service users, so that they can be used as internal accounts managed by the serviceuser plugin.
The saml-plugin uses the auth.userNameToLowerCase
-option to convert the username used to login to lowercase. This setting blocks all internal technical users and service users with uppercase letters in the username, e.g. the service user JenkinsBuild
will not be able to authenticate, since during authentication the username is converted to jenkinsbuild
, which is not present in NoteDB, where the external ID username:JenkinsBuild
is present. This can be fixed by adding an option complimentary to ldap.localUsernameToLowerCase
to the saml- plugin. However, with such an option the newly registered service users (former LDAP-based technical users) would not able to log in, if the usernames have uppercase letters, since this does not match the username in NoteDB that is all lowercase.
To illustrate, a list of example scenarios follows:
LDAP scenario (current state)
ldap.localUsernameToLowerCase = true
auth.userNameToLowerCase = false
user type | username used by user | username in NoteDB | username used in DB lookup | login successful |
---|---|---|---|---|
LDAP (human) | johndoe | johndoe | johndoe | true |
LDAP (human) | JohnDoe | johndoe | johndoe | true |
LDAP (technical) | johndoe | johndoe | johndoe | true |
LDAP (technical) | JohnDoe | johndoe | johndoe | true |
internal user/service user | johndoe | johndoe | johndoe | true |
internal user/service user | JohnDoe | JohnDoe | JohnDoe | true |
SAML scenario 1
auth.userNameToLowerCase = false
user type | username used by user | username in NoteDB | username used in DB lookup | login successful |
---|---|---|---|---|
SAML (human) | johndoe | johndoe | johndoe | true |
SAML (human) | JohnDoe | johndoe | JohnDoe | false |
formerly LDAP (technical) | johndoe | johndoe | johndoe | true |
formerly LDAP (technical) | JohnDoe | johndoe | JohnDoe | false |
internal user/service user | johndoe | johndoe | johndoe | true |
internal user/service user | JohnDoe | JohnDoe | JohnDoe | true |
SAML scenario 2
auth.userNameToLowerCase = true
user type | username used by user | username in NoteDB | username used in DB lookup | login successful |
---|---|---|---|---|
SAML (human) | johndoe | johndoe | johndoe | true |
SAML (human) | JohnDoe | johndoe | johndoe | true |
formerly LDAP (technical) | johndoe | johndoe | johndoe | true |
formerly LDAP (technical) | JohnDoe | johndoe | johndoe | true |
internal user/service user | johndoe | johndoe | johndoe | true |
internal user/service user | JohnDoe | JohnDoe | johndoe | false |
SAML scenario 3
auth.userNameToLowerCase = true
saml.localUsernameToLowerCase = true
(not yet implemented)user type | username used by user | username in NoteDB | username used in DB lookup | login successful |
---|---|---|---|---|
SAML (human) | johndoe | johndoe | johndoe | true |
SAML (human) | JohnDoe | johndoe | johndoe | true |
formerly LDAP (technical) | johndoe | johndoe | johndoe | true |
formerly LDAP (technical) | JohnDoe | johndoe | johndoe | true |
internal user/service user | johndoe | johndoe | johndoe | true |
internal user/service user | JohnDoe | JohnDoe | johndoe | false |
SAML scenario 4
auth.userNameToLowerCase = false
saml.localUsernameToLowerCase = true
(not yet implemented)user type | username used by user | username in NoteDB | username used in DB lookup | login successful |
---|---|---|---|---|
SAML (human) | johndoe | johndoe | johndoe | true |
SAML (human) | JohnDoe | johndoe | johndoe | true |
formerly LDAP (technical) | johndoe | johndoe | johndoe | true |
formerly LDAP (technical) | JohnDoe | johndoe | JohnDoe | false |
internal user/service user | johndoe | johndoe | johndoe | true |
internal user/service user | JohnDoe | JohnDoe | johndoe | true |
While this example uses non-core plugins and is very specific, it shows that having different accounts with usernames only different in capitalization can lead to hard to resolve issues or disruption of users. Further, there is likely no good use case to support case sensitive usernames. Usernames only different in capitalization might rather lead to confusion in identifying a user. Thus, account data could be made easier to manage by matching accounts case insensitive during authentication.