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

fix: reduce db lookups in whoami for aal check #3372

Merged
merged 9 commits into from
Jul 13, 2023
Merged

Conversation

aeneasr
Copy link
Member

@aeneasr aeneasr commented Jul 6, 2023

This PR removes queries to identity_credentials, identity_credential_types, and identity_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.

@aeneasr aeneasr marked this pull request as ready for review July 7, 2023 08:52
@aeneasr aeneasr requested a review from zepatrik as a code owner July 7, 2023 08:52
Significantly improves performance by reducing the amount of queries we need to do when checking for the different AAL levels.
Benehiko
Benehiko previously approved these changes Jul 7, 2023
Copy link
Contributor

@Benehiko Benehiko left a comment

Choose a reason for hiding this comment

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

LGTM

session/manager_http.go Outdated Show resolved Hide resolved
Co-authored-by: Alano Terblanche <[email protected]>
Copy link
Member

@zepatrik zepatrik left a 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';
Copy link
Member

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.

Copy link
Member Author

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.

Copy link
Member Author

Choose a reason for hiding this comment

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

It's now nullable

Comment on lines +209 to +210
// For the time being we want to update the AAL in the database if it is unset.
UpsertAAL,
Copy link
Member

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.

Copy link
Member Author

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.

Copy link
Member

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?

Copy link
Member Author

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

return m.r.PrivilegedIdentityPool().UpdateIdentity(ctx, updated)
}

func (m *Manager) setAAL(ctx context.Context, i *Identity) (err error) {
Copy link
Member

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.

Copy link
Member Author

Choose a reason for hiding this comment

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

done

} else if firstCount > 0 {
available = identity.AuthenticatorAssuranceLevel1
}
i.AvailableAAL = available
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
i.AvailableAAL = available
i.SetAvailableAAL(s.r.IdentityManager())

Comment on lines +335 to +336
// This is the migration strategy for identities that already exist.
if managerOpts.upsertAAL {
Copy link
Member

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.

Suggested change
// 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 {

Copy link
Member Author

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.

Copy link
Member

Choose a reason for hiding this comment

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

OK, makes sense.

zepatrik
zepatrik previously approved these changes Jul 11, 2023
Copy link
Member

@zepatrik zepatrik left a comment

Choose a reason for hiding this comment

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

Looks good now 👍

Comment on lines +307 to +312
// 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.
Copy link
Member

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.

Comment on lines +335 to +336
// This is the migration strategy for identities that already exist.
if managerOpts.upsertAAL {
Copy link
Member

Choose a reason for hiding this comment

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

OK, makes sense.

@codecov
Copy link

codecov bot commented Jul 11, 2023

Codecov Report

Merging #3372 (70e4eac) into master (eaa3f3c) will increase coverage by 0.00%.
The diff coverage is 75.86%.

❗ Current head 70e4eac differs from pull request most recent head 8fedaf1. Consider uploading reports for the commit 8fedaf1 to get more accurate results

@@           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     
Impacted Files Coverage Δ
identity/manager.go 76.92% <0.00%> (-3.73%) ⬇️
identity/identity.go 89.67% <53.84%> (-2.33%) ⬇️
session/manager_http.go 79.36% <68.75%> (+0.71%) ⬆️
identity/credentials.go 83.78% <84.00%> (+0.11%) ⬆️
cmd/clidoc/main.go 68.05% <100.00%> (ø)
identity/test/pool.go 100.00% <100.00%> (ø)
selfservice/strategy/code/strategy_recovery.go 70.56% <100.00%> (ø)
selfservice/strategy/code/strategy_verification.go 74.25% <100.00%> (ø)
session/handler.go 68.60% <100.00%> (+0.24%) ⬆️
text/message_node.go 100.00% <100.00%> (ø)

... and 1 file with indirect coverage changes

@aeneasr aeneasr merged commit d814a48 into master Jul 13, 2023
26 checks passed
@aeneasr aeneasr deleted the max-aal-in-sess branch July 13, 2023 08:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants