This commit is contained in:
Dejan Bosanac 2015-03-30 16:39:04 +02:00
parent af13292916
commit 0fd174b928
7 changed files with 193 additions and 6 deletions

View File

@ -21,17 +21,18 @@ import java.net.MalformedURLException;
import java.security.KeyStore;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.cert.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import javax.annotation.PostConstruct;
import javax.net.ssl.KeyManager;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
import javax.net.ssl.*;
import org.apache.activemq.broker.SslContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.io.Resource;
/**
* Extends the SslContext so that it's easier to configure from spring.
@ -42,6 +43,8 @@ import org.apache.activemq.broker.SslContext;
*/
public class SpringSslContext extends SslContext {
private static final transient Logger LOG = LoggerFactory.getLogger(SpringSslContext.class);
private String keyStoreType="jks";
private String trustStoreType="jks";
@ -56,6 +59,8 @@ public class SpringSslContext extends SslContext {
private String keyStorePassword;
private String trustStorePassword;
private String crlPath;
/**
* JSR-250 callback wrapper; converts checked exceptions to runtime exceptions
*
@ -92,9 +97,23 @@ public class SpringSslContext extends SslContext {
if( ks ==null ) {
return new ArrayList<TrustManager>(0);
}
TrustManagerFactory tmf = TrustManagerFactory.getInstance(trustStoreAlgorithm);
if (crlPath != null) {
if (trustStoreAlgorithm.equalsIgnoreCase("PKIX")) {
Collection<? extends CRL> crlList = loadCRL();
if (crlList != null) {
PKIXBuilderParameters pkixParams = new PKIXBuilderParameters(ks, null);
pkixParams.setRevocationEnabled(true);
pkixParams.addCertStore(CertStore.getInstance("Collection", new CollectionCertStoreParameters(crlList)));
tmf.init(new CertPathTrustManagerParameters(pkixParams));
}
} else {
LOG.warn("Revocation checking is only supported with 'trustStoreAlgorithm=\"PKIX\"'. Ignoring CRL: " + crlPath);
}
} else {
tmf.init(ks);
}
return Arrays.asList(tmf.getTrustManagers());
}
@ -219,4 +238,25 @@ public class SpringSslContext extends SslContext {
this.secureRandomAlgorithm = secureRandomAlgorithm;
}
public String getCrlPath() {
return crlPath;
}
public void setCrlPath(String crlPath) {
this.crlPath = crlPath;
}
private Collection<? extends CRL> loadCRL() throws Exception {
if (crlPath == null) {
return null;
}
Resource resource = Utils.resourceFromString(crlPath);
InputStream is = resource.getInputStream();
try {
return CertificateFactory.getInstance("X.509").generateCRLs(is);
} finally {
is.close();
}
}
}

View File

@ -0,0 +1,84 @@
/**
* 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.security;
import junit.framework.TestCase;
import org.apache.activemq.ActiveMQConnectionFactory;
import org.apache.activemq.broker.BrokerFactory;
import org.apache.activemq.broker.BrokerService;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import javax.jms.*;
import static junit.framework.TestCase.assertTrue;
public class CRLTest {
BrokerService broker;
@Before
public void setup() throws Exception {
broker = BrokerFactory.createBroker("xbean:src/test/resources/org/apache/activemq/security/activemq-revoke.xml");
broker.waitUntilStarted();
}
@After
public void after() throws Exception {
broker.stop();
broker.waitUntilStopped();
}
@Test
public void testCRL() throws Exception {
System.setProperty("javax.net.ssl.trustStore", "src/test/resources/org/apache/activemq/security/client.ts");
System.setProperty("javax.net.ssl.trustStorePassword", "password");
System.setProperty("javax.net.ssl.trustStoreType", "jks");
System.setProperty("javax.net.ssl.keyStore", "src/test/resources/org/apache/activemq/security/activemq-revoke.jks");
System.setProperty("javax.net.ssl.keyStorePassword", "password");
System.setProperty("javax.net.ssl.keyStoreType", "jks");
boolean failed = false;
try {
basicSendReceive("ssl://localhost:61617");
} catch (Exception e) {
failed = true;
}
assertTrue("Send should have failed", failed);
}
public void basicSendReceive(String uri) throws Exception {
ActiveMQConnectionFactory factory = new ActiveMQConnectionFactory(uri);
Connection connection = factory.createConnection();
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
connection.start();
String body = "hello world!";
Queue destination = session.createQueue("TEST");
MessageProducer producer = session.createProducer(destination);
producer.send(session.createTextMessage(body));
MessageConsumer consumer = session.createConsumer(destination);
Message received = consumer.receive(2000);
TestCase.assertEquals(body, ((TextMessage)received).getText());
}
}

View File

@ -0,0 +1,9 @@
-----BEGIN X509 CRL-----
MIIBRzCBsQIBATANBgkqhkiG9w0BAQUFADBYMQswCQYDVQQGEwJBVTETMBEGA1UE
CBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRk
MREwDwYDVQQDEwhhY3RpdmVtcRcNMTUwMzI3MTMwMjIwWhcNMTUwNDI2MTMwMjIw
WjAUMBICAQEXDTE1MDMyNzEzMDEzM1qgDzANMAsGA1UdFAQEAgIQATANBgkqhkiG
9w0BAQUFAAOBgQBLvpTwNFdjODFkJR1okloK5Qka6+Lzc5AwtqbYBlhQA1wCSpfB
qzrUh43D97r88+w03mh1FI1PSKACXikHAgm2KZEiZrObIXYwdhJ7t1oSdGM6gPPS
VQmgnvgbte3Mm8F4BoVhidp1gSe+f8RdRZYv1A+olREcz+lU7LxOIN6CpQ==
-----END X509 CRL-----

View File

@ -0,0 +1,10 @@
-----BEGIN X509 CRL-----
MIIBWzCBxQIBATANBgkqhkiG9w0BAQUFADBYMQswCQYDVQQGEwJBVTETMBEGA1UE
CBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRk
MREwDwYDVQQDEwhhY3RpdmVtcRcNMTUwMzMwMDk1ODI5WhcNMTUwNDI5MDk1ODI5
WjAoMBICAQEXDTE1MDMyNzEzMDEzM1owEgIBAhcNMTUwMzMwMDk1MzU3WqAPMA0w
CwYDVR0UBAQCAhAFMA0GCSqGSIb3DQEBBQUAA4GBADniQGR0r4x2zc33ozVkKpcm
RUMD0JWMYzACvBEkP84ymms3x4jZzvaSgnkLtenktlOAWfAF4RSAqKS+2Vk1jaZm
1drV1cGWnftHsLjvv9e226ROLQgZ+Wey0B3OyeiCubHVoZeyGEERoM4ZVrCxd5Oe
Lfj+PMhnHGKD9c1MP1rR
-----END X509 CRL-----

View File

@ -0,0 +1,43 @@
<!--
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.
-->
<!-- START SNIPPET: example -->
<beans
xmlns="http://www.springframework.org/schema/beans"
xmlns:amq="http://activemq.apache.org/schema/core"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
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">
<broker xmlns="http://activemq.apache.org/schema/core" brokerName="broker1" useJmx="false" persistent="false">
<sslContext>
<sslContext keyStore="org/apache/activemq/security/broker1.ks"
keyStorePassword="password"
trustStore="org/apache/activemq/security/activemq-revoke.jks"
trustStorePassword="password"
crlPath="org/apache/activemq/security/activemq-revoke.crl"/>
</sslContext>
<!-- The transport connectors ActiveMQ will listen to -->
<transportConnectors>
<transportConnector name="ssl" uri="ssl://0.0.0.0:61617?transport.closeAsync=false&amp;wantClientAuth=true&amp;needClientAuth=true"/>
</transportConnectors>
</broker>
</beans>
<!-- END SNIPPET: example -->

View File

@ -72,6 +72,7 @@ if [ -z "$ACTIVEMQ_QUEUEMANAGERURL" ]; then
fi
# Set additional JSE arguments
#ACTIVEMQ_SSL_OPTS="-Dcom.sun.security.enableCRLDP=true -Docsp.enable=true -Docsp.responderURL=http://ocsp.example.net:80"
ACTIVEMQ_SSL_OPTS=""
# Uncomment to enable remote debugging