예제 #1
0
  /**
   * Returns a new {@code PermissionCache} initialized with permission assignments from the {@code
   * hbase.superuser} configuration key.
   */
  private PermissionCache<Permission> initGlobal(Configuration conf) throws IOException {
    UserProvider userProvider = UserProvider.instantiate(conf);
    User user = userProvider.getCurrent();
    if (user == null) {
      throw new IOException(
          "Unable to obtain the current user, "
              + "authorization checks for internal operations will not work correctly!");
    }
    PermissionCache<Permission> newCache = new PermissionCache<Permission>();
    String currentUser = user.getShortName();

    // the system user is always included
    List<String> superusers =
        Lists.asList(
            currentUser, conf.getStrings(AccessControlLists.SUPERUSER_CONF_KEY, new String[0]));
    if (superusers != null) {
      for (String name : superusers) {
        if (AccessControlLists.isGroupPrincipal(name)) {
          newCache.putGroup(
              AccessControlLists.getGroupName(name), new Permission(Permission.Action.values()));
        } else {
          newCache.putUser(name, new Permission(Permission.Action.values()));
        }
      }
    }
    return newCache;
  }
예제 #2
0
  public boolean matchPermission(
      User user, byte[] table, byte[] family, byte[] qualifier, TablePermission.Action action) {
    PermissionCache<TablePermission> tablePerms = tableCache.get(table);
    if (tablePerms != null) {
      List<TablePermission> userPerms = tablePerms.getUser(user.getShortName());
      if (userPerms != null) {
        for (TablePermission p : userPerms) {
          if (p.matchesFamilyQualifier(table, family, qualifier, action)) {
            return true;
          }
        }
      }

      String[] groups = user.getGroupNames();
      if (groups != null) {
        for (String group : groups) {
          List<TablePermission> groupPerms = tablePerms.getGroup(group);
          if (groupPerms != null) {
            for (TablePermission p : groupPerms) {
              if (p.matchesFamilyQualifier(table, family, qualifier, action)) {
                return true;
              }
            }
          }
        }
      }
    }

    return false;
  }
예제 #3
0
 private Path createStagingDir(Path baseDir, User user, TableName tableName) throws IOException {
   String tblName = tableName.getNameAsString().replace(":", "_");
   String randomDir =
       user.getShortName()
           + "__"
           + tblName
           + "__"
           + (new BigInteger(RANDOM_WIDTH, random).toString(RANDOM_RADIX));
   return createStagingDir(baseDir, user, randomDir);
 }
 @Test
 public void testCreateWithCorrectOwner() throws Exception {
   // Create a test user
   final User testUser =
       User.createUserForTesting(TEST_UTIL.getConfiguration(), "TestUser", new String[0]);
   // Grant the test user the ability to create tables
   SecureTestUtil.grantGlobal(TEST_UTIL, testUser.getShortName(), Action.CREATE);
   verifyAllowed(
       new AccessTestAction() {
         @Override
         public Object run() throws Exception {
           HTableDescriptor desc = new HTableDescriptor(TEST_TABLE.getTableName());
           desc.addFamily(new HColumnDescriptor(TEST_FAMILY));
           try (Connection connection =
               ConnectionFactory.createConnection(TEST_UTIL.getConfiguration(), testUser)) {
             try (Admin admin = connection.getAdmin()) {
               admin.createTable(desc);
             }
           }
           return null;
         }
       },
       testUser);
   TEST_UTIL.waitTableEnabled(TEST_TABLE.getTableName());
   // Verify that owner permissions have been granted to the test user on the
   // table just created
   List<TablePermission> perms =
       AccessControlLists.getTablePermissions(conf, TEST_TABLE.getTableName())
           .get(testUser.getShortName());
   assertNotNull(perms);
   assertFalse(perms.isEmpty());
   // Should be RWXCA
   assertTrue(perms.get(0).implies(Permission.Action.READ));
   assertTrue(perms.get(0).implies(Permission.Action.WRITE));
   assertTrue(perms.get(0).implies(Permission.Action.EXEC));
   assertTrue(perms.get(0).implies(Permission.Action.CREATE));
   assertTrue(perms.get(0).implies(Permission.Action.ADMIN));
 }
