/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.apache.sentry.tests.e2e.hive;

import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.PrintStream;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Set;

import org.apache.sentry.binding.hive.authz.SentryConfigTool;
import org.apache.sentry.binding.hive.conf.HiveAuthzConf;
import org.apache.sentry.core.common.exception.SentryConfigurationException;
import org.apache.sentry.core.common.Subject;
import org.apache.sentry.core.common.utils.PolicyFile;
import org.junit.Before;
import org.junit.Test;

public class TestConfigTool extends AbstractTestWithStaticConfiguration {
  private static final String DB2_POLICY_FILE = "db2-policy-file.ini";
  private static String prefix;

  private PolicyFile policyFile;
  private SentryConfigTool configTool;

  @Before
  public void setup() throws Exception {
    policyFile = PolicyFile.setAdminOnServer1(ADMINGROUP);
    configTool = new SentryConfigTool();
    String hiveServer2 = System.getProperty("sentry.e2etest.hiveServer2Type",
        "InternalHiveServer2");
    String policyOnHDFS = System.getProperty(
        "sentry.e2etest.hive.policyOnHDFS", "true");
    if (policyOnHDFS.trim().equalsIgnoreCase("true")
        && (hiveServer2.equals("UnmanagedHiveServer2"))) {
      String policyLocation = System.getProperty(
          "sentry.e2etest.hive.policy.location", "/user/hive/sentry");
      prefix = "hdfs://" + policyLocation + "/";
    } else {
      prefix = "file://" + context.getPolicyFile().getParent() + "/";
    }

  }

  /**
   * Verify errors/warnings from malformed policy file
   * @throws Exception
   */
  @Test
  public void testInvalidPolicy() throws Exception {
    // policy file, missing insert_tab2 and select_tab3 role definition
    policyFile
        .addRolesToGroup(USERGROUP1, "select_tab1", "insert_tab2")
        .addRolesToGroup(USERGROUP2, "select_tab3")
        .addPermissionsToRole("select_tab1",
            "server=server1->db=db1->table=tab1->action=select")
        .setUserGroupMapping(StaticUserGroup.getStaticMapping());
    policyFile.write(context.getPolicyFile());

    configTool.setPolicyFile(context.getPolicyFile().getPath());
    configTool.setupConfig();
    try {
      configTool.getSentryProvider().validateResource(true);
      fail("Policy validation should fail for malformed policy");
    } catch (SentryConfigurationException e) {
      assertTrue(e
          .getConfigWarnings()
          .get(0)
          .contains(
              "Role select_tab3 for group " + USERGROUP2 + " does not exist"));
      assertTrue(e
          .getConfigWarnings()
          .get(1)
          .contains(
              "Role insert_tab2 for group " + USERGROUP1 + " does not exist"));
    }
  }

  /**
   * Verify errors/warnings from malformed policy file with per-DB policy
   * @throws Exception
   */
  @Test
  public void testInvalidPerDbPolicy() throws Exception {
    PolicyFile db2PolicyFile = new PolicyFile();
    File db2PolicyFileHandle = new File(context.getPolicyFile().getParent(),
        DB2_POLICY_FILE);
    // invalid db2 policy file with missing roles
    db2PolicyFile
        .addRolesToGroup(USERGROUP2, "select_tbl2", "insert_db2_tab2")
        .addPermissionsToRole("select_tbl2",
            "server=server1->db=db2->table=tbl2->action=select")
        .write(db2PolicyFileHandle);

    policyFile
        .addRolesToGroup(USERGROUP1, "select_tbl1")
        .addRolesToGroup(USERGROUP2, "select_tbl3")
        .addPermissionsToRole("select_tbl1",
            "server=server1->db=db1->table=tbl1->action=select")
        .addDatabase("db2", prefix + db2PolicyFileHandle.getName())
        .setUserGroupMapping(StaticUserGroup.getStaticMapping())
        .write(context.getPolicyFile());

    configTool.setPolicyFile(context.getPolicyFile().getPath());
    configTool.setupConfig();
    try {
      configTool.getSentryProvider().validateResource(true);
      fail("Policy validation should fail for malformed policy");
    } catch (SentryConfigurationException e) {
      assertTrue(e
          .getConfigWarnings()
          .get(0)
          .contains(
              "Role select_tbl3 for group " + USERGROUP2 + " does not exist"));
      assertTrue(e.getConfigWarnings().get(0)
          .contains(context.getPolicyFile().getName()));
      assertTrue(e
          .getConfigWarnings()
          .get(1)
          .contains(
              "Role insert_db2_tab2 for group " + USERGROUP2
                  + " does not exist"));
      assertTrue(e.getConfigWarnings().get(1)
          .contains(db2PolicyFileHandle.getName()));
    }
  }

