From 12d2ced3d2259b006af5b07f18acb28cb0902ddb Mon Sep 17 00:00:00 2001 From: Edoardo Spadolini Date: Fri, 29 Jul 2022 20:18:41 +0200 Subject: [PATCH] Implicit cache fixes (#14986) * GetCertAuthority cache bypass fixes * Bypass the cache for GetUser in WithUserLock It's is used in places that want the latest version (like registration) * Actually check the backend in GenerateHostCerts * Fix windows desktop event parsing and caching * GetWebSession and GetWebToken shouldn't be cached Very little would hit those directly, and *auth.ServerWithRoles bypasses the cache anyway. --- lib/auth/auth.go | 20 ++++++++++++-------- lib/services/local/desktops.go | 7 +++---- lib/services/local/events.go | 4 ++-- lib/services/local/presence.go | 2 +- 4 files changed, 18 insertions(+), 15 deletions(-) diff --git a/lib/auth/auth.go b/lib/auth/auth.go index 65437f25faa..959ff9809e6 100644 --- a/lib/auth/auth.go +++ b/lib/auth/auth.go @@ -655,7 +655,7 @@ func (a *Server) GenerateHostCert(hostPublicKey []byte, hostID, nodeName string, } // get the certificate authority that will be signing the public key of the host - ca, err := a.GetCertAuthority(context.TODO(), types.CertAuthID{ + ca, err := a.Services.GetCertAuthority(context.TODO(), types.CertAuthID{ Type: types.HostCA, DomainName: domainName, }, true) @@ -1241,7 +1241,7 @@ func (a *Server) generateUserCert(req certRequest) (*proto.Certs, error) { // In case if user exceeds defaults.MaxLoginAttempts // the user account will be locked for defaults.AccountLockInterval func (a *Server) WithUserLock(username string, authenticateFn func() error) error { - user, err := a.GetUser(username, false) + user, err := a.Services.GetUser(username, false) if err != nil { if trace.IsNotFound(err) { // If user is not found, still call authenticateFn. It should @@ -1810,15 +1810,15 @@ func (a *Server) registerWebauthnDevice(ctx context.Context, regResp *proto.MFAR } // GetWebSession returns existing web session described by req. Explicitly -// delegating to Cache as it's directly implemented by *Services as well. +// delegating to Services as it's directly implemented by Cache as well. func (a *Server) GetWebSession(ctx context.Context, req types.GetWebSessionRequest) (types.WebSession, error) { - return a.Cache.GetWebSession(ctx, req) + return a.Services.GetWebSession(ctx, req) } // GetWebToken returns existing web token described by req. Explicitly -// delegating to Cache as it's directly implemented by *Services as well. +// delegating to Services as it's directly implemented by Cache as well. func (a *Server) GetWebToken(ctx context.Context, req types.GetWebTokenRequest) (types.WebToken, error) { - return a.Cache.GetWebToken(ctx, req) + return a.Services.GetWebToken(ctx, req) } // ExtendWebSession creates a new web session for a user based on a valid previous (current) session. @@ -2106,7 +2106,11 @@ func (a *Server) GenerateHostCerts(ctx context.Context, req *proto.HostCertsRequ } // get the certificate authority that will be signing the public key of the host, - ca, err := a.GetCertAuthority(ctx, types.CertAuthID{ + client := a.Cache + if req.NoCache { + client = a.Services + } + ca, err := client.GetCertAuthority(ctx, types.CertAuthID{ Type: types.HostCA, DomainName: clusterName.GetClusterName(), }, true) @@ -2120,7 +2124,7 @@ func (a *Server) GenerateHostCerts(ctx context.Context, req *proto.HostCertsRequ // to the backend, which is a fine tradeoff if !req.NoCache && req.Rotation != nil && !req.Rotation.Matches(ca.GetRotation()) { log.Debugf("Client sent rotation state %v, cache state is %v, using state from the DB.", req.Rotation, ca.GetRotation()) - ca, err = a.GetCertAuthority(ctx, types.CertAuthID{ + ca, err = a.Services.GetCertAuthority(ctx, types.CertAuthID{ Type: types.HostCA, DomainName: clusterName.GetClusterName(), }, true) diff --git a/lib/services/local/desktops.go b/lib/services/local/desktops.go index 9ed77cbafc4..6668a7abd92 100644 --- a/lib/services/local/desktops.go +++ b/lib/services/local/desktops.go @@ -150,7 +150,7 @@ func (s *WindowsDesktopService) DeleteWindowsDesktop(ctx context.Context, hostID // DeleteAllWindowsDesktops removes all windows desktop resources. func (s *WindowsDesktopService) DeleteAllWindowsDesktops(ctx context.Context) error { - startKey := backend.Key(windowsDesktopsPrefix) + startKey := backend.Key(windowsDesktopsPrefix, "") err := s.DeleteRange(ctx, startKey, backend.RangeEnd(startKey)) if err != nil { return trace.Wrap(err) @@ -165,9 +165,8 @@ func (s *WindowsDesktopService) ListWindowsDesktops(ctx context.Context, req typ return nil, trace.BadParameter("nonpositive parameter limit") } - keyPrefix := []string{windowsDesktopsPrefix} - rangeStart := backend.Key(append(keyPrefix, req.StartKey)...) - rangeEnd := backend.RangeEnd(backend.Key(keyPrefix...)) + rangeStart := backend.Key(windowsDesktopsPrefix, req.StartKey) + rangeEnd := backend.RangeEnd(backend.Key(windowsDesktopsPrefix, "")) filter := services.MatchResourceFilter{ ResourceKind: types.KindWindowsDesktop, Labels: req.Labels, diff --git a/lib/services/local/events.go b/lib/services/local/events.go index f8f57cf4b15..23b9baf875e 100644 --- a/lib/services/local/events.go +++ b/lib/services/local/events.go @@ -1164,7 +1164,7 @@ func (p *networkRestrictionsParser) parse(event backend.Event) (types.Resource, func newWindowsDesktopServicesParser() *windowsDesktopServicesParser { return &windowsDesktopServicesParser{ - baseParser: newBaseParser(backend.Key(windowsDesktopServicesPrefix)), + baseParser: newBaseParser(backend.Key(windowsDesktopServicesPrefix, "")), } } @@ -1189,7 +1189,7 @@ func (p *windowsDesktopServicesParser) parse(event backend.Event) (types.Resourc func newWindowsDesktopsParser() *windowsDesktopsParser { return &windowsDesktopsParser{ - baseParser: newBaseParser(backend.Key(windowsDesktopsPrefix)), + baseParser: newBaseParser(backend.Key(windowsDesktopsPrefix, "")), } } diff --git a/lib/services/local/presence.go b/lib/services/local/presence.go index 07ad793c4d3..a6eeb4e5ac4 100644 --- a/lib/services/local/presence.go +++ b/lib/services/local/presence.go @@ -1439,7 +1439,7 @@ func (s *PresenceService) DeleteWindowsDesktopService(ctx context.Context, name // DeleteAllWindowsDesktopServices removes all registered Windows desktop services. func (s *PresenceService) DeleteAllWindowsDesktopServices(ctx context.Context) error { - startKey := backend.Key(windowsDesktopServicesPrefix) + startKey := backend.Key(windowsDesktopServicesPrefix, "") return s.DeleteRange(ctx, startKey, backend.RangeEnd(startKey)) }