You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sentry.apache.org by co...@apache.org on 2017/11/16 09:56:57 UTC

[20/32] sentry git commit: SENTRY-1475: Integrate Sentry with Solr 7 authorization framework. (Hrishikesh Gadre, reviewed by Kalyan Kumar Kalvagadda)

http://git-wip-us.apache.org/repos/asf/sentry/blob/e62fa28d/sentry-tests/sentry-tests-solr/src/test/java/org/apache/sentry/tests/e2e/solr/TestDocLevelOperations.java
----------------------------------------------------------------------
diff --git a/sentry-tests/sentry-tests-solr/src/test/java/org/apache/sentry/tests/e2e/solr/TestDocLevelOperations.java b/sentry-tests/sentry-tests-solr/src/test/java/org/apache/sentry/tests/e2e/solr/TestDocLevelOperations.java
index 71452e2..a24ceee 100644
--- a/sentry-tests/sentry-tests-solr/src/test/java/org/apache/sentry/tests/e2e/solr/TestDocLevelOperations.java
+++ b/sentry-tests/sentry-tests-solr/src/test/java/org/apache/sentry/tests/e2e/solr/TestDocLevelOperations.java
@@ -16,56 +16,64 @@
  */
 package org.apache.sentry.tests.e2e.solr;
 
-import org.junit.After;
-import org.junit.Before;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
+import static org.apache.sentry.tests.e2e.solr.TestSentryServer.ADMIN_USER;
 
+import java.net.URLEncoder;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.sentry.core.common.exception.SentryUserException;
+import org.apache.sentry.core.model.solr.SolrConstants;
 import org.apache.solr.client.solrj.SolrQuery;
-import org.apache.solr.client.solrj.impl.CloudSolrServer;
+import org.apache.solr.client.solrj.impl.CloudSolrClient;
 import org.apache.solr.client.solrj.request.QueryRequest;
 import org.apache.solr.client.solrj.response.QueryResponse;
-
 import org.apache.solr.common.SolrDocument;
 import org.apache.solr.common.SolrDocumentList;
 import org.apache.solr.common.SolrInputDocument;
 import org.apache.solr.common.params.ModifiableSolrParams;
 import org.apache.solr.common.params.SolrParams;
-
-import java.io.File;
-import java.net.URLEncoder;
-import java.util.ArrayList;
-import java.util.List;
-
+import org.junit.Before;
+import org.junit.BeforeClass;
 import org.junit.Test;
 
 /**
  * Test the document-level security features
  */
