- Formalized the notion of a client vs. node mode. Introduced an `AbstractShieldModule` that takes care of that
- For now, standarized on the `Shield` name across the board (e.g. change `SecurityModule` to `ShieldModule`)
- Introduces static methods to `ShieldPlugin` to resolve shield specific config files (on the way fixed the file resolving of the ldap group mapper)
- The n2n ip filtering is now resolved at the module level. If not enabled, null is injected and the netty handler is then not injected to the pipeline
- updated code base with the latest changes in es-core around how relevant http headers are registered and copied over to the transport request
- Added new known action in es-core  `indices:admin/get`

Original commit: elastic/x-pack-elasticsearch@ca8d85dc81
This commit is contained in:
uboness 2014-09-10 14:23:50 +03:00
parent 787a415c27
commit 1588c761ea
39 changed files with 369 additions and 201 deletions

View File

@ -5,15 +5,20 @@
*/
package org.elasticsearch.shield;
import org.elasticsearch.common.inject.AbstractModule;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.shield.support.AbstractShieldModule;
/**
*
*/
public class SecurityFilterModule extends AbstractModule {
public class SecurityFilterModule extends AbstractShieldModule.Node {
public SecurityFilterModule(Settings settings) {
super(settings);
}
@Override
protected void configure() {
protected void configureNode() {
bind(SecurityFilter.class).asEagerSingleton();
}
}

View File

@ -9,24 +9,24 @@ import org.elasticsearch.ElasticsearchException;
import org.elasticsearch.common.collect.ImmutableMap;
import org.elasticsearch.common.collect.Lists;
import org.elasticsearch.shield.plugin.SecurityPlugin;
import org.elasticsearch.shield.plugin.ShieldPlugin;
import java.util.List;
/**
*
*/
public class SecurityException extends ElasticsearchException.WithRestHeaders {
public class ShieldException extends ElasticsearchException.WithRestHeaders {
public static final ImmutableMap<String, List<String>> HEADERS = ImmutableMap.<String, List<String>>builder()
.put("WWW-Authenticate", Lists.newArrayList("Basic realm=\""+ SecurityPlugin.NAME +"\""))
.put("WWW-Authenticate", Lists.newArrayList("Basic realm=\""+ ShieldPlugin.NAME +"\""))
.build();
public SecurityException(String msg) {
public ShieldException(String msg) {
super(msg, HEADERS);
}
public SecurityException(String msg, Throwable cause) {
public ShieldException(String msg, Throwable cause) {
super(msg, cause, HEADERS);
}
}

View File

@ -7,61 +7,60 @@ package org.elasticsearch.shield;
import org.elasticsearch.action.ActionModule;
import org.elasticsearch.common.collect.ImmutableList;
import org.elasticsearch.common.inject.AbstractModule;
import org.elasticsearch.common.inject.Module;
import org.elasticsearch.common.inject.PreProcessModule;
import org.elasticsearch.common.inject.SpawnModules;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.shield.audit.AuditTrailModule;
import org.elasticsearch.shield.authc.AuthenticationModule;
import org.elasticsearch.shield.authz.AuthorizationModule;
import org.elasticsearch.shield.support.AbstractShieldModule;
import org.elasticsearch.shield.transport.SecuredRestModule;
import org.elasticsearch.shield.transport.SecuredTransportModule;
/**
*
*/
public class SecurityModule extends AbstractModule implements SpawnModules, PreProcessModule {
public class ShieldModule extends AbstractShieldModule.Spawn implements PreProcessModule {
private final Settings settings;
private final boolean isClient;
private final boolean isShieldEnabled;
private final boolean enabled;
public SecurityModule(Settings settings) {
this.settings = settings;
this.isClient = settings.getAsBoolean("node.client", false);
this.isShieldEnabled = settings.getAsBoolean("shield.enabled", true);
public ShieldModule(Settings settings) {
super(settings);
this.enabled = settings.getAsBoolean("shield.enabled", true);
}
@Override
public void processModule(Module module) {
if (module instanceof ActionModule && isShieldEnabled && !isClient) {
if (module instanceof ActionModule && enabled && !clientMode) {
((ActionModule) module).registerFilter(SecurityFilter.Action.class);
}
}
@Override
public Iterable<? extends Module> spawnModules() {
public Iterable<? extends Module> spawnModules(boolean clientMode) {
// don't spawn modules if shield is explicitly disabled
if (!isShieldEnabled) {
if (!enabled) {
return ImmutableList.of();
}
// spawn needed parts in client mode
if (isClient) {
return ImmutableList.of(new SecuredTransportModule(), new SecurityFilterModule());
if (clientMode) {
return ImmutableList.of(
new SecuredTransportModule(settings),
new SecurityFilterModule(settings));
}
return ImmutableList.of(
new AuthenticationModule(settings),
new AuthorizationModule(),
new AuthorizationModule(settings),
new AuditTrailModule(settings),
new SecuredTransportModule(),
new SecuredRestModule(),
new SecurityFilterModule());
new SecuredTransportModule(settings),
new SecuredRestModule(settings),
new SecurityFilterModule(settings));
}
@Override
protected void configure() {
protected void configure(boolean clientMode) {
}
}

View File

@ -8,13 +8,13 @@ package org.elasticsearch.shield;
/**
*
*/
public class SecuritySettingsException extends SecurityException {
public class ShieldSettingsException extends ShieldException {
public SecuritySettingsException(String msg) {
public ShieldSettingsException(String msg) {
super(msg);
}
public SecuritySettingsException(String msg, Throwable cause) {
public ShieldSettingsException(String msg, Throwable cause) {
super(msg, cause);
}

View File

@ -5,10 +5,12 @@
*/
package org.elasticsearch.shield.audit;
import org.elasticsearch.shield.ShieldException;
/**
*
*/
public class AuditException extends org.elasticsearch.shield.SecurityException {
public class AuditException extends ShieldException {
public AuditException(String msg) {
super(msg);

View File

@ -7,27 +7,28 @@ package org.elasticsearch.shield.audit;
import org.elasticsearch.ElasticsearchException;
import org.elasticsearch.common.collect.Sets;
import org.elasticsearch.common.inject.AbstractModule;
import org.elasticsearch.common.inject.multibindings.Multibinder;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.shield.audit.logfile.LoggingAuditTrail;
import org.elasticsearch.shield.support.AbstractShieldModule;
import java.util.Set;
/**
*
*/
public class AuditTrailModule extends AbstractModule {
public class AuditTrailModule extends AbstractShieldModule.Node {
private final Settings settings;
private final boolean enabled;
public AuditTrailModule(Settings settings) {
this.settings = settings;
super(settings);
enabled = settings.getAsBoolean("shield.audit.enabled", false);
}
@Override
protected void configure() {
if (!settings.getAsBoolean("shield.audit.enabled", false)) {
protected void configureNode() {
if (!enabled) {
bind(AuditTrail.class).toInstance(AuditTrail.NOOP);
return;
}

View File

@ -6,11 +6,12 @@
package org.elasticsearch.shield.authc;
import org.elasticsearch.rest.RestStatus;
import org.elasticsearch.shield.ShieldException;
/**
*
*/
public class AuthenticationException extends org.elasticsearch.shield.SecurityException {
public class AuthenticationException extends ShieldException {
public AuthenticationException(String msg) {
super(msg);

View File

@ -6,55 +6,31 @@
package org.elasticsearch.shield.authc;
import org.elasticsearch.common.collect.ImmutableList;
import org.elasticsearch.common.inject.AbstractModule;
import org.elasticsearch.common.inject.Module;
import org.elasticsearch.common.inject.SpawnModules;
import org.elasticsearch.common.inject.util.Providers;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.shield.authc.esusers.ESUsersModule;
import org.elasticsearch.shield.authc.esusers.ESUsersRealm;
import org.elasticsearch.shield.authc.ldap.LdapModule;
import org.elasticsearch.shield.authc.ldap.LdapRealm;
import org.elasticsearch.shield.authc.system.SystemRealm;
import static org.elasticsearch.common.inject.name.Names.named;
import org.elasticsearch.shield.support.AbstractShieldModule;
/**
*
*/
public class AuthenticationModule extends AbstractModule implements SpawnModules {
private final Settings settings;
private final boolean esusersEnabled;
private final boolean ldapEnabled;
public class AuthenticationModule extends AbstractShieldModule.Node.Spawn {
public AuthenticationModule(Settings settings) {
this.settings = settings;
this.esusersEnabled = ESUsersModule.enabled(settings);
this.ldapEnabled = LdapModule.enabled(settings);
super(settings);
}
@Override
public Iterable<? extends Module> spawnModules() {
ImmutableList.Builder<Module> modules = ImmutableList.builder();
modules.add(new SystemRealm.Module());
if (esusersEnabled) {
modules.add(new ESUsersModule());
}
if (ldapEnabled) {
modules.add(new LdapModule(settings));
}
return modules.build();
public Iterable<? extends Node> spawnModules() {
return ImmutableList.of(
new SystemRealm.Module(settings),
new ESUsersModule(settings),
new LdapModule(settings));
}
@Override
protected void configure() {
protected void configureNode() {
bind(AuthenticationService.class).to(InternalAuthenticationService.class).asEagerSingleton();
if (!esusersEnabled) {
bind(ESUsersRealm.class).toProvider(Providers.of((ESUsersRealm) null));
}
if (!ldapEnabled) {
bind(LdapRealm.class).toProvider(Providers.of((LdapRealm) null));
}
}
}

View File

@ -5,27 +5,39 @@
*/
package org.elasticsearch.shield.authc.esusers;
import org.elasticsearch.common.inject.AbstractModule;
import org.elasticsearch.common.inject.util.Providers;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.shield.authc.Realm;
import org.elasticsearch.shield.authc.support.UserPasswdStore;
import org.elasticsearch.shield.authc.support.UserRolesStore;
import org.elasticsearch.shield.support.AbstractShieldModule;
import static org.elasticsearch.common.inject.name.Names.named;
/**
*
*/
public class ESUsersModule extends AbstractModule {
public class ESUsersModule extends AbstractShieldModule.Node {
public static boolean enabled(Settings settings) {
return settings.getComponentSettings(ESUsersModule.class).getAsBoolean("enabled", true);
private final boolean enabled;
public ESUsersModule(Settings settings) {
super(settings);
enabled = enabled(settings);
}
@Override
protected void configure() {
bind(Realm.class).annotatedWith(named(ESUsersRealm.TYPE)).to(ESUsersRealm.class).asEagerSingleton();
bind(UserPasswdStore.class).annotatedWith(named("file")).to(FileUserPasswdStore.class).asEagerSingleton();
bind(UserRolesStore.class).annotatedWith(named("file")).to(FileUserRolesStore.class).asEagerSingleton();
protected void configureNode() {
if (enabled) {
bind(Realm.class).annotatedWith(named(ESUsersRealm.TYPE)).to(ESUsersRealm.class).asEagerSingleton();
bind(UserPasswdStore.class).annotatedWith(named("file")).to(FileUserPasswdStore.class).asEagerSingleton();
bind(UserRolesStore.class).annotatedWith(named("file")).to(FileUserRolesStore.class).asEagerSingleton();
} else {
bind(ESUsersRealm.class).toProvider(Providers.<ESUsersRealm>of(null));
}
}
static boolean enabled(Settings settings) {
return settings.getComponentSettings(ESUsersModule.class).getAsBoolean("enabled", true);
}
}

View File

@ -10,7 +10,7 @@ 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;
import org.elasticsearch.rest.BaseRestHandler;
import org.elasticsearch.rest.RestController;
import org.elasticsearch.rest.RestRequest;
import org.elasticsearch.shield.User;
import org.elasticsearch.shield.authc.AuthenticationToken;
@ -25,20 +25,18 @@ import org.elasticsearch.transport.TransportMessage;
*/
public class ESUsersRealm extends AbstractComponent implements Realm<UsernamePasswordToken> {
static {
BaseRestHandler.addUsefulHeaders(UsernamePasswordToken.BASIC_AUTH_HEADER);
}
public static final String TYPE = "esusers";
final UserPasswdStore userPasswdStore;
final UserRolesStore userRolesStore;
@Inject
public ESUsersRealm(Settings settings, @Named("file") UserPasswdStore userPasswdStore, @Named("file") UserRolesStore userRolesStore) {
public ESUsersRealm(Settings settings, @Named("file") UserPasswdStore userPasswdStore,
@Named("file") UserRolesStore userRolesStore, RestController restController) {
super(settings);
this.userPasswdStore = userPasswdStore;
this.userRolesStore = userRolesStore;
restController.registerRelevantHeaders(UsernamePasswordToken.BASIC_AUTH_HEADER);
}
@Override

View File

@ -16,7 +16,7 @@ import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.env.Environment;
import org.elasticsearch.shield.authc.support.Hasher;
import org.elasticsearch.shield.authc.support.UserPasswdStore;
import org.elasticsearch.shield.plugin.SecurityPlugin;
import org.elasticsearch.shield.plugin.ShieldPlugin;
import org.elasticsearch.watcher.FileChangesListener;
import org.elasticsearch.watcher.FileWatcher;
import org.elasticsearch.watcher.ResourceWatcherService;
@ -75,8 +75,7 @@ public class FileUserPasswdStore extends AbstractComponent implements UserPasswd
public static Path resolveFile(Settings settings, Environment env) {
String location = settings.get("shield.authc.esusers.files.users");
if (location == null) {
File shieldDirectory = new File(env.configFile(), SecurityPlugin.NAME);
return shieldDirectory.toPath().resolve(".users");
return ShieldPlugin.resolveConfigFile(env, ".users");
}
return Paths.get(location);
}

View File

@ -16,7 +16,7 @@ import org.elasticsearch.common.logging.ESLogger;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.env.Environment;
import org.elasticsearch.shield.authc.support.UserRolesStore;
import org.elasticsearch.shield.plugin.SecurityPlugin;
import org.elasticsearch.shield.plugin.ShieldPlugin;
import org.elasticsearch.watcher.FileChangesListener;
import org.elasticsearch.watcher.FileWatcher;
import org.elasticsearch.watcher.ResourceWatcherService;
@ -68,8 +68,7 @@ public class FileUserRolesStore extends AbstractComponent implements UserRolesSt
public static Path resolveFile(Settings settings, Environment env) {
String location = settings.get("shield.authc.esusers.files.users_roles");
if (location == null) {
File shieldDirectory = new File(env.configFile(), SecurityPlugin.NAME);
return shieldDirectory.toPath().resolve(".users_roles");
return ShieldPlugin.resolveConfigFile(env, ".users_roles");
}
return Paths.get(location);
}

View File

@ -10,6 +10,7 @@ import org.elasticsearch.common.collect.ImmutableMap;
import org.elasticsearch.common.component.AbstractComponent;
import org.elasticsearch.common.inject.Inject;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.shield.ShieldException;
import javax.naming.Context;
import javax.naming.NamingEnumeration;
@ -42,7 +43,7 @@ public class ActiveDirectoryConnectionFactory extends AbstractComponent implemen
super(settings);
domainName = componentSettings.get(AD_DOMAIN_NAME_SETTING);
if (domainName == null) {
throw new org.elasticsearch.shield.SecurityException("Missing [" + AD_DOMAIN_NAME_SETTING + "] setting for active directory");
throw new ShieldException("Missing [" + AD_DOMAIN_NAME_SETTING + "] setting for active directory");
}
userSearchDN = componentSettings.get(AD_USER_SEARCH_BASEDN_SETTING, buildDnFromDomain(domainName));
int port = componentSettings.getAsInt(AD_PORT, 389);

View File

@ -13,6 +13,7 @@ import org.elasticsearch.common.logging.ESLogger;
import org.elasticsearch.common.settings.ImmutableSettings;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.env.Environment;
import org.elasticsearch.shield.plugin.ShieldPlugin;
import org.elasticsearch.watcher.FileChangesListener;
import org.elasticsearch.watcher.FileWatcher;
import org.elasticsearch.watcher.ResourceWatcherService;
@ -32,7 +33,7 @@ import java.util.*;
*/
public class LdapGroupToRoleMapper extends AbstractComponent {
public static final String ROLE_MAPPING_DEFAULT_FILE_NAME = ".role_mapping";
public static final String DEFAULT_FILE_NAME = ".role_mapping";
public static final String ROLE_MAPPING_FILE_SETTING = "files.role_mapping";
public static final String USE_UNMAPPED_GROUPS_AS_ROLES_SETTING = "unmapped_groups_as_roles";
@ -57,6 +58,14 @@ public class LdapGroupToRoleMapper extends AbstractComponent {
this.listener = listener;
}
public static Path resolveFile(Settings settings, Environment env) {
String location = settings.get(ROLE_MAPPING_FILE_SETTING);
if (location == null) {
return ShieldPlugin.resolveConfigFile(env, DEFAULT_FILE_NAME);
}
return Paths.get(location);
}
public static ImmutableMap<LdapName, Set<String>> parseFile(Path path, ESLogger logger) {
if (!Files.exists(path)) {
return ImmutableMap.of();
@ -92,14 +101,6 @@ public class LdapGroupToRoleMapper extends AbstractComponent {
}
}
public static Path resolveFile(Settings settings, Environment env) {
String location = settings.get(ROLE_MAPPING_FILE_SETTING);
if (location == null) {
return env.configFile().toPath().resolve(ROLE_MAPPING_DEFAULT_FILE_NAME);
}
return Paths.get(location);
}
/**
* This will map the groupDN's to ES Roles
*/

View File

@ -5,24 +5,42 @@
*/
package org.elasticsearch.shield.authc.ldap;
import org.elasticsearch.common.inject.AbstractModule;
import org.elasticsearch.common.inject.util.Providers;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.shield.authc.AuthenticationModule;
import org.elasticsearch.shield.authc.Realm;
import org.elasticsearch.shield.support.AbstractShieldModule;
import static org.elasticsearch.common.inject.name.Names.named;
/**
* Configures Ldap object injections
*/
public class LdapModule extends AbstractModule {
private final Settings settings;
public class LdapModule extends AbstractShieldModule.Node {
private final boolean enabled;
public LdapModule(Settings settings) {
this.settings = settings;
super(settings);
enabled = enabled(settings);
}
public static boolean enabled(Settings settings) {
@Override
protected void configureNode() {
if (enabled) {
bind(Realm.class).annotatedWith(named(LdapRealm.TYPE)).to(LdapRealm.class).asEagerSingleton();
bind(LdapGroupToRoleMapper.class).asEagerSingleton();
String mode = settings.getComponentSettings(LdapModule.class).get("mode", "ldap");
if ("ldap".equals(mode)) {
bind(LdapConnectionFactory.class).to(StandardLdapConnectionFactory.class);
} else {
bind(LdapConnectionFactory.class).to(ActiveDirectoryConnectionFactory.class);
}
} else {
bind(LdapRealm.class).toProvider(Providers.of((LdapRealm) null));
}
}
static boolean enabled(Settings settings) {
Settings authcSettings = settings.getAsSettings("shield.authc");
if (!authcSettings.names().contains("ldap")) {
return false;
@ -30,16 +48,4 @@ public class LdapModule extends AbstractModule {
Settings ldapSettings = authcSettings.getAsSettings("ldap");
return ldapSettings.getAsBoolean("enabled", true);
}
@Override
protected void configure() {
bind(Realm.class).annotatedWith(named(LdapRealm.TYPE)).to(LdapRealm.class).asEagerSingleton();
bind(LdapGroupToRoleMapper.class).asEagerSingleton();
String mode = settings.getComponentSettings(LdapModule.class).get("mode", "ldap");
if ("ldap".equals(mode)) {
bind(LdapConnectionFactory.class).to(StandardLdapConnectionFactory.class);
} else {
bind(LdapConnectionFactory.class).to(ActiveDirectoryConnectionFactory.class);
}
}
}

View File

@ -7,10 +7,10 @@ package org.elasticsearch.shield.authc.ldap;
import org.elasticsearch.common.inject.Inject;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.rest.BaseRestHandler;
import org.elasticsearch.rest.RestController;
import org.elasticsearch.shield.ShieldException;
import org.elasticsearch.shield.User;
import org.elasticsearch.shield.authc.AuthenticationToken;
import org.elasticsearch.shield.SecurityException;
import org.elasticsearch.shield.authc.Realm;
import org.elasticsearch.shield.authc.support.CachingUsernamePasswordRealm;
import org.elasticsearch.shield.authc.support.UsernamePasswordToken;
@ -25,21 +25,17 @@ import java.util.Set;
*/
public class LdapRealm extends CachingUsernamePasswordRealm implements Realm<UsernamePasswordToken> {
static {
BaseRestHandler.addUsefulHeaders(UsernamePasswordToken.BASIC_AUTH_HEADER);
}
public static final String TYPE = "ldap";
private final LdapConnectionFactory connectionFactory;
private final LdapGroupToRoleMapper roleMapper;
@Inject
public LdapRealm(Settings settings, LdapConnectionFactory ldap, LdapGroupToRoleMapper roleMapper) {
public LdapRealm(Settings settings, LdapConnectionFactory ldap, LdapGroupToRoleMapper roleMapper, RestController restController) {
super(settings);
this.connectionFactory = ldap;
this.roleMapper = roleMapper;
restController.registerRelevantHeaders(UsernamePasswordToken.BASIC_AUTH_HEADER);
}
@Override
@ -68,7 +64,7 @@ public class LdapRealm extends CachingUsernamePasswordRealm implements Realm<Use
User.Simple user = new User.Simple(token.principal(), roles.toArray(new String[roles.size()]));
Arrays.fill(token.credentials(), '\0');
return user;
} catch (SecurityException e){
} catch (ShieldException e){
logger.info("Authentication Failed for user [{}]", e, token.principal());
return null;
}

View File

@ -10,6 +10,7 @@ import org.elasticsearch.common.collect.ImmutableMap;
import org.elasticsearch.common.component.AbstractComponent;
import org.elasticsearch.common.inject.Inject;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.shield.ShieldException;
import javax.naming.Context;
import javax.naming.NamingException;
@ -43,11 +44,11 @@ public class StandardLdapConnectionFactory extends AbstractComponent implements
super(settings);
userDnTemplates = componentSettings.getAsArray(USER_DN_TEMPLATES_SETTING);
if (userDnTemplates == null) {
throw new org.elasticsearch.shield.SecurityException("Missing required ldap setting [" + USER_DN_TEMPLATES_SETTING + "]");
throw new ShieldException("Missing required ldap setting [" + USER_DN_TEMPLATES_SETTING + "]");
}
String[] ldapUrls = componentSettings.getAsArray(URLS_SETTING);
if (ldapUrls == null) {
throw new org.elasticsearch.shield.SecurityException("Missing required ldap setting [" + URLS_SETTING + "]");
throw new ShieldException("Missing required ldap setting [" + URLS_SETTING + "]");
}
sharedLdapEnv = ImmutableMap.<String, Serializable>builder()
.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory")

View File

@ -5,11 +5,12 @@
*/
package org.elasticsearch.shield.authc.system;
import org.elasticsearch.common.inject.AbstractModule;
import org.elasticsearch.common.settings.Settings;
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.support.AbstractShieldModule;
import org.elasticsearch.transport.TransportMessage;
/**
@ -58,9 +59,14 @@ public class SystemRealm implements Realm<AuthenticationToken> {
return token == TOKEN ? User.SYSTEM : null;
}
public static class Module extends AbstractModule {
public static class Module extends AbstractShieldModule.Node {
public Module(Settings settings) {
super(settings);
}
@Override
protected void configure() {
protected void configureNode() {
bind(SystemRealm.class).asEagerSingleton();
}
}

View File

@ -6,11 +6,12 @@
package org.elasticsearch.shield.authz;
import org.elasticsearch.rest.RestStatus;
import org.elasticsearch.shield.ShieldException;
/**
*
*/
public class AuthorizationException extends org.elasticsearch.shield.SecurityException {
public class AuthorizationException extends ShieldException {
public AuthorizationException(String msg) {
super(msg);

View File

@ -5,17 +5,22 @@
*/
package org.elasticsearch.shield.authz;
import org.elasticsearch.common.inject.AbstractModule;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.shield.authz.store.FileRolesStore;
import org.elasticsearch.shield.authz.store.RolesStore;
import org.elasticsearch.shield.support.AbstractShieldModule;
/**
*
*/
public class AuthorizationModule extends AbstractModule {
public class AuthorizationModule extends AbstractShieldModule.Node {
public AuthorizationModule(Settings settings) {
super(settings);
}
@Override
protected void configure() {
protected void configureNode() {
bind(RolesStore.class).to(FileRolesStore.class);
bind(AuthorizationService.class).to(InternalAuthorizationService.class).asEagerSingleton();
}

View File

@ -21,7 +21,7 @@ import org.elasticsearch.common.xcontent.yaml.YamlXContent;
import org.elasticsearch.env.Environment;
import org.elasticsearch.shield.authz.Permission;
import org.elasticsearch.shield.authz.Privilege;
import org.elasticsearch.shield.plugin.SecurityPlugin;
import org.elasticsearch.shield.plugin.ShieldPlugin;
import org.elasticsearch.watcher.FileChangesListener;
import org.elasticsearch.watcher.FileWatcher;
import org.elasticsearch.watcher.ResourceWatcherService;
@ -74,8 +74,7 @@ public class FileRolesStore extends AbstractComponent implements RolesStore {
public static Path resolveFile(Settings settings, Environment env) {
String location = settings.get("files.roles");
if (location == null) {
File shieldDirectory = new File(env.configFile(), SecurityPlugin.NAME);
return shieldDirectory.toPath().resolve(".roles.yml");
return ShieldPlugin.resolveConfigFile(env, ".roles.yml");
}
return Paths.get(location);

View File

@ -7,15 +7,18 @@ package org.elasticsearch.shield.plugin;
import org.elasticsearch.common.collect.ImmutableList;
import org.elasticsearch.common.inject.Module;
import org.elasticsearch.env.Environment;
import org.elasticsearch.plugins.AbstractPlugin;
import org.elasticsearch.shield.SecurityModule;
import org.elasticsearch.shield.ShieldModule;
import java.io.File;
import java.nio.file.Path;
import java.util.Collection;
/**
*
*/
public class SecurityPlugin extends AbstractPlugin {
public class ShieldPlugin extends AbstractPlugin {
public static final String NAME = "shield";
@ -31,7 +34,15 @@ public class SecurityPlugin extends AbstractPlugin {
@Override
public Collection<Class<? extends Module>> modules() {
return ImmutableList.<Class<? extends Module>>of(SecurityModule.class);
return ImmutableList.<Class<? extends Module>>of(ShieldModule.class);
}
public static Path configDir(Environment env) {
return new File(env.configFile(), NAME).toPath();
}
public static Path resolveConfigFile(Environment env, String name) {
return configDir(env).resolve(name);
}
}

View File

@ -0,0 +1,72 @@
/*
* 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.elasticsearch.client.Client;
import org.elasticsearch.common.inject.AbstractModule;
import org.elasticsearch.common.inject.Module;
import org.elasticsearch.common.inject.SpawnModules;
import org.elasticsearch.common.settings.Settings;
/**
*
*/
public abstract class AbstractShieldModule extends AbstractModule {
protected final Settings settings;
protected final boolean clientMode;
public AbstractShieldModule(Settings settings) {
this.settings = settings;
this.clientMode = !"node".equals(settings.get(Client.CLIENT_TYPE_SETTING));
}
@Override
protected final void configure() {
configure(clientMode);
}
protected abstract void configure(boolean clientMode);
public static abstract class Spawn extends AbstractShieldModule implements SpawnModules {
protected Spawn(Settings settings) {
super(settings);
}
@Override
public final Iterable<? extends Module> spawnModules() {
return spawnModules(clientMode);
}
public abstract Iterable<? extends Module> spawnModules(boolean clientMode);
}
public static abstract class Node extends AbstractShieldModule {
protected Node(Settings settings) {
super(settings);
}
@Override
protected final void configure(boolean clientMode) {
assert !clientMode : "[" + getClass().getSimpleName() + "] is a node only module";
configureNode();
}
protected abstract void configureNode();
public static abstract class Spawn extends Node implements SpawnModules {
protected Spawn(Settings settings) {
super(settings);
}
public abstract Iterable<? extends AbstractShieldModule.Node> spawnModules();
}
}
}

View File

@ -5,16 +5,21 @@
*/
package org.elasticsearch.shield.transport;
import org.elasticsearch.common.inject.AbstractModule;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.shield.SecurityFilter;
import org.elasticsearch.shield.support.AbstractShieldModule;
/**
*
*/
public class SecuredRestModule extends AbstractModule {
public class SecuredRestModule extends AbstractShieldModule.Node {
public SecuredRestModule(Settings settings) {
super(settings);
}
@Override
protected void configure() {
protected void configureNode() {
bind(SecurityFilter.Rest.class).asEagerSingleton();
}
}

View File

@ -6,12 +6,13 @@
package org.elasticsearch.shield.transport;
import org.elasticsearch.common.collect.ImmutableList;
import org.elasticsearch.common.inject.AbstractModule;
import org.elasticsearch.common.inject.Module;
import org.elasticsearch.common.inject.PreProcessModule;
import org.elasticsearch.common.inject.SpawnModules;
import org.elasticsearch.common.inject.util.Providers;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.shield.SecurityFilter;
import org.elasticsearch.shield.plugin.SecurityPlugin;
import org.elasticsearch.shield.plugin.ShieldPlugin;
import org.elasticsearch.shield.support.AbstractShieldModule;
import org.elasticsearch.shield.transport.n2n.IPFilteringN2NAuthenticator;
import org.elasticsearch.shield.transport.netty.N2NNettyUpstreamHandler;
import org.elasticsearch.shield.transport.netty.NettySecuredHttpServerTransportModule;
@ -21,28 +22,46 @@ import org.elasticsearch.transport.TransportModule;
/**
*
*/
public class SecuredTransportModule extends AbstractModule implements SpawnModules, PreProcessModule {
public class SecuredTransportModule extends AbstractShieldModule.Spawn implements PreProcessModule {
public SecuredTransportModule(Settings settings) {
super(settings);
}
@Override
public Iterable<? extends Module> spawnModules() {
public Iterable<? extends Module> spawnModules(boolean clientMode) {
if (clientMode) {
return ImmutableList.of(new NettySecuredTransportModule(settings));
}
//todo we only need to spawn http module if we're not within the transport client context
return ImmutableList.of(
new NettySecuredHttpServerTransportModule(),
new NettySecuredTransportModule());
new NettySecuredHttpServerTransportModule(settings),
new NettySecuredTransportModule(settings));
}
@Override
public void processModule(Module module) {
if (module instanceof TransportModule) {
((TransportModule) module).setTransportService(SecuredTransportService.class, SecurityPlugin.NAME);
((TransportModule) module).setTransportService(SecuredTransportService.class, ShieldPlugin.NAME);
}
}
@Override
protected void configure() {
protected void configure(boolean clientMode) {
if (clientMode) {
// no ip filtering on the client
bind(N2NNettyUpstreamHandler.class).toProvider(Providers.<N2NNettyUpstreamHandler>of(null));
return;
}
bind(TransportFilter.class).to(SecurityFilter.Transport.class).asEagerSingleton();
bind(IPFilteringN2NAuthenticator.class).asEagerSingleton();
bind(N2NNettyUpstreamHandler.class).asEagerSingleton();
if (settings.getAsBoolean("shield.transport.n2n.ip_filter.enabled", true)) {
bind(IPFilteringN2NAuthenticator.class).asEagerSingleton();
bind(N2NNettyUpstreamHandler.class).asEagerSingleton();
} else {
bind(N2NNettyUpstreamHandler.class).toProvider(Providers.<N2NNettyUpstreamHandler>of(null));
}
}
}

View File

@ -20,7 +20,7 @@ import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.common.xcontent.yaml.YamlXContent;
import org.elasticsearch.env.Environment;
import org.elasticsearch.shield.plugin.SecurityPlugin;
import org.elasticsearch.shield.plugin.ShieldPlugin;
import org.elasticsearch.watcher.FileChangesListener;
import org.elasticsearch.watcher.FileWatcher;
import org.elasticsearch.watcher.ResourceWatcherService;
@ -60,8 +60,7 @@ public class IPFilteringN2NAuthenticator extends AbstractComponent implements N2
private Path resolveFile(Settings settings, Environment env) {
String location = settings.get("ip_filter.file");
if (location == null) {
File shieldDirectory = new File(env.configFile(), SecurityPlugin.NAME);
return shieldDirectory.toPath().resolve(DEFAULT_FILE);
return ShieldPlugin.resolveConfigFile(env, DEFAULT_FILE);
}
return Paths.get(location);
}

View File

@ -6,6 +6,7 @@
package org.elasticsearch.shield.transport.netty;
import org.elasticsearch.common.inject.Inject;
import org.elasticsearch.common.inject.internal.Nullable;
import org.elasticsearch.common.netty.channel.ChannelPipeline;
import org.elasticsearch.common.netty.channel.ChannelPipelineFactory;
import org.elasticsearch.common.netty.handler.ssl.SslHandler;
@ -27,7 +28,7 @@ public class NettySecuredHttpServerTransport extends NettyHttpServerTransport {
@Inject
public NettySecuredHttpServerTransport(Settings settings, NetworkService networkService, BigArrays bigArrays,
N2NNettyUpstreamHandler shieldUpstreamHandler) {
@Nullable N2NNettyUpstreamHandler shieldUpstreamHandler) {
super(settings, networkService, bigArrays);
this.ssl = settings.getAsBoolean("shield.http.ssl", false);
this.shieldUpstreamHandler = shieldUpstreamHandler;
@ -56,7 +57,7 @@ public class NettySecuredHttpServerTransport extends NettyHttpServerTransport {
@Override
public ChannelPipeline getPipeline() throws Exception {
ChannelPipeline pipeline = super.getPipeline();
if (settings.getAsBoolean("shield.transport.n2n.ip_filter.enabled", true)) {
if (shieldUpstreamHandler != null) {
pipeline.addFirst("ipfilter", shieldUpstreamHandler);
}
if (ssl) {

View File

@ -5,24 +5,30 @@
*/
package org.elasticsearch.shield.transport.netty;
import org.elasticsearch.common.inject.AbstractModule;
import org.elasticsearch.common.inject.Module;
import org.elasticsearch.common.inject.PreProcessModule;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.http.HttpServerModule;
import org.elasticsearch.shield.plugin.SecurityPlugin;
import org.elasticsearch.shield.plugin.ShieldPlugin;
import org.elasticsearch.shield.support.AbstractShieldModule;
/**
*
*/
public class NettySecuredHttpServerTransportModule extends AbstractModule implements PreProcessModule {
public class NettySecuredHttpServerTransportModule extends AbstractShieldModule implements PreProcessModule {
public NettySecuredHttpServerTransportModule(Settings settings) {
super(settings);
}
@Override
public void processModule(Module module) {
if (module instanceof HttpServerModule) {
((HttpServerModule) module).setHttpServerTransport(NettySecuredHttpServerTransport.class, SecurityPlugin.NAME);
((HttpServerModule) module).setHttpServerTransport(NettySecuredHttpServerTransport.class, ShieldPlugin.NAME);
}
}
@Override
protected void configure() {}
protected void configure(boolean clientMode) {
}
}

View File

@ -7,6 +7,7 @@ package org.elasticsearch.shield.transport.netty;
import org.elasticsearch.Version;
import org.elasticsearch.common.inject.Inject;
import org.elasticsearch.common.inject.internal.Nullable;
import org.elasticsearch.common.netty.channel.ChannelPipeline;
import org.elasticsearch.common.netty.channel.ChannelPipelineFactory;
import org.elasticsearch.common.netty.handler.ssl.SslHandler;
@ -29,7 +30,7 @@ public class NettySecuredTransport extends NettyTransport {
@Inject
public NettySecuredTransport(Settings settings, ThreadPool threadPool, NetworkService networkService, BigArrays bigArrays, Version version,
N2NNettyUpstreamHandler shieldUpstreamHandler) {
@Nullable N2NNettyUpstreamHandler shieldUpstreamHandler) {
super(settings, threadPool, networkService, bigArrays, version);
this.shieldUpstreamHandler = shieldUpstreamHandler;
this.ssl = settings.getAsBoolean("shield.transport.ssl", false);
@ -63,7 +64,7 @@ public class NettySecuredTransport extends NettyTransport {
@Override
public ChannelPipeline getPipeline() throws Exception {
ChannelPipeline pipeline = super.getPipeline();
if (settings.getAsBoolean("shield.transport.n2n.ip_filter.enabled", true)) {
if (shieldUpstreamHandler != null) {
pipeline.addFirst("ipfilter", shieldUpstreamHandler);
}
if (ssl) {

View File

@ -5,25 +5,30 @@
*/
package org.elasticsearch.shield.transport.netty;
import org.elasticsearch.common.inject.AbstractModule;
import org.elasticsearch.common.inject.Module;
import org.elasticsearch.common.inject.PreProcessModule;
import org.elasticsearch.shield.plugin.SecurityPlugin;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.shield.plugin.ShieldPlugin;
import org.elasticsearch.shield.support.AbstractShieldModule;
import org.elasticsearch.transport.TransportModule;
/**
*
*/
public class NettySecuredTransportModule extends AbstractModule implements PreProcessModule {
public class NettySecuredTransportModule extends AbstractShieldModule implements PreProcessModule {
public NettySecuredTransportModule(Settings settings) {
super(settings);
}
@Override
public void processModule(Module module) {
if (module instanceof TransportModule) {
((TransportModule) module).setTransport(NettySecuredTransport.class, SecurityPlugin.NAME);
((TransportModule) module).setTransport(NettySecuredTransport.class, ShieldPlugin.NAME);
}
}
@Override
protected void configure() {}
protected void configure(boolean clientMode) {}
}

View File

@ -1,2 +1,2 @@
plugin=org.elasticsearch.shield.plugin.SecurityPlugin
plugin=org.elasticsearch.shield.plugin.ShieldPlugin
version=${project.version}

View File

@ -24,6 +24,7 @@ public class AuditTrailModuleTests extends ElasticsearchTestCase {
@Test
public void testEnabled() throws Exception {
Settings settings = ImmutableSettings.builder()
.put("client.type", "node")
.put("shield.audit.enabled", false)
.build();
Injector injector = Guice.createInjector(new SettingsModule(settings), new AuditTrailModule(settings));
@ -33,7 +34,8 @@ public class AuditTrailModuleTests extends ElasticsearchTestCase {
@Test
public void testDisabledByDefault() throws Exception {
Settings settings = ImmutableSettings.EMPTY;
Settings settings = ImmutableSettings.builder()
.put("client.type", "node").build();
Injector injector = Guice.createInjector(new SettingsModule(settings), new AuditTrailModule(settings));
AuditTrail auditTrail = injector.getInstance(AuditTrail.class);
assertThat(auditTrail, is(AuditTrail.NOOP));
@ -43,6 +45,7 @@ public class AuditTrailModuleTests extends ElasticsearchTestCase {
public void testLogfile() throws Exception {
Settings settings = ImmutableSettings.builder()
.put("shield.audit.enabled", true)
.put("client.type", "node")
.build();
Injector injector = Guice.createInjector(new SettingsModule(settings), new AuditTrailModule(settings));
AuditTrail auditTrail = injector.getInstance(AuditTrail.class);
@ -58,6 +61,7 @@ public class AuditTrailModuleTests extends ElasticsearchTestCase {
Settings settings = ImmutableSettings.builder()
.put("shield.audit.enabled", true)
.put("shield.audit.outputs" , "foo")
.put("client.type", "node")
.build();
try {
Guice.createInjector(new SettingsModule(settings), new AuditTrailModule(settings));

View File

@ -11,6 +11,7 @@ import org.elasticsearch.common.inject.Injector;
import org.elasticsearch.common.settings.ImmutableSettings;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.env.Environment;
import org.elasticsearch.rest.RestController;
import org.elasticsearch.test.ElasticsearchTestCase;
import org.elasticsearch.threadpool.ThreadPool;
import org.elasticsearch.watcher.ResourceWatcherService;
@ -21,6 +22,7 @@ import java.nio.file.Path;
import java.nio.file.Paths;
import static org.hamcrest.Matchers.*;
import static org.mockito.Mockito.mock;
/**
*
@ -38,7 +40,8 @@ public class ESUsersModuleTests extends ElasticsearchTestCase {
@Test
public void test() throws Exception {
Injector injector = Guice.createInjector(new TestModule(users, usersRoles), new ESUsersModule());
Settings settings = ImmutableSettings.builder().put("client.type", "node").build();
Injector injector = Guice.createInjector(new TestModule(users, usersRoles), new ESUsersModule(settings));
ESUsersRealm realm = injector.getInstance(ESUsersRealm.class);
assertThat(realm, notNullValue());
assertThat(realm.userPasswdStore, notNullValue());
@ -81,6 +84,7 @@ public class ESUsersModuleTests extends ElasticsearchTestCase {
bind(Environment.class).toInstance(env);
bind(ThreadPool.class).toInstance(new ThreadPool("test"));
bind(ResourceWatcherService.class).asEagerSingleton();
bind(RestController.class).toInstance(mock(RestController.class));
}
}

View File

@ -13,12 +13,13 @@ import org.elasticsearch.client.AdminClient;
import org.elasticsearch.client.Client;
import org.elasticsearch.client.ClusterAdminClient;
import org.elasticsearch.client.IndicesAdminClient;
import org.elasticsearch.common.collect.ImmutableSet;
import org.elasticsearch.common.settings.ImmutableSettings;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.rest.BaseRestHandler;
import org.elasticsearch.rest.RestChannel;
import org.elasticsearch.rest.RestController;
import org.elasticsearch.rest.RestRequest;
import org.elasticsearch.shield.SecurityFilter;
import org.elasticsearch.shield.User;
import org.elasticsearch.shield.authc.support.UserPasswdStore;
import org.elasticsearch.shield.authc.support.UserRolesStore;
@ -26,25 +27,41 @@ import org.elasticsearch.shield.authc.support.UsernamePasswordToken;
import org.elasticsearch.test.ElasticsearchTestCase;
import org.elasticsearch.transport.TransportRequest;
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 static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import static org.mockito.Mockito.*;
/**
*
*/
public class ESUsersRealmTests extends ElasticsearchTestCase {
private RestController restController;
private Client client;
private AdminClient adminClient;
@Before
public void init() throws Exception {
client = mock(Client.class);
adminClient = mock(AdminClient.class);
restController = mock(RestController.class);
}
@Test
public void testRestHeaderRegistration() {
new ESUsersRealm(ImmutableSettings.EMPTY, mock(UserPasswdStore.class), mock(UserRolesStore.class), restController);
verify(restController).registerRelevantHeaders(UsernamePasswordToken.BASIC_AUTH_HEADER);
}
@Test
public void testAuthenticate() throws Exception {
Settings settings = ImmutableSettings.builder().build();
MockUserPasswdStore userPasswdStore = new MockUserPasswdStore("user1", "test123");
MockUserRolesStore userRolesStore = new MockUserRolesStore("user1", "role1", "role2");
ESUsersRealm realm = new ESUsersRealm(settings, userPasswdStore, userRolesStore);
ESUsersRealm realm = new ESUsersRealm(settings, userPasswdStore, userRolesStore, restController);
User user = realm.authenticate(new UsernamePasswordToken("user1", "test123".toCharArray()));
assertTrue(userPasswdStore.called);
assertTrue(userRolesStore.called);
@ -60,7 +77,7 @@ public class ESUsersRealmTests extends ElasticsearchTestCase {
Settings settings = ImmutableSettings.builder().build();
MockUserPasswdStore userPasswdStore = new MockUserPasswdStore("user1", "test123");
MockUserRolesStore userRolesStore = new MockUserRolesStore("user1", "role1", "role2");
ESUsersRealm realm = new ESUsersRealm(settings, userPasswdStore, userRolesStore);
ESUsersRealm realm = new ESUsersRealm(settings, userPasswdStore, userRolesStore, restController);
TransportRequest request = new TransportRequest() {};
UsernamePasswordToken.putTokenHeader(request, new UsernamePasswordToken("user1", "test123".toCharArray()));
@ -116,9 +133,8 @@ public class ESUsersRealmTests extends ElasticsearchTestCase {
@Test @SuppressWarnings("unchecked")
public void testRestHeadersAreCopied() throws Exception {
// the required header will be registered only if ESUsersRealm is actually used.
new ESUsersRealm(ImmutableSettings.EMPTY, null, null);
Client client = mock(Client.class);
AdminClient adminClient = mock(AdminClient.class);
new ESUsersRealm(ImmutableSettings.EMPTY, null, null, restController);
when(restController.relevantHeaders()).thenReturn(ImmutableSet.of(UsernamePasswordToken.BASIC_AUTH_HEADER));
when(client.admin()).thenReturn(adminClient);
when(adminClient.cluster()).thenReturn(mock(ClusterAdminClient.class));
when(adminClient.indices()).thenReturn(mock(IndicesAdminClient.class));
@ -128,15 +144,16 @@ public class ESUsersRealmTests extends ElasticsearchTestCase {
return null;
}
};
RestRequest restRequest = mock(RestRequest.class);
final Action action = mock(Action.class);
final ActionListener listener = mock(ActionListener.class);
BaseRestHandler handler = new BaseRestHandler(ImmutableSettings.EMPTY, client) {
BaseRestHandler handler = new BaseRestHandler(ImmutableSettings.EMPTY, restController, client) {
@Override
protected void handleRequest(RestRequest restRequest, RestChannel channel, Client client) throws Exception {
client.execute(action, request, listener);
}
};
RestRequest restRequest = mock(RestRequest.class);
when(restRequest.header(UsernamePasswordToken.BASIC_AUTH_HEADER)).thenReturn("foobar");
RestChannel channel = mock(RestChannel.class);
handler.handleRequest(restRequest, channel);

View File

@ -8,11 +8,13 @@ package org.elasticsearch.shield.authc.ldap;
import org.elasticsearch.common.settings.ImmutableSettings;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.env.Environment;
import org.elasticsearch.rest.RestController;
import org.elasticsearch.shield.User;
import org.elasticsearch.shield.authc.support.UsernamePasswordToken;
import org.elasticsearch.test.ElasticsearchTestCase;
import org.elasticsearch.threadpool.ThreadPool;
import org.elasticsearch.watcher.ResourceWatcherService;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Rule;
import org.junit.Test;
@ -31,9 +33,22 @@ public class LdapRealmTest extends ElasticsearchTestCase {
public static final String VALID_USERNAME = "Thomas Masterman Hardy";
public static final String PASSWORD = "pass";
private RestController restController;
@Before
public void init() throws Exception {
restController = mock(RestController.class);
}
@Rule
public static ApacheDsRule apacheDsRule = new ApacheDsRule();
@Test
public void testRestHeaderRegistration() {
new LdapRealm(ImmutableSettings.EMPTY, mock(LdapConnectionFactory.class), mock(LdapGroupToRoleMapper.class), restController);
verify(restController).registerRelevantHeaders(UsernamePasswordToken.BASIC_AUTH_HEADER);
}
@Test
public void testAuthenticate_subTreeGroupSearch(){
String groupSearchBase = "o=sevenSeas";
@ -41,7 +56,7 @@ public class LdapRealmTest extends ElasticsearchTestCase {
String userTemplate = VALID_USER_TEMPLATE;
Settings settings = LdapConnectionTests.buildLdapSettings(apacheDsRule.getUrl(), userTemplate, groupSearchBase, isSubTreeSearch);
StandardLdapConnectionFactory ldapFactory = new StandardLdapConnectionFactory(settings);
LdapRealm ldap = new LdapRealm(buildNonCachingSettings(), ldapFactory, buildGroupAsRoleMapper());
LdapRealm ldap = new LdapRealm(buildNonCachingSettings(), ldapFactory, buildGroupAsRoleMapper(), restController);
User user = ldap.authenticate(new UsernamePasswordToken(VALID_USERNAME, PASSWORD.toCharArray()));
assertThat( user, notNullValue());
@ -56,7 +71,7 @@ public class LdapRealmTest extends ElasticsearchTestCase {
StandardLdapConnectionFactory ldapFactory = new StandardLdapConnectionFactory(
LdapConnectionTests.buildLdapSettings(apacheDsRule.getUrl(), userTemplate, groupSearchBase, isSubTreeSearch));
LdapRealm ldap = new LdapRealm(buildNonCachingSettings(), ldapFactory, buildGroupAsRoleMapper());
LdapRealm ldap = new LdapRealm(buildNonCachingSettings(), ldapFactory, buildGroupAsRoleMapper(), restController);
User user = ldap.authenticate(new UsernamePasswordToken(VALID_USERNAME, PASSWORD.toCharArray()));
assertThat( user, notNullValue());
@ -73,7 +88,7 @@ public class LdapRealmTest extends ElasticsearchTestCase {
LdapConnectionTests.buildLdapSettings( apacheDsRule.getUrl(), userTemplate, groupSearchBase, isSubTreeSearch) );
ldapFactory = spy(ldapFactory);
LdapRealm ldap = new LdapRealm( buildCachingSettings(), ldapFactory, buildGroupAsRoleMapper());
LdapRealm ldap = new LdapRealm( buildCachingSettings(), ldapFactory, buildGroupAsRoleMapper(), restController);
User user = ldap.authenticate( new UsernamePasswordToken(VALID_USERNAME, PASSWORD.toCharArray()));
user = ldap.authenticate( new UsernamePasswordToken(VALID_USERNAME, PASSWORD.toCharArray()));
@ -90,7 +105,7 @@ public class LdapRealmTest extends ElasticsearchTestCase {
LdapConnectionTests.buildLdapSettings(apacheDsRule.getUrl(), userTemplate, groupSearchBase, isSubTreeSearch) );
ldapFactory = spy(ldapFactory);
LdapRealm ldap = new LdapRealm( buildNonCachingSettings(), ldapFactory, buildGroupAsRoleMapper());
LdapRealm ldap = new LdapRealm( buildNonCachingSettings(), ldapFactory, buildGroupAsRoleMapper(), restController);
User user = ldap.authenticate( new UsernamePasswordToken(VALID_USERNAME, PASSWORD.toCharArray()));
user = ldap.authenticate( new UsernamePasswordToken(VALID_USERNAME, PASSWORD.toCharArray()));
@ -107,7 +122,7 @@ public class LdapRealmTest extends ElasticsearchTestCase {
ActiveDirectoryConnectionFactory ldapFactory = new ActiveDirectoryConnectionFactory(
ActiveDirectoryFactoryTests.buildAdSettings(AD_URL, adDomain));
LdapRealm ldap = new LdapRealm( buildNonCachingSettings(), ldapFactory, buildGroupAsRoleMapper());
LdapRealm ldap = new LdapRealm( buildNonCachingSettings(), ldapFactory, buildGroupAsRoleMapper(), restController);
User user = ldap.authenticate( new UsernamePasswordToken("george", "R))Tr0x".toCharArray()));
@ -125,7 +140,7 @@ public class LdapRealmTest extends ElasticsearchTestCase {
.build();
ActiveDirectoryConnectionFactory ldapFactory = new ActiveDirectoryConnectionFactory( settings );
LdapRealm ldap = new LdapRealm( buildNonCachingSettings(), ldapFactory, buildGroupAsRoleMapper());
LdapRealm ldap = new LdapRealm( buildNonCachingSettings(), ldapFactory, buildGroupAsRoleMapper(), restController);
User user = ldap.authenticate( new UsernamePasswordToken("george", "R))Tr0x".toCharArray()));
assertThat( user, notNullValue());

View File

@ -22,7 +22,7 @@ public class ShieldPluginTests extends ShieldIntegrationTest {
logger.info("--> Checking nodes info that shield plugin is loaded");
for (NodeInfo nodeInfo : nodeInfos.getNodes()) {
assertThat(nodeInfo.getPlugins().getInfos(), hasSize(1));
assertThat(nodeInfo.getPlugins().getInfos().get(0).getName(), is(SecurityPlugin.NAME));
assertThat(nodeInfo.getPlugins().getInfos().get(0).getName(), is(ShieldPlugin.NAME));
}
}

View File

@ -6,17 +6,17 @@
package org.elasticsearch.shield.test;
import org.elasticsearch.rest.RestStatus;
import org.elasticsearch.shield.SecurityException;
import org.elasticsearch.shield.ShieldException;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.*;
public class ShieldAssertions {
public static void assertContainsWWWAuthenticateHeader(org.elasticsearch.shield.SecurityException e) {
public static void assertContainsWWWAuthenticateHeader(ShieldException e) {
assertThat(e.status(), is(RestStatus.UNAUTHORIZED));
assertThat(e.getHeaders(), hasKey("WWW-Authenticate"));
assertThat(e.getHeaders().get("WWW-Authenticate"), hasSize(1));
assertThat(e.getHeaders().get("WWW-Authenticate").get(0), is(SecurityException.HEADERS.get("WWW-Authenticate").get(0)));
assertThat(e.getHeaders().get("WWW-Authenticate").get(0), is(ShieldException.HEADERS.get("WWW-Authenticate").get(0)));
}
}

View File

@ -15,7 +15,7 @@ import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.transport.InetSocketTransportAddress;
import org.elasticsearch.common.transport.TransportAddress;
import org.elasticsearch.plugins.PluginsService;
import org.elasticsearch.shield.plugin.SecurityPlugin;
import org.elasticsearch.shield.plugin.ShieldPlugin;
import org.elasticsearch.shield.transport.netty.NettySecuredTransport;
import org.elasticsearch.test.ElasticsearchIntegrationTest;
import org.elasticsearch.transport.Transport;
@ -65,7 +65,7 @@ public abstract class ShieldIntegrationTest extends ElasticsearchIntegrationTest
.put("discovery.zen.ping.multicast.enabled", false)
.put("discovery.type", "zen")
.put("node.mode", "network")
.put("plugin.types", SecurityPlugin.class.getName())
.put("plugin.types", ShieldPlugin.class.getName())
.put("shield.authc.esusers.files.users", writeFile(folder, "users", CONFIG_STANDARD_USER))
.put("shield.authc.esusers.files.users_roles", writeFile(folder, "users_roles", CONFIG_STANDARD_USER_ROLES))
.put("shield.authz.store.files.roles", writeFile(folder, "roles.yml", CONFIG_ROLE_ALLOW_ALL))

View File

@ -25,6 +25,7 @@ indices:admin/cache/clear
indices:admin/close
indices:admin/create
indices:admin/delete
indices:admin/get
indices:admin/exists
indices:admin/flush
indices:admin/mapping/delete