You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@ranger.apache.org by Ramachandran Krishnan <ra...@gmail.com> on 2022/09/08 10:00:02 UTC

Review Request 74106: Bug in Ranger Roles Cache

-----------------------------------------------------------
This is an automatically generated e-mail. To reply, visit:
https://reviews.apache.org/r/74106/
-----------------------------------------------------------

Review request for ranger, Madhan Neethiraj, Nikhil P, and Velmurugan Periasamy.


Bugs: RANGER-3898
    https://issues.apache.org/jira/browse/RANGER-3898


Repository: ranger


Description
-------

Bug in Ranger Roles Cache

It seems Apache Ranger open source contains a bug where else block in the below code will not be called at all 

In the below code else block is a dead code

 

public RangerRoles getLatestRangerRoleOrCached(String serviceName, RoleDBStore roleDBStore, Long lastKnownRoleVersion, Long rangerRoleVersionInDB) throws Exception {
   final RangerRoles ret;

   if (lastKnownRoleVersion == null || !lastKnownRoleVersion.equals(rangerRoleVersionInDB)) {
      roleCacheWrapper = new RangerRoleCacheWrapper();
      ret              = roleCacheWrapper.getLatestRangerRoles(serviceName, roleDBStore, lastKnownRoleVersion, rangerRoleVersionInDB);
   } else if (lastKnownRoleVersion.equals(rangerRoleVersionInDB)) {
      ret = null;
   } else {
      ret = roleCacheWrapper.getRoles();
   }

   return ret;
}


The below behaviour also broken  

when multiple threads are trying to access and one or more threads got timeout while acquiring the lock,it will fetch the roles from cache but ,we are not setting the roles in cache anywhere in our code 

public RangerRoles getLatestRangerRoles(String serviceName, RoleDBStore roleDBStore, Long lastKnownRoleVersion, Long rolesVersionInDB) throws Exception {
   RangerRoles ret           = null;
   boolean     lockResult = false;

   if (LOG.isDebugEnabled()) {
      LOG.debug("==> RangerRoleCache.getLatestRangerRoles(ServiceName= " + serviceName + " lastKnownRoleVersion= " + lastKnownRoleVersion + " rolesVersionInDB= " + rolesVersionInDB + ")");
   }

   try {
      lockResult = lock.tryLock(waitTimeInSeconds, TimeUnit.SECONDS);

      if (lockResult) {
         // We are getting all the Roles to be downloaded for now. Should do downloades for each service based on what roles are there in the policies.
         SearchFilter          searchFilter = null;
         final Set<RangerRole> rolesInDB    = new HashSet<>(roleDBStore.getRoles(searchFilter));

         Date updateTime = new Date();

         if (rolesInDB != null) {
            ret = new RangerRoles();

            ret.setRangerRoles(rolesInDB);
            ret.setRoleUpdateTime(updateTime);
            ret.setRoleVersion(rolesVersionInDB);

            rolesVersion = rolesVersionInDB;
         } else {
            LOG.error("Could not get Ranger Roles from database ...");
         }
      } else {
         if (LOG.isDebugEnabled()) {
            LOG.debug("Could not get lock in [" + waitTimeInSeconds + "] seconds, returning cached RangerRoles");
         }
         ret = getRoles();
      }
   } catch (InterruptedException exception) {
      LOG.error("RangerRoleCache.getLatestRangerRoles:lock got interrupted..", exception);
   } finally {
      if (lockResult) {
         lock.unlock();
      }
   }

   if (LOG.isDebugEnabled()) {
      LOG.debug("<== RangerRoleCache.getLatestRangerRoles(ServiceName= " + serviceName + " lastKnownRoleVersion= " + lastKnownRoleVersion + " rolesVersionInDB= " + rolesVersionInDB + " RangerRoles= " + ret + ")");
   }

   return ret;
}


Diffs
-----

  security-admin/src/main/java/org/apache/ranger/common/RangerRoleCache.java d71e97034 


Diff: https://reviews.apache.org/r/74106/diff/1/


Testing
-------

Tested the below Rest API's to make sure everything works fine
1.GET /service/roles/download/{serviceName}  

2.GET /service/roles/secure/download/{serviceName}


Thanks,

Ramachandran Krishnan