[ 
https://issues.apache.org/jira/browse/ARTEMIS-1548?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=16291619#comment-16291619
 ] 

ASF GitHub Bot commented on ARTEMIS-1548:
-----------------------------------------

Github user jbertram commented on a diff in the pull request:

    https://github.com/apache/activemq-artemis/pull/1715#discussion_r157064083
  
    --- Diff: 
tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/mqtt/imported/MQTTSecurityCRLTest.java
 ---
    @@ -0,0 +1,357 @@
    +/**
    + * 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
    + * <p>
    + * http://www.apache.org/licenses/LICENSE-2.0
    + * <p>
    + * 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.artemis.tests.integration.mqtt.imported;
    +
    +import java.io.ByteArrayInputStream;
    +import java.io.ByteArrayOutputStream;
    +import java.io.File;
    +import java.io.FileInputStream;
    +import java.io.IOException;
    +import java.security.KeyStore;
    +import java.security.ProtectionDomain;
    +import java.util.HashSet;
    +import java.util.Set;
    +import java.util.concurrent.TimeUnit;
    +import javax.net.ssl.KeyManager;
    +import javax.net.ssl.KeyManagerFactory;
    +import javax.net.ssl.SSLContext;
    +import javax.net.ssl.SSLException;
    +import javax.net.ssl.TrustManager;
    +import javax.net.ssl.TrustManagerFactory;
    +import org.apache.activemq.artemis.api.core.TransportConfiguration;
    +import org.apache.activemq.artemis.core.config.Configuration;
    +import org.apache.activemq.artemis.core.config.WildcardConfiguration;
    +import org.apache.activemq.artemis.core.config.impl.FileConfiguration;
    +import 
org.apache.activemq.artemis.core.remoting.impl.netty.NettyAcceptorFactory;
    +import 
org.apache.activemq.artemis.core.remoting.impl.netty.TransportConstants;
    +import org.apache.activemq.artemis.core.security.Role;
    +import org.apache.activemq.artemis.core.server.ActiveMQServer;
    +import org.apache.activemq.artemis.core.settings.HierarchicalRepository;
    +import 
org.apache.activemq.artemis.spi.core.security.ActiveMQJAASSecurityManager;
    +import org.apache.activemq.artemis.tests.util.ActiveMQTestBase;
    +import org.fusesource.mqtt.client.BlockingConnection;
    +import org.fusesource.mqtt.client.MQTT;
    +import org.fusesource.mqtt.client.Message;
    +import org.fusesource.mqtt.client.QoS;
    +import org.fusesource.mqtt.client.Topic;
    +import org.junit.Test;
    +
    +public class MQTTSecurityCRLTest extends ActiveMQTestBase {
    +
    +
    +   /**
    +    * These artifacts are required for testing mqtt with CRL
    +    * <p>
    +    * openssl genrsa -out ca.key 2048
    +    * openssl req -new -x509 -days 1826 -key ca.key -out ca.crt
    +    * touch certindex
    +    * echo 01 > certserial
    +    * echo 01 > crlnumber
    +    * <p>
    +    * Create ca.conf file with
    +    * <p>
    +    * # Mainly copied from:
    +    * # http://swearingscience.com/2009/01/18/openssl-self-signed-ca/
    +    * <p>
    +    * [ ca ]
    +    * default_ca = myca
    +    * <p>
    +    * [ crl_ext ]
    +    * # issuerAltName=issuer:copy #this would copy the issuer name to 
altname
    +    * authorityKeyIdentifier=keyid:always
    +    * <p>
    +    * [ myca ]
    +    * dir = ./
    +    * new_certs_dir = $dir
    +    * unique_subject = no
    +    * certificate = $dir/ca.crt
    +    * database = $dir/certindex
    +    * private_key = $dir/ca.key
    +    * serial = $dir/certserial
    +    * default_days = 730
    +    * default_md = sha1
    +    * policy = myca_policy
    +    * x509_extensions = myca_extensions
    +    * crlnumber = $dir/crlnumber
    +    * default_crl_days = 730
    +    * <p>
    +    * [ myca_policy ]
    +    * commonName = supplied
    +    * stateOrProvinceName = supplied
    +    * countryName = optional
    +    * emailAddress = optional
    +    * organizationName = supplied
    +    * organizationalUnitName = optional
    +    * <p>
    +    * [ myca_extensions ]
    +    * basicConstraints = CA:false
    +    * subjectKeyIdentifier = hash
    +    * authorityKeyIdentifier = keyid:always
    +    * keyUsage = digitalSignature,keyEncipherment
    +    * extendedKeyUsage = serverAuth, clientAuth
    +    * crlDistributionPoints = URI:http://example.com/root.crl
    +    * subjectAltName = @alt_names
    +    * <p>
    +    * [alt_names]
    +    * DNS.1 = example.com
    +    * DNS.2 = *.example.com
    +    * <p>
    +    * Continue executing the commands:
    +    * <p>
    +    * openssl genrsa -out keystore1.key 2048
    +    * openssl req -new -key keystore1.key -out keystore1.csr
    +    * openssl ca -batch -config ca.conf -notext -in keystore1.csr -out 
keystore1.crt
    +    * openssl genrsa -out client_revoked.key 2048
    +    * openssl req -new -key client_revoked.key -out client_revoked.csr
    +    * openssl ca -batch -config ca.conf -notext -in client_revoked.csr 
-out client_revoked.crt
    +    * openssl genrsa -out client_not_revoked.key 2048
    +    * openssl req -new -key client_not_revoked.key -out 
client_not_revoked.csr
    +    * openssl ca -batch -config ca.conf -notext -in client_not_revoked.csr 
-out client_not_revoked.crt
    +    * openssl ca -config ca.conf -gencrl -keyfile ca.key -cert ca.crt -out 
root.crl.pem
    +    * openssl ca -config ca.conf -revoke client_revoked.crt -keyfile 
ca.key -cert ca.crt
    +    * openssl ca -config ca.conf -gencrl -keyfile ca.key -cert ca.crt -out 
root.crl.pem
    +    * <p>
    +    * openssl pkcs12 -export -name client_revoked -in client_revoked.crt 
-inkey client_revoked.key -out client_revoked.p12
    +    * keytool -importkeystore -destkeystore client_revoked.jks 
-srckeystore client_revoked.p12 -srcstoretype pkcs12 -alias client_revoked
    +    * <p>
    +    * openssl pkcs12 -export -name client_not_revoked -in 
client_not_revoked.crt -inkey client_not_revoked.key -out client_not_revoked.p12
    +    * keytool -importkeystore -destkeystore client_not_revoked.jks 
-srckeystore client_not_revoked.p12 -srcstoretype pkcs12 -alias 
client_not_revoked
    +    * <p>
    +    * openssl pkcs12 -export -name keystore1 -in keystore1.crt -inkey 
keystore1.key -out keystore1.p12
    +    * keytool -importkeystore -destkeystore keystore1.jks -srckeystore 
keystore1.p12 -srcstoretype pkcs12 -alias keystore1
    +    * <p>
    +    * keytool -import -trustcacerts -alias trust_key -file ca.crt 
-keystore truststore.jks
    +    */
    +
    +   protected String fullUser = "user";
    +   protected String fullPass = "pass";
    +
    +
    +   public File basedir() throws IOException {
    +      ProtectionDomain protectionDomain = getClass().getProtectionDomain();
    +      return new File(new 
File(protectionDomain.getCodeSource().getLocation().getPath()), 
"../..").getCanonicalFile();
    +   }
    +
    +   @Test(expected = SSLException.class)
    +   public void crlRevokedTest() throws Exception {
    +
    +      ActiveMQServer server1 = initServer();
    +      BlockingConnection connection1 = null;
    +      try {
    +         server1.start();
    +
    +         while (!server1.isStarted()) {
    +            Thread.sleep(50);
    +         }
    +
    +         String basedir = basedir().getPath() + 
"/src/test/resources/mqttCrl/client0/";
    +         connection1 = retrieveMQTTConnection("ssl://localhost:1883", 
basedir + "truststore.jks", "changeit", basedir + "client_revoked.jks", 
"changeit");
    +
    +         // Subscribe to topics
    +         Topic[] topics = {new Topic("test/+/some/#", QoS.AT_MOST_ONCE)};
    +         connection1.subscribe(topics);
    +
    +         // Publish Messages
    +         String payload1 = "This is message 1";
    +
    +         connection1.publish("test/1/some/la", payload1.getBytes(), 
QoS.AT_LEAST_ONCE, false);
    +
    +         Message message1 = connection1.receive(5, TimeUnit.SECONDS);
    +
    +         assertEquals(payload1, new String(message1.getPayload()));
    +
    +      } finally {
    +         if (connection1 != null) {
    +            connection1.disconnect();
    +         }
    +         if (server1.isStarted()) {
    +            server1.stop();
    +         }
    +      }
    +
    +   }
    +
    +   @Test
    +   public void crlNotRevokedTest() throws Exception {
    +
    +      ActiveMQServer server1 = initServer();
    +      BlockingConnection connection1 = null;
    +      try {
    +         server1.start();
    +
    +         while (!server1.isStarted()) {
    +            Thread.sleep(50);
    +         }
    +
    +         String basedir = basedir().getPath() + 
"/src/test/resources/mqttCrl/client1/";
    +         connection1 = retrieveMQTTConnection("ssl://localhost:1883", 
basedir + "truststore.jks", "changeit", basedir + "client_not_revoked.jks", 
"changeit");
    +
    +         // Subscribe to topics
    +         Topic[] topics = {new Topic("test/+/some/#", QoS.AT_MOST_ONCE)};
    +         connection1.subscribe(topics);
    +
    +         // Publish Messages
    +         String payload1 = "This is message 1";
    +
    +         connection1.publish("test/1/some/la", payload1.getBytes(), 
QoS.AT_LEAST_ONCE, false);
    +
    +         Message message1 = connection1.receive(5, TimeUnit.SECONDS);
    +
    +         assertEquals(payload1, new String(message1.getPayload()));
    +
    +      } finally {
    +         if (connection1 != null) {
    +            connection1.disconnect();
    +         }
    +         if (server1.isStarted()) {
    +            server1.stop();
    +         }
    +      }
    +
    +   }
    +
    +
    +   private ActiveMQServer initServer() throws Exception {
    +      Configuration configuration = createConfiguration("broker");
    +      ActiveMQServer server = createServer(true, configuration);
    +      configureBrokerSecurity(server);
    +      return server;
    +   }
    +
    +   protected Configuration createConfiguration(String name) throws 
