Solr Security

First and foremost, Solr does not concern itself with security either at the document level or the communication level. It is strongly recommended that the application server containing Solr be firewalled such the only clients with access to Solr are your own. A default/example installation of Solr allows any client with access to it to add, update, and delete documents (and of course search/read too), including access to the Solr configuration and schema files and the administrative user interface.

Besides limiting port access to the Solr server, standard Java web security can be added by tuning the container and the Solr web application configuration itself via web.xml. For example, all /update URLs could require HTTP authentication.

Cross-Site Scripting (XSS)

Solr has no known cross-site scripting vulnerabilities.

Cross-Site Request Forgery (CSRF)

Even if a Solr instance is protected by good firewalls so that "bad guys" have no direct access, that instance may be at risk to potential "Cross-Site Request Forgery" based attacks if the following are all true:

  1. Some number of "good guys" have direct access to that Solr instance from their web browsers.
  2. A "bad guy" knows/guesses the host:port/path of the Solr instance (even though they can not access it directly)
  3. The bad guy can trick one of the good guy into clicking a maliciously crafted URL, or loading a webpage that contains malicious javascript.

This is because Solr's most basic behavior is to receive updates and deletes via HTTP. If you have a firewall or other security measure restricting Solr's /update handler so it only accepts connections from approved hosts/clients, but you are approved then you could inadvertently be tricked into loading a web page that initiates an HTTP Connection to Solr on your behalf.

It's important to keep this in mind when thinking about what it means to "secure" an instance of Solr (if you have not already).

A basic technique that can be used to mitigate the risk of a possible CSRF attack like this is to configure your Servlet Container so that access to paths which can modify the index (ie: /update, /update/csv, etc...) are restricted either to specific client IPs, or using HTTP Authentication.

Path Based Authentication

For the most basic authentication, edit jetty.xml, webdefault.xml and add to realm.properties

Uncomment this section in /example/etc/jetty.xml

    <Set name="UserRealms">
      <Array type="org.mortbay.jetty.security.UserRealm">
        <Item>
          <New class="org.mortbay.jetty.security.HashUserRealm">
            <Set name="name">Test Realm</Set>
            <Set name="config"><SystemProperty name="jetty.home" default="."/>/etc/realm.properties</Set>
          </New>
        </Item>
      </Array>
    </Set>

Add this inside <web-app ..> to /example/etc/webdefault.xml

  <security-constraint>
    <web-resource-collection>
      <web-resource-name>Solr authenticated application</web-resource-name>
      <url-pattern>/core1/*</url-pattern>
    </web-resource-collection>
    <auth-constraint>
      <role-name>core1-role</role-name>
    </auth-constraint>
  </security-constraint>

  <login-config>
    <auth-method>BASIC</auth-method>
    <realm-name>Test Realm</realm-name>
  </login-config>

/example/etc/realm.properties

guest: guest, core1-role

Using path based request handlers with "appends" and "invariants" is a nice way to expose a subset of the documents and constraining or defaulting any request parameters. Consider:

  <requestHandler name="/instock" class="solr.DisMaxRequestHandler" >
    <lst name="appends">
      <str name="fq">inStock:true</str>
    </lst>
    <lst name="invariants">
      <str name="facet.field">cat</str>
    </lst>
  </requestHandler>

Any queries into /instock, such as /instock?q=ipod, will always be limited to documents with an indexed inStock field containing a value of "true", and all responses will include facet counts for the "cat" field.

Resin example authentication

See resin-security and auth-constraint

Here is an example showing how to force login for /update and /admin

      <web-app 
        id="/solr" 
        document-directory="/path/to/where/it/gets/exploded"
        archive-path="/path/to/solr.war"
        character-encoding="utf-8">
            
       <system-property solr.solr.home="/path/to/solr/data" />
      
       <authenticator type="com.caucho.server.security.XmlAuthenticator">
          <init>
            <user>yourusername:yourpassword:user,admin</user>
            <password-digest>none</password-digest>
          </init>
        </authenticator>
       <security-constraint url-pattern='/update/*' role-name='user'/>
       <security-constraint url-pattern='/admin/*' role-name='user'/>
       
     </web-app>

Document Level Security

Although Solr does not directly support Document level security, the SolrRequestHandler framework is easy to configure for your specific needs.

If you need permission based authentication -- where user A can update document 1 and 2, but not 3 -- you will need to augment the request with user information. Either you can add parameters to the query string (?u=XXX&p=YYY) or use a custom dispatcher filter that augments the context:

public class CustomDispatchFilter extends SolrDispatchFilter 
{
  @Override
  protected void execute( HttpServletRequest req, SolrRequestHandler handler, SolrQueryRequest sreq, SolrQueryResponse rsp) 
  {
    // perhaps the whole request
    sreq.getContext().put( "HttpServletRequest", req );

    // or maybe just the user
    sreq.getContext().put( "user", req.getRemoteUser());

    core.execute( handler, sreq, rsp );
  }
}


public class AuthenticatingHandler extends RequestHandlerBase 
{
  @Override
  public void handleRequestBody(SolrQueryRequest req, SolrQueryResponse rsp) throws Exception {
    
    HttpServletRequest httpreq = (HttpServletRequest)
      req.getContext().get( "HttpServletRequest" );
    
    if( httpreq.isUserInRole( "editor" ) ) {
      ...
    }

    String user = (String)req.getContext().get( "user" );
    ...
  }
  ...
}

Streaming Consideration

If streaming is enabled, you need to make sure Solr is as secure as it needs to be. When streaming is enabled, the parameters "stream.url" will go to a remote site and download the content. Likewise, "stream.file" will read a file on disk.

Streaming is disabled by default and is configured from solrconfig.xml

  <requestParsers enableRemoteStreaming="false" ... />

Request Handler Paths

Solr provides access to request handlers through a general purpose /select?qt=request_handler_name URL. Prior to Solr1.4 (via SOLR-1233), request handlers named with a leading forward-slash like /select?qt=/request_handler_name could not be used, but had to be requested using /request_handler_name. Solr1.4 removes the forward-slash restriction and allows /select to work with any request handler name. Externally blocking access to /select is recommended in environments where only path-based access to request handlers is warranted.

SolrSecurity (last edited 2009-09-20 22:05:24 by localhost)