예제 #5
0
  private User getActiveUser() {
    User user = RequestContext.getRequestUser();
    if (!RequestContext.isInRequestContext()) {
      return null;
    }

    // this is for testing
    if (userProvider.isHadoopSecurityEnabled()
        && "simple".equalsIgnoreCase(conf.get(User.HBASE_SECURITY_CONF_KEY))) {
      return User.createUserForTesting(conf, user.getShortName(), new String[] {});
    }

    return user;
  }
예제 #6
0
  public boolean authorize(
      User user, byte[] table, byte[] family, byte[] qualifier, Permission.Action action) {
    if (authorizeUser(user.getShortName(), table, family, qualifier, action)) {
      return true;
    }

    String[] groups = user.getGroupNames();
    if (groups != null) {
      for (String group : groups) {
        if (authorizeGroup(group, table, family, action)) {
          return true;
        }
      }
    }
    return false;
  }
예제 #7
0
 @Override
 public void whoAmI(
     RpcController controller,
     AuthenticationProtos.WhoAmIRequest request,
     RpcCallback<AuthenticationProtos.WhoAmIResponse> done) {
   User requestUser = RequestContext.getRequestUser();
   AuthenticationProtos.WhoAmIResponse.Builder response =
       AuthenticationProtos.WhoAmIResponse.newBuilder();
   if (requestUser != null) {
     response.setUsername(requestUser.getShortName());
     AuthenticationMethod method = requestUser.getUGI().getAuthenticationMethod();
     if (method != null) {
       response.setAuthMethod(method.name());
     }
   }
   done.run(response.build());
 }
예제 #8
0
  /**
   * Authorize a global permission based on ACLs for the given user and the user's groups.
   *
   * @param user
   * @param action
   * @return
   */
  public boolean authorize(User user, Permission.Action action) {
    if (user == null) {
      return false;
    }

    if (authorize(globalCache.getUser(user.getShortName()), action)) {
      return true;
    }

    String[] groups = user.getGroupNames();
    if (groups != null) {
      for (String group : groups) {
        if (authorize(globalCache.getGroup(group), action)) {
          return true;
        }
      }
    }
    return false;
  }
예제 #9
0
  public boolean authorize(User user, byte[] table, KeyValue kv, TablePermission.Action action) {
    PermissionCache<TablePermission> tablePerms = tableCache.get(table);
    if (tablePerms != null) {
      List<TablePermission> userPerms = tablePerms.getUser(user.getShortName());
      if (authorize(userPerms, table, kv, action)) {
        return true;
      }

      String[] groupNames = user.getGroupNames();
      if (groupNames != null) {
        for (String group : groupNames) {
          List<TablePermission> groupPerms = tablePerms.getGroup(group);
          if (authorize(groupPerms, table, kv, action)) {
            return true;
          }
        }
      }
    }

    return false;
  }
