The configured role-mapping file must be valid. (elastic/x-pack-elasticsearch#1940)
This adds a bootstrap-check that makes it an error to configure a role mapping file that doesn't exist or cannot be parsed. We are still lenient on dynamic reload because (a) killing a running node is quite drastic (b) file writes aren't atomic, so we might be picking up a file that is half way through being written (etc). If you rely on the default role mapping filename, then it doesn't need to exist (because you might be using the role mapping API instead) but if it does exist it has to parse successfully Original commit: elastic/x-pack-elasticsearch@5424dea4c4
This commit is contained in:
parent
d57e38fbed
commit
1686add7ce
|
@ -5,6 +5,25 @@
|
|||
*/
|
||||
package org.elasticsearch.xpack.security;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.security.GeneralSecurityException;
|
||||
import java.time.Clock;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.function.UnaryOperator;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.apache.lucene.util.SetOnce;
|
||||
import org.elasticsearch.action.ActionListener;
|
||||
|
@ -35,6 +54,7 @@ import org.elasticsearch.common.settings.Setting.Property;
|
|||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.settings.SettingsFilter;
|
||||
import org.elasticsearch.common.util.BigArrays;
|
||||
import org.elasticsearch.common.util.CollectionUtils;
|
||||
import org.elasticsearch.common.util.concurrent.ThreadContext;
|
||||
import org.elasticsearch.common.xcontent.NamedXContentRegistry;
|
||||
import org.elasticsearch.env.Environment;
|
||||
|
@ -159,25 +179,6 @@ import org.elasticsearch.xpack.ssl.SSLService;
|
|||
import org.joda.time.DateTime;
|
||||
import org.joda.time.DateTimeZone;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.security.GeneralSecurityException;
|
||||
import java.time.Clock;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.function.UnaryOperator;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static java.util.Collections.emptyList;
|
||||
import static java.util.Collections.singletonList;
|
||||
import static org.elasticsearch.xpack.XPackSettings.HTTP_SSL_ENABLED;
|
||||
|
@ -496,13 +497,15 @@ public class Security implements ActionPlugin, IngestPlugin, NetworkPlugin {
|
|||
|
||||
public List<BootstrapCheck> getBootstrapChecks() {
|
||||
if (enabled) {
|
||||
return Arrays.asList(
|
||||
new SSLBootstrapCheck(sslService, settings, env),
|
||||
new TokenPassphraseBootstrapCheck(settings),
|
||||
new TokenSSLBootstrapCheck(settings),
|
||||
new PkiRealmBootstrapCheck(settings, sslService),
|
||||
new ContainerPasswordBootstrapCheck()
|
||||
final ArrayList<BootstrapCheck> checks = CollectionUtils.arrayAsArrayList(
|
||||
new SSLBootstrapCheck(sslService, settings, env),
|
||||
new TokenPassphraseBootstrapCheck(settings),
|
||||
new TokenSSLBootstrapCheck(settings),
|
||||
new PkiRealmBootstrapCheck(settings, sslService),
|
||||
new ContainerPasswordBootstrapCheck()
|
||||
);
|
||||
checks.addAll(InternalRealms.getBootstrapChecks(settings));
|
||||
return checks;
|
||||
} else {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
|
|
@ -5,7 +5,18 @@
|
|||
*/
|
||||
package org.elasticsearch.xpack.security.authc;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.elasticsearch.bootstrap.BootstrapCheck;
|
||||
import org.elasticsearch.common.settings.Setting;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.threadpool.ThreadPool;
|
||||
import org.elasticsearch.watcher.ResourceWatcherService;
|
||||
import org.elasticsearch.xpack.security.authc.esnative.NativeRealm;
|
||||
|
@ -14,16 +25,10 @@ import org.elasticsearch.xpack.security.authc.esnative.ReservedRealm;
|
|||
import org.elasticsearch.xpack.security.authc.file.FileRealm;
|
||||
import org.elasticsearch.xpack.security.authc.ldap.LdapRealm;
|
||||
import org.elasticsearch.xpack.security.authc.pki.PkiRealm;
|
||||
import org.elasticsearch.xpack.security.authc.support.RoleMappingFileBootstrapCheck;
|
||||
import org.elasticsearch.xpack.security.authc.support.mapper.NativeRoleMappingStore;
|
||||
import org.elasticsearch.xpack.ssl.SSLService;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Provides a single entry point into dealing with all standard XPack security {@link Realm realms}.
|
||||
* This class does not handle extensions.
|
||||
|
@ -78,7 +83,7 @@ public class InternalRealms {
|
|||
* This excludes the {@link ReservedRealm}, as it cannot be configured dynamically.
|
||||
* @return A map from <em>realm-type</em> to a collection of <code>Setting</code> objects.
|
||||
*/
|
||||
public static Map<String,Set<Setting<?>>> getSettings() {
|
||||
public static Map<String, Set<Setting<?>>> getSettings() {
|
||||
Map<String, Set<Setting<?>>> map = new HashMap<>();
|
||||
map.put(FileRealm.TYPE, FileRealm.getSettings());
|
||||
map.put(NativeRealm.TYPE, NativeRealm.getSettings());
|
||||
|
@ -91,4 +96,21 @@ public class InternalRealms {
|
|||
private InternalRealms() {
|
||||
}
|
||||
|
||||
public static List<BootstrapCheck> getBootstrapChecks(final Settings globalSettings) {
|
||||
final List<BootstrapCheck> checks = new ArrayList<>();
|
||||
final Map<String, Settings> settingsByRealm = RealmSettings.getRealmSettings(globalSettings);
|
||||
settingsByRealm.forEach((name, settings) -> {
|
||||
final RealmConfig realmConfig = new RealmConfig(name, settings, globalSettings, null);
|
||||
switch (realmConfig.type()) {
|
||||
case LdapRealm.AD_TYPE:
|
||||
case LdapRealm.LDAP_TYPE:
|
||||
case PkiRealm.TYPE:
|
||||
final BootstrapCheck check = RoleMappingFileBootstrapCheck.create(realmConfig);
|
||||
if (check != null) {
|
||||
checks.add(check);
|
||||
}
|
||||
}
|
||||
});
|
||||
return checks;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,6 +16,7 @@ public class RealmConfig {
|
|||
final String name;
|
||||
final boolean enabled;
|
||||
final int order;
|
||||
private final String type;
|
||||
final Settings settings;
|
||||
|
||||
private final Environment env;
|
||||
|
@ -35,6 +36,7 @@ public class RealmConfig {
|
|||
this.env = env;
|
||||
enabled = RealmSettings.ENABLED_SETTING.get(settings);
|
||||
order = RealmSettings.ORDER_SETTING.get(settings);
|
||||
type = RealmSettings.TYPE_SETTING.get(settings);
|
||||
this.threadContext = threadContext;
|
||||
}
|
||||
|
||||
|
@ -50,6 +52,10 @@ public class RealmConfig {
|
|||
return order;
|
||||
}
|
||||
|
||||
public String type() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public Settings settings() {
|
||||
return settings;
|
||||
}
|
||||
|
|
|
@ -5,11 +5,6 @@
|
|||
*/
|
||||
package org.elasticsearch.xpack.security.authc;
|
||||
|
||||
import org.elasticsearch.common.settings.AbstractScopedSettings;
|
||||
import org.elasticsearch.common.settings.Setting;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.xpack.extensions.XPackExtension;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
|
@ -17,8 +12,14 @@ import java.util.List;
|
|||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.elasticsearch.common.settings.AbstractScopedSettings;
|
||||
import org.elasticsearch.common.settings.Setting;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.xpack.extensions.XPackExtension;
|
||||
|
||||
import static org.elasticsearch.common.Strings.isNullOrEmpty;
|
||||
import static org.elasticsearch.xpack.security.Security.setting;
|
||||
|
||||
|
@ -71,6 +72,16 @@ public class RealmSettings {
|
|||
return settings.getByPrefix(RealmSettings.PREFIX);
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts the realm settings from a global settings object.
|
||||
* Returns a Map of realm-name to realm-settings.
|
||||
*/
|
||||
public static Map<String, Settings> getRealmSettings(Settings globalSettings) {
|
||||
Settings realmsSettings = RealmSettings.get(globalSettings);
|
||||
return realmsSettings.names().stream()
|
||||
.collect(Collectors.toMap(Function.identity(), realmsSettings::getAsSettings));
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the child {@link Setting} for the provided realm into a fully scoped key for use in an error message.
|
||||
* @see #PREFIX
|
||||
|
|
|
@ -5,22 +5,6 @@
|
|||
*/
|
||||
package org.elasticsearch.xpack.security.authc.support;
|
||||
|
||||
import com.unboundid.ldap.sdk.DN;
|
||||
import com.unboundid.ldap.sdk.LDAPException;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.apache.logging.log4j.message.ParameterizedMessage;
|
||||
import org.apache.logging.log4j.util.Supplier;
|
||||
import org.elasticsearch.ElasticsearchException;
|
||||
import org.elasticsearch.action.ActionListener;
|
||||
import org.elasticsearch.common.settings.Setting;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.env.Environment;
|
||||
import org.elasticsearch.watcher.FileChangesListener;
|
||||
import org.elasticsearch.watcher.FileWatcher;
|
||||
import org.elasticsearch.watcher.ResourceWatcherService;
|
||||
import org.elasticsearch.xpack.XPackPlugin;
|
||||
import org.elasticsearch.xpack.security.authc.RealmConfig;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.file.Files;
|
||||
|
@ -37,6 +21,25 @@ import java.util.Set;
|
|||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
import java.util.function.Function;
|
||||
|
||||
import com.unboundid.ldap.sdk.DN;
|
||||
import com.unboundid.ldap.sdk.LDAPException;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.apache.logging.log4j.message.ParameterizedMessage;
|
||||
import org.apache.logging.log4j.util.Supplier;
|
||||
import org.apache.lucene.util.SetOnce;
|
||||
import org.elasticsearch.ElasticsearchException;
|
||||
import org.elasticsearch.action.ActionListener;
|
||||
import org.elasticsearch.bootstrap.BootstrapCheck;
|
||||
import org.elasticsearch.common.settings.Setting;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.env.Environment;
|
||||
import org.elasticsearch.watcher.FileChangesListener;
|
||||
import org.elasticsearch.watcher.FileWatcher;
|
||||
import org.elasticsearch.watcher.ResourceWatcherService;
|
||||
import org.elasticsearch.xpack.XPackPlugin;
|
||||
import org.elasticsearch.xpack.security.authc.RealmConfig;
|
||||
import org.yaml.snakeyaml.error.YAMLException;
|
||||
|
||||
import static java.util.Collections.emptyMap;
|
||||
import static java.util.Collections.unmodifiableMap;
|
||||
import static org.elasticsearch.xpack.security.authc.ldap.support.LdapUtils.dn;
|
||||
|
@ -57,20 +60,18 @@ public class DnRoleMapper implements UserRoleMapper {
|
|||
protected final Logger logger;
|
||||
protected final RealmConfig config;
|
||||
|
||||
private final String realmType;
|
||||
private final Path file;
|
||||
private final boolean useUnmappedGroupsAsRoles;
|
||||
private final CopyOnWriteArrayList<Runnable> listeners = new CopyOnWriteArrayList<>();
|
||||
private volatile Map<DN, Set<String>> dnRoles;
|
||||
|
||||
public DnRoleMapper(String realmType, RealmConfig config, ResourceWatcherService watcherService) {
|
||||
this.realmType = realmType;
|
||||
public DnRoleMapper(RealmConfig config, ResourceWatcherService watcherService) {
|
||||
this.config = config;
|
||||
this.logger = config.logger(getClass());
|
||||
|
||||
useUnmappedGroupsAsRoles = USE_UNMAPPED_GROUPS_AS_ROLES_SETTING.get(config.settings());
|
||||
file = resolveFile(config.settings(), config.env());
|
||||
dnRoles = parseFileLenient(file, logger, realmType, config.name());
|
||||
dnRoles = parseFileLenient(file, logger, config.type(), config.name());
|
||||
FileWatcher watcher = new FileWatcher(file.getParent());
|
||||
watcher.addListener(new FileListener());
|
||||
try {
|
||||
|
@ -101,7 +102,7 @@ public class DnRoleMapper implements UserRoleMapper {
|
|||
*/
|
||||
public static Map<DN, Set<String>> parseFileLenient(Path path, Logger logger, String realmType, String realmName) {
|
||||
try {
|
||||
return parseFile(path, logger, realmType, realmName);
|
||||
return parseFile(path, logger, realmType, realmName, false);
|
||||
} catch (Exception e) {
|
||||
logger.error(
|
||||
(Supplier<?>) () -> new ParameterizedMessage(
|
||||
|
@ -110,14 +111,20 @@ public class DnRoleMapper implements UserRoleMapper {
|
|||
}
|
||||
}
|
||||
|
||||
public static Map<DN, Set<String>> parseFile(Path path, Logger logger, String realmType, String realmName) {
|
||||
public static Map<DN, Set<String>> parseFile(Path path, Logger logger, String realmType, String realmName, boolean strict) {
|
||||
|
||||
logger.trace("reading realm [{}/{}] role mappings file [{}]...", realmType, realmName, path.toAbsolutePath());
|
||||
|
||||
if (!Files.exists(path)) {
|
||||
logger.warn("Role mapping file [{}] for realm [{}] does not exist. Role mapping will be skipped.",
|
||||
if (Files.exists(path) == false) {
|
||||
final ParameterizedMessage message = new ParameterizedMessage(
|
||||
"Role mapping file [{}] for realm [{}] does not exist.",
|
||||
path.toAbsolutePath(), realmName);
|
||||
return emptyMap();
|
||||
if (strict) {
|
||||
throw new ElasticsearchException(message.getFormattedMessage());
|
||||
} else {
|
||||
logger.warn(message.getFormattedMessage() + " Role mapping will be skipped.");
|
||||
return emptyMap();
|
||||
}
|
||||
}
|
||||
|
||||
try (InputStream in = Files.newInputStream(path)) {
|
||||
|
@ -136,14 +143,18 @@ public class DnRoleMapper implements UserRoleMapper {
|
|||
}
|
||||
dnRoles.add(role);
|
||||
} catch (LDAPException e) {
|
||||
logger.error(new ParameterizedMessage(
|
||||
"invalid DN [{}] found in [{}] role mappings [{}] for realm [{}/{}]. skipping... ",
|
||||
providedDn,
|
||||
realmType,
|
||||
path.toAbsolutePath(),
|
||||
realmType,
|
||||
realmName),
|
||||
e);
|
||||
ParameterizedMessage message = new ParameterizedMessage(
|
||||
"invalid DN [{}] found in [{}] role mappings [{}] for realm [{}/{}].",
|
||||
providedDn,
|
||||
realmType,
|
||||
path.toAbsolutePath(),
|
||||
realmType,
|
||||
realmName);
|
||||
if (strict) {
|
||||
throw new ElasticsearchException(message.getFormattedMessage(), e);
|
||||
} else {
|
||||
logger.error(message.getFormattedMessage() + " skipping...", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -152,7 +163,7 @@ public class DnRoleMapper implements UserRoleMapper {
|
|||
logger.debug("[{}] role mappings found in file [{}] for realm [{}/{}]", dnToRoles.size(), path.toAbsolutePath(), realmType,
|
||||
realmName);
|
||||
return unmodifiableMap(dnToRoles);
|
||||
} catch (IOException e) {
|
||||
} catch (IOException | YAMLException e) {
|
||||
throw new ElasticsearchException("could not read realm [" + realmType + "/" + realmName + "] role mappings file [" +
|
||||
path.toAbsolutePath() + "]", e);
|
||||
}
|
||||
|
@ -166,7 +177,7 @@ public class DnRoleMapper implements UserRoleMapper {
|
|||
public void resolveRoles(UserData user, ActionListener<Set<String>> listener) {
|
||||
try {
|
||||
listener.onResponse(resolveRoles(user.getDn(), user.getGroups()));
|
||||
} catch( Exception e) {
|
||||
} catch (Exception e) {
|
||||
listener.onFailure(e);
|
||||
}
|
||||
}
|
||||
|
@ -185,8 +196,8 @@ public class DnRoleMapper implements UserRoleMapper {
|
|||
}
|
||||
}
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("the roles [{}], are mapped from these [{}] groups [{}] using file [{}] for realm [{}/{}]", roles, realmType,
|
||||
groupDns, file.getFileName(), realmType, config.name());
|
||||
logger.debug("the roles [{}], are mapped from these [{}] groups [{}] using file [{}] for realm [{}/{}]", roles, config.type(),
|
||||
groupDns, file.getFileName(), config.type(), config.name());
|
||||
}
|
||||
|
||||
DN userDn = dn(userDnString);
|
||||
|
@ -197,7 +208,7 @@ public class DnRoleMapper implements UserRoleMapper {
|
|||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("the roles [{}], are mapped from the user [{}] using file [{}] for realm [{}/{}]",
|
||||
(rolesMappedToUserDn == null) ? Collections.emptySet() : rolesMappedToUserDn, userDnString, file.getFileName(),
|
||||
realmType, config.name());
|
||||
config.type(), config.name());
|
||||
}
|
||||
return roles;
|
||||
}
|
||||
|
@ -225,8 +236,8 @@ public class DnRoleMapper implements UserRoleMapper {
|
|||
public void onFileChanged(Path file) {
|
||||
if (file.equals(DnRoleMapper.this.file)) {
|
||||
logger.info("role mappings file [{}] changed for realm [{}/{}]. updating mappings...", file.toAbsolutePath(),
|
||||
realmType, config.name());
|
||||
dnRoles = parseFileLenient(file, logger, realmType, config.name());
|
||||
config.type(), config.name());
|
||||
dnRoles = parseFileLenient(file, logger, config.type(), config.name());
|
||||
notifyRefresh();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,58 @@
|
|||
/*
|
||||
* 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.authc.support;
|
||||
|
||||
import java.nio.file.Path;
|
||||
|
||||
import org.apache.lucene.util.SetOnce;
|
||||
import org.elasticsearch.bootstrap.BootstrapCheck;
|
||||
import org.elasticsearch.xpack.security.authc.RealmConfig;
|
||||
|
||||
/**
|
||||
* A BootstrapCheck that {@link DnRoleMapper} files exist and are valid (valid YAML and valid DNs)
|
||||
*/
|
||||
public class RoleMappingFileBootstrapCheck implements BootstrapCheck {
|
||||
|
||||
private final RealmConfig realmConfig;
|
||||
private final Path path;
|
||||
|
||||
private final SetOnce<String> error = new SetOnce<>();
|
||||
|
||||
public RoleMappingFileBootstrapCheck(RealmConfig config, Path path) {
|
||||
this.realmConfig = config;
|
||||
this.path = path;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean check() {
|
||||
try {
|
||||
DnRoleMapper.parseFile(path, realmConfig.logger(getClass()), realmConfig.type(), realmConfig.name(), true);
|
||||
return false;
|
||||
} catch (Exception e) {
|
||||
error.set(e.getMessage());
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public String errorMessage() {
|
||||
return error.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean alwaysEnforce() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public static BootstrapCheck create(RealmConfig realmConfig) {
|
||||
if (realmConfig.enabled() && DnRoleMapper.ROLE_MAPPING_FILE_SETTING.exists(realmConfig.settings())) {
|
||||
Path file = DnRoleMapper.resolveFile(realmConfig.settings(), realmConfig.env());
|
||||
return new RoleMappingFileBootstrapCheck(realmConfig, file);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -34,7 +34,7 @@ public class CompositeRoleMapper implements UserRoleMapper {
|
|||
public CompositeRoleMapper(String realmType, RealmConfig realmConfig,
|
||||
ResourceWatcherService watcherService,
|
||||
NativeRoleMappingStore nativeRoleMappingStore) {
|
||||
this(new DnRoleMapper(realmType, realmConfig, watcherService), nativeRoleMappingStore);
|
||||
this(new DnRoleMapper(realmConfig, watcherService), nativeRoleMappingStore);
|
||||
}
|
||||
|
||||
private CompositeRoleMapper(UserRoleMapper... delegates) {
|
||||
|
|
|
@ -136,7 +136,7 @@ public class ActiveDirectoryRealmTests extends ESTestCase {
|
|||
Settings settings = settings();
|
||||
RealmConfig config = new RealmConfig("testAuthenticateUserPrincipleName", settings, globalSettings, new Environment(globalSettings), new ThreadContext(globalSettings));
|
||||
ActiveDirectorySessionFactory sessionFactory = new ActiveDirectorySessionFactory(config, sslService);
|
||||
DnRoleMapper roleMapper = new DnRoleMapper(LdapRealm.AD_TYPE, config, resourceWatcherService);
|
||||
DnRoleMapper roleMapper = new DnRoleMapper(config, resourceWatcherService);
|
||||
LdapRealm realm = new LdapRealm(LdapRealm.AD_TYPE, config, sessionFactory, roleMapper, threadPool);
|
||||
|
||||
PlainActionFuture<AuthenticationResult> future = new PlainActionFuture<>();
|
||||
|
@ -152,7 +152,7 @@ public class ActiveDirectoryRealmTests extends ESTestCase {
|
|||
Settings settings = settings();
|
||||
RealmConfig config = new RealmConfig("testAuthenticateSAMAccountName", settings, globalSettings, new Environment(globalSettings), new ThreadContext(globalSettings));
|
||||
ActiveDirectorySessionFactory sessionFactory = new ActiveDirectorySessionFactory(config, sslService);
|
||||
DnRoleMapper roleMapper = new DnRoleMapper(LdapRealm.AD_TYPE, config, resourceWatcherService);
|
||||
DnRoleMapper roleMapper = new DnRoleMapper(config, resourceWatcherService);
|
||||
LdapRealm realm = new LdapRealm(LdapRealm.AD_TYPE, config, sessionFactory, roleMapper, threadPool);
|
||||
|
||||
// Thor does not have a UPN of form CN=Thor@ad.test.elasticsearch.com
|
||||
|
@ -176,7 +176,7 @@ public class ActiveDirectoryRealmTests extends ESTestCase {
|
|||
Settings settings = settings();
|
||||
RealmConfig config = new RealmConfig("testAuthenticateCachesSuccesfulAuthentications", settings, globalSettings, new Environment(globalSettings), new ThreadContext(globalSettings));
|
||||
ActiveDirectorySessionFactory sessionFactory = spy(new ActiveDirectorySessionFactory(config, sslService));
|
||||
DnRoleMapper roleMapper = new DnRoleMapper(LdapRealm.AD_TYPE, config, resourceWatcherService);
|
||||
DnRoleMapper roleMapper = new DnRoleMapper(config, resourceWatcherService);
|
||||
LdapRealm realm = new LdapRealm(LdapRealm.AD_TYPE, config, sessionFactory, roleMapper, threadPool);
|
||||
|
||||
int count = randomIntBetween(2, 10);
|
||||
|
@ -194,7 +194,7 @@ public class ActiveDirectoryRealmTests extends ESTestCase {
|
|||
Settings settings = settings(Settings.builder().put(CachingUsernamePasswordRealm.CACHE_TTL_SETTING.getKey(), -1).build());
|
||||
RealmConfig config = new RealmConfig("testAuthenticateCachingCanBeDisabled", settings, globalSettings, new Environment(globalSettings), new ThreadContext(globalSettings));
|
||||
ActiveDirectorySessionFactory sessionFactory = spy(new ActiveDirectorySessionFactory(config, sslService));
|
||||
DnRoleMapper roleMapper = new DnRoleMapper(LdapRealm.AD_TYPE, config, resourceWatcherService);
|
||||
DnRoleMapper roleMapper = new DnRoleMapper(config, resourceWatcherService);
|
||||
LdapRealm realm = new LdapRealm(LdapRealm.AD_TYPE, config, sessionFactory, roleMapper, threadPool);
|
||||
|
||||
int count = randomIntBetween(2, 10);
|
||||
|
@ -212,7 +212,7 @@ public class ActiveDirectoryRealmTests extends ESTestCase {
|
|||
Settings settings = settings();
|
||||
RealmConfig config = new RealmConfig("testAuthenticateCachingClearsCacheOnRoleMapperRefresh", settings, globalSettings, new Environment(globalSettings), new ThreadContext(globalSettings));
|
||||
ActiveDirectorySessionFactory sessionFactory = spy(new ActiveDirectorySessionFactory(config, sslService));
|
||||
DnRoleMapper roleMapper = new DnRoleMapper(LdapRealm.AD_TYPE, config, resourceWatcherService);
|
||||
DnRoleMapper roleMapper = new DnRoleMapper(config, resourceWatcherService);
|
||||
LdapRealm realm = new LdapRealm(LdapRealm.AD_TYPE, config, sessionFactory, roleMapper, threadPool);
|
||||
|
||||
int count = randomIntBetween(2, 10);
|
||||
|
@ -243,7 +243,7 @@ public class ActiveDirectoryRealmTests extends ESTestCase {
|
|||
.build());
|
||||
RealmConfig config = new RealmConfig("testRealmMapsGroupsToRoles", settings, globalSettings, new Environment(globalSettings), new ThreadContext(globalSettings));
|
||||
ActiveDirectorySessionFactory sessionFactory = new ActiveDirectorySessionFactory(config, sslService);
|
||||
DnRoleMapper roleMapper = new DnRoleMapper(LdapRealm.AD_TYPE, config, resourceWatcherService);
|
||||
DnRoleMapper roleMapper = new DnRoleMapper(config, resourceWatcherService);
|
||||
LdapRealm realm = new LdapRealm(LdapRealm.AD_TYPE, config, sessionFactory, roleMapper, threadPool);
|
||||
|
||||
PlainActionFuture<AuthenticationResult> future = new PlainActionFuture<>();
|
||||
|
@ -259,7 +259,7 @@ public class ActiveDirectoryRealmTests extends ESTestCase {
|
|||
.build());
|
||||
RealmConfig config = new RealmConfig("testRealmMapsGroupsToRoles", settings, globalSettings, new Environment(globalSettings), new ThreadContext(globalSettings));
|
||||
ActiveDirectorySessionFactory sessionFactory = new ActiveDirectorySessionFactory(config, sslService);
|
||||
DnRoleMapper roleMapper = new DnRoleMapper(LdapRealm.AD_TYPE, config, resourceWatcherService);
|
||||
DnRoleMapper roleMapper = new DnRoleMapper(config, resourceWatcherService);
|
||||
LdapRealm realm = new LdapRealm(LdapRealm.AD_TYPE, config, sessionFactory, roleMapper, threadPool);
|
||||
|
||||
PlainActionFuture<AuthenticationResult> future = new PlainActionFuture<>();
|
||||
|
@ -278,7 +278,7 @@ public class ActiveDirectoryRealmTests extends ESTestCase {
|
|||
RealmConfig config = new RealmConfig("testRealmUsageStats", settings, globalSettings, new Environment(globalSettings),
|
||||
new ThreadContext(globalSettings));
|
||||
ActiveDirectorySessionFactory sessionFactory = new ActiveDirectorySessionFactory(config, sslService);
|
||||
DnRoleMapper roleMapper = new DnRoleMapper(LdapRealm.AD_TYPE, config, resourceWatcherService);
|
||||
DnRoleMapper roleMapper = new DnRoleMapper(config, resourceWatcherService);
|
||||
LdapRealm realm = new LdapRealm(LdapRealm.AD_TYPE, config, sessionFactory, roleMapper, threadPool);
|
||||
|
||||
Map<String, Object> stats = realm.usageStats();
|
||||
|
|
|
@ -285,7 +285,7 @@ public class LdapRealmTests extends LdapTestCase {
|
|||
|
||||
LdapSessionFactory ldapFactory = new LdapSessionFactory(config, sslService);
|
||||
LdapRealm ldap = new LdapRealm(LdapRealm.LDAP_TYPE, config, ldapFactory,
|
||||
new DnRoleMapper(LdapRealm.LDAP_TYPE, config, resourceWatcherService), threadPool);
|
||||
new DnRoleMapper(config, resourceWatcherService), threadPool);
|
||||
|
||||
PlainActionFuture<AuthenticationResult> future = new PlainActionFuture<>();
|
||||
ldap.authenticate(new UsernamePasswordToken("Horatio Hornblower", new SecureString(PASSWORD)), future);
|
||||
|
@ -346,7 +346,7 @@ public class LdapRealmTests extends LdapTestCase {
|
|||
|
||||
LdapSessionFactory ldapFactory = new LdapSessionFactory(config, sslService);
|
||||
LdapRealm realm = new LdapRealm(LdapRealm.LDAP_TYPE, config, ldapFactory,
|
||||
new DnRoleMapper(LdapRealm.LDAP_TYPE, config, resourceWatcherService), threadPool);
|
||||
new DnRoleMapper(config, resourceWatcherService), threadPool);
|
||||
|
||||
Map<String, Object> stats = realm.usageStats();
|
||||
assertThat(stats, is(notNullValue()));
|
||||
|
|
|
@ -16,7 +16,6 @@ import org.elasticsearch.common.settings.Settings;
|
|||
import org.elasticsearch.common.unit.TimeValue;
|
||||
import org.elasticsearch.common.util.concurrent.ThreadContext;
|
||||
import org.elasticsearch.xpack.security.authc.RealmConfig;
|
||||
import org.elasticsearch.xpack.security.authc.ldap.LdapRealm;
|
||||
import org.elasticsearch.xpack.security.authc.ldap.LdapSessionFactory;
|
||||
import org.elasticsearch.xpack.security.authc.support.DnRoleMapper;
|
||||
import org.elasticsearch.test.ESTestCase;
|
||||
|
@ -138,7 +137,7 @@ public abstract class LdapTestCase extends ESTestCase {
|
|||
Settings global = Settings.builder().put("path.home", createTempDir()).build();
|
||||
RealmConfig config = new RealmConfig("ldap1", settings, global, new ThreadContext(Settings.EMPTY));
|
||||
|
||||
return new DnRoleMapper(LdapRealm.LDAP_TYPE, config, resourceWatcherService);
|
||||
return new DnRoleMapper(config, resourceWatcherService);
|
||||
}
|
||||
|
||||
protected LdapSession session(SessionFactory factory, String username, SecureString password) {
|
||||
|
|
|
@ -5,22 +5,6 @@
|
|||
*/
|
||||
package org.elasticsearch.xpack.security.authc.support;
|
||||
|
||||
import com.unboundid.ldap.sdk.DN;
|
||||
import org.apache.logging.log4j.Level;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.util.concurrent.ThreadContext;
|
||||
import org.elasticsearch.env.Environment;
|
||||
import org.elasticsearch.xpack.security.audit.logfile.CapturingLogger;
|
||||
import org.elasticsearch.xpack.security.authc.RealmConfig;
|
||||
import org.elasticsearch.xpack.security.authc.ldap.LdapRealm;
|
||||
import org.elasticsearch.test.ESTestCase;
|
||||
import org.elasticsearch.threadpool.TestThreadPool;
|
||||
import org.elasticsearch.threadpool.ThreadPool;
|
||||
import org.elasticsearch.watcher.ResourceWatcherService;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
@ -36,14 +20,33 @@ import java.util.Set;
|
|||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import com.unboundid.ldap.sdk.DN;
|
||||
import org.apache.logging.log4j.Level;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.elasticsearch.ElasticsearchException;
|
||||
import org.elasticsearch.bootstrap.BootstrapCheck;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.util.concurrent.ThreadContext;
|
||||
import org.elasticsearch.env.Environment;
|
||||
import org.elasticsearch.test.ESTestCase;
|
||||
import org.elasticsearch.threadpool.TestThreadPool;
|
||||
import org.elasticsearch.threadpool.ThreadPool;
|
||||
import org.elasticsearch.watcher.ResourceWatcherService;
|
||||
import org.elasticsearch.xpack.security.audit.logfile.CapturingLogger;
|
||||
import org.elasticsearch.xpack.security.authc.RealmConfig;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
|
||||
import static org.hamcrest.Matchers.contains;
|
||||
import static org.hamcrest.Matchers.containsInAnyOrder;
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
import static org.hamcrest.Matchers.hasItem;
|
||||
import static org.hamcrest.Matchers.hasItems;
|
||||
import static org.hamcrest.Matchers.hasKey;
|
||||
import static org.hamcrest.Matchers.hasSize;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
import static org.hamcrest.Matchers.not;
|
||||
import static org.hamcrest.Matchers.notNullValue;
|
||||
|
||||
public class DnRoleMapperTests extends ESTestCase {
|
||||
|
@ -186,6 +189,7 @@ public class DnRoleMapperTests extends ESTestCase {
|
|||
|
||||
public void testAddNullListener() throws Exception {
|
||||
Path file = env.configFile().resolve("test_role_mapping.yml");
|
||||
Files.write(file, Collections.singleton(""));
|
||||
ResourceWatcherService watcherService = new ResourceWatcherService(settings, threadPool);
|
||||
DnRoleMapper mapper = createMapper(file, watcherService);
|
||||
NullPointerException e = expectThrows(NullPointerException.class, () -> mapper.addListener(null));
|
||||
|
@ -195,7 +199,7 @@ public class DnRoleMapperTests extends ESTestCase {
|
|||
public void testParseFile() throws Exception {
|
||||
Path file = getDataPath("role_mapping.yml");
|
||||
Logger logger = CapturingLogger.newCapturingLogger(Level.INFO);
|
||||
Map<DN, Set<String>> mappings = DnRoleMapper.parseFile(file, logger, "_type", "_name");
|
||||
Map<DN, Set<String>> mappings = DnRoleMapper.parseFile(file, logger, "_type", "_name", false);
|
||||
assertThat(mappings, notNullValue());
|
||||
assertThat(mappings.size(), is(3));
|
||||
|
||||
|
@ -225,7 +229,7 @@ public class DnRoleMapperTests extends ESTestCase {
|
|||
Path file = createTempDir().resolve("foo.yaml");
|
||||
Files.createFile(file);
|
||||
Logger logger = CapturingLogger.newCapturingLogger(Level.DEBUG);
|
||||
Map<DN, Set<String>> mappings = DnRoleMapper.parseFile(file, logger, "_type", "_name");
|
||||
Map<DN, Set<String>> mappings = DnRoleMapper.parseFile(file, logger, "_type", "_name", false);
|
||||
assertThat(mappings, notNullValue());
|
||||
assertThat(mappings.isEmpty(), is(true));
|
||||
List<String> events = CapturingLogger.output(logger.getName(), Level.DEBUG);
|
||||
|
@ -236,9 +240,16 @@ public class DnRoleMapperTests extends ESTestCase {
|
|||
public void testParseFile_WhenFileDoesNotExist() throws Exception {
|
||||
Path file = createTempDir().resolve(randomAlphaOfLength(10));
|
||||
Logger logger = CapturingLogger.newCapturingLogger(Level.INFO);
|
||||
Map<DN, Set<String>> mappings = DnRoleMapper.parseFile(file, logger, "_type", "_name");
|
||||
Map<DN, Set<String>> mappings = DnRoleMapper.parseFile(file, logger, "_type", "_name", false);
|
||||
assertThat(mappings, notNullValue());
|
||||
assertThat(mappings.isEmpty(), is(true));
|
||||
|
||||
final ElasticsearchException exception = expectThrows(ElasticsearchException.class, () -> {
|
||||
DnRoleMapper.parseFile(file, logger, "_type", "_name", true);
|
||||
});
|
||||
assertThat(exception.getMessage(), containsString(file.toString()));
|
||||
assertThat(exception.getMessage(), containsString("does not exist"));
|
||||
assertThat(exception.getMessage(), containsString("_name"));
|
||||
}
|
||||
|
||||
public void testParseFile_WhenCannotReadFile() throws Exception {
|
||||
|
@ -247,7 +258,7 @@ public class DnRoleMapperTests extends ESTestCase {
|
|||
Files.write(file, Collections.singletonList("aldlfkjldjdflkjd"), StandardCharsets.UTF_16);
|
||||
Logger logger = CapturingLogger.newCapturingLogger(Level.INFO);
|
||||
try {
|
||||
DnRoleMapper.parseFile(file, logger, "_type", "_name");
|
||||
DnRoleMapper.parseFile(file, logger, "_type", "_name", false);
|
||||
fail("expected a parse failure");
|
||||
} catch (Exception e) {
|
||||
this.logger.info("expected", e);
|
||||
|
@ -274,7 +285,7 @@ public class DnRoleMapperTests extends ESTestCase {
|
|||
.build();
|
||||
RealmConfig config = new RealmConfig("ldap1", ldapSettings, settings, new ThreadContext(Settings.EMPTY));
|
||||
|
||||
DnRoleMapper mapper = new DnRoleMapper(LdapRealm.LDAP_TYPE, config, new ResourceWatcherService(settings, threadPool));
|
||||
DnRoleMapper mapper = new DnRoleMapper(config, new ResourceWatcherService(settings, threadPool));
|
||||
|
||||
Set<String> roles = mapper.resolveRoles("", Arrays.asList(STARK_GROUP_DNS));
|
||||
|
||||
|
@ -286,9 +297,9 @@ public class DnRoleMapperTests extends ESTestCase {
|
|||
Settings ldapSettings = Settings.builder()
|
||||
.put(USE_UNMAPPED_GROUPS_AS_ROLES_SETTING_KEY, true)
|
||||
.build();
|
||||
RealmConfig config = new RealmConfig("ldap1", ldapSettings, settings, new ThreadContext(Settings.EMPTY));;
|
||||
RealmConfig config = new RealmConfig("ldap1", ldapSettings, settings, new ThreadContext(Settings.EMPTY));
|
||||
|
||||
DnRoleMapper mapper = new DnRoleMapper(LdapRealm.LDAP_TYPE, config, new ResourceWatcherService(settings, threadPool));
|
||||
DnRoleMapper mapper = new DnRoleMapper(config, new ResourceWatcherService(settings, threadPool));
|
||||
|
||||
Set<String> roles = mapper.resolveRoles("", Arrays.asList(STARK_GROUP_DNS));
|
||||
assertThat(roles, hasItems("genius", "billionaire", "playboy", "philanthropist", "shield", "avengers"));
|
||||
|
@ -300,9 +311,9 @@ public class DnRoleMapperTests extends ESTestCase {
|
|||
.put(ROLE_MAPPING_FILE_SETTING, file.toAbsolutePath())
|
||||
.put(USE_UNMAPPED_GROUPS_AS_ROLES_SETTING_KEY, false)
|
||||
.build();
|
||||
RealmConfig config = new RealmConfig("ldap-userdn-role", ldapSettings, settings, new ThreadContext(Settings.EMPTY));;
|
||||
RealmConfig config = new RealmConfig("ldap-userdn-role", ldapSettings, settings, new ThreadContext(Settings.EMPTY));
|
||||
|
||||
DnRoleMapper mapper = new DnRoleMapper(LdapRealm.LDAP_TYPE, config, new ResourceWatcherService(settings, threadPool));
|
||||
DnRoleMapper mapper = new DnRoleMapper(config, new ResourceWatcherService(settings, threadPool));
|
||||
|
||||
Set<String> roles = mapper.resolveRoles("cn=Horatio Hornblower,ou=people,o=sevenSeas", Collections.<String>emptyList());
|
||||
assertThat(roles, hasItem("avenger"));
|
||||
|
@ -313,6 +324,6 @@ public class DnRoleMapperTests extends ESTestCase {
|
|||
.put("files.role_mapping", file.toAbsolutePath())
|
||||
.build();
|
||||
RealmConfig config = new RealmConfig("ad-group-mapper-test", realmSettings, settings, env, new ThreadContext(Settings.EMPTY));
|
||||
return new DnRoleMapper(randomBoolean() ? LdapRealm.AD_TYPE : LdapRealm.LDAP_TYPE, config, watcherService);
|
||||
return new DnRoleMapper(config, watcherService);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,103 @@
|
|||
/*
|
||||
* 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.authc.support;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Collections;
|
||||
|
||||
import org.elasticsearch.bootstrap.BootstrapCheck;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.util.concurrent.ThreadContext;
|
||||
import org.elasticsearch.test.ESTestCase;
|
||||
import org.elasticsearch.xpack.security.authc.RealmConfig;
|
||||
import org.junit.Before;
|
||||
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
import static org.hamcrest.Matchers.notNullValue;
|
||||
|
||||
public class RoleMappingFileBootstrapCheckTests extends ESTestCase {
|
||||
|
||||
private static final String ROLE_MAPPING_FILE_SETTING = DnRoleMapper.ROLE_MAPPING_FILE_SETTING.getKey();
|
||||
|
||||
protected Settings settings;
|
||||
|
||||
@Before
|
||||
public void init() throws IOException {
|
||||
settings = Settings.builder()
|
||||
.put("resource.reload.interval.high", "100ms")
|
||||
.put("path.home", createTempDir())
|
||||
.build();
|
||||
}
|
||||
|
||||
public void testBootstrapCheckOfValidFile() {
|
||||
Path file = getDataPath("role_mapping.yml");
|
||||
Settings ldapSettings = Settings.builder()
|
||||
.put(ROLE_MAPPING_FILE_SETTING, file.toAbsolutePath())
|
||||
.build();
|
||||
RealmConfig config = new RealmConfig("ldap1", ldapSettings, settings, new ThreadContext(Settings.EMPTY));
|
||||
final BootstrapCheck check = RoleMappingFileBootstrapCheck.create(config);
|
||||
assertThat(check, notNullValue());
|
||||
assertThat(check.alwaysEnforce(), equalTo(true));
|
||||
assertThat(check.check(), equalTo(false));
|
||||
}
|
||||
|
||||
public void testBootstrapCheckOfMissingFile() {
|
||||
final String fileName = randomAlphaOfLength(10);
|
||||
Path file = createTempDir().resolve(fileName);
|
||||
Settings ldapSettings = Settings.builder()
|
||||
.put(ROLE_MAPPING_FILE_SETTING, file.toAbsolutePath())
|
||||
.build();
|
||||
RealmConfig config = new RealmConfig("the-realm-name", ldapSettings, settings, new ThreadContext(Settings.EMPTY));
|
||||
final BootstrapCheck check = RoleMappingFileBootstrapCheck.create(config);
|
||||
assertThat(check, notNullValue());
|
||||
assertThat(check.alwaysEnforce(), equalTo(true));
|
||||
assertThat(check.check(), equalTo(true));
|
||||
assertThat(check.errorMessage(), containsString("the-realm-name"));
|
||||
assertThat(check.errorMessage(), containsString(fileName));
|
||||
assertThat(check.errorMessage(), containsString("does not exist"));
|
||||
}
|
||||
|
||||
public void testBootstrapCheckWithInvalidYaml() throws IOException {
|
||||
Path file = createTempFile("", ".yml");
|
||||
// writing in utf_16 should cause a parsing error as we try to read the file in utf_8
|
||||
Files.write(file, Collections.singletonList("junk"), StandardCharsets.UTF_16);
|
||||
|
||||
Settings ldapSettings = Settings.builder()
|
||||
.put(ROLE_MAPPING_FILE_SETTING, file.toAbsolutePath())
|
||||
.build();
|
||||
RealmConfig config = new RealmConfig("the-realm-name", ldapSettings, settings, new ThreadContext(Settings.EMPTY));
|
||||
final BootstrapCheck check = RoleMappingFileBootstrapCheck.create(config);
|
||||
assertThat(check, notNullValue());
|
||||
assertThat(check.alwaysEnforce(), equalTo(true));
|
||||
assertThat(check.check(), equalTo(true));
|
||||
assertThat(check.errorMessage(), containsString("the-realm-name"));
|
||||
assertThat(check.errorMessage(), containsString(file.toString()));
|
||||
assertThat(check.errorMessage(), containsString("could not read"));
|
||||
}
|
||||
|
||||
public void testBootstrapCheckWithInvalidDn() throws IOException {
|
||||
Path file = createTempFile("", ".yml");
|
||||
// A DN must have at least 1 '=' symbol
|
||||
Files.write(file, Collections.singletonList("role: not-a-dn"));
|
||||
|
||||
Settings ldapSettings = Settings.builder()
|
||||
.put(ROLE_MAPPING_FILE_SETTING, file.toAbsolutePath())
|
||||
.build();
|
||||
RealmConfig config = new RealmConfig("the-realm-name", ldapSettings, settings, new ThreadContext(Settings.EMPTY));
|
||||
final BootstrapCheck check = RoleMappingFileBootstrapCheck.create(config);
|
||||
assertThat(check, notNullValue());
|
||||
assertThat(check.alwaysEnforce(), equalTo(true));
|
||||
assertThat(check.check(), equalTo(true));
|
||||
assertThat(check.errorMessage(), containsString("the-realm-name"));
|
||||
assertThat(check.errorMessage(), containsString(file.toString()));
|
||||
assertThat(check.errorMessage(), containsString("invalid DN"));
|
||||
assertThat(check.errorMessage(), containsString("not-a-dn"));
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue