sql: properly populate is_superuser#69355
Conversation
3005c09 to
be561d9
Compare
rafiss
left a comment
There was a problem hiding this comment.
Reviewable status:
complete! 0 of 0 LGTMs obtained (waiting on @otan)
pkg/ccl/serverccl/role_authentication_test.go, line 104 at r1 (raw file):
{"druidia", "12345", false, true, ""}, {"druidia", "hunter2", false, false, "crypto/bcrypt"}, {"root", "", true, false, "crypto/bcrypt"},
looks like root is the only true case in these tests. can we add more tests for other admin roles having is_superuser true also?
pkg/sql/authorization.go, line 403 at r1 (raw file):
// we could save detailed memberships (as opposed to fully expanded) and reuse them // across users. We may then want to lookup more than just this user. func (p *planner) resolveMemberOfWithAdminOption(
this function wasn't really supposed to be used externally, since it does a KV lookup -- the idea was to always go through the RoleMembershipCache to avoid unexpected round trips
pkg/sql/user.go, line 257 at r1 (raw file):
) if err != nil { return sessioninit.AuthInfo{}, err
could this all be done outside of retrieveAuthInfo, so that it doesn't end up in the session init cache? instead, is there a way we could do this in the GetUserSessionInitInfo function, and reuse the execCfg.RoleMemberCache? it would address the concerns i had about cache inconsistency, and the danger of exposing a non-cached ResolveMemberOfWithAdminOption function
pkg/sql/sessioninit/cache.go, line 63 at r1 (raw file):
UserExists bool // IsSuperuser is set to true for any admin users. IsSuperuser bool
hm i think there's a cache consistency issue here now
when GRANT admin TO user happens, the role membership cache is invalidated:
cockroach/pkg/sql/grant_role.go
Line 206 in 8f82389
however, IsSuperUser is now going to be cached in the SessionInitCache, and as per the clearCacheIfStale method below, it won't be cleared out even if the role memberships change.
you should be able to repro with:
- login as testuser
- SHOW is_superuser should be false
- disconnect
- login as root
- GRANT admin TO testuser
- disconnect
- login as testuser
- SHOW is_superuser should be true at this point, but i think it will show false.
this points to the fact that this sessioninit cache is undertested right now -- i wanted to write tests for it during stability period
pkg/sql/sqlutil/auth.go, line 23 at r1 (raw file):
// ResolveMemberOfWithAdminOption explores all the memberships of the user. // It returns a map of memberships, as well as whether that membership // is an admin role.
i think this deserves some more disclaimers around how it can cause unexpected latency, and if possible you should use the cached version (see sql.MemberOfWithAdminOption)
even better would be to make this function here use the RoleMemberCache. see if we can pull the sql.planner.MemberOfWithAdminOption function in here and refactor it so it doesn't use the planner directly.
otan
left a comment
There was a problem hiding this comment.
Reviewable status:
complete! 0 of 0 LGTMs obtained (waiting on @otan and @rafiss)
pkg/ccl/serverccl/role_authentication_test.go, line 104 at r1 (raw file):
Previously, rafiss (Rafi Shamim) wrote…
looks like
rootis the only true case in these tests. can we add more tests for other admin roles havingis_superusertrue also?
Done.
pkg/sql/user.go, line 257 at r1 (raw file):
Previously, rafiss (Rafi Shamim) wrote…
could this all be done outside of
retrieveAuthInfo, so that it doesn't end up in the session init cache? instead, is there a way we could do this in theGetUserSessionInitInfofunction, and reuse theexecCfg.RoleMemberCache? it would address the concerns i had about cache inconsistency, and the danger of exposing a non-cachedResolveMemberOfWithAdminOptionfunction
urgh, that's annoying. not sure where to get p.Descriptors() from which is what held me back.
rafiss
left a comment
There was a problem hiding this comment.
Reviewable status:
complete! 0 of 0 LGTMs obtained (waiting on @otan and @rafiss)
pkg/sql/user.go, line 257 at r1 (raw file):
Previously, otan (Oliver Tan) wrote…
urgh, that's annoying. not sure where to get
p.Descriptors()from which is what held me back.
i think what we can do (not the prettiest...) is change the signature of retrieveSessionInitInfoWithCache (in pkg/sql/user.go) to
func retrieveSessionInitInfoWithCache(
ctx context.Context,
execCfg *ExecutorConfig,
ie *InternalExecutor,
username security.SQLUsername,
databaseName string,
) (aInfo sessioninit.AuthInfo, settingsEntries []sessioninit.SettingsCacheEntry, isSuperuser bool, err error) {
and somewhere in the impl of that you can use execCfg.CollectionFactory.Txn() which will give you the descs.Collection you need.
IMO, the func (p *planner) MemberOfWithAdminOption( method should actually be a method on the RoleMemberCache. similar to how SessionInitCache has a GetAuthInfo method.
|
okay, have a look at this. |
otan
left a comment
There was a problem hiding this comment.
Reviewable status:
complete! 0 of 0 LGTMs obtained (waiting on @rafiss)
pkg/sql/authorization.go, line 403 at r1 (raw file):
Previously, rafiss (Rafi Shamim) wrote…
this function wasn't really supposed to be used externally, since it does a KV lookup -- the idea was to always go through the RoleMembershipCache to avoid unexpected round trips
Done.
pkg/sql/user.go, line 257 at r1 (raw file):
Previously, rafiss (Rafi Shamim) wrote…
i think what we can do (not the prettiest...) is change the signature of
retrieveSessionInitInfoWithCache(in pkg/sql/user.go) tofunc retrieveSessionInitInfoWithCache( ctx context.Context, execCfg *ExecutorConfig, ie *InternalExecutor, username security.SQLUsername, databaseName string, ) (aInfo sessioninit.AuthInfo, settingsEntries []sessioninit.SettingsCacheEntry, isSuperuser bool, err error) {and somewhere in the impl of that you can use
execCfg.CollectionFactory.Txn()which will give you thedescs.Collectionyou need.IMO, the
func (p *planner) MemberOfWithAdminOption(method should actually be a method on theRoleMemberCache. similar to howSessionInitCachehas aGetAuthInfomethod.
Done.
pkg/sql/sessioninit/cache.go, line 63 at r1 (raw file):
Previously, rafiss (Rafi Shamim) wrote…
hm i think there's a cache consistency issue here now
when
GRANT admin TO userhappens, the role membership cache is invalidated:cockroach/pkg/sql/grant_role.go
Line 206 in 8f82389
however, IsSuperUser is now going to be cached in the SessionInitCache, and as per the
clearCacheIfStalemethod below, it won't be cleared out even if the role memberships change.you should be able to repro with:
- login as testuser - SHOW is_superuser should be false - disconnect - login as root - GRANT admin TO testuser - disconnect - login as testuser - SHOW is_superuser should be true at this point, but i think it will show false.this points to the fact that this sessioninit cache is undertested right now -- i wanted to write tests for it during stability period
Done.
pkg/sql/sqlutil/auth.go, line 23 at r1 (raw file):
Previously, rafiss (Rafi Shamim) wrote…
i think this deserves some more disclaimers around how it can cause unexpected latency, and if possible you should use the cached version (see
sql.MemberOfWithAdminOption)even better would be to make this function here use the
RoleMemberCache. see if we can pull thesql.planner.MemberOfWithAdminOptionfunction in here and refactor it so it doesn't use the planner directly.
Done.
79b3cd7 to
67b7349
Compare
rafiss
left a comment
There was a problem hiding this comment.
looking nice!
Reviewable status:
complete! 0 of 0 LGTMs obtained (waiting on @otan and @rafiss)
pkg/sql/user.go, line 109 at r10 (raw file):
} err = execCfg.CollectionFactory.Txn(
there's one sneaky thing here -- since this can result in a KV lookup and it's during the connection init flow, this is supposed to be behind the server.user_login.timeout setting. see the comment on GetUserSessionInitInfo. the timeout itself is applied inside of the retrieveSessionInitInfoWithCache function right now.
there's also a test for it in user_test.go (it's named TestGetUserHashedPasswordTimeout since i missed renaming it in my last refactor)
so could you move this lookup to be behind the timeout, and verify with that test that the timeout applies to this operation?
otan
left a comment
There was a problem hiding this comment.
Reviewable status:
complete! 0 of 0 LGTMs obtained (waiting on @rafiss)
pkg/sql/user.go, line 109 at r10 (raw file):
Previously, rafiss (Rafi Shamim) wrote…
there's one sneaky thing here -- since this can result in a KV lookup and it's during the connection init flow, this is supposed to be behind the
server.user_login.timeoutsetting. see the comment onGetUserSessionInitInfo. the timeout itself is applied inside of theretrieveSessionInitInfoWithCachefunction right now.there's also a test for it in user_test.go (it's named
TestGetUserHashedPasswordTimeoutsince i missed renaming it in my last refactor)so could you move this lookup to be behind the timeout, and verify with that test that the timeout applies to this operation?
gotcha, done
is_superuser was previously only true for root. This commit changes it such that it is true for *any* admin user. Release justification: low risk high benefit change Release note (sql change): `SHOW is_superuser` now works, and is set to true if the user has admin privileges.
rafiss
left a comment
There was a problem hiding this comment.
lgtm! thanks for the tests
Reviewed 5 of 6 files at r10, 13 of 13 files at r11, all commit messages.
Reviewable status:complete! 0 of 0 LGTMs obtained (waiting on @rafiss)
|
bors r=rafiss |
|
Build succeeded: |
Release justification: low risk high benefit change
Last commit only. First two commits in #69224
See individual commits for details.