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;
+ }
+
+}