@@ -27,14 +27,15 @@
import org.jboss.as.domain.management.CallbackHandlerFactory;
import org.jboss.as.domain.management.logging.DomainManagementLogger;
import org.jboss.as.domain.management.SecurityRealm;
import org.jboss.msc.service.Service;
import org.jboss.msc.Service;
import org.jboss.msc.service.ServiceName;
import org.jboss.msc.service.StartContext;
import org.jboss.msc.service.StartException;
import org.jboss.msc.service.StopContext;

import java.nio.charset.StandardCharsets;
import java.util.Base64;
import java.util.function.Consumer;
import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.NameCallback;
@@ -43,8 +44,6 @@
import javax.security.sasl.RealmCallback;
import javax.security.sasl.RealmChoiceCallback;
import java.io.IOException;
import org.jboss.msc.inject.Injector;
import org.jboss.msc.value.InjectedValue;
import org.wildfly.common.function.ExceptionSupplier;
import org.wildfly.security.auth.callback.OptionalNameCallback;
import org.wildfly.security.credential.source.CredentialSource;
@@ -54,24 +53,29 @@
* A simple identity service for an identity represented by a single secret or password.
*
* @author <a href="mailto:darran.lofthouse@jboss.com">Darran Lofthouse</a>
* @author <a href="mailto:ropalka@redhat.com">Richard Opalka</a>
*/
public class SecretIdentityService implements Service<CallbackHandlerFactory> {
public class SecretIdentityService implements Service {

private static final String SERVICE_SUFFIX = "secret";

private final String password;
private final boolean base64;

private volatile CallbackHandlerFactory factory;
private final InjectedValue<ExceptionSupplier<CredentialSource, Exception>> credentialSourceSupplier = new InjectedValue<>();
private final Consumer<CallbackHandlerFactory> callbackHandlerFactoryConsumer;
private final ExceptionSupplier<CredentialSource, Exception> credentialSourceSupplier;

public SecretIdentityService(final String password, boolean base64) {
public SecretIdentityService(final Consumer<CallbackHandlerFactory> callbackHandlerFactoryConsumer,
final ExceptionSupplier<CredentialSource, Exception> credentialSourceSupplier,
final String password, boolean base64) {
this.callbackHandlerFactoryConsumer = callbackHandlerFactoryConsumer;
this.credentialSourceSupplier = credentialSourceSupplier;
this.password = password;
this.base64 = base64;
}

@Override
public void start(StartContext startContext) throws StartException {
public void start(final StartContext startContext) throws StartException {
final char[] thePassword;
if (base64) {
byte[] value = Base64.getDecoder().decode(password);
@@ -86,24 +90,16 @@ public void start(StartContext startContext) throws StartException {
thePassword = password.toCharArray();
}

factory = (String username) -> new SecretCallbackHandler(username, resolvePassword(thePassword));
callbackHandlerFactoryConsumer.accept((String username) -> new SecretCallbackHandler(username, resolvePassword(thePassword)));
}

public void stop(StopContext stopContext) {
factory = null;
}

public CallbackHandlerFactory getValue() throws IllegalStateException, IllegalArgumentException {
return factory;
}

Injector<ExceptionSupplier<CredentialSource, Exception>> getCredentialSourceSupplierInjector() {
return credentialSourceSupplier;
public void stop(final StopContext stopContext) {
callbackHandlerFactoryConsumer.accept(null);
}

private char[] resolvePassword(char[] thePassword) {
try {
ExceptionSupplier<CredentialSource, Exception> sourceSupplier = credentialSourceSupplier.getOptionalValue();
ExceptionSupplier<CredentialSource, Exception> sourceSupplier = credentialSourceSupplier;
if (sourceSupplier == null) {
return thePassword;
}

Large diffs are not rendered by default.

@@ -47,6 +47,8 @@
import java.util.function.Function;
import java.util.Set;
import java.util.TreeSet;
import java.util.function.Consumer;
import java.util.function.Supplier;
import java.util.stream.Collectors;

import javax.net.ssl.SSLContext;
@@ -78,7 +80,6 @@
import org.jboss.msc.service.StartContext;
import org.jboss.msc.service.StartException;
import org.jboss.msc.service.StopContext;
import org.jboss.msc.value.InjectedSetValue;
import org.jboss.msc.value.InjectedValue;
import org.wildfly.security.SecurityFactory;
import org.wildfly.security.WildFlyElytronProvider;
@@ -117,7 +118,9 @@
* requiring any of the capabilities provided by the realm.
*
* @author <a href="mailto:darran.lofthouse@jboss.com">Darran Lofthouse</a>
* @author <a href="mailto:ropalka@redhat.com">Richard Opalka</a>
*/
// TODO: refactor org.jboss.msc.service.Service to org.jboss.msc.Service when WildFly codebase is fixed
public class SecurityRealmService implements Service<SecurityRealm>, SecurityRealm {

private static final String[] ADDITIONAL_PERMISSION = new String[] { "org.wildfly.transaction.client.RemoteTransactionPermission", "org.jboss.ejb.client.RemoteEJBPermission" };
@@ -139,14 +142,19 @@
}
}

private final InjectedValue<SubjectSupplementalService> subjectSupplemental = new InjectedValue<SubjectSupplementalService>();
private final Consumer<SecurityRealm> securityRealmConsumer;
private final Supplier<SubjectSupplementalService> subjectSupplementalSupplier;
private final Supplier<CallbackHandlerFactory> secretCallbackFactorySupplier;
private final Supplier<KeytabIdentityFactoryService> keytabFactorySupplier;
private final Supplier<SSLContext> sslContextSupplier;
// TODO: eliminate sslContext field when WildFly codebase is migrated to new constructor
@Deprecated
private final InjectedValue<SSLContext> sslContext = new InjectedValue<SSLContext>();

private final InjectedValue<CallbackHandlerFactory> secretCallbackFactory = new InjectedValue<CallbackHandlerFactory>();
private final InjectedValue<KeytabIdentityFactoryService> keytabFactory = new InjectedValue<KeytabIdentityFactoryService>();
private final InjectedSetValue<CallbackHandlerService> callbackHandlerServices = new InjectedSetValue<CallbackHandlerService>();

private final Supplier<String> tmpDirPathSupplier;
// TODO: eliminate tmpDirPath field when WildFly codebase is migrated to new constructor
@Deprecated
private final InjectedValue<String> tmpDirPath = new InjectedValue<>();
private final Set<Supplier<CallbackHandlerService>> callbackHandlerServices;

private final String name;
private final boolean mapGroupsToRoles;
@@ -159,29 +167,66 @@
private Map<String, String> mechanismConfiguration = new HashMap<>();
private MechanismConfigurationSelector mechanismConfigurationSelector;

public SecurityRealmService(String name, boolean mapGroupsToRoles) {
@Deprecated // TODO: eliminate this constructor when WildFly codebase is migrated to new constructor
public SecurityRealmService(final String name, final boolean mapGroupsToRoles) {
this(null, null, null, null, null, null, null, name, mapGroupsToRoles);
}

public SecurityRealmService(final Consumer<SecurityRealm> securityRealmConsumer,
final Supplier<SubjectSupplementalService> subjectSupplementalSupplier,
final Supplier<CallbackHandlerFactory> secretCallbackFactorySupplier,
final Supplier<KeytabIdentityFactoryService> keytabFactorySupplier,
final Supplier<SSLContext> sslContextSupplier,
final Supplier<String> tmpDirPathSupplier,
final Set<Supplier<CallbackHandlerService>> callbackHandlerServices,
final String name, final boolean mapGroupsToRoles) {
this.securityRealmConsumer = securityRealmConsumer;
this.subjectSupplementalSupplier = subjectSupplementalSupplier;
this.secretCallbackFactorySupplier = secretCallbackFactorySupplier;
this.keytabFactorySupplier = keytabFactorySupplier;
this.sslContextSupplier = sslContextSupplier;
this.tmpDirPathSupplier = tmpDirPathSupplier;
this.callbackHandlerServices = callbackHandlerServices;
this.name = name;
this.mapGroupsToRoles = mapGroupsToRoles;
}

@Deprecated // TODO: eliminate this method when WildFly codebase is migrated to new constructor
public InjectedValue<SSLContext> getSSLContextInjector() {
return sslContext;
}

@Deprecated // TODO: eliminate this method when WildFly codebase is migrated to new constructor
public Injector<String> getTmpDirPathInjector() {
return tmpDirPath;
}
/*
* Service Methods
*/

public void start(StartContext context) throws StartException {
@Deprecated // TODO: eliminate this method when WildFly codebase is migrated to new constructor
@Override
public SecurityRealm getValue() throws IllegalStateException, IllegalArgumentException {
return this;
}

@Override
public void start(final StartContext context) throws StartException {
ROOT_LOGGER.debugf("Starting '%s' Security Realm Service", name);
for (CallbackHandlerService current : callbackHandlerServices.getValue()) {
// accept this, but don't actually install it in the map
if (current instanceof DomainManagedServerCallbackHandler) {
domainManagedServersCallback = (DomainManagedServerCallbackHandler) current;
continue;
}
AuthMechanism mechanism = current.getPreferredMechanism();
if (registeredServices.containsKey(mechanism)) {
registeredServices.clear();
throw DomainManagementLogger.ROOT_LOGGER.multipleCallbackHandlerForMechanism(mechanism.name());
if (callbackHandlerServices != null) {
for (Supplier<CallbackHandlerService> current : callbackHandlerServices) {
// accept this, but don't actually install it in the map
if (current instanceof DomainManagedServerCallbackHandler) {
domainManagedServersCallback = (DomainManagedServerCallbackHandler) current;
continue;
}
AuthMechanism mechanism = current.get().getPreferredMechanism();
if (registeredServices.containsKey(mechanism)) {
registeredServices.clear();
throw DomainManagementLogger.ROOT_LOGGER.multipleCallbackHandlerForMechanism(mechanism.name());
}
registeredServices.put(mechanism, current.get());
}
registeredServices.put(mechanism, current);
}

/*
@@ -190,7 +235,7 @@ public void start(StartContext context) throws StartException {

final Map<AuthMechanism, MechanismConfiguration> configurationMap = new HashMap<>();

SubjectSupplementalService subjectSupplementalService = this.subjectSupplemental.getOptionalValue();
SubjectSupplementalService subjectSupplementalService = subjectSupplementalSupplier != null ? subjectSupplementalSupplier.get() : null;
org.wildfly.security.auth.server.SecurityRealm authorizationRealm = subjectSupplementalService != null ? subjectSupplementalService.getElytronSecurityRealm() : null;

SecurityDomain.Builder domainBuilder = SecurityDomain.builder();
@@ -231,7 +276,8 @@ public String getRealmMapping(Principal principal, Evidence evidence) {
}
}

mechanismConfiguration.put(LOCAL_USER_CHALLENGE_PATH, getAuthDir(tmpDirPath.getValue()));
// TODO: eliminate tmpDirPathSupplier null check when WildFly code base is migrated to new MSC API
mechanismConfiguration.put(LOCAL_USER_CHALLENGE_PATH, getAuthDir(tmpDirPathSupplier != null ? tmpDirPathSupplier.get() : tmpDirPath.getValue()));
mechanismConfiguration.put(WildFlySasl.ALTERNATIVE_PROTOCOLS, "remoting");

domainBuilder.addRealm("EMPTY", org.wildfly.security.auth.server.SecurityRealm.EMPTY_REALM).build();
@@ -318,6 +364,22 @@ public RealmIdentity getRealmIdentity(Evidence evidence) throws RealmUnavailable
saslBuilder.setFactory(saslServerFactory);
saslBuilder.setMechanismConfigurationSelector(mechanismConfigurationSelector);
saslAuthenticationFactory = saslBuilder.build();
if (securityRealmConsumer != null) {
// TODO: eliminate above null check when WildFly code base is migrated to new MSC API
securityRealmConsumer.accept(this);
}
}

@Override
public void stop(final StopContext context) {
ROOT_LOGGER.debugf("Stopping '%s' Security Realm Service", name);
if (securityRealmConsumer != null) {
// TODO: eliminate above null check when WildFly code base is migrated to new MSC API
securityRealmConsumer.accept(null);
}
registeredServices.clear();
saslAuthenticationFactory = null;
httpAuthenticationFactory = null;
}

public static PermissionVerifier createPermissionVerifier() {
@@ -410,18 +472,6 @@ private String getAuthDir(final String path) throws StartException {
return authDir.getAbsolutePath();
}


public void stop(StopContext context) {
ROOT_LOGGER.debugf("Stopping '%s' Security Realm Service", name);
registeredServices.clear();
saslAuthenticationFactory = null;
httpAuthenticationFactory = null;
}

public SecurityRealmService getValue() throws IllegalStateException, IllegalArgumentException {
return this;
}

public String getName() {
return name;
}
@@ -528,7 +578,7 @@ public SubjectUserInfo createSubjectUserInfo(Collection<Principal> userPrincipal

Object skipGroupLoading = sharedState.get(SKIP_GROUP_LOADING_KEY);
if (skipGroupLoading == null || Boolean.parseBoolean(skipGroupLoading.toString()) == false) {
SubjectSupplementalService subjectSupplementalService = subjectSupplemental.getOptionalValue();
SubjectSupplementalService subjectSupplementalService = subjectSupplementalSupplier != null ? subjectSupplementalSupplier.get() : null;
if (subjectSupplementalService != null) {
SubjectSupplemental subjectSupplemental = subjectSupplementalService.getSubjectSupplemental(sharedState);
subjectSupplemental.supplementSubject(subject);
@@ -567,7 +617,7 @@ private CallbackHandlerService getCallbackHandlerService(final AuthMechanism mec

@Override
public SubjectIdentity getSubjectIdentity(String protocol, String forHost) {
KeytabIdentityFactoryService kifs = keytabFactory.getOptionalValue();
KeytabIdentityFactoryService kifs = keytabFactorySupplier != null ? keytabFactorySupplier.get() : null;

return kifs != null ? kifs.getSubjectIdentity(protocol, forHost) : null;
}
@@ -678,40 +728,13 @@ public HttpAuthenticationFactory getHttpAuthenticationFactory() {
return httpAuthenticationFactory;
}

/*
* Injectors
*/

public InjectedValue<SubjectSupplementalService> getSubjectSupplementalInjector() {
return subjectSupplemental;
}

public InjectedValue<SSLContext> getSSLContextInjector() {
return sslContext;
}

public InjectedValue<CallbackHandlerFactory> getSecretCallbackFactory() {
return secretCallbackFactory;
}

public InjectedValue<KeytabIdentityFactoryService> getKeytabIdentityFactoryInjector() {
return keytabFactory;
}

public InjectedSetValue<CallbackHandlerService> getCallbackHandlerService() {
return callbackHandlerServices;
}

public Injector<String> getTmpDirPathInjector() {
return tmpDirPath;
}

public SSLContext getSSLContext() {
return sslContext.getOptionalValue();
// TODO: replace sslContext.getOptionalValue() with null once WildFly code base is migrated to new MSC API
return sslContextSupplier != null ? sslContextSupplier.get() : sslContext.getOptionalValue();
}

public CallbackHandlerFactory getSecretCallbackHandlerFactory() {
return secretCallbackFactory.getOptionalValue();
return secretCallbackFactorySupplier != null ? secretCallbackFactorySupplier.get() : null;
}

private GSSKerberosCredential getGSSKerberosCredential(final String protocol, final String forHost)
@@ -23,8 +23,8 @@
package org.jboss.as.domain.management.security;

import java.util.Map;
import java.util.function.Supplier;

import org.jboss.msc.inject.Injector;
import org.jboss.msc.service.ServiceBuilder;
import org.jboss.msc.service.ServiceName;
import org.wildfly.security.auth.server.SecurityRealm;
@@ -33,6 +33,7 @@
* Interface to be implemented by services supplying SubjectSupplemental implementations.
*
* @author <a href="mailto:darran.lofthouse@jboss.com">Darran Lofthouse</a>
* @author <a href="mailto:ropalka@redhat.com">Richard Opalka</a>
*/
public interface SubjectSupplementalService {

@@ -63,8 +64,8 @@ default SecurityRealm getElytronSecurityRealm() {
private ServiceUtil() {
}

public static ServiceBuilder<?> addDependency(ServiceBuilder<?> sb, Injector<SubjectSupplementalService> injector, ServiceName serviceName) {
return sb.addDependency(serviceName, SubjectSupplementalService.class, injector);
public static Supplier<SubjectSupplementalService> requires(final ServiceBuilder<?> sb, final ServiceName serviceName) {
return sb.requires(serviceName);
}

}
@@ -41,6 +41,7 @@
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.function.Consumer;

import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
@@ -54,13 +55,10 @@
import org.jboss.as.domain.management.SecurityRealm;
import org.jboss.as.domain.management.logging.DomainManagementLogger;
import org.jboss.dmr.ModelNode;
import org.jboss.msc.inject.Injector;
import org.jboss.msc.service.Service;
import org.jboss.msc.service.ServiceName;
import org.jboss.msc.service.StartContext;
import org.jboss.msc.service.StartException;
import org.jboss.msc.service.StopContext;
import org.jboss.msc.value.InjectedValue;
import org.wildfly.common.Assert;
import org.wildfly.common.function.ExceptionSupplier;
import org.wildfly.security.auth.SupportLevel;
@@ -83,6 +81,7 @@
* A CallbackHandler for users defined within the domain model.
*
* @author <a href="mailto:darran.lofthouse@jboss.com">Darran Lofthouse</a>
* @author <a href="mailto:ropalka@redhat.com">Richard Opalka</a>
*/
public class UserDomainCallbackHandler implements Service<CallbackHandlerService>, CallbackHandlerService, CallbackHandler {

@@ -92,9 +91,14 @@
private final String realm;

private volatile ModelNode userDomain;
private final InjectedValue<Map<String, ExceptionSupplier<CredentialSource, Exception>>> credentialSourceSupplier = new InjectedValue<>();

public UserDomainCallbackHandler(String realm, ModelNode userDomain) {
private final Consumer<CallbackHandlerService> callbackHandlerServiceConsumer;
private final Map<String, ExceptionSupplier<CredentialSource, Exception>> credentialSourceSupplier;

UserDomainCallbackHandler(final Consumer<CallbackHandlerService> callbackHandlerServiceConsumer,
final Map<String, ExceptionSupplier<CredentialSource, Exception>> credentialSourceSupplier,
final String realm, final ModelNode userDomain) {
this.callbackHandlerServiceConsumer = callbackHandlerServiceConsumer;
this.credentialSourceSupplier = credentialSourceSupplier;
this.realm = realm;
setUserDomain(userDomain);
}
@@ -103,10 +107,6 @@ void setUserDomain(final ModelNode userDomain) {
this.userDomain = userDomain == null || !userDomain.isDefined() ? new ModelNode().setEmptyObject() : userDomain.clone();
}

Injector<Map<String, ExceptionSupplier<CredentialSource, Exception>>> getCredentialSourceSupplierInjector() {
return credentialSourceSupplier;
}

/*
* CallbackHandlerService Methods
*/
@@ -137,17 +137,18 @@ public CallbackHandler getCallbackHandler(Map<String, Object> sharedState) {
return new SecurityRealmImpl();
}

/*
* Service Methods
*/

public void start(StartContext context) throws StartException {
@Override
public void start(final StartContext context) {
callbackHandlerServiceConsumer.accept(this);
}

public void stop(StopContext context) {
@Override
public void stop(final StopContext context) {
callbackHandlerServiceConsumer.accept(null);
}

public UserDomainCallbackHandler getValue() throws IllegalStateException, IllegalArgumentException {
@Override
public CallbackHandlerService getValue() throws IllegalStateException, IllegalArgumentException {
return this;
}

@@ -242,8 +243,8 @@ public void handle(Callback[] callbacks) throws IOException, UnsupportedCallback

private ExceptionSupplier<CredentialSource, Exception> getUserCredentialSourceSupplier(String userName) {
ExceptionSupplier<CredentialSource, Exception> userCredentialSourceSupplier = null;
if (credentialSourceSupplier.getOptionalValue() != null && credentialSourceSupplier.getValue().containsKey(userName)) {
userCredentialSourceSupplier = credentialSourceSupplier.getValue().get(userName);
if (credentialSourceSupplier != null && credentialSourceSupplier.containsKey(userName)) {
userCredentialSourceSupplier = credentialSourceSupplier.get(userName);
}
return userCredentialSourceSupplier;
}
@@ -34,6 +34,8 @@
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.function.Consumer;
import java.util.function.Supplier;
import java.util.function.Function;

import javax.naming.CommunicationException;
@@ -52,13 +54,10 @@
import org.jboss.as.domain.management.logging.DomainManagementLogger;
import org.jboss.as.domain.management.security.LdapSearcherCache.AttachmentKey;
import org.jboss.as.domain.management.security.LdapSearcherCache.SearchResult;
import org.jboss.msc.inject.Injector;
import org.jboss.msc.service.Service;
import org.jboss.msc.Service;
import org.jboss.msc.service.ServiceName;
import org.jboss.msc.service.StartContext;
import org.jboss.msc.service.StartException;
import org.jboss.msc.service.StopContext;
import org.jboss.msc.value.InjectedValue;
import org.wildfly.security.auth.SupportLevel;
import org.wildfly.security.auth.callback.EvidenceVerifyCallback;
import org.wildfly.security.auth.principal.NamePrincipal;
@@ -73,27 +72,43 @@
* A CallbackHandler for users within an LDAP directory.
*
* @author <a href="mailto:darran.lofthouse@jboss.com">Darran Lofthouse</a>
* @author <a href="mailto:ropalka@redhat.com>Richard Opalka</a>
*/
public class UserLdapCallbackHandler implements Service<CallbackHandlerService>, CallbackHandlerService {
public class UserLdapCallbackHandler implements Service, CallbackHandlerService {
private static final AttachmentKey<PasswordCredential> PASSWORD_KEY = AttachmentKey.create(PasswordCredential.class);
private static final String SERVICE_SUFFIX = "ldap";
public static final String DEFAULT_USER_DN = "dn";
private final InjectedValue<LdapConnectionManager> connectionManager = new InjectedValue<LdapConnectionManager>();
private final InjectedValue<LdapSearcherCache<LdapEntry, String>> userSearcherInjector = new InjectedValue<LdapSearcherCache<LdapEntry, String>>();
private final Consumer<CallbackHandlerService> callbackHandlerServiceConsumer;
private final Supplier<LdapConnectionManager> connectionManagerSupplier;
private final Supplier<LdapSearcherCache<LdapEntry, String>> userSearcherSupplier;
private final boolean allowEmptyPassword;
private final boolean shareConnection;
protected final int searchTimeLimit = 10000; // TODO - Maybe make configurable.
public UserLdapCallbackHandler(boolean allowEmptyPassword, boolean shareConnection) {
UserLdapCallbackHandler(final Consumer<CallbackHandlerService> callbackHandlerServiceConsumer,
final Supplier<LdapConnectionManager> connectionManagerSupplier,
final Supplier<LdapSearcherCache<LdapEntry, String>> userSearcherSupplier,
boolean allowEmptyPassword, boolean shareConnection) {
this.callbackHandlerServiceConsumer = callbackHandlerServiceConsumer;
this.connectionManagerSupplier = connectionManagerSupplier;
this.userSearcherSupplier = userSearcherSupplier;
this.allowEmptyPassword = allowEmptyPassword;
this.shareConnection = shareConnection;
}
public void start(final StartContext context) {
callbackHandlerServiceConsumer.accept(this);
}
public void stop(final StopContext context) {
callbackHandlerServiceConsumer.accept(null);
}
/*
* CallbackHandlerService Methods
*/
@@ -137,7 +152,7 @@ public CallbackHandler getCallbackHandler(Map<String, Object> sharedState) {
LdapConnectionHandler ldapConnectionHandler = createLdapConnectionHandler();
try {
try {
SearchResult<LdapEntry> searchResult = userSearcherInjector.getValue().search(ldapConnectionHandler, p.getName());
SearchResult<LdapEntry> searchResult = userSearcherSupplier.get().search(ldapConnectionHandler, p.getName());
return p instanceof RealmUser ? new MappedPrincipal(((RealmUser) p).getRealm(), searchResult.getResult().getSimpleName(), p.getName())
: new MappedPrincipal(searchResult.getResult().getSimpleName(), p.getName());
@@ -152,30 +167,8 @@ public CallbackHandler getCallbackHandler(Map<String, Object> sharedState) {
};
}
public void start(StartContext context) throws StartException {
}

public void stop(StopContext context) {
}

public CallbackHandlerService getValue() throws IllegalStateException, IllegalArgumentException {
return this;
}

/*
* Access to Injectors
*/

public InjectedValue<LdapConnectionManager> getConnectionManagerInjector() {
return connectionManager;
}

public Injector<LdapSearcherCache<LdapEntry, String>> getLdapUserSearcherInjector() {
return userSearcherInjector;
}

private LdapConnectionHandler createLdapConnectionHandler() {
LdapConnectionManager connectionManager = this.connectionManager.getValue();
LdapConnectionManager connectionManager = this.connectionManagerSupplier.get();
return LdapConnectionHandler.newInstance(connectionManager);
}
@@ -251,7 +244,7 @@ public void handle(Callback[] callbacks) throws IOException, UnsupportedCallback
LdapConnectionHandler lch = createLdapConnectionHandler();
try {
// 2 - Search to identify the DN of the user connecting
SearchResult<LdapEntry> searchResult = userSearcherInjector.getValue().search(lch, username);
SearchResult<LdapEntry> searchResult = userSearcherSupplier.get().search(lch, username);
evidenceVerifyCallback.setVerified(verifyPassword(lch, searchResult, username, password, sharedState));
} catch (Exception e) {
@@ -342,7 +335,7 @@ public RealmIdentity getRealmIdentity(Principal principal) throws RealmUnavailab
LdapConnectionHandler ldapConnectionHandler = createLdapConnectionHandler();
try {
SearchResult<LdapEntry> searchResult = userSearcherInjector.getValue().search(ldapConnectionHandler, name);
SearchResult<LdapEntry> searchResult = userSearcherSupplier.get().search(ldapConnectionHandler, name);
return new RealmIdentityImpl(new NamePrincipal(name), ldapConnectionHandler, searchResult, SecurityRealmService.SharedStateSecurityRealm.getSharedState());
} catch (IOException | CommunicationException e) {
@@ -22,13 +22,16 @@

package org.jboss.as.domain.management.security;

import org.jboss.as.controller.services.path.PathManager;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Supplier;
import java.util.regex.Matcher;

import static org.jboss.as.domain.management.logging.DomainManagementLogger.ROOT_LOGGER;
@@ -57,8 +60,12 @@
* End of state maintained during persistence.
*/

public UserPropertiesFileLoader(final String path, final String relativeTo) {
super(path, relativeTo);
public UserPropertiesFileLoader(final Supplier<PathManager> pathManagerSupplier, final String path, final String relativeTo) {
super(pathManagerSupplier, path, relativeTo);
}

public UserPropertiesFileLoader(final String path) {
super(null, path, null);
}

public String getRealmName() throws IOException {
@@ -161,7 +161,7 @@ public State execute() {
}

private UserPropertiesFileLoader loadUsersFile(File file) throws IOException {
UserPropertiesFileLoader fileLoader = new UserPropertiesFileLoader(file.getAbsolutePath(), null);
UserPropertiesFileLoader fileLoader = new UserPropertiesFileLoader(file.getAbsolutePath());
try {
fileLoader.start(null);
} catch (StartException e) {
@@ -176,7 +176,7 @@ private UserPropertiesFileLoader loadUsersFile(File file) throws IOException {
for (File file : foundGroupsFiles) {
PropertiesFileLoader propertiesLoad = null;
try {
propertiesLoad = new PropertiesFileLoader(file.getCanonicalPath(), null);
propertiesLoad = new PropertiesFileLoader(file.getCanonicalPath());
propertiesLoad.start(null);
loadedGroups.putAll((Map) propertiesLoad.getProperties());
} finally {
@@ -54,8 +54,8 @@ void persist(final String key, final String value, final boolean enableDisableMo
* Implement the persistence handler for storing the user properties.
*/
void persist(final String key, final String value, final boolean enableDisableMode, final boolean disable, final File file, final String realm) throws IOException, StartException {
final PropertiesFileLoader propertiesHandler = realm == null ? new PropertiesFileLoader(file.getAbsolutePath(), null) :
new UserPropertiesFileLoader(file.getAbsolutePath(), null);
final PropertiesFileLoader propertiesHandler = realm == null ? new PropertiesFileLoader(file.getAbsolutePath()) :
new UserPropertiesFileLoader(file.getAbsolutePath());
try {
propertiesHandler.start(null);
if (realm != null) {
@@ -23,7 +23,7 @@

package org.jboss.as.domain.management.security;


import java.util.function.Supplier;
import javax.security.auth.Subject;
import javax.security.auth.login.LoginException;

@@ -60,12 +60,12 @@
*/
@Test
public void testForHostWithProto() throws StartException {
KeytabIdentityFactoryService service = new KeytabIdentityFactoryService();
service.getKeytabInjector().inject(createKeytabService("HTTP/ANYVALUE@SOMETHING.COM", "HTTP/EXAMPLE", RIGHT_SUBJECT_IDENTITY));
service.getKeytabInjector().inject(createKeytabService("HTTP/ANYVALUE@SOMETHING.COM", "EXAMPLE", WRONG_SUBJECT_IDENTITY));
service.getKeytabInjector().inject(createKeytabService("HTTP/EXAMPLE@SOMETHING.COM", "SOMEHOST", WRONG_SUBJECT_IDENTITY));
service.getKeytabInjector().inject(createKeytabService("PROTO/EXAMPLE@SOMETHING.COM", "SOMEHOST", WRONG_SUBJECT_IDENTITY));
service.getKeytabInjector().inject(createKeytabService("HTTP/ANYVALUE@SOMETHING.COM", "*", WRONG_SUBJECT_IDENTITY));
KeytabIdentityFactoryService service = new KeytabIdentityFactoryService(null);
service.addKeytabSupplier(createKeytabService("HTTP/ANYVALUE@SOMETHING.COM", "HTTP/EXAMPLE", RIGHT_SUBJECT_IDENTITY));
service.addKeytabSupplier(createKeytabService("HTTP/ANYVALUE@SOMETHING.COM", "EXAMPLE", WRONG_SUBJECT_IDENTITY));
service.addKeytabSupplier(createKeytabService("HTTP/EXAMPLE@SOMETHING.COM", "SOMEHOST", WRONG_SUBJECT_IDENTITY));
service.addKeytabSupplier(createKeytabService("PROTO/EXAMPLE@SOMETHING.COM", "SOMEHOST", WRONG_SUBJECT_IDENTITY));
service.addKeytabSupplier(createKeytabService("HTTP/ANYVALUE@SOMETHING.COM", "*", WRONG_SUBJECT_IDENTITY));
service.start(null);

SubjectIdentity subjectIdentity = service.getSubjectIdentity("HTTP", "EXAMPLE");
@@ -79,12 +79,12 @@ public void testForHostWithProto() throws StartException {
*/
@Test
public void testForHostWithoutProto() throws StartException {
KeytabIdentityFactoryService service = new KeytabIdentityFactoryService();
service.getKeytabInjector().inject(createKeytabService("HTTP/ANYVALUE@SOMETHING.COM", "HTTP/SOMEHOST", WRONG_SUBJECT_IDENTITY));
service.getKeytabInjector().inject(createKeytabService("HTTP/ANYVALUE@SOMETHING.COM", "EXAMPLE", WRONG_SUBJECT_IDENTITY));
service.getKeytabInjector().inject(createKeytabService("HTTP/EXAMPLE@SOMETHING.COM", "SOMEHOST", RIGHT_SUBJECT_IDENTITY));
service.getKeytabInjector().inject(createKeytabService("PROTO/EXAMPLE@SOMETHING.COM", "SOMEHOST", WRONG_SUBJECT_IDENTITY));
service.getKeytabInjector().inject(createKeytabService("HTTP/ANYVALUE@SOMETHING.COM", "*", WRONG_SUBJECT_IDENTITY));
KeytabIdentityFactoryService service = new KeytabIdentityFactoryService(null);
service.addKeytabSupplier(createKeytabService("HTTP/ANYVALUE@SOMETHING.COM", "HTTP/SOMEHOST", WRONG_SUBJECT_IDENTITY));
service.addKeytabSupplier(createKeytabService("HTTP/ANYVALUE@SOMETHING.COM", "EXAMPLE", WRONG_SUBJECT_IDENTITY));
service.addKeytabSupplier(createKeytabService("HTTP/EXAMPLE@SOMETHING.COM", "SOMEHOST", RIGHT_SUBJECT_IDENTITY));
service.addKeytabSupplier(createKeytabService("PROTO/EXAMPLE@SOMETHING.COM", "SOMEHOST", WRONG_SUBJECT_IDENTITY));
service.addKeytabSupplier(createKeytabService("HTTP/ANYVALUE@SOMETHING.COM", "*", WRONG_SUBJECT_IDENTITY));
service.start(null);

SubjectIdentity subjectIdentity = service.getSubjectIdentity("HTTP", "EXAMPLE");
@@ -98,12 +98,12 @@ public void testForHostWithoutProto() throws StartException {
*/
@Test
public void testPrincipalWithProto() throws StartException {
KeytabIdentityFactoryService service = new KeytabIdentityFactoryService();
service.getKeytabInjector().inject(createKeytabService("HTTP/ANYVALUE@SOMETHING.COM", "HTTP/SOMEHOST", WRONG_SUBJECT_IDENTITY));
service.getKeytabInjector().inject(createKeytabService("HTTP/ANYVALUE@SOMETHING.COM", "SOMEHOST", WRONG_SUBJECT_IDENTITY));
service.getKeytabInjector().inject(createKeytabService("HTTP/EXAMPLE@SOMETHING.COM", "SOMEHOST", RIGHT_SUBJECT_IDENTITY));
service.getKeytabInjector().inject(createKeytabService("PROTO/EXAMPLE@SOMETHING.COM", "SOMEHOST", WRONG_SUBJECT_IDENTITY));
service.getKeytabInjector().inject(createKeytabService("HTTP/ANYVALUE@SOMETHING.COM", "*", WRONG_SUBJECT_IDENTITY));
KeytabIdentityFactoryService service = new KeytabIdentityFactoryService(null);
service.addKeytabSupplier(createKeytabService("HTTP/ANYVALUE@SOMETHING.COM", "HTTP/SOMEHOST", WRONG_SUBJECT_IDENTITY));
service.addKeytabSupplier(createKeytabService("HTTP/ANYVALUE@SOMETHING.COM", "SOMEHOST", WRONG_SUBJECT_IDENTITY));
service.addKeytabSupplier(createKeytabService("HTTP/EXAMPLE@SOMETHING.COM", "SOMEHOST", RIGHT_SUBJECT_IDENTITY));
service.addKeytabSupplier(createKeytabService("PROTO/EXAMPLE@SOMETHING.COM", "SOMEHOST", WRONG_SUBJECT_IDENTITY));
service.addKeytabSupplier(createKeytabService("HTTP/ANYVALUE@SOMETHING.COM", "*", WRONG_SUBJECT_IDENTITY));
service.start(null);

SubjectIdentity subjectIdentity = service.getSubjectIdentity("HTTP", "EXAMPLE");
@@ -117,12 +117,12 @@ public void testPrincipalWithProto() throws StartException {
*/
@Test
public void testPrincipalWithoutProto() throws StartException {
KeytabIdentityFactoryService service = new KeytabIdentityFactoryService();
service.getKeytabInjector().inject(createKeytabService("HTTP/ANYVALUE@SOMETHING.COM", "HTTP/SOMEHOST", WRONG_SUBJECT_IDENTITY));
service.getKeytabInjector().inject(createKeytabService("HTTP/ANYVALUE@SOMETHING.COM", "SOMEHOST", WRONG_SUBJECT_IDENTITY));
service.getKeytabInjector().inject(createKeytabService("HTTP/ANYVALUE@SOMETHING.COM", "SOMEHOST", WRONG_SUBJECT_IDENTITY));
service.getKeytabInjector().inject(createKeytabService("PROTO/EXAMPLE@SOMETHING.COM", "SOMEHOST", RIGHT_SUBJECT_IDENTITY));
service.getKeytabInjector().inject(createKeytabService("HTTP/ANYVALUE@SOMETHING.COM", "*", WRONG_SUBJECT_IDENTITY));
KeytabIdentityFactoryService service = new KeytabIdentityFactoryService(null);
service.addKeytabSupplier(createKeytabService("HTTP/ANYVALUE@SOMETHING.COM", "HTTP/SOMEHOST", WRONG_SUBJECT_IDENTITY));
service.addKeytabSupplier(createKeytabService("HTTP/ANYVALUE@SOMETHING.COM", "SOMEHOST", WRONG_SUBJECT_IDENTITY));
service.addKeytabSupplier(createKeytabService("HTTP/ANYVALUE@SOMETHING.COM", "SOMEHOST", WRONG_SUBJECT_IDENTITY));
service.addKeytabSupplier(createKeytabService("PROTO/EXAMPLE@SOMETHING.COM", "SOMEHOST", RIGHT_SUBJECT_IDENTITY));
service.addKeytabSupplier(createKeytabService("HTTP/ANYVALUE@SOMETHING.COM", "*", WRONG_SUBJECT_IDENTITY));
service.start(null);

SubjectIdentity subjectIdentity = service.getSubjectIdentity("HTTP", "EXAMPLE");
@@ -136,12 +136,12 @@ public void testPrincipalWithoutProto() throws StartException {
*/
@Test
public void testDefault() throws StartException {
KeytabIdentityFactoryService service = new KeytabIdentityFactoryService();
service.getKeytabInjector().inject(createKeytabService("HTTP/ANYVALUE@SOMETHING.COM", "HTTP/SOMEHOST", WRONG_SUBJECT_IDENTITY));
service.getKeytabInjector().inject(createKeytabService("HTTP/ANYVALUE@SOMETHING.COM", "SOMEHOST", WRONG_SUBJECT_IDENTITY));
service.getKeytabInjector().inject(createKeytabService("HTTP/ANYVALUE@SOMETHING.COM", "SOMEHOST", WRONG_SUBJECT_IDENTITY));
service.getKeytabInjector().inject(createKeytabService("PROTO/ANYVALUE@SOMETHING.COM", "SOMEHOST", WRONG_SUBJECT_IDENTITY));
service.getKeytabInjector().inject(createKeytabService("HTTP/ANYVALUE@SOMETHING.COM", "*", RIGHT_SUBJECT_IDENTITY));
KeytabIdentityFactoryService service = new KeytabIdentityFactoryService(null);
service.addKeytabSupplier(createKeytabService("HTTP/ANYVALUE@SOMETHING.COM", "HTTP/SOMEHOST", WRONG_SUBJECT_IDENTITY));
service.addKeytabSupplier(createKeytabService("HTTP/ANYVALUE@SOMETHING.COM", "SOMEHOST", WRONG_SUBJECT_IDENTITY));
service.addKeytabSupplier(createKeytabService("HTTP/ANYVALUE@SOMETHING.COM", "SOMEHOST", WRONG_SUBJECT_IDENTITY));
service.addKeytabSupplier(createKeytabService("PROTO/ANYVALUE@SOMETHING.COM", "SOMEHOST", WRONG_SUBJECT_IDENTITY));
service.addKeytabSupplier(createKeytabService("HTTP/ANYVALUE@SOMETHING.COM", "*", RIGHT_SUBJECT_IDENTITY));
service.start(null);

SubjectIdentity subjectIdentity = service.getSubjectIdentity("HTTP", "EXAMPLE");
@@ -155,10 +155,10 @@ public void testDefault() throws StartException {
*/
@Test
public void testHostNameCaseInSensitive() throws StartException {
KeytabIdentityFactoryService service = new KeytabIdentityFactoryService();
service.getKeytabInjector().inject(createKeytabService("HTTP/localhost@SOMETHING.COM", "SOMEHOST", RIGHT_SUBJECT_IDENTITY));
service.getKeytabInjector().inject(createKeytabService("HTTP/ANYVALUE@SOMETHING.COM", "SOMEHOST", WRONG_SUBJECT_IDENTITY));
service.getKeytabInjector().inject(createKeytabService("PROTO/ANYVALUE@SOMETHING.COM", "localhost", WRONG_SUBJECT_IDENTITY));
KeytabIdentityFactoryService service = new KeytabIdentityFactoryService(null);
service.addKeytabSupplier(createKeytabService("HTTP/localhost@SOMETHING.COM", "SOMEHOST", RIGHT_SUBJECT_IDENTITY));
service.addKeytabSupplier(createKeytabService("HTTP/ANYVALUE@SOMETHING.COM", "SOMEHOST", WRONG_SUBJECT_IDENTITY));
service.addKeytabSupplier(createKeytabService("PROTO/ANYVALUE@SOMETHING.COM", "localhost", WRONG_SUBJECT_IDENTITY));
service.start(null);

SubjectIdentity subjectIdentity = service.getSubjectIdentity("HTTP", "LocalHost");
@@ -171,11 +171,16 @@ public void testHostNameCaseInSensitive() throws StartException {
/**
* Creates mocked KeytabService
*/
private KeytabService createKeytabService(String principal, String forHost, final SubjectIdentity subjectIdentity) {
return new KeytabService(principal, null, null, new String[]{forHost}, true) {
private Supplier<KeytabService> createKeytabService(String principal, String forHost, final SubjectIdentity subjectIdentity) {
return new Supplier<KeytabService>() {
@Override
public SubjectIdentity createSubjectIdentity(boolean isClient) throws LoginException {
return subjectIdentity;
public KeytabService get() {
return new KeytabService(null, null, principal, null, null, new String[]{forHost}, true) {
@Override
public SubjectIdentity createSubjectIdentity(boolean isClient) throws LoginException {
return subjectIdentity;
}
};
}
};
}
@@ -44,6 +44,7 @@
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.function.Consumer;


/**
@@ -146,18 +147,34 @@ public void testModes() throws StartException, IOException, NamingException, Int
return startService(mode,cacheFailures, size, 30);
}

private LdapSearcherCache<LdapEntry, String> startService(CacheMode mode, boolean cacheFailures, int size, int evictionTimeout) throws StartException {
private LdapSearcherCache<LdapEntry, String> startService(CacheMode mode, boolean cacheFailures, int size, int evictionTimeout) {
LdapCacheService<LdapEntry, String> service;
switch (mode) {
case BY_ACCESS:
service = LdapCacheService.createByAccessCacheService(userSearcher, evictionTimeout, cacheFailures, size);
service = LdapCacheService.createByAccessCacheService(NullConsumer.INSTANCE, userSearcher, evictionTimeout, cacheFailures, size);
break;
default:
service = LdapCacheService.createBySearchCacheService(userSearcher, evictionTimeout, cacheFailures, size);
service = LdapCacheService.createBySearchCacheService(NullConsumer.INSTANCE, userSearcher, evictionTimeout, cacheFailures, size);
break;
}
service.start(null);
return service.getValue();
return service.cacheImplementation;
}

private static final class NullConsumer implements Consumer<LdapSearcherCache<LdapEntry, String>> {

private static final NullConsumer INSTANCE = new NullConsumer();

@Override
public Consumer<LdapSearcherCache<LdapEntry, String>> andThen(final Consumer<? super LdapSearcherCache<LdapEntry, String>> after) {
// ignored
return null;
}

@Override
public void accept(final LdapSearcherCache<LdapEntry, String> o) {
// ignored
}
}

private void testCacheFailures(CacheMode mode, boolean cacheFailure, int calls) throws StartException, IOException, NamingException {
@@ -97,7 +97,7 @@ public void testLoad() throws Exception {
tmpFile = createTempFile();
writeTestDataToFile(tmpFile);

PropertiesFileLoader loader = new PropertiesFileLoader(tmpFile.getAbsolutePath(), null);
PropertiesFileLoader loader = new PropertiesFileLoader(tmpFile.getAbsolutePath());
loader.start(null);
Properties props = loader.getProperties();
verifyProperties(props, props.size());
@@ -114,15 +114,15 @@ public void testAdd() throws Exception {
tmpFile = createTempFile();
writeTestDataToFile(tmpFile);

PropertiesFileLoader loader = new PropertiesFileLoader(tmpFile.getAbsolutePath(), null);
PropertiesFileLoader loader = new PropertiesFileLoader(tmpFile.getAbsolutePath());
loader.start(null);
Properties props = loader.getProperties();
props.put("NEW", "VALUE");
loader.persistProperties();
loader.stop(null);

// reload the file and make sure everything is there
PropertiesFileLoader loader2 = new PropertiesFileLoader(tmpFile.getAbsolutePath(), null);
PropertiesFileLoader loader2 = new PropertiesFileLoader(tmpFile.getAbsolutePath());
loader2.start(null);
Properties props2 = loader2.getProperties();
verifyProperties(props2, props2.size()-1, "NEW", "VALUE");
@@ -139,7 +139,7 @@ public void testDoublePersistWithEmptyValue() throws Exception {
tmpFile = createTempFile();
writeTestDataToFile(tmpFile);

PropertiesFileLoader loader = new PropertiesFileLoader(tmpFile.getAbsolutePath(), null);
PropertiesFileLoader loader = new PropertiesFileLoader(tmpFile.getAbsolutePath());
loader.start(null);
Properties props = loader.getProperties();
props.put("EMPTY", "");
@@ -151,7 +151,7 @@ public void testDoublePersistWithEmptyValue() throws Exception {
loader.stop(null);

//verify all properties are present
PropertiesFileLoader loader2 = new PropertiesFileLoader(tmpFile.getAbsolutePath(), null);
PropertiesFileLoader loader2 = new PropertiesFileLoader(tmpFile.getAbsolutePath());
loader2.start(null);
Properties props2 = loader2.getProperties();
verifyProperties(props2, props2.size()-2, "NEW", "VALUE");
@@ -173,15 +173,15 @@ public void testRemove() throws Exception {
tmpFile = createTempFile();
writeTestDataToFile(tmpFile);

PropertiesFileLoader loader = new PropertiesFileLoader(tmpFile.getAbsolutePath(), null);
PropertiesFileLoader loader = new PropertiesFileLoader(tmpFile.getAbsolutePath());
loader.start(null);
Properties props = loader.getProperties();
props.remove("ABC");
loader.persistProperties();
loader.stop(null);

// reload the file and make sure the removed item has been removed
PropertiesFileLoader loader2 = new PropertiesFileLoader(tmpFile.getAbsolutePath(), null);
PropertiesFileLoader loader2 = new PropertiesFileLoader(tmpFile.getAbsolutePath());
loader2.start(null);
Properties props2 = loader2.getProperties();
verifyProperties(props2, props2.size()+1, "ABC", null);
@@ -199,15 +199,15 @@ public void testChangeValue() throws Exception {
tmpFile = createTempFile();
writeTestDataToFile(tmpFile);

PropertiesFileLoader loader = new PropertiesFileLoader(tmpFile.getAbsolutePath(), null);
PropertiesFileLoader loader = new PropertiesFileLoader(tmpFile.getAbsolutePath());
loader.start(null);
Properties props = loader.getProperties();
props.put("ABC", "321");
loader.persistProperties();
loader.stop(null);

// reload the file and make sure the removed item has been removed
PropertiesFileLoader loader2 = new PropertiesFileLoader(tmpFile.getAbsolutePath(), null);
PropertiesFileLoader loader2 = new PropertiesFileLoader(tmpFile.getAbsolutePath());
loader2.start(null);
Properties props2 = loader2.getProperties();
verifyProperties(props2, props2.size(), "ABC", "321");
@@ -22,7 +22,10 @@
import java.nio.file.Path;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.HashSet;
import java.util.concurrent.TimeUnit;
import java.util.function.Consumer;
import java.util.function.Supplier;

import org.jboss.as.domain.management.SecurityRealm;
import org.jboss.msc.service.Service;
@@ -100,14 +103,14 @@ public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOEx
public void testDifferentServiceBuilderTypes() {
ServiceTarget serviceTarget = container.subTarget();

final SecurityRealmService securityRealmService = new SecurityRealmService(TESTNAME, false);
securityRealmService.getTmpDirPathInjector().inject(tmpDir.toAbsolutePath().toString());
final Supplier<String> tmpDirSupplier = () -> tmpDir.toAbsolutePath().toString();

final ServiceName realmServiceName = SecurityRealm.ServiceUtil.createServiceName(TESTNAME);
ServiceController<?> realmController = serviceTarget
.addService(realmServiceName, securityRealmService)
.addAliases(SecurityRealm.ServiceUtil.createLegacyServiceName(TESTNAME))
.install();
final ServiceBuilder<?> realmBuilder = serviceTarget.addService(realmServiceName);
final Consumer<SecurityRealm> securityRealmConsumer = realmBuilder.provides(realmServiceName, SecurityRealm.ServiceUtil.createLegacyServiceName(TESTNAME));
final SecurityRealmService securityRealmService = new SecurityRealmService(securityRealmConsumer, null, null, null, null, tmpDirSupplier, new HashSet(), TESTNAME, false);
realmBuilder.setInstance(securityRealmService);
final ServiceController<?> realmController = realmBuilder.install();

TestService legacy = new TestService();
ServiceBuilder legacyBuilder = serviceTarget.addService(ServiceName.of("LEGACY"), legacy);
@@ -71,7 +71,7 @@ public void testLoadEnabledDisabledUsers() throws IOException, StartException {
} finally {
writer.close();
}
UserPropertiesFileLoader propertiesLoad = new UserPropertiesFileLoader(usersPropertyFile.getAbsolutePath(), null);
UserPropertiesFileLoader propertiesLoad = new UserPropertiesFileLoader(usersPropertyFile.getAbsolutePath());
propertiesLoad.start(null);
assertEquals(1, propertiesLoad.getEnabledUserNames().size());
assertEquals(2, propertiesLoad.getDisabledUserNames().size());
@@ -103,7 +103,7 @@ public void testLoadEnabledDisabledUsersAfterUpdate() throws IOException, StartE
}

// make some updates
UserPropertiesFileLoader loader = new UserPropertiesFileLoader(usersPropertyFile.getAbsolutePath(), null);
UserPropertiesFileLoader loader = new UserPropertiesFileLoader(usersPropertyFile.getAbsolutePath());
loader.start(null);
Properties props = loader.getProperties();
props.put("newUser", "newPassword");
@@ -112,7 +112,7 @@ public void testLoadEnabledDisabledUsersAfterUpdate() throws IOException, StartE
loader.stop(null);

// reload the file and make sure everything is there
UserPropertiesFileLoader loader2 = new UserPropertiesFileLoader(usersPropertyFile.getAbsolutePath(), null);
UserPropertiesFileLoader loader2 = new UserPropertiesFileLoader(usersPropertyFile.getAbsolutePath());
loader2.start(null);
assertEquals(2, loader2.getEnabledUserNames().size());
assertEquals(2, loader2.getDisabledUserNames().size());
@@ -77,7 +77,7 @@ public void setUp() throws IOException {
}

protected Properties loadProperties(String filePath) throws StartException, IOException {
PropertiesFileLoader propertiesLoad = new PropertiesFileLoader(filePath, null);
PropertiesFileLoader propertiesLoad = new PropertiesFileLoader(filePath);
propertiesLoad.start(null);
Properties properties = (Properties) propertiesLoad.getProperties().clone();
propertiesLoad.stop(null);
@@ -68,8 +68,8 @@
*/

protected AuthorizingCallbackHandler getSlaveCallbackHandler() {
return ((SecurityRealm) getContainer().getService(SecurityRealm.ServiceUtil.createServiceName(SLAVE_REALM))
.getValue()).getAuthorizingCallbackHandler(AuthMechanism.PLAIN);
return SecurityRealmHelper.getSecurityRealm(getContainer(), SecurityRealm.ServiceUtil.createServiceName(SLAVE_REALM))
.getAuthorizingCallbackHandler(AuthMechanism.PLAIN);
}

@Test
@@ -49,8 +49,6 @@
import org.jboss.as.domain.management.connections.ldap.LdapConnectionManagerService;
import org.jboss.as.domain.management.security.operations.OutboundConnectionAddBuilder;
import org.jboss.dmr.ModelNode;
import org.jboss.msc.service.ServiceContainer;
import org.jboss.msc.service.ServiceController;
import org.wildfly.security.auth.callback.EvidenceVerifyCallback;
import org.wildfly.security.evidence.PasswordGuessEvidence;

@@ -84,10 +82,7 @@ private AuthorizingCallbackHandler getAuthorizingCallbackHandler(final String re
if (TEST_REALM.equals(realmName)) {
realm = securityRealm;
} else {
ServiceContainer container = getContainer();
ServiceController<?> service = container.getRequiredService(SecurityRealm.ServiceUtil.createServiceName(realmName));

realm = (SecurityRealm) service.getValue();
realm = SecurityRealmHelper.getSecurityRealm(getContainer(), SecurityRealm.ServiceUtil.createServiceName(realmName));
}

return realm.getAuthorizingCallbackHandler(AuthMechanism.PLAIN);
@@ -203,8 +203,8 @@ public void testVerifyIgnoredReferral() throws Exception {
*/

private AuthorizingCallbackHandler getAdvancedCallbackHandler() {
return ((SecurityRealm) getContainer().getService(SecurityRealm.ServiceUtil.createServiceName(ADVANCED_REALM))
.getValue()).getAuthorizingCallbackHandler(AuthMechanism.PLAIN);
return SecurityRealmHelper.getSecurityRealm(getContainer(), SecurityRealm.ServiceUtil.createServiceName(ADVANCED_REALM))
.getAuthorizingCallbackHandler(AuthMechanism.PLAIN);
}

@Test
@@ -0,0 +1,92 @@
/*
* JBoss, Home of Professional Open Source.
* Copyright 2019, Red Hat, Inc., and individual contributors
* as indicated by the @author tags. See the copyright.txt file in the
* distribution for a full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/

package org.jboss.as.domain.management.security.realms;

import org.jboss.as.domain.management.SecurityRealm;
import org.jboss.msc.Service;
import org.jboss.msc.service.ServiceBuilder;
import org.jboss.msc.service.ServiceController;
import org.jboss.msc.service.ServiceTarget;
import org.jboss.msc.service.ServiceName;
import org.jboss.msc.service.StabilityMonitor;
import org.jboss.msc.service.StartContext;
import org.jboss.msc.service.StopContext;

import java.util.function.Supplier;

final class SecurityRealmHelper {

private static final ServiceName SECURITY_REALM_GETTER = ServiceName.of("sec.realm.getter.for.test");

private SecurityRealmHelper() {
// forbidden instantiation
}

static SecurityRealm getSecurityRealm(final ServiceTarget target, final ServiceName securityRealmSN) {
SecurityRealm retVal = null;
ServiceBuilder<?> builder = target.addService(SECURITY_REALM_GETTER.append(securityRealmSN));
Supplier<SecurityRealm> securityRealmSupplier = builder.requires(securityRealmSN);
SecurityRealmGetterService service = new SecurityRealmGetterService(securityRealmSupplier);
builder.setInstance(service);
StabilityMonitor sm = new StabilityMonitor();
builder.addMonitor(sm);
ServiceController<?> ctrl = builder.install();
try {
sm.awaitStability();
retVal = service.securityRealmSupplier.get();
} catch (Throwable t) {
// ignored
} finally {
sm.clear();
ctrl.setMode(ServiceController.Mode.REMOVE);
try {
sm.awaitStability();
} catch (Throwable t) {
// ignored
} finally {
sm.removeController(ctrl);
}
}
return retVal;
}

private static final class SecurityRealmGetterService implements Service {

private final Supplier<SecurityRealm> securityRealmSupplier;

private SecurityRealmGetterService(final Supplier<SecurityRealm> securityRealmSupplier) {
this.securityRealmSupplier = securityRealmSupplier;
}

@Override
public void start(final StartContext startContext) {
// does nothing
}

@Override
public void stop(final StopContext stopContext) {
// does nothing
}
}

}
@@ -31,8 +31,6 @@
import org.jboss.as.domain.management.security.operations.SecurityRealmAddBuilder;
import org.jboss.as.domain.management.security.util.ManagementControllerTestBase;
import org.jboss.dmr.ModelNode;
import org.jboss.msc.service.ServiceContainer;
import org.jboss.msc.service.ServiceController;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
@@ -58,10 +56,7 @@ public void testRealmReady() {

@Before
public void lookupSecurityRealm() {
ServiceContainer container = getContainer();
ServiceController<?> service = container.getRequiredService(SecurityRealm.ServiceUtil.createServiceName(TEST_REALM));

securityRealm = (SecurityRealm) service.getValue();
securityRealm = SecurityRealmHelper.getSecurityRealm(getContainer(), SecurityRealm.ServiceUtil.createServiceName(TEST_REALM));
}

@After
@@ -53,6 +53,7 @@
*
* @author Emanuel Muckenhuber
* @author <a href="mailto:david.lloyd@redhat.com">David M. Lloyd</a>
* @author <a href="mailto:ropalka@redhat.com">Richard Opalka</a>
*/
class ServerInventoryService implements Service<ServerInventory> {

@@ -112,7 +113,7 @@ public synchronized void start(StartContext context) throws StartException {
processControllerConnectionService.setServerInventory(serverInventory);
serverCallback.getValue().setCallbackHandler(serverInventory.getServerCallbackHandler());
if (domainServerCallback != null && domainServerCallback.getValue() != null) {
domainServerCallback.getValue().getServerCallbackHandlerInjector().inject(serverInventory.getServerCallbackHandler());
domainServerCallback.getValue().setServerCallbackHandler(serverInventory.getServerCallbackHandler());
}
futureInventory.setInventory(serverInventory);
} catch (Exception e) {