  /**
   * Validate user permissions listing
   * @throws Exception
   */
  @Test
  public void testUserPermissions() throws Exception {
    policyFile
        .addRolesToGroup(USERGROUP1, "select_tab1", "insert_tab2")
        .addRolesToGroup(USERGROUP2, "select_tab3")
        .addRolesToGroup(USERGROUP3, "select_colA")
        .addRolesToGroup(USERGROUP4, "select_colAB")
        .addPermissionsToRole("select_tab1",
            "server=server1->db=db1->table=tab1->action=select")
        .addPermissionsToRole("insert_tab2",
            "server=server1->db=db1->table=tab2->action=insert")
        .addPermissionsToRole("select_tab3",
            "server=server1->db=db1->table=tab3->action=select")
        .addPermissionsToRole("select_colA",
            "server=server1->db=db1->table=tab3->column=a->action=select")
        .addPermissionsToRole("select_colAB",
            "server=server1->db=db1->table=tab3->column=a->action=select")
        .addPermissionsToRole("select_colAB",
            "server=server1->db=db1->table=tab3->column=b->action=select")
        .setUserGroupMapping(StaticUserGroup.getStaticMapping());
    policyFile.write(context.getPolicyFile());

    configTool.setPolicyFile(context.getPolicyFile().getPath());
    configTool.setupConfig();
    configTool.validatePolicy();

    Set<String> permList = configTool.getSentryProvider()
        .listPrivilegesForSubject(new Subject(USER1_1));
    assertTrue(permList
        .contains("server=server1->db=db1->table=tab1->action=select"));
    assertTrue(permList
        .contains("server=server1->db=db1->table=tab2->action=insert"));

    permList = configTool.getSentryProvider().listPrivilegesForSubject(
        new Subject(USER2_1));
    assertTrue(permList
        .contains("server=server1->db=db1->table=tab3->action=select"));

    permList = configTool.getSentryProvider().listPrivilegesForSubject(
        new Subject(USER3_1));
    assertTrue(permList
        .contains("server=server1->db=db1->table=tab3->column=a->action=select"));

    permList = configTool.getSentryProvider().listPrivilegesForSubject(
        new Subject(USER4_1));
    assertTrue(permList
        .contains("server=server1->db=db1->table=tab3->column=a->action=select"));
    assertTrue(permList
        .contains("server=server1->db=db1->table=tab3->column=b->action=select"));

    permList = configTool.getSentryProvider().listPrivilegesForSubject(
        new Subject(ADMIN1));
    assertTrue(permList.contains("server=server1"));
  }

  /***
   * Verify the mock compilation config setting forces query to abort
   * @throws Exception
   */
  @Test
  public void testMockCompilation() throws Exception {
    policyFile.setUserGroupMapping(StaticUserGroup.getStaticMapping());
    policyFile.write(context.getPolicyFile());
    // setup db objects needed by the test
    Connection connection = context.createConnection(ADMIN1);
    Statement statement = context.createStatement(connection);

    statement.execute("DROP TABLE IF EXISTS tab1");
    statement.execute("CREATE TABLE tab1(B INT, A STRING) "
        + " row format delimited fields terminated by '|'  stored as textfile");
    statement.execute("SELECT * FROM tab1");

    statement.execute("SET " + HiveAuthzConf.HIVE_SENTRY_MOCK_COMPILATION
        + "=true");
    try {
      statement.execute("SELECT * FROM tab1");
      fail("Query should fail with mock error config enabled");
    } catch (SQLException e) {
      assertTrue(e.getMessage().contains(HiveAuthzConf.HIVE_SENTRY_MOCK_ERROR));
    }
    statement.close();

  }

