blob: 2d0c5196efe44a5b2dc72ee25f17c063e7470e25 [file] [view]
---
title: "Design Doc - Case Insensitive Username Matching - Solution"
permalink: design-docs/case-insensitive-username-matching-solution.html
hide_sidebar: true
hide_navtoggle: true
toc: false
---
# Solution - Case Insensitive Username Matching
## <a id="overview"> Overview
* When case insensitive username matching is configured, the username is case
insensitively matched with the username/external ID stored in NoteDB, e.g.
`johndoe`, `JohnDoe` and `JOHNDOE` can all be used to authenticate against the
same account.
* Creation of accounts with usernames only different in capitalization is
prohibited by checking for existing usernames case insensitively, if case
insensitive username matching is configured. This can also be configured
separately.
* A migration path is provided, including tooling and documentation for how
to deal with duplicate usernames.
* Necessary changes in NoteDB are not done as a schema migration but using
a separate tool packaged in the gerrit.war.
* Next to using an offline tool the migration of NoteDB a way to migrate the data
online may be provided in the future.
* Usernames are stored preserving the original case.
## <a id="detailed-design"> Detailed Design
* Add a configuration option to enable case insensitive username handling.
* Make case insensitive username handling the default for new Gerrit sites, but
keep current case sensitive username handling on existing sites.
* A tool to detect accounts that are only different in capitalization from NoteDB
data. Already implemented in [change 300308](https://gerrit-review.googlesource.com/c/gerrit/+/300308)
* Add tooling that allows to change the username/external IDs as a way to deal
with accounts having usernames only different in capitalization.
* Document how such accounts can be dealt with without causing issues due
to missing data, by using existing REST API endpoints to either delete the
account's external IDs or by setting a different username.
This documentation should explain that a complete deletion of accounts is not
possible, since the data is referenced in other places of the NoteDB.
* Transform external IDs containing the username (`gerrit:JohnDoe`,
`username:JohnDoe`) to lowercase before computing the SHA1-sum used for
storage in NoteDB.
* During the upgrade the External ID data in NoteDB has to be migrated to fit the
new scheme that uses SHA1 sums of all lowercase external IDs. A warning should
be emitted for existing duplicate accounts. These accounts will not be usable
after migration.
* If case insensitive username matching is configured, creation of accounts with
usernames only different in capitalization is prohibited.
### <a id="scalability"> Scalability
During runtime no impact is to be expected, since transforming the external ID to
all lowercase should add negligible computation cost during externalId matching.
The migration of account data including reindexing of accounts took 9:57 min for
298609 accounts on a MacBook. Reindexing of accounts takes the majority of the
time. If additional speedup is required, multithreading might be tested. Online
migration would be preferable and might be added at a later point in time.
## <a id="alternatives-considered"> Alternatives Considered
* A [change](https://gerrit-review.googlesource.com/c/gerrit/+/300314) proposing
to use the AccountResolver to case insensitively lookup accounts was discussed,
but dismissed for the following reasons (Thanks to Edwin and Luca for the review):
* it is searching over a number of account fields, e.g. it would also find
accounts that contain username as part of their full name
* it filters out inactive and non-visible accounts
* it may use the account index, that may contain stale entries
* An additional consideration is to make case insensitive usernames mandatory.
In this case the general approach will stay the same, in that the SHA-1 sums
used as note IDs will be computed from the all lowercase external ID. However,
the migration will be added as a schema migration and thus be mandatory. The
advantage would be that the code change is a lot smaller, since the creation
of External IDs is not dependent on any configuration. However, Gerrit
administrators would still have to manually take care of accounts with usernames
only different in their capitalization, which might be quite some work. Also
this approach would require an identity provider that is als ocase insensitive
in handling usernames. This might not be the case for all Gerrit users.
## <a id="pros-and-cons"> Pros and Cons
* Existing accounts that are only different in capitalization will have to have
their externalIds deleted or renamed manually, which will disrupt clients using
these accounts and potentially create quite some work for Gerrit administrators
to decide which of the accounts to keep.
## <a id="implementation-plan"> Implementation Plan
1) Tooling and documentation of how to remove or rename external IDs of duplicate
accounts should be provided.
2) Provide migration path to the new case-insensitive way to compute SHA1 hashes
used for external IDs
3) Change the creation of new external IDs containing usernames to use all
lowercase IDs for SHA1 computation. This can be done in
[`ExternalId.Key.sha1()`](https://gerrit.googlesource.com/gerrit/+/refs/heads/master/java/com/google/gerrit/server/account/externalids/ExternalId.java#175).
This has to submitted together with 2).
4) Rollout with a minor (3.5) release due to requirement of data migration.
5) Provide way to perform migration of external IDs online to allow zero downtime
upgrades. There is no specific plan of how to implement online migration.
This feature might be added in the future.
## <a id="time-estimation"> Time Estimation
Release of this feature is planned to happen with the next Gerrit release (3.5).