[ 
https://issues.apache.org/jira/browse/SOLR-4470?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=13593830#comment-13593830
 ] 

Per Steffensen commented on SOLR-4470:
--------------------------------------

About SOLR-4470_branch_4x_r1452629.patch
* Fits on top of branch_4x revision 1452629
* Fairly big patch but most of it is to provide credentials across all requests 
issued by BaseDistributedSearchTest tests or to just to forward decisions on 
credentials down the call-flow on server-side. Notes on the major changes in 
non-test code
** AuthCredentials: New class encapsulating the concept of credentials. 
Supports "http basic" only for now, but using this object across code wherever 
credentials are needed, the framework will be in place for supporting other 
kinds of credentials in the future
** InterSolrNodeAuthCredentialsFactory: Separation of concern with respect to 
"getting credentials for inter-solr-node requests". The implementation of the 
factory can be replaced to "change strategy", but this is only used in tests 
(for now)
** InterSolrNodeAuthCredentialsFactory.AuthCredentialsSource: A level of 
abstraction to be used server-side whenever you have to decide on "how to get 
credentials for sub-requests" - possible decisions are "use credentials from 
super-request" or "use internal credentials" but NOT "use no credentials". Any 
server-side code should be able to provide credentials in requests, because you 
never know if the solr-cluster has been set up with protection on the URL you 
are about to hit. Therefore there are basically only the two choices listed 
above. The credentials (internal or on super-request) might be empty/null in 
concrete cases if no internal credentials has been specified or of no 
credentials was provided in the super-request, but you as a programmer never 
know, so you have to decide on "how to get credentials for sub-requests" for 
your server-side case. Idea is to "use credentials from super-request" whenever 
such exists, so that a request from "the outside" can never trigger a 
sub-request that the outside user was not allowed to do directly by himself. 
Whenever there is no "super-request" use "internal credentials". There are 
gray-area-cases like e.g. the Observer that asynchronously issues requests to 
CoreAdmin API when the Collection API has been called "from the outside" - to 
be true to the idea, in this case, we ought to actually use the credentials 
provided in the original request to Collection API, but that would require 
writing those credentials into the ZK-queue, and I wouldn't include that now, 
so in this case we use internal credentials. Server-side methods should 
typically not take AuthCredentials-parameters, because that will not 
encourage/remind developers to decide on the strategy when they use the method 
in the future - use AuthCredentialsSource instead.
** SolrRequest: Has been modified so that it can hold credentials to be used, 
and info on whether or not to provide them preemptively
** SolrQueryRequest: Has been modified to hold the credentials used in the 
request received
** SolrRequestParsers: Has been modified to extract the credentials from the 
request and add it to SolrQueryRequest
** HttpClientUtil: Has been changed to allow for specifying credentials and/or 
ClientConnectionManager when creating a HttpClient. Credentials to be used 
across all requests issued by this HttpClient. ClientConnectionManager to be 
able to share connection-manager across HttpClients - see reason below
** HttpShardHandler(Factory): It is used many places (and thats good) where 
sub-request are issued, places doing "use internal credentials" but also places 
"use credentials from super-request" (SolrCmdDistributor) and therefore 
HttpShardHandler(Factory) has been modified to support both.
** LBHttpSolrServer: Changed to allow for specific HttpClient for each request, 
so that even the loadbalancer in HttpShardHandler can use different HttpClients 
for different requests. It should have been done this way from the beginning - 
it is strange to use the defaultHttpClient for loadbalancing request through a 
HttpShardHandler which has been created with a specific HttpClient to use.
** Shared ClientConnectionManager instead of HttpClient: Several classes that 
used to have a HttpClient used for all requests (PeerSync, SyncStrategy and 
UpdateShardHandler), now have only a shared ClientConnetionManager. This in 
order to be able to specify different credentials (on HttpClient level) for 
different requests issued through those components. Actually it is not absolute 
necessary for PeerSync because it always uses "internal credentials", but it is 
done anyway in order to allow HttpShardHandlerFactory to insist on getting a 
decision on "how to get credentials for sub-requests" even when you "bring you 
own client" - shardhandlers ALWAYS need to have a strategy for providing 
credentials, because it is always used for inter-solr-node request. I believe 
it is ok to replace a shared HttpClient with a shared ClientConnectionManager 
in those cases, because the main reason for sharing a HttpClient must be to 
share its connection-manager.
** RegExpAuthorizationFilter: In order to be able to implement the most 
"common" kind of authorization (see descriptions below) in tests, 
RegExpAuthorizationFilter has been added for handling authorization. I have 
placed it in non-test code, even though it is only used in tests. This is due 
to the fact that it could very well be used by others in a real solr-setup - 
e.g. we will use it in my project. Will write a little bit about it on 
http://wiki.apache.org/solr/SolrSecurity.
** HttpSolrServer: Has been modified to be able to provide credentials (from 
HttpClient or from request) - both preemptively and non-preemptively. Support 
for non-preemptive POST requests required a little twist also.
* Regarding how to use the solution
** You can specify credentials once and for all to be used in every request 
issued by a specific HttpClient. E.g. to do it for the HttpClient behind a 
CloudSolrServer
{code}
HttpClientUtil.setAuthCredentials(cloudSolrServer.getLbServer().getHttpClient(),
 AuthCredentials.createBasicAuthCredentials(<username>, <password>));
{code}
** You can also specify credentials on a pre-request basis (will override 
credentials on the HttpClient for this particular request). Just do the 
following to your SolrRequest before using it
{code}
solrRequest.setAuthCredentials(AuthCredentials.createBasicAuthCredentials(<username>,
 <password>));
{code}
** Preemptive authentication supported (and is default)
** Non-preeemptive authentication also supported on a per-request basis. Just 
do the following to your SolrRequest before using it
{code}
solrRequest.setPreemptiveAuthentication(false);
{code}
Have made changes to HttpSolrServer so that non-preemptive POST request will 
also work. ConcurrentSolrServer enforces preemptive authentication.
* SolrServer helper-methods (add, commit, optimize, rollback, deleteByQuery, 
deleteById, ping, query and queryAndStreamResponse) have been change so that 
they in "the most advanced" variant support credentials as a parameter. I could 
have made a credentials variant for all existing variants of "the same 
operation", but that would make us end up with double the helper-methods. This 
meant that I had to call this version in cases where a non/few-parameters 
version of the helper-method uses to be called in all test inheriting from 
BaseDistributedSearchTestCase, because I have decided to run with "common 
security" on all resources/urls in those tests. I really believe this is a good 
decision for two reasons
** It helped me a lot for find particular/hidden places in the solr-server code 
where inter-solr-node requests where issued, so that I am now pretty sure we 
deal with credentials in all inter-solr-node requests.
** There is a great chance that future additions to the code where 
inter-solr-node requests are triggered, will have a test inheriting from 
BaseDistributedSearchTestCase, a test which will therefore run with "common" 
security set up, and therefore it is likely that such a test will make the 
developer discover that he needs to deal with credentials for the 
inter-solr-requests. Its my best attempt to try to ensure that this feature is 
not broken in the future.
* Introduced close on PeerSync and called it wherever needed. I needed it some 
time in my development work. Not sure if it is needed anymore for this 
particular issue, but why not get it done.
* Regarding test
** Idea is to run with "common security" in all "distributed" tests (all tests 
inheriting from BaseDistributedSearchTest) and therefore I needed to go add 
credentials here and there in all the sub-classes, in cases where they do not 
use the helper-methods (del, commit, add, etc) in BaseDistributedSearchTest 
itself. Support for running with "common" security has been added to 
JettySolrRunner and the feature is "turned on" for all test based on 
BaseDistributedSearchTest
** In this "common security" the web-container handles authentication (required 
for everything), but authorization is handled by RegExpAuthorizationFilter, in 
order to achieve what I consider the most "common" kind of authorization - 
namely authorization based on "operations allowed" instead of "collections 
allowed". In this "common security" setup used in BaseDistributedSearchTest 
tests, we have an all/internal/admin-user which is authorized to do anything, 
and search- plus update-users allowed to do only searches and updates 
respectively.
** Collection handling helper-methods (createCollection, 
checkCollectionExpectations, checkForCollection, checkCollectionIsNotCreated 
and checkForMissingCollection) and getCommonCloudSolrServer moved from 
BasicDistributedZkTest to AbstractFullDistribZkTestBase, because I also wanted 
to use them in new SecurityDistributedTest
* Additional
** There is more to say about "security" on a "users-guide" level - will add to 
http://wiki.apache.org/solr/SolrSecurity. There is also something to be say on 
a "developers-guide" level. Do we have a developers guide somewhere on Wiki?
** Regarding running the test-suite: If not already granted in your policy file 
you need to grant "permission javax.security.auth.AuthPermission "*";" in 
general or at least for the JettySolrRunner (or the anonymous 
MappedLoginService in JettySolrRunner). This permission is needed in order to 
be able to set up the LoginModule in JettySolrRunner (test-only)
** Havnt run "ant precommit" but I would if I where to commit myself. Guess it 
will fail due to the fact that I probably do not live up to the (very bad IMHO) 
coding-style

Please do not hesitate go ask questions about why I changed particular things 
the way I did and why it is needed. Or just ask questions in general. But 
please consider getting the patch in soon while its hot - its good stuff.
                
> Support for basic http auth in internal solr requests
> -----------------------------------------------------
>
>                 Key: SOLR-4470
>                 URL: https://issues.apache.org/jira/browse/SOLR-4470
>             Project: Solr
>          Issue Type: Bug
>          Components: clients - java, multicore, replication (java), SolrCloud
>    Affects Versions: 4.0
>            Reporter: Per Steffensen
>              Labels: authentication, solrclient, solrcloud
>             Fix For: 4.2
>
>
> We want to protect any HTTP-resource (url). We want to require credentials no 
> matter what kind of HTTP-request you make to a Solr-node.
> It can faily easy be acheived as described on 
> http://wiki.apache.org/solr/SolrSecurity. This problem is that Solr-nodes 
> also make "internal" request to other Solr-nodes, and for it to work 
> credentials need to be provided here also.
> Ideally we would like to "forward" credentials from a particular request to 
> all the "internal" sub-requests it triggers. E.g. for search and update 
> request.
> But there are also "internal" requests
> * that only indirectly/asynchronously triggered from "outside" requests (e.g. 
> shard creation/deletion/etc based on calls to the "Collection API")
> * that do not in any way have relation to an "outside" "super"-request (e.g. 
> replica synching stuff)
> We would like to aim at a solution where "original" credentials are 
> "forwarded" when a request directly/synchronously trigger a subrequest, and 
> fallback to a configured "internal credentials" for the 
> asynchronous/non-rooted requests.
> In our solution we would aim at only supporting basic http auth, but we would 
> like to make a "framework" around it, so that not to much refactoring is 
> needed if you later want to make support for other kinds of auth (e.g. digest)
> We will work at a solution but create this JIRA issue early in order to get 
> input/comments from the community as early as possible.

--
This message is automatically generated by JIRA.
If you think it was sent incorrectly, please contact your JIRA administrators
For more information on JIRA, see: http://www.atlassian.com/software/jira

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscr...@lucene.apache.org
For additional commands, e-mail: dev-h...@lucene.apache.org

Reply via email to