Exception {
    +      FileConfiguration fc = new FileConfiguration();
    +
    +      // we need this otherwise the data folder will be located under 
activemq-server and not on the temporary directory
    +      fc.setPagingDirectory(getTestDir() + "/" + name + "/" + 
fc.getPagingDirectory());
    +      fc.setLargeMessagesDirectory(getTestDir() + "/" + name + "/" + 
fc.getLargeMessagesDirectory());
    +      fc.setJournalDirectory(getTestDir() + "/" + name + "/" + 
fc.getJournalDirectory());
    +      fc.setBindingsDirectory(getTestDir() + "/" + name + "/" + 
fc.getBindingsDirectory());
    +
    +      addMqttTransportConfiguration(fc);
    +      addWildCardConfiguration(fc);
    +      fc.setSecurityEnabled(true);
    +
    +      return fc;
    +   }
    +
    +   private void addWildCardConfiguration(FileConfiguration fc) {
    +      WildcardConfiguration wildcardConfiguration = new 
WildcardConfiguration();
    +      wildcardConfiguration.setAnyWords('#');
    +      wildcardConfiguration.setDelimiter('/');
    +      wildcardConfiguration.setRoutingEnabled(true);
    +      wildcardConfiguration.setSingleWord('+');
    +
    +      fc.setWildCardConfiguration(wildcardConfiguration);
    +   }
    +
    +   private void addMqttTransportConfiguration(FileConfiguration fc) throws 
IOException {
    +      String basedir = basedir().getPath() + 
"/src/test/resources/mqttCrl/server/";
    +      TransportConfiguration transportConfiguration = new 
TransportConfiguration(NettyAcceptorFactory.class.getCanonicalName(), null, 
"mqtt", null);
    +
    +      
transportConfiguration.getParams().put(TransportConstants.SSL_ENABLED_PROP_NAME,
 true);
    +      
transportConfiguration.getParams().put(TransportConstants.TRUSTSTORE_PATH_PROP_NAME,
 basedir + "truststore.jks");
    +      
transportConfiguration.getParams().put(TransportConstants.TRUSTSTORE_PASSWORD_PROP_NAME,
 "changeit");
    +      
transportConfiguration.getParams().put(TransportConstants.KEYSTORE_PATH_PROP_NAME,
 basedir + "keystore1.jks");
    +      
transportConfiguration.getParams().put(TransportConstants.KEYSTORE_PASSWORD_PROP_NAME,
 "changeit");
    +      
transportConfiguration.getParams().put(TransportConstants.CRL_PATH_PROP_NAME, 
basedir + "root.crl.pem");
    +      
transportConfiguration.getParams().put(TransportConstants.NEED_CLIENT_AUTH_PROP_NAME,
 "true");
    +      
transportConfiguration.getParams().put(TransportConstants.PORT_PROP_NAME, 
"1883");
    +      
transportConfiguration.getParams().put(TransportConstants.HOST_PROP_NAME, 
"localhost");
    +      
transportConfiguration.getParams().put(TransportConstants.PROTOCOLS_PROP_NAME, 
"MQTT");
    +
    +      fc.getAcceptorConfigurations().add(transportConfiguration);
    +   }
    +
    +   protected void configureBrokerSecurity(ActiveMQServer server) {
    +
    +      ActiveMQJAASSecurityManager securityManager = 
(ActiveMQJAASSecurityManager) server.getSecurityManager();
    +
    +      securityManager.getConfiguration().addUser(fullUser, fullPass);
    +      securityManager.getConfiguration().addRole(fullUser, "full");
    +      // Configure roles
    +      HierarchicalRepository<Set<Role>> securityRepository = 
server.getSecurityRepository();
    +      HashSet<Role> value = new HashSet<>();
    +      value.add(new Role("nothing", false, false, false, false, false, 
false, false, false));
    +      value.add(new Role("browser", false, false, false, false, false, 
false, false, true));
    +      value.add(new Role("guest", false, true, false, false, false, false, 
false, true));
    +      value.add(new Role("full", true, true, true, true, true, true, true, 
true));
    +      securityRepository.addMatch("#", value);
    +
    +      server.getConfiguration().setSecurityEnabled(true);
    +   }
    +
    +   public static TrustManager[] getTrustManager(String truststorePath, 
String truststorePass) throws Exception {
    +      KeyStore trustedCertStore = KeyStore.getInstance("jks");
    +
    +      trustedCertStore.load(new FileInputStream(truststorePath), 
truststorePass.toCharArray());
    +      TrustManagerFactory tmf = 
TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
    +
    +      tmf.init(trustedCertStore);
    +      return tmf.getTrustManagers();
    +   }
    +
    +   public static KeyManager[] getKeyManager(String keystorePath, String 
keystorePass) throws Exception {
    +      KeyManagerFactory kmf = 
KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
    +      KeyStore ks = KeyStore.getInstance("jks");
    +      KeyManager[] keystoreManagers = null;
    +
    +      byte[] sslCert = loadClientCredential(keystorePath);
    +
    +      if (sslCert != null && sslCert.length > 0) {
    +         ByteArrayInputStream bin = new ByteArrayInputStream(sslCert);
    +         ks.load(bin, keystorePass.toCharArray());
    +         kmf.init(ks, keystorePass.toCharArray());
    +         keystoreManagers = kmf.getKeyManagers();
    +      }
    +      return keystoreManagers;
    +   }
    +
    +   private static byte[] loadClientCredential(String fileName) throws 
