Using JS Auth with found cluster
Using Found by elastic cluster helps a lot to have a ready to use and managed elasticsearch cluster.
I started my own cluster yesterday to power brownbaglunch.fr website (work in progress) and it was ready to use after some clicks!
It’s a kind of magic!
But I ran into an issue when you secure it and use the elasticsearch javascript client.
Creating your cluster
Adding ACL
By default, your cluster is opened but you can fix that by opening “Access Control” menu. Found proposes a default configuration which generates two users and restrict some access.
# Deny everyone by default, as authentication is required.
# Deny is the default also if no "default" is specified,
# so it's only necessary to specify it if you want the
# default to be "allow".
default: deny
auth:
users:
searchonly: searchonlypassword
readwrite: readwritepassword
rules:
- paths:
# Match all search requests.
- '/_search|/([^_/]+/_search)|/[^_/]+/[^_/]+/_search'
conditions:
- basic_auth:
users: [searchonly]
action: allow
# Also, allow any GET-request.
- paths: ['.*']
conditions:
- basic_auth:
users:
- searchonly
- method:
verbs: [GET]
action: allow
# Allow everything for the readwrite-user
- paths: ['.*']
conditions:
- basic_auth:
users:
- readwrite
# Uncomment the following if you want to require SSL.
# - ssl:
# require: true
action: allow
Create your javascript application
<!DOCTYPE html>
<html>
<head>
<script src="https://cdn.rawgit.com/elastic/bower-elasticsearch-js/12ec0b8ee6d776e077b160e6dd6fc2e1b5818a86/elasticsearch.min.js"></script>
</head>
<body>
<script>
var login = "readwrite";
var password = "readwritepassword";
var hostname = "youclusteraddress.foundcluster.com";
var client = new elasticsearch.Client({
hosts: [
{
host: hostname,
auth: login + ':' + password
}
]
});
client.cluster.health().then(done, done);
function done(resp) {
console.log(resp);
}
</script>
</body>
</html>
If you run it, you will get something like:
elasticsearch.min.js:18 OPTIONS http://youclusteraddress.foundcluster.com:9200/_cluster/health 401 (Unauthorized)26.d.request @ elasticsearch.min.js:18c @ elasticsearch.min.js:1842.j.applyArgs @ elasticsearch.min.js:18k @ elasticsearch.min.js:11(anonymous function) @ elasticsearch.min.js:11
bblfr_elasticsearch.dev/:1 XMLHttpRequest cannot load http://youclusteraddress.foundcluster.com:9200/_cluster/health. Invalid HTTP status code 401
elasticsearch.min.js:18 ERROR: 2015-05-19T14:47:01Z
Error: Request error, retrying -- Request failed to complete.
at d.29.d.error (http://bblfr_elasticsearch.dev/lib/elasticsearch.min.js:18:15537)
at d (http://bblfr_elasticsearch.dev/lib/elasticsearch.min.js:18:22917)
at XMLHttpRequest.26.d.request.d.onreadystatechange (http://bblfr_elasticsearch.dev/lib/elasticsearch.min.js:18:9781)
Modify ACL
The javascript client needs to discuss with found using OPTIONS
verb. So you basically need to add:
- paths:
- '.*'
conditions:
- method:
verbs: [OPTIONS]
action: allow
Running the same code will now work as expected!
{
cluster_name: "youclusteraddress",
status: "green",
timed_out: false,
number_of_nodes: 1,
number_of_data_nodes: 1
// ...
}
Using ACL for aliases
Note that for the project, I created one index named bbl_1
and one alias on top of it bbl
.
So I opened read access to anonymous users on this alias and add a secured one when it comes to write operations.
OPTIONS
in that case is applied only to the bbl
alias. I came up with this config:
default: deny
auth:
users:
readwrite: readwritepassword
rules:
- paths:
- '/bbl/.*'
conditions:
- method:
verbs: [OPTIONS]
action: allow
- paths:
- '/bbl/_search'
conditions:
- method:
verbs: [GET, POST]
action: allow
- paths: ['/bbl/.*']
conditions:
- method:
verbs: [GET]
action: allow
- paths: ['/bbl/.*']
conditions:
- method:
verbs: [PUT, DELETE]
- basic_auth:
users: [readwrite]
action: allow