http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/60bb1003/sentry-solr/solr-sentry-handlers/src/main/resources/sentry-handlers/solr/collection1/conf/solrconfig-secureadmin.xml
----------------------------------------------------------------------
diff --git 
a/sentry-solr/solr-sentry-handlers/src/main/resources/sentry-handlers/solr/collection1/conf/solrconfig-secureadmin.xml
 
b/sentry-solr/solr-sentry-handlers/src/main/resources/sentry-handlers/solr/collection1/conf/solrconfig-secureadmin.xml
new file mode 100644
index 0000000..6cf234a
--- /dev/null
+++ 
b/sentry-solr/solr-sentry-handlers/src/main/resources/sentry-handlers/solr/collection1/conf/solrconfig-secureadmin.xml
@@ -0,0 +1,494 @@
+<?xml version="1.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.
+-->
+
+<!-- This is a "kitchen sink" config file that tests can use.
+     When writting a new test, feel free to add *new* items (plugins,
+     config options, etc...) as long as they don't break any existing
+     tests.  if you need to test something esoteric please add a new
+     "solrconfig-your-esoteric-purpose.xml" config file.
+
+     Note in particular that this test is used by MinimalSchemaTest so
+     Anything added to this file needs to work correctly even if there
+     is now uniqueKey or defaultSearch Field.
+  -->
+
+<config>
+
+  <jmx />
+
+  <!-- Used to specify an alternate directory to hold all index data.
+       It defaults to "index" if not present, and should probably
+       not be changed if replication is in use. -->
+  <dataDir>${solr.data.dir:}</dataDir>
+
+  <!--  The DirectoryFactory to use for indexes.
+        solr.StandardDirectoryFactory, the default, is filesystem based.
+        solr.RAMDirectoryFactory is memory based and not persistent. -->
+  <directoryFactory name="DirectoryFactory" 
class="${solr.directoryFactory:solr.RAMDirectoryFactory}">
+    <double name="maxWriteMBPerSecDefault">1000000</double>
+    <double name="maxWriteMBPerSecFlush">2000000</double>
+    <double name="maxWriteMBPerSecMerge">3000000</double>
+    <double name="maxWriteMBPerSecRead">4000000</double>
+    <str name="solr.hdfs.home">${solr.hdfs.home:}</str>
+    <bool 
name="solr.hdfs.blockcache.enabled">${solr.hdfs.blockcache.enabled:true}</bool>
+  </directoryFactory>
+
+  
<luceneMatchVersion>${tests.luceneMatchVersion:LUCENE_CURRENT}</luceneMatchVersion>
+
+  <indexConfig>
+    <mergeScheduler class="org.apache.lucene.index.ConcurrentMergeScheduler"/>
+    <writeLockTimeout>1000</writeLockTimeout>
+    <mergeFactor>8</mergeFactor>
+    <useCompoundFile>${useCompoundFile:false}</useCompoundFile>
+    <!-- for better multi-segment testing, we are using slower
+    indexing properties of maxBufferedDocs=10 and LogDocMergePolicy.
+    -->
+    <maxBufferedDocs>10</maxBufferedDocs>
+    <mergePolicy class="org.apache.lucene.index.LogDocMergePolicy"/>
+    <lockType>native</lockType>
+    <unlockOnStartup>true</unlockOnStartup>
+  </indexConfig>
+  
+  <updateHandler class="solr.DirectUpdateHandler2">
+
+    <!-- autocommit pending docs if certain criteria are met
+    <autoCommit>
+      <maxDocs>10000</maxDocs>
+      <maxTime>3600000</maxTime>
+    </autoCommit>
+    -->
+    <!-- represents a lower bound on the frequency that commits may
+    occur (in seconds). NOTE: not yet implemented
+
+    <commitIntervalLowerBound>0</commitIntervalLowerBound>
+    -->
+
+    <!-- The RunExecutableListener executes an external command.
+         exe - the name of the executable to run
+         dir - dir to use as the current working directory. default="."
+         wait - the calling thread waits until the executable returns. 
default="true"
+         args - the arguments to pass to the program.  default=nothing
+         env - environment variables to set.  default=nothing
+      -->
+    <!-- A postCommit event is fired after every commit
+    <listener event="postCommit" class="solr.RunExecutableListener">
+      <str name="exe">/var/opt/resin3/__PORT__/scripts/solr/snapshooter</str>
+      <str name="dir">/var/opt/resin3/__PORT__</str>
+      <bool name="wait">true</bool>
+      <arr name="args"> <str>arg1</str> <str>arg2</str> </arr>
+      <arr name="env"> <str>MYVAR=val1</str> </arr>
+    </listener>
+    -->
+    
+    <updateLog enable="${enable.update.log:true}">
+         <str name="dir">${solr.ulog.dir:}</str>
+    </updateLog> 
+    
+    <commitWithin>
+      <softCommit>${solr.commitwithin.softcommit:true}</softCommit>
+    </commitWithin>
+
+  </updateHandler>
+
+  <query>
+    <!-- Maximum number of clauses in a boolean query... can affect
+        range or wildcard queries that expand to big boolean
+        queries.  An exception is thrown if exceeded.
+    -->
+    <maxBooleanClauses>1024</maxBooleanClauses>
+
+    <!-- Cache specification for Filters or DocSets - unordered set of *all* 
documents
+         that match a particular query.
+      -->
+    <filterCache
+      class="solr.search.FastLRUCache"
+      size="512"
+      initialSize="512"
+      autowarmCount="2"/>
+
+    <queryResultCache
+      class="solr.search.LRUCache"
+      size="512"
+      initialSize="512"
+      autowarmCount="2"/>
+
+    <documentCache
+      class="solr.search.LRUCache"
+      size="512"
+      initialSize="512"
+      autowarmCount="0"/>
+
+    <!-- If true, stored fields that are not requested will be loaded lazily.
+    -->
+    <enableLazyFieldLoading>true</enableLazyFieldLoading>
+
+    <!--
+
+    <cache name="myUserCache"
+      class="solr.search.LRUCache"
+      size="4096"
+      initialSize="1024"
+      autowarmCount="1024"
+      regenerator="MyRegenerator"
+      />
+    -->
+
+    <!--
+    <useFilterForSortedQuery>true</useFilterForSortedQuery>
+    -->
+
+    <queryResultWindowSize>10</queryResultWindowSize>
+
+    <!-- set maxSize artificially low to exercise both types of sets -->
+    <HashDocSet maxSize="3" loadFactor="0.75"/>
+
+    <!-- boolToFilterOptimizer converts boolean clauses with zero boost
+         into cached filters if the number of docs selected by the clause 
exceeds
+         the threshold (represented as a fraction of the total index)
+    -->
+    <boolTofilterOptimizer enabled="false" cacheSize="32" threshold=".05"/>
+
+    <!-- a newSearcher event is fired whenever a new searcher is being prepared
+         and there is a current searcher handling requests (aka registered). 
-->
+    <!-- QuerySenderListener takes an array of NamedList and executes a
+         local query request for each NamedList in sequence. -->
+    <!--
+    <listener event="newSearcher" class="solr.QuerySenderListener">
+      <arr name="queries">
+        <lst> <str name="q">solr</str> <str name="start">0</str> <str 
name="rows">10</str> </lst>
+        <lst> <str name="q">rocks</str> <str name="start">0</str> <str 
name="rows">10</str> </lst>
+      </arr>
+    </listener>
+    -->
+
+    <!-- a firstSearcher event is fired whenever a new searcher is being
+         prepared but there is no current registered searcher to handle
+         requests or to gain prewarming data from. -->
+    <!--
+    <listener event="firstSearcher" class="solr.QuerySenderListener">
+      <arr name="queries">
+        <lst> <str name="q">fast_warm</str> <str name="start">0</str> <str 
name="rows">10</str> </lst>
+      </arr>
+    </listener>
+    -->
+
+  </query>
+  
+  <queryResponseWriter name="xml" default="true"
+                       class="solr.XMLResponseWriter" />
+
+  <requestHandler name="/replication" class="solr.SecureReplicationHandler" 
startup="lazy" /> 
+
+  <!-- An alternate set representation that uses an integer hash to store 
filters (sets of docids).
+       If the set cardinality <= maxSize elements, then HashDocSet will be 
used instead of the bitset
+       based HashBitset. -->
+
+  <!-- requestHandler plugins... incoming queries will be dispatched to the
+     correct handler based on the 'qt' param matching the
+     name of registered handlers.
+      The "standard" request handler is the default and will be used if qt
+     is not specified in the request.
+  -->
+  <requestHandler name="standard" class="solr.StandardRequestHandler">
+       <bool name="httpCaching">true</bool>
+  </requestHandler>
+
+  <requestHandler name="/get" class="solr.RealTimeGetHandler">
+     <lst name="defaults">
+       <str name="omitHeader">true</str>
+     </lst>
+  </requestHandler>
+
+  <requestHandler name="dismax" class="solr.SearchHandler" >
+    <lst name="defaults">
+     <str name="defType">dismax</str>
+     <str name="q.alt">*:*</str>
+     <float name="tie">0.01</float>
+     <str name="qf">
+        text^0.5 features_t^1.0 subject^1.4 title_stemmed^2.0
+     </str>
+     <str name="pf">
+        text^0.2 features_t^1.1 subject^1.4 title_stemmed^2.0 title^1.5
+     </str>
+     <str name="bf">
+        ord(weight)^0.5 recip(rord(iind),1,1000,1000)^0.3
+     </str>
+     <str name="mm">
+        3&lt;-1 5&lt;-2 6&lt;90%
+     </str>
+     <int name="ps">100</int>
+    </lst>
+  </requestHandler>
+
+  <requestHandler name="/admin/" 
class="org.apache.solr.handler.admin.SecureAdminHandlers" />
+
+  <!-- test query parameter defaults -->
+  <requestHandler name="defaults" class="solr.StandardRequestHandler">
+    <lst name="defaults">
+      <int name="rows">4</int>
+      <bool name="hl">true</bool>
+      <str name="hl.fl">text,name,subject,title,whitetok</str>
+    </lst>
+  </requestHandler>
+
+  <!-- test query parameter defaults -->
+  <requestHandler name="lazy" class="solr.StandardRequestHandler" 
startup="lazy">
+    <lst name="defaults">
+      <int name="rows">4</int>
+      <bool name="hl">true</bool>
+      <str name="hl.fl">text,name,subject,title,whitetok</str>
+    </lst>
+  </requestHandler>
+
+  <requestHandler name="/update" class="solr.UpdateRequestHandler"  />
+
+  <!-- Field Analysis Request Handler
+
+       RequestHandler that provides much the same functionality as
+       analysis.jsp. Provides the ability to specify multiple field
+       types and field names in the same request and outputs
+       index-time and query-time analysis for each of them.
+
+       Request parameters are:
+       analysis.fieldname - field name whose analyzers are to be used
+
+       analysis.fieldtype - field type whose analyzers are to be used
+       analysis.fieldvalue - text for index-time analysis
+       q (or analysis.q) - text for query time analysis
+       analysis.showmatch (true|false) - When set to true and when
+           query analysis is performed, the produced tokens of the
+           field value analysis will be marked as "matched" for every
+           token that is produces by the query analysis
+   -->
+  <requestHandler name="/analysis/field" 
+                  startup="lazy"
+                  class="solr.SecureFieldAnalysisRequestHandler" />
+
+  <!-- Document Analysis Handler
+
+       http://wiki.apache.org/solr/AnalysisRequestHandler
+
+       An analysis handler that provides a breakdown of the analysis
+       process of provided documents. This handler expects a (single)
+       content stream with the following format:
+
+       <docs>
+         <doc>
+           <field name="id">1</field>
+           <field name="name">The Name</field>
+           <field name="text">The Text Value</field>
+         </doc>
+         <doc>...</doc>
+         <doc>...</doc>
+         ...
+       </docs>
+
+    Note: Each document must contain a field which serves as the
+    unique key. This key is used in the returned response to associate
+    an analysis breakdown to the analyzed document.
+
+    Like the FieldAnalysisRequestHandler, this handler also supports
+    query analysis by sending either an "analysis.query" or "q"
+    request parameter that holds the query text to be analyzed. It
+    also supports the "analysis.showmatch" parameter which when set to
+    true, all field tokens that match the query tokens will be marked
+    as a "match". 
+  -->
+  <requestHandler name="/analysis/document" 
+                  class="solr.SecureDocumentAnalysisRequestHandler" 
+                  startup="lazy" />
+
+  <searchComponent name="termsComp" 
class="org.apache.solr.handler.component.TermsComponent"/>
+
+  <requestHandler name="/terms" 
class="org.apache.solr.handler.component.SearchHandler">
+    <arr name="components">
+      <str>termsComp</str>
+    </arr>
+  </requestHandler>
+  <!--
+  The SpellingQueryConverter to convert raw (CommonParams.Q) queries into 
tokens.  Uses a simple regular expression
+   to strip off field markup, boosts, ranges, etc. but it is not guaranteed to 
match an exact parse from the query parser.
+   -->
+  <queryConverter name="queryConverter" 
class="org.apache.solr.spelling.SpellingQueryConverter"/>
+ 
+  <requestHandler name="mltrh" 
class="org.apache.solr.handler.component.SearchHandler">
+
+  </requestHandler>
+
+  <searchComponent name="tvComponent" 
class="org.apache.solr.handler.component.TermVectorComponent"/>
+
+  <requestHandler name="tvrh" 
class="org.apache.solr.handler.component.SearchHandler">
+    <lst name="defaults">
+
+    </lst>
+    <arr name="last-components">
+      <str>tvComponent</str>
+    </arr>
+  </requestHandler>
+
+  <requestHandler name="/mlt" class="solr.MoreLikeThisHandler">
+  </requestHandler>
+
+  <searchComponent class="solr.HighlightComponent" name="highlight">
+  <highlighting>
+   <!-- Configure the standard fragmenter -->
+   <fragmenter name="gap" class="org.apache.solr.highlight.GapFragmenter" 
default="true">
+    <lst name="defaults">
+     <int name="hl.fragsize">100</int>
+    </lst>
+   </fragmenter>
+
+   <fragmenter name="regex" class="org.apache.solr.highlight.RegexFragmenter">
+    <lst name="defaults">
+     <int name="hl.fragsize">70</int>
+    </lst>
+   </fragmenter>
+
+   <!-- Configure the standard formatter -->
+   <formatter name="html" class="org.apache.solr.highlight.HtmlFormatter" 
default="true">
+    <lst name="defaults">
+     <str name="hl.simple.pre"><![CDATA[<em>]]></str>
+     <str name="hl.simple.post"><![CDATA[</em>]]></str>
+    </lst>
+   </formatter>
+
+   <!-- Configure the standard fragListBuilder -->
+   <fragListBuilder name="simple" 
class="org.apache.solr.highlight.SimpleFragListBuilder" default="true"/>
+
+   <!-- Configure the standard fragmentsBuilder -->
+   <fragmentsBuilder name="simple" 
class="org.apache.solr.highlight.SimpleFragmentsBuilder" default="true"/>
+   <fragmentsBuilder name="scoreOrder" 
class="org.apache.solr.highlight.ScoreOrderFragmentsBuilder"/>
+
+   <boundaryScanner name="simple" class="solr.highlight.SimpleBoundaryScanner" 
default="true">
+     <lst name="defaults">
+       <str name="hl.bs.maxScan">10</str>
+       <str name="hl.bs.chars">.,!? &#9;&#10;&#13;</str>
+     </lst>
+   </boundaryScanner>
+
+   <boundaryScanner name="breakIterator" 
class="solr.highlight.BreakIteratorBoundaryScanner">
+     <lst name="defaults">
+       <str name="hl.bs.type">WORD</str>
+       <str name="hl.bs.language">en</str>
+       <str name="hl.bs.country">US</str>
+     </lst>
+   </boundaryScanner>
+  </highlighting>
+  </searchComponent>
+
+  <!-- enable streaming for testing... -->
+  <requestDispatcher handleSelect="true" >
+    <requestParsers enableRemoteStreaming="true" 
multipartUploadLimitInKB="2048" />
+    <httpCaching lastModifiedFrom="openTime" etagSeed="Solr" never304="false">
+      <cacheControl>max-age=30, public</cacheControl>
+    </httpCaching>
+  </requestDispatcher>
+
+  <!-- Echo the request contents back to the client -->
+  <requestHandler name="/debug/dump" class="solr.DumpRequestHandler" >
+    <lst name="defaults">
+      <str name="echoParams">explicit</str>
+      <str name="echoHandler">true</str>
+    </lst>
+  </requestHandler>
+
+  <admin>
+    <defaultQuery>solr</defaultQuery>
+    <gettableFiles>solrconfig-secureadmin.xml schema.xml 
admin-extra.html</gettableFiles>
+  </admin>
+
+  <!-- test getting system property -->
+  <propTest attr1="${solr.test.sys.prop1}-$${literal}"
+            
attr2="${non.existent.sys.prop:default-from-config}">prefix-${solr.test.sys.prop2}-suffix</propTest>
+
+  <updateRequestProcessorChain name="dedupe">
+    <processor 
class="org.apache.solr.update.processor.SignatureUpdateProcessorFactory">
+      <bool name="enabled">false</bool>
+      <bool name="overwriteDupes">true</bool>
+      <str name="fields">v_t,t_field</str>
+      <str 
name="signatureClass">org.apache.solr.update.processor.TextProfileSignature</str>
+    </processor>
+    <processor class="solr.RunUpdateProcessorFactory" />
+  </updateRequestProcessorChain>
+  <updateRequestProcessorChain name="dedupe-allfields">
+    <processor 
class="org.apache.solr.update.processor.SignatureUpdateProcessorFactory">
+      <bool name="enabled">false</bool>
+      <bool name="overwriteDupes">false</bool>
+      <str name="signatureField">id</str>
+      <str name="fields"></str>
+      <str 
name="signatureClass">org.apache.solr.update.processor.Lookup3Signature</str>
+    </processor>
+    <processor class="solr.RunUpdateProcessorFactory" />
+  </updateRequestProcessorChain>
+  <updateRequestProcessorChain name="stored_sig">
+    <!-- this chain is valid even though the signature field is not
+         indexed, because we are not asking for dups to be overwritten
+      -->
+    <processor 
class="org.apache.solr.update.processor.SignatureUpdateProcessorFactory">
+      <bool name="enabled">true</bool>
+      <str name="signatureField">non_indexed_signature_sS</str>
+      <bool name="overwriteDupes">false</bool>
+      <str name="fields">v_t,t_field</str>
+      <str 
name="signatureClass">org.apache.solr.update.processor.TextProfileSignature</str>
+    </processor>
+    <processor class="solr.RunUpdateProcessorFactory" />
+  </updateRequestProcessorChain>
+  <updateRequestProcessorChain name="uniq-fields">
+    <processor 
class="org.apache.solr.update.processor.UniqFieldsUpdateProcessorFactory">
+      <lst name="fields">
+        <str>uniq</str>
+        <str>uniq2</str>
+        <str>uniq3</str>
+      </lst>      
+    </processor>
+    <processor class="solr.RunUpdateProcessorFactory" />
+  </updateRequestProcessorChain>  
+
+  <updateRequestProcessorChain name="distrib-dup-test-chain-explicit">
+    <!-- explicit test using processors before and after distrib -->
+    <processor class="solr.RegexReplaceProcessorFactory">
+      <str name="fieldName">regex_dup_A_s</str>
+      <str name="pattern">x</str>
+      <str name="replacement">x_x</str>
+    </processor>
+    <processor class="solr.DistributedUpdateProcessorFactory" />
+    <processor class="solr.RegexReplaceProcessorFactory">
+      <str name="fieldName">regex_dup_B_s</str>
+      <str name="pattern">x</str>
+      <str name="replacement">x_x</str>
+    </processor>
+    <processor class="solr.RunUpdateProcessorFactory" />
+  </updateRequestProcessorChain>  
+
+  <updateRequestProcessorChain name="distrib-dup-test-chain-implicit">
+    <!-- implicit test w/o distrib declared-->
+    <processor class="solr.RegexReplaceProcessorFactory">
+      <str name="fieldName">regex_dup_A_s</str>
+      <str name="pattern">x</str>
+      <str name="replacement">x_x</str>
+    </processor>
+    <processor class="solr.RegexReplaceProcessorFactory">
+      <str name="fieldName">regex_dup_B_s</str>
+      <str name="pattern">x</str>
+      <str name="replacement">x_x</str>
+    </processor>
+    <processor class="solr.RunUpdateProcessorFactory" />
+  </updateRequestProcessorChain>  
+
+</config>

