Use Nginx basic auth to protect HTTP services like Solr

Sometimes it might be useful to add simple permissions layer on top of unprotected HTTP services ( especially if you would like to open those to the public! ). Recently we had to secure our Solrcloud install to be able to provide read only access to our FTS index to a partner, so they could develop their custom app using our data but without the option to accidentally (or intentionally) break the index.

I hear some of you saying something like “You should expose REST API endpoint, with proper access token!” and well, you are right! Unfortunately reality is not perfect and sometimes in order to move forward you need to come up with backup/temp solution.

Here is our backup solution for protecting our Solr install with basic read/write permissions using Nginx magic and Basic Auth:

server
{
# To avoid changing your app config
# point Nginx to the Solr port
listen 8983;
# Set read/write variables
set $solr_write "0";
set $solr_read "1";
set $solr_admin "0;
# Define users permissions
# $remote_user translates to Basic Auth user
if ($remote_user = "solr_r") {
set $solr_write "0";
set $solr_read "1";
}
if ($remote_user = "solr_w") {
set $solr_write "1";
set $solr_read "0";
}
if ($remote_user = "solr_rw") {
set $solr_write "1";
set $solr_read "1";
set $solr_admin "1";
}
# Force Basic Auth for all requests to Solr
# IMPORTANT:
# Make sure to add new users to htpasswd!
auth_basic "Private Beta";
auth_basic_user_file /etc/nginx/conf/htpasswd;
# Write Solr enpoint
location ~* /solr/\w+/update {
if ($solr_write != "1") {
return 403;
}
proxy_pass http://localhost:8900; # Proxy to solr
}
# Read Solr endpoint
location ~* /solr/\w+/select {
if ($solr_read != "1") {
return 403;
}
proxy_pass http://localhost:8900;
}
# Admin UI
location ~* /solr {
if ($solr_admin != "1") {
return 403;
}
proxy_pass http://localhost:8900;
}
# Disable proxy buffering because it was causing problems
proxy_buffering off;
# All other urls expect admin permission
location / {
proxy_pass http://localhost:8900;
}
}

I think the idea should be pretty clear, the key is to discover which url you want to protect ( hint: analyze access logs with Logstash ). It’s also a good idea to put your Nginx endpoint behind SSL, especially if it’s open to public.

Note: If condition in Nginx location evaluates to true ( if you don’t have write or admin permission for example ), it returns 403 without processing Basic Auth, so you may need to send Basic Auth credentials with the request, or land on / url to authenticate in the browser.

Note 2: The approach described here will most likely require a change to the application, since all requests to Solr will need to include Authorization header.

P.S. If you are going to use Nginx in front of your Solr service, then you may benefit from simplified logging as well. Read Improve and simplify Solr logging with Nginx proxy.

Join the Newsletter

Over the last 20+ years I wrote a ton of code, ran mission critical systems and co-founded multiple startups. Lately as a Dad and the CTO I've been focusing on the topics of leadership, motivation and life observation.

Consider subscribing if you found my writing useful and relevant.

    I won't send you spam. Unsubscribe at any time.


    Also published on Medium.

    Leave a Reply