Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Auth: Force lowercase login/email for users #86359

Conversation

eleijonmarck
Copy link
Contributor

@eleijonmarck eleijonmarck commented Apr 16, 2024

why/what

We are lowercasing the login, email parameters of user methods and queries due to enforcement of case insensitive login and emails for our users.
The change introduced makes users whom do not have lowercased login or email not able to login, this is why we opted for a migration as well. This is also part of the work to move to lowercased emails and logins.

  • Adds a migration that lowercases login or emails where we do not find a lowercased entry in the database for those users
  • Adds lowercasing of the parameters login and email for function calls of getting users
  • Removes LOWER() from query parameters, that was not using the indexes of the databases

Tasks

Edit tasklist title
Beta Give feedback Tasklist Tasks, more options

Delete tasklist

Delete tasklist block?
Are you sure? All relationships in this tasklist will be removed.
  1. test cases for lowercasing logins
    Options
  2. test cases for lowercasing emails
    Options
  3. test with terraform provider and state change for the users
    Options

Issue
https://github.com/grafana/identity-access-team/issues/657

Notes

We were initially querying the db with LOWER(login) which did not make use of our created indexes, causing the db to scan all rows.

Without the LOWER() operation, we now see that it is using the index correctly.

EXPLAIN QUERY PLAN SELECT `id`, `uid`, `version`, `email`, `name`, `login`, `password`, `salt`, `rands`, `company`, `email_verified`, `theme`, `help_flags1`, `is_disabled`, `is_admin`, `is_service_account`, `org_id`, `created`, `updated`, `last_seen_at` FROM `user` WHERE (`user`.is_service_account = 0) AND (login=?) LIMIT 1;
  • using indx SEARCH user USING INDEX UQE_user_login (login=?)

A follow up issue is to enforce lowercasing as part of the columns.

Release notice breaking change

We are migrating email and login automatically to lowercasing for our user table.

This is a breaking change that introduces lowercasing input fields in methods for GetByEmail, GetByLogin. The users are now using lowercase as part of their login and emails, regardless if they login with Grafanauser@Grafana.com.

Troubleshooting

If you are experiencing any issues with your users not being logged in with the correct user. Please refer to the CLI we built to deal with conflicting users.

Use our CLI introduced in Grafana 9.3 to resolve user conflicts.

You might experience constraints for duplicate entries (since you might have two user entries, one lowercased and one with mixed or capitalised cases).
Query 1 ERROR at Line 1: : UNIQUE constraint failed: user.email

There might be cases where you as an admin, have to go and look at the users table to see

@eleijonmarck eleijonmarck self-assigned this Apr 18, 2024
@eleijonmarck eleijonmarck changed the title [WIP]: Force lowercase login/email for user CRUD Auth: Force lowercase login/email for GetByEmail, GetByLogin Apr 18, 2024
@eleijonmarck eleijonmarck marked this pull request as ready for review April 18, 2024 12:50
@eleijonmarck eleijonmarck requested a review from a team as a code owner April 18, 2024 12:50
Copy link
Contributor

@IevaVasiljeva IevaVasiljeva left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a breaking change for users who might have mixed case login details, right? I think we need to add a breaking change notice and link to some steps on how to lowercase DB entries?

@eleijonmarck eleijonmarck added the breaking change Relevant for changelog generation label Apr 19, 2024
@eleijonmarck eleijonmarck added the backport v11.0.x Mark PR for automatic backport to v11.0.x label Apr 22, 2024
@Jguer
Copy link
Contributor

Jguer commented Apr 23, 2024

We never forced migration to lower case and as such this will break more users than the previous patch. I think this needs a migration patch to set all user logins to lower case other wise weird lookups on auth will start to happen and new users might be created

@eleijonmarck
Copy link
Contributor Author

We never forced migration to lower case and as such this will break more users than the previous patch. I think this needs a migration patch to set all user logins to lower case other wise weird lookups on auth will start to happen and new users might be created

let me work out a bunch of scenarios for different cases and make sure that we secure the desired state after a migration

