Skip to content

Commit ba9638a

Browse files
committed
Action rule and generalisation of wildcard aware matcher. Fixes sscarduzio#41
1 parent 0f6aa93 commit ba9638a

File tree

6 files changed

+202
-103
lines changed

6 files changed

+202
-103
lines changed

src/main/java/org/elasticsearch/plugin/readonlyrest/acl/blocks/Block.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,10 @@ public Block(Settings s, ESLogger logger) {
6868
conditionsToCheck.add(new IndicesRule(s));
6969
} catch (RuleNotConfiguredException e) {
7070
}
71+
try {
72+
conditionsToCheck.add(new ActionsRule(s));
73+
} catch (RuleNotConfiguredException e) {
74+
}
7175
}
7276

7377
public String getName() {
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
package org.elasticsearch.plugin.readonlyrest.acl.blocks.rules;
2+
3+
import com.google.common.collect.Lists;
4+
import org.elasticsearch.common.logging.ESLogger;
5+
import org.elasticsearch.common.logging.Loggers;
6+
import org.elasticsearch.common.settings.Settings;
7+
import org.elasticsearch.plugin.readonlyrest.ConfigurationHelper;
8+
9+
import java.util.List;
10+
import java.util.regex.Matcher;
11+
import java.util.regex.Pattern;
12+
13+
/**
14+
* Created by sscarduzio on 02/04/2016.
15+
*/
16+
public class MatcherWithWildcards {
17+
18+
private final static ESLogger logger = Loggers.getLogger(MatcherWithWildcards.class);
19+
20+
protected List<String> plainWordMatchers = Lists.newArrayList();
21+
protected List<Pattern> wildcardMatchers = Lists.newArrayList();
22+
23+
public MatcherWithWildcards(Settings s, String key) throws RuleNotConfiguredException {
24+
// Will work with single, non array conf.
25+
String[] a = s.getAsArray(key);
26+
27+
if (a == null || a.length == 0) {
28+
throw new RuleNotConfiguredException();
29+
}
30+
31+
for (int i = 0; i < a.length; i++) {
32+
a[i] = normalizePlusAndMinusIndex(a[i]);
33+
if (ConfigurationHelper.isNullOrEmpty(a[i])) {
34+
continue;
35+
}
36+
if (a[i].contains("*")) {
37+
// Patch the simple star wildcard to become a regex: ("*" -> ".*")
38+
String regex = ("\\Q" + a[i] + "\\E").replace("*", "\\E.*\\Q");
39+
40+
// Pre-compile the regex pattern matcher to validate the regex
41+
// AND faster matching later on.
42+
wildcardMatchers.add(Pattern.compile(regex));
43+
44+
// Let's match this also literally
45+
plainWordMatchers.add(a[i]);
46+
} else {
47+
// A plain word can be matched as string
48+
plainWordMatchers.add(a[i].trim());
49+
}
50+
}
51+
}
52+
53+
/**
54+
* Returns null if the matchable is not worth processing because it's invalid or starts with "-"
55+
*/
56+
static String normalizePlusAndMinusIndex(String s) {
57+
if(ConfigurationHelper.isNullOrEmpty(s)){
58+
return null;
59+
}
60+
// Ignore the excluded indices
61+
if (s.startsWith("-")) {
62+
return null;
63+
}
64+
// Call included indices with their name
65+
if (s.startsWith("+")) {
66+
if (s.length() == 1) {
67+
logger.warn("invalid matchable! " + s);
68+
return null;
69+
}
70+
return s.substring(1, s.length());
71+
}
72+
return s;
73+
}
74+
75+
76+
public boolean match(String[] matchables) {
77+
78+
if (matchables == null || matchables.length == 0) {
79+
return false;
80+
}
81+
82+
for (String i : matchables) {
83+
String matchable = normalizePlusAndMinusIndex(i);
84+
if (matchable == null) {
85+
continue;
86+
}
87+
// Try to match plain strings first
88+
if (plainWordMatchers.contains(matchable)) {
89+
return true;
90+
}
91+
92+
for (Pattern p : wildcardMatchers) {
93+
Matcher m = p.matcher(matchable);
94+
if (m == null) {
95+
continue;
96+
}
97+
if (m.find()) {
98+
return true;
99+
}
100+
}
101+
}
102+
return false;
103+
}
104+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
package org.elasticsearch.plugin.readonlyrest.acl.blocks.rules.impl;
2+
3+
import org.elasticsearch.common.logging.ESLogger;
4+
import org.elasticsearch.common.logging.Loggers;
5+
import org.elasticsearch.common.settings.Settings;
6+
import org.elasticsearch.plugin.readonlyrest.acl.RequestContext;
7+
import org.elasticsearch.plugin.readonlyrest.acl.blocks.rules.MatcherWithWildcards;
8+
import org.elasticsearch.plugin.readonlyrest.acl.blocks.rules.Rule;
9+
import org.elasticsearch.plugin.readonlyrest.acl.blocks.rules.RuleExitResult;
10+
import org.elasticsearch.plugin.readonlyrest.acl.blocks.rules.RuleNotConfiguredException;
11+
12+
/**
13+
* Created by sscarduzio on 14/02/2016.
14+
*/
15+
public class ActionsRule extends Rule {
16+
17+
private final static ESLogger logger = Loggers.getLogger(ActionsRule.class);
18+
19+
protected MatcherWithWildcards m;
20+
21+
public ActionsRule(Settings s) throws RuleNotConfiguredException {
22+
super(s);
23+
m = new MatcherWithWildcards(s, KEY);
24+
}
25+
26+
27+
@Override
28+
public RuleExitResult match(RequestContext rc) {
29+
if(m.match(new String[]{rc.getAction()})){
30+
return MATCH;
31+
}
32+
logger.debug("This request uses the action'" + rc.getAction() + "' and none of them is on the list.");
33+
return NO_MATCH;
34+
}
35+
}

src/main/java/org/elasticsearch/plugin/readonlyrest/acl/blocks/rules/impl/IndicesRule.java

Lines changed: 6 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,15 @@
11
package org.elasticsearch.plugin.readonlyrest.acl.blocks.rules.impl;
22

3-
import com.google.common.collect.Lists;
43
import org.elasticsearch.common.logging.ESLogger;
54
import org.elasticsearch.common.logging.Loggers;
65
import org.elasticsearch.common.settings.Settings;
7-
import org.elasticsearch.plugin.readonlyrest.ConfigurationHelper;
86
import org.elasticsearch.plugin.readonlyrest.acl.RequestContext;
7+
import org.elasticsearch.plugin.readonlyrest.acl.blocks.rules.MatcherWithWildcards;
98
import org.elasticsearch.plugin.readonlyrest.acl.blocks.rules.Rule;
109
import org.elasticsearch.plugin.readonlyrest.acl.blocks.rules.RuleExitResult;
1110
import org.elasticsearch.plugin.readonlyrest.acl.blocks.rules.RuleNotConfiguredException;
1211

1312
import java.util.Arrays;
14-
import java.util.List;
15-
import java.util.regex.Matcher;
16-
import java.util.regex.Pattern;
1713

1814
/**
1915
* Created by sscarduzio on 20/02/2016.
@@ -22,90 +18,19 @@ public class IndicesRule extends Rule {
2218

2319
private final static ESLogger logger = Loggers.getLogger(IndicesRule.class);
2420

25-
protected List<String> indicesToMatch = Lists.newArrayList();
26-
protected List<Pattern> indicesWithWildcards = Lists.newArrayList();
21+
protected MatcherWithWildcards m;
2722

2823
public IndicesRule(Settings s) throws RuleNotConfiguredException {
2924
super(s);
30-
String[] a = s.getAsArray(KEY);
31-
32-
if (a == null || a.length == 0) {
33-
throw new RuleNotConfiguredException();
34-
}
35-
36-
for (int i = 0; i < a.length; i++) {
37-
a[i] = normalizePlusAndMinusIndex(a[i]);
38-
if (ConfigurationHelper.isNullOrEmpty(a[i])) {
39-
continue;
40-
}
41-
if (a[i].contains("*")) {
42-
// Patch the simple star wildcard to become a regex: ("*" -> ".*")
43-
String regex = ("\\Q" + a[i] + "\\E").replace("*", "\\E.*\\Q");
44-
45-
// Pre-compile the regex pattern matcher to validate the regex
46-
// AND faster matching later on.
47-
indicesWithWildcards.add(Pattern.compile(regex));
48-
49-
// Let's match this also literally
50-
indicesToMatch.add(a[i]);
51-
} else {
52-
// A plain word can be matched as string
53-
indicesToMatch.add(a[i].trim());
54-
}
55-
}
56-
}
57-
58-
/**
59-
* Returns null if the index is not worth processing because it's invalid or starts with "-"
60-
*/
61-
String normalizePlusAndMinusIndex(String s) {
62-
// Ignore the excluded indices
63-
if (s.startsWith("-")) {
64-
return null;
65-
}
66-
// Call included indices with their name
67-
if (s.startsWith("+")) {
68-
if (s.length() == 1) {
69-
logger.warn("invalid index! " + s);
70-
return null;
71-
}
72-
return s.substring(1, s.length());
73-
}
74-
return s;
25+
m = new MatcherWithWildcards(s, KEY);
7526
}
7627

7728
@Override
7829
public RuleExitResult match(RequestContext rc) {
79-
80-
String[] indices = rc.getIndices();
81-
82-
if (indices == null || indices.length == 0) {
83-
logger.warn("didn't find any index for this request: " + rc.getRequest().method() + " " + rc.getRequest().rawPath());
84-
return NO_MATCH;
30+
if(m.match(rc.getIndices())){
31+
return MATCH;
8532
}
86-
87-
for (String i : indices) {
88-
String idx = normalizePlusAndMinusIndex(i);
89-
if(idx == null) {
90-
continue;
91-
}
92-
// Try to match plain strings first
93-
if (indicesToMatch.contains(idx)) {
94-
return MATCH;
95-
}
96-
97-
for (Pattern p : indicesWithWildcards) {
98-
Matcher m = p.matcher(idx);
99-
if(m == null) {
100-
continue;
101-
}
102-
if (m.find()) {
103-
return MATCH;
104-
}
105-
}
106-
}
107-
108-
logger.debug("This request uses the indices '" + Arrays.toString(indices) + "' and none of them is on the list.");
33+
logger.debug("This request uses the indices '" + Arrays.toString(rc.getIndices()) + "' and none of them is on the list.");
10934
return NO_MATCH;
11035
}
11136

0 commit comments

Comments
 (0)