Uploaded image for project: 'HBase'
  1. HBase
  2. HBASE-22503

Failed to upgrade to 2.2+ as the global permission which storaged in zk is not right

    XMLWordPrintableJSON

Details

    • Bug
    • Status: Resolved
    • Blocker
    • Resolution: Fixed
    • 2.2.0
    • 3.0.0-alpha-1, 2.2.0, 2.3.0
    • None
    • None

    Description

      Before 2.2, the global permission which storaged in zk is not right. It was storaged as a table permission. After HBASE-21255, 2.2+ will read it as a global permission and will throw a cast error.

       

      Caused by: java.lang.ClassCastException: org.apache.hadoop.hbase.security.access.TablePermission cannot be cast to org.apache.hadoop.hbase.security.access.GlobalPermission
      at org.apache.hadoop.hbase.security.access.AuthManager.updateGlobalCache(AuthManager.java:171)
      at org.apache.hadoop.hbase.security.access.AuthManager.refreshTableCacheFromWritable(AuthManager.java:129)
      at org.apache.hadoop.hbase.security.access.ZKPermissionWatcher.refreshAuthManager(ZKPermissionWatcher.java:252)
      at org.apache.hadoop.hbase.security.access.ZKPermissionWatcher.refreshNodes(ZKPermissionWatcher.java:235)
      

       

      Before 2.2, the acl update logic is complicated. Client sent the grant/revoke rpc call to AccessControl coprocessor directly. And only the RS which has acl region will put a acl record to hbase:acl table. And the AccessControl override postPut/postDelete method, too. It will update zk when postPut/postDelete found this is a put/delete for acl region...And there is a TODO "global entry should be handled differently". The global entry was handled as a table permission, too.

       

      private static Pair<String, TablePermission> parsePermissionRecord(
          byte[] entryName, Cell kv) {
        // return X given a set of permissions encoded in the permissionRecord kv.
        byte[] family = CellUtil.cloneFamily(kv);
      
        if (!Bytes.equals(family, ACL_LIST_FAMILY)) {
          return null;
        }
      
        byte[] key = CellUtil.cloneQualifier(kv);
        byte[] value = CellUtil.cloneValue(kv);
        if (LOG.isDebugEnabled()) {
          LOG.debug("Read acl: kv ["+
              Bytes.toStringBinary(key)+": "+
              Bytes.toStringBinary(value)+"]");
        }
      
        // check for a column family appended to the key
        // TODO: avoid the string conversion to make this more efficient
        String username = Bytes.toString(key);
      
        //Handle namespace entry
        if(isNamespaceEntry(entryName)) {
          return new Pair<>(username, new TablePermission(Bytes.toString(fromNamespaceEntry(entryName)), value));
        }
      
        //Handle table and global entry
        //TODO global entry should be handled differently
        int idx = username.indexOf(ACL_KEY_DELIMITER);
        byte[] permFamily = null;
        byte[] permQualifier = null;
        if (idx > 0 && idx < username.length()-1) {
          String remainder = username.substring(idx+1);
          username = username.substring(0, idx);
          idx = remainder.indexOf(ACL_KEY_DELIMITER);
          if (idx > 0 && idx < remainder.length()-1) {
            permFamily = Bytes.toBytes(remainder.substring(0, idx));
            permQualifier = Bytes.toBytes(remainder.substring(idx+1));
          } else {
            permFamily = Bytes.toBytes(remainder);
          }
        }
      
        return new Pair<>(username, new TablePermission(TableName.valueOf(entryName), permFamily, permQualifier, value));
      }
      

       

       

      Attachments

        Issue Links

          Activity

            People

              zghao Guanghao Zhang
              zghao Guanghao Zhang
              Votes:
              0 Vote for this issue
              Watchers:
              2 Start watching this issue

              Dates

                Created:
                Updated:
                Resolved: