Is there an actual "Read Only" setting?

Hi there and thanks for this wonderful tool.

So the main problem we were trying to solve with this was locking down our Elasticsearch and making it so that no one could execute a POST or DELETE to our ES service, but we were still able to query ES.

We were able to solve part of this. Now our index is built on the server side only and a POST or DELETE can’t be executed externally.

The issue is, now, we can’t get anything to work on the javascript application. We’ve tried to pass API keys through on the header, and they appear to be there but it’s not working.

We’ve tried to set it up so that only host from certainly IPs can read from ES without any kind of authentication but that doesn’t seem to be working.

So my question is: is there a setting somewhere that I’m missing that simply makes ES “read only” without any kind of authentication or noting the host. For instance, we’re trying to figure out if we can implement “read only” as the default for ES unless you execute a curl server side with the auth keys (which is working).

We’re pulling data from ES using AJAX and absolutely nothing seems to be getting through now. We constantly get a “Failed to load resource: net::ERR_SSL_PROTOCOL_ERROR” error in console.

We’re running SSL and executing everything across https.

The api keys in the header simply don’t seem to be authenticating with javascript. The idea was that we’d match the api keys with the query and then authenticate based on the hosts.

It would be ideal if we could lock down individual indicies as read only unless you provide the API keys.

Any thoughts or suggestions?

Hi @tk421jag,

  1. Are you using a reverse proxy between the clients and ES?
  2. Don’t use HTTP methods to prevent writes, it’s insecure
  3. I recommend using basic auth credentials instead of API keys, as they can be stored as hashes in settings
  4. We did not see your readonlyresty.yml so I it’s impossible to help you at this stage.
  5. We didn’t see your JS code for the AJAX connection either.
  6. How did you create the SSL certificate?

Sorry, I can certainly post all of that. I was really just looking for a “Yes, there is a setting you can change for it.” or a “No, that’s not possible.” so as to not waste anyones time.

I was thinking that there may be a way to completely lock the entire system down and make it read only without any kind of authentication. Basically like a read only access global permission. The only exception would be a curl with some kind of auth_key.

  1. Not using reverse proxy but we are using a load balancer.
  2. Got it.
  3. Do you mean like a basic username and password with the Base64 user/pass? readonlyrest-docs/elasticsearch.md at master · beshu-tech/readonlyrest-docs · GitHub
  4. Something else that I’m not clear on, it seems like everything that supposed to be in my readonlyrest.yml is actually working in my elasticsearch.yml file. This could also be the problem on my end.
  5. Not sure if I can share that code (government project) but I’d like to see if I can.
  6. SSL cert is letsencrypt on all of our environments except for production.

I should also mention that this is all in a docker container (rancher setup). Not sure if that matters at all.

Certainly appreciate all of the help and reaching out to me about this.

This is my readonlyrest.yml file:

readonlyrest:
    access_control_rules:

    - name: "Require HTTP Basic Auth"
      type: allow
      auth_key: user:password

rest.action.multi.allow_explicit_index: true

http.cors:
  enabled: true
  allow-origin: "*"
  allow-methods: OPTIONS, HEAD, GET
  allow-headers: X-Api-Key, X-Requested-With, Content-Type, Content-Length, Accept

After reading the documentation over and over, it seems that I have to configure the SSL certificate via readonlyrest.

“ReadonlyREST can be configured to require that all REST requests come through HTTPS.”

Is this a MUST or can you bypass this so that readonly data can come through the HTTPS without some kind of authentication?

I don’t have direct access to this SSL data, but I can probably get it in the coming week.

If configuring SSL is absolutely necessary, the key must be in .jks format and filetype, correct?

The SSL is necessary for the credentials to be encrypted when they are transmitted as HTTP headers. This is a non functional requirement (for security).

I don’t understand why you mix settings that should be in elasticsearch.yml with settings that go in readonlyrest.yml. Where did you see such example?

Ah ok. Thanks for the clarification on the SSL. I’ll work with our dev ops engineer this week to see if we can iron out this part it.

So just for clarification, we need to make sure we have the following in the readonlyrest.yml file:

  ssl:
     enable: true
     keystore_file: "keystore.jks"
     keystore_pass: readonlyrest
     key_pass: readonlyrest

The example of elasticsearch.yml was in one of the docker containers that we used. Maybe an older version of readonlyrest? It seems that everything is only working in my elasticsearch.yml. I’ve changed all of me settings in the readonlyrest.yml file and nothing seems to be affected.

No, that would not work because you don’t have the “readonlyrest:” in the beginning, and because you don’t have declared any ACL rule.

This is the minimal configuration for your case:

readonlyrest:
  ssl:
    enable: true
    keystore_file: "keystore.jks"
    keystore_pass: readonlyrest
    key_pass: readonlyrest

  access_control_rules:

    - name: "Require HTTP Basic Auth"
      auth_key: "user:password"

Leave all the http.* and rest.* out of this file. Those belong to elasticsearch.yml

Alright. I’ll try that. I’m not sure why, but all of the access controls seem to be working correctly in the elasticsearch.yml. I’m able to curl using the account settings in the yml. I don’t have a readonlyrest.yml

I tried it with a readonlyrest.yml and took those settings out of the elasticsearch.yml. They didn’t seem to be affected or working in the readonlyrest.yml

For legacy reasons, our settings are still picked up from elasticsearch.yml if they are not found in readonlyrest.yml. But this does not mean it’s the correct way to do it, as it implies security risks.

Make sure that your readonlyrest.yml file lives in the same directory with elasticsearch.yml, and the file permissions are right for the elasticsearch process to read it.

Looks like we were able to get this working by using the SSL keystore and passing the hash from the yml file into the ajax script. Seems to be working well. Thank you for all of your help!

1 Like

If you want read only for specific indices without authentication there is definitely a way to do that. This is what we have been doing with our indices.

If you put this as the last access control rule in your readonlyrest.yml that should allow readonly access to specific indices. This is public to the world.

- name: "::GLOBAL::"
  type: allow
  indices: ["your-index"]
  actions: ["indices:data/read/*"]

I imagine the host filtering didn’t work because you are calling the index via AJAX which executes client side so the IP will be that of the user. If you don’t want it public you would have to use basic auth or api keys.

1 Like