How to add basic auth to an apache proxy while using CORS headers

apache-2.2corselasticsearchhttp-basic-authenticationreverse-proxy

Background

I use grafana for displaying graphs of our server-metrics. Grafana is a JS-app which in our case is getting the data from graphite and storing search-queries in elasticsearch. All three services have their own vhost, although being on the same machine for now. Because of JS-rules, I have added CORS-headers to the graphite- and elasticsearch-vhost. The graphite-vhost is a routing requests to WSGI, because graphite is a python/django app. The elasticsearch-vhost is a reverse proxy to forward data from port 443 to localhost:9200. This helps to not open the elasticsearch-service directly to the world and also gives me a place to add the CORS-header. So far, this works: grafana can talk to both services.

Problems arise

I added Basic Auth to the grafana and graphite-hosts. These work fine and as expected. grafana is able to retrieve and display the data.

When adding Basic Auth to the elasticsearch-vhost, I run into Problems. While I can add the Auth-settings in a <Location / >-block, it seems to disable the CORS-headers. With the Authentication activated, I can use elasticsearch with a browser or curl.

However, grafana is not able to search for configured dashboards in elasticsearch.

The search seems to be more complex that a GET, because grafana starts with a OPTIONS-request. This fails with a 401 error. Funnily, grafana can and does retrieve known dashboards (which is a simple GET).

I do not mention a restriction of HTTP-methods in the Headers.

So, to sum this up:

How can I add basic auth to an apache proxy while using CORS headers?

If you want to see the apache configs, please tell me which parts, I don't want to post three vhosts of considerable length "just to be sure".

Best Answer

I solved this by always allowing OPTIONS-requests. Those Request only serve as a "ping" to check if the server is there.

<Proxy *>
  Order deny,allow
  Allow from all

  AuthType Basic
  AuthBasicProvider file
  AuthUserFile /path/to/passwords

  # This allows OPTIONS-requests without authorization
  <LimitExcept OPTIONS>
    Require valid-user
  </LimitExcept>

</Proxy>

A more clean approach could be to change grafana and how the requests are made, but this solves the immediate problem without opening new ones.

This does currently not make things worse from a security point of view:

  • OPTIONS currently does not have a body to reveal more information
  • OPTIONS is idempotent in the sense that it always does nothing
  • The mere existence of the server can also be checked with a heavier GET /.
  • All other HTTP-methods but OPTIONS are password-protected