  /**
   * verify missing permissions for query using remote query validation
   * @throws Exception
   */
  @Test
  public void testQueryPermissions() throws Exception {
    policyFile
        .addRolesToGroup(USERGROUP1, "select_tab1", "insert_tab2")
        .addRolesToGroup(USERGROUP2, "select_tab3")
        .addRolesToGroup(USERGROUP3, "select_colAB")
        .addRolesToGroup(USERGROUP4, "select_colA")
        .addPermissionsToRole("select_tab1",
            "server=server1->db=default->table=tab1->action=select")
        .addPermissionsToRole("insert_tab2",
            "server=server1->db=default->table=tab2->action=insert")
        .addPermissionsToRole("select_tab3",
            "server=server1->db=default->table=tab3->action=select")
        .addPermissionsToRole("select_colA",
            "server=server1->db=default->table=tab1->column=a->action=select")
        .addPermissionsToRole("select_colAB",
            "server=server1->db=default->table=tab1->column=a->action=select")
        .addPermissionsToRole("select_colAB",
            "server=server1->db=default->table=tab1->column=b->action=select")
        .setUserGroupMapping(StaticUserGroup.getStaticMapping());
    policyFile.write(context.getPolicyFile());

    // setup db objects needed by the test
    Connection connection = context.createConnection(ADMIN1);
    Statement statement = context.createStatement(connection);

    statement.execute("DROP TABLE IF EXISTS tab1");
    statement.execute("DROP TABLE IF EXISTS tab2");
    statement.execute("DROP TABLE IF EXISTS tab3");
    statement.execute("CREATE TABLE tab1(b INT, a STRING) "
        + " row format delimited fields terminated by '|'  stored as textfile");
    statement.execute("CREATE TABLE tab2(b INT, a STRING) "
        + " row format delimited fields terminated by '|'  stored as textfile");
    statement.execute("CREATE TABLE tab3(b INT, a STRING) "
        + " row format delimited fields terminated by '|'  stored as textfile");
    statement.close();
    connection.close();

    configTool.setPolicyFile(context.getPolicyFile().getPath());
    configTool.setJdbcURL(context.getConnectionURL());
    configTool.setUser(USER1_1);
    configTool.setupConfig();
    ByteArrayOutputStream errBuffer = new ByteArrayOutputStream();

    // user1_1 can query table1
    configTool.setUser(USER1_1);
    configTool.verifyRemoteQuery("SELECT COUNT(*) FROM tab1");

    // user1_1 can't select from tab3
    try {
      System.setOut(new PrintStream(errBuffer));
      configTool.setUser(USER1_1);
      configTool.verifyRemoteQuery("SELECT COUNT(*) FROM tab3");
      fail("Query should have failed with insufficient perms");
    } catch (SQLException e) {
      assertTrue(errBuffer.toString().contains(
          "Server=server1->Db=default->Table=tab3->action=select"));
      errBuffer.flush();
    }

    // user2_1 can select from tab3, but can't insert into tab2
    try {
      configTool.setUser(USER2_1);
      configTool
          .verifyRemoteQuery("INSERT OVERWRITE TABLE tab2 SELECT * FROM tab3");
      fail("Query should have failed with insufficient perms");
    } catch (SQLException e) {
      assertTrue(errBuffer.toString().contains(
          "Server=server1->Db=default->Table=tab2->action=insert"));
      errBuffer.flush();
    }

    // user3_1 can select A from tab1, but can't select B from tab1
    configTool.setUser(USER3_1);
    configTool.verifyRemoteQuery("SELECT a FROM tab1");
    configTool.verifyRemoteQuery("SELECT COUNT(a) FROM tab1");
    configTool.verifyRemoteQuery("SELECT b FROM tab1");
    configTool.verifyRemoteQuery("SELECT COUNT(b) FROM tab1");
    configTool.verifyRemoteQuery("SELECT a,b FROM tab1");

    // user4_1 can select A from tab1, but can't select B from tab1
    configTool.setUser(USER4_1);
    configTool.verifyRemoteQuery("SELECT a FROM tab1");
    configTool.verifyRemoteQuery("SELECT COUNT(a) FROM tab1");

    try {
      configTool.setUser(USER4_1);
      configTool
          .verifyRemoteQuery("SELECT b FROM tab1");
      fail("Query should have failed with insufficient perms");
    } catch (SQLException e) {
      assertTrue(errBuffer.toString().contains(
          "Server=server1->Db=default->Table=tab1->Column=b->action=select"));
      errBuffer.flush();
    }

    try {
      configTool.setUser(USER4_1);
      configTool
          .verifyRemoteQuery("SELECT COUNT(b) FROM tab1");
      fail("Query should have failed with insufficient perms");
    } catch (SQLException e) {
      assertTrue(errBuffer.toString().contains(
          "Server=server1->Db=default->Table=tab1->Column=b->action=select"));
    }
  }
}