@eleijonmarck eleijonmarck requested a review from a team as a code owner April 23, 2024 13:52
@eleijonmarck eleijonmarck requested review from owensmallwood and removed request for a team April 23, 2024 13:52
users []*user.User
wantUsers []*user.User
}
testCases := []migrationTestCase{
Copy link
Contributor

@Jguer Jguer Apr 23, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

missing the cases:
"2 users - same login, one already lowercase"
"2 users - same login, none lowercase"

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yea I will expand on the test cases. Thanks! In general it looks good?

@eleijonmarck eleijonmarck changed the title Auth: Force lowercase login/email for GetByEmail, GetByLogin Auth: Force lowercase login/email for users Apr 24, 2024
Copy link
Contributor

@IevaVasiljeva IevaVasiljeva left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code LGTM, I added a few suggestions for optimising the migration a bit.

I'm not sure what the expected behaviour should be when it comes to several non-lowercased conflicting entries - I guess sticking with the more recent one makes sense, but then we should clearly document how the conflict resolution tool can be used to pick the older user instead. I'm mostly worried about the cloud scenario, where users can neither access the DB nor use the CLI, right?

Also breaking change notice should be updated to explain that we're migrating emails and logins automatically (so it will only break for users with conflicting entries).


// "2 users - same login, none lowercase"
{
desc: "2 users with same login noone is lowercased we pick the most recent user to lowercase",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

question: how is the preference of the more recent user enforced? Is it just based on the more recently created (so the more recent entry in the DB table)?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

currently it will be the one that loops through for the user. ideally we would want to choose the one that has the latest updated

Copy link
Contributor

This PR must be merged before a backport PR will be created.

@eleijonmarck
Copy link
Contributor Author

Terraform considerations

We need to consider that terraform provider will break due to the migration.

  1. Create a script that created UPPERCASE user logins for Grafana terraform apply
// Create 100 Grafana users with uppercase login and email
resource "grafana_user" "user_upper" {
  count = 100
  login    = upper(format("user%03d", count.index + 1))
  email    = upper(format("user%03d@example.com", count.index + 1))
  name     = upper(format("User %03d", count.index + 1))
  password = "InitialPassword123!"
  is_admin = false
}
  1. remove the migration from the migration_log
  2. terraform apply

This will produce an error for the terrraform

  # grafana_user.user_upper[97] will be updated in-place
  ~ resource "grafana_user" "user_upper" {
      ~ email    = "user098@example.com" -> "USER098@EXAMPLE.COM"
        id       = "138"
      ~ login    = "user098" -> "USER098"
        name     = "USER 098"
        # (3 unchanged attributes hidden)
    }

  # grafana_user.user_upper[98] will be updated in-place
  ~ resource "grafana_user" "user_upper" {
      ~ email    = "user099@example.com" -> "USER099@EXAMPLE.COM"
        id       = "132"
      ~ login    = "user099" -> "USER099"
        name     = "USER 099"
        # (3 unchanged attributes hidden)
    }

  # grafana_user.user_upper[99] will be updated in-place
  ~ resource "grafana_user" "user_upper" {
      ~ email    = "user100@example.com" -> "USER100@EXAMPLE.COM"
        id       = "149"
      ~ login    = "user100" -> "USER100"
        name     = "USER 100"
        # (3 unchanged attributes hidden)
    }

Copy link
Contributor

@IevaVasiljeva IevaVasiljeva left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've tested this, and the migrations as well as lower casing logic upon logins and user email/login changes work as I'd expect it to.

I still think the migration can be optimised a bit, but I don't see it as a blocking change. Similarly, the Terraform fix can be merged later.

@eleijonmarck eleijonmarck merged commit e394e16 into main Apr 25, 2024
13 checks passed
@eleijonmarck eleijonmarck deleted the eleijonmarck/user/caseinsensitive/enforce-lowercase-on-parameters branch April 25, 2024 16:31
Copy link
Contributor

The backport to v11.0.x failed:

The process '/usr/bin/git' failed with exit code 1

To backport manually, run these commands in your terminal:

# Fetch latest updates from GitHub
git fetch
# Create a new branch
git switch --create backport-86359-to-v11.0.x origin/v11.0.x
# Cherry-pick the merged commit of this pull request and resolve the conflicts
git cherry-pick -x e394e16073dd73fef589d2b42afbb9e0a9eed606

When the conflicts are resolved, stage and commit the changes:

git add . && git cherry-pick --continue

If you have the GitHub CLI installed:

# Push the branch to GitHub:
git push --set-upstream origin backport-86359-to-v11.0.x
# Create the PR body template
PR_BODY=$(gh pr view 86359 --json body --template 'Backport e394e16073dd73fef589d2b42afbb9e0a9eed606 from #86359{{ "\n\n---\n\n" }}{{ index . "body" }}')
# Create the PR on GitHub
echo "${PR_BODY}" | gh pr create --title "[v11.0.x] Auth: Force lowercase login/email for users" --body-file - --label "type/bug" --label "area/backend" --label "add to changelog" --label "breaking change" --label "area/backend/db/migration" --label "backport" --base v11.0.x --milestone 11.0.x --web

Or, if you don't have the GitHub CLI installed (we recommend you install it!):

# Push the branch to GitHub:
git push --set-upstream origin backport-86359-to-v11.0.x

# Create a pull request where the `base` branch is `v11.0.x` and the `compare`/`head` branch is `backport-86359-to-v11.0.x`.

# Remove the local backport branch
git switch main
git branch -D backport-86359-to-v11.0.x

@grafana-delivery-bot grafana-delivery-bot bot added the backport-failed Failed to generate backport PR. Please resolve conflicts and create one manually. label Apr 25, 2024
eleijonmarck added a commit that referenced this pull request Apr 26, 2024
* [WIP]: Force lowercase login/email for user CRUD

* warn and remove use of userCaseInsensitiveLogin check

* remove log warning

* reimplementation of the caseinsensitive

* need to decide if we want the conflict check or not

* remvoved the tests for conflict user by getEmail, getLogin

* added tests for user lowercase migration

* wip: emails next

* tests for email lowercasing

* review comments

* optimized login and email lookup before migrating

(cherry picked from commit e394e16)
eleijonmarck added a commit that referenced this pull request Apr 26, 2024
* [WIP]: Force lowercase login/email for user CRUD

* warn and remove use of userCaseInsensitiveLogin check

* remove log warning

* reimplementation of the caseinsensitive

* need to decide if we want the conflict check or not

* remvoved the tests for conflict user by getEmail, getLogin

* added tests for user lowercase migration

* wip: emails next

* tests for email lowercasing

* review comments

* optimized login and email lookup before migrating

(cherry picked from commit e394e16)
eleijonmarck added a commit that referenced this pull request May 2, 2024
Auth: Force lowercase login/email for users (#86359)

* [WIP]: Force lowercase login/email for user CRUD

* warn and remove use of userCaseInsensitiveLogin check

* remove log warning

* reimplementation of the caseinsensitive

* need to decide if we want the conflict check or not

* remvoved the tests for conflict user by getEmail, getLogin

* added tests for user lowercase migration

* wip: emails next

* tests for email lowercasing

* review comments

* optimized login and email lookup before migrating

(cherry picked from commit e394e16)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
add to changelog area/backend/db/migration area/backend backport v11.0.x Mark PR for automatic backport to v11.0.x backport-failed Failed to generate backport PR. Please resolve conflicts and create one manually. breaking change Relevant for changelog generation type/bug
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants