diff --git a/controller/src/main/java/org/jboss/as/controller/descriptions/ModelDescriptionConstants.java b/controller/src/main/java/org/jboss/as/controller/descriptions/ModelDescriptionConstants.java
index c1e6aa6c3381..475f918d4ee2 100644
--- a/controller/src/main/java/org/jboss/as/controller/descriptions/ModelDescriptionConstants.java
+++ b/controller/src/main/java/org/jboss/as/controller/descriptions/ModelDescriptionConstants.java
@@ -142,6 +142,7 @@ public class ModelDescriptionConstants {
public static final String PRIORITY = "priority";
public static final String PROFILE = "profile";
public static final String PROFILE_NAME = "profile-name";
+ public static final String PROPERTIES = "properties";
public static final String PROTOCOL = "protocol";
public static final String READ_ATTRIBUTE_OPERATION = "read-attribute";
public static final String READ_CHILDREN_NAMES_OPERATION = "read-children-names";
diff --git a/controller/src/main/java/org/jboss/as/controller/parsing/CommonXml.java b/controller/src/main/java/org/jboss/as/controller/parsing/CommonXml.java
index e45288d7219b..f54d25baa72a 100644
--- a/controller/src/main/java/org/jboss/as/controller/parsing/CommonXml.java
+++ b/controller/src/main/java/org/jboss/as/controller/parsing/CommonXml.java
@@ -61,6 +61,7 @@
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.PATH;
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.PORT;
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.PORT_OFFSET;
+import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.PROPERTIES;
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.PROTOCOL;
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.RECURSIVE;
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.RELATIVE_TO;
@@ -692,14 +693,18 @@ protected void parseAuthentication(final XMLExtendedStreamReader reader, final M
throw unexpectedElement(reader);
}
switch (element) {
- case USERS: {
- parseUsersAuthentication(reader, authentication);
- break;
- }
case LDAP: {
parseLdapAuthentication(reader, authentication);
break;
}
+ case PROPERTIES: {
+ parsePropertiesAuthentication(reader, authentication);
+ break;
+ }
+ case USERS: {
+ parseUsersAuthentication(reader, authentication);
+ break;
+ }
default: {
throw unexpectedElement(reader);
}
@@ -783,7 +788,46 @@ protected void parseLdapAuthentication(final XMLExtendedStreamReader reader, fin
}
}
- // The user domain element defines users within the domain model, it is a simple authentication for some out of the box users.
+ protected void parsePropertiesAuthentication(final XMLExtendedStreamReader reader, final ModelNode authentication) throws XMLStreamException {
+ ModelNode properties = authentication.get(PROPERTIES);
+
+ String path = null;
+ String relativeTo = null;
+
+ final int count = reader.getAttributeCount();
+ for (int i = 0; i < count; i++) {
+ final String value = reader.getAttributeValue(i);
+ if (!isNoNamespaceAttribute(reader, i)) {
+ throw unexpectedAttribute(reader, i);
+ } else {
+ final Attribute attribute = Attribute.forName(reader.getAttributeLocalName(i));
+ switch (attribute) {
+ case PATH:
+ path = value;
+ break;
+ case RELATIVE_TO: {
+ relativeTo = value;
+ break;
+ }
+ default: {
+ throw unexpectedAttribute(reader, i);
+ }
+ }
+ }
+ }
+
+ if (path == null)
+ throw missingRequired(reader, Collections.singleton(Attribute.PATH));
+
+ requireNoContent(reader);
+
+ properties.get(PATH).set(path);
+ if (relativeTo != null) {
+ properties.get(RELATIVE_TO).set(relativeTo);
+ }
+ }
+
+ // The users element defines users within the domain model, it is a simple authentication for some out of the box users.
protected void parseUsersAuthentication(final XMLExtendedStreamReader reader, final ModelNode authentication) throws XMLStreamException {
ModelNode userDomain = authentication.get(USERS);
@@ -2289,6 +2333,15 @@ protected void writeManagement(final XMLExtendedStreamWriter writer, final Model
if (userLdap.hasDefined(USER_DN)) {
writer.writeAttribute(Attribute.USER_DN.getLocalName(), userLdap.require(USER_DN).asString());
}
+ writer.writeEndElement();
+ } else if (authentication.hasDefined(PROPERTIES)) {
+ ModelNode properties = authentication.require(PROPERTIES);
+ writer.writeStartElement(Element.PROPERTIES.getLocalName());
+ writer.writeAttribute(Attribute.PATH.getLocalName(), properties.require(PATH).asString());
+ if (properties.hasDefined(RELATIVE_TO)) {
+ writer.writeAttribute(Attribute.RELATIVE_TO.getLocalName(), properties.require(RELATIVE_TO).asString());
+ }
+
writer.writeEndElement();
}
diff --git a/controller/src/main/java/org/jboss/as/controller/parsing/Element.java b/controller/src/main/java/org/jboss/as/controller/parsing/Element.java
index 18f5a7d9f0bc..55e36a915522 100644
--- a/controller/src/main/java/org/jboss/as/controller/parsing/Element.java
+++ b/controller/src/main/java/org/jboss/as/controller/parsing/Element.java
@@ -104,6 +104,7 @@ public enum Element {
PROFILE("profile"),
PROFILES("profiles"),
PROPERTY("property"),
+ PROPERTIES("properties"),
PUBLIC_ADDRESS("public-address"),
REMOTE("remote"),
diff --git a/controller/src/main/resources/schema/jboss_7_0.xsd b/controller/src/main/resources/schema/jboss_7_0.xsd
index e4d3f1730936..6904048a6890 100644
--- a/controller/src/main/resources/schema/jboss_7_0.xsd
+++ b/controller/src/main/resources/schema/jboss_7_0.xsd
@@ -281,8 +281,9 @@
-
+
+
@@ -366,6 +367,31 @@
+
+
+
+ Declaration of users stored within properties files.
+
+
+
+
+
+ The name of another previously named path, or of one of the
+ standard paths provided by the system. If 'relative-to' is
+ provided, the value of the 'path' attribute is treated as
+ relative to the path specified by this attribute.
+
+
+
+
+
+
+ The path of the properties file containing the users.
+
+
+
+
+
diff --git a/domain-http-api/src/main/java/org/jboss/as/domain/http/server/ConsoleHandler.java b/domain-http-api/src/main/java/org/jboss/as/domain/http/server/ConsoleHandler.java
index ab805b0595f1..22c9698ae2b4 100644
--- a/domain-http-api/src/main/java/org/jboss/as/domain/http/server/ConsoleHandler.java
+++ b/domain-http-api/src/main/java/org/jboss/as/domain/http/server/ConsoleHandler.java
@@ -81,7 +81,6 @@ public ConsoleHandler(ClassLoader loader) {
this.loader = loader;
}
- @Override
public void handle(HttpExchange http) throws IOException {
final URI uri = http.getRequestURI();
final String requestMethod = http.getRequestMethod();
@@ -185,12 +184,10 @@ private ClassLoader getLoader() {
return ConsoleHandler.class.getClassLoader();
}
- @Override
public void start(HttpServer httpServer, SecurityRealm securityRealm) {
httpServer.createContext(CONTEXT, this);
}
- @Override
public void stop(HttpServer httpServer) {
httpServer.removeContext(CONTEXT);
}
diff --git a/domain-management/src/main/java/org/jboss/as/domain/management/operations/SecurityRealmAddHandler.java b/domain-management/src/main/java/org/jboss/as/domain/management/operations/SecurityRealmAddHandler.java
index 4273b1b9a61a..4c65f2ee0350 100644
--- a/domain-management/src/main/java/org/jboss/as/domain/management/operations/SecurityRealmAddHandler.java
+++ b/domain-management/src/main/java/org/jboss/as/domain/management/operations/SecurityRealmAddHandler.java
@@ -26,9 +26,11 @@
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.KEYSTORE;
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.LDAP;
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.OP_ADDR;
+import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.PROPERTIES;
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.RELATIVE_TO;
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.SERVER_IDENTITIES;
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.SSL;
+import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.USERS;
import java.util.Locale;
@@ -44,9 +46,13 @@
import org.jboss.as.controller.descriptions.DescriptionProvider;
import org.jboss.as.controller.descriptions.ModelDescriptionConstants;
import org.jboss.as.domain.management.connections.ConnectionManager;
+import org.jboss.as.domain.management.security.DomainCallbackHandler;
import org.jboss.as.domain.management.security.LdapConnectionManagerService;
+import org.jboss.as.domain.management.security.PropertiesCallbackHandler;
import org.jboss.as.domain.management.security.SSLIdentityService;
import org.jboss.as.domain.management.security.SecurityRealmService;
+import org.jboss.as.domain.management.security.UserDomainCallbackHandler;
+import org.jboss.as.domain.management.security.UserLdapCallbackHandler;
import org.jboss.dmr.ModelNode;
import org.jboss.msc.service.ServiceBuilder;
import org.jboss.msc.service.ServiceController;
@@ -81,65 +87,122 @@ public OperationResult execute(OperationContext context, ModelNode operation, fi
final ModelNode compensatingOperation = new ModelNode(); // TODO - Complete the remove.
if (context.getRuntimeContext() != null) {
- context.getRuntimeContext().setRuntimeTask(new RuntimeTask() {
- public void execute(RuntimeTaskContext context) throws OperationFailedException {
- final ServiceTarget serviceTarget = context.getServiceTarget();
+ context.getRuntimeContext().setRuntimeTask(new SecurityRealmAddTask(securityRealm, serverIdentities, authentication));
+ } else {
+ resultHandler.handleResultComplete();
+ }
+ return new BasicOperationResult(compensatingOperation);
+ }
- final SecurityRealmService securityRealmService = new SecurityRealmService(securityRealm, authentication);
- ServiceName realmServiceName = SecurityRealmService.BASE_SERVICE_NAME.append(securityRealm);
- ServiceBuilder realmBuilder = serviceTarget.addService(realmServiceName, securityRealmService);
+ // TODO - These need to be split into more fine grained services so allow service specific checks.
- String connectionManager = requiredConnectionManager(authentication);
- if (connectionManager != null) {
- realmBuilder.addDependency(LdapConnectionManagerService.BASE_SERVICE_NAME.append(connectionManager), ConnectionManager.class, securityRealmService.getConnectionManagerInjector());
- }
- // TODO - The operation will also be split out into it's own handler when I make the operations more fine grained.
- if (serverIdentities != null && serverIdentities.has(SSL)) {
- ModelNode ssl = serverIdentities.require(SSL);
- ServiceName sslServiceName = realmServiceName.append("ssl");
- SSLIdentityService sslIdentityService = new SSLIdentityService(ssl);
+ public ModelNode getModelDescription(Locale locale) {
+ // TODO - Complete getModelDescription()
+ return new ModelNode();
+ }
+}
- ServiceBuilder sslBuilder = serviceTarget.addService(sslServiceName, sslIdentityService);
+class SecurityRealmAddTask implements RuntimeTask {
- if (ssl.hasDefined(KEYSTORE) && ssl.get(KEYSTORE).hasDefined(RELATIVE_TO)) {
- sslBuilder.addDependency(pathName(ssl.get(KEYSTORE, RELATIVE_TO).asString()), String.class, sslIdentityService.getRelativeToInjector());
- }
+ final String realmName;
+ final ModelNode serverIdentities;
+ final ModelNode authentication;
- sslBuilder.setInitialMode(ServiceController.Mode.ON_DEMAND)
- .install();
+ SecurityRealmAddTask(String realmName, ModelNode serverIdentities, ModelNode authentication) {
+ this.realmName = realmName;
+ this.serverIdentities = serverIdentities;
+ this.authentication = authentication;
+ }
- realmBuilder.addDependency(sslServiceName, SSLIdentityService.class, securityRealmService.getSSLIdentityInjector());
- }
+ public void execute(RuntimeTaskContext context) throws OperationFailedException {
+ final ServiceTarget serviceTarget = context.getServiceTarget();
- realmBuilder.setInitialMode(ServiceController.Mode.ON_DEMAND)
- .install();
- }
- });
- } else {
- resultHandler.handleResultComplete();
+ final SecurityRealmService securityRealmService = new SecurityRealmService(realmName);
+ final ServiceName realmServiceName = SecurityRealmService.BASE_SERVICE_NAME.append(realmName);
+ ServiceBuilder realmBuilder = serviceTarget.addService(realmServiceName, securityRealmService);
+
+ ServiceName authenticationName = null;
+ if (authentication.hasDefined(LDAP)) {
+ authenticationName = addLdapService(authentication.require(LDAP), realmServiceName, serviceTarget);
+ } else if (authentication.hasDefined(PROPERTIES)) {
+ authenticationName = addPropertiesService(authentication.require(PROPERTIES), realmServiceName, realmName, serviceTarget);
+ } else if (authentication.hasDefined(USERS)) {
+ authenticationName = addUsersService(authentication.require(USERS), realmServiceName, realmName, serviceTarget);
}
- return new BasicOperationResult(compensatingOperation);
+ if (authenticationName != null) {
+ realmBuilder.addDependency(authenticationName, DomainCallbackHandler.class, securityRealmService.getCallbackHandlerInjector());
+ }
+
+ if (serverIdentities != null && serverIdentities.hasDefined(SSL)) {
+ ServiceName sslServiceName = addSSLService(serverIdentities.require(SSL), realmServiceName, serviceTarget);
+ realmBuilder.addDependency(sslServiceName, SSLIdentityService.class, securityRealmService.getSSLIdentityInjector());
+ }
+
+ realmBuilder.setInitialMode(ServiceController.Mode.ON_DEMAND)
+ .install();
}
- // TODO - These need to be split into more fine grained services so allow service specific checks.
+ private ServiceName addLdapService(ModelNode ldap, ServiceName realmServiceName, ServiceTarget serviceTarget) {
+ ServiceName ldapServiceName = realmServiceName.append(UserLdapCallbackHandler.SERVICE_SUFFIX);
+ UserLdapCallbackHandler ldapCallbackHandler = new UserLdapCallbackHandler(ldap);
+
+ ServiceBuilder ldapBuilder = serviceTarget.addService(ldapServiceName, ldapCallbackHandler);
+ String connectionManager = ldap.require(CONNECTION).asString();
+ ldapBuilder.addDependency(LdapConnectionManagerService.BASE_SERVICE_NAME.append(connectionManager), ConnectionManager.class, ldapCallbackHandler.getConnectionManagerInjector());
+
+ ldapBuilder.setInitialMode(ServiceController.Mode.ON_DEMAND)
+ .install();
- private static String requiredConnectionManager(ModelNode authentication) {
- String connectionManager = null;
- if (authentication != null && authentication.hasDefined(LDAP)) {
- ModelNode userLdap = authentication.require(LDAP);
- connectionManager = userLdap.require(CONNECTION).asString();
+ return ldapServiceName;
+ }
+
+ private ServiceName addPropertiesService(ModelNode properties, ServiceName realmServiceName, String realmName, ServiceTarget serviceTarget) {
+ ServiceName propsServiceName = realmServiceName.append(PropertiesCallbackHandler.SERVICE_SUFFIX);
+ PropertiesCallbackHandler propsCallbackHandler = new PropertiesCallbackHandler(realmName, properties);
+
+ ServiceBuilder propsBuilder = serviceTarget.addService(propsServiceName, propsCallbackHandler);
+ if (properties.hasDefined(RELATIVE_TO)) {
+ propsBuilder.addDependency(pathName(properties.get(RELATIVE_TO).asString()), String.class, propsCallbackHandler.getRelativeToInjector());
}
- return connectionManager;
+ propsBuilder.setInitialMode(ServiceController.Mode.ON_DEMAND)
+ .install();
+
+ return propsServiceName;
}
- private static ServiceName pathName(String relativeTo) {
- return ServiceName.JBOSS.append("server", "path", relativeTo);
+ // TODO - The operation will also be split out into it's own handler when I make the operations more fine grained.
+ private ServiceName addSSLService(ModelNode ssl, ServiceName realmServiceName, ServiceTarget serviceTarget) {
+ ServiceName sslServiceName = realmServiceName.append(SSLIdentityService.SERVICE_SUFFIX);
+ SSLIdentityService sslIdentityService = new SSLIdentityService(ssl);
+
+ ServiceBuilder sslBuilder = serviceTarget.addService(sslServiceName, sslIdentityService);
+
+ if (ssl.hasDefined(KEYSTORE) && ssl.get(KEYSTORE).hasDefined(RELATIVE_TO)) {
+ sslBuilder.addDependency(pathName(ssl.get(KEYSTORE, RELATIVE_TO).asString()), String.class, sslIdentityService.getRelativeToInjector());
+ }
+
+ sslBuilder.setInitialMode(ServiceController.Mode.ON_DEMAND)
+ .install();
+
+ return sslServiceName;
}
- public ModelNode getModelDescription(Locale locale) {
- // TODO - Complete getModelDescription()
- return new ModelNode();
+ private ServiceName addUsersService(ModelNode users, ServiceName realmServiceName, String realmName, ServiceTarget serviceTarget) {
+ ServiceName usersServiceName = realmServiceName.append(UserDomainCallbackHandler.SERVICE_SUFFIX);
+ UserDomainCallbackHandler usersCallbackHandler = new UserDomainCallbackHandler(realmName, users);
+
+ ServiceBuilder usersBuilder = serviceTarget.addService(usersServiceName, usersCallbackHandler);
+
+
+ usersBuilder.setInitialMode(ServiceController.Mode.ON_DEMAND)
+ .install();
+
+ return usersServiceName;
+ }
+
+ private static ServiceName pathName(String relativeTo) {
+ return ServiceName.JBOSS.append("server", "path", relativeTo);
}
}
diff --git a/domain-management/src/main/java/org/jboss/as/domain/management/security/PropertiesCallbackHandler.java b/domain-management/src/main/java/org/jboss/as/domain/management/security/PropertiesCallbackHandler.java
new file mode 100644
index 000000000000..e294db9f89b7
--- /dev/null
+++ b/domain-management/src/main/java/org/jboss/as/domain/management/security/PropertiesCallbackHandler.java
@@ -0,0 +1,162 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2011, 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;
+
+import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.PATH;
+
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.NameCallback;
+import javax.security.auth.callback.PasswordCallback;
+import javax.security.auth.callback.UnsupportedCallbackException;
+import javax.security.sasl.AuthorizeCallback;
+import javax.security.sasl.RealmCallback;
+import java.io.File;
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Properties;
+
+import org.jboss.dmr.ModelNode;
+import org.jboss.msc.service.Service;
+import org.jboss.msc.service.StartContext;
+import org.jboss.msc.service.StartException;
+import org.jboss.msc.service.StopContext;
+import org.jboss.msc.value.InjectedValue;
+
+/**
+ * A CallbackHandler obtaining the users and their passwords from a properties file.
+ *
+ * @author Darran Lofthouse
+ */
+public class PropertiesCallbackHandler implements Service, DomainCallbackHandler {
+
+ public static final String SERVICE_SUFFIX = "properties";
+
+ private static final Class[] supportedCallbacks = {RealmCallback.class, NameCallback.class, PasswordCallback.class};
+
+ private final String realm;
+ private final String path;
+ private final InjectedValue relativeTo = new InjectedValue();
+ private final Properties users = new Properties();
+
+ public PropertiesCallbackHandler(String realm, ModelNode properties) {
+ this.realm = realm;
+ path = properties.require(PATH).asString();
+ }
+
+ /*
+ * Service Methods
+ */
+
+ public void start(StartContext context) throws StartException {
+ String relativeTo = this.relativeTo.getOptionalValue();
+ String file = relativeTo == null ? path : relativeTo + "/" + path;
+
+ File propertiesFile = new File(file);
+ try {
+ users.load(propertiesFile.toURI().toURL().openStream());
+ } catch (MalformedURLException mue) {
+ throw new StartException("Unable to load properties", mue);
+ } catch (IOException ioe) {
+ throw new StartException("Unable to load properties", ioe);
+ }
+ }
+
+ public void stop(StopContext context) {
+ users.clear();
+ }
+
+ public PropertiesCallbackHandler getValue() throws IllegalStateException, IllegalArgumentException {
+ return this;
+ }
+
+ /*
+ * Injector Accessors
+ */
+
+ public InjectedValue getRelativeToInjector() {
+ return relativeTo;
+ }
+
+ /*
+ * DomainCallbackHandler Methods
+ */
+
+ public Class[] getSupportedCallbacks() {
+ return supportedCallbacks;
+ }
+
+ public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
+ List toRespondTo = new LinkedList();
+
+ String userName = null;
+ boolean userFound = false;
+
+ // A single pass may be sufficient but by using a two pass approach the Callbackhandler will not
+ // fail if an unexpected order is encountered.
+
+ // First Pass - is to double check no unsupported callbacks and to retrieve
+ // information from the callbacks passing in information.
+ for (Callback current : callbacks) {
+
+ if (current instanceof AuthorizeCallback) {
+ toRespondTo.add(current);
+ } else if (current instanceof NameCallback) {
+ NameCallback nameCallback = (NameCallback) current;
+ userName = nameCallback.getDefaultName();
+ userFound = users.containsKey(userName);
+ } else if (current instanceof PasswordCallback) {
+ toRespondTo.add(current);
+ } else if (current instanceof RealmCallback) {
+ String realm = ((RealmCallback) current).getDefaultText();
+ if (this.realm.equals(realm) == false) {
+ // TODO - Check if this needs a real error or of just an unexpected internal error.
+ throw new IllegalStateException("Invalid Realm '" + realm + "' expected '" + this.realm + "'");
+ }
+ } else {
+ throw new UnsupportedCallbackException(current);
+ }
+ }
+
+ if (userFound == false) {
+ // TODO - Again proper error reporting.
+ throw new IllegalStateException("User '" + userName + "' not found.");
+ }
+
+ // Second Pass - Now iterate the Callback(s) requiring a response.
+ for (Callback current : toRespondTo) {
+ if (current instanceof AuthorizeCallback) {
+ AuthorizeCallback authorizeCallback = (AuthorizeCallback) current;
+ // Don't support impersonating another identity
+ authorizeCallback.setAuthorized(authorizeCallback.getAuthenticationID().equals(authorizeCallback.getAuthorizedID()));
+ } else if (current instanceof PasswordCallback) {
+ String password = users.get(userName).toString();
+ ((PasswordCallback) current).setPassword(password.toCharArray());
+ }
+ }
+
+ }
+
+
+}
diff --git a/domain-management/src/main/java/org/jboss/as/domain/management/security/SSLIdentityService.java b/domain-management/src/main/java/org/jboss/as/domain/management/security/SSLIdentityService.java
index 455d3da79acc..4ea3bec8d43e 100644
--- a/domain-management/src/main/java/org/jboss/as/domain/management/security/SSLIdentityService.java
+++ b/domain-management/src/main/java/org/jboss/as/domain/management/security/SSLIdentityService.java
@@ -54,6 +54,8 @@
*/
public class SSLIdentityService implements Service {
+ public static final String SERVICE_SUFFIX = "ssl";
+
private final ModelNode ssl;
private final InjectedValue relativeTo = new InjectedValue();
diff --git a/domain-management/src/main/java/org/jboss/as/domain/management/security/SecurityRealmService.java b/domain-management/src/main/java/org/jboss/as/domain/management/security/SecurityRealmService.java
index 66239fff060a..809a527be0d0 100644
--- a/domain-management/src/main/java/org/jboss/as/domain/management/security/SecurityRealmService.java
+++ b/domain-management/src/main/java/org/jboss/as/domain/management/security/SecurityRealmService.java
@@ -22,35 +22,13 @@
package org.jboss.as.domain.management.security;
-import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.FILE;
-import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.KEYSTORE;
-import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.LDAP;
-import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.PASSWORD;
-import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.PATH;
-import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.PROTOCOL;
-import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.SSL;
-import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.USERS;
-
-import javax.net.ssl.KeyManager;
-import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.security.auth.callback.Callback;
import javax.security.auth.callback.UnsupportedCallbackException;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
import java.io.IOException;
-import java.security.KeyManagementException;
-import java.security.KeyStore;
-import java.security.KeyStoreException;
-import java.security.NoSuchAlgorithmException;
-import java.security.UnrecoverableKeyException;
-import java.security.cert.CertificateException;
-
-import org.jboss.as.domain.management.connections.ConnectionManager;
+
import org.jboss.as.domain.management.SecurityRealm;
-import org.jboss.dmr.ModelNode;
import org.jboss.logging.Logger;
-import org.jboss.msc.inject.Injector;
import org.jboss.msc.service.Service;
import org.jboss.msc.service.ServiceName;
import org.jboss.msc.service.StartContext;
@@ -67,43 +45,19 @@
public class SecurityRealmService implements Service, SecurityRealm {
public static final ServiceName BASE_SERVICE_NAME = ServiceName.JBOSS.append("server", "controller", "management", "security_realm");
- private static final Logger log = Logger.getLogger("org.jboss.as");
+ private static final Logger log = Logger.getLogger("org.jboss.as.domain-management");
- private final InjectedValue connectionManagerValue = new InjectedValue();
- private final InjectedValue relativeTo = new InjectedValue();
+ private final InjectedValue callbackHandler = new InjectedValue();
private final InjectedValue sslIdentity = new InjectedValue();
private final String name;
- private ModelNode authentication;
- private DomainCallbackHandler callbackHandler;
-
- private SSLContext sslContext;
-
- public SecurityRealmService(String name, ModelNode authentication) {
+ public SecurityRealmService(String name) {
this.name = name;
- this.authentication = authentication;
}
public void start(StartContext context) throws StartException {
log.infof("Starting '%s' Security Realm Service", name);
- if (authentication != null && authentication.hasDefined(USERS)) {
- callbackHandler = new UserDomainCallbackHandler(name, authentication.require(USERS));
- } else if (authentication != null && authentication.hasDefined(LDAP)) {
- callbackHandler = new UserLdapCallbackHandler(connectionManagerValue.getValue(), authentication.require(LDAP));
- } else {
- callbackHandler = new DomainCallbackHandler() {
-
- public Class[] getSupportedCallbacks() {
- return new Class[0];
- }
-
- public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
- // TODO - Should be a real error with code.
- throw new IllegalStateException("No authentication mechanism defined in security realm.");
- }
- };
- }
}
public void stop(StopContext context) {
@@ -118,23 +72,35 @@ public String getName() {
return name;
}
- public InjectedValue getConnectionManagerInjector() {
- return connectionManagerValue;
+ public InjectedValue getCallbackHandlerInjector() {
+ return callbackHandler;
}
-
public InjectedValue getSSLIdentityInjector() {
return sslIdentity;
}
-
/**
* Used to obtain the callback handler for the configured 'authorizations'.
*
* @return The CallbackHandler to be used for verifying the identity of the caller.
*/
public DomainCallbackHandler getCallbackHandler() {
- return callbackHandler;
+ DomainCallbackHandler response = callbackHandler.getOptionalValue();
+ if (response == null) {
+ response = new DomainCallbackHandler() {
+ public Class[] getSupportedCallbacks() {
+ return new Class[0];
+ }
+
+ public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
+ // TODO - Should be a real error with code.
+ throw new IllegalStateException("No authentication mechanism defined in security realm.");
+ }
+ };
+ }
+
+ return response;
}
public SSLContext getSSLContext() {
diff --git a/domain-management/src/main/java/org/jboss/as/domain/management/security/UserDomainCallbackHandler.java b/domain-management/src/main/java/org/jboss/as/domain/management/security/UserDomainCallbackHandler.java
index 35cc8abefe02..211ac01a25b3 100644
--- a/domain-management/src/main/java/org/jboss/as/domain/management/security/UserDomainCallbackHandler.java
+++ b/domain-management/src/main/java/org/jboss/as/domain/management/security/UserDomainCallbackHandler.java
@@ -36,13 +36,19 @@
import java.util.List;
import org.jboss.dmr.ModelNode;
+import org.jboss.msc.service.Service;
+import org.jboss.msc.service.StartContext;
+import org.jboss.msc.service.StartException;
+import org.jboss.msc.service.StopContext;
/**
* A CallbackHandler for users defined within the domain mode.
*
* @author Darran Lofthouse
*/
-public class UserDomainCallbackHandler implements DomainCallbackHandler {
+public class UserDomainCallbackHandler implements Service, DomainCallbackHandler {
+
+ public static final String SERVICE_SUFFIX = "users";
private static final Class[] supportedCallbacks = {RealmCallback.class, NameCallback.class, PasswordCallback.class};
@@ -50,11 +56,29 @@ public class UserDomainCallbackHandler implements DomainCallbackHandler {
private final ModelNode userDomain;
- UserDomainCallbackHandler(String realm, ModelNode userDomain) {
+ public UserDomainCallbackHandler(String realm, ModelNode userDomain) {
this.realm = realm;
this.userDomain = userDomain;
}
+ /*
+ * Service Methods
+ */
+
+ public void start(StartContext context) throws StartException {
+ }
+
+ public void stop(StopContext context) {
+ }
+
+ public UserDomainCallbackHandler getValue() throws IllegalStateException, IllegalArgumentException {
+ return this;
+ }
+
+ /*
+ * DomainCallbackHandler Methods
+ */
+
public Class[] getSupportedCallbacks() {
return supportedCallbacks;
}
diff --git a/domain-management/src/main/java/org/jboss/as/domain/management/security/UserLdapCallbackHandler.java b/domain-management/src/main/java/org/jboss/as/domain/management/security/UserLdapCallbackHandler.java
index 1b88e768e95a..1d069d874d64 100644
--- a/domain-management/src/main/java/org/jboss/as/domain/management/security/UserLdapCallbackHandler.java
+++ b/domain-management/src/main/java/org/jboss/as/domain/management/security/UserLdapCallbackHandler.java
@@ -43,18 +43,25 @@
import org.jboss.as.domain.management.connections.ConnectionManager;
import org.jboss.dmr.ModelNode;
+import org.jboss.msc.service.Service;
+import org.jboss.msc.service.StartContext;
+import org.jboss.msc.service.StartException;
+import org.jboss.msc.service.StopContext;
+import org.jboss.msc.value.InjectedValue;
/**
* A CallbackHandler for users within an LDAP directory.
*
* @author Darran Lofthouse
*/
-public class UserLdapCallbackHandler implements DomainCallbackHandler {
+public class UserLdapCallbackHandler implements Service, DomainCallbackHandler {
+
+ public static final String SERVICE_SUFFIX = "ldap";
private static final Class[] supportedCallbacks = {RealmCallback.class, NameCallback.class, VerifyPasswordCallback.class};
private static final String DEFAULT_USER_DN = "dn";
- private final ConnectionManager connectionManager;
+ private final InjectedValue connectionManager = new InjectedValue();
private final String baseDn;
private final String usernameAttribute;
@@ -62,8 +69,7 @@ public class UserLdapCallbackHandler implements DomainCallbackHandler {
private final String userDn;
protected final int searchTimeLimit = 10000; // TODO - Maybe make configurable.
- public UserLdapCallbackHandler(ConnectionManager connectionManager, ModelNode userLdap) {
- this.connectionManager = connectionManager;
+ public UserLdapCallbackHandler(ModelNode userLdap) {
baseDn = userLdap.require(BASE_DN).asString();
usernameAttribute = userLdap.require(USERNAME_ATTRIBUTE).asString();
if (userLdap.has(RECURSIVE)) {
@@ -78,6 +84,33 @@ public UserLdapCallbackHandler(ConnectionManager connectionManager, ModelNode us
}
}
+ /*
+ * Service Methods
+ */
+
+ public void start(StartContext context) throws StartException {
+ }
+
+ public void stop(StopContext context) {
+ }
+
+ public UserLdapCallbackHandler getValue() throws IllegalStateException, IllegalArgumentException {
+ return this;
+ }
+
+ /*
+ * Access to Injectors
+ */
+
+ public InjectedValue getConnectionManagerInjector() {
+ return connectionManager;
+ }
+
+
+ /*
+ * DomainCallbackHandler Methods
+ */
+
public Class[] getSupportedCallbacks() {
// TODO - For safety this Array should be cloned or should use an unmodifiable collection to ensure
// TODO - caller can not modify.
@@ -85,6 +118,7 @@ public Class[] getSupportedCallbacks() {
}
public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
+ ConnectionManager connectionManager = this.connectionManager.getValue();
String username = null;
VerifyPasswordCallback verifyPasswordCallback = null;