You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@brooklyn.apache.org by ha...@apache.org on 2015/08/18 17:04:00 UTC
[51/64] [abbrv] incubator-brooklyn git commit: BROOKLYN-162 - apply
org.apache package prefix to jmx util/agent projects
BROOKLYN-162 - apply org.apache package prefix to jmx util/agent projects
Project: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/commit/e6ac83be
Tree: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/tree/e6ac83be
Diff: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/diff/e6ac83be
Branch: refs/heads/master
Commit: e6ac83be8f4e5c0e7dc70c46fa6fb854d90428e7
Parents: e114a25
Author: Alex Heneveld <al...@cloudsoftcorp.com>
Authored: Tue Aug 18 14:10:57 2015 +0100
Committer: Alex Heneveld <al...@cloudsoftcorp.com>
Committed: Tue Aug 18 14:51:57 2015 +0100
----------------------------------------------------------------------
.../java/brooklyn/entity/java/JmxSupport.java | 5 +-
.../brooklyn/entity/java/JmxmpSslSupport.java | 3 +-
.../java/brooklyn/event/feed/jmx/JmxHelper.java | 2 +-
.../java/brooklyn/entity/java/JavaOptsTest.java | 3 +-
.../entity/java/VanillaJavaAppTest.java | 3 +-
utils/jmx/jmxmp-ssl-agent/pom.xml | 4 +-
.../brooklyn/util/jmx/jmxmp/JmxmpAgent.java | 335 ------------------
.../brooklyn/util/jmx/jmxmp/JmxmpAgent.java | 337 +++++++++++++++++++
.../util/jmx/jmxmp/JmxmpAgentSslTest.java | 256 --------------
.../brooklyn/util/jmx/jmxmp/JmxmpClient.java | 88 -----
.../util/jmx/jmxmp/JmxmpAgentSslTest.java | 257 ++++++++++++++
.../brooklyn/util/jmx/jmxmp/JmxmpClient.java | 89 +++++
utils/jmx/jmxrmi-agent/pom.xml | 4 +-
.../brooklyn/util/jmx/jmxrmi/JmxRmiAgent.java | 188 -----------
.../brooklyn/util/jmx/jmxrmi/JmxRmiAgent.java | 190 +++++++++++
.../brooklyn/util/jmx/jmxrmi/JmxRmiClient.java | 47 ---
.../brooklyn/util/jmx/jmxrmi/JmxRmiClient.java | 47 +++
17 files changed, 930 insertions(+), 928 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e6ac83be/software/base/src/main/java/brooklyn/entity/java/JmxSupport.java
----------------------------------------------------------------------
diff --git a/software/base/src/main/java/brooklyn/entity/java/JmxSupport.java b/software/base/src/main/java/brooklyn/entity/java/JmxSupport.java
index b519804..58b148b 100644
--- a/software/base/src/main/java/brooklyn/entity/java/JmxSupport.java
+++ b/software/base/src/main/java/brooklyn/entity/java/JmxSupport.java
@@ -43,14 +43,13 @@ import org.apache.brooklyn.location.basic.SshMachineLocation;
import org.apache.brooklyn.util.collections.MutableList;
import org.apache.brooklyn.util.collections.MutableMap;
import org.apache.brooklyn.util.guava.Maybe;
+import org.apache.brooklyn.util.jmx.jmxmp.JmxmpAgent;
+import org.apache.brooklyn.util.jmx.jmxrmi.JmxRmiAgent;
import org.apache.brooklyn.util.maven.MavenArtifact;
import org.apache.brooklyn.util.maven.MavenRetriever;
import org.apache.brooklyn.util.net.Urls;
import org.apache.brooklyn.util.text.Strings;
-import brooklyn.util.jmx.jmxmp.JmxmpAgent;
-import brooklyn.util.jmx.jmxrmi.JmxRmiAgent;
-
import com.google.common.base.Preconditions;
import com.google.common.net.HostAndPort;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e6ac83be/software/base/src/main/java/brooklyn/entity/java/JmxmpSslSupport.java
----------------------------------------------------------------------
diff --git a/software/base/src/main/java/brooklyn/entity/java/JmxmpSslSupport.java b/software/base/src/main/java/brooklyn/entity/java/JmxmpSslSupport.java
index 51587ab..99601e8 100644
--- a/software/base/src/main/java/brooklyn/entity/java/JmxmpSslSupport.java
+++ b/software/base/src/main/java/brooklyn/entity/java/JmxmpSslSupport.java
@@ -31,10 +31,9 @@ import org.apache.brooklyn.core.util.crypto.SecureKeys;
import org.apache.brooklyn.core.util.task.Tasks;
import org.apache.brooklyn.util.collections.MutableMap.Builder;
import org.apache.brooklyn.util.exceptions.Exceptions;
+import org.apache.brooklyn.util.jmx.jmxmp.JmxmpAgent;
import org.apache.brooklyn.util.net.Urls;
-import brooklyn.util.jmx.jmxmp.JmxmpAgent;
-
import com.google.common.base.Preconditions;
public class JmxmpSslSupport {
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e6ac83be/software/base/src/main/java/brooklyn/event/feed/jmx/JmxHelper.java
----------------------------------------------------------------------
diff --git a/software/base/src/main/java/brooklyn/event/feed/jmx/JmxHelper.java b/software/base/src/main/java/brooklyn/event/feed/jmx/JmxHelper.java
index 7a4a3a0..4438c2d 100644
--- a/software/base/src/main/java/brooklyn/event/feed/jmx/JmxHelper.java
+++ b/software/base/src/main/java/brooklyn/event/feed/jmx/JmxHelper.java
@@ -65,6 +65,7 @@ import org.apache.brooklyn.core.util.crypto.SecureKeys;
import org.apache.brooklyn.util.crypto.SslTrustUtils;
import org.apache.brooklyn.util.exceptions.Exceptions;
import org.apache.brooklyn.util.exceptions.RuntimeInterruptedException;
+import org.apache.brooklyn.util.jmx.jmxmp.JmxmpAgent;
import org.apache.brooklyn.util.repeat.Repeater;
import org.apache.brooklyn.util.time.Duration;
import org.apache.brooklyn.util.time.Time;
@@ -73,7 +74,6 @@ import org.slf4j.LoggerFactory;
import brooklyn.entity.java.JmxSupport;
import brooklyn.entity.java.UsesJmx;
-import brooklyn.util.jmx.jmxmp.JmxmpAgent;
import com.google.common.base.Preconditions;
import com.google.common.base.Throwables;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e6ac83be/software/base/src/test/java/brooklyn/entity/java/JavaOptsTest.java
----------------------------------------------------------------------
diff --git a/software/base/src/test/java/brooklyn/entity/java/JavaOptsTest.java b/software/base/src/test/java/brooklyn/entity/java/JavaOptsTest.java
index bfe8af8..0bc08b0 100644
--- a/software/base/src/test/java/brooklyn/entity/java/JavaOptsTest.java
+++ b/software/base/src/test/java/brooklyn/entity/java/JavaOptsTest.java
@@ -46,10 +46,9 @@ import org.apache.brooklyn.location.basic.SshMachineLocation;
import org.apache.brooklyn.util.collections.MutableList;
import org.apache.brooklyn.util.collections.MutableMap;
import org.apache.brooklyn.util.collections.MutableSet;
+import org.apache.brooklyn.util.jmx.jmxmp.JmxmpAgent;
import org.apache.brooklyn.util.text.Strings;
-import brooklyn.util.jmx.jmxmp.JmxmpAgent;
-
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.MapDifference.ValueDifference;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e6ac83be/software/base/src/test/java/brooklyn/entity/java/VanillaJavaAppTest.java
----------------------------------------------------------------------
diff --git a/software/base/src/test/java/brooklyn/entity/java/VanillaJavaAppTest.java b/software/base/src/test/java/brooklyn/entity/java/VanillaJavaAppTest.java
index da65c68..c0fd3e3 100644
--- a/software/base/src/test/java/brooklyn/entity/java/VanillaJavaAppTest.java
+++ b/software/base/src/test/java/brooklyn/entity/java/VanillaJavaAppTest.java
@@ -50,6 +50,7 @@ import org.apache.brooklyn.test.Asserts;
import org.apache.brooklyn.test.entity.TestApplication;
import org.apache.brooklyn.util.collections.MutableMap;
import org.apache.brooklyn.util.crypto.SslTrustUtils;
+import org.apache.brooklyn.util.jmx.jmxmp.JmxmpAgent;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.testng.annotations.AfterMethod;
@@ -63,8 +64,6 @@ import brooklyn.event.feed.jmx.JmxHelper;
import org.apache.brooklyn.location.basic.LocalhostMachineProvisioningLocation;
import org.apache.brooklyn.location.basic.PortRanges;
-import brooklyn.util.jmx.jmxmp.JmxmpAgent;
-
import com.google.common.base.Predicate;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e6ac83be/utils/jmx/jmxmp-ssl-agent/pom.xml
----------------------------------------------------------------------
diff --git a/utils/jmx/jmxmp-ssl-agent/pom.xml b/utils/jmx/jmxmp-ssl-agent/pom.xml
index 10a45d9..77b5e41 100644
--- a/utils/jmx/jmxmp-ssl-agent/pom.xml
+++ b/utils/jmx/jmxmp-ssl-agent/pom.xml
@@ -107,8 +107,8 @@
<configuration>
<archive>
<manifestEntries>
- <Premain-Class>brooklyn.util.jmx.jmxmp.JmxmpAgent</Premain-Class>
- <Agent-Class>brooklyn.util.jmx.jmxmp.JmxmpAgent</Agent-Class>
+ <Premain-Class>org.apache.brooklyn.util.jmx.jmxmp.JmxmpAgent</Premain-Class>
+ <Agent-Class>org.apache.brooklyn.util.jmx.jmxmp.JmxmpAgent</Agent-Class>
</manifestEntries>
</archive>
</configuration>
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e6ac83be/utils/jmx/jmxmp-ssl-agent/src/main/java/brooklyn/util/jmx/jmxmp/JmxmpAgent.java
----------------------------------------------------------------------
diff --git a/utils/jmx/jmxmp-ssl-agent/src/main/java/brooklyn/util/jmx/jmxmp/JmxmpAgent.java b/utils/jmx/jmxmp-ssl-agent/src/main/java/brooklyn/util/jmx/jmxmp/JmxmpAgent.java
deleted file mode 100644
index f9697f8..0000000
--- a/utils/jmx/jmxmp-ssl-agent/src/main/java/brooklyn/util/jmx/jmxmp/JmxmpAgent.java
+++ /dev/null
@@ -1,335 +0,0 @@
-/*
- * 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 brooklyn.util.jmx.jmxmp;
-
-import java.io.FileInputStream;
-import java.lang.management.ManagementFactory;
-import java.net.InetAddress;
-import java.net.UnknownHostException;
-import java.rmi.registry.LocateRegistry;
-import java.security.KeyStore;
-import java.security.cert.X509Certificate;
-import java.util.ArrayList;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Properties;
-
-import javax.management.MBeanServer;
-import javax.management.remote.JMXConnectorServer;
-import javax.management.remote.JMXConnectorServerFactory;
-import javax.management.remote.JMXServiceURL;
-import javax.management.remote.rmi.RMIConnectorServer;
-import javax.net.ssl.KeyManagerFactory;
-import javax.net.ssl.SSLContext;
-import javax.net.ssl.SSLSocketFactory;
-import javax.net.ssl.TrustManager;
-import javax.net.ssl.TrustManagerFactory;
-import javax.net.ssl.X509TrustManager;
-
-
-/**
- * This exposes JMX access over JMXMP, suitable for high-security environments,
- * with support for going through firewalls as well as encrypting and authenticating securely.
- * <p>
- * Listens on 11099 unless overridden by system property brooklyn.jmxmp.port.
- * <p>
- * Use the usual com.sun.management.jmxremote.ssl to enable both SSL _and_ authentication
- * (setting brooklyn.jmxmp.ssl.authenticate false if you need to disable authentication for some reason);
- * unless you disable client-side server authentication you will need to supply brooklyn.jmxmp.ssl.keyStore,
- * and similarly unless server-side client auth is off you'll need the corresponding trustStore
- * (both pointing to files on the local file system).
- * <p>
- * Service comes up on: service:jmx:jmxmp://${HOSTNAME}:${PORT}
- * <p>
- * If {@link #RMI_REGISTRY_PORT_PROPERTY} is also set, this agent will start a normal JMX/RMI server bound to
- * all interfaces, which is contactable on: service:jmx:rmi:///jndi/rmi://${HOSTNAME}:${RMI_REGISTRY_PORT}/jmxrmi
- * <p>
- * NB: To use JConsole with this endpoing, you need the jmxremote_optional JAR, and the
- * following command (even more complicated if using SSL):
- * java -classpath $JAVA_HOME/lib/jconsole.jar:$HOME/.m2/repository/javax/management/jmxremote_optional/1.0.1_04/jmxremote_optional-1.0.1_04.jar sun.tools.jconsole.JConsole
- */
-public class JmxmpAgent {
-
- /** port to listen on; default to {@link #JMXMP_DEFAULT_PORT} */
- public static final String JMXMP_PORT_PROPERTY = "brooklyn.jmxmp.port";
- /** hostname to advertise, and if {@value #JMX_SERVER_ADDRESS_WILDCARD_PROPERTY} is false also the hostname/interface to bind to */
- public static final String RMI_HOSTNAME_PROPERTY = "java.rmi.server.hostname";
- /** whether JMX should bind to all interfaces */
- public static final String JMX_SERVER_ADDRESS_WILDCARD_PROPERTY = "jmx.remote.server.address.wildcard";
-
- /** optional port for RMI registry to listen on; if not supplied, RMI is disabled. 1099 is a common choice.
- * it will *always* use an anonymous high-numbered port as the rmi server it redirects to
- * (ie it behaves like the default JMX agent, not the custom JmxRmiAgent). */
- public static final String RMI_REGISTRY_PORT_PROPERTY = "brooklyn.jmxmp.rmi-port";
-
- /** whether to use SSL (TLS) encryption; requires a keystore to be set */
- public static final String USE_SSL_PROPERTY = "com.sun.management.jmxremote.ssl";
- /** whether to use SSL (TLS) certificates to authenticate the client;
- * requires a truststore to be set, and requires {@link #USE_SSL_PROPERTY} true
- * (different to 'com.sun.management.jmxremote.authenticate' because something else
- * insists on intercepting that and uses it for passwords);
- * defaults to true iff {@link #USE_SSL_PROPERTY} is set because
- * who wouldn't want client authentication if you're encrypting the link */
- public static final String AUTHENTICATE_CLIENTS_PROPERTY = "brooklyn.jmxmp.ssl.authenticate";
-
- public static final String JMXMP_KEYSTORE_FILE_PROPERTY = "brooklyn.jmxmp.ssl.keyStore";
- public static final String JMXMP_KEYSTORE_PASSWORD_PROPERTY = "brooklyn.jmxmp.ssl.keyStorePassword";
- public static final String JMXMP_KEYSTORE_KEY_PASSWORD_PROPERTY = "brooklyn.jmxmp.ssl.keyStore.keyPassword";
- public static final String JMXMP_KEYSTORE_TYPE_PROPERTY = "brooklyn.jmxmp.ssl.keyStoreType";
-
- public static final String JMXMP_TRUSTSTORE_FILE_PROPERTY = "brooklyn.jmxmp.ssl.trustStore";
- public static final String JMXMP_TRUSTSTORE_PASSWORD_PROPERTY = "brooklyn.jmxmp.ssl.trustStorePassword";
- public static final String JMXMP_TRUSTSTORE_TYPE_PROPERTY = "brooklyn.jmxmp.ssl.trustStoreType";
-
- // properties above affect behaviour; those below are simply used in code
-
-
- public static final String TLS_NEED_AUTHENTICATE_CLIENTS_PROPERTY = "jmx.remote.tls.need.client.authentication";
- public static final String TLS_WANT_AUTHENTICATE_CLIENTS_PROPERTY = "jmx.remote.tls.want.client.authentication";
- public static final String TLS_SOCKET_FACTORY_PROPERTY = "jmx.remote.tls.socket.factory";
-
- public static final String TLS_JMX_REMOTE_PROFILES = "TLS";
- public static final int JMXMP_DEFAULT_PORT = 11099;
-
- public static void premain(String agentArgs) {
- doMain(agentArgs);
- }
-
- public static void agentmain(String agentArgs) {
- doMain(agentArgs);
- }
-
- public static void doMain(final String agentArgs) {
- // do the work in a daemon thread so that if the main class terminates abnormally,
- // such that shutdown hooks aren't called, we don't keep the application running
- // (e.g. if the app is compiled with java7 then run with java6, with a java6 agent here;
- // that causes the agent to launch, the main to fail, but the process to keep going)
- Thread t = new Thread() {
- public void run() {
- doMainForeground(agentArgs);
- }
- };
- t.setDaemon(true);
- t.start();
- }
-
- public static void doMainForeground(String agentArgs) {
- final List<JMXConnectorServer> connectors = new JmxmpAgent().startConnectors(System.getProperties());
- if (!connectors.isEmpty()) {
- Runtime.getRuntime().addShutdownHook(new Thread("jmxmp-agent-shutdownHookThread") {
- @Override public void run() {
- for (JMXConnectorServer connector: connectors) {
- try {
- connector.stop();
- } catch (Exception e) {
- System.err.println("Error closing jmxmp connector "+connector+" in shutdown hook (continuing): "+e);
- }
- }
- }});
- }
- }
-
- public List<JMXConnectorServer> startConnectors(Properties properties) {
- List<JMXConnectorServer> connectors = new ArrayList<JMXConnectorServer>();
- addIfNotNull(startJmxmpConnector(properties), connectors);
- addIfNotNull(startNormalJmxRmiConnectorIfRequested(properties), connectors);
- return connectors;
- }
-
- private static <T> void addIfNotNull(T item, List<T> list) {
- if (item!=null) list.add(item);
- }
-
- public JMXConnectorServer startJmxmpConnector(Properties properties) {
- try {
- final int port = Integer.parseInt(properties.getProperty(JMXMP_PORT_PROPERTY, ""+JMXMP_DEFAULT_PORT));
-
- String hostname = getLocalhostHostname(properties);
- JMXServiceURL serviceUrl = new JMXServiceURL("service:jmx:jmxmp://"+hostname+":"+port);
-
- Map<String,Object> env = new LinkedHashMap<String, Object>();
- propagate(properties, env, JMX_SERVER_ADDRESS_WILDCARD_PROPERTY, null);
-
- if (asBoolean(properties, USE_SSL_PROPERTY, false, true)) {
- setSslEnvFromProperties(env, properties);
- } else {
- if (asBoolean(properties, AUTHENTICATE_CLIENTS_PROPERTY, false, true)) {
- throw new IllegalStateException("Client authentication not supported when not using SSL");
- }
- }
- MBeanServer platformMBeanServer = ManagementFactory.getPlatformMBeanServer();
-
- JMXConnectorServer connector = JMXConnectorServerFactory.newJMXConnectorServer(serviceUrl, env, platformMBeanServer);
- connector.start();
-
- System.out.println("JmxmpAgent active at: "+serviceUrl);
-
- return connector;
- } catch (RuntimeException e) {
- System.err.println("Unable to start JmxmpAgent: "+e);
- throw e;
- } catch (Exception e) {
- System.err.println("Unable to start JmxmpAgent: "+e);
- throw new RuntimeException(e);
- }
- }
-
- /** optionally starts a normal JMXRMI connector in addition */
- public JMXConnectorServer startNormalJmxRmiConnectorIfRequested(Properties properties) {
- try {
- String rmiPortS = properties.getProperty(RMI_REGISTRY_PORT_PROPERTY);
- if (rmiPortS==null || rmiPortS.length()==0)
- return null;
-
- int rmiPort = Integer.parseInt(rmiPortS);
- LocateRegistry.createRegistry(rmiPort);
- MBeanServer mbeanServer = ManagementFactory.getPlatformMBeanServer();
- String svc =
- "service:jmx:rmi:///jndi/rmi://localhost:"+rmiPort+"/jmxrmi";
-
- JMXServiceURL url = new JMXServiceURL(svc);
- RMIConnectorServer rmiServer = new RMIConnectorServer(url, null, mbeanServer);
- rmiServer.start();
- return rmiServer;
- } catch (Exception e) {
- System.err.println("Unable to start JmxmpAgent: "+e);
- throw new RuntimeException(e);
- }
- }
-
- public static String getLocalhostHostname(Properties properties) throws UnknownHostException {
- String hostname = properties==null ? null : properties.getProperty(RMI_HOSTNAME_PROPERTY);
- if (hostname==null || hostname.isEmpty()) {
- try {
- hostname = InetAddress.getLocalHost().getHostName();
- } catch (Exception e) {
- System.err.println("Misconfigured hostname when setting JmxmpAgent; reverting to 127.0.0.1: "+e);
- hostname = "127.0.0.1";
- }
- }
- return hostname;
- }
-
- /** copies the value of key from the source to the target, if set;
- * otherwise sets the defaultValueIfNotNull (final arg) if that is not null;
- * returns whether anything is set
- */
- private static boolean propagate(Properties source, Map<String, Object> target, String key, Object defaultValueIfNotNull) {
- Object v = source.getProperty(key);
- if (v==null) v = defaultValueIfNotNull;
- if (v==null) return false;
- target.put(key, v);
- return true;
- }
-
- /** returns boolean interpretation of a string,
- * defaulting to valueIfUnknownText (last arg) if the value is unset or unrecognised,
- * throwing exception if that is null and value is unset or unrecognised */
- private boolean asBoolean(Properties properties, String key, Boolean valueIfNull, Boolean valueIfUnknownText) {
- Object v = properties.get(key);
- if (v==null) {
- if (valueIfNull==null) throw new IllegalStateException("Property '"+key+"' is required.");
- return valueIfNull;
- }
- String vv = v.toString();
- if ("true".equalsIgnoreCase(vv)) return true;
- if ("false".equalsIgnoreCase(vv)) return false;
- if (valueIfUnknownText==null)
- throw new IllegalStateException("Property '"+key+"' has illegal value '"+vv+"'; should be true or false");
- return valueIfUnknownText;
- }
-
- public void setSslEnvFromProperties(Map<String, Object> env, Properties properties) throws Exception {
- env.put("jmx.remote.profiles", TLS_JMX_REMOTE_PROFILES);
-
- boolean authenticating = asBoolean(properties, AUTHENTICATE_CLIENTS_PROPERTY, true, null);
- if (authenticating) {
- env.put(AUTHENTICATE_CLIENTS_PROPERTY, "true");
- // NB: the above seem to be ignored (horrid API!); we need the ones below set
- propagate(properties, env, TLS_NEED_AUTHENTICATE_CLIENTS_PROPERTY, "true");
- // also note, the above seems to be overridden by below internally !
- // (setting WANT=false and NEED=true allows access if no trust managers are specified)
- propagate(properties, env, TLS_WANT_AUTHENTICATE_CLIENTS_PROPERTY, "true");
- }
-
-
- if (!propagate(properties, env, TLS_SOCKET_FACTORY_PROPERTY, null)) {
- String keyStoreFile = properties.getProperty(JMXMP_KEYSTORE_FILE_PROPERTY);
- String keyStorePass = properties.getProperty(JMXMP_KEYSTORE_PASSWORD_PROPERTY, "");
- String keyStoreType = properties.getProperty(JMXMP_KEYSTORE_TYPE_PROPERTY, KeyStore.getDefaultType());
- String keyStoreKeyPass = properties.getProperty(JMXMP_KEYSTORE_KEY_PASSWORD_PROPERTY, "");
-
- KeyStore ks = KeyStore.getInstance(keyStoreType);
- if (keyStoreFile!=null)
- ks.load(new FileInputStream(keyStoreFile), keyStorePass.toCharArray());
- else
- ks.load(null, null);
- KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
- kmf.init(ks, keyStoreKeyPass.toCharArray());
-
- String trustStoreFile = properties.getProperty(JMXMP_TRUSTSTORE_FILE_PROPERTY);
- String trustStorePass = properties.getProperty(JMXMP_TRUSTSTORE_PASSWORD_PROPERTY, "");
- String trustStoreType = properties.getProperty(JMXMP_TRUSTSTORE_TYPE_PROPERTY, KeyStore.getDefaultType());
-
- TrustManager[] tms;
- if (trustStoreFile!=null) {
- TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
- KeyStore ts = KeyStore.getInstance(trustStoreType);
- ts.load(new FileInputStream(trustStoreFile), trustStorePass.toCharArray());
- tmf.init(ts);
-// tms = tmf.getTrustManagers();
- // line above causes tests to fail! bug in JMXMP TLS impl?
- tms = new TrustManager[] { newInspectAllTrustManager((X509TrustManager) tmf.getTrustManagers()[0]) };
- } else {
- tms = null;
- if (authenticating)
- System.err.println("Authentication required but no truststore supplied to JmxmpAgent. Client connections will likely fail.");
- }
-
- SSLContext ctx = SSLContext.getInstance("TLSv1");
- ctx.init(kmf.getKeyManagers(), tms, null);
- SSLSocketFactory ssf = ctx.getSocketFactory();
- env.put(TLS_SOCKET_FACTORY_PROPERTY, ssf);
- }
- }
-
- public static final TrustManager newInspectAllTrustManager(final X509TrustManager delegate) {
- return new X509TrustManager() {
- public X509Certificate[] getAcceptedIssuers() {
- // overriding this method fixes bug where non-accepted issuers have an "accept all" policy, in JMXMP/TLS
- return new X509Certificate[0];
- }
- @Override
- public void checkClientTrusted(X509Certificate[] chain, String authType)
- throws java.security.cert.CertificateException {
- delegate.checkClientTrusted(chain, authType);
- }
- @Override
- public void checkServerTrusted(X509Certificate[] chain, String authType)
- throws java.security.cert.CertificateException {
- delegate.checkServerTrusted(chain, authType);
- }
- };
- };
-
- public static void main(String[] args) {
- premain("");
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e6ac83be/utils/jmx/jmxmp-ssl-agent/src/main/java/org/apache/brooklyn/util/jmx/jmxmp/JmxmpAgent.java
----------------------------------------------------------------------
diff --git a/utils/jmx/jmxmp-ssl-agent/src/main/java/org/apache/brooklyn/util/jmx/jmxmp/JmxmpAgent.java b/utils/jmx/jmxmp-ssl-agent/src/main/java/org/apache/brooklyn/util/jmx/jmxmp/JmxmpAgent.java
new file mode 100644
index 0000000..0ac40bc
--- /dev/null
+++ b/utils/jmx/jmxmp-ssl-agent/src/main/java/org/apache/brooklyn/util/jmx/jmxmp/JmxmpAgent.java
@@ -0,0 +1,337 @@
+/*
+ * 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.brooklyn.util.jmx.jmxmp;
+
+import java.io.FileInputStream;
+import java.lang.management.ManagementFactory;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.rmi.registry.LocateRegistry;
+import java.security.KeyStore;
+import java.security.cert.X509Certificate;
+import java.util.ArrayList;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+
+import javax.management.MBeanServer;
+import javax.management.remote.JMXConnectorServer;
+import javax.management.remote.JMXConnectorServerFactory;
+import javax.management.remote.JMXServiceURL;
+import javax.management.remote.rmi.RMIConnectorServer;
+import javax.net.ssl.KeyManagerFactory;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLSocketFactory;
+import javax.net.ssl.TrustManager;
+import javax.net.ssl.TrustManagerFactory;
+import javax.net.ssl.X509TrustManager;
+
+import org.apache.brooklyn.util.jmx.jmxmp.JmxmpAgent;
+
+
+/**
+ * This exposes JMX access over JMXMP, suitable for high-security environments,
+ * with support for going through firewalls as well as encrypting and authenticating securely.
+ * <p>
+ * Listens on 11099 unless overridden by system property brooklyn.jmxmp.port.
+ * <p>
+ * Use the usual com.sun.management.jmxremote.ssl to enable both SSL _and_ authentication
+ * (setting brooklyn.jmxmp.ssl.authenticate false if you need to disable authentication for some reason);
+ * unless you disable client-side server authentication you will need to supply brooklyn.jmxmp.ssl.keyStore,
+ * and similarly unless server-side client auth is off you'll need the corresponding trustStore
+ * (both pointing to files on the local file system).
+ * <p>
+ * Service comes up on: service:jmx:jmxmp://${HOSTNAME}:${PORT}
+ * <p>
+ * If {@link #RMI_REGISTRY_PORT_PROPERTY} is also set, this agent will start a normal JMX/RMI server bound to
+ * all interfaces, which is contactable on: service:jmx:rmi:///jndi/rmi://${HOSTNAME}:${RMI_REGISTRY_PORT}/jmxrmi
+ * <p>
+ * NB: To use JConsole with this endpoing, you need the jmxremote_optional JAR, and the
+ * following command (even more complicated if using SSL):
+ * java -classpath $JAVA_HOME/lib/jconsole.jar:$HOME/.m2/repository/javax/management/jmxremote_optional/1.0.1_04/jmxremote_optional-1.0.1_04.jar sun.tools.jconsole.JConsole
+ */
+public class JmxmpAgent {
+
+ /** port to listen on; default to {@link #JMXMP_DEFAULT_PORT} */
+ public static final String JMXMP_PORT_PROPERTY = "brooklyn.jmxmp.port";
+ /** hostname to advertise, and if {@value #JMX_SERVER_ADDRESS_WILDCARD_PROPERTY} is false also the hostname/interface to bind to */
+ public static final String RMI_HOSTNAME_PROPERTY = "java.rmi.server.hostname";
+ /** whether JMX should bind to all interfaces */
+ public static final String JMX_SERVER_ADDRESS_WILDCARD_PROPERTY = "jmx.remote.server.address.wildcard";
+
+ /** optional port for RMI registry to listen on; if not supplied, RMI is disabled. 1099 is a common choice.
+ * it will *always* use an anonymous high-numbered port as the rmi server it redirects to
+ * (ie it behaves like the default JMX agent, not the custom JmxRmiAgent). */
+ public static final String RMI_REGISTRY_PORT_PROPERTY = "brooklyn.jmxmp.rmi-port";
+
+ /** whether to use SSL (TLS) encryption; requires a keystore to be set */
+ public static final String USE_SSL_PROPERTY = "com.sun.management.jmxremote.ssl";
+ /** whether to use SSL (TLS) certificates to authenticate the client;
+ * requires a truststore to be set, and requires {@link #USE_SSL_PROPERTY} true
+ * (different to 'com.sun.management.jmxremote.authenticate' because something else
+ * insists on intercepting that and uses it for passwords);
+ * defaults to true iff {@link #USE_SSL_PROPERTY} is set because
+ * who wouldn't want client authentication if you're encrypting the link */
+ public static final String AUTHENTICATE_CLIENTS_PROPERTY = "brooklyn.jmxmp.ssl.authenticate";
+
+ public static final String JMXMP_KEYSTORE_FILE_PROPERTY = "brooklyn.jmxmp.ssl.keyStore";
+ public static final String JMXMP_KEYSTORE_PASSWORD_PROPERTY = "brooklyn.jmxmp.ssl.keyStorePassword";
+ public static final String JMXMP_KEYSTORE_KEY_PASSWORD_PROPERTY = "brooklyn.jmxmp.ssl.keyStore.keyPassword";
+ public static final String JMXMP_KEYSTORE_TYPE_PROPERTY = "brooklyn.jmxmp.ssl.keyStoreType";
+
+ public static final String JMXMP_TRUSTSTORE_FILE_PROPERTY = "brooklyn.jmxmp.ssl.trustStore";
+ public static final String JMXMP_TRUSTSTORE_PASSWORD_PROPERTY = "brooklyn.jmxmp.ssl.trustStorePassword";
+ public static final String JMXMP_TRUSTSTORE_TYPE_PROPERTY = "brooklyn.jmxmp.ssl.trustStoreType";
+
+ // properties above affect behaviour; those below are simply used in code
+
+
+ public static final String TLS_NEED_AUTHENTICATE_CLIENTS_PROPERTY = "jmx.remote.tls.need.client.authentication";
+ public static final String TLS_WANT_AUTHENTICATE_CLIENTS_PROPERTY = "jmx.remote.tls.want.client.authentication";
+ public static final String TLS_SOCKET_FACTORY_PROPERTY = "jmx.remote.tls.socket.factory";
+
+ public static final String TLS_JMX_REMOTE_PROFILES = "TLS";
+ public static final int JMXMP_DEFAULT_PORT = 11099;
+
+ public static void premain(String agentArgs) {
+ doMain(agentArgs);
+ }
+
+ public static void agentmain(String agentArgs) {
+ doMain(agentArgs);
+ }
+
+ public static void doMain(final String agentArgs) {
+ // do the work in a daemon thread so that if the main class terminates abnormally,
+ // such that shutdown hooks aren't called, we don't keep the application running
+ // (e.g. if the app is compiled with java7 then run with java6, with a java6 agent here;
+ // that causes the agent to launch, the main to fail, but the process to keep going)
+ Thread t = new Thread() {
+ public void run() {
+ doMainForeground(agentArgs);
+ }
+ };
+ t.setDaemon(true);
+ t.start();
+ }
+
+ public static void doMainForeground(String agentArgs) {
+ final List<JMXConnectorServer> connectors = new JmxmpAgent().startConnectors(System.getProperties());
+ if (!connectors.isEmpty()) {
+ Runtime.getRuntime().addShutdownHook(new Thread("jmxmp-agent-shutdownHookThread") {
+ @Override public void run() {
+ for (JMXConnectorServer connector: connectors) {
+ try {
+ connector.stop();
+ } catch (Exception e) {
+ System.err.println("Error closing jmxmp connector "+connector+" in shutdown hook (continuing): "+e);
+ }
+ }
+ }});
+ }
+ }
+
+ public List<JMXConnectorServer> startConnectors(Properties properties) {
+ List<JMXConnectorServer> connectors = new ArrayList<JMXConnectorServer>();
+ addIfNotNull(startJmxmpConnector(properties), connectors);
+ addIfNotNull(startNormalJmxRmiConnectorIfRequested(properties), connectors);
+ return connectors;
+ }
+
+ private static <T> void addIfNotNull(T item, List<T> list) {
+ if (item!=null) list.add(item);
+ }
+
+ public JMXConnectorServer startJmxmpConnector(Properties properties) {
+ try {
+ final int port = Integer.parseInt(properties.getProperty(JMXMP_PORT_PROPERTY, ""+JMXMP_DEFAULT_PORT));
+
+ String hostname = getLocalhostHostname(properties);
+ JMXServiceURL serviceUrl = new JMXServiceURL("service:jmx:jmxmp://"+hostname+":"+port);
+
+ Map<String,Object> env = new LinkedHashMap<String, Object>();
+ propagate(properties, env, JMX_SERVER_ADDRESS_WILDCARD_PROPERTY, null);
+
+ if (asBoolean(properties, USE_SSL_PROPERTY, false, true)) {
+ setSslEnvFromProperties(env, properties);
+ } else {
+ if (asBoolean(properties, AUTHENTICATE_CLIENTS_PROPERTY, false, true)) {
+ throw new IllegalStateException("Client authentication not supported when not using SSL");
+ }
+ }
+ MBeanServer platformMBeanServer = ManagementFactory.getPlatformMBeanServer();
+
+ JMXConnectorServer connector = JMXConnectorServerFactory.newJMXConnectorServer(serviceUrl, env, platformMBeanServer);
+ connector.start();
+
+ System.out.println("JmxmpAgent active at: "+serviceUrl);
+
+ return connector;
+ } catch (RuntimeException e) {
+ System.err.println("Unable to start JmxmpAgent: "+e);
+ throw e;
+ } catch (Exception e) {
+ System.err.println("Unable to start JmxmpAgent: "+e);
+ throw new RuntimeException(e);
+ }
+ }
+
+ /** optionally starts a normal JMXRMI connector in addition */
+ public JMXConnectorServer startNormalJmxRmiConnectorIfRequested(Properties properties) {
+ try {
+ String rmiPortS = properties.getProperty(RMI_REGISTRY_PORT_PROPERTY);
+ if (rmiPortS==null || rmiPortS.length()==0)
+ return null;
+
+ int rmiPort = Integer.parseInt(rmiPortS);
+ LocateRegistry.createRegistry(rmiPort);
+ MBeanServer mbeanServer = ManagementFactory.getPlatformMBeanServer();
+ String svc =
+ "service:jmx:rmi:///jndi/rmi://localhost:"+rmiPort+"/jmxrmi";
+
+ JMXServiceURL url = new JMXServiceURL(svc);
+ RMIConnectorServer rmiServer = new RMIConnectorServer(url, null, mbeanServer);
+ rmiServer.start();
+ return rmiServer;
+ } catch (Exception e) {
+ System.err.println("Unable to start JmxmpAgent: "+e);
+ throw new RuntimeException(e);
+ }
+ }
+
+ public static String getLocalhostHostname(Properties properties) throws UnknownHostException {
+ String hostname = properties==null ? null : properties.getProperty(RMI_HOSTNAME_PROPERTY);
+ if (hostname==null || hostname.isEmpty()) {
+ try {
+ hostname = InetAddress.getLocalHost().getHostName();
+ } catch (Exception e) {
+ System.err.println("Misconfigured hostname when setting JmxmpAgent; reverting to 127.0.0.1: "+e);
+ hostname = "127.0.0.1";
+ }
+ }
+ return hostname;
+ }
+
+ /** copies the value of key from the source to the target, if set;
+ * otherwise sets the defaultValueIfNotNull (final arg) if that is not null;
+ * returns whether anything is set
+ */
+ private static boolean propagate(Properties source, Map<String, Object> target, String key, Object defaultValueIfNotNull) {
+ Object v = source.getProperty(key);
+ if (v==null) v = defaultValueIfNotNull;
+ if (v==null) return false;
+ target.put(key, v);
+ return true;
+ }
+
+ /** returns boolean interpretation of a string,
+ * defaulting to valueIfUnknownText (last arg) if the value is unset or unrecognised,
+ * throwing exception if that is null and value is unset or unrecognised */
+ private boolean asBoolean(Properties properties, String key, Boolean valueIfNull, Boolean valueIfUnknownText) {
+ Object v = properties.get(key);
+ if (v==null) {
+ if (valueIfNull==null) throw new IllegalStateException("Property '"+key+"' is required.");
+ return valueIfNull;
+ }
+ String vv = v.toString();
+ if ("true".equalsIgnoreCase(vv)) return true;
+ if ("false".equalsIgnoreCase(vv)) return false;
+ if (valueIfUnknownText==null)
+ throw new IllegalStateException("Property '"+key+"' has illegal value '"+vv+"'; should be true or false");
+ return valueIfUnknownText;
+ }
+
+ public void setSslEnvFromProperties(Map<String, Object> env, Properties properties) throws Exception {
+ env.put("jmx.remote.profiles", TLS_JMX_REMOTE_PROFILES);
+
+ boolean authenticating = asBoolean(properties, AUTHENTICATE_CLIENTS_PROPERTY, true, null);
+ if (authenticating) {
+ env.put(AUTHENTICATE_CLIENTS_PROPERTY, "true");
+ // NB: the above seem to be ignored (horrid API!); we need the ones below set
+ propagate(properties, env, TLS_NEED_AUTHENTICATE_CLIENTS_PROPERTY, "true");
+ // also note, the above seems to be overridden by below internally !
+ // (setting WANT=false and NEED=true allows access if no trust managers are specified)
+ propagate(properties, env, TLS_WANT_AUTHENTICATE_CLIENTS_PROPERTY, "true");
+ }
+
+
+ if (!propagate(properties, env, TLS_SOCKET_FACTORY_PROPERTY, null)) {
+ String keyStoreFile = properties.getProperty(JMXMP_KEYSTORE_FILE_PROPERTY);
+ String keyStorePass = properties.getProperty(JMXMP_KEYSTORE_PASSWORD_PROPERTY, "");
+ String keyStoreType = properties.getProperty(JMXMP_KEYSTORE_TYPE_PROPERTY, KeyStore.getDefaultType());
+ String keyStoreKeyPass = properties.getProperty(JMXMP_KEYSTORE_KEY_PASSWORD_PROPERTY, "");
+
+ KeyStore ks = KeyStore.getInstance(keyStoreType);
+ if (keyStoreFile!=null)
+ ks.load(new FileInputStream(keyStoreFile), keyStorePass.toCharArray());
+ else
+ ks.load(null, null);
+ KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
+ kmf.init(ks, keyStoreKeyPass.toCharArray());
+
+ String trustStoreFile = properties.getProperty(JMXMP_TRUSTSTORE_FILE_PROPERTY);
+ String trustStorePass = properties.getProperty(JMXMP_TRUSTSTORE_PASSWORD_PROPERTY, "");
+ String trustStoreType = properties.getProperty(JMXMP_TRUSTSTORE_TYPE_PROPERTY, KeyStore.getDefaultType());
+
+ TrustManager[] tms;
+ if (trustStoreFile!=null) {
+ TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
+ KeyStore ts = KeyStore.getInstance(trustStoreType);
+ ts.load(new FileInputStream(trustStoreFile), trustStorePass.toCharArray());
+ tmf.init(ts);
+// tms = tmf.getTrustManagers();
+ // line above causes tests to fail! bug in JMXMP TLS impl?
+ tms = new TrustManager[] { newInspectAllTrustManager((X509TrustManager) tmf.getTrustManagers()[0]) };
+ } else {
+ tms = null;
+ if (authenticating)
+ System.err.println("Authentication required but no truststore supplied to JmxmpAgent. Client connections will likely fail.");
+ }
+
+ SSLContext ctx = SSLContext.getInstance("TLSv1");
+ ctx.init(kmf.getKeyManagers(), tms, null);
+ SSLSocketFactory ssf = ctx.getSocketFactory();
+ env.put(TLS_SOCKET_FACTORY_PROPERTY, ssf);
+ }
+ }
+
+ public static final TrustManager newInspectAllTrustManager(final X509TrustManager delegate) {
+ return new X509TrustManager() {
+ public X509Certificate[] getAcceptedIssuers() {
+ // overriding this method fixes bug where non-accepted issuers have an "accept all" policy, in JMXMP/TLS
+ return new X509Certificate[0];
+ }
+ @Override
+ public void checkClientTrusted(X509Certificate[] chain, String authType)
+ throws java.security.cert.CertificateException {
+ delegate.checkClientTrusted(chain, authType);
+ }
+ @Override
+ public void checkServerTrusted(X509Certificate[] chain, String authType)
+ throws java.security.cert.CertificateException {
+ delegate.checkServerTrusted(chain, authType);
+ }
+ };
+ };
+
+ public static void main(String[] args) {
+ premain("");
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e6ac83be/utils/jmx/jmxmp-ssl-agent/src/test/java/brooklyn/util/jmx/jmxmp/JmxmpAgentSslTest.java
----------------------------------------------------------------------
diff --git a/utils/jmx/jmxmp-ssl-agent/src/test/java/brooklyn/util/jmx/jmxmp/JmxmpAgentSslTest.java b/utils/jmx/jmxmp-ssl-agent/src/test/java/brooklyn/util/jmx/jmxmp/JmxmpAgentSslTest.java
deleted file mode 100644
index 771ba6d..0000000
--- a/utils/jmx/jmxmp-ssl-agent/src/test/java/brooklyn/util/jmx/jmxmp/JmxmpAgentSslTest.java
+++ /dev/null
@@ -1,256 +0,0 @@
-/*
- * 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 brooklyn.util.jmx.jmxmp;
-
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.security.KeyPair;
-import java.security.KeyStore;
-import java.security.KeyStoreException;
-import java.security.NoSuchAlgorithmException;
-import java.security.Security;
-import java.security.cert.CertificateException;
-import java.security.cert.X509Certificate;
-import java.util.LinkedHashMap;
-import java.util.Properties;
-
-import javax.management.remote.JMXConnectorServer;
-
-import org.apache.brooklyn.core.util.crypto.FluentKeySigner;
-import org.apache.brooklyn.core.util.crypto.SecureKeys;
-import org.bouncycastle.jce.provider.BouncyCastleProvider;
-import org.bouncycastle.x509.extension.AuthorityKeyIdentifierStructure;
-import org.testng.annotations.AfterMethod;
-import org.testng.annotations.BeforeMethod;
-import org.testng.annotations.Test;
-
-public class JmxmpAgentSslTest {
-
- KeyPair caRootKey;
- FluentKeySigner caRootSigner;
- X509Certificate caRootCert;
-
- KeyPair caChildKey;
- X509Certificate caChildCert;
- FluentKeySigner caChildSigner;
-
- KeyPair grandchildKey;
- X509Certificate grandchildCert;
-
- KeyPair child2Key;
- X509Certificate child2Cert;
-
- KeyPair selfSign1Key;
- X509Certificate selfSign1Cert;
-
- KeyPair selfSign2Key;
- X509Certificate selfSign2Cert;
-
- KeyStore serverKeystore;
- KeyStore serverTruststore;
- KeyStore clientTruststore;
- KeyStore clientKeystore;
-
- JMXConnectorServer server;
-
- static { Security.addProvider(new BouncyCastleProvider()); }
-
- @BeforeMethod
- public void setup() throws Exception {
- caRootSigner = new FluentKeySigner("ca-root").selfsign();
- caRootKey = caRootSigner.getKey();
- caRootCert = caRootSigner.getAuthorityCertificate();
-
- caChildKey = SecureKeys.newKeyPair();
- caChildCert = caRootSigner.newCertificateFor("ca-child", caChildKey);
- caChildSigner = new FluentKeySigner("ca-child", caChildKey).
- authorityKeyIdentifier(new AuthorityKeyIdentifierStructure(caChildCert));
-
- grandchildKey = SecureKeys.newKeyPair();
- grandchildCert = caChildSigner.newCertificateFor("grandchild", grandchildKey);
-
- child2Key = SecureKeys.newKeyPair();
- child2Cert =
- caRootSigner.
- newCertificateFor("child-2", child2Key);
-
- selfSign1Key = SecureKeys.newKeyPair();
- selfSign1Cert =
- new FluentKeySigner("self-1", selfSign1Key).
- newCertificateFor("self-1", selfSign1Key);
-
- selfSign2Key = SecureKeys.newKeyPair();
- selfSign2Cert =
- new FluentKeySigner("self-2", selfSign2Key).
- newCertificateFor("self-2", selfSign2Key);
-
- serverKeystore = KeyStore.getInstance(KeyStore.getDefaultType());
- serverKeystore.load(null, null);
-
- serverTruststore = KeyStore.getInstance(KeyStore.getDefaultType());
- serverTruststore.load(null, null);
-
- clientTruststore = KeyStore.getInstance(KeyStore.getDefaultType());
- clientTruststore.load(null, null);
-
- clientKeystore = KeyStore.getInstance(KeyStore.getDefaultType());
- clientKeystore.load(null, null);
- }
-
- @AfterMethod
- public void teardown() throws Exception {
- if (server!=null) server.stop();
- server = null;
- }
-
- private Properties saveStoresAndGetConnectorProperties() throws
- KeyStoreException, IOException, NoSuchAlgorithmException,
- CertificateException, FileNotFoundException {
- String keystoreFile = File.createTempFile("server-keystore", ".jmx.test").getAbsolutePath();
- String truststoreFile = File.createTempFile("server-truststore", ".jmx.test").getAbsolutePath();
- if (serverKeystore!=null) serverKeystore.store( new FileOutputStream(keystoreFile), new char[0]);
- if (serverTruststore!=null) serverTruststore.store( new FileOutputStream(truststoreFile), new char[0]);
- Properties p = new Properties();
- p.put(JmxmpAgent.JMXMP_KEYSTORE_FILE_PROPERTY, keystoreFile);
- p.put(JmxmpAgent.JMXMP_TRUSTSTORE_FILE_PROPERTY, truststoreFile);
- p.put(JmxmpAgent.USE_SSL_PROPERTY, "true");
- p.put(JmxmpAgent.AUTHENTICATE_CLIENTS_PROPERTY, "true");
- return p;
- }
-
- @SuppressWarnings("rawtypes")
- @Test
- public void testNoAuth() throws Exception {
- serverKeystore = null;
- serverTruststore = null;
- clientKeystore = null;
- clientTruststore = null;
-
- Properties p = saveStoresAndGetConnectorProperties();
- p.put(JmxmpAgent.USE_SSL_PROPERTY, "false");
- p.put(JmxmpAgent.AUTHENTICATE_CLIENTS_PROPERTY, "false");
-
- server = new JmxmpAgent().startJmxmpConnector(p);
- new JmxmpClient().connect("service:jmx:jmxmp://localhost:11099", new LinkedHashMap());
- }
-
- @SuppressWarnings("rawtypes")
- @Test(expectedExceptions = { IllegalStateException.class })
- public void testAuthWithoutSslFails() throws Exception {
- serverKeystore = null;
- serverTruststore = null;
- clientKeystore = null;
- clientTruststore = null;
-
- Properties p = saveStoresAndGetConnectorProperties();
- p.put(JmxmpAgent.USE_SSL_PROPERTY, "false");
- p.put(JmxmpAgent.AUTHENTICATE_CLIENTS_PROPERTY, "true");
-
- server = new JmxmpAgent().startJmxmpConnector(p);
- new JmxmpClient().connect("service:jmx:jmxmp://localhost:11099", new LinkedHashMap());
- }
-
- @Test
- public void testAllGoodSignatures() throws Exception {
- serverKeystore.setKeyEntry("child-2", child2Key.getPrivate(), new char[]{},
- new java.security.cert.Certificate[]{ child2Cert, caRootCert });
- serverTruststore.setCertificateEntry("ca-child", caChildCert);
-
- clientKeystore.setKeyEntry("grandchild", grandchildKey.getPrivate(), new char[] {},
- new java.security.cert.Certificate[]{ grandchildCert });
- clientTruststore.setCertificateEntry("ca-root", caRootCert);
-
- Properties p = saveStoresAndGetConnectorProperties();
- server = new JmxmpAgent().startJmxmpConnector(p);
- new JmxmpClient().connectTls("service:jmx:jmxmp://localhost:11099",
- clientKeystore, "", clientTruststore);
- }
-
- @Test(expectedExceptions = { Exception.class })
- public void testWrongServerKey() throws Exception {
- /** not a trusted key */
- serverKeystore.setKeyEntry("self-1", selfSign1Key.getPrivate(), new char[]{},
- new java.security.cert.Certificate[]{ selfSign1Cert });
- serverTruststore.setCertificateEntry("ca-child", caChildCert);
-
- clientKeystore.setKeyEntry("grandchild", grandchildKey.getPrivate(), new char[] {},
- new java.security.cert.Certificate[]{ grandchildCert });
- clientTruststore.setCertificateEntry("ca-root", caRootCert);
-
- Properties p = saveStoresAndGetConnectorProperties();
- server = new JmxmpAgent().startJmxmpConnector(p);
- new JmxmpClient().connectTls("service:jmx:jmxmp://localhost:11099",
- clientKeystore, "", clientTruststore);
- }
-
- @Test(expectedExceptions = { Exception.class })
- public void testLyingServerChain() throws Exception {
- /** caChildCert hasn't signed this */
- serverKeystore.setKeyEntry("self-1", selfSign1Key.getPrivate(), new char[]{},
- new java.security.cert.Certificate[]{ selfSign1Cert, caChildCert });
- serverTruststore.setCertificateEntry("ca-child", caChildCert);
-
- clientKeystore.setKeyEntry("grandchild", grandchildKey.getPrivate(), new char[] {},
- new java.security.cert.Certificate[]{ grandchildCert, caChildCert });
- clientTruststore.setCertificateEntry("ca-root", caRootCert);
-
- Properties p = saveStoresAndGetConnectorProperties();
- server = new JmxmpAgent().startJmxmpConnector(p);
- new JmxmpClient().connectTls("service:jmx:jmxmp://localhost:11099",
- clientKeystore, "", clientTruststore);
- }
-
- @Test(expectedExceptions = { Exception.class })
- public void testWrongClientKey() throws Exception {
- serverKeystore.setKeyEntry("child-2", child2Key.getPrivate(), new char[]{},
- new java.security.cert.Certificate[]{ child2Cert, caRootCert });
- serverTruststore.setCertificateEntry("ca-child", caChildCert);
-
- /** this key should not have access */
- clientKeystore.setKeyEntry("self-1", selfSign1Key.getPrivate(), new char[] {},
- new java.security.cert.Certificate[]{ selfSign1Cert });
- clientTruststore.setCertificateEntry("ca-root", caRootCert);
-
- Properties p = saveStoresAndGetConnectorProperties();
- server = new JmxmpAgent().startJmxmpConnector(p);
- new JmxmpClient().connectTls("service:jmx:jmxmp://localhost:11099",
- clientKeystore, "", clientTruststore);
- }
-
- @Test(expectedExceptions = { Exception.class })
- public void testLyingClientChain() throws Exception {
- serverKeystore.setKeyEntry("child-2", child2Key.getPrivate(), new char[]{},
- new java.security.cert.Certificate[]{ child2Cert, caRootCert });
- serverTruststore.setCertificateEntry("ca-child", caChildCert);
-
- /** caChildCert hasn't signed this */
- clientKeystore.setKeyEntry("self-1", selfSign1Key.getPrivate(), new char[] {},
- new java.security.cert.Certificate[]{ selfSign1Cert, caChildCert });
- clientTruststore.setCertificateEntry("ca-root", caRootCert);
-
- Properties p = saveStoresAndGetConnectorProperties();
- server = new JmxmpAgent().startJmxmpConnector(p);
- new JmxmpClient().connectTls("service:jmx:jmxmp://localhost:11099",
- clientKeystore, "", clientTruststore);
- }
-
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e6ac83be/utils/jmx/jmxmp-ssl-agent/src/test/java/brooklyn/util/jmx/jmxmp/JmxmpClient.java
----------------------------------------------------------------------
diff --git a/utils/jmx/jmxmp-ssl-agent/src/test/java/brooklyn/util/jmx/jmxmp/JmxmpClient.java b/utils/jmx/jmxmp-ssl-agent/src/test/java/brooklyn/util/jmx/jmxmp/JmxmpClient.java
deleted file mode 100644
index dbad7b8..0000000
--- a/utils/jmx/jmxmp-ssl-agent/src/test/java/brooklyn/util/jmx/jmxmp/JmxmpClient.java
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * 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 brooklyn.util.jmx.jmxmp;
-
-import java.io.IOException;
-import java.net.MalformedURLException;
-import java.security.InvalidKeyException;
-import java.security.KeyManagementException;
-import java.security.KeyStore;
-import java.security.KeyStoreException;
-import java.security.NoSuchAlgorithmException;
-import java.security.SignatureException;
-import java.security.UnrecoverableKeyException;
-import java.security.cert.CertificateException;
-import java.util.LinkedHashMap;
-import java.util.Map;
-
-import javax.management.MBeanServerConnection;
-import javax.management.remote.JMXConnector;
-import javax.management.remote.JMXConnectorFactory;
-import javax.management.remote.JMXServiceURL;
-import javax.net.ssl.KeyManagerFactory;
-import javax.net.ssl.SSLContext;
-import javax.net.ssl.SSLSocketFactory;
-import javax.net.ssl.TrustManager;
-
-import org.apache.brooklyn.core.util.crypto.SecureKeys;
-import org.apache.brooklyn.util.crypto.SslTrustUtils;
-
-@SuppressWarnings({"rawtypes","unchecked"})
-public class JmxmpClient {
-
- public void connect(String urlString, Map env) throws MalformedURLException, IOException {
- JMXServiceURL url = new JMXServiceURL(urlString);
- System.out.println("JmxmpClient connecting to "+url);
- JMXConnector jmxc = JMXConnectorFactory.connect(url, env);
-
- MBeanServerConnection mbsc = jmxc.getMBeanServerConnection();
- String domains[] = mbsc.getDomains();
- for (int i = 0; i < domains.length; i++) {
- System.out.println("Domain[" + i + "] = " + domains[i]);
- }
-
- jmxc.close();
- }
-
- /** tries to connect to the given JMX url over tls,
- * optionally using the given keystore (if null using a randomly generated key)
- * and optionally using the given truststore (if null trusting all) */
- public void connectTls(String urlString, KeyStore keyStore, String keyStorePass, KeyStore trustStore) throws NoSuchAlgorithmException, UnrecoverableKeyException, KeyStoreException, InvalidKeyException, CertificateException, SecurityException, SignatureException, IOException, KeyManagementException {
- Map env = new LinkedHashMap();
-
- env.put("jmx.remote.profiles", JmxmpAgent.TLS_JMX_REMOTE_PROFILES);
-
- if (keyStore==null) throw new NullPointerException("keyStore must be supplied");
- KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); //"SunX509");
- kmf.init(keyStore, (keyStorePass!=null ? keyStorePass : "").toCharArray());
-
- TrustManager tms = trustStore!=null ? SecureKeys.getTrustManager(trustStore) : SslTrustUtils.TRUST_ALL;
-
- SSLContext ctx = SSLContext.getInstance("TLSv1");
- ctx.init(kmf.getKeyManagers(), new TrustManager[] { tms }, null);
- SSLSocketFactory ssf = ctx.getSocketFactory();
- env.put(JmxmpAgent.TLS_SOCKET_FACTORY_PROPERTY, ssf);
-
- connect(urlString, env);
- }
-
- public static void main(String[] args) throws Exception {
- new JmxmpClient().connect("service:jmx:jmxmp://localhost:1099", null);
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e6ac83be/utils/jmx/jmxmp-ssl-agent/src/test/java/org/apache/brooklyn/util/jmx/jmxmp/JmxmpAgentSslTest.java
----------------------------------------------------------------------
diff --git a/utils/jmx/jmxmp-ssl-agent/src/test/java/org/apache/brooklyn/util/jmx/jmxmp/JmxmpAgentSslTest.java b/utils/jmx/jmxmp-ssl-agent/src/test/java/org/apache/brooklyn/util/jmx/jmxmp/JmxmpAgentSslTest.java
new file mode 100644
index 0000000..9aa1bad
--- /dev/null
+++ b/utils/jmx/jmxmp-ssl-agent/src/test/java/org/apache/brooklyn/util/jmx/jmxmp/JmxmpAgentSslTest.java
@@ -0,0 +1,257 @@
+/*
+ * 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.brooklyn.util.jmx.jmxmp;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.security.KeyPair;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.Security;
+import java.security.cert.CertificateException;
+import java.security.cert.X509Certificate;
+import java.util.LinkedHashMap;
+import java.util.Properties;
+
+import javax.management.remote.JMXConnectorServer;
+
+import org.apache.brooklyn.core.util.crypto.FluentKeySigner;
+import org.apache.brooklyn.core.util.crypto.SecureKeys;
+import org.apache.brooklyn.util.jmx.jmxmp.JmxmpAgent;
+import org.bouncycastle.jce.provider.BouncyCastleProvider;
+import org.bouncycastle.x509.extension.AuthorityKeyIdentifierStructure;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+public class JmxmpAgentSslTest {
+
+ KeyPair caRootKey;
+ FluentKeySigner caRootSigner;
+ X509Certificate caRootCert;
+
+ KeyPair caChildKey;
+ X509Certificate caChildCert;
+ FluentKeySigner caChildSigner;
+
+ KeyPair grandchildKey;
+ X509Certificate grandchildCert;
+
+ KeyPair child2Key;
+ X509Certificate child2Cert;
+
+ KeyPair selfSign1Key;
+ X509Certificate selfSign1Cert;
+
+ KeyPair selfSign2Key;
+ X509Certificate selfSign2Cert;
+
+ KeyStore serverKeystore;
+ KeyStore serverTruststore;
+ KeyStore clientTruststore;
+ KeyStore clientKeystore;
+
+ JMXConnectorServer server;
+
+ static { Security.addProvider(new BouncyCastleProvider()); }
+
+ @BeforeMethod
+ public void setup() throws Exception {
+ caRootSigner = new FluentKeySigner("ca-root").selfsign();
+ caRootKey = caRootSigner.getKey();
+ caRootCert = caRootSigner.getAuthorityCertificate();
+
+ caChildKey = SecureKeys.newKeyPair();
+ caChildCert = caRootSigner.newCertificateFor("ca-child", caChildKey);
+ caChildSigner = new FluentKeySigner("ca-child", caChildKey).
+ authorityKeyIdentifier(new AuthorityKeyIdentifierStructure(caChildCert));
+
+ grandchildKey = SecureKeys.newKeyPair();
+ grandchildCert = caChildSigner.newCertificateFor("grandchild", grandchildKey);
+
+ child2Key = SecureKeys.newKeyPair();
+ child2Cert =
+ caRootSigner.
+ newCertificateFor("child-2", child2Key);
+
+ selfSign1Key = SecureKeys.newKeyPair();
+ selfSign1Cert =
+ new FluentKeySigner("self-1", selfSign1Key).
+ newCertificateFor("self-1", selfSign1Key);
+
+ selfSign2Key = SecureKeys.newKeyPair();
+ selfSign2Cert =
+ new FluentKeySigner("self-2", selfSign2Key).
+ newCertificateFor("self-2", selfSign2Key);
+
+ serverKeystore = KeyStore.getInstance(KeyStore.getDefaultType());
+ serverKeystore.load(null, null);
+
+ serverTruststore = KeyStore.getInstance(KeyStore.getDefaultType());
+ serverTruststore.load(null, null);
+
+ clientTruststore = KeyStore.getInstance(KeyStore.getDefaultType());
+ clientTruststore.load(null, null);
+
+ clientKeystore = KeyStore.getInstance(KeyStore.getDefaultType());
+ clientKeystore.load(null, null);
+ }
+
+ @AfterMethod
+ public void teardown() throws Exception {
+ if (server!=null) server.stop();
+ server = null;
+ }
+
+ private Properties saveStoresAndGetConnectorProperties() throws
+ KeyStoreException, IOException, NoSuchAlgorithmException,
+ CertificateException, FileNotFoundException {
+ String keystoreFile = File.createTempFile("server-keystore", ".jmx.test").getAbsolutePath();
+ String truststoreFile = File.createTempFile("server-truststore", ".jmx.test").getAbsolutePath();
+ if (serverKeystore!=null) serverKeystore.store( new FileOutputStream(keystoreFile), new char[0]);
+ if (serverTruststore!=null) serverTruststore.store( new FileOutputStream(truststoreFile), new char[0]);
+ Properties p = new Properties();
+ p.put(JmxmpAgent.JMXMP_KEYSTORE_FILE_PROPERTY, keystoreFile);
+ p.put(JmxmpAgent.JMXMP_TRUSTSTORE_FILE_PROPERTY, truststoreFile);
+ p.put(JmxmpAgent.USE_SSL_PROPERTY, "true");
+ p.put(JmxmpAgent.AUTHENTICATE_CLIENTS_PROPERTY, "true");
+ return p;
+ }
+
+ @SuppressWarnings("rawtypes")
+ @Test
+ public void testNoAuth() throws Exception {
+ serverKeystore = null;
+ serverTruststore = null;
+ clientKeystore = null;
+ clientTruststore = null;
+
+ Properties p = saveStoresAndGetConnectorProperties();
+ p.put(JmxmpAgent.USE_SSL_PROPERTY, "false");
+ p.put(JmxmpAgent.AUTHENTICATE_CLIENTS_PROPERTY, "false");
+
+ server = new JmxmpAgent().startJmxmpConnector(p);
+ new JmxmpClient().connect("service:jmx:jmxmp://localhost:11099", new LinkedHashMap());
+ }
+
+ @SuppressWarnings("rawtypes")
+ @Test(expectedExceptions = { IllegalStateException.class })
+ public void testAuthWithoutSslFails() throws Exception {
+ serverKeystore = null;
+ serverTruststore = null;
+ clientKeystore = null;
+ clientTruststore = null;
+
+ Properties p = saveStoresAndGetConnectorProperties();
+ p.put(JmxmpAgent.USE_SSL_PROPERTY, "false");
+ p.put(JmxmpAgent.AUTHENTICATE_CLIENTS_PROPERTY, "true");
+
+ server = new JmxmpAgent().startJmxmpConnector(p);
+ new JmxmpClient().connect("service:jmx:jmxmp://localhost:11099", new LinkedHashMap());
+ }
+
+ @Test
+ public void testAllGoodSignatures() throws Exception {
+ serverKeystore.setKeyEntry("child-2", child2Key.getPrivate(), new char[]{},
+ new java.security.cert.Certificate[]{ child2Cert, caRootCert });
+ serverTruststore.setCertificateEntry("ca-child", caChildCert);
+
+ clientKeystore.setKeyEntry("grandchild", grandchildKey.getPrivate(), new char[] {},
+ new java.security.cert.Certificate[]{ grandchildCert });
+ clientTruststore.setCertificateEntry("ca-root", caRootCert);
+
+ Properties p = saveStoresAndGetConnectorProperties();
+ server = new JmxmpAgent().startJmxmpConnector(p);
+ new JmxmpClient().connectTls("service:jmx:jmxmp://localhost:11099",
+ clientKeystore, "", clientTruststore);
+ }
+
+ @Test(expectedExceptions = { Exception.class })
+ public void testWrongServerKey() throws Exception {
+ /** not a trusted key */
+ serverKeystore.setKeyEntry("self-1", selfSign1Key.getPrivate(), new char[]{},
+ new java.security.cert.Certificate[]{ selfSign1Cert });
+ serverTruststore.setCertificateEntry("ca-child", caChildCert);
+
+ clientKeystore.setKeyEntry("grandchild", grandchildKey.getPrivate(), new char[] {},
+ new java.security.cert.Certificate[]{ grandchildCert });
+ clientTruststore.setCertificateEntry("ca-root", caRootCert);
+
+ Properties p = saveStoresAndGetConnectorProperties();
+ server = new JmxmpAgent().startJmxmpConnector(p);
+ new JmxmpClient().connectTls("service:jmx:jmxmp://localhost:11099",
+ clientKeystore, "", clientTruststore);
+ }
+
+ @Test(expectedExceptions = { Exception.class })
+ public void testLyingServerChain() throws Exception {
+ /** caChildCert hasn't signed this */
+ serverKeystore.setKeyEntry("self-1", selfSign1Key.getPrivate(), new char[]{},
+ new java.security.cert.Certificate[]{ selfSign1Cert, caChildCert });
+ serverTruststore.setCertificateEntry("ca-child", caChildCert);
+
+ clientKeystore.setKeyEntry("grandchild", grandchildKey.getPrivate(), new char[] {},
+ new java.security.cert.Certificate[]{ grandchildCert, caChildCert });
+ clientTruststore.setCertificateEntry("ca-root", caRootCert);
+
+ Properties p = saveStoresAndGetConnectorProperties();
+ server = new JmxmpAgent().startJmxmpConnector(p);
+ new JmxmpClient().connectTls("service:jmx:jmxmp://localhost:11099",
+ clientKeystore, "", clientTruststore);
+ }
+
+ @Test(expectedExceptions = { Exception.class })
+ public void testWrongClientKey() throws Exception {
+ serverKeystore.setKeyEntry("child-2", child2Key.getPrivate(), new char[]{},
+ new java.security.cert.Certificate[]{ child2Cert, caRootCert });
+ serverTruststore.setCertificateEntry("ca-child", caChildCert);
+
+ /** this key should not have access */
+ clientKeystore.setKeyEntry("self-1", selfSign1Key.getPrivate(), new char[] {},
+ new java.security.cert.Certificate[]{ selfSign1Cert });
+ clientTruststore.setCertificateEntry("ca-root", caRootCert);
+
+ Properties p = saveStoresAndGetConnectorProperties();
+ server = new JmxmpAgent().startJmxmpConnector(p);
+ new JmxmpClient().connectTls("service:jmx:jmxmp://localhost:11099",
+ clientKeystore, "", clientTruststore);
+ }
+
+ @Test(expectedExceptions = { Exception.class })
+ public void testLyingClientChain() throws Exception {
+ serverKeystore.setKeyEntry("child-2", child2Key.getPrivate(), new char[]{},
+ new java.security.cert.Certificate[]{ child2Cert, caRootCert });
+ serverTruststore.setCertificateEntry("ca-child", caChildCert);
+
+ /** caChildCert hasn't signed this */
+ clientKeystore.setKeyEntry("self-1", selfSign1Key.getPrivate(), new char[] {},
+ new java.security.cert.Certificate[]{ selfSign1Cert, caChildCert });
+ clientTruststore.setCertificateEntry("ca-root", caRootCert);
+
+ Properties p = saveStoresAndGetConnectorProperties();
+ server = new JmxmpAgent().startJmxmpConnector(p);
+ new JmxmpClient().connectTls("service:jmx:jmxmp://localhost:11099",
+ clientKeystore, "", clientTruststore);
+ }
+
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e6ac83be/utils/jmx/jmxmp-ssl-agent/src/test/java/org/apache/brooklyn/util/jmx/jmxmp/JmxmpClient.java
----------------------------------------------------------------------
diff --git a/utils/jmx/jmxmp-ssl-agent/src/test/java/org/apache/brooklyn/util/jmx/jmxmp/JmxmpClient.java b/utils/jmx/jmxmp-ssl-agent/src/test/java/org/apache/brooklyn/util/jmx/jmxmp/JmxmpClient.java
new file mode 100644
index 0000000..3c7d664
--- /dev/null
+++ b/utils/jmx/jmxmp-ssl-agent/src/test/java/org/apache/brooklyn/util/jmx/jmxmp/JmxmpClient.java
@@ -0,0 +1,89 @@
+/*
+ * 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.brooklyn.util.jmx.jmxmp;
+
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.security.InvalidKeyException;
+import java.security.KeyManagementException;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.SignatureException;
+import java.security.UnrecoverableKeyException;
+import java.security.cert.CertificateException;
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+import javax.management.MBeanServerConnection;
+import javax.management.remote.JMXConnector;
+import javax.management.remote.JMXConnectorFactory;
+import javax.management.remote.JMXServiceURL;
+import javax.net.ssl.KeyManagerFactory;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLSocketFactory;
+import javax.net.ssl.TrustManager;
+
+import org.apache.brooklyn.core.util.crypto.SecureKeys;
+import org.apache.brooklyn.util.crypto.SslTrustUtils;
+import org.apache.brooklyn.util.jmx.jmxmp.JmxmpAgent;
+
+@SuppressWarnings({"rawtypes","unchecked"})
+public class JmxmpClient {
+
+ public void connect(String urlString, Map env) throws MalformedURLException, IOException {
+ JMXServiceURL url = new JMXServiceURL(urlString);
+ System.out.println("JmxmpClient connecting to "+url);
+ JMXConnector jmxc = JMXConnectorFactory.connect(url, env);
+
+ MBeanServerConnection mbsc = jmxc.getMBeanServerConnection();
+ String domains[] = mbsc.getDomains();
+ for (int i = 0; i < domains.length; i++) {
+ System.out.println("Domain[" + i + "] = " + domains[i]);
+ }
+
+ jmxc.close();
+ }
+
+ /** tries to connect to the given JMX url over tls,
+ * optionally using the given keystore (if null using a randomly generated key)
+ * and optionally using the given truststore (if null trusting all) */
+ public void connectTls(String urlString, KeyStore keyStore, String keyStorePass, KeyStore trustStore) throws NoSuchAlgorithmException, UnrecoverableKeyException, KeyStoreException, InvalidKeyException, CertificateException, SecurityException, SignatureException, IOException, KeyManagementException {
+ Map env = new LinkedHashMap();
+
+ env.put("jmx.remote.profiles", JmxmpAgent.TLS_JMX_REMOTE_PROFILES);
+
+ if (keyStore==null) throw new NullPointerException("keyStore must be supplied");
+ KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); //"SunX509");
+ kmf.init(keyStore, (keyStorePass!=null ? keyStorePass : "").toCharArray());
+
+ TrustManager tms = trustStore!=null ? SecureKeys.getTrustManager(trustStore) : SslTrustUtils.TRUST_ALL;
+
+ SSLContext ctx = SSLContext.getInstance("TLSv1");
+ ctx.init(kmf.getKeyManagers(), new TrustManager[] { tms }, null);
+ SSLSocketFactory ssf = ctx.getSocketFactory();
+ env.put(JmxmpAgent.TLS_SOCKET_FACTORY_PROPERTY, ssf);
+
+ connect(urlString, env);
+ }
+
+ public static void main(String[] args) throws Exception {
+ new JmxmpClient().connect("service:jmx:jmxmp://localhost:1099", null);
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e6ac83be/utils/jmx/jmxrmi-agent/pom.xml
----------------------------------------------------------------------
diff --git a/utils/jmx/jmxrmi-agent/pom.xml b/utils/jmx/jmxrmi-agent/pom.xml
index e9ea011..d725405 100644
--- a/utils/jmx/jmxrmi-agent/pom.xml
+++ b/utils/jmx/jmxrmi-agent/pom.xml
@@ -52,8 +52,8 @@
<artifactId>maven-bundle-plugin</artifactId>
<configuration>
<instructions>
- <Premain-Class>brooklyn.util.jmx.jmxrmi.JmxRmiAgent</Premain-Class>
- <Agent-Class>brooklyn.util.jmx.jmxrmi.JmxRmiAgent</Agent-Class>
+ <Premain-Class>org.apache.brooklyn.util.jmx.jmxrmi.JmxRmiAgent</Premain-Class>
+ <Agent-Class>org.apache.brooklyn.util.jmx.jmxrmi.JmxRmiAgent</Agent-Class>
</instructions>
</configuration>
</plugin>
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e6ac83be/utils/jmx/jmxrmi-agent/src/main/java/brooklyn/util/jmx/jmxrmi/JmxRmiAgent.java
----------------------------------------------------------------------
diff --git a/utils/jmx/jmxrmi-agent/src/main/java/brooklyn/util/jmx/jmxrmi/JmxRmiAgent.java b/utils/jmx/jmxrmi-agent/src/main/java/brooklyn/util/jmx/jmxrmi/JmxRmiAgent.java
deleted file mode 100644
index 089de45..0000000
--- a/utils/jmx/jmxrmi-agent/src/main/java/brooklyn/util/jmx/jmxrmi/JmxRmiAgent.java
+++ /dev/null
@@ -1,188 +0,0 @@
-/*
- * 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 brooklyn.util.jmx.jmxrmi;
-
-import java.lang.management.ManagementFactory;
-import java.net.InetAddress;
-import java.net.UnknownHostException;
-import java.rmi.registry.LocateRegistry;
-import java.util.LinkedHashMap;
-import java.util.Map;
-import java.util.Properties;
-
-import javax.management.MBeanServer;
-import javax.management.remote.JMXConnectorServer;
-import javax.management.remote.JMXConnectorServerFactory;
-import javax.management.remote.JMXServiceURL;
-
-/**
- * This exposes JMX support for going through firewalls by starting an RMI registry server
- * on a well-known port.
- * <p>
- * This implementation DOES NOT support port-forwarding however. The same hostname used internally
- * (specified in {@link #RMI_HOSTNAME_PROPERTY} or autodetected by java) must also be addressable
- * by the JMX client. This is due to how the property is used internally by java during the
- * RMI registry re-direction.
- * <p>
- * If you require that the client connects to a different hostname/IP than the one where the
- * service is bound, consider using the Brooklyn JmxmpAgent, as this will not work!
- * <p>
- * This listens on {@value #RMI_REGISTRY_PORT_PROPERTY} unless overridden by system property
- * {@link #RMI_REGISTRY_PORT_PROPERTY} ({@value #RMI_REGISTRY_PORT_PROPERTY}).
- *
- * @see brooklyn.util.jmx.jmxmp.JmxmpAgent
- * @see https://blogs.oracle.com/jmxetc/entry/connecting_through_firewall_using_jmx
- * @see https://blogs.oracle.com/jmxetc/entry/more_on_premain_and_jmx
- */
-public class JmxRmiAgent {
-
- /** Port for RMI registry to listen on. Default to {@link #RMI_REGISTRY_DEFAULT_PORT}. */
- public static final String RMI_REGISTRY_PORT_PROPERTY = "brooklyn.jmx-agent.rmi-port";
- public static final String RMI_REGISTRY_DEFAULT_PORT = "9001";
-
- /** Port for JMX server (sometimes called JMX_RMI server) to listen on. Default to {@link #JMX_SERVER_DEFAULT_PORT}. */
- public static final String JMX_SERVER_PORT_PROPERTY = "brooklyn.jmx-agent.jmx-port";
- public static final String JMX_SERVER_DEFAULT_PORT = "11099";
-
- /** Hostname to advertise, and if {@value #JMX_SERVER_ADDRESS_WILDCARD_PROPERTY} is false also the hostname/interface to bind to.
- * Should never be 0.0.0.0 as it is publicly advertised. */
- public static final String RMI_HOSTNAME_PROPERTY = "java.rmi.server.hostname";
-
- /** Whether JMX should bind to all interfaces. */
- public static final String JMX_SERVER_ADDRESS_WILDCARD_PROPERTY = "jmx.remote.server.address.wildcard";
-
- /**
- * The entry point, uses the JDK dynamic agent loading feature.
- */
- public static void premain(String agentArgs) {
- doMain(agentArgs);
- }
-
- public static void agentmain(String agentArgs) {
- doMain(agentArgs);
- }
-
- public static void doMain(final String agentArgs) {
- // taken from JmxmpAgent in sister project
-
- // do the work in a daemon thread so that if the main class terminates abnormally,
- // such that shutdown hooks aren't called, we don't keep the application running
- // (e.g. if the app is compiled with java7 then run with java6, with a java6 agent here;
- // that causes the agent to launch, the main to fail, but the process to keep going)
- Thread t = new Thread() {
- public void run() {
- doMainForeground(agentArgs);
- }
- };
- t.setDaemon(true);
- t.start();
- }
-
- public static void doMainForeground(String agentArgs) {
- final JMXConnectorServer connector = new JmxRmiAgent().startServer(System.getProperties());
- if (connector != null) {
- Runtime.getRuntime().addShutdownHook(new Thread("jmxrmi-agent-shutdownHookThread") {
- @Override public void run() {
- try {
- connector.stop();
- } catch (Exception e) {
- System.err.println("Error closing jmxrmi connector in shutdown hook (continuing): "+e);
- }
- }});
- }
- }
-
- public JMXConnectorServer startServer(Properties properties) {
- try {
- // Ensure cryptographically strong random number generator used
- // to choose the object number - see java.rmi.server.ObjID
- System.setProperty("java.rmi.server.randomIDs", "true");
-
- // Start an RMI registry on port specified
- final int rmiPort = Integer.parseInt(System.getProperty(RMI_REGISTRY_PORT_PROPERTY, RMI_REGISTRY_DEFAULT_PORT));
- final int jmxPort = Integer.parseInt(System.getProperty(JMX_SERVER_PORT_PROPERTY, JMX_SERVER_DEFAULT_PORT));
- final String hostname = getLocalhostHostname(properties);
-
- System.out.println("Setting up JmxRmiAgent for: "+hostname+" "+rmiPort+" / "+jmxPort);
-
- LocateRegistry.createRegistry(rmiPort);
-
- // Retrieve the PlatformMBeanServer.
- MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
-
- // Environment map.
- Map<String, Object> env = new LinkedHashMap<String, Object>();
- propagate(properties, env, JMX_SERVER_ADDRESS_WILDCARD_PROPERTY, "true");
-
- // TODO Security
-
- // Create an RMI connector server.
- JMXServiceURL url = new JMXServiceURL("service:jmx:rmi://" + hostname + ":" + jmxPort + "/jndi/rmi://" + hostname + ":" + rmiPort + "/jmxrmi");
-
- // Now create the server from the JMXServiceURL
- JMXConnectorServer connector = JMXConnectorServerFactory.newJMXConnectorServer(url, env, mbs);
-
- // Start the RMI connector server.
- connector.start();
- System.out.println("JmxRmiAgent JMXConnectorServer active at: " + url);
-
- return connector;
- } catch (RuntimeException e) {
- System.err.println("Unable to start JMXConnectorServer: " + e);
- throw e;
- } catch (Exception e) {
- System.err.println("Unable to start JMXConnectorServer: " + e);
- throw new RuntimeException(e);
- }
- }
-
- /**
- * Copies the value of key from the source to the target, if set. Otherwise
- * sets the {@code defaultValueIfNotNull} if that is not null.
- *
- * @return whether anything is set
- */
- private static boolean propagate(Properties source, Map<String, Object> target, String key, Object defaultValueIfNotNull) {
- Object v = source.getProperty(key);
- if (v == null) v = defaultValueIfNotNull;
- if (v == null) return false;
- target.put(key, v);
- return true;
- }
-
- private String getLocalhostHostname(Properties properties) throws UnknownHostException {
- String hostname = properties == null ? null : properties.getProperty(RMI_HOSTNAME_PROPERTY);
- if ("0.0.0.0".equals(hostname)) {
- System.err.println("WARN: invalid hostname 0.0.0.0 specified for JmxRmiAgent; " +
- "it typically must be an address or hostname which is bindable on the machine where " +
- "this service is running AND accessible by a client machine (access will likely be impossible)");
- }
- if (hostname == null || hostname.isEmpty()) {
- hostname = InetAddress.getLocalHost().getHostName();
- }
- return hostname;
- }
-
- /**
- * Convenience main method.
- */
- public static void main(String[] args) throws Exception {
- premain("");
- }
-}