Conflicts:
	docs/public/04-authorization.asciidoc
	docs/public/clients/logstash.asciidoc

Original commit: elastic/x-pack-elasticsearch@699aa52379
This commit is contained in:
Paul Echeverri 2014-10-23 14:01:41 -07:00
commit b3789a74e4
27 changed files with 391 additions and 47 deletions

View File

@ -0,0 +1,13 @@
admin:
cluster: all
indices:
'.*': all
power_user:
cluster: monitor
indices:
'.*': all
user:
indices:
'.*': read

View File

@ -0,0 +1 @@
*43QåÆ]Ûùð/÷ô<14>>eû.²¾g^lçH¶ûgu«•±Ê O/Gaoƒ˜ Ⱥâ•rr³ø´èk_ËÐ2û*¹©m•?д,”]‡<>Ƥå¦p¶I婳ò¼£¸sOYwu†¹äŸK•¨°+_¹0

View File

@ -0,0 +1,5 @@
admin-bcrypt:$2a$10$5uCJHPn3p0ZPQp6rIIgcDO0VZ3urZZmA.egHiy/WknxIkAyZXPGpy
admin-plain:{plain}changeme
admin-sha:{SHA}+pvrmeQCmtWmYVOZ57uuITVghrM=
admin-apr:$apr1$fCQ4kkwA$ETvNx37ooOcdau5a61S/s.
admin-sha2:$5$mw0LEbLr$s57Rbo0wfH8Z690Dc0..VgC1qn/a5h73bbpt8kql8B4

View File

@ -0,0 +1 @@
admin:admin-bcrypt,admin-sha,admin-plain,admin-apr,admin-sha2

12
.esvmrc
View File

@ -3,12 +3,15 @@
"plugins": [ "lmenezes/elasticsearch-kopf", { "name": "shield", "path" : "file:./target/releases/elasticsearch-shield-1.0.0-SNAPSHOT.zip" } ],
"config" : {
"cluster": { "name": "shield" },
"indices.store.throttle.max_bytes_per_sec": "100mb",
"discovery" : {
"type" : "zen",
"zen.ping.multicast.enabled": false,
"zen.ping.unicast.hosts" : [ "localhost:9300", "localhost:9301" ]
},
"shield" : {
"enabled" : true,
"system_key.file": ".esvm-shield-config/system_key",
"audit.enabled" : false,
"transport.ssl": true,
"http.ssl": true,
@ -17,7 +20,14 @@
"keystore_password" : "testnode",
"truststore" : "src/test/resources/org/elasticsearch/shield/transport/ssl/certs/simple/testnode.jks",
"truststore_password" : "testnode"
}
},
"authc": {
"esusers.files" : {
"users" : ".esvm-shield-config/users",
"users_roles" : ".esvm-shield-config/users_roles"
}
},
"authz.store.files.roles" : ".esvm-shield-config/roles.yml"
}
}
},

View File

@ -59,6 +59,7 @@ public class SecurityFilter extends AbstractComponent {
AuthenticationToken token = authcService.token(action, request, defaultToken);
User user = authcService.authenticate(action, request, token);
authzService.authorize(user, action, request);
return user;
}

View File

@ -7,6 +7,8 @@ package org.elasticsearch.shield;
import org.elasticsearch.shield.authz.SystemRole;
import java.util.Arrays;
/**
* An authenticated user
*/
@ -48,6 +50,26 @@ public abstract class User {
public String[] roles() {
return roles;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Simple simple = (Simple) o;
if (!Arrays.equals(roles, simple.roles)) return false;
if (!username.equals(simple.username)) return false;
return true;
}
@Override
public int hashCode() {
int result = username.hashCode();
result = 31 * result + Arrays.hashCode(roles);
return result;
}
}
private static class System extends User {
@ -67,6 +89,7 @@ public abstract class User {
public String[] roles() {
return ROLES;
}
}
}

View File

