[IAM] Clear user's permission cache after login (#102311)
This commit is contained in:
@@ -142,6 +142,7 @@ func ProvideRegistration(
|
||||
|
||||
authnSvc.RegisterPostAuthHook(rbacSync.SyncPermissionsHook, 120)
|
||||
authnSvc.RegisterPostLoginHook(orgSync.SetDefaultOrgHook, 140)
|
||||
authnSvc.RegisterPostLoginHook(rbacSync.ClearUserPermissionCacheHook, 170)
|
||||
|
||||
nsSync := sync.ProvideNamespaceSync(cfg)
|
||||
authnSvc.RegisterPostAuthHook(nsSync.SyncNamespace, 150)
|
||||
|
||||
@@ -186,3 +186,22 @@ func (s *RBACSync) SyncCloudRoles(ctx context.Context, ident *authn.Identity, r
|
||||
RolesToRemove: rolesToRemove,
|
||||
})
|
||||
}
|
||||
|
||||
// ClearUserPermissionCacheHook clears a user's permission cache if user Login succeeded. Necessary so that if a user logs in
|
||||
// through different SSO providers with different roles assigned in each, they do not get the wrong permissions.
|
||||
func (s *RBACSync) ClearUserPermissionCacheHook(ctx context.Context, ident *authn.Identity, r *authn.Request, err error) {
|
||||
ctx, span := s.tracer.Start(ctx, "rbac.sync.ClearUserPermissionCacheHook")
|
||||
defer span.End()
|
||||
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
ctxLogger := s.log.FromContext(ctx)
|
||||
if !ident.IsIdentityType(claims.TypeUser) {
|
||||
ctxLogger.Debug("Skipping user permission cache clear, not a user", "type", ident.GetIdentityType())
|
||||
return
|
||||
}
|
||||
|
||||
s.ac.ClearUserPermissionCache(ident)
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package sync
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
@@ -365,6 +366,61 @@ func TestRBACSync_cloudRolesToAddAndRemove(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestRBACSync_ClearUserPermissionCacheHook(t *testing.T) {
|
||||
type testCase struct {
|
||||
desc string
|
||||
identityType claims.IdentityType
|
||||
loginErr error
|
||||
expectedCalled bool
|
||||
}
|
||||
|
||||
tests := []testCase{
|
||||
{
|
||||
desc: "should clear the permission cache when the user logged in successfully",
|
||||
identityType: claims.TypeUser,
|
||||
loginErr: nil,
|
||||
expectedCalled: true,
|
||||
},
|
||||
{
|
||||
desc: "should skip clearing the permission cache when the user failed to log in",
|
||||
identityType: claims.TypeUser,
|
||||
loginErr: errors.New("failed to log in"),
|
||||
expectedCalled: false,
|
||||
},
|
||||
{
|
||||
desc: "should skip clearing the permission cache when the identity is not a user",
|
||||
identityType: claims.TypeServiceAccount,
|
||||
loginErr: nil,
|
||||
expectedCalled: false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.desc, func(t *testing.T) {
|
||||
var called bool
|
||||
s := &RBACSync{
|
||||
ac: &acmock.Mock{
|
||||
ClearUserPermissionCacheFunc: func(_ identity.Requester) {
|
||||
called = true
|
||||
},
|
||||
},
|
||||
log: log.NewNopLogger(),
|
||||
tracer: tracing.InitializeTracerForTest(),
|
||||
}
|
||||
identity := &authn.Identity{
|
||||
ID: "1",
|
||||
Type: tt.identityType,
|
||||
OrgID: 1,
|
||||
OrgRoles: map[int64]org.RoleType{1: org.RoleViewer},
|
||||
}
|
||||
req := &authn.Request{}
|
||||
|
||||
s.ClearUserPermissionCacheHook(context.Background(), identity, req, tt.loginErr)
|
||||
assert.Equal(t, tt.expectedCalled, called)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func setupTestEnv(t *testing.T) *RBACSync {
|
||||
acMock := &acmock.Mock{
|
||||
GetUserPermissionsFunc: func(ctx context.Context, siu identity.Requester, o accesscontrol.Options) ([]accesscontrol.Permission, error) {
|
||||
|
||||
Reference in New Issue
Block a user