mirror of https://github.com/apache/activemq.git
https://issues.apache.org/jira/browse/AMQ-4298 Add mutual authentication (needClientAuth) to https transport added tests as well
git-svn-id: https://svn.apache.org/repos/asf/activemq/trunk@1445299 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
cd5e1f3d99
commit
571d452053
|
@ -31,6 +31,10 @@ public class SecureSocketConnectorFactory extends SocketConnectorFactory {
|
|||
private String keyPassword = System.getProperty("javax.net.ssl.keyPassword");
|
||||
private String keyStorePassword = System.getProperty("javax.net.ssl.keyStorePassword");
|
||||
private String keyStore = System.getProperty("javax.net.ssl.keyStore");
|
||||
private String trustStorePassword = System.getProperty("javax.net.ssl.trustStorePassword");
|
||||
private String trustStore = System.getProperty("javax.net.ssl.trustStore");
|
||||
private boolean needClientAuth;
|
||||
private boolean wantClientAuth;
|
||||
private String keyStoreType;
|
||||
private String secureRandomCertficateAlgorithm;
|
||||
private String trustCertificateAlgorithm;
|
||||
|
@ -94,8 +98,18 @@ public class SecureSocketConnectorFactory extends SocketConnectorFactory {
|
|||
if (protocol != null) {
|
||||
factory.setProtocol(protocol);
|
||||
}
|
||||
if (trustStore != null) {
|
||||
factory.setTrustStore(trustStore);
|
||||
}
|
||||
if (trustStorePassword != null) {
|
||||
factory.setTrustStorePassword(trustStorePassword);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
factory.setNeedClientAuth(needClientAuth);
|
||||
factory.setWantClientAuth(wantClientAuth);
|
||||
|
||||
return sslConnector;
|
||||
}
|
||||
|
||||
|
@ -179,4 +193,36 @@ public class SecureSocketConnectorFactory extends SocketConnectorFactory {
|
|||
public void setAuth(String auth) {
|
||||
this.auth = auth;
|
||||
}
|
||||
|
||||
public boolean isWantClientAuth() {
|
||||
return wantClientAuth;
|
||||
}
|
||||
|
||||
public void setWantClientAuth(boolean wantClientAuth) {
|
||||
this.wantClientAuth = wantClientAuth;
|
||||
}
|
||||
|
||||
public boolean isNeedClientAuth() {
|
||||
return needClientAuth;
|
||||
}
|
||||
|
||||
public void setNeedClientAuth(boolean needClientAuth) {
|
||||
this.needClientAuth = needClientAuth;
|
||||
}
|
||||
|
||||
public String getTrustStore() {
|
||||
return trustStore;
|
||||
}
|
||||
|
||||
public void setTrustStore(String trustStore) {
|
||||
this.trustStore = trustStore;
|
||||
}
|
||||
|
||||
public String getTrustStorePassword() {
|
||||
return trustStorePassword;
|
||||
}
|
||||
|
||||
public void setTrustStorePassword(String trustStorePassword) {
|
||||
this.trustStorePassword = trustStorePassword;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -45,6 +45,7 @@ import org.apache.http.client.methods.HttpGet;
|
|||
import org.apache.http.client.methods.HttpHead;
|
||||
import org.apache.http.client.methods.HttpOptions;
|
||||
import org.apache.http.client.methods.HttpPost;
|
||||
import org.apache.http.conn.ClientConnectionManager;
|
||||
import org.apache.http.conn.params.ConnRoutePNames;
|
||||
import org.apache.http.entity.ByteArrayEntity;
|
||||
import org.apache.http.impl.client.BasicResponseHandler;
|
||||
|
@ -80,7 +81,7 @@ public class HttpClientTransport extends HttpTransportSupport {
|
|||
private int soTimeout = MAX_CLIENT_TIMEOUT;
|
||||
|
||||
private boolean useCompression = false;
|
||||
private boolean canSendCompressed = false;
|
||||
protected boolean canSendCompressed = false;
|
||||
private int minSendAsCompressedSize = 0;
|
||||
|
||||
public HttpClientTransport(TextWireFormat wireFormat, URI remoteUrl) {
|
||||
|
@ -285,7 +286,7 @@ public class HttpClientTransport extends HttpTransportSupport {
|
|||
}
|
||||
|
||||
protected HttpClient createHttpClient() {
|
||||
DefaultHttpClient client = new DefaultHttpClient(new PoolingClientConnectionManager());
|
||||
DefaultHttpClient client = new DefaultHttpClient(createClientConnectionManager());
|
||||
if (useCompression) {
|
||||
client.addRequestInterceptor( new HttpRequestInterceptor() {
|
||||
@Override
|
||||
|
@ -308,6 +309,10 @@ public class HttpClientTransport extends HttpTransportSupport {
|
|||
return client;
|
||||
}
|
||||
|
||||
protected ClientConnectionManager createClientConnectionManager() {
|
||||
return new PoolingClientConnectionManager();
|
||||
}
|
||||
|
||||
protected void configureMethod(AbstractHttpMessage method) {
|
||||
method.setHeader("clientID", clientID);
|
||||
}
|
||||
|
|
|
@ -17,14 +17,46 @@
|
|||
*/
|
||||
package org.apache.activemq.transport.https;
|
||||
|
||||
import java.net.URI;
|
||||
|
||||
import org.apache.activemq.transport.http.HttpClientTransport;
|
||||
import org.apache.activemq.transport.util.TextWireFormat;
|
||||
import org.apache.http.conn.ClientConnectionManager;
|
||||
import org.apache.http.conn.scheme.Scheme;
|
||||
import org.apache.http.conn.scheme.SchemeRegistry;
|
||||
import org.apache.http.conn.ssl.SSLSocketFactory;
|
||||
import org.apache.http.impl.conn.PoolingClientConnectionManager;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.FileInputStream;
|
||||
import java.io.InputStream;
|
||||
import java.net.URI;
|
||||
import java.security.KeyStore;
|
||||
|
||||
public class HttpsClientTransport extends HttpClientTransport {
|
||||
|
||||
|
||||
public HttpsClientTransport(TextWireFormat wireFormat, URI remoteUrl) {
|
||||
super(wireFormat, remoteUrl);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ClientConnectionManager createClientConnectionManager() {
|
||||
PoolingClientConnectionManager connectionManager = new PoolingClientConnectionManager(createSchemeRegistry());
|
||||
return connectionManager;
|
||||
}
|
||||
|
||||
private SchemeRegistry createSchemeRegistry() {
|
||||
|
||||
SchemeRegistry schemeRegistry = new SchemeRegistry();
|
||||
try {
|
||||
// register the default socket factory so that it looks at the javax.net.ssl.keyStore,
|
||||
// javax.net.ssl.trustStore, etc, properties by default
|
||||
SSLSocketFactory sslSocketFactory =
|
||||
new SSLSocketFactory((javax.net.ssl.SSLSocketFactory) javax.net.ssl.SSLSocketFactory.getDefault(),
|
||||
SSLSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);
|
||||
schemeRegistry.register(new Scheme("https", getRemoteUrl().getPort(), sslSocketFactory));
|
||||
return schemeRegistry;
|
||||
} catch (Exception e) {
|
||||
throw new IllegalStateException("Failure trying to create scheme registry", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,62 @@
|
|||
/**
|
||||
* 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.activemq.transport.https;
|
||||
|
||||
import junit.framework.Test;
|
||||
import junit.textui.TestRunner;
|
||||
import org.apache.activemq.broker.BrokerFactory;
|
||||
import org.apache.activemq.broker.BrokerService;
|
||||
import org.apache.activemq.transport.http.HttpTransportBrokerTest;
|
||||
|
||||
import java.net.URI;
|
||||
|
||||
/**
|
||||
* @author <a href="http://www.christianposta.com/blog">Christian Posta</a>
|
||||
*/
|
||||
public class HttpsNeedClientAuthBrokerTest extends HttpTransportBrokerTest {
|
||||
|
||||
private static final String HTTPS_TRANSPORT_URL = "https://localhost:8161?transport.needClientAuth=true";
|
||||
|
||||
protected String getBindLocation() {
|
||||
return "https://localhost:8161";
|
||||
}
|
||||
|
||||
protected void setUp() throws Exception {
|
||||
System.setProperty("javax.net.ssl.trustStore", "src/test/resources/client.keystore");
|
||||
System.setProperty("javax.net.ssl.trustStorePassword", "password");
|
||||
System.setProperty("javax.net.ssl.trustStoreType", "jks");
|
||||
System.setProperty("javax.net.ssl.keyStore", "src/test/resources/server.keystore");
|
||||
System.setProperty("javax.net.ssl.keyStorePassword", "password");
|
||||
System.setProperty("javax.net.ssl.keyStoreType", "jks");
|
||||
super.setUp();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected BrokerService createBroker() throws Exception {
|
||||
BrokerService broker = BrokerFactory.createBroker(new URI("broker:()/localhost?persistent=false&useJmx=false"));
|
||||
connector = broker.addConnector(HTTPS_TRANSPORT_URL);
|
||||
return broker;
|
||||
}
|
||||
|
||||
public static Test suite() {
|
||||
return suite(HttpsNeedClientAuthBrokerTest.class);
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
TestRunner.run(suite());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,70 @@
|
|||
/**
|
||||
* 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.activemq.transport.https;
|
||||
|
||||
import org.apache.activemq.ActiveMQConnectionFactory;
|
||||
import org.apache.activemq.JmsTopicSendReceiveTest;
|
||||
import org.apache.activemq.broker.BrokerFactory;
|
||||
import org.apache.activemq.broker.BrokerService;
|
||||
|
||||
/**
|
||||
* @author <a href="http://www.christianposta.com/blog">Christian Posta</a>
|
||||
*/
|
||||
public class HttpsNeedClientAuthSendAndReceiveTest extends JmsTopicSendReceiveTest {
|
||||
|
||||
public static final String KEYSTORE_TYPE = "jks";
|
||||
public static final String PASSWORD = "password";
|
||||
public static final String TRUST_KEYSTORE = "src/test/resources/client.keystore";
|
||||
public static final String KEYSTORE = "src/test/resources/server.keystore";
|
||||
|
||||
|
||||
private BrokerService broker;
|
||||
|
||||
|
||||
|
||||
// set up broker with https first...
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
broker = BrokerFactory.createBroker("xbean:activemq-https-need-client-auth.xml");
|
||||
broker.setPersistent(false);
|
||||
broker.start();
|
||||
broker.waitUntilStarted();
|
||||
|
||||
// these are used for the client side... for the server side, the SSL context
|
||||
// will be configured through the <sslContext> spring beans
|
||||
System.setProperty("javax.net.ssl.trustStore", TRUST_KEYSTORE);
|
||||
System.setProperty("javax.net.ssl.trustStorePassword", PASSWORD);
|
||||
System.setProperty("javax.net.ssl.trustStoreType", KEYSTORE_TYPE);
|
||||
System.setProperty("javax.net.ssl.keyStore", KEYSTORE);
|
||||
System.setProperty("javax.net.ssl.keyStorePassword", PASSWORD);
|
||||
System.setProperty("javax.net.ssl.keyStoreType", KEYSTORE_TYPE);
|
||||
super.setUp();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void tearDown() throws Exception {
|
||||
super.tearDown();
|
||||
if (broker != null) {
|
||||
broker.stop();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ActiveMQConnectionFactory createConnectionFactory() throws Exception {
|
||||
return new ActiveMQConnectionFactory("https://localhost:8161");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,70 @@
|
|||
/**
|
||||
* 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.activemq.transport.https;
|
||||
|
||||
import org.apache.activemq.ActiveMQConnectionFactory;
|
||||
import org.apache.activemq.JmsTopicSendReceiveTest;
|
||||
import org.apache.activemq.broker.BrokerFactory;
|
||||
import org.apache.activemq.broker.BrokerService;
|
||||
|
||||
/**
|
||||
* @author <a href="http://www.christianposta.com/blog">Christian Posta</a>
|
||||
*/
|
||||
public class HttpsWantClientAuthSendAndReceiveTest extends JmsTopicSendReceiveTest {
|
||||
|
||||
public static final String KEYSTORE_TYPE = "jks";
|
||||
public static final String PASSWORD = "password";
|
||||
public static final String TRUST_KEYSTORE = "src/test/resources/client.keystore";
|
||||
public static final String KEYSTORE = "src/test/resources/server.keystore";
|
||||
|
||||
|
||||
private BrokerService broker;
|
||||
|
||||
|
||||
|
||||
// set up broker with https first...
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
broker = BrokerFactory.createBroker("xbean:activemq-https-want-client-auth.xml");
|
||||
broker.setPersistent(false);
|
||||
broker.start();
|
||||
broker.waitUntilStarted();
|
||||
|
||||
// these are used for the client side... for the server side, the SSL context
|
||||
// will be configured through the <sslContext> spring beans
|
||||
System.setProperty("javax.net.ssl.trustStore", TRUST_KEYSTORE);
|
||||
System.setProperty("javax.net.ssl.trustStorePassword", PASSWORD);
|
||||
System.setProperty("javax.net.ssl.trustStoreType", KEYSTORE_TYPE);
|
||||
// System.setProperty("javax.net.ssl.keyStore", KEYSTORE);
|
||||
// System.setProperty("javax.net.ssl.keyStorePassword", PASSWORD);
|
||||
// System.setProperty("javax.net.ssl.keyStoreType", KEYSTORE_TYPE);
|
||||
super.setUp();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void tearDown() throws Exception {
|
||||
super.tearDown();
|
||||
if (broker != null) {
|
||||
broker.stop();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ActiveMQConnectionFactory createConnectionFactory() throws Exception {
|
||||
return new ActiveMQConnectionFactory("https://localhost:8161");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
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.
|
||||
-->
|
||||
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:amq="http://activemq.apache.org/schema/core"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd http://activemq.apache.org/schema/core http://activemq.apache.org/schema/core/activemq-core.xsd ">
|
||||
|
||||
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer" />
|
||||
|
||||
<amq:broker brokerName="localhost" useJmx="false">
|
||||
|
||||
<amq:sslContext>
|
||||
<amq:sslContext keyStorePassword="password"
|
||||
keyStore="src/test/resources/server.keystore"
|
||||
trustStore="src/test/resources/client.keystore"
|
||||
trustStorePassword="password" />
|
||||
</amq:sslContext>
|
||||
|
||||
<amq:transportConnectors>
|
||||
<amq:transportConnector name="https"
|
||||
uri="https://localhost:8161?transport.needClientAuth=true" />
|
||||
</amq:transportConnectors>
|
||||
</amq:broker>
|
||||
|
||||
</beans>
|
|
@ -0,0 +1,41 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
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.
|
||||
-->
|
||||
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:amq="http://activemq.apache.org/schema/core"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd http://activemq.apache.org/schema/core http://activemq.apache.org/schema/core/activemq-core.xsd ">
|
||||
|
||||
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer" />
|
||||
|
||||
<amq:broker brokerName="localhost" useJmx="false">
|
||||
|
||||
<amq:sslContext>
|
||||
<amq:sslContext keyStorePassword="password"
|
||||
keyStore="src/test/resources/server.keystore"
|
||||
trustStore="src/test/resources/client.keystore"
|
||||
trustStorePassword="password" />
|
||||
</amq:sslContext>
|
||||
|
||||
<amq:transportConnectors>
|
||||
<amq:transportConnector name="https"
|
||||
uri="https://localhost:8161?transport.wantClientAuth=true" />
|
||||
</amq:transportConnectors>
|
||||
</amq:broker>
|
||||
|
||||
</beans>
|
|
@ -80,7 +80,7 @@ public class SslBrokerServiceTest extends TransportBrokerTestSupport {
|
|||
return service;
|
||||
}
|
||||
|
||||
public void testNeedClientAuth() throws Exception {
|
||||
public void testNeedClientAuthReject() throws Exception {
|
||||
SSLContext context = SSLContext.getInstance("TLS");
|
||||
// no client cert
|
||||
context.init(null, getTrustManager(), null);
|
||||
|
@ -94,6 +94,12 @@ public class SslBrokerServiceTest extends TransportBrokerTestSupport {
|
|||
// should work with regular connector
|
||||
makeSSLConnection(context, null, connector);
|
||||
}
|
||||
|
||||
public void testNeedClientAuthSucceed() throws Exception {
|
||||
SSLContext context = SSLContext.getInstance("TLS");
|
||||
context.init(getKeyManager(), getTrustManager(), null);
|
||||
makeSSLConnection(context, null, needClientAuthConnector);
|
||||
}
|
||||
|
||||
public void testCipherSuitesDisabled() throws Exception {
|
||||
SSLContext context = SSLContext.getInstance("TLS");
|
||||
|
|
Loading…
Reference in New Issue