ReadonlyREST puts access control inside Elasticsearch instead of in front of it
Free Elasticsearch security plugin and Kibana security plugin: super-easy Kibana multi-tenancy, Encryption, Authentication, Authorization, Auditing
At a glance
- What is it?
- ReadonlyREST is a Scala and Java Elasticsearch plugin that exposes the embedded HTTP server with rule based filtering for authentication, authorization, encryption and auditing. Its central argument is that access control belongs at the Elasticsearch protocol level, after queries are parsed, not in a reverse proxy that matches paths.
- Who is it for?
- ReadonlyREST fits an Elasticsearch cluster that has to answer read traffic from people or systems outside the cluster, and an operator who would rather express access rules against Elasticsearch semantics than against HTTP paths. It does not fit a cluster on an Elasticsearch version the project has no matching build for, nor a team unwilling to read its external rule documentation or to accept that the rule set lives outside the repository.
- Can I use it commercially?
- Yes, with conditions. GPL-3.0 is a copyleft licence: if you distribute software that includes it, you must release that software's source code under the same licence. Running it internally without distributing it does not trigger that obligation.
- Is it still maintained?
- Yes. The repository received new commits within the last day.
- What is it written in?
- Mainly Scala, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
The problem: exposing an Elasticsearch HTTP server without exposing write access
ReadonlyREST is a plugin for Elasticsearch that lets you put the cluster's own HTTP server in front of users while blocking attempts to delete or modify data. The repository description frames it as a security plugin for Elasticsearch and for Kibana, listing multi-tenancy in Kibana, encryption, authentication, authorization and auditing among its advertised features, and the project site is readonlyrest.com.
The audience is specific. It is the team that has an Elasticsearch cluster and needs some part of it reachable by people who are not cluster operators: a support team searching tickets, a dashboard product reading an index, a partner integration, or a read-only replica of operational logs. Anyone in that position faces the same problem, which is that Elasticsearch's own HTTP API is not safe to expose as it stands, and filtering it afterwards is awkward.
The project frames this as a solved problem by a filtering layer rather than by a second system. The one-line description is that there is no need for a proxy, and the history section says the project began in a StackOverflow thread about using CloudFront to expose the Elasticsearch REST API in read-only mode.
That origin explains the design. This is a tool built by someone who had to answer the question in the simplest way that also happened to be the least fragile.
Why a reverse proxy in front of Elasticsearch is the wrong layer
The documentation argues against the common alternative directly. The suggestion it rejects is spinning up an HTTP proxy such as Varnish, Nginx or HAProxy between Elasticsearch and its clients, filtering access with regular expressions on HTTP methods and paths.
Two reasons are given. The first is architectural: another proxy in the path adds complexity. The second is the one that matters for security. Reasoning about security at the HTTP level is described as risky, flaky and less granular than controlling access at the internal Elasticsearch protocol level. The claim in the documentation is that the only clean way to do access control is after Elasticsearch has parsed the queries.
That is the whole design idea, and it explains the feature set. Once the plugin sits inside the cluster, it can reason about indices, about the operation being requested, about the fields being written and about the identity of the caller, rather than about whether the URL contains a forbidden word. A rule written at the HTTP layer has to guess; a rule written after parsing does not.
The cost of this choice is that the plugin is bound to Elasticsearch internals and to specific versions of them. You cannot take it out and reuse it elsewhere, and it cannot protect a cluster it is not installed in.
A pure-Java filtering layer over the embedded Netty server
The technical claim about architecture is that other security plugins replace the high performance Netty based embedded REST API of Elasticsearch with Tomcat, Jetty or other XML based JEE stacks, and that this plugin instead is a lightweight pure-Java filtering layer, with the SSL layer provided as an extra Netty transport handler.
That is a meaningful difference in resource use and in failure modes. An embedded handler sits inside the same JVM and the same event loop as the server it filters, so there is no second HTTP stack to tune, no second set of thread pools and no extra network hop between the proxy and the cluster. It also means the plugin sees requests at the point where Elasticsearch is already parsing them, which is what the previous section is about.
The implementation language is Scala, with the filtering layer written in pure Java according to the documentation, and the build is Gradle based with a scalafmt configuration. The repository also carries a benchmarks directory, so the performance claim has somewhere to be measured rather than only asserted.
The trade-off is that this design only works for Elasticsearch. There is no portable abstraction here, and the plugin cannot be used as a general HTTP authorisation layer in front of anything else.
Getting it: Maven Central artifacts, per-version source trees and a Docker image
The repository does not give a copy-and-paste installation command, so it is worth being explicit about where the project says to get the software. The build output is published to Maven Central under the tech.beshu.ror group, and the badges in the documentation point at the audit artifacts for two different Elasticsearch lines.
tech.beshu.ror/audit_2.13
tech.beshu.ror/audit_2.12Those coordinates are the audit module, which is the part an operator interacts with. The repository itself is organised the other way round, with one source tree per supported Elasticsearch version, from es67x through es94x, each a separate build target. The presence of those directories is the practical constraint on adoption: your cluster version determines which build you need, and a version without a matching tree means you are building one yourself.
There is also a docker-image directory and a docker-based-builder directory, and a docker-envs directory, which suggests containerised packaging of the plugin is part of the workflow rather than an afterthought.
For the rule documentation, the project points outside the repository to the official website, docs.readonlyrest.com, with the detailed rule reference under its Elasticsearch section. The repository also ships docs, a development guide in development.md, a SECURITY.md, a CONTRIBUTING.md and a CLAUDE.md file, and the CI configuration lives under ci and .github.
The rule set lives on the website, not in the repository
This is the most important practical detail for anyone evaluating the project. The documentation links the full set of available rules to the official website, and the repository itself does not carry a copy of that reference. So the rules, their parameters and their defaults are documented outside the code you would be deploying.
That has two consequences. The first is practical: you will need the website open while you configure access rules, and the exact syntax of a rule is not something you can read offline in the repository. The second is about trust and reproducibility. A rule set that can change independently of the plugin binary means the behaviour of your cluster can change without a version bump, so a configuration you audit today is not necessarily the configuration that applies later. Pinning plugin versions without pinning the rule semantics leaves a gap.
The documentation also pushes the rule model towards internal Elasticsearch concepts rather than HTTP ones. The kinds of things a rule needs to express, index level access, read versus write, and the identity of the caller, only make sense once Elasticsearch has parsed the request, which is the argument the plugin makes against proxy filtering in the first place.
Auditing, custom audit examples and what the audit module records
Auditing is one of the named feature areas, and the repository backs it with dedicated directories. There is an audit directory for the audit module itself, and a custom-audit-examples directory showing how to extend it, which suggests the audit log format is intended to be shaped by operators rather than accepted as fixed.
This matters for the use case the plugin targets. If you are exposing an Elasticsearch cluster to an internal application, the audit trail is how you answer the question of which client read which index, and a plugin that filters at the protocol level is in a much better position to produce that record than a proxy that only sees paths.
The project also keeps an eshome directory in the tree, which in this layout is the Elasticsearch home used for test runs, and a build-base directory with the shared Gradle configuration. Between the benchmarks directory and the per-version source trees, the repository shows a project that runs the plugin against real Elasticsearch versions as part of its own development, which is what you would expect from a plugin whose compatibility surface is the version range.
What the repository does not do is describe the audit record format, the fields it contains, or where the log is written. For that you are back to the external documentation.
GPL-3.0, a contributor licence agreement, and no GitHub releases
The project is licensed GPL-3.0. For an Elasticsearch plugin that most organisations run as part of a server stack, that is the licence your compliance process will care about, so read the LICENSE.md file and have it checked before the plugin goes anywhere near production. This is a pointer to the right file, not legal advice.
The contributor terms deserve a closer look than most projects get. The contributor licence agreement grants the project owner, Simone Scarduzio, a non-exclusive, irrevocable, worldwide, royalty-free, sublicenseable and transferable licence over contributions, explicitly including the right to use them under GPLv3 or under binary, proprietary or commercial licences. Contributions are also provided as is, without warranties. For a company contributing code and later wanting to relicense it, that is a one-way grant, and it is stated at the top of the contributor documentation rather than buried.
Release management works differently from the usual GitHub model. The repository has no GitHub releases at all, so versions are not tagged in the way most projects tag them. The last push to the repository was on 2026-10-19, which shows the work continues even though the version history lives elsewhere, on Maven Central. Plan your upgrades around the Maven Central coordinates rather than around GitHub tags.
Editorial conclusion
ReadonlyREST fits an Elasticsearch cluster that has to answer read traffic from people or systems outside the cluster, and an operator who would rather express access rules against Elasticsearch semantics than against HTTP paths. It does not fit a cluster on an Elasticsearch version the project has no matching build for, nor a team unwilling to read its external rule documentation or to accept that the rule set lives outside the repository. Before installing it, check that a build exists for your exact Elasticsearch version, review the rule reference at docs.readonlyrest.com against the roles your users actually need, and confirm that the audit artifact published to Maven Central under the tech.beshu.ror group covers the version you run.
Frequently asked questions
What is ReadonlyREST used for?
It exposes the HTTP server embedded in Elasticsearch while blocking attempts to delete or modify data, and it adds authentication, authorization, encryption and auditing at the Elasticsearch protocol level. The project presents it as an alternative to putting a filtering reverse proxy in front of the cluster.
Why does ReadonlyREST discourage using a proxy in front of Elasticsearch?
The documentation argues that filtering with regular expressions on HTTP methods and paths is risky, flaky and less granular than controlling access at the internal Elasticsearch protocol level, and that the clean way is to act after Elasticsearch has parsed the queries.
Where do I find the ReadonlyREST rule documentation?
The full list of available rules is documented on the official website at docs.readonlyrest.com under the Elasticsearch rules section. The repository links to it rather than carrying a copy of the reference.
Which Elasticsearch versions does ReadonlyREST build for?
The repository contains one source tree per supported version, from es67x through es94x, and the published audit artifacts on Maven Central exist for particular version lines such as 2.12 and 2.13 under the tech.beshu.ror group. Check that a build matches your cluster version.
What licence is ReadonlyREST under and what are the contributor terms?
The project is licensed GPL-3.0, and the contributor licence agreement grants the project owner a broad, irrevocable and transferable licence over contributions, including the right to distribute them under GPLv3 or under proprietary or commercial licences. Contributions are provided as is.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/sscarduzio-elasticsearch-readonlyrest-plugin)Was this useful?