-
Notifications
You must be signed in to change notification settings - Fork 163
Supported Rules
The evaluation stops at the first matching block (block = sets of rules), that is, the first block where all the rules match.
- name: block 1
type: allow
methods: [GET]
hosts: [localhost]
- name: block 2
type: allow
method: [POST]
Is equivalent to (pseudo code):
if (
(method == GET && host == localhost) ||
(method == POST)
)
{
return allow;
}
return forbid;
All the rules exit statuses in a block are in logic AND. All the blocks exit statuses are in OR.
The blocks are evaluated in the order they appear in the configuration file. So you should have the most specific rules in the beginning, and the most generic rules in the end.
rule_name : example_argument ______________________________________ | Description |
---|---|
type: allow |
mandatory rule! If all the following rules match the request, then allow or forbid it |
hosts: [localhost, 10.0.0.0/24] | a list of origin IP addresses or subnets |
accept_x-forwarded-for_header: false | interpret the X-Forwarded-For header as origin host (useful for AWS ELB and other reverse proxies) |
methods: [GET, OPTIONS] | match the HTTP method |
api_keys: [123456, abcdefg] | a list of api keys expected in the header X-Api-Key
|
uri_re: ^/secret-index/.* | A regular expression to match the request URI. Hint: superseded by indices! |
maxBodyLength: 0 | limit HTTP request body length. |
auth_key: sales:p455wd |
HTTP Basic Auth. Configure this value in clear text. Clients will need to provide the header e.g. Authorization: Basic c2FsZXM6cDQ1NXdk where "c2FsZXM6cDQ1NXdk" is base64 for "sales:p455wd". |
indices: [sales, logstash-*] | Match if the request touches indices whose name is "sales", starts with "logstash-" or a combination of both, including unspecified indices. See the note on white listing strictness and also the note on <no-index> . |
kibana_access: ro | Match if the request comes from Kibana and does not change the content. If configured as "rw" will allow kibana action that change the dashboard and the content. If configured as "ro+" will allow kibana actions that only change the .kibana index and read the rest the indices. |
kibana_index: .kibana-123 | Optional modifier to let kibana_access work even when you have a custom configuration of "kibana.index" property in kibana.yml |
actions: [cluster:*] | Match if the request action matches the exact words or wildcard patterns. SEE TABLE BELOW for a list of known actions |
There is no explicit list of what actions are required for different operations in ElasticSearch. Below there is a list with some known values and the corresponding API operations.
Action String | Operations |
---|---|
cluster:admin/repository/get |
cat API repositories |
cluster:monitor/health |
cat API health |
cluster:monitor/state |
|
cluster:monitor/nodes/stats |
cat API fielddata |
cluster:monitor/task |
cat API pending tasks |
indices:admin/create |
Indices API create |
indices:admin/exists |
Indices API exists |
indices:admin/open |
Indices API open |
indices:admin/close |
Indices API close |
indices:admin/delete |
Indices API delete |
indices:admin/aliases/get |
cat API aliases |
indices:admin/mappings/get |
Indices API get mapping |
indices:admin/mapping/put |
Indices API put mapping |
indices:admin/types/exists |
Indices API types exists |
indices:admin/validate/query |
Search API validate query |
indices:data/read/search |
|
indices:data/read/get |
|
indices:data/read/suggest |
Search API suggest |
indices:data/read/explain |
Search API explain |
indices:data/read/field_stats |
Search API field stats |
indices:data/write/index |
Documents API index (op_type=create also uses this action) |
indices:data/write/bulk |
Bulk operations |
indices:data/write/bulk[s] |
Documents API bulk |
indices:monitor/stats |
Indices API indices stats |
indices:monitor/recovery |
cat API recovery |
The indices
rule returns true on the first index matching within the comma separated list of indices. This can be viewed as overly permissive if the indices list is intended to be exclusive (that is, the given indices should be read only and only them). See the acl example below:
readonlyrest: enable: true response_if_req_forbidden: Nope, you are forbidden from doing that. access_control_rules: - name: Read only for public indices type: allow actions: ["indices:data/read/*"] indices: ["test_public"]
http://***:9200/test_private,test_public/_search?q=dataallows access to test_private which may not be the users intention since only test_public is listed.
However, as a workaround, you may be explicitly restrictive with the following additional rule
readonlyrest: enable: true response_if_req_forbidden: Nope, you are forbidden from doing that. access_control_rules: - name: Explicitly block access to any combination to private indices type: forbid actions: ["indices:data/read/*"] indices: ["*private*"] - name: Read only for public indices type: allow actions: ["indices:data/read/*"] indices: ["test_public"]
In this case
http://***:9200/test_private,test_public/_search?q=datafails
but
http://***:9200/test_public/_search?q=datasucceeds.
indices
rule name can accept a special value <no-index>
, which matches the case when no index has been detected in the request context. This is quite usual when clients request for generic cluster state related actions, for which the notion of indices-context simply does not apply.
Although from the usability stand point, this is quite puzzling, author believes that the situation in which a system implicitly whitelists some stuff is not exactly the path of least surprise. Especially when one is defining ACLs for security.
If in doubt on why some requests get forbidden, set ElasticSearch debug level to DEBUG and grep the logs for action:
. This will show you the whole request context (including the action and indices fields) of blocked request.
It is possible to tweak your logging.yml elasticsearch file to separate access and activity recorded by ReadonlyRest-plugin from the ES main log file. It can be useful for audit purpose, letting ES log as INFO.
here logging.yml modification
Just complete logging.yml section by adding dedicated lines for readonlyrest
logger:
#Plugin readonly rest logging to dedicated file - Comments these lines to disable logging, or set to INFO to reduce flow
plugin.readonlyrest.acl.blocks.rules.impl: DEBUG, access_log_file
plugin.readonlyrest.acl: DEBUG, access_log_file
additivity:
#Plugin readonly rest exclusion from ES main log file
plugin.readonlyrest.acl.blocks.rules.impl: false
plugin.readonlyrest.acl: false
appender:
#Plugin readonly rest logging file definition
access_log_file:
type: dailyRollingFile
file: ${path.logs}/${cluster.name}_access.log
datePattern: "'.'yyyy-MM-dd"
layout:
type: pattern
conversionPattern: "[%d{ISO8601}][%-5p][%-25c] %m%n"
you will get a file dedicated for readonlyrest logs in debug mode, named clustername_access.log, rotating every day, filled with :
loading rules
[2016-07-20 08:41:44,189][INFO ][plugin.readonlyrest.acl ] ADDING readonlyrest Rules Block :: { name: 'standard_users', policy: ALLOW}
a request which does not match rule standard_users
[2016-07-20 08:42:50,850][DEBUG][plugin.readonlyrest.acl ] Discovered indices:
[2016-07-20 08:43:17,805][DEBUG][plugin.readonlyrest.acl ] [standard_users] the request matches no rules in this block: { action: indices:monitor/stats, OA:127.0.0.1, indices:[], M:GET, P:/_stats/docs,store, C:, Headers:[]}
the request has been blocked
[2016-07-20 08:43:17,805][INFO ][plugin.readonlyrest.acl ] no block has matched, forbidding by default: { action: indices:monitor/stats, OA:127.0.0.1, indices:[], M:GET, P:/_stats/docs,store, C:, Headers:[]}
a success access
[2016-07-20 12:19:11,418][DEBUG][plugin.readonlyrest.acl ] matched readonlyrest Rules Block :: { name: 'standard_users', policy: ALLOW}
[2016-07-20 12:18:01,776][DEBUG][plugin.readonlyrest.acl ] Block standard_users has matched: standard_users match: true}
the logon user
[2016-07-20 08:43:17,805][DEBUG][plugin.readonlyrest.acl.blocks.rules.impl] Login as: Fredo rc: { action: indices:monitor/stats, OA:127.0.0.1, indices:[], M:GET, P:/_stats/docs,store, C:, Headers:[]}