예제 #10
0
  /**
   * Take a snapshot based on the enabled/disabled state of the table.
   *
   * @param snapshot
   * @throws HBaseSnapshotException when a snapshot specific exception occurs.
   * @throws IOException when some sort of generic IO exception occurs.
   */
  public void takeSnapshot(SnapshotDescription snapshot) throws IOException {
    // check to see if we already completed the snapshot
    if (isSnapshotCompleted(snapshot)) {
      throw new SnapshotExistsException(
          "Snapshot '" + snapshot.getName() + "' already stored on the filesystem.",
          ProtobufUtil.createSnapshotDesc(snapshot));
    }

    LOG.debug("No existing snapshot, attempting snapshot...");

    // stop tracking "abandoned" handlers
    cleanupSentinels();

    // check to see if the table exists
    HTableDescriptor desc = null;
    try {
      desc = master.getTableDescriptors().get(TableName.valueOf(snapshot.getTable()));
    } catch (FileNotFoundException e) {
      String msg = "Table:" + snapshot.getTable() + " info doesn't exist!";
      LOG.error(msg);
      throw new SnapshotCreationException(msg, e, ProtobufUtil.createSnapshotDesc(snapshot));
    } catch (IOException e) {
      throw new SnapshotCreationException(
          "Error while geting table description for table " + snapshot.getTable(),
          e,
          ProtobufUtil.createSnapshotDesc(snapshot));
    }
    if (desc == null) {
      throw new SnapshotCreationException(
          "Table '" + snapshot.getTable() + "' doesn't exist, can't take snapshot.",
          ProtobufUtil.createSnapshotDesc(snapshot));
    }
    SnapshotDescription.Builder builder = snapshot.toBuilder();
    // if not specified, set the snapshot format
    if (!snapshot.hasVersion()) {
      builder.setVersion(SnapshotDescriptionUtils.SNAPSHOT_LAYOUT_VERSION);
    }
    User user = RpcServer.getRequestUser();
    if (User.isHBaseSecurityEnabled(master.getConfiguration()) && user != null) {
      builder.setOwner(user.getShortName());
    }
    snapshot = builder.build();

    // call pre coproc hook
    MasterCoprocessorHost cpHost = master.getMasterCoprocessorHost();
    if (cpHost != null) {
      cpHost.preSnapshot(snapshot, desc);
    }

    // if the table is enabled, then have the RS run actually the snapshot work
    TableName snapshotTable = TableName.valueOf(snapshot.getTable());
    if (master.getTableStateManager().isTableState(snapshotTable, TableState.State.ENABLED)) {
      LOG.debug("Table enabled, starting distributed snapshot.");
      snapshotEnabledTable(snapshot);
      LOG.debug("Started snapshot: " + ClientSnapshotDescriptionUtils.toString(snapshot));
    }
    // For disabled table, snapshot is created by the master
    else if (master.getTableStateManager().isTableState(snapshotTable, TableState.State.DISABLED)) {
      LOG.debug("Table is disabled, running snapshot entirely on master.");
      snapshotDisabledTable(snapshot);
      LOG.debug("Started snapshot: " + ClientSnapshotDescriptionUtils.toString(snapshot));
    } else {
      LOG.error(
          "Can't snapshot table '"
              + snapshot.getTable()
              + "', isn't open or closed, we don't know what to do!");
      TablePartiallyOpenException tpoe =
          new TablePartiallyOpenException(snapshot.getTable() + " isn't fully open.");
      throw new SnapshotCreationException(
          "Table is not entirely open or closed", tpoe, ProtobufUtil.createSnapshotDesc(snapshot));
    }

    // call post coproc hook
    if (cpHost != null) {
      cpHost.postSnapshot(snapshot, desc);
    }
  }
