Use Cases

Definitions

  • 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.

Primary Use Cases

  • Gerrit administrators can migrate between LDAP- and SAML identity providers and from LDAP-based accounts to accounts managed by Gerrit, regardless of handling of capitalization of usernames in the different systems.

Secondary Use Cases

  • Prohibit usernames only different in capitalization to make it easier for humans to unequivocally identify users by their username.

Acceptance Criteria

  • An administrator should be able to prohibit the creation of accounts with usernames that are only different in capitalization.
  • A tool that allows Gerrit administrators to identify existing duplicate accounts should be available. Already implemented in change 300308.
  • The process of dealing with duplicates by either deletion of the external IDs or changing of the username by the administrator should be properly documented and facilitated by Gerrit tools.
  • Gerrit should provide an option to allow clients to be able to login with a username using any capitalization they prefer, i.e. username matching during authentication should be case insensitive. It might be considered to be the default in the future.
  • Display names of accounts using the username as a default display name should use the username as presented during account creation, i.e. with the original capitalization. E.g. if JohnDoe is used during account registration this form should appear if mentioned in the UI, regardless of how the username is represented internally.
  • Existing accounts, except for duplicates, should not be disrupted by introducing this change.
  • Gerrit administrators should have a straightforward way of migrating to other identity providers without disrupting users, e.g. from LDAP to SAML or LDAP to Gerrit-serviceuser.

Background

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:

  • Internal technical users (created via REST API or the create-account SSH command or via the serviceuser-plugin)
  • Technical users managed by LDAP
  • Human users managed by LDAP

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
    • technical users (internal users and LDAP-managed technical users) are registered as service users
    • 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
    • technical users (internal users and LDAP-managed technical users) are registered as service users
    • 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
    • technical users (internal users and LDAP-managed technical users) are registered as service users
    • 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
    • technical users (internal users and LDAP-managed technical users) are registered as service users
    • 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.