1
0
Эх сурвалжийг харах

[PkiRealm] Invalidate cache on role mappings change (#31510)

PkiRealm caches successful authentications and provides ways to
invalidate the cache. But in some scenario's the cache was not being
invalidated on role mapping change.
PkiRealm does not inform role mapper to be notified for cache
refresh on role mapping updates.
The logic in `TransportClearRealmCacheAction#nodeOperation`
which gets invoked for refreshing cache on realms, considers null or
empty realm names in the request as clear cache on all realms. When
LDAP realm is not present then it clears cache for all realms so it
works fine, but when LDAP realm is configured then role mapper
sends a request with LDAP realm names and so the cache is cleared
only for those realms.

This commit resolves the issue by registering PkiRealm with role
mapper for cache refresh. PkiRealm implements CachingRealm and as it
does not extend CachingUsernamePasswordRealm, have modified the
interface method `refreshRealmOnChange` to accept CachingRealm.
Yogesh Gaikwad 7 жил өмнө
parent
commit
009ae48cba

+ 1 - 0
x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authc/pki/PkiRealm.java

@@ -86,6 +86,7 @@ public class PkiRealm extends Realm implements CachingRealm {
         this.trustManager = trustManagers(config);
         this.principalPattern = PkiRealmSettings.USERNAME_PATTERN_SETTING.get(config.settings());
         this.roleMapper = roleMapper;
+        this.roleMapper.refreshRealmOnChange(this);
         this.cache = CacheBuilder.<BytesKey, User>builder()
                 .setExpireAfterWrite(PkiRealmSettings.CACHE_TTL_SETTING.get(config.settings()))
                 .setMaximumWeight(PkiRealmSettings.CACHE_MAX_USERS_SETTING.get(config.settings()))

+ 5 - 0
x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authc/support/CachingRealm.java

@@ -13,6 +13,11 @@ import org.elasticsearch.xpack.core.security.authc.Realm;
  */
 public interface CachingRealm {
 
+    /**
+     * @return The name of this realm.
+     */
+    String name();
+
     /**
      * Expires a single user from the cache identified by the String agument
      * @param username the identifier of the user to be cleared

+ 1 - 1
x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authc/support/DnRoleMapper.java

@@ -69,7 +69,7 @@ public class DnRoleMapper implements UserRoleMapper {
     }
 
     @Override
-    public void refreshRealmOnChange(CachingUsernamePasswordRealm realm) {
+    public void refreshRealmOnChange(CachingRealm realm) {
         addListener(realm::expireAll);
     }
 

+ 1 - 1
x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authc/support/UserRoleMapper.java

@@ -44,7 +44,7 @@ public interface UserRoleMapper {
      * the whole cluster depending on whether this role-mapper has node-local data or cluster-wide
      * data.
      */
-    void refreshRealmOnChange(CachingUsernamePasswordRealm realm);
+    void refreshRealmOnChange(CachingRealm realm);
 
     /**
      * A representation of a user for whom roles should be mapped.

+ 2 - 2
x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authc/support/mapper/CompositeRoleMapper.java

@@ -16,7 +16,7 @@ import org.elasticsearch.action.ActionListener;
 import org.elasticsearch.action.support.GroupedActionListener;
 import org.elasticsearch.watcher.ResourceWatcherService;
 import org.elasticsearch.xpack.core.security.authc.RealmConfig;
-import org.elasticsearch.xpack.security.authc.support.CachingUsernamePasswordRealm;
+import org.elasticsearch.xpack.security.authc.support.CachingRealm;
 import org.elasticsearch.xpack.security.authc.support.DnRoleMapper;
 import org.elasticsearch.xpack.security.authc.support.UserRoleMapper;
 
@@ -48,7 +48,7 @@ public class CompositeRoleMapper implements UserRoleMapper {
     }
 
     @Override
-    public void refreshRealmOnChange(CachingUsernamePasswordRealm realm) {
+    public void refreshRealmOnChange(CachingRealm realm) {
         this.delegates.forEach(mapper -> mapper.refreshRealmOnChange(realm));
     }
 

+ 2 - 2
x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authc/support/mapper/NativeRoleMappingStore.java

@@ -34,7 +34,7 @@ import org.elasticsearch.xpack.core.security.action.rolemapping.PutRoleMappingRe
 import org.elasticsearch.xpack.core.security.authc.support.mapper.ExpressionRoleMapping;
 import org.elasticsearch.xpack.core.security.authc.support.mapper.expressiondsl.ExpressionModel;
 import org.elasticsearch.xpack.core.security.client.SecurityClient;
-import org.elasticsearch.xpack.security.authc.support.CachingUsernamePasswordRealm;
+import org.elasticsearch.xpack.security.authc.support.CachingRealm;
 import org.elasticsearch.xpack.security.authc.support.UserRoleMapper;
 import org.elasticsearch.xpack.security.support.SecurityIndexManager;
 
@@ -369,7 +369,7 @@ public class NativeRoleMappingStore extends AbstractComponent implements UserRol
      * @see ClearRealmCacheAction
      */
     @Override
-    public void refreshRealmOnChange(CachingUsernamePasswordRealm realm) {
+    public void refreshRealmOnChange(CachingRealm realm) {
         realmsToRefresh.add(realm.name());
     }
 }

+ 3 - 0
x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/pki/PkiRealmTests.java

@@ -50,6 +50,7 @@ import static org.mockito.Mockito.any;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
 import static org.mockito.Mockito.when;
 
 public class PkiRealmTests extends ESTestCase {
@@ -104,6 +105,7 @@ public class PkiRealmTests extends ESTestCase {
         UserRoleMapper roleMapper = mock(UserRoleMapper.class);
         PkiRealm realm = new PkiRealm(new RealmConfig("", Settings.EMPTY, globalSettings, TestEnvironment.newEnvironment(globalSettings),
             new ThreadContext(globalSettings)), roleMapper);
+        verify(roleMapper).refreshRealmOnChange(realm);
         Mockito.doAnswer(invocation -> {
             final UserRoleMapper.UserData userData = (UserRoleMapper.UserData) invocation.getArguments()[0];
             final ActionListener<Set<String>> listener = (ActionListener<Set<String>>) invocation.getArguments()[1];
@@ -144,6 +146,7 @@ public class PkiRealmTests extends ESTestCase {
 
         final int numTimes = invalidate ? 2 : 1;
         verify(roleMapper, times(numTimes)).resolveRoles(any(UserRoleMapper.UserData.class), any(ActionListener.class));
+        verifyNoMoreInteractions(roleMapper);
     }
 
     public void testCustomUsernamePattern() throws Exception {