IOException {
    +      if (fileName == null) {
    +         return null;
    +      }
    +      FileInputStream in = new FileInputStream(fileName);
    +      ByteArrayOutputStream out = new ByteArrayOutputStream();
    +      byte[] buf = new byte[512];
    +      int i = in.read(buf);
    +      while (i > 0) {
    +         out.write(buf, 0, i);
    +         i = in.read(buf);
    +      }
    +      in.close();
    +      return out.toByteArray();
    +   }
    +
    +   private BlockingConnection retrieveMQTTConnection(String host, String 
truststorePath, String truststorePass, String keystorePath, String 
keystorePass) throws Exception {
    +
    +      MQTT mqtt = new MQTT();
    +      mqtt.setConnectAttemptsMax(1);
    +      mqtt.setReconnectAttemptsMax(0);
    +      mqtt.setHost(host);
    +      mqtt.setUserName(fullUser);
    +      mqtt.setPassword(fullPass);
    +      SSLContext sslContext = SSLContext.getInstance("TLS");
    --- End diff --
    
    Why not use the SSLSupport class that's already included in the code-base 
to generate the SSLContext?


> Support CRL
> -----------
>
>                 Key: ARTEMIS-1548
>                 URL: https://issues.apache.org/jira/browse/ARTEMIS-1548
>             Project: ActiveMQ Artemis
>          Issue Type: New Feature
>            Reporter: Justin Bertram
>            Assignee: Justin Bertram
>




--
This message was sent by Atlassian JIRA
(v6.4.14#64029)

Reply via email to