@ -62,6 +62,11 @@ public class InternalAuthenticationService extends AbstractComponent implements
for (Realm realm : realms) {
token = realm.token(message);
if (token != null) {
if (logger.isTraceEnabled()) {
logger.trace("Realm [{}] resolved auth token [{}] from transport request with action [{}]", realm.type(), token.principal(), action);
}
message.putInContext(TOKEN_CTX_KEY, token);
return token;
}

View File

@ -29,7 +29,7 @@ public class ESUsersModule extends AbstractShieldModule.Node {
@Override
protected void configureNode() {
if (enabled) {
bind(Realm.class).annotatedWith(named(ESUsersRealm.TYPE)).to(ESUsersRealm.class).asEagerSingleton();
bind(ESUsersRealm.class).asEagerSingleton();
bind(UserPasswdStore.class).annotatedWith(named("file")).to(FileUserPasswdStore.class).asEagerSingleton();
bind(UserRolesStore.class).annotatedWith(named("file")).to(FileUserRolesStore.class).asEagerSingleton();
} else {

View File

@ -6,7 +6,6 @@
package org.elasticsearch.shield.authc.esusers;
import org.elasticsearch.common.Strings;
import org.elasticsearch.common.component.AbstractComponent;
import org.elasticsearch.common.inject.Inject;
import org.elasticsearch.common.inject.name.Named;
import org.elasticsearch.common.settings.Settings;
@ -14,7 +13,7 @@ import org.elasticsearch.rest.RestController;
import org.elasticsearch.rest.RestRequest;
import org.elasticsearch.shield.User;
import org.elasticsearch.shield.authc.AuthenticationToken;
import org.elasticsearch.shield.authc.Realm;
import org.elasticsearch.shield.authc.support.CachingUsernamePasswordRealm;
import org.elasticsearch.shield.authc.support.UserPasswdStore;
import org.elasticsearch.shield.authc.support.UserRolesStore;
import org.elasticsearch.shield.authc.support.UsernamePasswordToken;
@ -23,7 +22,7 @@ import org.elasticsearch.transport.TransportMessage;
/**
*
*/
public class ESUsersRealm extends AbstractComponent implements Realm<UsernamePasswordToken> {
public class ESUsersRealm extends CachingUsernamePasswordRealm {
public static final String TYPE = "esusers";
@ -60,7 +59,7 @@ public class ESUsersRealm extends AbstractComponent implements Realm<UsernamePas
}
@Override
public User authenticate(UsernamePasswordToken token) {
protected User doAuthenticate(UsernamePasswordToken token) {
if (userPasswdStore == null) {
return null;
}

View File

@ -30,8 +30,11 @@ public abstract class CachingUsernamePasswordRealm extends AbstractComponent imp
private final Cache<String, UserWithHash> cache;
private final Hasher hasher;
protected CachingUsernamePasswordRealm(Settings settings) {
super(settings);
hasher = Hasher.resolve(componentSettings.get("cache.hash_algo", null), Hasher.SHA2);
TimeValue ttl = componentSettings.getAsTime(CACHE_TTL, DEFAULT_TTL);
if (ttl.millis() > 0) {
cache = CacheBuilder.newBuilder()
@ -91,7 +94,7 @@ public abstract class CachingUsernamePasswordRealm extends AbstractComponent imp
if (user == null) {
throw new AuthenticationException("Could not authenticate ['" + token.principal() + "]");
}
return new UserWithHash(user, token.credentials());
return new UserWithHash(user, token.credentials(), hasher);
}
};
@ -116,13 +119,15 @@ public abstract class CachingUsernamePasswordRealm extends AbstractComponent imp
public static class UserWithHash {
User user;
char[] hash;
public UserWithHash(User user, SecuredString password){
Hasher hasher;
public UserWithHash(User user, SecuredString password, Hasher hasher){
this.user = user;
this.hash = Hasher.HTPASSWD.hash(password);
this.hash = hasher.hash(password);
this.hasher = hasher;
}
public boolean verify(SecuredString password){
return Hasher.HTPASSWD.verify(password, hash);
return hasher.verify(password, hash);
}
}
}

View File

@ -12,6 +12,7 @@ import org.apache.commons.codec.digest.Md5Crypt;
import org.apache.commons.codec.digest.Sha2Crypt;
import org.elasticsearch.ElasticsearchIllegalArgumentException;
import org.elasticsearch.common.os.OsUtils;
import org.elasticsearch.shield.ShieldSettingsException;
import java.util.Locale;
@ -147,6 +148,10 @@ public enum Hasher {
}
switch (name.toLowerCase(Locale.ROOT)) {
case "htpasswd" : return HTPASSWD;
case "bcrypt" : return BCRYPT;
case "sha1" : return SHA1;
case "sha2" : return SHA2;
case "md5" : return MD5;
default:
return defaultHasher;
}
@ -155,7 +160,7 @@ public enum Hasher {
public static Hasher resolve(String name) {
Hasher hasher = resolve(name, null);
if (hasher == null) {
throw new ElasticsearchIllegalArgumentException("Unknown hash function [" + name + "]");
throw new ShieldSettingsException("Unknown hash function [" + name + "]");
}
return hasher;
}

View File

@ -33,7 +33,7 @@ import static org.elasticsearch.shield.support.Automatons.patterns;
*/
public abstract class Privilege<P extends Privilege<P>> {
static final String SUB_ACTION_SUFFIX_PATTERN = ".*";
static final String SUB_ACTION_SUFFIX_PATTERN = "*";
public static final System SYSTEM = new System();
@ -76,7 +76,9 @@ public abstract class Privilege<P extends Privilege<P>> {
public static class System extends Privilege<System> {
protected static final Predicate<String> PREDICATE = new AutomatonPredicate(patterns(
"internal:.*"
"internal:*",
"indices:monitor/*", // added for marvel
"cluster:monitor/*" // added for marvel
));
private System() {
@ -97,18 +99,18 @@ public abstract class Privilege<P extends Privilege<P>> {
public static class Index extends AutomatonPrivilege<Index> {
public static final Index NONE = new Index(Name.NONE, Automata.makeEmpty());
public static final Index ALL = new Index(Name.ALL, "indices:.*");
public static final Index MANAGE = new Index("manage", "indices:monitor/.*", "indices:admin/.*");
public static final Index ALL = new Index(Name.ALL, "indices:*");
public static final Index MANAGE = new Index("manage", "indices:monitor/*", "indices:admin/*");
public static final Index CREATE_INDEX = new Index("create_index", "indices:admin/create");
public static final Index MONITOR = new Index("monitor", "indices:monitor/.*");
public static final Index DATA_ACCESS = new Index("data_access", "indices:data/.*");
public static final Index CRUD = new Index("crud", "indices:data/write/.*", "indices:data/read/.*");
public static final Index READ = new Index("read", "indices:data/read/.*");
public static final Index SEARCH = new Index("search", SearchAction.NAME + ".*", GetAction.NAME + ".*");
public static final Index GET = new Index("get", GetAction.NAME + ".*");
public static final Index INDEX = new Index("index", "indices:data/write/index.*", "indices:data/write/update");
public static final Index DELETE = new Index("delete", "indices:data/write/delete.*");
public static final Index WRITE = new Index("write", "indices:data/write/.*");
public static final Index MONITOR = new Index("monitor", "indices:monitor/*");
public static final Index DATA_ACCESS = new Index("data_access", "indices:data/*");
public static final Index CRUD = new Index("crud", "indices:data/write/*", "indices:data/read/*");
public static final Index READ = new Index("read", "indices:data/read/*");
public static final Index SEARCH = new Index("search", SearchAction.NAME + "*", GetAction.NAME + "*");
public static final Index GET = new Index("get", GetAction.NAME + "*");
public static final Index INDEX = new Index("index", "indices:data/write/index*", "indices:data/write/update");
public static final Index DELETE = new Index("delete", "indices:data/write/delete*");
public static final Index WRITE = new Index("write", "indices:data/write/*");
public static final Index BENCHMARK = new Index("benchmark", "indices:data/benchmark");
private static final Index[] values = new Index[] {
@ -196,8 +198,8 @@ public abstract class Privilege<P extends Privilege<P>> {
public static class Cluster extends AutomatonPrivilege<Cluster> {
public static final Cluster NONE = new Cluster(Name.NONE, Automata.makeEmpty());
public static final Cluster ALL = new Cluster(Name.ALL, "cluster:.*", "indices:admin/template/.*");
public static final Cluster MONITOR = new Cluster("monitor", "cluster:monitor/.*");
public static final Cluster ALL = new Cluster(Name.ALL, "cluster:*", "indices:admin/template/*");
public static final Cluster MONITOR = new Cluster("monitor", "cluster:monitor/*");
private static final Cluster[] values = new Cluster[] { NONE, ALL, MONITOR };
@ -272,7 +274,7 @@ public abstract class Privilege<P extends Privilege<P>> {
}
static String actionToPattern(String text) {
return text.replace(":", "\\:") + SUB_ACTION_SUFFIX_PATTERN;
return text + SUB_ACTION_SUFFIX_PATTERN;
}
@SuppressWarnings("unchecked")

View File

@ -7,9 +7,12 @@ package org.elasticsearch.shield.support;
import org.apache.lucene.util.automaton.Automata;
import org.apache.lucene.util.automaton.Automaton;
import org.apache.lucene.util.automaton.Operations;
import org.apache.lucene.util.automaton.RegExp;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import static org.apache.lucene.util.automaton.MinimizationOperations.minimize;
import static org.apache.lucene.util.automaton.Operations.*;
@ -19,20 +22,30 @@ import static org.apache.lucene.util.automaton.Operations.*;
*/
public final class Automatons {
static final char WILDCARD_STRING = '*'; // String equality with support for wildcards
static final char WILDCARD_CHAR = '?'; // Char equality with support for wildcards
static final char WILDCARD_ESCAPE = '\\'; // Escape character
private Automatons() {
}
/**
* Builds and returns an automaton that will represent the union of all the given patterns.
*/
public static Automaton patterns(String... patterns) {
if (patterns.length == 0) {
return Automata.makeEmpty();
}
Automaton automaton = new RegExp(patterns[0]).toAutomaton();
Automaton automaton = pattern(patterns[0]);
for (String pattern : patterns) {
automaton = union(automaton, new RegExp(pattern).toAutomaton());
automaton = union(automaton, pattern(pattern));
}
return determinize(minimize(automaton));
}
/**
* Builds and returns an automaton that will represent the union of all the given patterns.
*/
public static Automaton patterns(Collection<String> patterns) {
if (patterns.isEmpty()) {
return Automata.makeEmpty();
@ -40,14 +53,61 @@ public final class Automatons {
Automaton automaton = null;
for (String pattern : patterns) {
if (automaton == null) {
automaton = new RegExp(pattern).toAutomaton();
automaton = pattern(pattern);
} else {
automaton = union(automaton, new RegExp(pattern).toAutomaton());
automaton = union(automaton, pattern(pattern));
}
}
return determinize(minimize(automaton));
}
/**
* Builds and returns an automaton that represents the given pattern.
*/
static Automaton pattern(String pattern) {
if (pattern.startsWith("/")) { // it's a lucene regexp
if (pattern.length() == 1 || !pattern.endsWith("/")) {
throw new IllegalArgumentException("Invalid pattern [" + pattern + "]. Patterns starting with '/' " +
"indicate regular expression pattern and therefore must also end with '/'." +
" Other patterns (those that do not start with '/') will be treated as simple wildcard patterns");
}
String regex = pattern.substring(1, pattern.length() - 1);
return new RegExp(regex).toAutomaton();
}
return wildcard(pattern);
}
/**
* Builds and returns an automaton that represents the given pattern.
*/
static Automaton wildcard(String text) {
List<Automaton> automata = new ArrayList<>();
for (int i = 0; i < text.length();) {
final int c = text.codePointAt(i);
int length = Character.charCount(c);
switch(c) {
case WILDCARD_STRING:
automata.add(Automata.makeAnyString());
break;
case WILDCARD_CHAR:
automata.add(Automata.makeAnyChar());
break;
case WILDCARD_ESCAPE:
// add the next codepoint instead, if it exists
if (i + length < text.length()) {
final int nextChar = text.codePointAt(i + length);
length += Character.charCount(nextChar);
automata.add(Automata.makeChar(nextChar));
break;
} // else fallthru, lenient parsing with a trailing \
default:
automata.add(Automata.makeChar(c));
}
i += length;
}
return Operations.concatenate(automata);
}
public static Automaton unionAndDeterminize(Automaton a1, Automaton a2) {
return determinize(union(a1, a2));
}

View File

@ -27,8 +27,8 @@ public class MultipleIndicesPermissionsTests extends ShieldIntegrationTest {
public static final String ROLES = "user:\n" +
" cluster: all\n" +
" indices:\n" +
" '.*': manage\n" +
" '.*': write\n" +
" '*': manage\n" +
" '/.*/': write\n" +
" 'test': read\n" +
" 'test1': read\n";

View File

@ -5,6 +5,7 @@
*/
package org.elasticsearch.shield.authc.esusers;
import com.carrotsearch.randomizedtesting.annotations.Repeat;
import org.elasticsearch.action.Action;
import org.elasticsearch.action.ActionListener;
import org.elasticsearch.action.ActionRequest;
@ -28,9 +29,9 @@ import org.hamcrest.Matchers;
import org.junit.Before;
import org.junit.Test;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.CoreMatchers.notNullValue;
import static org.hamcrest.Matchers.arrayContaining;
import java.util.Locale;
import static org.hamcrest.Matchers.*;
import static org.mockito.Mockito.*;
/**
@ -70,6 +71,19 @@ public class ESUsersRealmTests extends ElasticsearchTestCase {
assertThat(user.roles(), arrayContaining("role1", "role2"));
}
@Test @Repeat(iterations = 20)
public void testAuthenticate_Caching() throws Exception {
Settings settings = ImmutableSettings.builder()
.put("shield.authc.esusers.cache.hash_algo", Hasher.values()[randomIntBetween(0, Hasher.values().length - 1)].name().toLowerCase(Locale.ROOT))
.build();
MockUserPasswdStore userPasswdStore = new MockUserPasswdStore("user1", "test123");
MockUserRolesStore userRolesStore = new MockUserRolesStore("user1", "role1", "role2");
ESUsersRealm realm = new ESUsersRealm(settings, userPasswdStore, userRolesStore, restController);
User user1 = realm.authenticate(new UsernamePasswordToken("user1", SecuredStringTests.build("test123")));
User user2 = realm.authenticate(new UsernamePasswordToken("user1", SecuredStringTests.build("test123")));
assertThat(user1, sameInstance(user2));
}
@Test
public void testToken() throws Exception {
Settings settings = ImmutableSettings.builder().build();

View File

@ -25,9 +25,9 @@ public class PermissionTests extends ElasticsearchTestCase {
@Before
public void init() {
Permission.Global.Builder builder = Permission.Global.builder(mock(AuthorizationService.class));
builder.add(union(SEARCH, MONITOR), "test_.*", "foo.*");
builder.add(union(READ), "baz_.*foo", "fool.*bar");
builder.add(union(MONITOR), "bar.*");
builder.add(union(SEARCH, MONITOR), "test_*", "/foo.*/");
builder.add(union(READ), "baz_*foo", "/fool.*bar/");
builder.add(union(MONITOR), "/bar.*/");
permission = builder.build();
}

View File

@ -7,6 +7,7 @@ package org.elasticsearch.shield.authz;
import com.carrotsearch.randomizedtesting.annotations.Repeat;
import org.elasticsearch.ElasticsearchIllegalArgumentException;
import org.elasticsearch.common.base.Predicate;
import org.elasticsearch.shield.support.AutomatonPredicate;
import org.elasticsearch.shield.support.Automatons;
import org.elasticsearch.test.ElasticsearchTestCase;
@ -147,4 +148,14 @@ public class PrivilegeTests extends ElasticsearchTestCase {
}
}
@Test
public void testSystem() throws Exception {
Predicate<String> predicate = Privilege.SYSTEM.predicate();
assertThat(predicate.apply("indices:monitor/whatever"), is(true));
assertThat(predicate.apply("cluster:monitor/whatever"), is(true));
assertThat(predicate.apply("internal:whatever"), is(true));
assertThat(predicate.apply("indices:whatever"), is(false));
assertThat(predicate.apply("cluster:whatever"), is(false));
assertThat(predicate.apply("whatever"), is(false));
}
}

View File

@ -0,0 +1,27 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
package org.elasticsearch.shield.authz;
import org.elasticsearch.test.ElasticsearchTestCase;
import org.junit.Test;
import static org.hamcrest.Matchers.*;
/**
*
*/
public class SystemRoleTests extends ElasticsearchTestCase {
@Test
public void testCheck() throws Exception {
assertThat(SystemRole.INSTANCE.check("indices:monitor/whatever"), is(true));
assertThat(SystemRole.INSTANCE.check("cluster:monitor/whatever"), is(true));
assertThat(SystemRole.INSTANCE.check("internal:whatever"), is(true));
assertThat(SystemRole.INSTANCE.check("indices:whatever"), is(false));
assertThat(SystemRole.INSTANCE.check("cluster:whatever"), is(false));
assertThat(SystemRole.INSTANCE.check("whatever"), is(false));
}
}

View File

@ -29,8 +29,8 @@ public class IndicesResolverIntegrationTests extends ShieldIntegrationTest {
return DEFAULT_ROLE + ":\n" +
" cluster: ALL\n" +
" indices:\n" +
" '.*': manage,write\n" +
" 'test.*': read\n";
" '*': manage,write\n" +
" '/test.*/': read\n";
}
@Test

View File

@ -89,7 +89,7 @@ public class FileRolesStoreTests extends ElasticsearchTestCase {
group = permission.indices().groups()[0];
assertThat(group.indices(), notNullValue());
assertThat(group.indices().length, is(1));
assertThat(group.indices()[0], equalTo(".*_.*"));
assertThat(group.indices()[0], equalTo("/.*_.*/"));
assertThat(group.privilege(), notNullValue());
assertThat(group.privilege().isAlias(Privilege.Index.union(Privilege.Index.READ, Privilege.Index.WRITE)), is(true));
}
@ -164,7 +164,7 @@ public class FileRolesStoreTests extends ElasticsearchTestCase {
@Test(expected = ElasticsearchException.class)
public void testThatInvalidYAMLThrowsElasticsearchException() throws Exception {
File file = tempFolder.newFile();
com.google.common.io.Files.write("user: cluster: ALL indices: '.*': ALL".getBytes(Charsets.UTF_8), file);
com.google.common.io.Files.write("user: cluster: ALL indices: '*': ALL".getBytes(Charsets.UTF_8), file);
FileRolesStore.parseFile(file.toPath(), logger, mock(AuthorizationService.class));
}
}

View File

@ -0,0 +1,80 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
package org.elasticsearch.shield.support;
import org.apache.lucene.util.automaton.Automaton;
import org.apache.lucene.util.automaton.CharacterRunAutomaton;
import org.elasticsearch.test.ElasticsearchTestCase;
import org.junit.Test;
import static org.elasticsearch.shield.support.Automatons.*;
import static org.hamcrest.Matchers.*;
/**
*
*/
public class AutomatonsTests extends ElasticsearchTestCase {
@Test
public void testPatterns_UnionOfMultiplePatterns() throws Exception {
assertMatch(patterns("/fo.*/", "ba*"), "foo");
assertMatch(patterns("/fo.*/", "ba*"), "bar");
assertMismatch(patterns("/fo.*/", "ba*"), "zipfoo");
}
@Test
public void testPattern_Single() throws Exception {
assertMatch(pattern("/.*st/"), "test");
assertMatch(pattern("/t.*st/"), "test");
assertMatch(pattern("/tes*./"), "test");
assertMatch(pattern("/test/"), "test");
assertMismatch(pattern("/.*st/"), "tet");
assertMatch(pattern("*st"), "test");
assertMatch(pattern("t*t"), "test");
assertMatch(pattern("t?st"), "test");
assertMismatch(pattern("t?t"), "test");
assertMatch(pattern("tes*"), "test");
assertMatch(pattern("test"), "test");
assertMismatch(pattern("*st"), "tet");
assertInvalidPattern("/test");
assertInvalidPattern("/te*");
assertInvalidPattern("/te.*");
assertMismatch(pattern(".*st"), "test");
assertMatch(pattern("*st\\"), "test\\");
assertMatch(pattern("tes.*/"), "tes.t/");
assertMatch(pattern("\\/test"), "/test");
}
@Test
public void testWildcard() throws Exception {
assertMatch(wildcard("*st"), "test");
assertMatch(wildcard("t*st"), "test");
assertMatch(wildcard("tes*"), "test");
assertMatch(wildcard("test"), "test");
assertMismatch(wildcard("*st"), "tet");
assertMismatch(wildcard("t\\*st"), "test");
assertMatch(wildcard("t\\*st"), "t*st");
}
private void assertMatch(Automaton automaton, String text) {
CharacterRunAutomaton runAutomaton = new CharacterRunAutomaton(automaton);
assertThat(runAutomaton.run(text), is(true));
}
private void assertMismatch(Automaton automaton, String text) {
CharacterRunAutomaton runAutomaton = new CharacterRunAutomaton(automaton);
assertThat(runAutomaton.run(text), is(false));
}
private void assertInvalidPattern(String text) {
try {
pattern(text);
fail("expected an error on invalid pattern [" + text + "]");
} catch (IllegalArgumentException iae) {
// expected
}
}
}

View File

@ -53,7 +53,7 @@ public abstract class ShieldIntegrationTest extends ElasticsearchIntegrationTest
public static final String CONFIG_ROLE_ALLOW_ALL = DEFAULT_ROLE + ":\n" +
" cluster: ALL\n" +
" indices:\n" +
" '.*': ALL\n";
" '*': ALL\n";
@ClassRule
public static TemporaryFolder tmpFolder = new TemporaryFolder();

View File

@ -56,7 +56,7 @@ public class ShieldRestTests extends ElasticsearchRestTests {
public static final String CONFIG_ROLE_ALLOW_ALL = DEFAULT_ROLE + ":\n" +
" cluster: ALL\n" +
" indices:\n" +
" '.*': ALL\n";
" '*': ALL\n";
static {

View File

@ -0,0 +1,82 @@
##############
## Logstash configuration for shield load testing
##
## This configuration makes performance testing against SHIELD a lot easier
## The generator input creates 1000000 very small documents
## The elasticsearch outputs (you should choose only one!) then can be configured to use
## one of the configured setups (shield enabled/disabled, ssl enabled/disabled, HTTP or transport)
## to find out, what kind of overhead the plugin has
##
## Note: Please make sure you are using a logstash instance, that supports shield (as of 10-2014, this resided in its own branch)
##
#############
## Running the tests
## 1. Start an elasticsearch cluster using esvm (this one only starts one node): esvm shield -n 1
## 2. Start logstash against it: ../logstash-output-es-shield/build/tarball/logstash-1.4.2/bin/logstash -p ~/.esvm/1.4.0.Beta1/plugins/ agent -f src/test/resources/logstash-shield.conf
#############
input {
generator {
count => 1000000
}
}
output {
##########
## HTTP
##########
# Use this when shield is disabled
# elasticsearch {
# protocol => 'http'
# }
# Shield enabled, SSL disabled
elasticsearch {
protocol => 'http'
# can be one of admin-plain, admin-bcrypt, admin-sha, admin-apr, admin-sha2
user => 'admin-plain'
password => 'changeme'
}
# Shield enabled, SSL enabled
# elasticsearch {
# protocol => 'http'
# user => 'admin'
# password => 'changeme'
# ssl => 'true'
# ssl_verify => false
# }
##########
## Transport Client
##########
# Use this when shield is disabled
# elasticsearch {
# protocol => 'transport'
# }
# Shield enabled, SSL disabled
# elasticsearch {
# protocol => 'transport'
# user => 'admin'
# password => 'changeme'
# }
# Shield enabled, SSL enabled
# elasticsearch {
# protocol => 'transport'
# user => 'admin'
# password => 'changeme'
# ssl => 'true'
# keystore => 'src/test/resources/org/elasticsearch/shield/transport/ssl/certs/simple/testclient.jks'
# keystore_password => 'testclient'
# truststore => 'src/test/resources/org/elasticsearch/shield/transport/ssl/certs/simple/testclient.jks'
# truststore_password => 'testclient'
# }
}

View File

@ -9,5 +9,5 @@ role2:
role3:
indices:
'.*_.*': READ, WRITE
'/.*_.*/': READ, WRITE

View File

@ -1,4 +1,4 @@
user:
cluster: ALL
indices:
'.*': ALL
'*': ALL