From 0cd1dff0185c7f28ed86f9d8826a4a6ac5ec6b9c Mon Sep 17 00:00:00 2001 From: Simone Scarduzio Date: Wed, 18 Mar 2026 18:46:38 +0100 Subject: [PATCH 1/2] Fix ACL documentation discrepancies found via source code audit MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Fix `maxBodyLength` → `max_body_length` (correct snake_case key name) - Add missing `response_headers` rule documentation - Add group rule aliases table (groups, roles, any_of, all_of, etc.) - Add `external_authorization` alias note for `groups_provider_authorization` - Add "Incompatible rule combinations" section (kibana_access conflicts) - Document auth-only rule requirement (must pair with authentication rule) Co-Authored-By: Claude Opus 4.6 (1M context) --- elasticsearch.md | 42 ++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 40 insertions(+), 2 deletions(-) diff --git a/elasticsearch.md b/elasticsearch.md index 5034947..be979ce 100644 --- a/elasticsearch.md +++ b/elasticsearch.md @@ -828,6 +828,19 @@ The groups rules use the user definitions from [the `users` section](#users-and- - after this step, we have an authorized user with information about the authorized groups to which the user belongs - then we check whether the authorized user groups are permitted in context of the rule +{% hint style="info" %} +**Groups rule aliases**: For backwards compatibility, the following YAML key aliases are recognized and treated identically to their canonical names: + +| Canonical Rule | Aliases | +|---------------|---------| +| `groups_any_of` | `groups`, `any_of`, `groups_or`, `roles` | +| `groups_all_of` | `all_of`, `groups_and`, `roles_and` | +| `groups_not_any_of` | `not_any_of` | +| `groups_not_all_of` | `not_all_of` | + +Similarly, `headers_and` can be written as `headers`. +{% endhint %} + ##### `groups_any_of` The ACL block will match when the user belongs to any of the specified groups (boolean OR logic). @@ -1121,6 +1134,8 @@ For more information on the ROR's authorization rules, see [Authorization rules #### `groups_provider_authorization` +Also available as the alias `external_authorization`. + Used to delegate groups resolution for a user to a JSON microservice. See below, the dedicated [Groups Provider Authorization section](elasticsearch.md#custom-groups-providers) [Impersonation](details/impersonation.md) support by this rule requires to add [an extra configuration](details/impersonation.md#defining-mocks-of-the-external-services-optional). @@ -1804,9 +1819,9 @@ Match if **at least one** the specified HTTP headers `key:value` pairs is matche Match if **at least one** specified regular expression matches requested URI. -#### `maxBodyLength` +#### `max_body_length` -`maxBodyLength: 0` +`max_body_length: 0` Match requests having a request body length less or equal to an integer. Use `0` to match only requests without body. @@ -1818,6 +1833,12 @@ Match requests having a request body length less or equal to an integer. Use `0` A list of api keys expected in the header `X-Api-Key` +#### `response_headers` + +`response_headers: ["X-Custom-Header:value", "X-Another:123"]` + +Add custom headers to the Elasticsearch HTTP response when this block matches. Useful for passing metadata (e.g. group names, routing hints) back to clients or proxies. + #### `session_max_idle` `session_max_idle: 1h` @@ -2104,6 +2125,23 @@ ldaps: And ReadonlyREST ES will load "S3cr3tP4ss" as `bind_password`. +### Incompatible rule combinations + +Certain rules cannot be used together within a single ACL block. ReadonlyREST will report a validation error if any of these combinations are detected: + +| Rule A | Rule B | Reason | +|--------|--------|--------| +| `kibana_access` | `actions` | Kibana access internally manages action filtering | +| `kibana_access` | `filter` | Kibana access conflicts with Document Level Security | +| `kibana_access` | `fields` | Kibana access conflicts with Field Level Security | +| `kibana_access` | `response_fields` | Kibana access conflicts with response field filtering | + +{% hint style="info" %} +The composite `kibana` rule does **not** have these conflicts — it replaces the legacy separate rules (`kibana_access`, `kibana_index`, `kibana_hide_apps`, `kibana_template_index`) and handles these interactions internally. +{% endhint %} + +Additionally, a block with an **authorization-only** rule (e.g. `ldap_authorization`, `jwt_authorization`) must also contain an **authentication** rule in the same block. A block cannot have more than one authentication rule. + ### Dynamic variables One of the neatest features in ReadonlyREST is that you can use dynamic variables inside most values of the following rules: `data_streams`, `indices`, `users`, `fields`, `filter`, `repositories`, `hosts`, `hosts_local`, `snapshots`, `response_fields`, `uri_re`, `x_forwarded_for`, `hosts_local`, `hosts`, `kibana.index`, `kibana.template_index`, `kibana.metadata`, [groups rules](#groups-rules). The variables are related to different contexts: From 8f1c4eec9f9ae38f827127bbdec55509726c08a1 Mon Sep 17 00:00:00 2001 From: Simone Scarduzio Date: Wed, 18 Mar 2026 20:02:10 +0100 Subject: [PATCH 2/2] Clarify group rule aliases scope per review feedback Add sentence clarifying that groups/roles aliases apply only to ACL rule keys inside access blocks, not to the users section groups field. Co-Authored-By: Claude Opus 4.6 (1M context) --- elasticsearch.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/elasticsearch.md b/elasticsearch.md index be979ce..31b0a96 100644 --- a/elasticsearch.md +++ b/elasticsearch.md @@ -839,6 +839,8 @@ The groups rules use the user definitions from [the `users` section](#users-and- | `groups_not_all_of` | `not_all_of` | Similarly, `headers_and` can be written as `headers`. + +These aliases apply only to **ACL rule keys inside access control blocks** — they are unrelated to the `groups` field in the [`users` section](#users-and-groups). {% endhint %} ##### `groups_any_of`