You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@servicemix.apache.org by gn...@apache.org on 2006/08/31 10:24:45 UTC
svn commit: r438836 -
/incubator/servicemix/trunk/servicemix-core/src/main/java/org/apache/servicemix/jbi/management/
Author: gnodet
Date: Thu Aug 31 01:24:44 2006
New Revision: 438836
URL: http://svn.apache.org/viewvc?rev=438836&view=rev
Log:
Remove dependency on mx4j-tools
Add factory beans for jmx server, jmx connector, rmi registry and jmx password authentication
Added:
incubator/servicemix/trunk/servicemix-core/src/main/java/org/apache/servicemix/jbi/management/ConnectorServerFactoryBean.java
incubator/servicemix/trunk/servicemix-core/src/main/java/org/apache/servicemix/jbi/management/PasswordAuthenticator.java
incubator/servicemix/trunk/servicemix-core/src/main/java/org/apache/servicemix/jbi/management/PasswordAuthenticatorFactoryBean.java
incubator/servicemix/trunk/servicemix-core/src/main/java/org/apache/servicemix/jbi/management/RmiRegistryFactoryBean.java
Modified:
incubator/servicemix/trunk/servicemix-core/src/main/java/org/apache/servicemix/jbi/management/MBeanServerContext.java
Added: incubator/servicemix/trunk/servicemix-core/src/main/java/org/apache/servicemix/jbi/management/ConnectorServerFactoryBean.java
URL: http://svn.apache.org/viewvc/incubator/servicemix/trunk/servicemix-core/src/main/java/org/apache/servicemix/jbi/management/ConnectorServerFactoryBean.java?rev=438836&view=auto
==============================================================================
--- incubator/servicemix/trunk/servicemix-core/src/main/java/org/apache/servicemix/jbi/management/ConnectorServerFactoryBean.java (added)
+++ incubator/servicemix/trunk/servicemix-core/src/main/java/org/apache/servicemix/jbi/management/ConnectorServerFactoryBean.java Thu Aug 31 01:24:44 2006
@@ -0,0 +1,132 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.servicemix.jbi.management;
+
+import java.util.Map;
+import java.util.Properties;
+
+import javax.management.MBeanServer;
+import javax.management.MalformedObjectNameException;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.springframework.beans.factory.DisposableBean;
+import org.springframework.beans.factory.FactoryBean;
+import org.springframework.beans.factory.InitializingBean;
+
+public class ConnectorServerFactoryBean implements FactoryBean, InitializingBean, DisposableBean{
+
+ private Log log = LogFactory.getLog(ConnectorServerFactoryBean.class);
+ private String serviceUrl = org.springframework.jmx.support.ConnectorServerFactoryBean.DEFAULT_SERVICE_URL;
+ private org.springframework.jmx.support.ConnectorServerFactoryBean csfb = new org.springframework.jmx.support.ConnectorServerFactoryBean();
+
+ /**
+ * @param daemon
+ * @see org.springframework.jmx.support.ConnectorServerFactoryBean#setDaemon(boolean)
+ */
+ public void setDaemon(boolean daemon) {
+ csfb.setDaemon(daemon);
+ }
+
+ /**
+ * @param environment
+ * @see org.springframework.jmx.support.ConnectorServerFactoryBean#setEnvironment(java.util.Properties)
+ */
+ public void setEnvironment(Properties environment) {
+ csfb.setEnvironment(environment);
+ }
+
+ /**
+ * @param environment
+ * @see org.springframework.jmx.support.ConnectorServerFactoryBean#setEnvironmentMap(java.util.Map)
+ */
+ public void setEnvironmentMap(Map environment) {
+ csfb.setEnvironmentMap(environment);
+ }
+
+ /**
+ * @param objectName
+ * @throws MalformedObjectNameException
+ * @see org.springframework.jmx.support.ConnectorServerFactoryBean#setObjectName(java.lang.String)
+ */
+ public void setObjectName(String objectName) throws MalformedObjectNameException {
+ csfb.setObjectName(objectName);
+ }
+
+ /**
+ * @param registrationBehavior
+ * @see org.springframework.jmx.support.MBeanRegistrationSupport#setRegistrationBehavior(int)
+ */
+ public void setRegistrationBehavior(int registrationBehavior) {
+ csfb.setRegistrationBehavior(registrationBehavior);
+ }
+
+ /**
+ * @param registrationBehavior
+ * @see org.springframework.jmx.support.MBeanRegistrationSupport#setRegistrationBehaviorName(java.lang.String)
+ */
+ public void setRegistrationBehaviorName(String registrationBehavior) {
+ csfb.setRegistrationBehaviorName(registrationBehavior);
+ }
+
+ /**
+ * @param server
+ * @see org.springframework.jmx.support.MBeanRegistrationSupport#setServer(javax.management.MBeanServer)
+ */
+ public void setServer(MBeanServer server) {
+ csfb.setServer(server);
+ }
+
+ /**
+ * @param serviceUrl
+ * @see org.springframework.jmx.support.ConnectorServerFactoryBean#setServiceUrl(java.lang.String)
+ */
+ public void setServiceUrl(String serviceUrl) {
+ this.serviceUrl = serviceUrl;
+ }
+
+ /**
+ * @param threaded
+ * @see org.springframework.jmx.support.ConnectorServerFactoryBean#setThreaded(boolean)
+ */
+ public void setThreaded(boolean threaded) {
+ csfb.setThreaded(threaded);
+ }
+
+ public Object getObject() throws Exception {
+ return csfb.getObject();
+ }
+
+ public Class getObjectType() {
+ return csfb.getObjectType();
+ }
+
+ public boolean isSingleton() {
+ return csfb.isSingleton();
+ }
+
+ public void afterPropertiesSet() throws Exception {
+ csfb.setServiceUrl(serviceUrl);
+ csfb.afterPropertiesSet();
+ log.info("JMX connector available at: " + serviceUrl);
+ }
+
+ public void destroy() throws Exception {
+ csfb.destroy();
+ }
+
+}
Modified: incubator/servicemix/trunk/servicemix-core/src/main/java/org/apache/servicemix/jbi/management/MBeanServerContext.java
URL: http://svn.apache.org/viewvc/incubator/servicemix/trunk/servicemix-core/src/main/java/org/apache/servicemix/jbi/management/MBeanServerContext.java?rev=438836&r1=438835&r2=438836&view=diff
==============================================================================
--- incubator/servicemix/trunk/servicemix-core/src/main/java/org/apache/servicemix/jbi/management/MBeanServerContext.java (original)
+++ incubator/servicemix/trunk/servicemix-core/src/main/java/org/apache/servicemix/jbi/management/MBeanServerContext.java Thu Aug 31 01:24:44 2006
@@ -32,7 +32,6 @@
import javax.management.remote.JMXConnectorServerFactory;
import javax.management.remote.JMXServiceURL;
-import org.apache.activemq.broker.jmx.ManagementContext;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@@ -297,7 +296,7 @@
result=createMBeanServer();
}
}catch(NoClassDefFoundError e){
- log.error("Couldnot load MBeanServer",e);
+ log.error("Could not load MBeanServer",e);
}catch(Throwable e){
// probably don't have access to system properties
log.error("Failed to initialize MBeanServer",e);
@@ -391,7 +390,7 @@
String serviceURL="service:jmx:rmi:///jndi/rmi://localhost:"+connectorPort+connectorPath;
JMXServiceURL url=new JMXServiceURL(serviceURL);
connectorServer=JMXConnectorServerFactory.newJMXConnectorServer(url,null,mbeanServer);
- // log.info("JMX consoles can connect to serviceURL: " + serviceURL);
+ log.info("JMX connector available at: " + serviceURL);
}
public String getConnectorPath(){
Added: incubator/servicemix/trunk/servicemix-core/src/main/java/org/apache/servicemix/jbi/management/PasswordAuthenticator.java
URL: http://svn.apache.org/viewvc/incubator/servicemix/trunk/servicemix-core/src/main/java/org/apache/servicemix/jbi/management/PasswordAuthenticator.java?rev=438836&view=auto
==============================================================================
--- incubator/servicemix/trunk/servicemix-core/src/main/java/org/apache/servicemix/jbi/management/PasswordAuthenticator.java (added)
+++ incubator/servicemix/trunk/servicemix-core/src/main/java/org/apache/servicemix/jbi/management/PasswordAuthenticator.java Thu Aug 31 01:24:44 2006
@@ -0,0 +1,275 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.servicemix.jbi.management;
+
+/*
+ * Copyright (C) The MX4J Contributors.
+ * All rights reserved.
+ *
+ * This software is distributed under the terms of the MX4J License version 1.0.
+ * See the terms of the MX4J License in the documentation provided with this software.
+ */
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Set;
+import javax.management.remote.JMXAuthenticator;
+import javax.management.remote.JMXPrincipal;
+import javax.security.auth.Subject;
+
+import mx4j.util.Base64Codec;
+
+/**
+ * Implementation of the JMXAuthenticator interface to be used on server side
+ * to secure access to {@link javax.management.remote.JMXConnectorServer JMXConnectorServer}s. <br/>
+ * Usage:
+ * <pre>
+ * JMXAuthenticator authenticator = new PasswordAuthenticator(new File("users.properties"));
+ * Map environment = new HashMap();
+ * environment.put(JMXConnectorServer.AUTHENTICATOR, authenticator);
+ * JMXServiceURL address = new JMXServiceURL("rmi", "localhost", 0);
+ * MBeanServer server = ...;
+ * JMXConnectorServer cntorServer = JMXConnectorServerFactory.newJMXConnectorServer(address, environment, server);
+ * </pre>
+ * The format of the users.properties file is that of a standard properties file: <br/>
+ * <user>=<password><br/>
+ * where <password> can be stored in 2 ways:
+ * <ul>
+ * <li>Clear text: the password is written in clear text</li>
+ * <li>Obfuscated text: the password is obfuscated</li>
+ * </ul>
+ * The obfuscated form can be obtained running this class as a main class:
+ * <pre>
+ * java -cp mx4j-remote.jar mx4j.tools.remote.PasswordAuthenticator
+ * </pre>
+ * and following the instructions printed on the console. The output will be a string that should be
+ * copy/pasted as the password into the properties file.<br/>
+ * The obfuscated password is obtained by digesting the clear text password using a
+ * {@link java.security.MessageDigest} algorithm, and then by Base64-encoding the resulting bytes.<br/>
+ * <br/>
+ * On client side, you are allowed to connect to a server side secured with the PasswordAuthenticator
+ * only if you provide the correct credentials:
+ * <pre>
+ * String[] credentials = new String[2];
+ * // The user will travel as clear text
+ * credentials[0] = "user";
+ * // You may send the password in clear text, but it's better to obfuscate it
+ * credentials[1] = PasswordAuthenticator.obfuscatePassword("password");
+ * Map environment = new HashMap();
+ * environment.put(JMXConnector.CREDENTIALS, credentials);
+ * JMXServiceURL address = ...;
+ * JMXConnector cntor = JMXConnectorFactory.connect(address, environment);
+ * </pre>
+ * Note that {@link #obfuscatePassword(java.lang.String,java.lang.String) obfuscating} the passwords only works if the server side has been
+ * setup with the PasswordAuthenticator.
+ * However, the PasswordAuthenticator can be used with other JSR 160 implementations, such as Sun's reference
+ * implementation.
+ *
+ * @version $Revision: 1.3 $
+ */
+public class PasswordAuthenticator implements JMXAuthenticator
+{
+ private static final String LEFT_DELIMITER = "OBF(";
+ private static final String RIGHT_DELIMITER = "):";
+
+ /**
+ * Runs this class as main class to obfuscate passwords.
+ * When no arguments are provided, it prints out the usage.
+ *
+ * @see #obfuscatePassword(java.lang.String,java.lang.String)
+ */
+ public static void main(String[] args) throws Exception
+ {
+ if (args.length == 1)
+ {
+ if (!"-help".equals(args[0]))
+ {
+ printPassword("MD5", args[0]);
+ return;
+ }
+ }
+ else if (args.length == 3)
+ {
+ if ("-alg".equals(args[0]))
+ {
+ printPassword(args[1], args[2]);
+ return;
+ }
+ }
+ printUsage();
+ }
+
+ private static void printPassword(String algorithm, String input)
+ {
+ String password = obfuscatePassword(input, algorithm);
+ System.out.println(password);
+ }
+
+ private static void printUsage()
+ {
+ System.out.println();
+ System.out.println("Usage: java -cp <lib>/mx4j-tools.jar mx4j.tools.remote.PasswordAuthenticator <options> <password>");
+ System.out.println("Where <options> is one of the following:");
+ System.out.println(" -help Prints this message");
+ System.out.println(" -alg <digest algorithm> Specifies the digest algorithm (default is MD5)");
+ System.out.println();
+ }
+
+ /**
+ * Obfuscates the given password using MD5 as digest algorithm
+ *
+ * @see #obfuscatePassword(java.lang.String,java.lang.String)
+ */
+ public static String obfuscatePassword(String password)
+ {
+ return obfuscatePassword(password, "MD5");
+ }
+
+ /**
+ * Obfuscates the given password using the given digest algorithm.<br/>
+ * Obfuscation consists of 2 steps: first the clear text password is {@link java.security.MessageDigest#digest digested}
+ * using the specified algorithm, then the resulting bytes are Base64-encoded.<br/>
+ * For example, the obfuscated version of the password "password" is "OBF(MD5):X03MO1qnZdYdgyfeuILPmQ=="
+ * or "OBF(SHA-1):W6ph5Mm5Pz8GgiULbPgzG37mj9g=". <br/>
+ * OBF stands for "obfuscated", in parenthesis the algorithm used to digest the password.
+ */
+ public static String obfuscatePassword(String password, String algorithm)
+ {
+ try
+ {
+ MessageDigest digest = MessageDigest.getInstance(algorithm);
+ byte[] digestedBytes = digest.digest(password.getBytes());
+ byte[] obfuscatedBytes = Base64Codec.encodeBase64(digestedBytes);
+ return LEFT_DELIMITER + algorithm + RIGHT_DELIMITER + new String(obfuscatedBytes);
+ }
+ catch (NoSuchAlgorithmException x)
+ {
+ throw new SecurityException("Could not find digest algorithm " + algorithm);
+ }
+ }
+
+ private Map passwords;
+
+ /**
+ * Creates a new PasswordAuthenticator that reads user/password pairs from the specified properties file.
+ * The file format is described in the javadoc of this class.
+ *
+ * @see #obfuscatePassword
+ */
+ public PasswordAuthenticator(File passwordFile) throws IOException
+ {
+ this(new FileInputStream(passwordFile));
+ }
+
+ /**
+ * Creates a new PasswordAuthenticator that reads user/password pairs from the specified InputStream.
+ * The file format is described in the javadoc of this class.
+ *
+ * @see #obfuscatePassword
+ */
+ public PasswordAuthenticator(InputStream is) throws IOException
+ {
+ passwords = readPasswords(is);
+ }
+
+ private Map readPasswords(InputStream is) throws IOException
+ {
+ Properties properties = new Properties();
+ try
+ {
+ properties.load(is);
+ }
+ finally
+ {
+ is.close();
+ }
+ return new HashMap(properties);
+ }
+
+ public Subject authenticate(Object credentials) throws SecurityException
+ {
+ if (!(credentials instanceof String[])) throw new SecurityException("Bad credentials");
+ String[] creds = (String[])credentials;
+ if (creds.length != 2) throw new SecurityException("Bad credentials");
+
+ String user = creds[0];
+ String password = creds[1];
+
+ if (password == null) throw new SecurityException("Bad password");
+
+ if (!passwords.containsKey(user)) throw new SecurityException("Unknown user " + user);
+
+ String storedPassword = (String)passwords.get(user);
+ if (!isPasswordCorrect(password, storedPassword)) throw new SecurityException("Bad password");
+
+ Set principals = new HashSet();
+ principals.add(new JMXPrincipal(user));
+ return new Subject(true, principals, Collections.EMPTY_SET, Collections.EMPTY_SET);
+ }
+
+ private boolean isPasswordCorrect(String password, String storedPassword)
+ {
+ if (password.startsWith(LEFT_DELIMITER))
+ {
+ if (storedPassword.startsWith(LEFT_DELIMITER))
+ {
+ return password.equals(storedPassword);
+ }
+ else
+ {
+ String algorithm = getAlgorithm(password);
+ String obfuscated = obfuscatePassword(storedPassword, algorithm);
+ return password.equals(obfuscated);
+ }
+ }
+ else
+ {
+ if (storedPassword.startsWith(LEFT_DELIMITER))
+ {
+ // Password was sent in clear, bad practice
+ String algorithm = getAlgorithm(storedPassword);
+ String obfuscated = obfuscatePassword(password, algorithm);
+ return obfuscated.equals(storedPassword);
+ }
+ else
+ {
+ return password.equals(storedPassword);
+ }
+ }
+ }
+
+ private String getAlgorithm(String obfuscatedPassword)
+ {
+ try
+ {
+ return obfuscatedPassword.substring(LEFT_DELIMITER.length(), obfuscatedPassword.indexOf(RIGHT_DELIMITER));
+ }
+ catch (IndexOutOfBoundsException x)
+ {
+ throw new SecurityException("Bad password");
+ }
+ }
+}
Added: incubator/servicemix/trunk/servicemix-core/src/main/java/org/apache/servicemix/jbi/management/PasswordAuthenticatorFactoryBean.java
URL: http://svn.apache.org/viewvc/incubator/servicemix/trunk/servicemix-core/src/main/java/org/apache/servicemix/jbi/management/PasswordAuthenticatorFactoryBean.java?rev=438836&view=auto
==============================================================================
--- incubator/servicemix/trunk/servicemix-core/src/main/java/org/apache/servicemix/jbi/management/PasswordAuthenticatorFactoryBean.java (added)
+++ incubator/servicemix/trunk/servicemix-core/src/main/java/org/apache/servicemix/jbi/management/PasswordAuthenticatorFactoryBean.java Thu Aug 31 01:24:44 2006
@@ -0,0 +1,56 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.servicemix.jbi.management;
+
+import org.springframework.beans.factory.FactoryBean;
+import org.springframework.core.io.Resource;
+
+public class PasswordAuthenticatorFactoryBean implements FactoryBean {
+
+ private Resource passwords;
+ private PasswordAuthenticator authenticator;
+
+ /**
+ * @return the passwords
+ */
+ public Resource getPasswords() {
+ return passwords;
+ }
+
+ /**
+ * @param passwords the passwords to set
+ */
+ public void setPasswords(Resource passwords) {
+ this.passwords = passwords;
+ }
+
+ public Object getObject() throws Exception {
+ if (authenticator == null) {
+ authenticator = new PasswordAuthenticator(passwords.getInputStream());
+ }
+ return authenticator;
+ }
+
+ public Class getObjectType() {
+ return PasswordAuthenticator.class;
+ }
+
+ public boolean isSingleton() {
+ return true;
+ }
+
+}
Added: incubator/servicemix/trunk/servicemix-core/src/main/java/org/apache/servicemix/jbi/management/RmiRegistryFactoryBean.java
URL: http://svn.apache.org/viewvc/incubator/servicemix/trunk/servicemix-core/src/main/java/org/apache/servicemix/jbi/management/RmiRegistryFactoryBean.java?rev=438836&view=auto
==============================================================================
--- incubator/servicemix/trunk/servicemix-core/src/main/java/org/apache/servicemix/jbi/management/RmiRegistryFactoryBean.java (added)
+++ incubator/servicemix/trunk/servicemix-core/src/main/java/org/apache/servicemix/jbi/management/RmiRegistryFactoryBean.java Thu Aug 31 01:24:44 2006
@@ -0,0 +1,68 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.servicemix.jbi.management;
+
+import java.rmi.registry.LocateRegistry;
+import java.rmi.registry.Registry;
+import java.rmi.server.UnicastRemoteObject;
+
+import org.springframework.beans.factory.DisposableBean;
+import org.springframework.beans.factory.FactoryBean;
+import org.springframework.beans.factory.InitializingBean;
+
+public class RmiRegistryFactoryBean implements FactoryBean, InitializingBean, DisposableBean{
+
+ private int port = Registry.REGISTRY_PORT;
+ private Registry registry;
+
+ /**
+ * @return the port
+ */
+ public int getPort() {
+ return port;
+ }
+
+ /**
+ * @param port the port to set
+ */
+ public void setPort(int port) {
+ this.port = port;
+ }
+
+ public Object getObject() throws Exception {
+ return registry;
+ }
+
+ public Class getObjectType() {
+ return Registry.class;
+ }
+
+ public boolean isSingleton() {
+ return true;
+ }
+
+ public void afterPropertiesSet() throws Exception {
+ registry = LocateRegistry.createRegistry(getPort());
+ }
+
+ public void destroy() throws Exception {
+ if (registry != null) {
+ UnicastRemoteObject.unexportObject(registry, true);
+ }
+ }
+
+}