Internal: Remove guice from audit trail construction

This change removes guice from audit trails.

Original commit: elastic/x-pack-elasticsearch@ace1f11dc4
This commit is contained in:
Ryan Ernst 2016-07-18 13:59:51 -07:00
parent c3a3898da9
commit f03683fb18
12 changed files with 175 additions and 206 deletions

View File

@ -11,14 +11,19 @@ import java.util.Arrays;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Optional; import java.util.Optional;
import java.util.Set;
import java.util.function.Function; import java.util.function.Function;
import java.util.stream.Collectors;
import org.elasticsearch.action.ActionRequest; import org.elasticsearch.action.ActionRequest;
import org.elasticsearch.action.ActionResponse; import org.elasticsearch.action.ActionResponse;
import org.elasticsearch.action.support.ActionFilter; import org.elasticsearch.action.support.ActionFilter;
import org.elasticsearch.cluster.service.ClusterService;
import org.elasticsearch.common.Booleans; import org.elasticsearch.common.Booleans;
import org.elasticsearch.common.Strings; import org.elasticsearch.common.Strings;
import org.elasticsearch.common.component.LifecycleComponent; import org.elasticsearch.common.component.LifecycleComponent;
@ -63,12 +68,12 @@ import org.elasticsearch.xpack.security.action.user.TransportChangePasswordActio
import org.elasticsearch.xpack.security.action.user.TransportDeleteUserAction; import org.elasticsearch.xpack.security.action.user.TransportDeleteUserAction;
import org.elasticsearch.xpack.security.action.user.TransportGetUsersAction; import org.elasticsearch.xpack.security.action.user.TransportGetUsersAction;
import org.elasticsearch.xpack.security.action.user.TransportPutUserAction; import org.elasticsearch.xpack.security.action.user.TransportPutUserAction;
import org.elasticsearch.xpack.security.audit.AuditTrailModule; import org.elasticsearch.xpack.security.audit.AuditTrail;
import org.elasticsearch.xpack.security.audit.AuditTrailService;
import org.elasticsearch.xpack.security.audit.index.IndexAuditTrail; import org.elasticsearch.xpack.security.audit.index.IndexAuditTrail;
import org.elasticsearch.xpack.security.audit.index.IndexNameResolver; import org.elasticsearch.xpack.security.audit.index.IndexNameResolver;
import org.elasticsearch.xpack.security.authc.AuthenticationFailureHandler; import org.elasticsearch.xpack.security.audit.logfile.LoggingAuditTrail;
import org.elasticsearch.xpack.security.authc.AuthenticationModule; import org.elasticsearch.xpack.security.authc.AuthenticationModule;
import org.elasticsearch.xpack.security.authc.DefaultAuthenticationFailureHandler;
import org.elasticsearch.xpack.security.authc.InternalAuthenticationService; import org.elasticsearch.xpack.security.authc.InternalAuthenticationService;
import org.elasticsearch.xpack.security.authc.Realm; import org.elasticsearch.xpack.security.authc.Realm;
import org.elasticsearch.xpack.security.authc.Realms; import org.elasticsearch.xpack.security.authc.Realms;
@ -128,6 +133,14 @@ public class Security implements ActionPlugin {
public static final String DLS_FLS_FEATURE = "security.dls_fls"; public static final String DLS_FLS_FEATURE = "security.dls_fls";
public static final Setting<Optional<String>> USER_SETTING = OptionalSettings.createString(setting("user"), Property.NodeScope); public static final Setting<Optional<String>> USER_SETTING = OptionalSettings.createString(setting("user"), Property.NodeScope);
public static final Setting<Boolean> AUDIT_ENABLED_SETTING =
Setting.boolSetting(featureEnabledSetting("audit"), false, Property.NodeScope);
public static final Setting<List<String>> AUDIT_OUTPUTS_SETTING =
Setting.listSetting(setting("audit.outputs"),
s -> s.getAsMap().containsKey(setting("audit.outputs")) ?
Collections.emptyList() : Collections.singletonList(LoggingAuditTrail.NAME),
Function.identity(), Property.NodeScope);
private final Settings settings; private final Settings settings;
private final Environment env; private final Environment env;
private final boolean enabled; private final boolean enabled;
@ -182,10 +195,17 @@ public class Security implements ActionPlugin {
modules.add(new AuthenticationModule(settings)); modules.add(new AuthenticationModule(settings));
modules.add(new AuthorizationModule(settings)); modules.add(new AuthorizationModule(settings));
if (enabled == false || auditingEnabled(settings) == false) {
modules.add(b -> {
b.bind(AuditTrailService.class).toProvider(Providers.of(null));
b.bind(AuditTrail.class).toInstance(AuditTrail.NOOP);
});
}
if (enabled == false) { if (enabled == false) {
modules.add(b -> b.bind(CryptoService.class).toProvider(Providers.of(null))); modules.add(b -> {
b.bind(CryptoService.class).toProvider(Providers.of(null));
});
modules.add(new SecurityModule(settings)); modules.add(new SecurityModule(settings));
modules.add(new AuditTrailModule(settings));
modules.add(new SecurityTransportModule(settings)); modules.add(new SecurityTransportModule(settings));
return modules; return modules;
} }
@ -193,10 +213,16 @@ public class Security implements ActionPlugin {
// we can't load that at construction time since the license plugin might not have been loaded at that point // we can't load that at construction time since the license plugin might not have been loaded at that point
// which might not be the case during Plugin class instantiation. Once nodeModules are pulled // which might not be the case during Plugin class instantiation. Once nodeModules are pulled
// everything should have been loaded // everything should have been loaded
modules.add(b -> {
modules.add(b -> b.bind(CryptoService.class).toInstance(cryptoService)); b.bind(CryptoService.class).toInstance(cryptoService);
if (auditingEnabled(settings)) {
b.bind(AuditTrail.class).to(AuditTrailService.class); // interface used by some actions...
} else {
// TODO: remove this once we can construct SecurityLifecycleService without guice
b.bind(IndexAuditTrail.class).toProvider(Providers.of(null));
}
});
modules.add(new SecurityModule(settings)); modules.add(new SecurityModule(settings));
modules.add(new AuditTrailModule(settings));
modules.add(new SecurityRestModule(settings)); modules.add(new SecurityRestModule(settings));
modules.add(new SecurityActionModule(settings)); modules.add(new SecurityActionModule(settings));
modules.add(new SecurityTransportModule(settings)); modules.add(new SecurityTransportModule(settings));
@ -212,15 +238,18 @@ public class Security implements ActionPlugin {
return list; return list;
} }
public Collection<Object> createComponents(InternalClient client, ThreadPool threadPool, public Collection<Object> createComponents(InternalClient client, ThreadPool threadPool, ClusterService clusterService,
ResourceWatcherService resourceWatcherService, List<XPackExtension> extensions) { ResourceWatcherService resourceWatcherService, List<XPackExtension> extensions) {
if (enabled == false) { if (enabled == false) {
return Collections.emptyList(); return Collections.emptyList();
} }
List<Object> components = new ArrayList<>();
final SSLConfiguration.Global globalSslConfig = new SSLConfiguration.Global(settings); final SSLConfiguration.Global globalSslConfig = new SSLConfiguration.Global(settings);
final ClientSSLService clientSSLService = new ClientSSLService(settings, env, globalSslConfig, resourceWatcherService); final ClientSSLService clientSSLService = new ClientSSLService(settings, env, globalSslConfig, resourceWatcherService);
final ServerSSLService serverSSLService = new ServerSSLService(settings, env, globalSslConfig, resourceWatcherService); final ServerSSLService serverSSLService = new ServerSSLService(settings, env, globalSslConfig, resourceWatcherService);
components.add(clientSSLService);
components.add(serverSSLService);
// realms construction // realms construction
final NativeUsersStore nativeUsersStore = new NativeUsersStore(settings, client, threadPool); final NativeUsersStore nativeUsersStore = new NativeUsersStore(settings, client, threadPool);
@ -241,8 +270,33 @@ public class Security implements ActionPlugin {
} }
} }
final Realms realms = new Realms(settings, env, realmFactories, securityLicenseState, reservedRealm); final Realms realms = new Realms(settings, env, realmFactories, securityLicenseState, reservedRealm);
components.add(nativeUsersStore);
components.add(realms);
return Arrays.asList(clientSSLService, serverSSLService, nativeUsersStore, realms); // audit trails construction
if (AUDIT_ENABLED_SETTING.get(settings)) {
List<String> outputs = AUDIT_OUTPUTS_SETTING.get(settings);
if (outputs.isEmpty()) {
throw new IllegalArgumentException("Audit logging is enabled but there are zero output types in "
+ AUDIT_ENABLED_SETTING.getKey());
}
Set<AuditTrail> auditTrails = new LinkedHashSet<>();
for (String output : outputs) {
switch (output) {
case LoggingAuditTrail.NAME:
auditTrails.add(new LoggingAuditTrail(settings, clusterService, threadPool));
break;
case IndexAuditTrail.NAME:
auditTrails.add(new IndexAuditTrail(settings, client, threadPool, clusterService));
break;
default:
throw new IllegalArgumentException("Unknown audit trail output [" + output + "]");
}
}
components.add(new AuditTrailService(settings, auditTrails.stream().collect(Collectors.toList()), securityLicenseState));
}
return components;
} }
public Settings additionalSettings() { public Settings additionalSettings() {
@ -288,7 +342,10 @@ public class Security implements ActionPlugin {
IPFilter.addSettings(settingsList); IPFilter.addSettings(settingsList);
// audit settings // audit settings
AuditTrailModule.addSettings(settingsList); settingsList.add(AUDIT_ENABLED_SETTING);
settingsList.add(AUDIT_OUTPUTS_SETTING);
LoggingAuditTrail.registerSettings(settingsList);
IndexAuditTrail.registerSettings(settingsList);
// authentication settings // authentication settings
FileRolesStore.addSettings(settingsList); FileRolesStore.addSettings(settingsList);
@ -515,13 +572,29 @@ public class Security implements ActionPlugin {
return XPackPlugin.featureEnabledSetting("security." + feature); return XPackPlugin.featureEnabledSetting("security." + feature);
} }
public static boolean auditingEnabled(Settings settings) {
return AUDIT_ENABLED_SETTING.get(settings);
}
public static boolean indexAuditLoggingEnabled(Settings settings) {
if (auditingEnabled(settings)) {
List<String> outputs = AUDIT_OUTPUTS_SETTING.get(settings);
for (String output : outputs) {
if (output.equals(IndexAuditTrail.NAME)) {
return true;
}
}
}
return false;
}
static void validateAutoCreateIndex(Settings settings) { static void validateAutoCreateIndex(Settings settings) {
String value = settings.get("action.auto_create_index"); String value = settings.get("action.auto_create_index");
if (value == null) { if (value == null) {
return; return;
} }
final boolean indexAuditingEnabled = AuditTrailModule.indexAuditLoggingEnabled(settings); final boolean indexAuditingEnabled = Security.indexAuditLoggingEnabled(settings);
final String auditIndex = indexAuditingEnabled ? "," + IndexAuditTrail.INDEX_NAME_PREFIX + "*" : ""; final String auditIndex = indexAuditingEnabled ? "," + IndexAuditTrail.INDEX_NAME_PREFIX + "*" : "";
String errorMessage = LoggerMessageFormat.format("the [action.auto_create_index] setting value [{}] is too" + String errorMessage = LoggerMessageFormat.format("the [action.auto_create_index] setting value [{}] is too" +
" restrictive. disable [action.auto_create_index] or set it to " + " restrictive. disable [action.auto_create_index] or set it to " +

View File

@ -11,10 +11,8 @@ import org.elasticsearch.cluster.ClusterStateListener;
import org.elasticsearch.common.component.AbstractComponent; import org.elasticsearch.common.component.AbstractComponent;
import org.elasticsearch.common.component.LifecycleListener; import org.elasticsearch.common.component.LifecycleListener;
import org.elasticsearch.common.inject.Inject; import org.elasticsearch.common.inject.Inject;
import org.elasticsearch.common.inject.Provider;
import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.util.concurrent.AbstractRunnable; import org.elasticsearch.common.util.concurrent.AbstractRunnable;
import org.elasticsearch.xpack.security.audit.AuditTrailModule;
import org.elasticsearch.xpack.security.audit.index.IndexAuditTrail; import org.elasticsearch.xpack.security.audit.index.IndexAuditTrail;
import org.elasticsearch.xpack.security.authc.esnative.NativeUsersStore; import org.elasticsearch.xpack.security.authc.esnative.NativeUsersStore;
import org.elasticsearch.xpack.security.authz.store.NativeRolesStore; import org.elasticsearch.xpack.security.authz.store.NativeRolesStore;
@ -111,7 +109,7 @@ public class SecurityLifecycleService extends AbstractComponent implements Clust
} }
try { try {
if (AuditTrailModule.indexAuditLoggingEnabled(settings) && if (Security.indexAuditLoggingEnabled(settings) &&
indexAuditTrail.state() == IndexAuditTrail.State.INITIALIZED) { indexAuditTrail.state() == IndexAuditTrail.State.INITIALIZED) {
if (indexAuditTrail.canStart(event, master)) { if (indexAuditTrail.canStart(event, master)) {
threadPool.generic().execute(new AbstractRunnable() { threadPool.generic().execute(new AbstractRunnable() {

View File

@ -1,108 +0,0 @@
/*
* 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.xpack.security.audit;
import org.elasticsearch.ElasticsearchException;
import org.elasticsearch.common.inject.multibindings.Multibinder;
import org.elasticsearch.common.inject.util.Providers;
import org.elasticsearch.common.settings.Setting;
import org.elasticsearch.common.settings.Setting.Property;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.util.set.Sets;
import org.elasticsearch.xpack.security.audit.index.IndexAuditTrail;
import org.elasticsearch.xpack.security.audit.logfile.LoggingAuditTrail;
import org.elasticsearch.xpack.security.support.AbstractSecurityModule;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.function.Function;
import static org.elasticsearch.xpack.security.Security.featureEnabledSetting;
import static org.elasticsearch.xpack.security.Security.setting;
/**
*
*/
public class AuditTrailModule extends AbstractSecurityModule.Node {
public static final Setting<Boolean> ENABLED_SETTING =
Setting.boolSetting(featureEnabledSetting("audit"), false, Property.NodeScope);
public static final Setting<List<String>> OUTPUTS_SETTING =
Setting.listSetting(setting("audit.outputs"),
s -> s.getAsMap().containsKey(setting("audit.outputs")) ?
Collections.emptyList() : Collections.singletonList(LoggingAuditTrail.NAME),
Function.identity(), Property.NodeScope);
private final boolean enabled;
public AuditTrailModule(Settings settings) {
super(settings);
enabled = ENABLED_SETTING.get(settings);
}
@Override
protected void configureNode() {
List<String> outputs = OUTPUTS_SETTING.get(settings);
if (securityEnabled == false || enabled == false || outputs.isEmpty()) {
bind(AuditTrailService.class).toProvider(Providers.of(null));
bind(AuditTrail.class).toInstance(AuditTrail.NOOP);
return;
}
bind(AuditTrailService.class).asEagerSingleton();
bind(AuditTrail.class).to(AuditTrailService.class);
Multibinder<AuditTrail> binder = Multibinder.newSetBinder(binder(), AuditTrail.class);
for (String output : outputs) {
switch (output) {
case LoggingAuditTrail.NAME:
binder.addBinding().to(LoggingAuditTrail.class);
bind(LoggingAuditTrail.class).asEagerSingleton();
break;
case IndexAuditTrail.NAME:
binder.addBinding().to(IndexAuditTrail.class);
bind(IndexAuditTrail.class).asEagerSingleton();
break;
default:
throw new IllegalArgumentException("unknown audit trail output [" + output + "]");
}
}
}
public static boolean auditingEnabled(Settings settings) {
return ENABLED_SETTING.get(settings);
}
public static boolean indexAuditLoggingEnabled(Settings settings) {
if (auditingEnabled(settings)) {
List<String> outputs = OUTPUTS_SETTING.get(settings);
for (String output : outputs) {
if (output.equals(IndexAuditTrail.NAME)) {
return true;
}
}
}
return false;
}
public static boolean fileAuditLoggingEnabled(Settings settings) {
if (auditingEnabled(settings)) {
List<String> outputs = OUTPUTS_SETTING.get(settings);
for (String output : outputs) {
if (output.equals(LoggingAuditTrail.NAME)) {
return true;
}
}
}
return false;
}
public static void addSettings(List<Setting<?>> settings) {
settings.add(ENABLED_SETTING);
settings.add(OUTPUTS_SETTING);
LoggingAuditTrail.registerSettings(settings);
IndexAuditTrail.registerSettings(settings);
}
}

View File

@ -5,20 +5,23 @@
*/ */
package org.elasticsearch.xpack.security.audit; package org.elasticsearch.xpack.security.audit;
import java.net.InetAddress;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.elasticsearch.common.component.AbstractComponent; import org.elasticsearch.common.component.AbstractComponent;
import org.elasticsearch.common.inject.Inject; import org.elasticsearch.common.inject.Inject;
import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.rest.RestRequest; import org.elasticsearch.rest.RestRequest;
import org.elasticsearch.transport.TransportMessage;
import org.elasticsearch.xpack.security.Security;
import org.elasticsearch.xpack.security.SecurityLicenseState; import org.elasticsearch.xpack.security.SecurityLicenseState;
import org.elasticsearch.xpack.security.user.User;
import org.elasticsearch.xpack.security.authc.AuthenticationToken; import org.elasticsearch.xpack.security.authc.AuthenticationToken;
import org.elasticsearch.xpack.security.transport.filter.SecurityIpFilterRule; import org.elasticsearch.xpack.security.transport.filter.SecurityIpFilterRule;
import org.elasticsearch.transport.TransportMessage; import org.elasticsearch.xpack.security.user.User;
import java.net.InetAddress;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
/** /**
* *
@ -26,20 +29,24 @@ import java.util.Set;
public class AuditTrailService extends AbstractComponent implements AuditTrail { public class AuditTrailService extends AbstractComponent implements AuditTrail {
private final SecurityLicenseState securityLicenseState; private final SecurityLicenseState securityLicenseState;
final AuditTrail[] auditTrails; final List<AuditTrail> auditTrails;
@Override @Override
public String name() { public String name() {
return "service"; return "service";
} }
@Inject public AuditTrailService(Settings settings, List<AuditTrail> auditTrails, SecurityLicenseState licenseState) {
public AuditTrailService(Settings settings, Set<AuditTrail> auditTrails, SecurityLicenseState licenseState) {
super(settings); super(settings);
this.auditTrails = auditTrails.toArray(new AuditTrail[auditTrails.size()]); this.auditTrails = Collections.unmodifiableList(auditTrails);
this.securityLicenseState = licenseState; this.securityLicenseState = licenseState;
} }
/** Returns the audit trail implementations that this service delegates to. */
public List<AuditTrail> getAuditTrails() {
return auditTrails;
}
@Override @Override
public void anonymousAccessDenied(String action, TransportMessage message) { public void anonymousAccessDenied(String action, TransportMessage message) {
if (securityLicenseState.auditingEnabled()) { if (securityLicenseState.auditingEnabled()) {
@ -202,8 +209,8 @@ public class AuditTrailService extends AbstractComponent implements AuditTrail {
public Map<String, Object> usageStats() { public Map<String, Object> usageStats() {
Map<String, Object> map = new HashMap<>(2); Map<String, Object> map = new HashMap<>(2);
map.put("enabled", AuditTrailModule.ENABLED_SETTING.get(settings)); map.put("enabled", Security.AUDIT_ENABLED_SETTING.get(settings));
map.put("outputs", AuditTrailModule.OUTPUTS_SETTING.get(settings)); map.put("outputs", Security.AUDIT_OUTPUTS_SETTING.get(settings));
return map; return map;
} }
} }

View File

@ -169,9 +169,7 @@ public class IndexAuditTrail extends AbstractComponent implements AuditTrail, Cl
return NAME; return NAME;
} }
@Inject public IndexAuditTrail(Settings settings, InternalClient client, ThreadPool threadPool, ClusterService clusterService) {
public IndexAuditTrail(Settings settings, InternalClient client, ThreadPool threadPool,
ClusterService clusterService) {
super(settings); super(settings);
this.threadPool = threadPool; this.threadPool = threadPool;
this.clusterService = clusterService; this.clusterService = clusterService;

View File

@ -68,7 +68,6 @@ public class LoggingAuditTrail extends AbstractComponent implements AuditTrail {
return NAME; return NAME;
} }
@Inject
public LoggingAuditTrail(Settings settings, ClusterService clusterService, ThreadPool threadPool) { public LoggingAuditTrail(Settings settings, ClusterService clusterService, ThreadPool threadPool) {
this(settings, clusterService, Loggers.getLogger(LoggingAuditTrail.class), threadPool.getThreadContext()); this(settings, clusterService, Loggers.getLogger(LoggingAuditTrail.class), threadPool.getThreadContext());
} }

View File

@ -18,7 +18,6 @@ import org.elasticsearch.test.ESIntegTestCase.Scope;
import org.elasticsearch.xpack.security.authc.file.FileRealm; import org.elasticsearch.xpack.security.authc.file.FileRealm;
import org.elasticsearch.xpack.security.authc.esnative.NativeRealm; import org.elasticsearch.xpack.security.authc.esnative.NativeRealm;
import org.elasticsearch.xpack.security.Security; import org.elasticsearch.xpack.security.Security;
import org.elasticsearch.xpack.security.audit.AuditTrailModule;
import org.elasticsearch.xpack.security.audit.logfile.LoggingAuditTrail; import org.elasticsearch.xpack.security.audit.logfile.LoggingAuditTrail;
import org.elasticsearch.xpack.security.authc.support.Hasher; import org.elasticsearch.xpack.security.authc.support.Hasher;
import org.elasticsearch.xpack.security.authc.support.SecuredString; import org.elasticsearch.xpack.security.authc.support.SecuredString;
@ -129,7 +128,7 @@ public class SecuritySettingsSource extends ClusterDiscoveryConfiguration.Unicas
//TODO: for now isolate security tests from watcher & monitoring (randomize this later) //TODO: for now isolate security tests from watcher & monitoring (randomize this later)
.put(XPackPlugin.featureEnabledSetting(Watcher.NAME), false) .put(XPackPlugin.featureEnabledSetting(Watcher.NAME), false)
.put(XPackPlugin.featureEnabledSetting(Monitoring.NAME), false) .put(XPackPlugin.featureEnabledSetting(Monitoring.NAME), false)
.put(AuditTrailModule.ENABLED_SETTING.getKey(), randomBoolean()) .put(Security.AUDIT_ENABLED_SETTING.getKey(), randomBoolean())
.put(LoggingAuditTrail.HOST_ADDRESS_SETTING.getKey(), randomBoolean()) .put(LoggingAuditTrail.HOST_ADDRESS_SETTING.getKey(), randomBoolean())
.put(LoggingAuditTrail.HOST_NAME_SETTING.getKey(), randomBoolean()) .put(LoggingAuditTrail.HOST_NAME_SETTING.getKey(), randomBoolean())
.put(LoggingAuditTrail.NODE_NAME_SETTING.getKey(), randomBoolean()) .put(LoggingAuditTrail.NODE_NAME_SETTING.getKey(), randomBoolean())

View File

@ -9,8 +9,6 @@ import java.io.IOException;
import org.elasticsearch.common.Strings; import org.elasticsearch.common.Strings;
import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.env.Environment;
import org.elasticsearch.xpack.security.audit.AuditTrailModule;
import org.elasticsearch.xpack.security.audit.index.IndexAuditTrail; import org.elasticsearch.xpack.security.audit.index.IndexAuditTrail;
import org.elasticsearch.test.ESTestCase; import org.elasticsearch.test.ESTestCase;
import org.elasticsearch.xpack.XPackPlugin; import org.elasticsearch.xpack.XPackPlugin;
@ -159,14 +157,14 @@ public class SecuritySettingsTests extends ESTestCase {
Security.validateAutoCreateIndex(Settings.builder() Security.validateAutoCreateIndex(Settings.builder()
.put("action.auto_create_index", ".security") .put("action.auto_create_index", ".security")
.put(AuditTrailModule.ENABLED_SETTING.getKey(), true) .put(Security.AUDIT_ENABLED_SETTING.getKey(), true)
.build()); .build());
try { try {
Security.validateAutoCreateIndex(Settings.builder() Security.validateAutoCreateIndex(Settings.builder()
.put("action.auto_create_index", ".security") .put("action.auto_create_index", ".security")
.put(AuditTrailModule.ENABLED_SETTING.getKey(), true) .put(Security.AUDIT_ENABLED_SETTING.getKey(), true)
.put(AuditTrailModule.OUTPUTS_SETTING.getKey(), randomFrom("index", "logfile,index")) .put(Security.AUDIT_OUTPUTS_SETTING.getKey(), randomFrom("index", "logfile,index"))
.build()); .build());
fail("IllegalArgumentException expected"); fail("IllegalArgumentException expected");
} catch (IllegalArgumentException e) { } catch (IllegalArgumentException e) {
@ -176,8 +174,8 @@ public class SecuritySettingsTests extends ESTestCase {
Security.validateAutoCreateIndex(Settings.builder() Security.validateAutoCreateIndex(Settings.builder()
.put("action.auto_create_index", ".security_audit_log*,.security") .put("action.auto_create_index", ".security_audit_log*,.security")
.put(AuditTrailModule.ENABLED_SETTING.getKey(), true) .put(Security.AUDIT_ENABLED_SETTING.getKey(), true)
.put(AuditTrailModule.OUTPUTS_SETTING.getKey(), randomFrom("index", "logfile,index")) .put(Security.AUDIT_OUTPUTS_SETTING.getKey(), randomFrom("index", "logfile,index"))
.build()); .build());
} }
} }

View File

@ -9,6 +9,7 @@ import java.io.IOException;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.List;
import java.util.Map; import java.util.Map;
import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.settings.Settings;
@ -16,6 +17,10 @@ import org.elasticsearch.env.Environment;
import org.elasticsearch.test.ESTestCase; import org.elasticsearch.test.ESTestCase;
import org.elasticsearch.threadpool.ThreadPool; import org.elasticsearch.threadpool.ThreadPool;
import org.elasticsearch.xpack.extensions.XPackExtension; import org.elasticsearch.xpack.extensions.XPackExtension;
import org.elasticsearch.xpack.security.audit.AuditTrail;
import org.elasticsearch.xpack.security.audit.AuditTrailService;
import org.elasticsearch.xpack.security.audit.index.IndexAuditTrail;
import org.elasticsearch.xpack.security.audit.logfile.LoggingAuditTrail;
import org.elasticsearch.xpack.security.authc.Realm; import org.elasticsearch.xpack.security.authc.Realm;
import org.elasticsearch.xpack.security.authc.Realms; import org.elasticsearch.xpack.security.authc.Realms;
import org.elasticsearch.xpack.security.authc.file.FileRealm; import org.elasticsearch.xpack.security.authc.file.FileRealm;
@ -49,7 +54,7 @@ public class SecurityTests extends ESTestCase {
Environment env = new Environment(settings); Environment env = new Environment(settings);
Security security = new Security(settings, env); Security security = new Security(settings, env);
ThreadPool threadPool = mock(ThreadPool.class); ThreadPool threadPool = mock(ThreadPool.class);
return security.createComponents(null, threadPool, null, Arrays.asList(extensions)); return security.createComponents(null, threadPool, null, null, Arrays.asList(extensions));
} }
private <T> T findComponent(Class<T> type, Collection<Object> components) { private <T> T findComponent(Class<T> type, Collection<Object> components) {
@ -58,12 +63,13 @@ public class SecurityTests extends ESTestCase {
return type.cast(obj); return type.cast(obj);
} }
} }
throw new AssertionError("Could not find component of type " + type + " in components"); return null;
} }
public void testCustomRealmExtension() throws Exception { public void testCustomRealmExtension() throws Exception {
Collection<Object> components = createComponents(Settings.EMPTY, new DummyExtension("myrealm")); Collection<Object> components = createComponents(Settings.EMPTY, new DummyExtension("myrealm"));
Realms realms = findComponent(Realms.class, components); Realms realms = findComponent(Realms.class, components);
assertNotNull(realms);
assertNotNull(realms.realmFactory("myrealm")); assertNotNull(realms.realmFactory("myrealm"));
} }
@ -72,4 +78,50 @@ public class SecurityTests extends ESTestCase {
() -> createComponents(Settings.EMPTY, new DummyExtension(FileRealm.TYPE))); () -> createComponents(Settings.EMPTY, new DummyExtension(FileRealm.TYPE)));
assertEquals("Realm type [" + FileRealm.TYPE + "] is already registered", e.getMessage()); assertEquals("Realm type [" + FileRealm.TYPE + "] is already registered", e.getMessage());
} }
public void testAuditEnabled() throws Exception {
Settings settings = Settings.builder().put(Security.AUDIT_ENABLED_SETTING.getKey(), true).build();
Collection<Object> components = createComponents(settings);
AuditTrailService service = findComponent(AuditTrailService.class, components);
assertNotNull(service);
assertEquals(1, service.getAuditTrails().size());
assertEquals(LoggingAuditTrail.NAME, service.getAuditTrails().get(0).name());
}
public void testDisabledByDefault() throws Exception {
Collection<Object> components = createComponents(Settings.EMPTY);
assertNull(findComponent(AuditTrailService.class, components));
}
public void testIndexAuditTrail() throws Exception {
Settings settings = Settings.builder()
.put(Security.AUDIT_ENABLED_SETTING.getKey(), true)
.put(Security.AUDIT_OUTPUTS_SETTING.getKey(), "index").build();
Collection<Object> components = createComponents(settings);
AuditTrailService service = findComponent(AuditTrailService.class, components);
assertNotNull(service);
assertEquals(1, service.getAuditTrails().size());
assertEquals(IndexAuditTrail.NAME, service.getAuditTrails().get(0).name());
}
public void testIndexAndLoggingAuditTrail() throws Exception {
Settings settings = Settings.builder()
.put(Security.AUDIT_ENABLED_SETTING.getKey(), true)
.put(Security.AUDIT_OUTPUTS_SETTING.getKey(), "index,logfile").build();
Collection<Object> components = createComponents(settings);
AuditTrailService service = findComponent(AuditTrailService.class, components);
assertNotNull(service);
assertEquals(2, service.getAuditTrails().size());
assertEquals(IndexAuditTrail.NAME, service.getAuditTrails().get(0).name());
assertEquals(LoggingAuditTrail.NAME, service.getAuditTrails().get(1).name());
}
public void testUnknownOutput() throws Exception {
Settings settings = Settings.builder()
.put(Security.AUDIT_ENABLED_SETTING.getKey(), true)
.put(Security.AUDIT_OUTPUTS_SETTING.getKey(), "foo").build();
IllegalArgumentException e = expectThrows(IllegalArgumentException.class, () -> createComponents(settings));
assertEquals("Unknown audit trail output [foo]", e.getMessage());
}
} }

View File

@ -1,50 +0,0 @@
/*
* 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.xpack.security.audit;
import org.elasticsearch.common.inject.ModuleTestCase;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.xpack.security.audit.index.IndexAuditTrail;
import org.elasticsearch.xpack.security.audit.logfile.LoggingAuditTrail;
public class AuditTrailModuleTests extends ModuleTestCase {
public void testEnabled() throws Exception {
Settings settings = Settings.builder().put(AuditTrailModule.ENABLED_SETTING.getKey(), true).build();
AuditTrailModule module = new AuditTrailModule(settings);
assertBinding(module, AuditTrail.class, AuditTrailService.class);
assertSetMultiBinding(module, AuditTrail.class, LoggingAuditTrail.class);
}
public void testDisabledByDefault() throws Exception {
AuditTrailModule module = new AuditTrailModule(Settings.EMPTY);
assertInstanceBinding(module, AuditTrail.class, x -> x == AuditTrail.NOOP);
}
public void testIndexAuditTrail() throws Exception {
Settings settings = Settings.builder()
.put(AuditTrailModule.ENABLED_SETTING.getKey(), true)
.put(AuditTrailModule.OUTPUTS_SETTING.getKey(), "index").build();
AuditTrailModule module = new AuditTrailModule(settings);
assertSetMultiBinding(module, AuditTrail.class, IndexAuditTrail.class);
}
public void testIndexAndLoggingAuditTrail() throws Exception {
Settings settings = Settings.builder()
.put(AuditTrailModule.ENABLED_SETTING.getKey(), true)
.put(AuditTrailModule.OUTPUTS_SETTING.getKey(), "index,logfile").build();
AuditTrailModule module = new AuditTrailModule(settings);
assertSetMultiBinding(module, AuditTrail.class, IndexAuditTrail.class, LoggingAuditTrail.class);
}
public void testUnknownOutput() throws Exception {
Settings settings = Settings.builder()
.put(AuditTrailModule.ENABLED_SETTING.getKey(), true)
.put(AuditTrailModule.OUTPUTS_SETTING.getKey(), "foo").build();
AuditTrailModule module = new AuditTrailModule(settings);
assertBindingFailure(module, "unknown audit trail output [foo]");
}
}

View File

@ -17,10 +17,12 @@ import org.elasticsearch.transport.TransportMessage;
import org.junit.Before; import org.junit.Before;
import java.net.InetAddress; import java.net.InetAddress;
import java.util.ArrayList;
import java.util.HashSet; import java.util.HashSet;
import java.util.List;
import java.util.Set; import java.util.Set;
import static java.util.Collections.unmodifiableSet; import static java.util.Collections.unmodifiableList;
import static org.mockito.Mockito.mock; import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyZeroInteractions; import static org.mockito.Mockito.verifyZeroInteractions;
@ -30,7 +32,7 @@ import static org.mockito.Mockito.when;
* *
*/ */
public class AuditTrailServiceTests extends ESTestCase { public class AuditTrailServiceTests extends ESTestCase {
private Set<AuditTrail> auditTrails; private List<AuditTrail> auditTrails;
private AuditTrailService service; private AuditTrailService service;
private AuthenticationToken token; private AuthenticationToken token;
@ -41,11 +43,11 @@ public class AuditTrailServiceTests extends ESTestCase {
@Before @Before
public void init() throws Exception { public void init() throws Exception {
Set<AuditTrail> auditTrailsBuilder = new HashSet<>(); List<AuditTrail> auditTrailsBuilder = new ArrayList<>();
for (int i = 0; i < randomIntBetween(1, 4); i++) { for (int i = 0; i < randomIntBetween(1, 4); i++) {
auditTrailsBuilder.add(mock(AuditTrail.class)); auditTrailsBuilder.add(mock(AuditTrail.class));
} }
auditTrails = unmodifiableSet(auditTrailsBuilder); auditTrails = unmodifiableList(auditTrailsBuilder);
securityLicenseState = mock(SecurityLicenseState.class); securityLicenseState = mock(SecurityLicenseState.class);
service = new AuditTrailService(Settings.EMPTY, auditTrails, securityLicenseState); service = new AuditTrailService(Settings.EMPTY, auditTrails, securityLicenseState);
auditingEnabled = randomBoolean(); auditingEnabled = randomBoolean();

View File

@ -192,7 +192,8 @@ public class XPackPlugin extends Plugin implements ScriptPlugin, ActionPlugin {
components.addAll(licensing.createComponents(clusterService, getClock(), env, resourceWatcherService, components.addAll(licensing.createComponents(clusterService, getClock(), env, resourceWatcherService,
security.getSecurityLicenseState())); security.getSecurityLicenseState()));
components.addAll(security.createComponents(internalClient, threadPool, resourceWatcherService, extensionsService.getExtensions())); components.addAll(security.createComponents(internalClient, threadPool, clusterService, resourceWatcherService,
extensionsService.getExtensions()));
// watcher http stuff // watcher http stuff
Map<String, HttpAuthFactory> httpAuthFactories = new HashMap<>(); Map<String, HttpAuthFactory> httpAuthFactories = new HashMap<>();