Skip to content

Supported Rules

maitai edited this page Oct 13, 2016 · 24 revisions

Rules and blocks

The evaluation stops at the first matching block (block = sets of rules), that is, the first block where all the rules match.

Example: evaluation of two blocks

 - name: block 1
   type: allow
   methods: [GET, DELETE]
   hosts: [localhost]

 - name: block 2
   type: allow
   method: [POST]

Is equivalent to (pseudo code):

if (
     // Block 1
     ( (method == GET || method == DELETE) && host == localhost ) ||    
     
     // Block 2
     (method == POST) 
)
{
  return allow;
}

return forbid;
  • All the rules exit statuses in a block are in logic AND.
  • If the rule has an array of arguments, the exit status of the rule is computed as the logical OR of all the arguments (see Block1, methods).
  • 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.

List of supported rules in ACL blocks

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".
auth_key_sha1: 6ceffdb1598c8c12e1e908549ed013c9d23145a0 HTTP Basic Auth. Configure this value hashed in sha1 (put the clea text user:pass string through some web based hashing tool. Clients will need to provide the usual Authorization header.
groups: ["group1", "group2"] Limit access to members of specific user groups. See User management
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

Actions and APIs

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

A note on <no-index>

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.

User management with group-based access

The groups rule accepts a list of group names. A request is allowed as long as its Basic Authentication header matches the auth_key (or auth_key_sha1) of a user and that user also happens to be a member of one of the groups defined in the rule. User management is done inside the Elasticsearch configuration file (e.g. right after the access rule configuration):

    users:
    
    - username: alice
      auth_key: alice:p455phrase
      groups: ["group1"]
      
    - username: bob
      auth_key: bob:s3cr37
      groups: ["group2", "group3"]

Troubleshooting

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.

Dedicated and logging file rotation

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:[]}

Clone this wiki locally