Skip to content

Commit

Permalink
[AS7-833] Properties file based repository of users for domain manage…
Browse files Browse the repository at this point in the history
…ment.
  • Loading branch information
darranl authored and kabir committed May 26, 2011
1 parent 0916311 commit 9c93124
Show file tree
Hide file tree
Showing 11 changed files with 441 additions and 112 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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);
}
Expand Down Expand Up @@ -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);

Expand Down Expand Up @@ -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();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ public enum Element {
PROFILE("profile"),
PROFILES("profiles"),
PROPERTY("property"),
PROPERTIES("properties"),
PUBLIC_ADDRESS("public-address"),

REMOTE("remote"),
Expand Down
28 changes: 27 additions & 1 deletion controller/src/main/resources/schema/jboss_7_0.xsd
Original file line number Diff line number Diff line change
Expand Up @@ -281,8 +281,9 @@
</xs:documentation>
</xs:annotation>
<xs:choice>
<xs:element name="users" type="usersAuthenticationType" minOccurs="0" />
<xs:element name="ldap" type="ldapAuthenticationType" minOccurs="0" />
<xs:element name="properties" type="propertiesAuthenticationType" minOccurs="0" />
<xs:element name="users" type="usersAuthenticationType" minOccurs="0" />
</xs:choice>
<xs:attribute name="useDomainController" type="xs:boolean" default="false">
<xs:annotation>
Expand Down Expand Up @@ -366,6 +367,31 @@
</xs:attribute>
</xs:complexType>

<xs:complexType name="propertiesAuthenticationType">
<xs:annotation>
<xs:documentation>
Declaration of users stored within properties files.
</xs:documentation>
</xs:annotation>
<xs:attribute name="relative-to" use="optional" type="xs:string">
<xs:annotation>
<xs:documentation>
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.
</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="path" type="xs:string" use="required">
<xs:annotation>
<xs:documentation>
The path of the properties file containing the users.
</xs:documentation>
</xs:annotation>
</xs:attribute>
</xs:complexType>

<xs:complexType name="management-interfaceType">
<xs:annotation>
<xs:documentation>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down Expand Up @@ -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);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -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;
Expand Down Expand Up @@ -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);
}
}

0 comments on commit 9c93124

Please sign in to comment.