-public class TestDocLevelOperations extends AbstractSolrSentryTestBase {
+public class TestDocLevelOperations extends AbstractSolrSentryTestCase {
   private static final String AUTH_FIELD = "sentry_auth";
   private static final int NUM_DOCS = 100;
   private static final int EXTRA_AUTH_FIELDS = 2;
-  private String userName = null;
 
-  @Before
-  public void beforeTest() throws Exception {
-    userName = getAuthenticatedUser();
-  }
-
-  @After
-  public void afterTest() throws Exception {
-    setAuthenticationUser(userName);
+  @BeforeClass
+  public static void setupPermissions() throws SentryUserException {
+    sentryClient.createRole(ADMIN_USER, "junit_role", COMPONENT_SOLR);
+    sentryClient.createRole(ADMIN_USER, "doclevel_role", COMPONENT_SOLR);
+    sentryClient.grantRoleToGroups(ADMIN_USER, "junit_role", COMPONENT_SOLR,
+        Collections.singleton("junit"));
+    sentryClient.grantRoleToGroups(ADMIN_USER, "doclevel_role", COMPONENT_SOLR,
+        Collections.singleton("doclevel"));
+
+    // junit user
+    grantAdminPrivileges(ADMIN_USER, "junit_role", SolrConstants.ALL, SolrConstants.ALL);
+    grantCollectionPrivileges(ADMIN_USER, "junit_role", "docLevelCollection", SolrConstants.ALL);
+    grantCollectionPrivileges(ADMIN_USER, "junit_role", "allRolesCollection", SolrConstants.ALL);
+    grantCollectionPrivileges(ADMIN_USER, "junit_role", "testUpdateDeleteOperations", SolrConstants.ALL);
+
+    // docLevel user
+    grantCollectionPrivileges(ADMIN_USER, "doclevel_role", "docLevelCollection", SolrConstants.ALL);
+    grantCollectionPrivileges(ADMIN_USER, "doclevel_role", "testUpdateDeleteOperations", SolrConstants.ALL);
+
+    // admin user
+    grantCollectionPrivileges(ADMIN_USER, ADMIN_ROLE, SolrConstants.ALL, SolrConstants.ALL);
   }
 
-  private void setupCollectionWithDocSecurity(String name) throws Exception {
-    String configDir = RESOURCES_DIR + File.separator + DEFAULT_COLLECTION
-      + File.separator + "conf";
-    uploadConfigDirToZk(configDir);
-    // replace solrconfig.xml with solrconfig-doc-level.xml
-    uploadConfigFileToZk(configDir + File.separator + "solrconfig-doclevel.xml",
-      "solrconfig.xml");
-    setupCollection(name);
+  @Before
+  public void resetAuthenticatedUser() {
+    setAuthenticationUser("admin");
   }
 
   private QueryRequest getRealTimeGetRequest() {
@@ -77,6 +85,7 @@ public class TestDocLevelOperations extends AbstractSolrSentryTestBase {
     return getRealTimeGetRequest(idsBuilder.toString());
   }
 
+  @SuppressWarnings("serial")
   private QueryRequest getRealTimeGetRequest(String ids) {
     final ModifiableSolrParams idsParams = new ModifiableSolrParams();
     idsParams.add("ids", ids);
@@ -107,34 +116,29 @@ public class TestDocLevelOperations extends AbstractSolrSentryTestBase {
     // ensure no current documents
     verifyDeletedocsPass(ADMIN_USER, collectionName, true);
 
-    CloudSolrServer server = getCloudSolrServer(collectionName);
-    try {
-      DocLevelGenerator generator = new DocLevelGenerator(AUTH_FIELD);
-      generator.generateDocs(server, NUM_DOCS, "junit_role", "admin_role", EXTRA_AUTH_FIELDS);
+    DocLevelGenerator generator = new DocLevelGenerator(collectionName, AUTH_FIELD);
+    generator.generateDocs(cluster.getSolrClient(), NUM_DOCS, "junit_role", "admin_role", EXTRA_AUTH_FIELDS);
 
-      querySimple(new QueryRequest(new SolrQuery("*:*")), server, checkNonAdminUsers);
-      querySimple(getRealTimeGetRequest(), server, checkNonAdminUsers);
-    } finally {
-      server.shutdown();
-    }
+    querySimple(collectionName, new QueryRequest(new SolrQuery("*:*")), cluster.getSolrClient(), checkNonAdminUsers);
+    querySimple(collectionName, getRealTimeGetRequest(), cluster.getSolrClient(), checkNonAdminUsers);
   }
 
-  private void querySimple(QueryRequest request, CloudSolrServer server,
+  private void querySimple(String collectionName, QueryRequest request, CloudSolrClient client,
       boolean checkNonAdminUsers) throws Exception {
     // as admin  -- should get the other half
     setAuthenticationUser("admin");
-    QueryResponse  rsp = request.process(server);
+    QueryResponse  rsp = request.process(client, collectionName);
     SolrDocumentList docList = rsp.getResults();
     assertEquals(NUM_DOCS / 2, docList.getNumFound());
     for (SolrDocument doc : docList) {
       String id = doc.getFieldValue("id").toString();
       assertEquals(1, Long.valueOf(id) % 2);
     }
- 
+
     if (checkNonAdminUsers) {
       // as junit -- should get half the documents
       setAuthenticationUser("junit");
-      rsp = request.process(server);
+      rsp = request.process(client, collectionName);
       docList = rsp.getResults();
       assertEquals(NUM_DOCS / 2, docList.getNumFound());
       for (SolrDocument doc : docList) {
@@ -143,8 +147,8 @@ public class TestDocLevelOperations extends AbstractSolrSentryTestBase {
       }
 
       // as docLevel -- should get all
-      setAuthenticationUser("docLevel");
-      rsp = request.process(server);
+      setAuthenticationUser("doclevel");
+      rsp = request.process(client, collectionName);
       assertEquals(NUM_DOCS, rsp.getResults().getNumFound());
     }
   }
@@ -155,38 +159,31 @@ public class TestDocLevelOperations extends AbstractSolrSentryTestBase {
   @Test
   public void testDocLevelOperations() throws Exception {
     String collectionName = "docLevelCollection";
-    setupCollectionWithDocSecurity(collectionName);
-
-    try {
-      createDocsAndQuerySimple(collectionName, true);
-      CloudSolrServer server = getCloudSolrServer(collectionName);
-      try {
-        // test filter queries work as AND -- i.e. user can't avoid doc-level
-        // checks by prefixing their own filterQuery
-        setAuthenticationUser("junit");
-        String fq = URLEncoder.encode(" {!raw f=" + AUTH_FIELD + " v=docLevel_role}", "UTF-8");
-        String path = "/" + collectionName + "/select?q=*:*&fq="+fq;
-        String retValue = makeHttpRequest(server, "GET", path, null, null);
-        assertTrue(retValue.contains("numFound=\"" + NUM_DOCS / 2 + "\" "));
-
-        // test that user can't inject an "OR" into the query
-        final String syntaxErrorMsg = "org.apache.solr.search.SyntaxError: Cannot parse";
-        fq = URLEncoder.encode(" {!raw f=" + AUTH_FIELD + " v=docLevel_role} OR ", "UTF-8");
-        path = "/" + collectionName + "/select?q=*:*&fq="+fq;
-        retValue = makeHttpRequest(server, "GET", path, null, null);
-        assertTrue(retValue.contains(syntaxErrorMsg));
-
-        // same test, prefix OR this time
-        fq = URLEncoder.encode(" OR {!raw f=" + AUTH_FIELD + " v=docLevel_role}", "UTF-8");
-        path = "/" + collectionName + "/select?q=*:*&fq="+fq;
-        retValue = makeHttpRequest(server, "GET", path, null, null);
-        assertTrue(retValue.contains(syntaxErrorMsg));
-      } finally {
-        server.shutdown();
-      }
-    } finally {
-      deleteCollection(collectionName);
-    }
+    createCollection(ADMIN_USER, collectionName, "cloud-minimal_doc_level_security", NUM_SERVERS, 1);
+
+    CloudSolrClient client = cluster.getSolrClient();
+    createDocsAndQuerySimple(collectionName, true);
+
+    // test filter queries work as AND -- i.e. user can't avoid doc-level
+    // checks by prefixing their own filterQuery
+    setAuthenticationUser("junit");
+    String fq = URLEncoder.encode(" {!raw f=" + AUTH_FIELD + " v=doclevel_role}");
+    String path = "/" + collectionName + "/select?q=*:*&fq="+fq;
+    String retValue = makeHttpRequest(client, "GET", path, null, null, HttpServletResponse.SC_OK);
+    assertTrue("Result : " + retValue, retValue.contains("\"numFound\":"  + NUM_DOCS / 2));
+
+    // test that user can't inject an "OR" into the query
+    final String syntaxErrorMsg = "org.apache.solr.search.SyntaxError: Cannot parse";
+    fq = URLEncoder.encode(" {!raw f=" + AUTH_FIELD + " v=docLevel_role} OR ");
+    path = "/" + collectionName + "/select?q=*:*&fq="+fq;
+    retValue = makeHttpRequest(client, "GET", path, null, null, HttpServletResponse.SC_BAD_REQUEST);
+    assertTrue(retValue.contains(syntaxErrorMsg));
+
+    // same test, prefix OR this time
+    fq = URLEncoder.encode(" OR {!raw f=" + AUTH_FIELD + " v=docLevel_role}");
+    path = "/" + collectionName + "/select?q=*:*&fq="+fq;
+    retValue = makeHttpRequest(client, "GET", path, null, null, HttpServletResponse.SC_BAD_REQUEST);
+    assertTrue(retValue.contains(syntaxErrorMsg));
   }
 
   /**
@@ -196,67 +193,57 @@ public class TestDocLevelOperations extends AbstractSolrSentryTestBase {
   @Test
   public void testAllRolesToken() throws Exception {
     String collectionName = "allRolesCollection";
-    setupCollectionWithDocSecurity(collectionName);
-
-
-    try {
-      String allRolesToken = "OR";
-      int junitFactor = 2;
-      int allRolesFactor  = 5;
-
-      int totalJunitAdded = 0; // total docs added with junit token
-      int totalAllRolesAdded = 0; // total number of docs with the allRolesToken
-      int totalOnlyAllRolesAdded = 0; // total number of docs with _only_ the allRolesToken
-
-      // create documents
-      ArrayList<SolrInputDocument> docs = new ArrayList<SolrInputDocument>();
-      for (int i = 0; i < NUM_DOCS; ++i) {
-        boolean addedViaJunit = false;
-        SolrInputDocument doc = new SolrInputDocument();
-        String iStr = Long.toString(i);
-        doc.addField("id", iStr);
-        doc.addField("description", "description" + iStr);
-
-        if (i % junitFactor == 0) {
-          doc.addField(AUTH_FIELD, "junit_role");
-          addedViaJunit = true;
-          ++totalJunitAdded;
-        } if (i % allRolesFactor == 0) {
-          doc.addField(AUTH_FIELD, allRolesToken);
-          ++totalAllRolesAdded;
-          if (!addedViaJunit) {
-            ++totalOnlyAllRolesAdded;
-          }
+    createCollection(ADMIN_USER, collectionName, "cloud-minimal_doc_level_security", NUM_SERVERS, 1);
+
+    String allRolesToken = "OR";
+    int junitFactor = 2;
+    int allRolesFactor  = 5;
+
+    int totalJunitAdded = 0; // total docs added with junit token
+    int totalAllRolesAdded = 0; // total number of docs with the allRolesToken
+    int totalOnlyAllRolesAdded = 0; // total number of docs with _only_ the allRolesToken
+
+    // create documents
+    ArrayList<SolrInputDocument> docs = new ArrayList<SolrInputDocument>();
+    for (int i = 0; i < NUM_DOCS; ++i) {
+      boolean addedViaJunit = false;
+      SolrInputDocument doc = new SolrInputDocument();
+      String iStr = Long.toString(i);
+      doc.addField("id", iStr);
+      doc.addField("description", "description" + iStr);
+
+      if (i % junitFactor == 0) {
+        doc.addField(AUTH_FIELD, "junit_role");
+        addedViaJunit = true;
+        ++totalJunitAdded;
+      } if (i % allRolesFactor == 0) {
+        doc.addField(AUTH_FIELD, allRolesToken);
+        ++totalAllRolesAdded;
+        if (!addedViaJunit) {
+          ++totalOnlyAllRolesAdded;
         }
-        docs.add(doc);
-      }
-      // make sure our factors give us interesting results --
-      // that some docs only have all roles and some only have junit
-      assert(totalOnlyAllRolesAdded > 0);
-      assert(totalJunitAdded > totalAllRolesAdded);
-
-      CloudSolrServer server = getCloudSolrServer(collectionName);
-      try {
-        server.add(docs);
-        server.commit(true, true);
-
-        checkAllRolesToken(new QueryRequest(new SolrQuery("*:*")), server,
-            totalAllRolesAdded, totalOnlyAllRolesAdded, allRolesFactor, totalJunitAdded, junitFactor);
-        checkAllRolesToken(getRealTimeGetRequest(), server,
-             totalAllRolesAdded, totalOnlyAllRolesAdded, allRolesFactor, totalJunitAdded, junitFactor);
-      } finally {
-        server.shutdown();
       }
-    } finally {
-      deleteCollection(collectionName);
+      docs.add(doc);
     }
+    // make sure our factors give us interesting results --
+    // that some docs only have all roles and some only have junit
+    assert(totalOnlyAllRolesAdded > 0);
+    assert(totalJunitAdded > totalAllRolesAdded);
+
+    cluster.getSolrClient().add(collectionName, docs);
+    cluster.getSolrClient().commit(collectionName, true, true);
+
+    checkAllRolesToken(collectionName, new QueryRequest(new SolrQuery("*:*")), cluster.getSolrClient(),
+        totalAllRolesAdded, totalOnlyAllRolesAdded, allRolesFactor, totalJunitAdded, junitFactor);
+    checkAllRolesToken(collectionName, getRealTimeGetRequest(), cluster.getSolrClient(),
+         totalAllRolesAdded, totalOnlyAllRolesAdded, allRolesFactor, totalJunitAdded, junitFactor);
   }
 
-  private void checkAllRolesToken(QueryRequest request, CloudSolrServer server,
+  private void checkAllRolesToken(String collectionName, QueryRequest request, CloudSolrClient client,
       int totalAllRolesAdded, int totalOnlyAllRolesAdded, int allRolesFactor, int totalJunitAdded, int junitFactor) throws Exception {
     // as admin  -- should only get all roles token documents
     setAuthenticationUser("admin");
-    QueryResponse rsp = request.process(server);
+    QueryResponse rsp = request.process(client, collectionName);
     SolrDocumentList docList = rsp.getResults();
     assertEquals(totalAllRolesAdded, docList.getNumFound());
     for (SolrDocument doc : docList) {
@@ -266,7 +253,7 @@ public class TestDocLevelOperations extends AbstractSolrSentryTestBase {
 
     // as junit -- should get junit added + onlyAllRolesAdded
     setAuthenticationUser("junit");
-    rsp = request.process(server);
+    rsp = request.process(client, collectionName);
     docList = rsp.getResults();
     assertEquals(totalJunitAdded + totalOnlyAllRolesAdded, docList.getNumFound());
     for (SolrDocument doc : docList) {
@@ -285,122 +272,106 @@ public class TestDocLevelOperations extends AbstractSolrSentryTestBase {
   private void deleteByQueryTest(String collectionName, String deleteUser,
       String deleteByQueryStr, String queryUser, int expectedQueryDocs) throws Exception {
     createDocsAndQuerySimple(collectionName, true);
-    CloudSolrServer server = getCloudSolrServer(collectionName);
-    try {
-      setAuthenticationUser(deleteUser);
-      server.deleteByQuery(deleteByQueryStr);
-      server.commit();
-
-      checkDeleteByQuery(new QueryRequest(new SolrQuery("*:*")), server,
-          queryUser, expectedQueryDocs);
-      checkDeleteByQuery(getRealTimeGetRequest(), server,
-          queryUser, expectedQueryDocs);
-    } finally {
-      server.shutdown();
-    }
+    setAuthenticationUser(deleteUser);
+    cluster.getSolrClient().deleteByQuery(collectionName, deleteByQueryStr);
+    cluster.getSolrClient().commit(collectionName);
+
+    checkDeleteByQuery(collectionName, new QueryRequest(new SolrQuery("*:*")), cluster.getSolrClient(),
+        queryUser, expectedQueryDocs);
+    checkDeleteByQuery(collectionName, getRealTimeGetRequest(), cluster.getSolrClient(),
+        queryUser, expectedQueryDocs);
   }
 
-  private void checkDeleteByQuery(QueryRequest query, CloudSolrServer server,
+  private void checkDeleteByQuery(String collectionName, QueryRequest query, CloudSolrClient server,
       String queryUser, int expectedQueryDocs) throws Exception {
-    QueryResponse rsp =  query.process(server);
+    QueryResponse rsp =  query.process(server, collectionName);
     long junitResults = rsp.getResults().getNumFound();
     assertEquals(0, junitResults);
 
     setAuthenticationUser(queryUser);
-    rsp =  query.process(server);
+    rsp =  query.process(server, collectionName);
     long docLevelResults = rsp.getResults().getNumFound();
     assertEquals(expectedQueryDocs, docLevelResults);
   }
 
   private void deleteByIdTest(String collectionName) throws Exception {
     createDocsAndQuerySimple(collectionName, true);
-    CloudSolrServer server = getCloudSolrServer(collectionName);
-    try {
-      setAuthenticationUser("junit");
-      List<String> allIds = new ArrayList<String>(NUM_DOCS);
-      for (int i = 0; i < NUM_DOCS; ++i) {
-        allIds.add(Long.toString(i));
-      }
-      server.deleteById(allIds);
-      server.commit();
-
-      checkDeleteById(new QueryRequest(new SolrQuery("*:*")), server);
-      checkDeleteById(getRealTimeGetRequest(), server);
-    } finally {
-      server.shutdown();
+    setAuthenticationUser("junit");
+    List<String> allIds = new ArrayList<String>(NUM_DOCS);
+    for (int i = 0; i < NUM_DOCS; ++i) {
+      allIds.add(Long.toString(i));
     }
+    cluster.getSolrClient().deleteById(collectionName, allIds);
+    cluster.getSolrClient().commit(collectionName);
+
+    checkDeleteById(collectionName, new QueryRequest(new SolrQuery("*:*")), cluster.getSolrClient());
+    checkDeleteById(collectionName, getRealTimeGetRequest(), cluster.getSolrClient());
+
   }
 
-  private void checkDeleteById(QueryRequest request, CloudSolrServer server)
+  private void checkDeleteById(String collectionName, QueryRequest request, CloudSolrClient server)
       throws Exception {
-    QueryResponse rsp = request.process(server);
+    QueryResponse rsp = request.process(server, collectionName);
     long junitResults = rsp.getResults().getNumFound();
     assertEquals(0, junitResults);
 
-    setAuthenticationUser("docLevel");
-    rsp =  request.process(server);
+    setAuthenticationUser("doclevel");
+    rsp =  request.process(server, collectionName);
     long docLevelResults = rsp.getResults().getNumFound();
     assertEquals(0, docLevelResults);
   }
 
   private void updateDocsTest(String collectionName) throws Exception {
     createDocsAndQuerySimple(collectionName, true);
-    CloudSolrServer server = getCloudSolrServer(collectionName);
-    try {
-      setAuthenticationUser("junit");
-      String docIdStr = Long.toString(1);
-
-      // verify we can't view one of the odd documents
-      QueryRequest query = new QueryRequest(new SolrQuery("id:"+docIdStr));
-      QueryRequest rtgQuery = getRealTimeGetRequest(docIdStr);
-      checkUpdateDocsQuery(query, server, 0);
-      checkUpdateDocsQuery(rtgQuery, server, 0);
+    setAuthenticationUser("junit");
+    String docIdStr = Long.toString(1);
+
+    // verify we can't view one of the odd documents
+    QueryRequest query = new QueryRequest(new SolrQuery("id:"+docIdStr));
+    QueryRequest rtgQuery = getRealTimeGetRequest(docIdStr);
+    checkUpdateDocsQuery(collectionName, query, cluster.getSolrClient(), 0);
+    checkUpdateDocsQuery(collectionName, rtgQuery, cluster.getSolrClient(), 0);
+
+    // overwrite the document that we can't see
+    ArrayList<SolrInputDocument> docs = new ArrayList<SolrInputDocument>();
+    SolrInputDocument doc = new SolrInputDocument();
+    doc.addField("id", docIdStr);
+    doc.addField("description", "description" + docIdStr);
+    doc.addField(AUTH_FIELD, "junit_role");
+    docs.add(doc);
+    cluster.getSolrClient().add(collectionName, docs);
+    cluster.getSolrClient().commit(collectionName);
+
+    // verify we can now view the document
+    checkUpdateDocsQuery(collectionName, query, cluster.getSolrClient(), 1);
+    checkUpdateDocsQuery(collectionName, rtgQuery, cluster.getSolrClient(), 1);
 
-      // overwrite the document that we can't see
-      ArrayList<SolrInputDocument> docs = new ArrayList<SolrInputDocument>();
-      SolrInputDocument doc = new SolrInputDocument();
-      doc.addField("id", docIdStr);
-      doc.addField("description", "description" + docIdStr);
-      doc.addField(AUTH_FIELD, "junit_role");
-      docs.add(doc);
-      server.add(docs);
-      server.commit();
-
-      // verify we can now view the document
-      checkUpdateDocsQuery(query, server, 1);
-      checkUpdateDocsQuery(rtgQuery, server, 1);
-    } finally {
-      server.shutdown();
-    }
   }
 
-  private void checkUpdateDocsQuery(QueryRequest request, CloudSolrServer server, int expectedDocs)
+  private void checkUpdateDocsQuery(String collectionName, QueryRequest request, CloudSolrClient server, int expectedDocs)
       throws Exception {
-    QueryResponse rsp = request.process(server);
+    QueryResponse rsp = request.process(server, collectionName);
     assertEquals(expectedDocs, rsp.getResults().getNumFound());
   }
 
   @Test
   public void testUpdateDeleteOperations() throws Exception {
     String collectionName = "testUpdateDeleteOperations";
+    createCollection(ADMIN_USER, collectionName, "cloud-minimal_doc_level_security", NUM_SERVERS, 1);
 
-    setupCollectionWithDocSecurity(collectionName);
-    try {
-      createDocsAndQuerySimple(collectionName, true);
+    createDocsAndQuerySimple(collectionName, true);
 
-      // test deleteByQuery "*:*"
-      deleteByQueryTest(collectionName, "junit", "*:*", "docLevel", 0);
+    // test deleteByQuery "*:*"
+    deleteByQueryTest(collectionName, "junit", "*:*", "doclevel", 0);
 
-      // test deleteByQuery non-*:*
-      deleteByQueryTest(collectionName, "junit", "sentry_auth:docLevel_role", "docLevel", 0);
+    // test deleteByQuery non-*:*
+    deleteByQueryTest(collectionName, "junit", "sentry_auth:doclevel_role", "doclevel", 0);
 
-      // test deleting all documents by Id
-      deleteByIdTest(collectionName);
+    // test deleting all documents by Id
+    deleteByIdTest(collectionName);
+
+    updateDocsTest(collectionName);
 
-      updateDocsTest(collectionName);
-    } finally {
-      deleteCollection(collectionName);
-    }
   }
 
   /**
@@ -410,19 +381,14 @@ public class TestDocLevelOperations extends AbstractSolrSentryTestBase {
   @Test
   public void indexDocAuthTests() throws Exception {
     String collectionName = "testIndexlevelDoclevelOperations";
+    createCollection(ADMIN_USER, collectionName, "cloud-minimal_doc_level_security", NUM_SERVERS, 1);
 
-    setupCollectionWithDocSecurity(collectionName);
-    try {
-      createDocsAndQuerySimple(collectionName, false);
-
-      // test query for "*:*" fails as junit user (junit user doesn't have index level permissions but has doc level permissions set)
-      verifyQueryFail("junit", collectionName, ALL_DOCS);
+    createDocsAndQuerySimple(collectionName, false);
 
-      // test query for "*:*" fails as docLevel user (docLevel user has neither index level permissions nor doc level permissions set)
-      verifyQueryFail("docLevel", collectionName, ALL_DOCS);
+    // test query for "*:*" fails as junit user (junit user doesn't have index level permissions but has doc level permissions set)
+    verifyQueryFail("junit", collectionName, ALL_DOCS);
 
-    } finally {
-      deleteCollection(collectionName);
-    }
+    // test query for "*:*" fails as docLevel user (docLevel user has neither index level permissions nor doc level permissions set)
+    verifyQueryFail("doclevel", collectionName, ALL_DOCS);
   }
 }

http://git-wip-us.apache.org/repos/asf/sentry/blob/e62fa28d/sentry-tests/sentry-tests-solr/src/test/java/org/apache/sentry/tests/e2e/solr/TestQueryOperations.java
----------------------------------------------------------------------
diff --git a/sentry-tests/sentry-tests-solr/src/test/java/org/apache/sentry/tests/e2e/solr/TestQueryOperations.java b/sentry-tests/sentry-tests-solr/src/test/java/org/apache/sentry/tests/e2e/solr/TestQueryOperations.java
deleted file mode 100644
index f8ed955..0000000
--- a/sentry-tests/sentry-tests-solr/src/test/java/org/apache/sentry/tests/e2e/solr/TestQueryOperations.java
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * 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.solr;
-
-import java.io.File;
-import java.io.PrintWriter;
-import java.io.StringWriter;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-
-import org.apache.solr.common.SolrInputDocument;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import org.junit.Test;
-import static org.junit.Assert.assertEquals;
-
-public class TestQueryOperations extends AbstractSolrSentryTestBase {
-
-  private static final Logger LOG = LoggerFactory
-      .getLogger(TestQueryOperations.class);
-  private static final String COLLECTION_NAME = "sentryCollection";
-  private static final List<Boolean> BOOLEAN_VALUES = Arrays.asList(new Boolean[]{true, false});
-  private static final String DEFAULT_COLLECTION = "collection1";
-
-  @Test
-  public void testQueryOps() throws Exception {
-    // Upload configs to ZK
-    uploadConfigDirToZk(RESOURCES_DIR + File.separator + DEFAULT_COLLECTION
-        + File.separator + "conf");
-    setupCollection(COLLECTION_NAME);
-    ArrayList<String> testFailures = new ArrayList<String>();
-
-    for (boolean query : BOOLEAN_VALUES) {
-      for (boolean update : BOOLEAN_VALUES) {
-        for (boolean all : BOOLEAN_VALUES) {
-          String test_user = getUsernameForPermissions(COLLECTION_NAME, query, update, all);
-          LOG.info("TEST_USER: " + test_user);
-
-          try {
-            cleanSolrCollection(COLLECTION_NAME);
-            SolrInputDocument solrInputDoc = createSolrTestDoc();
-            uploadSolrDoc(COLLECTION_NAME, solrInputDoc);
-            if (all || query) {
-              verifyQueryPass(test_user, COLLECTION_NAME, ALL_DOCS);
-            } else {
-              verifyQueryFail(test_user, COLLECTION_NAME, ALL_DOCS);
-            }
-          } catch (Throwable testException) {
-            StringWriter stringWriter = new StringWriter();
-            PrintWriter printWriter = new PrintWriter(stringWriter);
-            testException.printStackTrace(printWriter);
-            testFailures.add("\n\nTestFailure: User -> " + test_user + "\n"
-                + stringWriter.toString());
-          }
-        }
-      }
-    }
-
-    assertEquals("Total test failures: " + testFailures.size() + " \n\n"
-        + testFailures.toString() + "\n\n\n", 0, testFailures.size());
-  }
-}

http://git-wip-us.apache.org/repos/asf/sentry/blob/e62fa28d/sentry-tests/sentry-tests-solr/src/test/java/org/apache/sentry/tests/e2e/solr/TestRealTimeGet.java
----------------------------------------------------------------------
diff --git a/sentry-tests/sentry-tests-solr/src/test/java/org/apache/sentry/tests/e2e/solr/TestRealTimeGet.java b/sentry-tests/sentry-tests-solr/src/test/java/org/apache/sentry/tests/e2e/solr/TestRealTimeGet.java
deleted file mode 100644
index f9b6c07..0000000
--- a/sentry-tests/sentry-tests-solr/src/test/java/org/apache/sentry/tests/e2e/solr/TestRealTimeGet.java
+++ /dev/null
@@ -1,476 +0,0 @@
-/*
- * 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.solr;
-
-import org.apache.solr.client.solrj.SolrServerException;
-import org.apache.solr.client.solrj.impl.CloudSolrServer;
-import org.apache.solr.client.solrj.request.QueryRequest;
-import org.apache.solr.client.solrj.response.QueryResponse;
-import org.apache.solr.common.SolrDocument;
-import org.apache.solr.common.SolrDocumentList;
-import org.apache.solr.common.SolrInputDocument;
-import org.apache.solr.common.params.CollectionParams.CollectionAction;
-import org.apache.solr.common.params.ModifiableSolrParams;
-import org.apache.solr.common.params.SolrParams;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
-
-import java.io.File;
-import java.io.IOException;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.HashSet;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Random;
-import java.util.Set;
-
-public class TestRealTimeGet extends AbstractSolrSentryTestBase {
-  private static final String AUTH_FIELD = "sentry_auth";
-  private static final Random rand = new Random();
-  private String userName = null;
-
-  @Before
-  public void beforeTest() throws Exception {
-    userName = getAuthenticatedUser();
-  }
-
-  @After
-  public void afterTest() throws Exception {
-    setAuthenticationUser(userName);
-  }
-
-  private void setupCollectionWithDocSecurity(String name) throws Exception {
-    setupCollectionWithDocSecurity(name, 2);
-  }
-
-  private void setupCollectionWithDocSecurity(String name, int shards) throws Exception {
-    String configDir = RESOURCES_DIR + File.separator + DEFAULT_COLLECTION
-      + File.separator + "conf";
-    uploadConfigDirToZk(configDir, name);
-    // replace solrconfig.xml with solrconfig-doc-level.xml
-    uploadConfigFileToZk(configDir + File.separator + "solrconfig-doclevel.xml",
-        "solrconfig.xml", name);
-    ModifiableSolrParams modParams = new ModifiableSolrParams();
-    modParams.set("numShards", shards);
-    StringBuilder builder = new StringBuilder();
-    for (int i = 0; i < shards; ++i) {
-      if (i != 0) {
-        builder.append(",");
-      }
-      builder.append("shard").append(i+1);
-    }
-    modParams.set("shards", builder.toString());
-    verifyCollectionAdminOpPass(ADMIN_USER, CollectionAction.CREATE, name, modParams);
-  }
-
-  private void setupCollectionWithoutDocSecurity(String name) throws Exception {
-    String configDir = RESOURCES_DIR + File.separator + DEFAULT_COLLECTION
-      + File.separator + "conf";
-    uploadConfigDirToZk(configDir, name);
-    setupCollection(name);
-  }
-
-  private QueryRequest getRealTimeGetRequest(final SolrParams params) {
-    return new QueryRequest() {
-      @Override
-      public String getPath() {
-        return "/get";
-      }
-
-      @Override
-      public SolrParams getParams() {
-        return params;
-      }
-    };
-  }
-
-  private void assertExpected(ExpectedResult expectedResult, QueryResponse rsp,
-        QueryResponse controlRsp) throws Exception {
-    SolrDocumentList docList = rsp.getResults();
-    SolrDocumentList controlDocList = controlRsp.getResults();
-    SolrDocument doc = (SolrDocument)rsp.getResponse().get("doc");
-    SolrDocument controlDoc = (SolrDocument)controlRsp.getResponse().get("doc");
-
-    if (expectedResult.expectedDocs == 0) {
-      // could be null rather than 0 size, check against control that format is identical
-      assertNull("Should be no doc present: " + doc, doc);
-      assertNull("Should be no doc present: " + controlDoc, controlDoc);
-      assertTrue((docList == null && controlDocList == null) ||
-          (controlDocList.getNumFound() == 0));
-    } else {
-      if (docList == null) {
-        assertNull(controlDocList);
-        assertNotNull(doc);
-        assertNotNull(controlDoc);
-      } else {
-        assertNotNull(controlDocList);
-        assertNull(doc);
-        assertNull(controlDoc);
-        assertEquals(expectedResult.expectedDocs, docList.getNumFound());
-        assertEquals(docList.getNumFound(), controlDocList.getNumFound());
-      }
-    }
-  }
-
-  private QueryResponse getIdResponse(ExpectedResult expectedResult) throws Exception {
-    ModifiableSolrParams params = new ModifiableSolrParams();
-    for (int i = 0; i < expectedResult.ids.length; ++i) {
-      params.add("id", expectedResult.ids[ i ]);
-    }
-    if (expectedResult.fl != null) {
-      params.add("fl", expectedResult.fl);
-    }
-    QueryRequest request = getRealTimeGetRequest(params);
-    return request.process(expectedResult.server);
-  }
-
-  private QueryResponse getIdsResponse(ExpectedResult expectedResult) throws Exception {
-    StringBuilder builder = new StringBuilder();
-    for (int i = 0; i < expectedResult.ids.length; ++i) {
-      if (i != 0) {
-        builder.append(",");
-      }
-      builder.append(expectedResult.ids[ i ]);
-    }
-    ModifiableSolrParams params = new ModifiableSolrParams();
-    params.add("ids", builder.toString());
-    if (expectedResult.fl != null) {
-      params.add("fl", expectedResult.fl);
-    }
-    QueryRequest request = getRealTimeGetRequest(params);
-    return request.process(expectedResult.server);
-  }
-
-  private void assertIdVsIds(ExpectedResult expectedResult, ExpectedResult controlExpectedResult)
-      throws Exception {
-    // test specifying with "id"
-    QueryResponse idRsp = getIdResponse(expectedResult);
-    QueryResponse idControlRsp = getIdResponse(controlExpectedResult);
-    assertExpected(expectedResult, idRsp, idControlRsp);
-
-    // test specifying with "ids"
-    QueryResponse idsRsp = getIdsResponse(expectedResult);
-    QueryResponse idsControlRsp = getIdsResponse(controlExpectedResult);
-    assertExpected(expectedResult, idsRsp, idsControlRsp);
-  }
-
-  @Test
-  public void testIdvsIds() throws Exception {
-    final String collection = "testIdvsIds";
-    final String collectionControl = collection + "Control";
-    setupCollectionWithDocSecurity(collection);
-    setupCollectionWithoutDocSecurity(collectionControl);
-    CloudSolrServer server = getCloudSolrServer(collection);
-    CloudSolrServer serverControl = getCloudSolrServer(collectionControl);
-
-    try {
-      for (CloudSolrServer s : new CloudSolrServer [] {server, serverControl}) {
-        DocLevelGenerator generator = new DocLevelGenerator(AUTH_FIELD);
-        generator.generateDocs(s, 100, "junit_role", "admin_role", 2);
-      }
-
-      // check that control collection does not filter
-      assertIdVsIds(new ExpectedResult(serverControl, new String[] {"2"}, 1),
-          new ExpectedResult(serverControl, new String[] {"2"}, 1));
-
-      // single id
-      assertIdVsIds(new ExpectedResult(server, new String[] {"1"}, 1),
-          new ExpectedResult(serverControl, new String[] {"1"}, 1));
-
-      // single id (invalid)
-      assertIdVsIds(new ExpectedResult(server, new String[] {"bogusId"}, 0),
-          new ExpectedResult(serverControl, new String[] {"bogusId"}, 0));
-
-      // single id (no permission)
-      assertIdVsIds(new ExpectedResult(server, new String[] {"2"}, 0),
-          new ExpectedResult(serverControl, new String[] {"2fake"}, 0));
-
-      // multiple ids (some invalid, some valid, some no permission)
-      assertIdVsIds(new ExpectedResult(server, new String[] {"bogus1", "1", "2"}, 1),
-          new ExpectedResult(serverControl, new String[] {"bogus1", "1", "bogus2"}, 1));
-      assertIdVsIds(new ExpectedResult(server, new String[] {"bogus1", "1", "2", "3"}, 2),
-          new ExpectedResult(serverControl, new String[] {"bogus1", "1", "bogus2", "3"}, 2));
-
-      // multiple ids (all invalid)
-      assertIdVsIds(new ExpectedResult(server, new String[] {"bogus1", "bogus2", "bogus3"}, 0),
-          new ExpectedResult(serverControl, new String[] {"bogus1", "bogus2", "bogus3"}, 0));
-
-      // multiple ids (all no permission)
-      assertIdVsIds(new ExpectedResult(server, new String[] {"2", "4", "6"}, 0),
-          new ExpectedResult(serverControl, new String[] {"bogus2", "bogus4", "bogus6"}, 0));
-
-    } finally {
-      server.shutdown();
-      serverControl.shutdown();
-    }
-  }
-
-  private void assertFlOnDocList(SolrDocumentList list, Set<String> expectedIds,
-      List<String> expectedFields) {
-    assertEquals("Doc list size should be: " + expectedIds.size(), expectedIds.size(), list.getNumFound());
-    for (SolrDocument doc : list) {
-      expectedIds.contains(doc.get("id"));
-      for (String field : expectedFields) {
-        assertNotNull("Field: " + field + " should not be null in doc: " + doc, doc.get(field));
-      }
-      assertEquals("doc should have: " + expectedFields.size() + " fields.  Doc: " + doc,
-          expectedFields.size(), doc.getFieldNames().size());
-    }
-  }
-
-  private void assertFl(CloudSolrServer server, String [] ids, Set<String> expectedIds,
-        String fl, List<String> expectedFields) throws Exception {
-    {
-      QueryResponse idRsp = getIdResponse(new ExpectedResult(server, ids, expectedIds.size(), fl));
-      SolrDocumentList idList = idRsp.getResults();
-      assertFlOnDocList(idList, expectedIds, expectedFields);
-    }
-    {
-      QueryResponse idsRsp = getIdsResponse(new ExpectedResult(server, ids, expectedIds.size(), fl));
-      SolrDocumentList idsList = idsRsp.getResults();
-      assertFlOnDocList(idsList, expectedIds, expectedFields);
-    }
-  }
-
-  @Test
-  public void testFl() throws Exception {
-    final String collection = "testFl";
-    // FixMe: have to use one shard, because of a Solr bug where "fl" is not applied to
-    // multi-shard get requests
-    setupCollectionWithDocSecurity(collection, 1);
-    CloudSolrServer server = getCloudSolrServer(collection);
-
-    try {
-      DocLevelGenerator generator = new DocLevelGenerator(AUTH_FIELD);
-      generator.generateDocs(server, 100, "junit_role", "admin_role", 2);
-      String [] ids = new String[] {"1", "3", "5"};
-
-      assertFl(server, ids, new HashSet<String>(Arrays.asList(ids)), "id", Arrays.asList("id"));
-      assertFl(server, ids, new HashSet<String>(Arrays.asList(ids)), null, Arrays.asList("id", "description", "_version_"));
-      // test transformer
-      assertFl(server, ids, new HashSet<String>(Arrays.asList(ids)), "id,mydescription:description", Arrays.asList("id", "mydescription"));
-    } finally {
-      server.shutdown();
-    }
-  }
-
-  @Test
-  public void testNonCommitted() throws Exception {
-    final String collection = "testNonCommitted";
-    setupCollectionWithDocSecurity(collection, 1);
-    CloudSolrServer server = getCloudSolrServer(collection);
-
-    try {
-      DocLevelGenerator generator = new DocLevelGenerator(AUTH_FIELD);
-      generator.generateDocs(server, 100, "junit_role", "admin_role", 2);
-
-      // make some uncommitted modifications and ensure they are reflected
-      server.deleteById("1");
-
-      SolrInputDocument doc2 = new SolrInputDocument();
-      doc2.addField("id", "2");
-      doc2.addField("description", "description2");
-      doc2.addField(AUTH_FIELD, "admin_role");
- 
-      SolrInputDocument doc3 = new SolrInputDocument();
-      doc3.addField("id", "3");
-      doc3.addField("description", "description3");
-      doc3.addField(AUTH_FIELD, "junit_role");
-
-      SolrInputDocument doc200 = new SolrInputDocument();
-      doc200.addField("id", "200");
-      doc200.addField("description", "description200");
-      doc200.addField(AUTH_FIELD, "admin_role");
-      server.add(Arrays.asList(new SolrInputDocument [] {doc2, doc3, doc200}));
-
-      assertFl(server, new String[] {"1", "2", "3", "4", "5", "200"},
-          new HashSet<String>(Arrays.asList("2", "5", "200")), "id", Arrays.asList("id"));
-    } finally {
-      server.shutdown();
-    }
-  }
-
-  private void assertConcurrentOnDocList(SolrDocumentList list, String authField, String expectedAuthFieldValue) {
-    for (SolrDocument doc : list) {
-      Collection<Object> authFieldValues = doc.getFieldValues(authField);
-      assertNotNull(authField + " should not be null.  Doc: " + doc, authFieldValues);
-
-      boolean foundAuthFieldValue = false;
-      for (Object obj : authFieldValues) {
-        if (obj.toString().equals(expectedAuthFieldValue)) {
-          foundAuthFieldValue = true;
-          break;
-        }
-      }
-      assertTrue("Did not find: " + expectedAuthFieldValue + " in doc: " + doc, foundAuthFieldValue);
-    }
-  }
-
-  private void assertConcurrent(CloudSolrServer server, String [] ids, String authField, String expectedAuthFieldValue)
-      throws Exception {
-    {
-      QueryResponse idRsp = getIdResponse(new ExpectedResult(server, ids, -1, null));
-      SolrDocumentList idList = idRsp.getResults();
-      assertConcurrentOnDocList(idList, authField, expectedAuthFieldValue);
-    }
-    {
-      QueryResponse idsRsp = getIdsResponse(new ExpectedResult(server, ids, -1, null));
-      SolrDocumentList idsList = idsRsp.getResults();
-      assertConcurrentOnDocList(idsList, authField, expectedAuthFieldValue);
-    }
-  }
-
-  @Test
-  public void testConcurrentChanges() throws Exception {
-    final String collection = "testConcurrentChanges";
-    // Ensure the auth field is stored so we can check a consistent doc is returned
-    final String authField = "sentry_auth_stored";
-    System.setProperty("sentry.auth.field", authField);
-    setupCollectionWithDocSecurity(collection, 1);
-    CloudSolrServer server = getCloudSolrServer(collection);
-    int numQueries = 5;
-
-    try {
-      DocLevelGenerator generator = new DocLevelGenerator(authField);
-      generator.generateDocs(server, 100, "junit_role", "admin_role", 2);
-
-      List<AuthFieldModifyThread> threads = new LinkedList<AuthFieldModifyThread>();
-      int docsToModify = 10;
-      for (int i = 0; i < docsToModify; ++i) {
-        SolrInputDocument doc = new SolrInputDocument();
-        doc.addField("id", Integer.toString(i));
-        doc.addField("description", "description" + Integer.toString(i));
-        doc.addField(authField, "junit_role");
-        server.add(doc);
-
-        threads.add(new AuthFieldModifyThread(server, doc,
-            authField, "junit_role", "admin_role"));
-      }
-      server.commit();
-
-      for (AuthFieldModifyThread thread : threads) {
-        thread.start();
-      }
-
-      // query
-      String [] ids = new String[docsToModify];
-      for (int j = 0; j < ids.length; ++j) {
-        ids[ j ] = Integer.toString(j);
-      }
-      for (int k = 0; k < numQueries; ++k) {
-        assertConcurrent(server, ids, authField, "admin_role");
-      }
-
-      for (AuthFieldModifyThread thread : threads) {
-        thread.setFinished();
-        thread.join();
-      }
-    } finally {
-      System.clearProperty("sentry.auth.field");
-      server.shutdown();
-    }
-  }
-
-  @Test
-  public void testSuperUser() throws Exception {
-    final String collection = "testSuperUser";
-    setupCollectionWithDocSecurity(collection, 1);
-    CloudSolrServer server = getCloudSolrServer(collection);
-    int docCount = 100;
-
-    try {
-      DocLevelGenerator generator = new DocLevelGenerator(AUTH_FIELD);
-      generator.generateDocs(server, docCount, "junit_role", "admin_role", 2);
-
-      setAuthenticationUser("solr");
-      String [] ids = new String[docCount];
-      for (int i = 0; i < docCount; ++i) {
-        ids[ i ] = Integer.toString(i);
-      }
-      QueryResponse response = getIdResponse(new ExpectedResult(server, ids, docCount));
-      assertEquals("Wrong number of documents", docCount, response.getResults().getNumFound());
-    } finally {
-      server.shutdown();
-    }
-  }
-
-  private class AuthFieldModifyThread extends Thread {
-    private CloudSolrServer server;
-    private SolrInputDocument doc;
-    private String authField;
-    private String authFieldValue0;
-    private String authFieldValue1;
-    private volatile boolean finished = false;
-
-    private AuthFieldModifyThread(CloudSolrServer server,
-        SolrInputDocument doc, String authField,
-        String authFieldValue0, String authFieldValue1) {
-      this.server = server;
-      this.doc = doc;
-      this.authField = authField;
-      this.authFieldValue0 = authFieldValue0;
-      this.authFieldValue1 = authFieldValue1;
-    }
-
-    @Override
-    public void run() {
-      while (!finished) {
-        if (rand.nextBoolean()) {
-          doc.setField(authField, authFieldValue0);
-        } else {
-          doc.setField(authField, authFieldValue1);
-        }
-        try {
-          server.add(doc);
-        } catch (SolrServerException sse) {
-          throw new RuntimeException(sse);
-        } catch (IOException ioe) {
-          throw new RuntimeException(ioe);
-        }
-      }
-    }
-
-    public void setFinished() {
-      finished = true;
-    }
-  }
-
-  private static class ExpectedResult {
-    public final CloudSolrServer server;
-    public final String [] ids;
-    public final int expectedDocs;
-    public final String fl;
-
-    public ExpectedResult(CloudSolrServer server, String [] ids, int expectedDocs) {
-      this(server, ids, expectedDocs, null);
-    }
-
-    public ExpectedResult(CloudSolrServer server, String [] ids, int expectedDocs, String fl) {
-      this.server = server;
-      this.ids = ids;
-      this.expectedDocs = expectedDocs;
-      this.fl = fl;
-    }
-  }
-}

http://git-wip-us.apache.org/repos/asf/sentry/blob/e62fa28d/sentry-tests/sentry-tests-solr/src/test/java/org/apache/sentry/tests/e2e/solr/TestSentryServer.java
----------------------------------------------------------------------
diff --git a/sentry-tests/sentry-tests-solr/src/test/java/org/apache/sentry/tests/e2e/solr/TestSentryServer.java b/sentry-tests/sentry-tests-solr/src/test/java/org/apache/sentry/tests/e2e/solr/TestSentryServer.java
new file mode 100644
index 0000000..ff55790
--- /dev/null
+++ b/sentry-tests/sentry-tests-solr/src/test/java/org/apache/sentry/tests/e2e/solr/TestSentryServer.java
@@ -0,0 +1,144 @@
+/*
+ * 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.solr;
+
+import java.io.Closeable;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.nio.file.Path;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+
+import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.net.NetUtils;
+import org.apache.sentry.provider.db.generic.SentryGenericProviderBackend;
+import org.apache.sentry.provider.db.generic.service.thrift.SentryGenericServiceClient;
+import org.apache.sentry.provider.db.generic.service.thrift.SentryGenericServiceClientFactory;
+import org.apache.sentry.provider.file.LocalGroupResourceAuthorizationProvider;
+import org.apache.sentry.provider.file.PolicyFile;
+import org.apache.sentry.service.thrift.SentryService;
+import org.apache.sentry.service.thrift.SentryServiceFactory;
+import org.apache.sentry.service.thrift.ServiceConstants.ClientConfig;
+import org.apache.sentry.service.thrift.ServiceConstants.ServerConfig;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.apache.sentry.binding.solr.conf.SolrAuthzConf.AuthzConfVars;
+
+public class TestSentryServer implements Closeable {
+  private static final Logger log = LoggerFactory.getLogger(TestSentryServer.class);
+
+  protected static final String SERVER_HOST =
+      NetUtils.createSocketAddr("localhost:80").getAddress().getCanonicalHostName();
+  protected static final int PORT = 8038;
+  protected static final String ADMIN_GROUP = "admin_group";
+  static final String ADMIN_USER = "admin";
+
+  private final Path dbDir;
+  private final Path policyFilePath;
+  private final Path sentrySitePath;
+  private final Configuration clientConf;
+  private final SentryService sentryService;
+
+  public TestSentryServer(Path testDir, Map<String, Set<String>> groupsByUserName) throws Exception {
+    this.dbDir = testDir.resolve("sentry_policy_db");
+    this.policyFilePath = testDir.resolve("local_policy_file.ini");
+    this.sentrySitePath = testDir.resolve("sentry-site.xml");
+    this.sentryService = new SentryServiceFactory().create(getServerConfig());
+    this.clientConf = getClientConfig();
+    // Write sentry-site.xml
+    this.clientConf.writeXml(new FileOutputStream(this.sentrySitePath.toFile()));
+    // Write sentry policy file (for storing user-group mappings).
+    PolicyFile policyFile = new PolicyFile();
+    for (Map.Entry<String, Set<String>> userGroupMapping : groupsByUserName.entrySet()) {
+      String userName = userGroupMapping.getKey();
+      for (String groupName : userGroupMapping.getValue()) {
+        log.info("Configuring user-group mapping with userName : {} group: {}", userName, groupName);
+        policyFile.addGroupsToUser(userName, groupName);
+      }
+    }
+
+    policyFile.write(this.policyFilePath.toFile());
+  }
+
+  public SentryService getSentryService() {
+    return sentryService;
+  }
+
+  public Path getSentrySitePath() {
+    return sentrySitePath;
+  }
+
+  public void startSentryService() throws Exception {
+    sentryService.start();
+    final long start = System.nanoTime();
+    while(!sentryService.isRunning()) {
+      Thread.sleep(1000);
+      if (TimeUnit.NANOSECONDS.toSeconds(System.nanoTime() - start) > 60) {
+        throw new TimeoutException("Server did not start after 60 seconds");
+      }
+    }
+  }
+
+  public SentryGenericServiceClient connectToSentryService() throws Exception {
+    return SentryGenericServiceClientFactory.create(this.clientConf);
+  }
+
+  @Override
+  public void close() throws IOException {
+    if (this.sentryService != null) {
+      try {
+        this.sentryService.stop();
+      } catch (Exception e) {
+        throw new IOException(e);
+      }
+    }
+  }
+
+  private Configuration getServerConfig () {
+    Configuration conf = new Configuration(false);
+    conf.set(ServerConfig.SECURITY_MODE, ServerConfig.SECURITY_MODE_NONE);
+    conf.set(ServerConfig.SENTRY_VERIFY_SCHEM_VERSION, "false");
+    conf.set(ServerConfig.ADMIN_GROUPS, ADMIN_GROUP + ",solr");
+    conf.set(ServerConfig.RPC_ADDRESS, SERVER_HOST);
+    conf.set(ServerConfig.RPC_PORT, String.valueOf(PORT));
+    conf.set(ServerConfig.SENTRY_STORE_JDBC_URL,
+        "jdbc:derby:;databaseName=" + dbDir + ";create=true");
+    conf.set(ServerConfig.SENTRY_STORE_JDBC_PASS, "dummy");
+    conf.set(ServerConfig.SENTRY_STORE_GROUP_MAPPING,
+        ServerConfig.SENTRY_STORE_LOCAL_GROUP_MAPPING);
+    conf.set(ServerConfig.SENTRY_STORE_GROUP_MAPPING_RESOURCE,
+        policyFilePath.toString());
+    return conf;
+  }
+
+  private Configuration getClientConfig() {
+    Configuration conf = new Configuration(false);
+    conf.set(ServerConfig.SECURITY_MODE, ServerConfig.SECURITY_MODE_NONE);
+    conf.set(ClientConfig.SERVER_RPC_ADDRESS, sentryService.getAddress().getHostName());
+    conf.set(ClientConfig.SERVER_RPC_PORT, String.valueOf(sentryService.getAddress().getPort()));
+    conf.set(AuthzConfVars.AUTHZ_PROVIDER_BACKEND.getVar(),
+        SentryGenericProviderBackend.class.getName());
+    conf.set("sentry.provider",
+        LocalGroupResourceAuthorizationProvider.class.getName());
+    conf.set("sentry.solr.provider.resource",
+        policyFilePath.toString());
+    return conf;
+  }
+}

http://git-wip-us.apache.org/repos/asf/sentry/blob/e62fa28d/sentry-tests/sentry-tests-solr/src/test/java/org/apache/sentry/tests/e2e/solr/TestSolrAdminOperations.java
----------------------------------------------------------------------
diff --git a/sentry-tests/sentry-tests-solr/src/test/java/org/apache/sentry/tests/e2e/solr/TestSolrAdminOperations.java b/sentry-tests/sentry-tests-solr/src/test/java/org/apache/sentry/tests/e2e/solr/TestSolrAdminOperations.java
new file mode 100644
index 0000000..190b9d4
--- /dev/null
+++ b/sentry-tests/sentry-tests-solr/src/test/java/org/apache/sentry/tests/e2e/solr/TestSolrAdminOperations.java
@@ -0,0 +1,188 @@
+/*
+ * 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.solr;
+
+import static org.apache.sentry.tests.e2e.solr.TestSentryServer.ADMIN_USER;
+import static org.apache.sentry.core.model.solr.AdminOperation.COLLECTIONS;
+
+import java.io.IOException;
+import java.util.Map;
+
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.sentry.core.model.solr.AdminOperation;
+import org.apache.sentry.core.model.solr.SolrConstants;
+import org.apache.solr.client.solrj.SolrServerException;
+import org.apache.solr.client.solrj.impl.HttpSolrClient.RemoteSolrException;
+import org.apache.solr.client.solrj.request.CollectionAdminRequest;
+import org.apache.solr.client.solrj.request.CollectionAdminRequest.ClusterStatus;
+import org.apache.solr.SolrTestCaseJ4.SuppressSSL;
+import org.junit.Test;
+import org.restlet.data.MediaType;
+import org.restlet.resource.ClientResource;
+import org.restlet.resource.ResourceException;
+
+@SuppressSSL
+public class TestSolrAdminOperations extends AbstractSolrSentryTestCase {
+
+  @Test
+  public void testQueryAdminOperation() throws Exception {
+    // Success.
+    adminQueryActionSuccess(ADMIN_USER);
+    // Failure
+    adminQueryActionFailure("user0");
+    // Now grant admin privileges to user0 (i.e. role0) and verify the admin operations again.
+    grantAdminPrivileges(ADMIN_USER, "role0", COLLECTIONS.getName(), SolrConstants.ALL);
+    adminQueryActionSuccess("user0");
+    // Now revoke admin update privileges from user0 (i.e. role0) and verify the admin operations again.
+    revokeAdminPrivileges(ADMIN_USER, "role0", COLLECTIONS.getName(), SolrConstants.UPDATE);
+    adminQueryActionSuccess("user0");
+    // Now revoke admin query privileges from user0 (i.e. role0) and verify the admin operations again.
+    revokeAdminPrivileges(ADMIN_USER, "role0", COLLECTIONS.getName(), SolrConstants.QUERY);
+    adminQueryActionFailure("user0");
+  }
+
+  @Test
+  public void testUpdateAdminOperation() throws Exception {
+    String collectionName = "testUpdateAdminOperation";
+
+    // Success.
+    grantCollectionPrivileges(ADMIN_USER, ADMIN_ROLE, collectionName, SolrConstants.UPDATE);
+    adminUpdateActionSuccess(ADMIN_USER, collectionName);
+
+    // Failure
+    adminUpdateActionFailure("user0", collectionName);
+
+    // Now grant admin privileges role0 and verify the admin operations again.
+    grantAdminPrivileges(ADMIN_USER, "role0", COLLECTIONS.getName(), SolrConstants.ALL);
+    grantCollectionPrivileges(ADMIN_USER, "role0", collectionName, SolrConstants.UPDATE);
+    adminUpdateActionSuccess("user0", collectionName);
+
+    // Now revoke admin query privileges from role0 and verify the admin operations again.
+    revokeAdminPrivileges(ADMIN_USER, "role0", COLLECTIONS.getName(), SolrConstants.QUERY);
+    adminUpdateActionSuccess(ADMIN_USER, collectionName);
+
+    // Now revoke admin update privileges from role0 and verify the admin operations again.
+    revokeAdminPrivileges(ADMIN_USER, "role0", COLLECTIONS.getName(), SolrConstants.UPDATE);
+    adminUpdateActionFailure("user0", collectionName);
+  }
+
+  @SuppressWarnings("rawtypes")
+  @Test
+  public void testMetricsQuerySuccess() throws Exception {
+    grantAdminPrivileges(ADMIN_USER, "role0", AdminOperation.METRICS.getName(), SolrConstants.QUERY);
+
+    String tmp = getAuthenticatedUser();
+    try {
+      setAuthenticationUser("user0");
+
+      String url = String.format("%s/admin/metrics?wt=json&group=jvm",
+          cluster.getJettySolrRunner(0).getBaseUrl().toString());
+      ClientResource resource = new ClientResource(url);
+      Map result = readNestedElement(deserialize(resource.get(MediaType.APPLICATION_JSON)), "metrics");
+      assertTrue(result.containsKey("solr.jvm"));
+
+    } finally {
+      revokeAdminPrivileges(ADMIN_USER, "role0", AdminOperation.METRICS.getName(), SolrConstants.QUERY);
+      setAuthenticationUser(tmp);
+    }
+  }
+
+  @Test
+  public void testMetricsQueryFailure() throws Exception {
+    String tmp = getAuthenticatedUser();
+    try {
+      setAuthenticationUser("user1");
+
+      String url = String.format("%s/admin/metrics?wt=json",
+          cluster.getJettySolrRunner(0).getBaseUrl().toString());
+      ClientResource resource = new ClientResource(url);
+      resource.get(MediaType.APPLICATION_JSON);
+      fail("This admin request should have failed with authorization error.");
+
+    } catch (ResourceException ex) {
+      assertEquals(HttpServletResponse.SC_FORBIDDEN , ex.getStatus().getCode());
+    } finally {
+      setAuthenticationUser(tmp);
+    }
+  }
+
+  protected void adminQueryActionSuccess(String userName) throws SolrServerException, IOException {
+    String tmp = getAuthenticatedUser();
+    try {
+      setAuthenticationUser(userName);
+      ClusterStatus clusterStatus = new ClusterStatus();
+      assertEquals(0, clusterStatus.process(cluster.getSolrClient()).getStatus());
+
+    } finally {
+      setAuthenticationUser(tmp);
+    }
+  }
+
+  protected void adminQueryActionFailure(String userName) throws SolrServerException, IOException {
+    String tmp = getAuthenticatedUser();
+    try {
+      setAuthenticationUser(userName);
+      ClusterStatus clusterStatus = new ClusterStatus();
+      clusterStatus.process(cluster.getSolrClient());
+      fail("This admin request should have failed with authorization error.");
+
+    } catch (RemoteSolrException ex) {
+      assertEquals(HttpServletResponse.SC_FORBIDDEN , ex.code());
+    } finally {
+      setAuthenticationUser(tmp);
+    }
+  }
+
+  protected void adminUpdateActionSuccess(String userName, String collectionName)
+      throws SolrServerException, IOException {
+    // Success.
+    String tmp = getAuthenticatedUser();
+    try {
+      // Create collection.
+      setAuthenticationUser(userName);
+      CollectionAdminRequest.Create createCmd =
+          CollectionAdminRequest.createCollection(collectionName, "cloud-minimal", 1, NUM_SERVERS);
+      assertEquals(0, createCmd.process(cluster.getSolrClient()).getStatus());
+
+      // Delete collection.
+      CollectionAdminRequest.Delete delCmd = CollectionAdminRequest.deleteCollection(collectionName);
+      assertEquals(0, delCmd.process(cluster.getSolrClient()).getStatus());
+
+    } finally {
+      setAuthenticationUser(tmp);
+    }
+  }
+
+  protected void adminUpdateActionFailure(String userName, String collectionName)
+      throws SolrServerException, IOException {
+    String tmp = getAuthenticatedUser();
+    try {
+      setAuthenticationUser(userName); // This user doesn't have admin permissions
+      // Create collection.
+      CollectionAdminRequest.Create createCmd =
+          CollectionAdminRequest.createCollection(collectionName, "cloud-minimal", 1, NUM_SERVERS);
+      createCmd.process(cluster.getSolrClient());
+      fail("This admin request should have failed with authorization error.");
+
+    } catch (RemoteSolrException ex) {
+      assertEquals(HttpServletResponse.SC_FORBIDDEN , ex.code());
+    } finally {
+      setAuthenticationUser(tmp);
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/sentry/blob/e62fa28d/sentry-tests/sentry-tests-solr/src/test/java/org/apache/sentry/tests/e2e/solr/TestSolrCollectionOperations.java
----------------------------------------------------------------------
diff --git a/sentry-tests/sentry-tests-solr/src/test/java/org/apache/sentry/tests/e2e/solr/TestSolrCollectionOperations.java b/sentry-tests/sentry-tests-solr/src/test/java/org/apache/sentry/tests/e2e/solr/TestSolrCollectionOperations.java
new file mode 100644
index 0000000..3d9faa0
--- /dev/null
+++ b/sentry-tests/sentry-tests-solr/src/test/java/org/apache/sentry/tests/e2e/solr/TestSolrCollectionOperations.java
@@ -0,0 +1,141 @@
+/*
+ * 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.solr;
+
+import static org.apache.sentry.tests.e2e.solr.TestSentryServer.ADMIN_USER;
+
+import java.io.IOException;
+
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.sentry.core.model.solr.SolrConstants;
+import org.apache.solr.client.solrj.SolrQuery;
+import org.apache.solr.client.solrj.SolrServerException;
+import org.apache.solr.client.solrj.impl.HttpSolrClient.RemoteSolrException;
+import org.apache.solr.common.SolrDocument;
+import org.apache.solr.common.SolrDocumentList;
+import org.apache.solr.common.SolrInputDocument;
+import org.apache.solr.common.SolrInputField;
+import org.junit.Test;
+
+
+public class TestSolrCollectionOperations extends AbstractSolrSentryTestCase {
+
+  @Test
+  public void testQueryOperations() throws Exception {
+    String collectionName = "testCollectionQueryOps";
+
+    // Create collection as an admin user.
+    grantCollectionPrivileges(ADMIN_USER, ADMIN_ROLE, collectionName, SolrConstants.UPDATE);
+    createCollection(ADMIN_USER, collectionName, "cloud-minimal", NUM_SERVERS, 1);
+
+    // Grant all privileges for the test collection to role0
+    grantCollectionPrivileges(ADMIN_USER, "role0", collectionName, SolrConstants.ALL);
+
+    cleanSolrCollection("user0", collectionName);
+
+    SolrInputDocument solrInputDoc = createSolrTestDoc();
+    uploadSolrDoc("user0", collectionName, solrInputDoc);
+    SolrDocumentList expectedDocs = expectedDocs(solrInputDoc);
+
+    validateSolrDocCountAndContent(expectedDocs,
+        getSolrDocs("user0", collectionName, ALL_DOCS));
+
+    revokeCollectionPrivileges(ADMIN_USER, "role0", collectionName, SolrConstants.UPDATE);
+    validateSolrDocCountAndContent(expectedDocs,
+        getSolrDocs("user0", collectionName, ALL_DOCS));
+
+    revokeCollectionPrivileges(ADMIN_USER, "role0", collectionName, SolrConstants.QUERY);
+    verifyCollectionQueryFailure("user0", collectionName, ALL_DOCS);
+
+    verifyCollectionQueryFailure("user1", collectionName, ALL_DOCS);
+  }
+
+  @Test
+  public void testUpdateOperations() throws Exception {
+    String collectionName = "testCollectionUpdateOps";
+
+    // Create collection as an admin user.
+    grantCollectionPrivileges(ADMIN_USER, ADMIN_ROLE, collectionName, SolrConstants.UPDATE);
+    createCollection(ADMIN_USER, collectionName, "cloud-minimal", 1, NUM_SERVERS);
+
+    // Grant all privileges for the test collection to role0
+    grantCollectionPrivileges(ADMIN_USER, "role0", collectionName, SolrConstants.ALL);
+
+    cleanSolrCollection("user0", collectionName);
+
+    SolrInputDocument solrInputDoc = createSolrTestDoc();
+    uploadSolrDoc("user0", collectionName, solrInputDoc);
+    SolrDocumentList expectedDocs = expectedDocs(solrInputDoc);
+
+    validateSolrDocCountAndContent(expectedDocs,
+        getSolrDocs("user0", collectionName, ALL_DOCS));
+
+    verifyDeletedocsPass("user0", collectionName, false);
+
+    revokeCollectionPrivileges(ADMIN_USER, "role0", collectionName, SolrConstants.ALL);
+
+    verifyCollectionUpdateFailure("user0", collectionName, solrInputDoc);
+    verifyCollectionUpdateFailure("user1", collectionName, solrInputDoc);
+  }
+
+
+  protected void verifyCollectionUpdateFailure(String userName, String collectionName,
+      SolrInputDocument doc) throws SolrServerException, IOException {
+    String tmp = getAuthenticatedUser();
+    try {
+      setAuthenticationUser(userName);
+      cluster.getSolrClient().add(collectionName, doc);
+      cluster.getSolrClient().commit(collectionName);
+      fail("This collection query request should have failed with authorization error.");
+
+    } catch (RemoteSolrException ex) {
+      assertEquals(HttpServletResponse.SC_FORBIDDEN, ex.code());
+    } finally {
+      setAuthenticationUser(tmp);
+    }
+  }
+
+  protected void verifyCollectionQueryFailure(String userName, String collectionName,
+      String queryStr) throws SolrServerException, IOException {
+    String tmp = getAuthenticatedUser();
+    try {
+      setAuthenticationUser(userName);
+      cluster.getSolrClient().query(collectionName, new SolrQuery(queryStr));
+      fail("This collection query request should have failed with authorization error.");
+
+    } catch (SolrServerException ex) {
+      assertTrue(ex.getRootCause() instanceof RemoteSolrException);
+      assertEquals(HttpServletResponse.SC_FORBIDDEN, ((RemoteSolrException)ex.getRootCause()).code());
+    } finally {
+      setAuthenticationUser(tmp);
+    }
+  }
+
+  protected SolrDocumentList expectedDocs(SolrInputDocument... docs) {
+    SolrDocumentList result = new SolrDocumentList();
+
+    for (SolrInputDocument doc : docs) {
+      SolrDocument r = new SolrDocument();
+      for (SolrInputField field : doc) {
+        r.setField(field.getName(), field.getValue());
+      }
+      result.add(r);
+    }
+    return result;
+  }
+}

http://git-wip-us.apache.org/repos/asf/sentry/blob/e62fa28d/sentry-tests/sentry-tests-solr/src/test/java/org/apache/sentry/tests/e2e/solr/TestSolrConfigOperations.java
----------------------------------------------------------------------
diff --git a/sentry-tests/sentry-tests-solr/src/test/java/org/apache/sentry/tests/e2e/solr/TestSolrConfigOperations.java b/sentry-tests/sentry-tests-solr/src/test/java/org/apache/sentry/tests/e2e/solr/TestSolrConfigOperations.java
new file mode 100644
index 0000000..620825f
--- /dev/null
+++ b/sentry-tests/sentry-tests-solr/src/test/java/org/apache/sentry/tests/e2e/solr/TestSolrConfigOperations.java
@@ -0,0 +1,232 @@
+/*
+ * 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.solr;
+
+import static org.apache.sentry.tests.e2e.solr.TestSentryServer.ADMIN_USER;
+
+import java.io.IOException;
+import java.util.Map;
+
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.sentry.core.model.solr.SolrConstants;
+import org.apache.solr.SolrTestCaseJ4.SuppressSSL;
+import org.apache.solr.client.solrj.SolrServerException;
+import org.apache.solr.client.solrj.impl.HttpSolrClient.RemoteSolrException;
+import org.apache.solr.client.solrj.request.ConfigSetAdminRequest;
+import org.apache.solr.client.solrj.response.ConfigSetAdminResponse;
+import org.junit.Test;
+import org.restlet.data.MediaType;
+import org.restlet.resource.ClientResource;
+import org.restlet.resource.ResourceException;
+
+@SuppressSSL
+public class TestSolrConfigOperations extends AbstractSolrSentryTestCase {
+  @Test
+  public void testConfigSetOperations() throws Exception {
+    grantConfigPrivileges(ADMIN_USER, "role0", "test", SolrConstants.UPDATE);
+    grantConfigPrivileges(ADMIN_USER, "role1", SolrConstants.ALL, SolrConstants.QUERY);
+
+    configSetCreationSuccess("user0", "test", "cloud-minimal");
+
+    ConfigSetAdminResponse resp = configSetListSuccess("user1");
+    assertEquals(2, resp.getResponse().size());
+
+    configSetDeleteSuccess("user0", "test");
+
+    configSetCreationFailure("user1", "test1", "cloud-minimal");
+    configSetListFailure("user0");
+  }
+
+  @Test
+  public void testConfigOperations() throws Exception {
+    String collectionName = "testConfigOperations";
+
+    grantConfigPrivileges(ADMIN_USER, "role0", collectionName, SolrConstants.ALL);
+    grantConfigPrivileges(ADMIN_USER, "role1", SolrConstants.ALL, SolrConstants.QUERY);
+
+    grantCollectionPrivileges(ADMIN_USER, ADMIN_ROLE, collectionName, SolrConstants.UPDATE);
+    createCollection(ADMIN_USER, collectionName, "cloud-minimal", NUM_SERVERS, 1);
+
+    configReadSuccess("user1", collectionName);
+    configReadSuccess("user0", collectionName);
+    configUpdateSuccess("user0", collectionName);
+
+    revokeConfigPrivileges(ADMIN_USER, "role0", collectionName, SolrConstants.QUERY);
+    configReadFailure ("user0", collectionName);
+  }
+
+  @SuppressWarnings("rawtypes")
+  protected void configReadSuccess( String userName, String collectionName)
+      throws ResourceException, IOException {
+    String tmp = getAuthenticatedUser();
+    try {
+      setAuthenticationUser(userName);
+
+      Map result = queryHandlerConfig(collectionName, "/select");
+      assertEquals("/select", (String)readNestedElement(result,
+          "config", "requestHandler", "/select", "name"));
+      assertEquals("solr.SearchHandler", (String)readNestedElement(result,
+          "config", "requestHandler", "/select", "class"));
+      assertEquals("explicit", (String)readNestedElement(result,
+          "config", "requestHandler", "/select", "defaults", "echoParams"));
+
+    } finally {
+      setAuthenticationUser(tmp);
+    }
+  }
+
+  protected void configReadFailure( String userName, String collectionName)
+      throws ResourceException, IOException {
+    String tmp = getAuthenticatedUser();
+    try {
+      setAuthenticationUser(userName);
+
+      queryHandlerConfig(collectionName, "/select");
+      fail("This config query request should have failed with authorization error.");
+
+    } catch (ResourceException ex) {
+      assertEquals(HttpServletResponse.SC_FORBIDDEN, ex.getStatus().getCode());
+    } finally {
+      setAuthenticationUser(tmp);
+    }
+  }
+
+  @SuppressWarnings("rawtypes")
+  protected void configUpdateSuccess( String userName, String collectionName)
+      throws ResourceException, IOException {
+
+    String configToBeAdded = "{" +
+                                "\"add-requesthandler\" : { " +
+                                "\"name\": \"/mypath\"," +
+                                "\"class\":\"solr.DumpRequestHandler\", " +
+                                "\"defaults\":{ \"x\":\"y\" ,\"a\":\"b\"," +
+                                " \"wt\":\"json\", \"indent\":true }," +
+                                "\"useParams\":\"x\"}}";
+
+    String tmp = getAuthenticatedUser();
+    try {
+      setAuthenticationUser(userName);
+      String url = String.format("%s/%s/config",
+          cluster.getJettySolrRunner(0).getBaseUrl().toString(), collectionName);
+
+      ClientResource resource = new ClientResource(url);
+      Map updateResp = deserialize(resource.post(configToBeAdded, MediaType.APPLICATION_JSON));
+      assertEquals(0, (long)readNestedElement(updateResp, "responseHeader", "status"));
+
+      Map result = queryHandlerConfig(collectionName, "/mypath");
+      assertEquals("/mypath", (String)readNestedElement(result,
+          "config", "requestHandler", "/mypath", "name"));
+      assertEquals("solr.DumpRequestHandler", (String)readNestedElement(result,
+          "config", "requestHandler", "/mypath", "class"));
+      assertEquals("y", (String)readNestedElement(result,
+          "config", "requestHandler", "/mypath", "defaults", "x"));
+
+    } finally {
+      setAuthenticationUser(tmp);
+    }
+  }
+
+  protected void configSetCreationSuccess(String userName, String configName,
+      String baseConfigSetName) throws SolrServerException, IOException {
+    String tmp = getAuthenticatedUser();
+    try {
+      setAuthenticationUser(userName);
+      ConfigSetAdminRequest.Create create = new ConfigSetAdminRequest.Create();
+      create.setBaseConfigSetName(baseConfigSetName);
+      create.setConfigSetName(configName);
+      assertEquals(0, create.process(cluster.getSolrClient()).getStatus());
+
+    } finally {
+      setAuthenticationUser(tmp);
+    }
+  }
+
+  protected void configSetCreationFailure(String userName, String configName,
+      String baseConfigSetName) throws SolrServerException, IOException {
+    String tmp = getAuthenticatedUser();
+    try {
+      setAuthenticationUser(userName);
+      ConfigSetAdminRequest.Create create = new ConfigSetAdminRequest.Create();
+      create.setBaseConfigSetName(baseConfigSetName);
+      create.setConfigSetName(configName);
+      create.process(cluster.getSolrClient());
+      fail("This config request should have failed with authorization error.");
+
+    } catch (RemoteSolrException ex) {
+      assertEquals(HttpServletResponse.SC_FORBIDDEN , ex.code());
+    } finally {
+      setAuthenticationUser(tmp);
+    }
+  }
+
+  protected void configSetDeleteSuccess(String userName, String configName)
+      throws SolrServerException, IOException {
+    String tmp = getAuthenticatedUser();
+    try {
+      setAuthenticationUser(userName);
+      ConfigSetAdminRequest.Delete delete = new ConfigSetAdminRequest.Delete();
+      delete.setConfigSetName(configName);
+      assertEquals(0, delete.process(cluster.getSolrClient()).getStatus());
+
+    } finally {
+      setAuthenticationUser(tmp);
+    }
+  }
+
+  protected ConfigSetAdminResponse configSetListSuccess(String userName)
+      throws SolrServerException, IOException {
+    String tmp = getAuthenticatedUser();
+    try {
+      setAuthenticationUser(userName);
+      ConfigSetAdminRequest.List list = new ConfigSetAdminRequest.List();
+      ConfigSetAdminResponse resp = list.process(cluster.getSolrClient());
+      assertEquals(0, resp.getStatus());
+      return resp;
+
+    } finally {
+      setAuthenticationUser(tmp);
+    }
+  }
+
+  protected void configSetListFailure(String userName)
+      throws SolrServerException, IOException {
+    String tmp = getAuthenticatedUser();
+    try {
+      setAuthenticationUser(userName);
+      ConfigSetAdminRequest.List list = new ConfigSetAdminRequest.List();
+      list.process(cluster.getSolrClient());
+      fail("This config request should have failed with authorization error.");
+
+    } catch (RemoteSolrException ex) {
+      assertEquals(HttpServletResponse.SC_FORBIDDEN , ex.code());
+    } finally {
+      setAuthenticationUser(tmp);
+    }
+  }
+
+  @SuppressWarnings("rawtypes")
+  protected Map queryHandlerConfig(String collectionName, String handlerPath) throws ResourceException, IOException {
+    String url = String.format("%s/%s/config/requestHandler?componentName=%s",
+        cluster.getJettySolrRunner(0).getBaseUrl().toString(), collectionName, handlerPath);
+
+    Map result = deserialize(new ClientResource(url).get());
+    assertEquals(0, (long)readNestedElement(result, "responseHeader", "status"));
+
+    return result;
+  }
+}

http://git-wip-us.apache.org/repos/asf/sentry/blob/e62fa28d/sentry-tests/sentry-tests-solr/src/test/java/org/apache/sentry/tests/e2e/solr/TestSolrSchemaOperations.java
----------------------------------------------------------------------
diff --git a/sentry-tests/sentry-tests-solr/src/test/java/org/apache/sentry/tests/e2e/solr/TestSolrSchemaOperations.java b/sentry-tests/sentry-tests-solr/src/test/java/org/apache/sentry/tests/e2e/solr/TestSolrSchemaOperations.java
new file mode 100644
index 0000000..1169b54
--- /dev/null
+++ b/sentry-tests/sentry-tests-solr/src/test/java/org/apache/sentry/tests/e2e/solr/TestSolrSchemaOperations.java
@@ -0,0 +1,146 @@
+/*
+ * 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.solr;
+
+import static org.apache.sentry.tests.e2e.solr.TestSentryServer.ADMIN_USER;
+
+import java.io.IOException;
+import java.util.Map;
+
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.sentry.core.model.solr.SolrConstants;
+import org.apache.solr.SolrTestCaseJ4.SuppressSSL;
+import org.junit.Test;
+import org.restlet.data.MediaType;
+import org.restlet.resource.ClientResource;
+import org.restlet.resource.ResourceException;
+
+@SuppressSSL
+public class TestSolrSchemaOperations extends AbstractSolrSentryTestCase {
+  private static final String fieldToBeAdded = "{ " +
+      "\"add-field\":{" +
+      "\"name\":\"test\"," +
+      "\"type\":\"string\"," +
+      "\"stored\":true }}";
+
+
+  @Test
+  public void testSolrSchemaOperations()  throws Exception {
+    String collectionName = "testSolrSchemaOperations";
+
+    grantSchemaPrivileges(ADMIN_USER, "role0", collectionName, SolrConstants.ALL);
+
+    grantCollectionPrivileges(ADMIN_USER, ADMIN_ROLE, collectionName, SolrConstants.UPDATE);
+    createCollection(ADMIN_USER, collectionName, "cloud-managed", NUM_SERVERS, 1);
+
+    schemaReadSuccess("user0", collectionName);
+    schemaUpdateSuccess("user0", collectionName);
+
+    revokeSchemaPrivileges(ADMIN_USER, "role0", collectionName, SolrConstants.QUERY);
+    schemaReadFailure("user0", collectionName);
+
+    revokeSchemaPrivileges(ADMIN_USER, "role0", collectionName, SolrConstants.UPDATE);
+    schemaUpdateFailure("user0", collectionName);
+  }
+
+
+  @SuppressWarnings("rawtypes")
+  protected void schemaReadSuccess( String userName, String collectionName) throws ResourceException, IOException {
+    String tmp = getAuthenticatedUser();
+    try {
+      setAuthenticationUser(userName);
+
+      Map result = querySchemaConfig(collectionName, "name?wt=json");
+      assertEquals("minimal", readNestedElement(result, "name"));
+
+      result = querySchemaConfig(collectionName, "version?wt=json");
+      assertEquals(new Double(1.1d), (Double)readNestedElement(result, "version"));
+
+    } finally {
+      setAuthenticationUser(tmp);
+    }
+  }
+
+  protected void schemaReadFailure( String userName, String collectionName) throws ResourceException, IOException {
+    String tmp = getAuthenticatedUser();
+    try {
+      setAuthenticationUser(userName);
+
+      querySchemaConfig(collectionName, "name?wt=json");
+      fail("This schema query request should have failed with authorization error.");
+
+    } catch (ResourceException ex) {
+      assertEquals(HttpServletResponse.SC_FORBIDDEN, ex.getStatus().getCode());
+    } finally {
+      setAuthenticationUser(tmp);
+    }
+  }
+
+  @SuppressWarnings("rawtypes")
+  protected void schemaUpdateSuccess( String userName, String collectionName) throws ResourceException, IOException {
+    String tmp = getAuthenticatedUser();
+    try {
+      setAuthenticationUser(userName);
+
+      String url = String.format("%s/%s/schema",
+          cluster.getJettySolrRunner(0).getBaseUrl().toString(), collectionName);
+      ClientResource resource = new ClientResource(url);
+      Map updateResp = deserialize(resource.post(fieldToBeAdded, MediaType.APPLICATION_JSON));
+      assertEquals(0, (long)readNestedElement(updateResp, "responseHeader", "status"));
+
+      Map result = querySchemaConfig(collectionName, "fields/test");
+      assertEquals("test", readNestedElement(result, "field", "name"));
+      assertEquals("string", readNestedElement(result, "field", "type"));
+      assertEquals(true, readNestedElement(result, "field", "stored"));
+
+    } finally {
+      setAuthenticationUser(tmp);
+    }
+  }
+
+  protected void schemaUpdateFailure( String userName, String collectionName) throws ResourceException, IOException {
+    String tmp = getAuthenticatedUser();
+    try {
+      setAuthenticationUser(userName);
+
+      String url = String.format("%s/%s/schema",
+          cluster.getJettySolrRunner(0).getBaseUrl().toString(), collectionName);
+      ClientResource resource = new ClientResource(url);
+      resource.post(fieldToBeAdded, MediaType.APPLICATION_JSON);
+      fail("This schema update request should have failed with authorization error.");
+
+    } catch (ResourceException ex) {
+      assertEquals(HttpServletResponse.SC_FORBIDDEN, ex.getStatus().getCode());
+    } finally {
+      setAuthenticationUser(tmp);
+    }
+  }
+
+  @SuppressWarnings("rawtypes")
+  protected Map querySchemaConfig(String collectionName, String reqPath) throws ResourceException, IOException {
+    String url = String.format("%s/%s/schema/%s",
+        cluster.getJettySolrRunner(0).getBaseUrl().toString(), collectionName, reqPath);
+    System.out.println("^^^:"+url);
+
+    Map result = deserialize(new ClientResource(url).get());
+    assertEquals(0, (long)readNestedElement(result, "responseHeader", "status"));
+
+    return result;
+  }
+
+}