/** SHOW CURRENT ROLE */
 @Test
 public void testShowCurrentRole() throws Exception {
   DDLWork work = analyze(parse("SHOW CURRENT ROLES"));
   RoleDDLDesc roleDDLDesc = work.getRoleDDLDesc();
   Assert.assertEquals(PrincipalType.USER, roleDDLDesc.getPrincipalType());
   Assert.assertEquals(RoleOperation.SHOW_CURRENT_ROLE, roleDDLDesc.getOperation());
 }
 /** CREATE ROLE ... */
 @Test
 public void testCreateRole() throws Exception {
   DDLWork work = analyze(parse("CREATE ROLE " + ROLE));
   RoleDDLDesc roleDesc = work.getRoleDDLDesc();
   Assert.assertNotNull("Role should not be null", roleDesc);
   Assert.assertEquals(RoleOperation.CREATE_ROLE, roleDesc.getOperation());
   Assert.assertFalse("Did not expect a group", roleDesc.getGroup());
   Assert.assertEquals(ROLE, roleDesc.getName());
 }
 /** SHOW ROLE GRANT GROUP ... */
 @Test
 public void testShowRoleGrantGroup() throws Exception {
   DDLWork work = analyze(parse("SHOW ROLE GRANT GROUP " + GROUP));
   RoleDDLDesc roleDesc = work.getRoleDDLDesc();
   Assert.assertNotNull("Role should not be null", roleDesc);
   Assert.assertEquals(RoleOperation.SHOW_ROLE_GRANT, roleDesc.getOperation());
   Assert.assertEquals(PrincipalType.GROUP, roleDesc.getPrincipalType());
   Assert.assertEquals(GROUP, roleDesc.getName());
 }
 /** SHOW GRANT ROLE ... ON TABLE ... */
 @Test
 public void testShowGrantRoleOnTable() throws Exception {
   DDLWork work = analyze(parse("SHOW GRANT ROLE " + ROLE + " ON TABLE " + TABLE));
   ShowGrantDesc grantDesc = work.getShowGrantDesc();
   Assert.assertNotNull("Show grant should not be null", grantDesc);
   Assert.assertEquals(PrincipalType.ROLE, grantDesc.getPrincipalDesc().getType());
   Assert.assertEquals(ROLE, grantDesc.getPrincipalDesc().getName());
   Assert.assertTrue("Expected table", grantDesc.getHiveObj().getTable());
   Assert.assertEquals(TABLE, grantDesc.getHiveObj().getObject());
   Assert.assertTrue("Expected table", grantDesc.getHiveObj().getTable());
 }
 /** REVOKE ... ON TABLE ... FROM ROLE ... */
 @Test
 public void testRevokeRoleTable() throws Exception {
   DDLWork work = analyze(parse("REVOKE " + ALL + " ON TABLE " + TABLE + " FROM ROLE " + ROLE));
   RevokeDesc grantDesc = work.getRevokeDesc();
   Assert.assertNotNull("Revoke should not be null", grantDesc);
   for (PrincipalDesc principal : assertSize(1, grantDesc.getPrincipals())) {
     Assert.assertEquals(PrincipalType.ROLE, principal.getType());
     Assert.assertEquals(ROLE, principal.getName());
   }
   for (PrivilegeDesc privilege : assertSize(1, grantDesc.getPrivileges())) {
     Assert.assertEquals(Privilege.ALL, privilege.getPrivilege());
   }
   Assert.assertTrue("Expected table", grantDesc.getPrivilegeSubjectDesc().getTable());
   Assert.assertEquals(TABLE, grantDesc.getPrivilegeSubjectDesc().getObject());
 }
 /** REVOKE ROLE ... FROM GROUP ... */
 @Test
 public void testRevokeRoleGroup() throws Exception {
   DDLWork work = analyze(parse("REVOKE ROLE " + ROLE + " FROM GROUP " + GROUP));
   GrantRevokeRoleDDL grantDesc = work.getGrantRevokeRoleDDL();
   Assert.assertNotNull("Grant should not be null", grantDesc);
   Assert.assertFalse("Did not expect grant ", grantDesc.getGrant());
   Assert.assertFalse("Grant option is always true ", grantDesc.isGrantOption());
   Assert.assertEquals(currentUser, grantDesc.getGrantor());
   Assert.assertEquals(PrincipalType.USER, grantDesc.getGrantorType());
   for (String role : assertSize(1, grantDesc.getRoles())) {
     Assert.assertEquals(ROLE, role);
   }
   for (PrincipalDesc principal : assertSize(1, grantDesc.getPrincipalDesc())) {
     Assert.assertEquals(PrincipalType.GROUP, principal.getType());
     Assert.assertEquals(GROUP, principal.getName());
   }
 }
 /** GRANT ... ON TABLE ... TO ROLE ... WITH GRANT OPTION */
 @Test
 public void testGrantRoleTableWithGrantOption() throws Exception {
   DDLWork work =
       analyze(
           parse(
               "GRANT " + ALL + " ON TABLE " + TABLE + " TO ROLE " + ROLE + " WITH GRANT OPTION"));
   GrantDesc grantDesc = work.getGrantDesc();
   Assert.assertNotNull("Grant should not be null", grantDesc);
   for (PrincipalDesc principal : assertSize(1, grantDesc.getPrincipals())) {
     Assert.assertEquals(PrincipalType.ROLE, principal.getType());
     Assert.assertEquals(ROLE, principal.getName());
   }
   for (PrivilegeDesc privilege : assertSize(1, grantDesc.getPrivileges())) {
     Assert.assertEquals(Privilege.ALL, privilege.getPrivilege());
   }
   Assert.assertTrue("Expected table", grantDesc.getPrivilegeSubjectDesc().getTable());
   Assert.assertTrue("Expected grantOption is true", grantDesc.isGrantOption());
   Assert.assertEquals(TABLE, grantDesc.getPrivilegeSubjectDesc().getObject());
 }
 /** SHOW ROLES */
 @Test
 public void testShowRoles() throws Exception {
   DDLWork work = analyze(parse("SHOW ROLES"));
   RoleDDLDesc roleDDLDesc = work.getRoleDDLDesc();
   Assert.assertEquals(RoleOperation.SHOW_ROLES, roleDDLDesc.getOperation());
 }
  @Override
  protected void authorizeDDLWork(HiveSemanticAnalyzerHookContext cntxt, Hive hive, DDLWork work)
      throws HiveException {
    // DB opereations, none of them are enforced by Hive right now.

    ShowDatabasesDesc showDatabases = work.getShowDatabasesDesc();
    if (showDatabases != null) {
      authorize(
          HiveOperation.SHOWDATABASES.getInputRequiredPrivileges(),
          HiveOperation.SHOWDATABASES.getOutputRequiredPrivileges());
    }

    DropDatabaseDesc dropDb = work.getDropDatabaseDesc();
    if (dropDb != null) {
      Database db = cntxt.getHive().getDatabase(dropDb.getDatabaseName());
      authorize(db, Privilege.DROP);
    }

    DescDatabaseDesc descDb = work.getDescDatabaseDesc();
    if (descDb != null) {
      Database db = cntxt.getHive().getDatabase(descDb.getDatabaseName());
      authorize(db, Privilege.SELECT);
    }

    SwitchDatabaseDesc switchDb = work.getSwitchDatabaseDesc();
    if (switchDb != null) {
      Database db = cntxt.getHive().getDatabase(switchDb.getDatabaseName());
      authorize(db, Privilege.SELECT);
    }

    ShowTablesDesc showTables = work.getShowTblsDesc();
    if (showTables != null) {
      String dbName =
          showTables.getDbName() == null
              ? SessionState.get().getCurrentDatabase()
              : showTables.getDbName();
      authorize(cntxt.getHive().getDatabase(dbName), Privilege.SELECT);
    }

    ShowTableStatusDesc showTableStatus = work.getShowTblStatusDesc();
    if (showTableStatus != null) {
      String dbName =
          showTableStatus.getDbName() == null
              ? SessionState.get().getCurrentDatabase()
              : showTableStatus.getDbName();
      authorize(cntxt.getHive().getDatabase(dbName), Privilege.SELECT);
    }

    // TODO: add alter database support in HCat

    // Table operations.

    DropTableDesc dropTable = work.getDropTblDesc();
    if (dropTable != null) {
      if (dropTable.getPartSpecs() == null) {
        // drop table is already enforced by Hive. We only check for table level location even if
        // the
        // table is partitioned.
      } else {
        // this is actually a ALTER TABLE DROP PARITITION statement
        for (DropTableDesc.PartSpec partSpec : dropTable.getPartSpecs()) {
          // partitions are not added as write entries in drop partitions in Hive
          Table table =
              hive.getTable(SessionState.get().getCurrentDatabase(), dropTable.getTableName());
          List<Partition> partitions = null;
          try {
            partitions = hive.getPartitionsByFilter(table, partSpec.getPartSpec().getExprString());
          } catch (Exception e) {
            throw new HiveException(e);
          }

          for (Partition part : partitions) {
            authorize(part, Privilege.DROP);
          }
        }
      }
    }

    AlterTableDesc alterTable = work.getAlterTblDesc();
    if (alterTable != null) {
      Table table =
          hive.getTable(SessionState.get().getCurrentDatabase(), alterTable.getOldName(), false);

      Partition part = null;
      if (alterTable.getPartSpec() != null) {
        part = hive.getPartition(table, alterTable.getPartSpec(), false);
      }

      String newLocation = alterTable.getNewLocation();

      /* Hcat requires ALTER_DATA privileges for ALTER TABLE LOCATION statements
       * for the old table/partition location and the new location.
       */
      if (alterTable.getOp() == AlterTableDesc.AlterTableTypes.ALTERLOCATION) {
        if (part != null) {
          authorize(part, Privilege.ALTER_DATA); // authorize for the old
          // location, and new location
          part.setLocation(newLocation);
          authorize(part, Privilege.ALTER_DATA);
        } else {
          authorize(table, Privilege.ALTER_DATA); // authorize for the old
          // location, and new location
          table.getTTable().getSd().setLocation(newLocation);
          authorize(table, Privilege.ALTER_DATA);
        }
      }
      // other alter operations are already supported by Hive
    }

    // we should be careful when authorizing table based on just the
    // table name. If columns have separate authorization domain, it
    // must be honored
    DescTableDesc descTable = work.getDescTblDesc();
    if (descTable != null) {
      String tableName = extractTableName(descTable.getTableName());
      authorizeTable(cntxt.getHive(), tableName, Privilege.SELECT);
    }

    ShowPartitionsDesc showParts = work.getShowPartsDesc();
    if (showParts != null) {
      String tableName = extractTableName(showParts.getTabName());
      authorizeTable(cntxt.getHive(), tableName, Privilege.SELECT);
    }
  }