-
-
Notifications
You must be signed in to change notification settings - Fork 954
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
fix: reduce db lookups in whoami for aal check #3372
Conversation
Significantly improves performance by reducing the amount of queries we need to do when checking for the different AAL levels.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
Co-authored-by: Alano Terblanche <[email protected]>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have some doubts about the migration strategy, see comments.
@@ -0,0 +1 @@ | |||
ALTER TABLE identities ADD COLUMN available_aal VARCHAR(4) NOT NULL DEFAULT 'aal0'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Doesn't NOT NULL DEFAULT ...
do a full table update? Wouldn't it be better to use a nullable column here instead?
Like this every identity would have available_aal
set to 0 after the migration, and only on update we would set the correct value.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yep, absolutely. However as I understood the people from CRDB, this should not be an issue due to the way migrations work. We still need to verify that though.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's now nullable
// For the time being we want to update the AAL in the database if it is unset. | ||
UpsertAAL, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A nullable column makes this unnecessary, because we can distinguish the "not yet computed" from the "zero" case.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think that this state could also happen during an import, which is why I think this fallback is required.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why does this lack the new column?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Because it's not exposed in JSON
identity/manager.go
Outdated
return m.r.PrivilegedIdentityPool().UpdateIdentity(ctx, updated) | ||
} | ||
|
||
func (m *Manager) setAAL(ctx context.Context, i *Identity) (err error) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it makes more sense to make this a function on the identity, and provide the manager as a dependency there (potentially as an interface). The logic is duplicated in the session manager well.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
session/manager_http.go
Outdated
} else if firstCount > 0 { | ||
available = identity.AuthenticatorAssuranceLevel1 | ||
} | ||
i.AvailableAAL = available |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i.AvailableAAL = available | |
i.SetAvailableAAL(s.r.IdentityManager()) |
// This is the migration strategy for identities that already exist. | ||
if managerOpts.upsertAAL { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
During the "migration" we just recompute it for everyone. Users that don't log in during the migration period stay at AAL0 forever. I think a nullable column is the way to go instead.
// This is the migration strategy for identities that already exist. | |
if managerOpts.upsertAAL { | |
// This is the migration strategy for identities that already exist. | |
if !i.AvailableAAL.Valid { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yup - it's now nullable. This parameter however is still here because we don't always want to perform an INSERT or UPDATE statement when this method is called, so there has to be a way to control it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK, makes sense.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good now 👍
// Available is 0 if the identity was created before the AAL feature was introduced, or if the identity | ||
// was directly created in the persister and not the identity manager. | ||
// | ||
// aal0 indicates that the AAL state of the identity is probably unknown. | ||
// | ||
// In either case, we need to fetch the credentials from the database to determine the AAL. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This comment is not accurate anymore.
// This is the migration strategy for identities that already exist. | ||
if managerOpts.upsertAAL { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK, makes sense.
Codecov Report
@@ Coverage Diff @@
## master #3372 +/- ##
=======================================
Coverage 77.98% 77.99%
=======================================
Files 327 327
Lines 21279 21331 +52
=======================================
+ Hits 16595 16637 +42
- Misses 3449 3456 +7
- Partials 1235 1238 +3
|
This PR removes queries to
identity_credentials
,identity_credential_types
, andidentity_credential_identifiers
when performing the whoami check.It does this by “caching” the maximum available AAL in the identity table. The value is updated whenever an identity is created or updated.
The mechanism can also fall back to generate the AAL value itself if the value is not available in the identity (this is a migration strategy).
One potential issue: If the
available_aal
is not correctly set, it might lead to issues where the user has 2FA enabled, but the system thinks they only have 1FA enabled.