Skip to content

Commit c3dc04f

Browse files
author
Simone Scarduzio
committed
[ENHANCEMENT] issue#8 : throw runtime error if configuration is incorrect.
1 parent 04dd724 commit c3dc04f

File tree

6 files changed

+115
-18
lines changed

6 files changed

+115
-18
lines changed

src/main/java/org/elasticsearch/rest/action/readonlyrest/ReadonlyRestAction.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
import org.elasticsearch.rest.RestStatus;
1414
import org.elasticsearch.rest.action.readonlyrest.acl.ACL;
1515
import org.elasticsearch.rest.action.readonlyrest.acl.ACLRequest;
16+
import org.elasticsearch.rest.action.readonlyrest.acl.RuleConfigurationError;
1617

1718
/**
1819
* Readonly REST plugin. Adding some access control to the fast Netty based REST interface of Elasticsearch.
@@ -48,8 +49,9 @@ public ReadonlyRestAction(final Settings settings, Client client, RestController
4849
acl = new ACL(logger, settings);
4950
logger.info("ACL configuration: OK");
5051
}
51-
catch (Exception e) {
52+
catch (RuleConfigurationError e) {
5253
logger.error("impossible to initialize ACL configuration", e);
54+
throw e;
5355
}
5456
controller.registerFilter(new RestFilter() {
5557

@@ -61,6 +63,7 @@ public void process(RestRequest request, RestChannel channel, RestFilterChain fi
6163
ok(request, filterChain, channel);
6264
}
6365
else {
66+
logger.trace("forbidden request: " + aclReq + " Reason: " + reason);
6467
if(conf.forbiddenResponse != null){
6568
reason = conf.forbiddenResponse;
6669
}

src/main/java/org/elasticsearch/rest/action/readonlyrest/acl/ACL.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,13 @@ public class ACL {
1414
private TreeMap<Integer, Rule> rules = new TreeMap<>();
1515
private final static String PREFIX = "readonlyrest.access_control_rules";
1616

17-
public ACL(ESLogger logger, Settings s) throws Exception {
17+
public ACL(ESLogger logger, Settings s) {
1818
this.logger = logger;
1919
this.s = s;
2020
readRules();
2121
}
2222

23-
private void readRules() throws Exception {
23+
private void readRules() {
2424
Map<String, Settings> g = s.getGroups(PREFIX);
2525
// Maintaining the order is not guaranteed, moving everything to tree map!
2626
TreeMap<String, Settings> tmp = new TreeMap<>();
@@ -39,7 +39,7 @@ private void readRules() throws Exception {
3939
* Check the request against configured ACL rules. This does not work with try/catch because stacktraces are expensive
4040
* for performance.
4141
*
42-
* @param r
42+
* @param req the ACLRequest to be checked by the ACL rules.
4343
* @return null if request pass the rules or the name of the first violated rule
4444
*/
4545
public String check(ACLRequest req) {

src/main/java/org/elasticsearch/rest/action/readonlyrest/acl/Rule.java

Lines changed: 35 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,15 @@ public class Rule {
1212

1313
public enum Type {
1414
ALLOW, FORBID;
15+
16+
public static String valuesString(){
17+
StringBuilder sb = new StringBuilder();
18+
for(Type v: values()){
19+
sb.append(v.toString()).append(",");
20+
}
21+
sb.deleteCharAt(sb.length()-1);
22+
return sb.toString();
23+
}
1524
}
1625

1726
String name;
@@ -32,25 +41,32 @@ public Rule(String name, Type type, Pattern uri_re, Integer bodyLenght, List<Str
3241
this.stringRepresentation = toString;
3342
}
3443

35-
public static Rule build(Settings s) throws Exception {
44+
public static Rule build(Settings s) {
3645
List<String> hosts = null;
3746
String[] a = s.getAsArray("hosts");
3847
if (a != null && a.length > 0) {
39-
hosts = Lists.newArrayList(a);
40-
for (String address : a) {
41-
address = address.trim();
48+
hosts = Lists.newArrayList();
49+
for (int i=0; i < a.length; i++) {
50+
if(!ConfigurationHelper.isNullOrEmpty(a[i])) {
51+
hosts.add(a[i].trim());
52+
}
4253
}
4354
}
4455

4556
a = s.getAsArray("methods");
4657
List<Method> methods = null;
4758
if (a != null && a.length > 0) {
48-
for (String string : a) {
49-
Method m = Method.valueOf(string.trim().toUpperCase());
50-
if (methods == null) {
51-
methods = Lists.newArrayList();
59+
try {
60+
for (String string : a) {
61+
Method m = Method.valueOf(string.trim().toUpperCase());
62+
if (methods == null) {
63+
methods = Lists.newArrayList();
64+
}
65+
methods.add(m);
5266
}
53-
methods.add(m);
67+
}
68+
catch(Throwable t){
69+
throw new RuleConfigurationError("Invalid HTTP method found in configuration " + a, t);
5470
}
5571
}
5672

@@ -60,13 +76,18 @@ public static Rule build(Settings s) throws Exception {
6076
uri_re = Pattern.compile(tmp.trim());
6177
}
6278
String name = s.get("name");
63-
Rule.Type type = Type.valueOf(s.get("type").toUpperCase());
64-
Integer maxBodyLenght = s.getAsInt("maxBodyLength", null);
79+
80+
String sType = s.get("type");
81+
if(sType == null) {
82+
throw new RuleConfigurationError("The field \"type\" is mandatory and should be either of " + Type.valuesString() + ". If this field is correct, check the YAML indentation is correct.", null);
83+
}
84+
Rule.Type type = Type.valueOf(sType.toUpperCase());
85+
Integer maxBodyLength = s.getAsInt("maxBodyLength", null);
6586
if ((!ConfigurationHelper.isNullOrEmpty(name) && type != null) &&
66-
(uri_re != null || maxBodyLenght != null || hosts != null || methods != null)) {
67-
return new Rule(name.trim(), type, uri_re, maxBodyLenght, hosts, methods, s.toDelimitedString(' '));
87+
(uri_re != null || maxBodyLength != null || hosts != null || methods != null)) {
88+
return new Rule(name.trim(), type, uri_re, maxBodyLength, hosts, methods, s.toDelimitedString(' '));
6889
}
69-
throw new Exception("insufficient or invalid configuration for rule: '" + name + "'");
90+
throw new RuleConfigurationError("insufficient or invalid configuration for rule: '" + name + "'", null);
7091

7192
}
7293

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
package org.elasticsearch.rest.action.readonlyrest.acl;
2+
3+
/**
4+
* Created by sscarduzio on 12/07/2015.
5+
*/
6+
public class RuleConfigurationError extends RuntimeException {
7+
public RuleConfigurationError(String msg, Throwable cause) {
8+
super(msg, cause);
9+
}
10+
}

src/test/issue8.yml

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
cluster:
2+
name: elasticsearch
3+
4+
index:
5+
number_of_replicas: 0
6+
number_of_shards: 1
7+
analysis:
8+
analyzer:
9+
eulang:
10+
type: custom
11+
tokenizer: standard
12+
filter: [standard, lowercase, asciifolding]
13+
location:
14+
type: custom
15+
tokenizer: standard
16+
filter: [standard, lowercase, asciifolding]
17+
18+
transport.tcp.port : 9310
19+
20+
readonlyrest:
21+
# (De)activate plugin
22+
enable: true
23+
24+
# HTTP response body in case of forbidden request.
25+
# If this is null or omitted, the name of the first violated access control rule is returned (useful for debugging!)
26+
response_if_req_forbidden: Sorry, your request is forbidden
27+
28+
# Default policy is to forbid everything, let's define a whitelist
29+
access_control_rules:
30+
31+
- name: restricted access to all other hosts
32+
type: allow
33+
methods: [OPTIONS,GET]
34+
maxBodyLength: 0
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
package org.elasticsearch.rest.action.readonlyrest.acl.test;
2+
3+
import org.elasticsearch.common.base.Charsets;
4+
import org.elasticsearch.common.logging.ESLoggerFactory;
5+
import org.elasticsearch.common.settings.ImmutableSettings;
6+
import org.elasticsearch.common.settings.Settings;
7+
import org.elasticsearch.rest.RestRequest.Method;
8+
import org.elasticsearch.rest.action.readonlyrest.acl.ACL;
9+
import org.elasticsearch.rest.action.readonlyrest.acl.ACLRequest;
10+
import org.elasticsearch.rest.action.readonlyrest.acl.RuleConfigurationError;
11+
import org.junit.*;
12+
13+
import java.io.IOException;
14+
import java.nio.ByteBuffer;
15+
import java.nio.file.Files;
16+
import java.nio.file.Paths;
17+
18+
public class Issue8ACLTest {
19+
20+
@Test(expected=RuleConfigurationError.class)
21+
public final void testRuleConfigurationError() throws Throwable{
22+
byte[] encoded = Files.readAllBytes(Paths.get(System.getProperty("user.dir") + "/src/test/issue8.yml"));
23+
String str = Charsets.UTF_8.decode(ByteBuffer.wrap(encoded)).toString();
24+
Settings s = ImmutableSettings.builder().loadFromSource(str).build();
25+
new ACL(ESLoggerFactory.getLogger(ACL.class.getName()), s);
26+
}
27+
28+
29+
}

0 commit comments

Comments
 (0)