http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/60bb1003/sentry-solr/solr-sentry-handlers/src/main/resources/sentry-handlers/solr/collection1/conf/solrconfig.xml
----------------------------------------------------------------------
diff --git 
a/sentry-solr/solr-sentry-handlers/src/main/resources/sentry-handlers/solr/collection1/conf/solrconfig.xml
 
b/sentry-solr/solr-sentry-handlers/src/main/resources/sentry-handlers/solr/collection1/conf/solrconfig.xml
new file mode 100644
index 0000000..f15d137
--- /dev/null
+++ 
b/sentry-solr/solr-sentry-handlers/src/main/resources/sentry-handlers/solr/collection1/conf/solrconfig.xml
@@ -0,0 +1,436 @@
+<?xml version="1.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.
+-->
+
+<!-- This is a "kitchen sink" config file that tests can use.
+     When writting a new test, feel free to add *new* items (plugins,
+     config options, etc...) as long as they don't break any existing
+     tests.  if you need to test something esoteric please add a new
+     "solrconfig-your-esoteric-purpose.xml" config file.
+
+     Note in particular that this test is used by MinimalSchemaTest so
+     Anything added to this file needs to work correctly even if there
+     is now uniqueKey or defaultSearch Field.
+  -->
+
+<config>
+
+  <jmx />
+
+  <!-- Used to specify an alternate directory to hold all index data.
+       It defaults to "index" if not present, and should probably
+       not be changed if replication is in use. -->
+  <dataDir>${solr.data.dir:}</dataDir>
+
+  <!--  The DirectoryFactory to use for indexes.
+        solr.StandardDirectoryFactory, the default, is filesystem based.
+        solr.RAMDirectoryFactory is memory based and not persistent. -->
+  <directoryFactory name="DirectoryFactory" 
class="${solr.directoryFactory:solr.RAMDirectoryFactory}">
+    <double name="maxWriteMBPerSecDefault">1000000</double>
+    <double name="maxWriteMBPerSecFlush">2000000</double>
+    <double name="maxWriteMBPerSecMerge">3000000</double>
+    <double name="maxWriteMBPerSecRead">4000000</double>
+  </directoryFactory>
+
+  
<luceneMatchVersion>${tests.luceneMatchVersion:LUCENE_CURRENT}</luceneMatchVersion>
+
+  <indexConfig>
+    <mergeScheduler class="org.apache.lucene.index.ConcurrentMergeScheduler"/>
+    <writeLockTimeout>1000</writeLockTimeout>
+    <mergeFactor>8</mergeFactor>
+    <useCompoundFile>${useCompoundFile:false}</useCompoundFile>
+    <!-- for better multi-segment testing, we are using slower
+    indexing properties of maxBufferedDocs=10 and LogDocMergePolicy.
+    -->
+    <maxBufferedDocs>10</maxBufferedDocs>
+    <mergePolicy class="org.apache.lucene.index.LogDocMergePolicy"/>
+    <lockType>native</lockType>
+    <unlockOnStartup>true</unlockOnStartup>
+  </indexConfig>
+  
+  <updateHandler class="solr.DirectUpdateHandler2">
+
+    <!-- autocommit pending docs if certain criteria are met
+    <autoCommit>
+      <maxDocs>10000</maxDocs>
+      <maxTime>3600000</maxTime>
+    </autoCommit>
+    -->
+    <!-- represents a lower bound on the frequency that commits may
+    occur (in seconds). NOTE: not yet implemented
+
+    <commitIntervalLowerBound>0</commitIntervalLowerBound>
+    -->
+
+    <!-- The RunExecutableListener executes an external command.
+         exe - the name of the executable to run
+         dir - dir to use as the current working directory. default="."
+         wait - the calling thread waits until the executable returns. 
default="true"
+         args - the arguments to pass to the program.  default=nothing
+         env - environment variables to set.  default=nothing
+      -->
+    <!-- A postCommit event is fired after every commit
+    <listener event="postCommit" class="solr.RunExecutableListener">
+      <str name="exe">/var/opt/resin3/__PORT__/scripts/solr/snapshooter</str>
+      <str name="dir">/var/opt/resin3/__PORT__</str>
+      <bool name="wait">true</bool>
+      <arr name="args"> <str>arg1</str> <str>arg2</str> </arr>
+      <arr name="env"> <str>MYVAR=val1</str> </arr>
+    </listener>
+    -->
+    
+    <updateLog enable="${enable.update.log:true}">
+         <str name="dir">${solr.ulog.dir:}</str>
+    </updateLog> 
+    
+    <commitWithin>
+      <softCommit>${solr.commitwithin.softcommit:true}</softCommit>
+    </commitWithin>
+
+  </updateHandler>
+
+  <query>
+    <!-- Maximum number of clauses in a boolean query... can affect
+        range or wildcard queries that expand to big boolean
+        queries.  An exception is thrown if exceeded.
+    -->
+    <maxBooleanClauses>1024</maxBooleanClauses>
+
+    <!-- Cache specification for Filters or DocSets - unordered set of *all* 
documents
+         that match a particular query.
+      -->
+    <filterCache
+      class="solr.search.FastLRUCache"
+      size="512"
+      initialSize="512"
+      autowarmCount="2"/>
+
+    <queryResultCache
+      class="solr.search.LRUCache"
+      size="512"
+      initialSize="512"
+      autowarmCount="2"/>
+
+    <documentCache
+      class="solr.search.LRUCache"
+      size="512"
+      initialSize="512"
+      autowarmCount="0"/>
+
+    <!-- If true, stored fields that are not requested will be loaded lazily.
+    -->
+    <enableLazyFieldLoading>true</enableLazyFieldLoading>
+
+    <!--
+
+    <cache name="myUserCache"
+      class="solr.search.LRUCache"
+      size="4096"
+      initialSize="1024"
+      autowarmCount="1024"
+      regenerator="MyRegenerator"
+      />
+    -->
+
+    <!--
+    <useFilterForSortedQuery>true</useFilterForSortedQuery>
+    -->
+
+    <queryResultWindowSize>10</queryResultWindowSize>
+
+    <!-- set maxSize artificially low to exercise both types of sets -->
+    <HashDocSet maxSize="3" loadFactor="0.75"/>
+
+    <!-- boolToFilterOptimizer converts boolean clauses with zero boost
+         into cached filters if the number of docs selected by the clause 
exceeds
+         the threshold (represented as a fraction of the total index)
+    -->
+    <boolTofilterOptimizer enabled="false" cacheSize="32" threshold=".05"/>
+
+    <!-- a newSearcher event is fired whenever a new searcher is being prepared
+         and there is a current searcher handling requests (aka registered). 
-->
+    <!-- QuerySenderListener takes an array of NamedList and executes a
+         local query request for each NamedList in sequence. -->
+    <!--
+    <listener event="newSearcher" class="solr.QuerySenderListener">
+      <arr name="queries">
+        <lst> <str name="q">solr</str> <str name="start">0</str> <str 
name="rows">10</str> </lst>
+        <lst> <str name="q">rocks</str> <str name="start">0</str> <str 
name="rows">10</str> </lst>
+      </arr>
+    </listener>
+    -->
+
+    <!-- a firstSearcher event is fired whenever a new searcher is being
+         prepared but there is no current registered searcher to handle
+         requests or to gain prewarming data from. -->
+    <!--
+    <listener event="firstSearcher" class="solr.QuerySenderListener">
+      <arr name="queries">
+        <lst> <str name="q">fast_warm</str> <str name="start">0</str> <str 
name="rows">10</str> </lst>
+      </arr>
+    </listener>
+    -->
+
+  </query>
+  
+  <queryResponseWriter name="xml" default="true"
+                       class="solr.XMLResponseWriter" />
+
+  <requestHandler name="/replication" class="solr.ReplicationHandler" 
startup="lazy" /> 
+
+  <!-- An alternate set representation that uses an integer hash to store 
filters (sets of docids).
+       If the set cardinality <= maxSize elements, then HashDocSet will be 
used instead of the bitset
+       based HashBitset. -->
+
+  <!-- requestHandler plugins... incoming queries will be dispatched to the
+     correct handler based on the 'qt' param matching the
+     name of registered handlers.
+      The "standard" request handler is the default and will be used if qt
+     is not specified in the request.
+  -->
+  <requestHandler name="standard" class="solr.StandardRequestHandler">
+       <bool name="httpCaching">true</bool>
+  </requestHandler>
+
+  <requestHandler name="/get" class="solr.RealTimeGetHandler">
+     <lst name="defaults">
+       <str name="omitHeader">true</str>
+     </lst>
+  </requestHandler>
+
+  <requestHandler name="dismax" class="solr.SearchHandler" >
+    <lst name="defaults">
+     <str name="defType">dismax</str>
+     <str name="q.alt">*:*</str>
+     <float name="tie">0.01</float>
+     <str name="qf">
+        text^0.5 features_t^1.0 subject^1.4 title_stemmed^2.0
+     </str>
+     <str name="pf">
+        text^0.2 features_t^1.1 subject^1.4 title_stemmed^2.0 title^1.5
+     </str>
+     <str name="bf">
+        ord(weight)^0.5 recip(rord(iind),1,1000,1000)^0.3
+     </str>
+     <str name="mm">
+        3&lt;-1 5&lt;-2 6&lt;90%
+     </str>
+     <int name="ps">100</int>
+    </lst>
+  </requestHandler>
+
+  <requestHandler name="/admin/" 
class="org.apache.solr.handler.admin.AdminHandlers" />
+
+  <!-- test query parameter defaults -->
+  <requestHandler name="defaults" class="solr.StandardRequestHandler">
+    <lst name="defaults">
+      <int name="rows">4</int>
+      <bool name="hl">true</bool>
+      <str name="hl.fl">text,name,subject,title,whitetok</str>
+    </lst>
+  </requestHandler>
+
+  <!-- test query parameter defaults -->
+  <requestHandler name="lazy" class="solr.StandardRequestHandler" 
startup="lazy">
+    <lst name="defaults">
+      <int name="rows">4</int>
+      <bool name="hl">true</bool>
+      <str name="hl.fl">text,name,subject,title,whitetok</str>
+    </lst>
+  </requestHandler>
+
+  <requestHandler name="/update" class="solr.UpdateRequestHandler"  />
+
+  <searchComponent name="termsComp" 
class="org.apache.solr.handler.component.TermsComponent"/>
+
+  <requestHandler name="/terms" 
class="org.apache.solr.handler.component.SearchHandler">
+    <arr name="components">
+      <str>termsComp</str>
+    </arr>
+  </requestHandler>
+  <!--
+  The SpellingQueryConverter to convert raw (CommonParams.Q) queries into 
tokens.  Uses a simple regular expression
+   to strip off field markup, boosts, ranges, etc. but it is not guaranteed to 
match an exact parse from the query parser.
+   -->
+  <queryConverter name="queryConverter" 
class="org.apache.solr.spelling.SpellingQueryConverter"/>
+ 
+  <requestHandler name="mltrh" 
class="org.apache.solr.handler.component.SearchHandler">
+
+  </requestHandler>
+
+  <searchComponent name="tvComponent" 
class="org.apache.solr.handler.component.TermVectorComponent"/>
+
+  <requestHandler name="tvrh" 
class="org.apache.solr.handler.component.SearchHandler">
+    <lst name="defaults">
+
+    </lst>
+    <arr name="last-components">
+      <str>tvComponent</str>
+    </arr>
+  </requestHandler>
+
+  <requestHandler name="/mlt" class="solr.MoreLikeThisHandler">
+  </requestHandler>
+
+  <searchComponent class="solr.HighlightComponent" name="highlight">
+  <highlighting>
+   <!-- Configure the standard fragmenter -->
+   <fragmenter name="gap" class="org.apache.solr.highlight.GapFragmenter" 
default="true">
+    <lst name="defaults">
+     <int name="hl.fragsize">100</int>
+    </lst>
+   </fragmenter>
+
+   <fragmenter name="regex" class="org.apache.solr.highlight.RegexFragmenter">
+    <lst name="defaults">
+     <int name="hl.fragsize">70</int>
+    </lst>
+   </fragmenter>
+
+   <!-- Configure the standard formatter -->
+   <formatter name="html" class="org.apache.solr.highlight.HtmlFormatter" 
default="true">
+    <lst name="defaults">
+     <str name="hl.simple.pre"><![CDATA[<em>]]></str>
+     <str name="hl.simple.post"><![CDATA[</em>]]></str>
+    </lst>
+   </formatter>
+
+   <!-- Configure the standard fragListBuilder -->
+   <fragListBuilder name="simple" 
class="org.apache.solr.highlight.SimpleFragListBuilder" default="true"/>
+
+   <!-- Configure the standard fragmentsBuilder -->
+   <fragmentsBuilder name="simple" 
class="org.apache.solr.highlight.SimpleFragmentsBuilder" default="true"/>
+   <fragmentsBuilder name="scoreOrder" 
class="org.apache.solr.highlight.ScoreOrderFragmentsBuilder"/>
+
+   <boundaryScanner name="simple" class="solr.highlight.SimpleBoundaryScanner" 
default="true">
+     <lst name="defaults">
+       <str name="hl.bs.maxScan">10</str>
+       <str name="hl.bs.chars">.,!? &#9;&#10;&#13;</str>
+     </lst>
+   </boundaryScanner>
+
+   <boundaryScanner name="breakIterator" 
class="solr.highlight.BreakIteratorBoundaryScanner">
+     <lst name="defaults">
+       <str name="hl.bs.type">WORD</str>
+       <str name="hl.bs.language">en</str>
+       <str name="hl.bs.country">US</str>
+     </lst>
+   </boundaryScanner>
+  </highlighting>
+  </searchComponent>
+
+  <!-- enable streaming for testing... -->
+  <requestDispatcher handleSelect="true" >
+    <requestParsers enableRemoteStreaming="true" 
multipartUploadLimitInKB="2048" />
+    <httpCaching lastModifiedFrom="openTime" etagSeed="Solr" never304="false">
+      <cacheControl>max-age=30, public</cacheControl>
+    </httpCaching>
+  </requestDispatcher>
+
+  <!-- Echo the request contents back to the client -->
+  <requestHandler name="/debug/dump" class="solr.DumpRequestHandler" >
+    <lst name="defaults">
+      <str name="echoParams">explicit</str>
+      <str name="echoHandler">true</str>
+    </lst>
+  </requestHandler>
+
+  <admin>
+    <defaultQuery>solr</defaultQuery>
+    <gettableFiles>solrconfig.xml schema.xml admin-extra.html</gettableFiles>
+  </admin>
+
+  <!-- test getting system property -->
+  <propTest attr1="${solr.test.sys.prop1}-$${literal}"
+            
attr2="${non.existent.sys.prop:default-from-config}">prefix-${solr.test.sys.prop2}-suffix</propTest>
+
+  <updateRequestProcessorChain name="dedupe">
+    <processor 
class="org.apache.solr.update.processor.SignatureUpdateProcessorFactory">
+      <bool name="enabled">false</bool>
+      <bool name="overwriteDupes">true</bool>
+      <str name="fields">v_t,t_field</str>
+      <str 
name="signatureClass">org.apache.solr.update.processor.TextProfileSignature</str>
+    </processor>
+    <processor class="solr.RunUpdateProcessorFactory" />
+  </updateRequestProcessorChain>
+  <updateRequestProcessorChain name="dedupe-allfields">
+    <processor 
class="org.apache.solr.update.processor.SignatureUpdateProcessorFactory">
+      <bool name="enabled">false</bool>
+      <bool name="overwriteDupes">false</bool>
+      <str name="signatureField">id</str>
+      <str name="fields"></str>
+      <str 
name="signatureClass">org.apache.solr.update.processor.Lookup3Signature</str>
+    </processor>
+    <processor class="solr.RunUpdateProcessorFactory" />
+  </updateRequestProcessorChain>
+  <updateRequestProcessorChain name="stored_sig">
+    <!-- this chain is valid even though the signature field is not
+         indexed, because we are not asking for dups to be overwritten
+      -->
+    <processor 
class="org.apache.solr.update.processor.SignatureUpdateProcessorFactory">
+      <bool name="enabled">true</bool>
+      <str name="signatureField">non_indexed_signature_sS</str>
+      <bool name="overwriteDupes">false</bool>
+      <str name="fields">v_t,t_field</str>
+      <str 
name="signatureClass">org.apache.solr.update.processor.TextProfileSignature</str>
+    </processor>
+    <processor class="solr.RunUpdateProcessorFactory" />
+  </updateRequestProcessorChain>
+  <updateRequestProcessorChain name="uniq-fields">
+    <processor 
class="org.apache.solr.update.processor.UniqFieldsUpdateProcessorFactory">
+      <lst name="fields">
+        <str>uniq</str>
+        <str>uniq2</str>
+        <str>uniq3</str>
+      </lst>      
+    </processor>
+    <processor class="solr.RunUpdateProcessorFactory" />
+  </updateRequestProcessorChain>  
+
+  <updateRequestProcessorChain name="distrib-dup-test-chain-explicit">
+    <!-- explicit test using processors before and after distrib -->
+    <processor class="solr.RegexReplaceProcessorFactory">
+      <str name="fieldName">regex_dup_A_s</str>
+      <str name="pattern">x</str>
+      <str name="replacement">x_x</str>
+    </processor>
+    <processor class="solr.DistributedUpdateProcessorFactory" />
+    <processor class="solr.RegexReplaceProcessorFactory">
+      <str name="fieldName">regex_dup_B_s</str>
+      <str name="pattern">x</str>
+      <str name="replacement">x_x</str>
+    </processor>
+    <processor class="solr.RunUpdateProcessorFactory" />
+  </updateRequestProcessorChain>  
+
+  <updateRequestProcessorChain name="distrib-dup-test-chain-implicit">
+    <!-- implicit test w/o distrib declared-->
+    <processor class="solr.RegexReplaceProcessorFactory">
+      <str name="fieldName">regex_dup_A_s</str>
+      <str name="pattern">x</str>
+      <str name="replacement">x_x</str>
+    </processor>
+    <processor class="solr.RegexReplaceProcessorFactory">
+      <str name="fieldName">regex_dup_B_s</str>
+      <str name="pattern">x</str>
+      <str name="replacement">x_x</str>
+    </processor>
+    <processor class="solr.RunUpdateProcessorFactory" />
+  </updateRequestProcessorChain>  
+
+</config>