예제 #11
0
  @BeforeClass
  public static void beforeClass() throws Exception {
    conf = UTIL.getConfiguration();
    enableSecurity(conf);

    SUPERUSER = User.createUserForTesting(conf, "admin", new String[] {"supergroup"});
    // Users with global permissions
    USER_GLOBAL_ADMIN = User.createUserForTesting(conf, "global_admin", new String[0]);
    USER_GLOBAL_CREATE = User.createUserForTesting(conf, "global_create", new String[0]);
    USER_GLOBAL_WRITE = User.createUserForTesting(conf, "global_write", new String[0]);
    USER_GLOBAL_READ = User.createUserForTesting(conf, "global_read", new String[0]);
    USER_GLOBAL_EXEC = User.createUserForTesting(conf, "global_exec", new String[0]);

    USER_NS_ADMIN = User.createUserForTesting(conf, "namespace_admin", new String[0]);
    USER_NS_CREATE = User.createUserForTesting(conf, "namespace_create", new String[0]);
    USER_NS_WRITE = User.createUserForTesting(conf, "namespace_write", new String[0]);
    USER_NS_READ = User.createUserForTesting(conf, "namespace_read", new String[0]);
    USER_NS_EXEC = User.createUserForTesting(conf, "namespace_exec", new String[0]);

    USER_TABLE_CREATE = User.createUserForTesting(conf, "table_create", new String[0]);
    USER_TABLE_WRITE = User.createUserForTesting(conf, "table_write", new String[0]);

    USER_GROUP_ADMIN =
        User.createUserForTesting(conf, "user_group_admin", new String[] {GROUP_ADMIN});
    USER_GROUP_NS_ADMIN =
        User.createUserForTesting(conf, "user_group_ns_admin", new String[] {GROUP_NS_ADMIN});
    USER_GROUP_CREATE =
        User.createUserForTesting(conf, "user_group_create", new String[] {GROUP_CREATE});
    USER_GROUP_READ = User.createUserForTesting(conf, "user_group_read", new String[] {GROUP_READ});
    USER_GROUP_WRITE =
        User.createUserForTesting(conf, "user_group_write", new String[] {GROUP_WRITE});
    // TODO: other table perms

    UTIL.startMiniCluster();
    // Wait for the ACL table to become available
    UTIL.waitTableAvailable(AccessControlLists.ACL_TABLE_NAME.getName(), 30 * 1000);

    ACCESS_CONTROLLER =
        (AccessController)
            UTIL.getMiniHBaseCluster()
                .getMaster()
                .getRegionServerCoprocessorHost()
                .findCoprocessor(AccessController.class.getName());

    UTIL.getHBaseAdmin().createNamespace(NamespaceDescriptor.create(TEST_NAMESPACE).build());
    UTIL.getHBaseAdmin().createNamespace(NamespaceDescriptor.create(TEST_NAMESPACE2).build());

    // grants on global
    grantGlobal(UTIL, USER_GLOBAL_ADMIN.getShortName(), Permission.Action.ADMIN);
    grantGlobal(UTIL, USER_GLOBAL_CREATE.getShortName(), Permission.Action.CREATE);
    grantGlobal(UTIL, USER_GLOBAL_WRITE.getShortName(), Permission.Action.WRITE);
    grantGlobal(UTIL, USER_GLOBAL_READ.getShortName(), Permission.Action.READ);
    grantGlobal(UTIL, USER_GLOBAL_EXEC.getShortName(), Permission.Action.EXEC);

    // grants on namespace
    grantOnNamespace(UTIL, USER_NS_ADMIN.getShortName(), TEST_NAMESPACE, Permission.Action.ADMIN);
    grantOnNamespace(UTIL, USER_NS_CREATE.getShortName(), TEST_NAMESPACE, Permission.Action.CREATE);
    grantOnNamespace(UTIL, USER_NS_WRITE.getShortName(), TEST_NAMESPACE, Permission.Action.WRITE);
    grantOnNamespace(UTIL, USER_NS_READ.getShortName(), TEST_NAMESPACE, Permission.Action.READ);
    grantOnNamespace(UTIL, USER_NS_EXEC.getShortName(), TEST_NAMESPACE, Permission.Action.EXEC);
    grantOnNamespace(UTIL, toGroupEntry(GROUP_NS_ADMIN), TEST_NAMESPACE, Permission.Action.ADMIN);

    grantOnNamespace(UTIL, USER_NS_ADMIN.getShortName(), TEST_NAMESPACE2, Permission.Action.ADMIN);

    grantGlobal(UTIL, toGroupEntry(GROUP_ADMIN), Permission.Action.ADMIN);
    grantGlobal(UTIL, toGroupEntry(GROUP_CREATE), Permission.Action.CREATE);
    grantGlobal(UTIL, toGroupEntry(GROUP_READ), Permission.Action.READ);
    grantGlobal(UTIL, toGroupEntry(GROUP_WRITE), Permission.Action.WRITE);
  }
  @Test
  public void testACLTableAccess() throws Exception {
    final Configuration conf = TEST_UTIL.getConfiguration();

    // Superuser
    User superUser = User.createUserForTesting(conf, "admin", new String[] {"supergroup"});

    // Global users
    User globalRead = User.createUserForTesting(conf, "globalRead", new String[0]);
    User globalWrite = User.createUserForTesting(conf, "globalWrite", new String[0]);
    User globalCreate = User.createUserForTesting(conf, "globalCreate", new String[0]);
    User globalAdmin = User.createUserForTesting(conf, "globalAdmin", new String[0]);
    SecureTestUtil.grantGlobal(TEST_UTIL, globalRead.getShortName(), Action.READ);
    SecureTestUtil.grantGlobal(TEST_UTIL, globalWrite.getShortName(), Action.WRITE);
    SecureTestUtil.grantGlobal(TEST_UTIL, globalCreate.getShortName(), Action.CREATE);
    SecureTestUtil.grantGlobal(TEST_UTIL, globalAdmin.getShortName(), Action.ADMIN);

    // Namespace users
    User nsRead = User.createUserForTesting(conf, "nsRead", new String[0]);
    User nsWrite = User.createUserForTesting(conf, "nsWrite", new String[0]);
    User nsCreate = User.createUserForTesting(conf, "nsCreate", new String[0]);
    User nsAdmin = User.createUserForTesting(conf, "nsAdmin", new String[0]);
    SecureTestUtil.grantOnNamespace(
        TEST_UTIL,
        nsRead.getShortName(),
        TEST_TABLE.getTableName().getNamespaceAsString(),
        Action.READ);
    SecureTestUtil.grantOnNamespace(
        TEST_UTIL,
        nsWrite.getShortName(),
        TEST_TABLE.getTableName().getNamespaceAsString(),
        Action.WRITE);
    SecureTestUtil.grantOnNamespace(
        TEST_UTIL,
        nsCreate.getShortName(),
        TEST_TABLE.getTableName().getNamespaceAsString(),
        Action.CREATE);
    SecureTestUtil.grantOnNamespace(
        TEST_UTIL,
        nsAdmin.getShortName(),
        TEST_TABLE.getTableName().getNamespaceAsString(),
        Action.ADMIN);

    // Table users
    User tableRead = User.createUserForTesting(conf, "tableRead", new String[0]);
    User tableWrite = User.createUserForTesting(conf, "tableWrite", new String[0]);
    User tableCreate = User.createUserForTesting(conf, "tableCreate", new String[0]);
    User tableAdmin = User.createUserForTesting(conf, "tableAdmin", new String[0]);
    SecureTestUtil.grantOnTable(
        TEST_UTIL, tableRead.getShortName(), TEST_TABLE.getTableName(), null, null, Action.READ);
    SecureTestUtil.grantOnTable(
        TEST_UTIL, tableWrite.getShortName(), TEST_TABLE.getTableName(), null, null, Action.WRITE);
    SecureTestUtil.grantOnTable(
        TEST_UTIL,
        tableCreate.getShortName(),
        TEST_TABLE.getTableName(),
        null,
        null,
        Action.CREATE);
    SecureTestUtil.grantOnTable(
        TEST_UTIL, tableAdmin.getShortName(), TEST_TABLE.getTableName(), null, null, Action.ADMIN);

    // Write tests

    AccessTestAction writeAction =
        new AccessTestAction() {
          @Override
          public Object run() throws Exception {
            try (Connection conn = ConnectionFactory.createConnection(conf);
                Table t = conn.getTable(AccessControlLists.ACL_TABLE_NAME)) {
              t.put(
                  new Put(TEST_ROW)
                      .add(AccessControlLists.ACL_LIST_FAMILY, TEST_QUALIFIER, TEST_VALUE));
              return null;
            } finally {
            }
          }
        };

    // All writes to ACL table denied except for GLOBAL WRITE permission and superuser

    verifyDenied(writeAction, globalAdmin, globalCreate, globalRead);
    verifyDenied(writeAction, nsAdmin, nsCreate, nsRead, nsWrite);
    verifyDenied(writeAction, tableAdmin, tableCreate, tableRead, tableWrite);
    verifyAllowed(writeAction, superUser, globalWrite);

    // Read tests

    AccessTestAction scanAction =
        new AccessTestAction() {
          @Override
          public Object run() throws Exception {
            try (Connection conn = ConnectionFactory.createConnection(conf);
                Table t = conn.getTable(AccessControlLists.ACL_TABLE_NAME)) {
              ResultScanner s = t.getScanner(new Scan());
              try {
                for (Result r = s.next(); r != null; r = s.next()) {
                  // do nothing
                }
              } finally {
                s.close();
              }
              return null;
            }
          }
        };

    // All reads from ACL table denied except for GLOBAL READ and superuser

    verifyDenied(scanAction, globalAdmin, globalCreate, globalWrite);
    verifyDenied(scanAction, nsCreate, nsAdmin, nsRead, nsWrite);
    verifyDenied(scanAction, tableCreate, tableAdmin, tableRead, tableWrite);
    verifyAllowed(scanAction, superUser, globalRead);
  }