Separate Rules for Global Read and Global Write Access?

Trying to determine how best to approach this.

I want to be able to use elastic:changeme for global read access to elasticsearch capabilities
(such as searching within an index, or calling elastic apis like /_nodes/_all) and
I want to be able to use elastic:writeme for restricting write access to the same
(such as PUT/POST/DELETE to a specific index or calling write elastic apis like /_template)
I want to be able to give ro access to all requests coming from Kibana.

How would I approach this? Using this seems to be doing some of the PUT/POST/DELETE correctly but I’m not able to call GET on the elastic apis like /_nodes/_all (though I am able to call GET on my own indices like /myindex/_search)
The GOAL is for me to be able to call ALL Monitor/Admin/Cluster/Kibana/MyIndex READ APIs using elastic:changeme and any and ALL Write APIs (Monitor/Admin/Cluster/MyIndexes) using elastic:writeme

readonlyrest:
     access_control_rules:
     - name: "just that action from localhost"
       type: allow
       actions: ["cluster:monitor/main"]
       hosts: ["127.0.0.1"]
 
     - name: "Global Read/Monitor Access"
       auth_key: "elastic:changeme"
       type: allow
       actions: ["indices:data/read/*","indices:admin/get", "cluster:*"]
 
     - name: "Global Write/Admin Access"
       auth_key: "elastic:$apr1$AtIR0e/S$lC346PxpaBQODjx7.avAi."
       type: allow
       actions: ["indices:data/write/*","indices:admin/*"]

Yeah that’s quite ok. Might be that some actions group will be not included, but you’ll figure it out when you find the FORBIDDEN log lines in ES log when requests are blocked.

@sscarduzio Thanks! I was able to proceed. However, I haev an ELB and ROute53 fronting the Elastic CO nodes where ROR is delployed and started getting the usual FORBIDDEN for route53 access. I look at the official documentation and added the x-forwarded-for suggestion. But it looks like that rule is subsuming all others and I’m able to bypass the remaining rules below. Any ideas how can I ALLOW the ELB/Route54 requests but at the same time allow the rest of the rules to function as indicated?

readonlyrest:
access_control_rules: ~
- name: “Rout53 Access”
type: allow
x_forwarded_for: [“0.0.0.0/0”]
verbosity: error

- name: "Global Read/Monitor Access"                             
  auth_key: "elastic:changeme"                                   
  type: allow                                                    
  actions: ["indices:data/read/*","indices:admin/get"]           
                                                                 
- name: "Global Write/Admin Access"                              
  auth_key: "elastic:$apr1$AtIR0e/S$lC346PxpaBQODjx7.avAi."      
  type: allow                                                    
  actions: ["indices:data/write/*","indices:admin/*"]

ELB/Route53 Error

[2018-03-16T20:35:35,440][INFO ][t.b.r.a.ACL ] FORBIDDEN by default req={ ID:22055712-1909977967#4790, TYP:MainRequest, CGR:N/A, USR:[no basic auth header], BRS:false, ACT:cluster:monitor/main, OA:10.187.25.136, DA:10.187.16.110, IDX:<N/A>, MET:HEAD, PTH:/, CNT:<N/A>, HDR:{Connection=keep-alive, content-length=0, host=myapp-elasticsearch.myhost.com, X-Forwarded-For=10.187.25.63, X-Forwarded-Port=443, X-Forwarded-Proto=https}, HIS:[Global Read/Monitor Access->[auth_key->false]], [Global Write/Admin Access->[auth_key->false]] }

Your history (HIS:) log testifies that the first block “Rout53 Access” is not part of the ACL. Verify your YAML.

@sscarduzio

I did add the ACL rule for the Route53 access. But it looks like that rule is OVERRULING all other rules and every request is now getting passed whether or not Basic Authorization is passed!

With the Route53 Rule ELB is able to access Elastic Correctly

[2018-03-19T15:13:13,875][INFO ][t.b.r.a.ACL] ALLOWED by { name: ‘Rout53 Access’, policy: ALLOW} req={ ID:1157575513-115849859#124, TYP:SearchRequest, CGR:N/A, USR:[no basic auth header], BRS:false, ACT:indices:data/read/search, OA:10.187.25.247, DA:10.187.16.110, IDX:.kibana, MET:POST, PTH:/.kibana/config/_search, CNT:{“size”:1000,“sort”:[{“buildNum”:{“order”:“desc”,“unmapped_type”:“string”}}]}, HDR:{Connection=keep-alive, Content-Length=77, content-type=application/json, host=myapp-elasticsearch.clouddqt.capitalone.com, X-Forwarded-For=10.187.25.63, X-Forwarded-Port=443, X-Forwarded-Proto=https}, HIS:[Rout53 Access->[x_forwarded_for->true]] }

However, this is now allowing the other requests to pass whether or not they pass Basic Auth. This is a GET request with No Basic Authorization passed. Before adding the Route53 rule - this was throwing 403 correctly

[2018-03-19T15:13:13,961][INFO ][t.b.r.a.ACL] ALLOWED by { name: ‘Rout53 Access’, policy: ALLOW} req={ ID:24739190-87285795#125, TYP:SearchRequest, CGR:N/A, USR:[no basic auth header], BRS:true, ACT:indices:data/read/search, OA:10.187.25.247, DA:10.187.16.110, IDX:myapp, MET:GET, PTH:/myapp/transcript,ctr/_search, CNT:<N/A>, HDR:{Accept=application/json, accept-encoding=gzip, deflate, cache-control=no-cache, Connection=keep-alive, content-length=0, Content-Type=application/json, host=myapp-elasticsearch.clouddqt.capitalone.com, Postman-Token=0ee81f45-87b1-4172-8c1b-bae1b24298c2, User-Agent=PostmanRuntime/7.1.1, X-Forwarded-For=10.37.130.39, X-Forwarded-Port=443, X-Forwarded-Proto=https}, HIS:[Rout53 Access->[x_forwarded_for->true]] }

Of course it “overrules” everything,

This literally means allow any request that has a x-forwarded-for header with a value of any IP.

If all you want is to allow the health checks of the load balancer, create a block that matches http method and path, or action you see in the incoming health check requests.

@sscarduzio

Unfortunately it looks like the ELB Http calls are not being limited to just Health Checks. So far these are the growing lists of indices the ELB (fronted by R53) seems to be calling and some of those are the ones I want protected with Basic Auth:

indices:data/read/ ← Need this protected. But ELB too seems to be requesting this every second.
clusters:monitors/nodes/search

yes but what’s the HTTP path and method? You may restrict it better with those in this case.

@sscarduzio Thanks! I’m going to try your suggested approach

1 Like