http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/60bb1003/sentry-solr/solr-sentry-handlers/src/main/resources/sentry-handlers/solr/collection1/lib/README
----------------------------------------------------------------------
diff --git 
a/sentry-solr/solr-sentry-handlers/src/main/resources/sentry-handlers/solr/collection1/lib/README
 
b/sentry-solr/solr-sentry-handlers/src/main/resources/sentry-handlers/solr/collection1/lib/README
new file mode 100644
index 0000000..b7ca5b8
--- /dev/null
+++ 
b/sentry-solr/solr-sentry-handlers/src/main/resources/sentry-handlers/solr/collection1/lib/README
@@ -0,0 +1,18 @@
+<!--
+ 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.
+-->
+
+Items under this directory are used by TestConfig.testLibs()

http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/60bb1003/sentry-solr/solr-sentry-handlers/src/main/resources/sentry-handlers/solr/collection1/lib/classes/empty-file-main-lib.txt
----------------------------------------------------------------------
diff --git 
a/sentry-solr/solr-sentry-handlers/src/main/resources/sentry-handlers/solr/collection1/lib/classes/empty-file-main-lib.txt
 
b/sentry-solr/solr-sentry-handlers/src/main/resources/sentry-handlers/solr/collection1/lib/classes/empty-file-main-lib.txt
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ 
b/sentry-solr/solr-sentry-handlers/src/main/resources/sentry-handlers/solr/collection1/lib/classes/empty-file-main-lib.txt
@@ -0,0 +1 @@
+

http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/60bb1003/sentry-solr/solr-sentry-handlers/src/test/java/org/apache/solr/handler/TestSecureAnalysisHandlers.java
----------------------------------------------------------------------
diff --git 
a/sentry-solr/solr-sentry-handlers/src/test/java/org/apache/solr/handler/TestSecureAnalysisHandlers.java
 
b/sentry-solr/solr-sentry-handlers/src/test/java/org/apache/solr/handler/TestSecureAnalysisHandlers.java
new file mode 100644
index 0000000..28406e2
--- /dev/null
+++ 
b/sentry-solr/solr-sentry-handlers/src/test/java/org/apache/solr/handler/TestSecureAnalysisHandlers.java
@@ -0,0 +1,82 @@
+/*
+ * 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.solr.handler;
+
+import org.apache.solr.cloud.CloudDescriptor;
+import org.apache.solr.core.SolrCore;
+import org.apache.solr.request.SolrQueryRequest;
+import org.apache.solr.request.SolrRequestHandler;
+import org.apache.solr.sentry.SentryTestBase;
+import org.apache.solr.sentry.SentrySingletonTestInstance;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+public class TestSecureAnalysisHandlers extends SentryTestBase {
+
+  private static SolrCore core;
+  private static CloudDescriptor cloudDescriptor;
+
+   @BeforeClass
+  public static void beforeClass() throws Exception {
+    core = createCore("solrconfig-secureadmin.xml", "schema-minimal.xml");
+    // store the CloudDescriptor, because we will overwrite it with a mock
+    // and restore it later
+    cloudDescriptor = core.getCoreDescriptor().getCloudDescriptor();
+    // ensure the SentrySingletonTestInstance is initialized
+    SentrySingletonTestInstance.getInstance();
+  }
+
+  @AfterClass
+  public static void afterClass() throws Exception {
+    closeCore(core, cloudDescriptor);
+    core = null;
+    cloudDescriptor = null;
+  }
+
+  @Override
+  public void setUp() throws Exception {
+    super.setUp(core);
+  }
+
+  private SolrQueryRequest getAnalysisRequest(String collection, String user)
+      throws Exception {
+    SolrQueryRequest request = getRequest();
+    return prepareCollAndUser(core, request, collection, user);
+  }
+
+  private void verifyQueryAccess(SolrRequestHandler handler) throws Exception {
+    verifyAuthorized(handler, getAnalysisRequest("collection1", "junit"));
+    verifyAuthorized(handler, getAnalysisRequest("queryCollection", "junit"));
+    verifyUnauthorized(handler, getAnalysisRequest("bogusCollection", "junit"),
+      "bogusCollection", "junit");
+    verifyUnauthorized(handler, getAnalysisRequest("updateCollection", 
"junit"),
+      "updateCollection", "junit");
+  }
+
+  @Test
+  public void testSecureFieldAnalysisRequestHandler() throws Exception {
+    SolrRequestHandler handler = core.getRequestHandler("/analysis/field");
+    verifyQueryAccess(handler);
+  }
+
+  @Test
+  public void testDocumentAnalysisRequestHandler() throws Exception {
+    SolrRequestHandler handler = core.getRequestHandler("/analysis/document");
+    verifyQueryAccess(handler);
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/60bb1003/sentry-solr/solr-sentry-handlers/src/test/java/org/apache/solr/handler/TestSecureReplicationHandler.java
----------------------------------------------------------------------
diff --git 
a/sentry-solr/solr-sentry-handlers/src/test/java/org/apache/solr/handler/TestSecureReplicationHandler.java
 
b/sentry-solr/solr-sentry-handlers/src/test/java/org/apache/solr/handler/TestSecureReplicationHandler.java
new file mode 100644
index 0000000..9387677
--- /dev/null
+++ 
b/sentry-solr/solr-sentry-handlers/src/test/java/org/apache/solr/handler/TestSecureReplicationHandler.java
@@ -0,0 +1,64 @@
+/*
+ * 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.solr.handler;
+
+import org.apache.solr.cloud.CloudDescriptor;
+import org.apache.solr.core.SolrCore;
+import org.apache.solr.request.SolrQueryRequest;
+import org.apache.solr.request.SolrRequestHandler;
+import org.apache.solr.sentry.SentryTestBase;
+import org.apache.solr.sentry.SentrySingletonTestInstance;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+public class TestSecureReplicationHandler extends SentryTestBase {
+
+  private static SolrCore core;
+  private static CloudDescriptor cloudDescriptor;
+
+  @BeforeClass
+  public static void beforeClass() throws Exception {
+    core = createCore("solrconfig-secureadmin.xml", "schema-minimal.xml");
+    // store the CloudDescriptor, because we will overwrite it with a mock
+    // and restore it later
+    cloudDescriptor = core.getCoreDescriptor().getCloudDescriptor();
+    // ensure the SentrySingletonTestInstance is initialized
+    SentrySingletonTestInstance.getInstance();
+  }
+
+  @AfterClass
+  public static void afterClass() throws Exception {
+    closeCore(core, cloudDescriptor);
+    core = null;
+    cloudDescriptor = null;
+  }
+
+  @Override
+  public void setUp() throws Exception {
+    super.setUp(core);
+  }
+
+  @Test
+  public void testSecureReplicationHandler() throws Exception {
+    SolrRequestHandler handler = core.getRequestHandler("/replication");
+    verifyAuthorized(handler, prepareCollAndUser(core, getRequest(), 
"collection1", "junit", false));
+    verifyUnauthorized(handler, prepareCollAndUser(core, getRequest(), 
"queryCollection", "junit", false), "queryCollection", "junit");
+    verifyUnauthorized(handler, prepareCollAndUser(core, getRequest(), 
"bogusCollection", "junit", false), "bogusCollection", "junit");
+    verifyUnauthorized(handler, prepareCollAndUser(core, getRequest(), 
"updateCollection", "junit", false), "updateCollection", "junit");
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/60bb1003/sentry-solr/solr-sentry-handlers/src/test/java/org/apache/solr/handler/admin/SecureAdminHandlersTest.java
----------------------------------------------------------------------
diff --git 
a/sentry-solr/solr-sentry-handlers/src/test/java/org/apache/solr/handler/admin/SecureAdminHandlersTest.java
 
b/sentry-solr/solr-sentry-handlers/src/test/java/org/apache/solr/handler/admin/SecureAdminHandlersTest.java
new file mode 100644
index 0000000..3cb2597
--- /dev/null
+++ 
b/sentry-solr/solr-sentry-handlers/src/test/java/org/apache/solr/handler/admin/SecureAdminHandlersTest.java
@@ -0,0 +1,182 @@
+/*
+ * 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.solr.handler.admin;
+
+import java.util.Map;
+
+import org.apache.solr.handler.RequestHandlerBase;
+import org.apache.solr.cloud.CloudDescriptor;
+import org.apache.solr.common.SolrException;
+import org.apache.solr.core.SolrCore;
+import org.apache.solr.sentry.SentryTestBase;
+import org.apache.solr.request.SolrQueryRequest;
+import org.apache.solr.request.SolrRequestHandler;
+import org.apache.solr.response.SolrQueryResponse;
+import org.apache.solr.sentry.SentrySingletonTestInstance;
+import org.junit.AfterClass;
+import org.junit.Assert;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class SecureAdminHandlersTest extends SentryTestBase {
+
+  private static SolrCore core;
+  private static CloudDescriptor cloudDescriptor;
+
+  @BeforeClass
+  public static void beforeClass() throws Exception {
+    core = createCore("solrconfig-secureadmin.xml", "schema-minimal.xml");
+    // store the CloudDescriptor, because we will overwrite it with a mock
+    // and restore it later
+    cloudDescriptor = core.getCoreDescriptor().getCloudDescriptor();
+    // ensure SentrySingletonTestInstance is initialized
+    SentrySingletonTestInstance.getInstance();
+  }
+
+  @AfterClass
+  public static void afterClass() throws Exception {
+    closeCore(core, cloudDescriptor);
+    core = null;
+    cloudDescriptor = null;
+  }
+
+  @Override
+  public void setUp() throws Exception {
+    super.setUp(core);
+  }
+
+  @Test
+  public void testAllAdminHandlersSecured() throws Exception {
+    int numFound = 0;
+    for (Map.Entry<String, SolrRequestHandler> entry : 
core.getRequestHandlers().entrySet() ) {
+      // see note about ShowFileRequestHandler below
+      if (entry.getKey().startsWith("/admin/") && !(entry.getValue() 
instanceof ShowFileRequestHandler)) {
+         
assertTrue(entry.getValue().getClass().getEnclosingClass().equals(SecureAdminHandlers.class));
+         ++numFound;
+      }
+    }
+    assertTrue(numFound > 0);
+  }
+
+  @Test
+  public void testSecureAdminHandlers() throws Exception {
+    verifyLuke();
+    verifyMBeans();
+    verifyPlugins();
+    verifyThreads();
+    verifyProperties();
+    verifyLogging();
+    verifyFile();
+  }
+
+  private void verifyAuthorized(RequestHandlerBase handler, String collection, 
String user) throws Exception {
+    SolrQueryRequest req = getRequest();
+    prepareCollAndUser(core, req, collection, user, false);
+    // just ensure we don't get an unauthorized exception
+    try {
+      handler.handleRequestBody(req, new SolrQueryResponse());
+    } catch (SolrException ex) {
+      assertFalse(ex.code() == SolrException.ErrorCode.UNAUTHORIZED.code);
+    } catch (Throwable t) {
+      // okay, we only want to verify we didn't get an Unauthorized exception,
+      // going to treat each handler as a black box.
+    }
+  }
+
+  private void verifyUnauthorized(RequestHandlerBase handler,
+      String collection, String user, boolean shouldFailAdmin) throws 
Exception {
+    String exMsgContains = "User " + user + " does not have privileges for " + 
(shouldFailAdmin?"admin":collection);
+    SolrQueryRequest req = getRequest();
+    prepareCollAndUser(core, req, collection, user, false);
+    try {
+      handler.handleRequestBody(req, new SolrQueryResponse());
+      Assert.fail("Expected SolrException");
+    } catch (SolrException ex) {
+      assertEquals(ex.code(), SolrException.ErrorCode.UNAUTHORIZED.code);
+      assertTrue(ex.getMessage().contains(exMsgContains));
+    }
+  }
+
+  private void verifyQueryAccess(RequestHandlerBase handler, boolean 
checkCollection) throws Exception {
+    verifyAuthorized(handler, "collection1", "junit");
+    verifyAuthorized(handler, "queryCollection", "junit");
+    if (checkCollection) {
+      verifyUnauthorized(handler, "bogusCollection", "junit", false);
+      verifyUnauthorized(handler, "updateCollection", "junit", false);
+    } else {
+      verifyUnauthorized(handler, "collection1", "bogusUser", true);
+    }
+  }
+
+  private void verifyQueryAccess(String path, boolean checkCollection) throws 
Exception {
+    RequestHandlerBase handler =
+      (RequestHandlerBase)core.getRequestHandlers().get(path);
+    verifyQueryAccess(handler, checkCollection);
+  }
+
+  private void verifyQueryUpdateAccess(String path, boolean checkCollection) 
throws Exception {
+    RequestHandlerBase handler =
+      (RequestHandlerBase)core.getRequestHandlers().get(path);
+    verifyAuthorized(handler, "collection1", "junit");
+    verifyUnauthorized(handler, "collection1", "bogusUser", true);
+    if (checkCollection) {
+      verifyUnauthorized(handler, "queryCollection", "junit", false);
+      verifyUnauthorized(handler, "bogusCollection", "junit", false);
+      verifyUnauthorized(handler, "updateCollection", "junit", false);
+    }
+  }
+
+  private void verifyLuke() throws Exception {
+    verifyQueryAccess("/admin/luke", true);
+  }
+
+  private void verifySystem() throws Exception {
+    verifyQueryAccess("/admin/system", true);
+  }
+
+  private void verifyMBeans() throws Exception {
+    verifyQueryAccess("/admin/mbeans", true);
+  }
+
+  private void verifyPlugins() throws Exception {
+    verifyQueryAccess("/admin/plugins", true);
+  }
+
+  private void verifyThreads() throws Exception {
+    verifyQueryAccess("/admin/threads", false);
+  }
+
+  private void verifyProperties() throws Exception {
+    verifyQueryAccess("/admin/properties", false);
+  }
+
+  private void verifyLogging() throws Exception {
+    verifyQueryUpdateAccess("/admin/logging", false);
+  }
+
+  private void verifyFile() throws Exception {
+    // file handler is built-in for backwards compatibility reasons.  Thus,
+    // handler will not be secure, so let's create one to test.
+    String path = "/admin/file";
+    RequestHandlerBase handler = 
(RequestHandlerBase)core.getRequestHandlers().get(path);
+    assertFalse(handler instanceof 
SecureAdminHandlers.SecureShowFileRequestHandler);
+    handler = new SecureAdminHandlers.SecureShowFileRequestHandler();
+    verifyQueryAccess(handler, true);
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/60bb1003/sentry-solr/solr-sentry-handlers/src/test/java/org/apache/solr/handler/admin/SecureCollectionsHandlerTest.java
----------------------------------------------------------------------
diff --git 
a/sentry-solr/solr-sentry-handlers/src/test/java/org/apache/solr/handler/admin/SecureCollectionsHandlerTest.java
 
b/sentry-solr/solr-sentry-handlers/src/test/java/org/apache/solr/handler/admin/SecureCollectionsHandlerTest.java
new file mode 100644
index 0000000..218302e
--- /dev/null
+++ 
b/sentry-solr/solr-sentry-handlers/src/test/java/org/apache/solr/handler/admin/SecureCollectionsHandlerTest.java
@@ -0,0 +1,84 @@
+/*
+ * 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.solr.handler.admin;
+
+import org.apache.solr.cloud.CloudDescriptor;
+import org.apache.solr.core.SolrCore;
+import org.apache.solr.common.params.CoreAdminParams;
+import org.apache.solr.common.params.CollectionParams.CollectionAction;
+import org.apache.solr.common.params.ModifiableSolrParams;
+import org.apache.solr.request.SolrQueryRequest;
+import org.apache.solr.sentry.SentryTestBase;
+import org.apache.solr.sentry.SentrySingletonTestInstance;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+public class SecureCollectionsHandlerTest extends SentryTestBase {
+
+  private static SolrCore core;
+  private static CloudDescriptor cloudDescriptor;
+
+  @BeforeClass
+  public static void beforeClass() throws Exception {
+    core = createCore("solrconfig-secureadmin.xml", "schema-minimal.xml");
+    // store the CloudDescriptor, because we will overwrite it with a mock
+    // and restore it later
+    cloudDescriptor = core.getCoreDescriptor().getCloudDescriptor();
+    // ensure SentrySingletonTestInstance is initialized
+    SentrySingletonTestInstance.getInstance();
+  }
+
+  @AfterClass
+  public static void afterClass() throws Exception {
+    closeCore(core, cloudDescriptor);
+    core = null;
+    cloudDescriptor = null;
+  }
+
+  @Override
+  public void setUp() throws Exception {
+    super.setUp(core);
+  }
+
+  private SolrQueryRequest getCollectionsRequest(String collection, String 
user,
+      CollectionAction action) throws Exception {
+    SolrQueryRequest req = getRequest();
+    prepareCollAndUser(core, req, collection, user, false);
+    ModifiableSolrParams modParams = new ModifiableSolrParams(req.getParams());
+    modParams.set(CoreAdminParams.ACTION, action.name());
+    modParams.set("name", collection);
+    modParams.set("collection", collection);
+    req.setParams(modParams);
+    return req;
+  }
+
+  private void verifyUpdateAccess(CollectionAction action) throws Exception {
+    CollectionsHandler handler = new 
SecureCollectionsHandler(h.getCoreContainer());
+    verifyAuthorized(handler, getCollectionsRequest("collection1", "junit", 
action));
+    verifyAuthorized(handler, getCollectionsRequest("updateCollection", 
"junit", action));
+    verifyUnauthorized(handler, getCollectionsRequest("queryCollection", 
"junit", action), "queryCollection", "junit");
+    verifyUnauthorized(handler, getCollectionsRequest("bogusCollection", 
"junit", action), "bogusCollection", "junit");
+  }
+
+  @Test
+  public void testSecureCollectionsHandler() throws Exception {
+    for (CollectionAction action : CollectionAction.values()) {
+      verifyUpdateAccess(action);
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/60bb1003/sentry-solr/solr-sentry-handlers/src/test/java/org/apache/solr/handler/admin/SecureCoreAdminHandlerTest.java
----------------------------------------------------------------------
diff --git 
a/sentry-solr/solr-sentry-handlers/src/test/java/org/apache/solr/handler/admin/SecureCoreAdminHandlerTest.java
 
b/sentry-solr/solr-sentry-handlers/src/test/java/org/apache/solr/handler/admin/SecureCoreAdminHandlerTest.java
new file mode 100644
index 0000000..1857feb
--- /dev/null
+++ 
b/sentry-solr/solr-sentry-handlers/src/test/java/org/apache/solr/handler/admin/SecureCoreAdminHandlerTest.java
@@ -0,0 +1,173 @@
+/*
+ * 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.solr.handler.admin;
+
+import java.util.Arrays;
+import java.util.List;
+
+import org.apache.solr.cloud.CloudDescriptor;
+import org.apache.solr.common.params.CoreAdminParams;
+import org.apache.solr.common.params.CoreAdminParams.CoreAdminAction;
+import org.apache.solr.common.params.ModifiableSolrParams;
+import org.apache.solr.common.params.CoreAdminParams.CoreAdminAction;
+import org.apache.solr.core.SolrCore;
+import org.apache.solr.request.SolrQueryRequest;
+import org.apache.solr.sentry.SentryTestBase;
+import org.apache.solr.sentry.SentrySingletonTestInstance;
+import org.eclipse.jetty.util.log.Log;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+public class SecureCoreAdminHandlerTest extends SentryTestBase {
+
+  private static SolrCore core;
+  private static CloudDescriptor cloudDescriptor;
+
+  public final static List<CoreAdminAction> QUERY_ACTIONS = Arrays.asList(
+      CoreAdminAction.STATUS
+      );
+  public final static List<CoreAdminAction> UPDATE_ACTIONS = Arrays.asList(
+      CoreAdminAction.LOAD,
+      CoreAdminAction.UNLOAD,
+      CoreAdminAction.CREATE,
+      CoreAdminAction.PERSIST,
+      CoreAdminAction.SWAP,
+      CoreAdminAction.RENAME,
+      CoreAdminAction.MERGEINDEXES,
+      CoreAdminAction.SPLIT,
+      CoreAdminAction.PREPRECOVERY,
+      CoreAdminAction.REQUESTRECOVERY,
+      CoreAdminAction.REQUESTSYNCSHARD,
+      CoreAdminAction.CREATEALIAS,
+      CoreAdminAction.DELETEALIAS,
+      CoreAdminAction.REQUESTAPPLYUPDATES,
+      CoreAdminAction.REQUESTBUFFERUPDATES,
+      CoreAdminAction.LOAD_ON_STARTUP,
+      CoreAdminAction.TRANSIENT,
+      CoreAdminAction.OVERSEEROP,
+      CoreAdminAction.REQUESTSTATUS,
+      // RELOAD needs to go last, because our bogus calls leaves things in a 
bad state for later calls.
+      // We could handle this more cleanly at the cost of a lot more creating 
and deleting cores.
+      CoreAdminAction.RELOAD
+      );
+
+  // only specify the collection on these, no cores
+  public final static List<CoreAdminAction> REQUIRES_COLLECTION = 
Arrays.asList(
+      CoreAdminAction.CREATE
+      );
+
+  // actions which don't check the actual collection
+  public final static List<CoreAdminAction> NO_CHECK_COLLECTIONS = 
Arrays.asList(
+      CoreAdminAction.LOAD,
+      CoreAdminAction.PERSIST,
+      CoreAdminAction.CREATEALIAS,
+      CoreAdminAction.DELETEALIAS,
+      CoreAdminAction.LOAD_ON_STARTUP,
+      CoreAdminAction.REQUESTBUFFERUPDATES,
+      CoreAdminAction.OVERSEEROP,
+      CoreAdminAction.REQUESTSTATUS,
+      CoreAdminAction.TRANSIENT
+      );
+
+  @BeforeClass
+  public static void beforeClass() throws Exception {
+    core = createCore("solrconfig-secureadmin.xml", "schema-minimal.xml");
+    // store the CloudDescriptor, because we will overwrite it with a mock
+    // and restore it later
+    cloudDescriptor = core.getCoreDescriptor().getCloudDescriptor();
+    // ensure the SentrySingletonTestInstance is initialized
+    SentrySingletonTestInstance.getInstance();
+  }
+
+  @AfterClass
+  public static void afterClass() throws Exception {
+    closeCore(core, cloudDescriptor);
+    core = null;
+    cloudDescriptor = null;
+  }
+
+  @Override
+  public void setUp() throws Exception {
+    super.setUp(core);
+  }
+
+  private SolrQueryRequest getCoreAdminRequest(String collection, String user,
+      CoreAdminAction action) throws Exception {
+    SolrQueryRequest req = getRequest();
+    prepareCollAndUser(core, req, collection, user, false);
+    ModifiableSolrParams modParams = new ModifiableSolrParams(req.getParams());
+    modParams.set(CoreAdminParams.ACTION, action.name());
+    modParams.set(CoreAdminParams.COLLECTION, "");
+    modParams.set(CoreAdminParams.CORE, "");
+    modParams.set(CoreAdminParams.NAME, "");
+    if (!REQUIRES_COLLECTION.contains(action)) {
+      for (SolrCore core : h.getCoreContainer().getCores()) {
+        
if(core.getCoreDescriptor().getCloudDescriptor().getCollectionName().equals(collection))
 {
+          modParams.set(CoreAdminParams.CORE, core.getName());
+          modParams.set(CoreAdminParams.NAME, core.getName());
+          break;
+        }
+      }
+    } else {
+      modParams.set(CoreAdminParams.COLLECTION, collection);
+    }
+    req.setParams(modParams);
+    return req;
+  }
+
+  private void verifyQueryAccess(CoreAdminAction action) throws Exception {
+    CoreAdminHandler handler = new 
SecureCoreAdminHandler(h.getCoreContainer());
+    verifyAuthorized(handler, getCoreAdminRequest("collection1", "junit", 
action));
+    verifyAuthorized(handler, getCoreAdminRequest("queryCollection", "junit", 
action));
+    if (action.equals(CoreAdminAction.STATUS)) {
+      // STATUS doesn't check collection permissions
+      verifyAuthorized(handler, getCoreAdminRequest("bogusCollection", 
"junit", action));
+      verifyAuthorized(handler, getCoreAdminRequest("updateCollection", 
"junit", action));
+    } else {
+      verifyUnauthorized(handler, getCoreAdminRequest("bogusCollection", 
"junit", action), "bogusCollection", "junit");
+      verifyUnauthorized(handler, getCoreAdminRequest("updateCollection", 
"junit", action), "updateCollection", "junit");
+    }
+  }
+
+  private void verifyUpdateAccess(CoreAdminAction action, boolean 
checkCollection) throws Exception {
+    CoreAdminHandler handler = new 
SecureCoreAdminHandler(h.getCoreContainer());
+    verifyAuthorized(handler, getCoreAdminRequest("collection1", "junit", 
action));
+    verifyAuthorized(handler, getCoreAdminRequest("updateCollection", "junit", 
action));
+    verifyUnauthorized(handler, getCoreAdminRequest("bogusCollection", 
"bogusUser", action), "bogusCollection", "bogusUser", true);
+    if (checkCollection) {
+      verifyUnauthorized(handler, getCoreAdminRequest("queryCollection", 
"junit", action), "queryCollection", "junit");
+    }
+  }
+
+  @Test
+  public void testSecureAdminHandler() throws Exception {
+    for (CoreAdminAction action : QUERY_ACTIONS) {
+      verifyQueryAccess(action);
+    }
+    for (CoreAdminAction action : UPDATE_ACTIONS) {
+      verifyUpdateAccess(action, !NO_CHECK_COLLECTIONS.contains(action));
+    }
+  }
+
+  @Test
+  public void testAllActionsChecked() throws Exception {
+    for (CoreAdminAction action : CoreAdminAction.values()) {
+      assertTrue(QUERY_ACTIONS.contains(action) || 
UPDATE_ACTIONS.contains(action));
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/60bb1003/sentry-solr/solr-sentry-handlers/src/test/java/org/apache/solr/handler/admin/SecureInfoHandlerTest.java
----------------------------------------------------------------------
diff --git 
a/sentry-solr/solr-sentry-handlers/src/test/java/org/apache/solr/handler/admin/SecureInfoHandlerTest.java
 
b/sentry-solr/solr-sentry-handlers/src/test/java/org/apache/solr/handler/admin/SecureInfoHandlerTest.java
new file mode 100644
index 0000000..7221fa0
--- /dev/null
+++ 
b/sentry-solr/solr-sentry-handlers/src/test/java/org/apache/solr/handler/admin/SecureInfoHandlerTest.java
@@ -0,0 +1,105 @@
+/*
+ * 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.solr.handler.admin;
+
+import org.apache.solr.cloud.CloudDescriptor;
+import org.apache.solr.common.SolrException;
+import org.apache.solr.core.SolrCore;
+import org.apache.solr.handler.RequestHandlerBase;
+import org.apache.solr.request.SolrQueryRequest;
+import org.apache.solr.response.SolrQueryResponse;
+import org.apache.solr.sentry.SentryTestBase;
+import org.apache.solr.sentry.SentrySingletonTestInstance;
+import org.junit.AfterClass;
+import org.junit.Assert;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+public class SecureInfoHandlerTest extends SentryTestBase {
+
+  private static SolrCore core;
+  private static CloudDescriptor cloudDescriptor;
+
+  @BeforeClass
+  public static void beforeClass() throws Exception {
+    core = createCore("solrconfig-secureadmin.xml", "schema-minimal.xml");
+    // store the CloudDescriptor, because we will overwrite it with a mock
+    // and restore it later
+    cloudDescriptor = core.getCoreDescriptor().getCloudDescriptor();
+    SentrySingletonTestInstance.getInstance();
+  }
+
+  @AfterClass
+  public static void afterClass() throws Exception {
+    closeCore(core, cloudDescriptor);
+    core = null;
+    cloudDescriptor = null;
+  }
+
+  @Override
+  public void setUp() throws Exception {
+    super.setUp(core);
+  }
+
+  private SolrQueryRequest getInfoRequest(String collection, String user, 
String path)
+      throws Exception {
+    SolrQueryRequest req = getRequest();
+    prepareCollAndUser(core, req, collection, user, false);
+    req.getContext().put("path", path);
+    return req;
+  }
+
+  @Test
+  public void testSecureInfoHandlers() throws Exception {
+    verifyThreadDumpHandler();
+    verifyPropertiesHandler();
+    verifyLoggingHandler();
+    verifySystemInfoHandler();
+  }
+
+  private void verifyQueryAccess(String path) throws Exception {
+    InfoHandler handler = new SecureInfoHandler(h.getCoreContainer());
+    verifyAuthorized(handler, getInfoRequest("collection1", "junit", path));
+    verifyAuthorized(handler, getInfoRequest("queryCollection", "junit", 
path));
+    verifyUnauthorized(handler, getInfoRequest("bogusCollection", "bogusUser", 
path), "bogusCollection", "bogusUser", true);
+    verifyUnauthorized(handler, getInfoRequest("updateCollection", 
"updateOnlyAdmin", path), "updateCollection", "updateOnlyAdmin", true);
+  }
+
+  private void verifyQueryUpdateAccess(String path) throws Exception {
+    InfoHandler handler = new SecureInfoHandler(h.getCoreContainer());
+    verifyAuthorized(handler, getInfoRequest("collection1", "junit", path));
+    verifyUnauthorized(handler, getInfoRequest("queryCollection", 
"queryOnlyAdmin", path), "queryCollection", "queryOnlyAdmin", true);
+    verifyUnauthorized(handler, getInfoRequest("bogusCollection", "bogusUser", 
path), "bogusCollection", "bogusUser", true);
+    verifyUnauthorized(handler, getInfoRequest("updateCollection", 
"updateOnlyAdmin", path), "updateCollection", "updateOnlyAdmin", true);
+  }
+
+  private void verifyThreadDumpHandler() throws Exception {
+    verifyQueryAccess("info/threads");
+  }
+
+  private void verifyPropertiesHandler() throws Exception {
+    verifyQueryAccess("info/properties");
+  }
+
+  private void verifyLoggingHandler() throws Exception {
+    verifyQueryUpdateAccess("info/logging");
+  }
+
+  private void verifySystemInfoHandler() throws Exception {
+    verifyQueryAccess("info/system");
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/60bb1003/sentry-solr/solr-sentry-handlers/src/test/java/org/apache/solr/handler/component/QueryDocAuthorizationComponentTest.java
----------------------------------------------------------------------
diff --git 
a/sentry-solr/solr-sentry-handlers/src/test/java/org/apache/solr/handler/component/QueryDocAuthorizationComponentTest.java
 
b/sentry-solr/solr-sentry-handlers/src/test/java/org/apache/solr/handler/component/QueryDocAuthorizationComponentTest.java
new file mode 100644
index 0000000..c94f6fb
--- /dev/null
+++ 
b/sentry-solr/solr-sentry-handlers/src/test/java/org/apache/solr/handler/component/QueryDocAuthorizationComponentTest.java
@@ -0,0 +1,266 @@
+package org.apache.solr.handler.component;
+/*
+ * 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.
+ */
+
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Set;
+
+import org.apache.solr.common.params.ModifiableSolrParams;
+import org.apache.solr.common.SolrException;
+import org.apache.solr.common.params.SolrParams;
+import org.apache.solr.common.util.NamedList;
+import org.apache.solr.core.SolrCore;
+import org.apache.solr.handler.component.ResponseBuilder;
+import org.apache.solr.sentry.SentryTestBase;
+import org.apache.solr.sentry.SentryIndexAuthorizationSingleton;
+import org.apache.solr.sentry.SentrySingletonTestInstance;
+import org.apache.solr.request.SolrQueryRequest;
+import org.junit.AfterClass;
+import org.junit.Assert;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+/**
+ * Test for QueryIndexAuthorizationComponent
+ */
+public class QueryDocAuthorizationComponentTest extends SentryTestBase {
+  private static SolrCore core;
+  private static SentryIndexAuthorizationSingleton sentryInstance;
+
+  @BeforeClass
+  public static void beforeClass() throws Exception {
+    core = createCore("solrconfig.xml", "schema-minimal.xml");
+    // store the CloudDescriptor, because we will overwrite it with a mock
+    // and restore it later
+    sentryInstance = 
SentrySingletonTestInstance.getInstance().getSentryInstance();
+  }
+
+  @AfterClass
+  public static void afterClass() throws Exception {
+    closeCore(core, null);
+    core = null;
+  }
+
+  @Override
+  public void setUp() throws Exception {
+    super.setUp(core);
+  }
+
+  private String getClause(String authField, String value) {
+    StringBuilder builder = new StringBuilder();
+    builder.append(" {!raw f=").append(authField)
+      .append(" v=").append(value).append("}");
+    return builder.toString();
+  }
+
+  private ResponseBuilder getResponseBuilder() {
+    SolrQueryRequest request = getRequest();
+    return new ResponseBuilder(request, null, null);
+  }
+
+  private ResponseBuilder runComponent(String user, NamedList args, SolrParams 
params)
+  throws Exception {
+    ResponseBuilder builder = getResponseBuilder();
+    prepareCollAndUser(core, builder.req, "collection1", user);
+
+    if (params != null) {
+      builder.req.setParams(params);
+    } else {
+      builder.req.setParams(new ModifiableSolrParams());
+    }
+
+    QueryDocAuthorizationComponent component =
+      new QueryDocAuthorizationComponent(sentryInstance);
+    component.init(args);
+    component.prepare(builder);
+    return builder;
+  }
+
+  // Clauses are treated as OR, so order does not matter.
+  private void assertEqualClausesOrderIndependent(String expected, String 
actual) {
+    Set<String> expectedSet = new 
HashSet<String>(Arrays.asList(expected.split("}")));
+    Set<String> actualSet = new 
HashSet<String>(Arrays.asList(actual.split("}")));
+    assertEquals(expectedSet, actualSet);
+  }
+
+  private void checkParams(String[] expected, ResponseBuilder builder) {
+    final String fieldName = "fq";
+    final String [] params = builder.req.getParams().getParams(fieldName);
+    if (expected == null) {
+      assertEquals(null, params);
+    } else {
+      assertNotNull(params);
+      assertEquals(expected.length, params.length);
+      for (int i = 0; i < params.length; ++i) {
+        assertEqualClausesOrderIndependent(expected[ i ], params[ i ]);
+      }
+    }
+  }
+
+  @Test
+  public void testSimple() throws Exception {
+    NamedList args = new NamedList();
+    args.add(QueryDocAuthorizationComponent.ENABLED_PROP, "true");
+    ResponseBuilder builder = runComponent("junit", args, null);
+
+    String expect = 
getClause(QueryDocAuthorizationComponent.DEFAULT_AUTH_FIELD, "junit_role");
+    checkParams(new String[] {expect}, builder);
+  }
+
+  @Test
+  public void testEnabled() throws Exception {
+    // Test empty args
+    NamedList args = new NamedList();
+    ResponseBuilder builder = runComponent("junit", args, null);
+    checkParams(null, builder);
+
+    // Test enabled false
+    args.add(QueryDocAuthorizationComponent.ENABLED_PROP, "false");
+    builder = runComponent("junit", args, null);
+    checkParams(null, builder);
+  }
+
+  @Test
+  public void testAuthFieldNonDefault() throws Exception {
+    String authField = "nonDefaultAuthField";
+    NamedList args = new NamedList();
+    args.add(QueryDocAuthorizationComponent.ENABLED_PROP, "true");
+    args.add(QueryDocAuthorizationComponent.AUTH_FIELD_PROP, authField);
+    ResponseBuilder builder = runComponent("junit", args, null);
+
+    String expect = getClause(authField, "junit_role");
+    checkParams(new String[] {expect}, builder);
+  }
+
+  @Test
+  public void testSuperUser() throws Exception {
+    String superUser = (System.getProperty("solr.authorization.superuser", 
"solr"));
+    NamedList args = new NamedList();
+    args.add(QueryDocAuthorizationComponent.ENABLED_PROP, "true");
+    ResponseBuilder builder = runComponent(superUser, args, null);
+    prepareCollAndUser(core, builder.req, "collection1", superUser);
+
+    checkParams(null, builder);
+  }
+
+  @Test
+  public void testExistingFilterQuery() throws Exception {
+    ModifiableSolrParams newParams = new ModifiableSolrParams();
+    String existingFq = "bogusField:(bogusUser)";
+    newParams.add("fq", existingFq);
+    NamedList args = new NamedList();
+    args.add(QueryDocAuthorizationComponent.ENABLED_PROP, "true");
+    ResponseBuilder builder = runComponent("junit", args, newParams);
+
+    String expect = 
getClause(QueryDocAuthorizationComponent.DEFAULT_AUTH_FIELD, "junit_role");
+    checkParams(new String[] {existingFq, expect} , builder);
+  }
+
+  /**
+   * Test a request from a user coming from an empty group.
+   * This request should be rejected because otherwise document-level
+   * filtering will be skipped.
+   */
+  @Test
+  public void testEmptyGroup() throws Exception {
+    String user = "bogusUser";
+    try {
+      NamedList args = new NamedList();
+      args.add(QueryDocAuthorizationComponent.ENABLED_PROP, "true");
+      ResponseBuilder builder = runComponent(user, args, null);
+
+      checkParams(null, builder);
+      Assert.fail("Expected SolrException");
+    } catch (SolrException ex) {
+      assertEquals(ex.code(), SolrException.ErrorCode.UNAUTHORIZED.code);
+      assertTrue(ex.getMessage().contains(
+        user + " rejected because user is not associated with any roles"));
+    }
+  }
+
+  /**
+   * Test a request from a user coming from an empty role.
+   * This request should be rejected because otherwise document-level
+   * filtering will be skipped.
+   */
+  @Test
+  public void testEmptyRole() throws Exception {
+    String user = "undefinedRoleUser";
+    try {
+      NamedList args = new NamedList();
+      args.add(QueryDocAuthorizationComponent.ENABLED_PROP, "true");
+      ResponseBuilder builder = runComponent(user, args, null);
+
+      checkParams(null, builder);
+      Assert.fail("Expected SolrException");
+    } catch (SolrException ex) {
+      assertEquals(ex.code(), SolrException.ErrorCode.UNAUTHORIZED.code);
+      assertTrue(ex.getMessage().contains(
+        user + " rejected because user is not associated with any roles"));
+    }
+  }
+
+  @Test
+  public void testMultipleRoles() throws Exception {
+    NamedList args = new NamedList();
+    args.add(QueryDocAuthorizationComponent.ENABLED_PROP, "true");
+    ResponseBuilder builder = runComponent("multiGroupUser", args, null);
+
+    String expect = 
getClause(QueryDocAuthorizationComponent.DEFAULT_AUTH_FIELD, "junit_role")
+      + getClause(QueryDocAuthorizationComponent.DEFAULT_AUTH_FIELD, 
"queryOnlyAdmin_role")
+      + getClause(QueryDocAuthorizationComponent.DEFAULT_AUTH_FIELD, 
"updateOnlyAdmin_role");
+    checkParams(new String[] {expect}, builder);
+  }
+
+  @Test
+  public void testAllRolesToken() throws Exception {
+    // test no arg
+    NamedList args = new NamedList();
+    args.add(QueryDocAuthorizationComponent.ENABLED_PROP, "true");
+    ResponseBuilder builder = runComponent("junit", args, null);
+    String expect = 
getClause(QueryDocAuthorizationComponent.DEFAULT_AUTH_FIELD, "junit_role");
+    checkParams(new String[] {expect}, builder);
+
+    // test empty string arg
+    args = new NamedList();
+    args.add(QueryDocAuthorizationComponent.ENABLED_PROP, "true");
+    args.add(QueryDocAuthorizationComponent.ALL_ROLES_TOKEN_PROP, "");
+    builder = runComponent("junit", args, null);
+    expect = getClause(QueryDocAuthorizationComponent.DEFAULT_AUTH_FIELD, 
"junit_role");
+    checkParams(new String[] {expect}, builder);
+
+    String allRolesToken = "specialAllRolesToken";
+    args = new NamedList();
+    args.add(QueryDocAuthorizationComponent.ENABLED_PROP, "true");
+    args.add(QueryDocAuthorizationComponent.ALL_ROLES_TOKEN_PROP, 
allRolesToken);
+
+    // test valid single group
+    builder = runComponent("junit", args, null);
+    expect = getClause(QueryDocAuthorizationComponent.DEFAULT_AUTH_FIELD, 
"junit_role")
+      + getClause(QueryDocAuthorizationComponent.DEFAULT_AUTH_FIELD, 
allRolesToken);
+    checkParams(new String[] {expect}, builder);
+
+    // test valid multiple group
+    builder = runComponent("multiGroupUser", args, null);
+    expect = getClause(QueryDocAuthorizationComponent.DEFAULT_AUTH_FIELD, 
"junit_role")
+      + getClause(QueryDocAuthorizationComponent.DEFAULT_AUTH_FIELD, 
"queryOnlyAdmin_role")
+      + getClause(QueryDocAuthorizationComponent.DEFAULT_AUTH_FIELD, 
"updateOnlyAdmin_role")
+      + getClause(QueryDocAuthorizationComponent.DEFAULT_AUTH_FIELD, 
allRolesToken);
+    checkParams(new String[] {expect}, builder);
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/60bb1003/sentry-solr/solr-sentry-handlers/src/test/java/org/apache/solr/handler/component/QueryIndexAuthorizationComponentTest.java
----------------------------------------------------------------------
diff --git 
a/sentry-solr/solr-sentry-handlers/src/test/java/org/apache/solr/handler/component/QueryIndexAuthorizationComponentTest.java
 
b/sentry-solr/solr-sentry-handlers/src/test/java/org/apache/solr/handler/component/QueryIndexAuthorizationComponentTest.java
new file mode 100644
index 0000000..b9766e0
--- /dev/null
+++ 
b/sentry-solr/solr-sentry-handlers/src/test/java/org/apache/solr/handler/component/QueryIndexAuthorizationComponentTest.java
@@ -0,0 +1,128 @@
+package org.apache.solr.handler.component;
+/*
+ * 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.
+ */
+
+import org.apache.solr.cloud.CloudDescriptor;
+import org.apache.solr.common.SolrException;
+import org.apache.solr.core.SolrCore;
+import org.apache.solr.handler.component.ResponseBuilder;
+import org.apache.solr.sentry.SentryIndexAuthorizationSingleton;
+import org.apache.solr.sentry.SentryTestBase;
+import org.apache.solr.sentry.SentrySingletonTestInstance;
+import org.apache.solr.request.SolrQueryRequest;
+import org.junit.AfterClass;
+import org.junit.Assert;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+/**
+ * Test for QueryIndexAuthorizationComponent
+ */
+public class QueryIndexAuthorizationComponentTest extends SentryTestBase {
+  private static SolrCore core;
+  private static CloudDescriptor cloudDescriptor;
+  private static SentryIndexAuthorizationSingleton sentryInstance;
+
+  @BeforeClass
+  public static void beforeClass() throws Exception {
+    core = createCore("solrconfig.xml", "schema-minimal.xml");
+    // store the CloudDescriptor, because we will overwrite it with a mock
+    // and restore it later
+    cloudDescriptor = core.getCoreDescriptor().getCloudDescriptor();
+    sentryInstance = 
SentrySingletonTestInstance.getInstance().getSentryInstance();
+  }
+
+  @AfterClass
+  public static void afterClass() throws Exception {
+    closeCore(core, cloudDescriptor);
+    core = null;
+    cloudDescriptor = null;
+  }
+
+  @Override
+  public void setUp() throws Exception {
+    super.setUp(core);
+  }
+
+  private void doExpectUnauthorized(SearchComponent component,
+      ResponseBuilder rb, String msgContains) throws Exception {
+    try {
+      component.prepare(rb);
+      Assert.fail("Expected SolrException");
+    } catch (SolrException ex) {
+      assertEquals(ex.code(), SolrException.ErrorCode.UNAUTHORIZED.code);
+      assertTrue(ex.getMessage().contains(msgContains));
+    }
+  }
+
+  private void doExpectComponentUnauthorized(SearchComponent component,
+      String collection, String user) throws Exception {
+    ResponseBuilder responseBuilder = getResponseBuilder();
+    prepareCollAndUser(core, responseBuilder.req, collection, user);
+    doExpectUnauthorized(component, responseBuilder,
+      "User " + user + " does not have privileges for " + collection);
+  }
+
+  private ResponseBuilder getResponseBuilder() {
+    SolrQueryRequest request = getRequest();
+    return new ResponseBuilder(request, null, null);
+  }
+
+  /**
+   * Test the QueryIndexAuthorizationComponent on a collection that
+   * the user has ALL access
+   */
+  @Test
+  public void testQueryComponentAccessAll() throws Exception {
+    ResponseBuilder responseBuilder = getResponseBuilder();
+    prepareCollAndUser(core, responseBuilder.req, "collection1", "junit");
+    QueryIndexAuthorizationComponent query = new 
QueryIndexAuthorizationComponent(sentryInstance);
+    query.prepare(responseBuilder);
+  }
+
+  /**
+   * Test the QueryIndexAuthorizationComponent on a collection that
+   * the user has QUERY only access
+   */
+  @Test
+  public void testQueryComponentAccessQuery() throws Exception {
+    ResponseBuilder responseBuilder = getResponseBuilder();
+    prepareCollAndUser(core, responseBuilder.req, "queryCollection", "junit");
+    QueryIndexAuthorizationComponent query = new 
QueryIndexAuthorizationComponent(sentryInstance);
+    query.prepare(responseBuilder);
+  }
+
+  /**
+   * Test the QueryIndexAuthorizationComponent on a collection that
+   * the user has UPDATE only access
+   */
+  @Test
+  public void testQueryComponentAccessUpdate() throws Exception {
+    doExpectComponentUnauthorized(new 
QueryIndexAuthorizationComponent(sentryInstance),
+      "updateCollection", "junit");
+  }
+
+  /**
+   * Test the QueryIndexAuthorizationComponent on a collection that
+   * the user has no access
+   */
+  @Test
+  public void testQueryComponentAccessNone() throws Exception {
+    doExpectComponentUnauthorized(new 
QueryIndexAuthorizationComponent(sentryInstance),
+      "noAccessCollection", "junit");
+  }
+}

Reply via email to