You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by co...@apache.org on 2019/05/24 19:39:26 UTC

[camel] 04/21: Improving TLS configuration

This is an automated email from the ASF dual-hosted git repository.

coheigea pushed a commit to branch camel-2.x
in repository https://gitbox.apache.org/repos/asf/camel.git

commit a7f884d132bc0ace1682d90efdd6e367240f3ab6
Author: Colm O hEigeartaigh <co...@apache.org>
AuthorDate: Wed Apr 10 13:48:52 2019 +0100

    Improving TLS configuration
---
 .../camel-coap/src/main/docs/coap-component.adoc   |  10 +-
 .../java/org/apache/camel/coap/CoAPComponent.java  |  53 ++++----
 .../java/org/apache/camel/coap/CoAPEndpoint.java   | 150 ++++++++++++++++++++-
 .../java/org/apache/camel/coap/CoAPProducer.java   |  45 +++----
 4 files changed, 198 insertions(+), 60 deletions(-)

diff --git a/components/camel-coap/src/main/docs/coap-component.adoc b/components/camel-coap/src/main/docs/coap-component.adoc
index 1517f4f..0ac6390 100644
--- a/components/camel-coap/src/main/docs/coap-component.adoc
+++ b/components/camel-coap/src/main/docs/coap-component.adoc
@@ -50,18 +50,24 @@ with the following path and query parameters:
 |===
 
 
-==== Query Parameters (6 parameters):
+==== Query Parameters (12 parameters):
 
 
 [width="100%",cols="2,5,^1,2",options="header"]
 |===
 | Name | Description | Default | Type
-| *keyStoreParameters* (common) | The KeyStoreParameters object to use with TLS |  | KeyStoreParameters
+| *alias* (common) | Sets the alias used to query the KeyStore for the private key and certificate. |  | String
+| *cipherSuites* (common) | Sets the cipherSuites String. This is a comma separated String of ciphersuites to configure. |  | String
+| *keystore* (common) | Sets the TLS key store. Alternatively, a KeyStoreParameters object can be configured instead. An alias and password should also be configured on the route definition. |  | KeyStore
+| *keyStoreParameters* (common) | The KeyStoreParameters object to use with TLS to configure the keystore. Alternatively, a keystore parameter can be directly configured instead. An alias and password should also be configured on the route definition. |  | KeyStoreParameters
+| *truststore* (common) | Sets the TLS trust store. Alternatively, a trustStoreParameters object can be configured instead. All certificates in the truststore are used to establish trust. |  | KeyStore
+| *trustStoreParameters* (common) | The KeyStoreParameters object to use with TLS to configure the truststore. Alternatively, a truststore object can be directly configured instead. All certificates in the truststore are used to establish trust. |  | KeyStoreParameters
 | *bridgeErrorHandler* (consumer) | Allows for bridging the consumer to the Camel routing Error Handler, which mean any exceptions occurred while the consumer is trying to pickup incoming messages, or the likes, will now be processed as a message and handled by the routing Error Handler. By default the consumer will use the org.apache.camel.spi.ExceptionHandler to deal with exceptions, that will be logged at WARN or ERROR level and ignored. | false | boolean
 | *coapMethodRestrict* (consumer) | Comma separated list of methods that the CoAP consumer will bind to. The default is to bind to all methods (DELETE, GET, POST, PUT). |  | String
 | *exceptionHandler* (consumer) | To let the consumer use a custom ExceptionHandler. Notice if the option bridgeErrorHandler is enabled then this option is not in use. By default the consumer will deal with exceptions, that will be logged at WARN or ERROR level and ignored. |  | ExceptionHandler
 | *exchangePattern* (consumer) | Sets the exchange pattern when the consumer creates an exchange. |  | ExchangePattern
 | *synchronous* (advanced) | Sets whether synchronous processing should be strictly used, or Camel is allowed to use asynchronous processing (if supported). | false | boolean
+| *password* (security) | Sets the password used to access an aliased PrivateKey in the KeyStore. |  | String
 |===
 // endpoint options: END
 // spring-boot-auto-configure options: START
diff --git a/components/camel-coap/src/main/java/org/apache/camel/coap/CoAPComponent.java b/components/camel-coap/src/main/java/org/apache/camel/coap/CoAPComponent.java
index 40e2c20..13f0c9b 100644
--- a/components/camel-coap/src/main/java/org/apache/camel/coap/CoAPComponent.java
+++ b/components/camel-coap/src/main/java/org/apache/camel/coap/CoAPComponent.java
@@ -16,17 +16,10 @@
  */
 package org.apache.camel.coap;
 
-import java.io.IOException;
 import java.net.InetSocketAddress;
 import java.security.GeneralSecurityException;
-import java.security.KeyStore;
 import java.security.PrivateKey;
-import java.security.cert.Certificate;
-import java.security.cert.X509Certificate;
-import java.util.ArrayList;
-import java.util.Enumeration;
 import java.util.HashMap;
-import java.util.List;
 import java.util.Locale;
 import java.util.Map;
 import java.util.concurrent.ConcurrentHashMap;
@@ -68,10 +61,10 @@ public class CoAPComponent extends UriEndpointComponent implements RestConsumerF
         super(context, CoAPEndpoint.class);
     }
 
-    public synchronized CoapServer getServer(int port, KeyStoreParameters keyStoreParameters) {
+    public synchronized CoapServer getServer(int port, CoAPEndpoint endpoint) {
         CoapServer server = servers.get(port);
         if (server == null && port == -1) {
-            server = getServer(DEFAULT_PORT, keyStoreParameters);
+            server = getServer(DEFAULT_PORT, endpoint);
         }
         if (server == null) {
             CoapEndpoint.Builder coapBuilder = new CoapEndpoint.Builder();
@@ -79,37 +72,37 @@ public class CoAPComponent extends UriEndpointComponent implements RestConsumerF
             InetSocketAddress address = new InetSocketAddress(port);
             coapBuilder.setNetworkConfig(config);
             
-            if (keyStoreParameters != null) {
+            if (endpoint.getKeystore() != null) {
                 DtlsConnectorConfig.Builder builder = new DtlsConnectorConfig.Builder();
                 builder.setAddress(address);
+                if (endpoint.getAlias() == null) {
+                    throw new IllegalStateException("An alias must be configured to use TLS");
+                }
+                if (endpoint.getPassword() == null) {
+                    throw new IllegalStateException("A password must be configured to use TLS");
+                }
+                if (endpoint.getTruststore() == null) {
+                    throw new IllegalStateException("A truststore must be configured to use TLS");
+                }
 
                 try {
-                    KeyStore keyStore = keyStoreParameters.createKeyStore();
-                    // TODO
-                    PrivateKey privateKey = (PrivateKey)keyStoreParameters.createKeyStore().getKey("ec", "security".toCharArray());
-                    builder.setIdentity(privateKey, keyStore.getCertificateChain("ec"));
+                    // Configure the identity
+                    PrivateKey privateKey = 
+                        (PrivateKey)endpoint.getKeystore().getKey(endpoint.getAlias(), endpoint.getPassword());
+                    builder.setIdentity(privateKey, endpoint.getKeystore().getCertificateChain(endpoint.getAlias()));
 
                     // Add all certificates from the truststore
-                    Enumeration<String> aliases = keyStore.aliases();
-                    List<Certificate> trustCerts = new ArrayList<>();
-                    while (aliases.hasMoreElements()) {
-                        String alias = aliases.nextElement();
-                        X509Certificate cert =
-                                (X509Certificate) keyStore.getCertificate(alias);
-                        if (cert != null) {
-                            trustCerts.add(cert);
-                        }
-                    }
-                    builder.setTrustStore(trustCerts.toArray(new Certificate[0]));
-
-                } catch (GeneralSecurityException | IOException e) {
-                    // TODO Auto-generated catch block
-                    e.printStackTrace();
+                    builder.setTrustStore(endpoint.getTrustedCerts());
+
+                } catch (GeneralSecurityException e) {
+                    throw new IllegalStateException("Error in configuring TLS", e);
                 }
 
                 builder.setClientAuthenticationRequired(false); //TODO
 
-                builder.setSupportedCipherSuites(new String[] {"TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256"}); //TODO
+                if (endpoint.getConfiguredCipherSuites() != null) {
+                    builder.setSupportedCipherSuites(endpoint.getConfiguredCipherSuites());
+                }
 
                 DTLSConnector connector = new DTLSConnector(builder.build());
                 coapBuilder.setConnector(connector);
diff --git a/components/camel-coap/src/main/java/org/apache/camel/coap/CoAPEndpoint.java b/components/camel-coap/src/main/java/org/apache/camel/coap/CoAPEndpoint.java
index 5e989b7..2a3c0ad 100644
--- a/components/camel-coap/src/main/java/org/apache/camel/coap/CoAPEndpoint.java
+++ b/components/camel-coap/src/main/java/org/apache/camel/coap/CoAPEndpoint.java
@@ -16,7 +16,17 @@
  */
 package org.apache.camel.coap;
 
+import java.io.IOException;
 import java.net.URI;
+import java.security.GeneralSecurityException;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.security.PrivateKey;
+import java.security.cert.Certificate;
+import java.security.cert.X509Certificate;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.List;
 
 import org.apache.camel.Consumer;
 import org.apache.camel.Processor;
@@ -40,6 +50,26 @@ public class CoAPEndpoint extends DefaultEndpoint {
     
     @UriParam
     private KeyStoreParameters keyStoreParameters;
+    
+    @UriParam
+    private KeyStore keystore;
+    
+    @UriParam
+    private KeyStoreParameters trustStoreParameters;
+    
+    @UriParam
+    private KeyStore truststore;
+    
+    @UriParam
+    private String alias;
+    
+    @UriParam(label = "security", javaType = "java.lang.String", secret = true)
+    private char[] password;
+    
+    @UriParam
+    private String cipherSuites;
+    
+    private String[] configuredCipherSuites;
         
     private CoAPComponent component;
     
@@ -88,17 +118,131 @@ public class CoAPEndpoint extends DefaultEndpoint {
     }
 
     public CoapServer getCoapServer() {
-        return component.getServer(getUri().getPort(), keyStoreParameters);
+        return component.getServer(getUri().getPort(), this);
     }
     
     /**
-     * The KeyStoreParameters object to use with TLS
+     * The KeyStoreParameters object to use with TLS to configure the keystore. Alternatively, a "keystore" 
+     * parameter can be directly configured instead. An alias and password should also be configured on the route definition.
      */
     public KeyStoreParameters getKeyStoreParameters() {
         return keyStoreParameters;
     }
 
-    public void setKeyStoreParameters(KeyStoreParameters keyStoreParameters) {
+    public void setKeyStoreParameters(KeyStoreParameters keyStoreParameters) throws GeneralSecurityException, IOException {
         this.keyStoreParameters = keyStoreParameters;
+        if (keyStoreParameters != null) {
+            this.keystore = keyStoreParameters.createKeyStore();
+        }
+    }
+    
+    /**
+     * The KeyStoreParameters object to use with TLS to configure the truststore. Alternatively, a "truststore" 
+     * object can be directly configured instead. All certificates in the truststore are used to establish trust.
+     */
+    public KeyStoreParameters getTrustStoreParameters() {
+        return trustStoreParameters;
+    }
+
+    public void setTrustStoreParameters(KeyStoreParameters trustStoreParameters) throws GeneralSecurityException, IOException {
+        this.trustStoreParameters = trustStoreParameters;
+        if (trustStoreParameters != null) {
+            this.truststore = trustStoreParameters.createKeyStore();
+        }
+    }
+    
+    /**
+     * Gets the TLS key store. Alternatively, a KeyStoreParameters object can be configured instead.
+     * An alias and password should also be configured on the route definition.
+     */
+    public KeyStore getKeystore() {
+        return keystore;
+    }
+
+    /**
+     * Sets the TLS key store. Alternatively, a KeyStoreParameters object can be configured instead.
+     * An alias and password should also be configured on the route definition.
+     */
+    public void setKeystore(KeyStore keystore) {
+        this.keystore = keystore;
+    }
+    
+    /**
+     * Gets the TLS trust store. Alternatively, a "trustStoreParameters" object can be configured instead.
+     * All certificates in the truststore are used to establish trust.
+     */
+    public KeyStore getTruststore() {
+        return truststore;
+    }
+
+    /**
+     * Sets the TLS trust store. Alternatively, a "trustStoreParameters" object can be configured instead.
+     * All certificates in the truststore are used to establish trust.
+     */
+    public void setTruststore(KeyStore truststore) {
+        this.truststore = truststore;
+    }
+    
+    /**
+     * Gets the alias used to query the KeyStore for the private key and certificate.
+     */
+    public String getAlias() {
+        return alias;
+    }
+
+    /**
+     * Sets the alias used to query the KeyStore for the private key and certificate.
+     */
+    public void setAlias(String alias) {
+        this.alias = alias;
+    }
+    
+    /**
+     * Gets the password used to access an aliased {@link PrivateKey} in the KeyStore.
+     */
+    public char[] getPassword() {
+        return password;
+    }
+
+    /**
+     * Sets the password used to access an aliased {@link PrivateKey} in the KeyStore.
+     */
+    public void setPassword(char[] password) {
+        this.password = password;
+    }
+    
+    /**
+     * Gets the cipherSuites String. This is a comma separated String of ciphersuites to configure.
+     */
+    public String getCipherSuites() {
+        return cipherSuites;
+    }
+
+    /**
+     * Sets the cipherSuites String. This is a comma separated String of ciphersuites to configure.
+     */
+    public void setCipherSuites(String cipherSuites) {
+        this.cipherSuites = cipherSuites;
+        if (cipherSuites != null) {
+            configuredCipherSuites = cipherSuites.split(",");
+        }
+    }
+    
+    public String[] getConfiguredCipherSuites() {
+        return configuredCipherSuites;
+    }
+    
+    public Certificate[] getTrustedCerts() throws KeyStoreException {
+        Enumeration<String> aliases = truststore.aliases();
+        List<Certificate> trustCerts = new ArrayList<>();
+        while (aliases.hasMoreElements()) {
+            String alias = aliases.nextElement();
+            X509Certificate cert = (X509Certificate) truststore.getCertificate(alias);
+            if (cert != null) {
+                trustCerts.add(cert);
+            }
+        }
+        
+        return trustCerts.toArray(new Certificate[0]);
     }
 }
diff --git a/components/camel-coap/src/main/java/org/apache/camel/coap/CoAPProducer.java b/components/camel-coap/src/main/java/org/apache/camel/coap/CoAPProducer.java
index c4bc8c9..588e429 100644
--- a/components/camel-coap/src/main/java/org/apache/camel/coap/CoAPProducer.java
+++ b/components/camel-coap/src/main/java/org/apache/camel/coap/CoAPProducer.java
@@ -16,15 +16,9 @@
  */
 package org.apache.camel.coap;
 
-import java.io.IOException;
 import java.net.URI;
 import java.security.GeneralSecurityException;
-import java.security.KeyStore;
-import java.security.cert.Certificate;
-import java.security.cert.X509Certificate;
-import java.util.ArrayList;
-import java.util.Enumeration;
-import java.util.List;
+import java.security.PrivateKey;
 
 import org.apache.camel.Exchange;
 import org.apache.camel.Message;
@@ -103,32 +97,33 @@ public class CoAPProducer extends DefaultProducer {
             }
             client = new CoapClient(uri);
             
-            if (endpoint.getKeyStoreParameters() != null) {
+            if (endpoint.getTruststore() != null) {
                 DtlsConnectorConfig.Builder builder = new DtlsConnectorConfig.Builder();
                 builder.setClientOnly();
 
                 try {
-                    // TODO Add client key config if specified
-                    
-                    KeyStore keyStore = endpoint.getKeyStoreParameters().createKeyStore();
-                    // Add all certificates from the truststore
-                    Enumeration<String> aliases = keyStore.aliases();
-                    List<Certificate> trustCerts = new ArrayList<>();
-                    while (aliases.hasMoreElements()) {
-                        String alias = aliases.nextElement();
-                        X509Certificate cert =
-                                (X509Certificate) keyStore.getCertificate(alias);
-                        if (cert != null) {
-                            trustCerts.add(cert);
+                    // Configure the identity if the keystore parameter is specified
+                    if (endpoint.getKeystore() != null) {
+                        if (endpoint.getAlias() == null) {
+                            throw new IllegalStateException("An alias must be configured to use TLS");
+                        }
+                        if (endpoint.getPassword() == null) {
+                            throw new IllegalStateException("A password must be configured to use TLS");
                         }
+                        PrivateKey privateKey = 
+                            (PrivateKey)endpoint.getKeystore().getKey(endpoint.getAlias(), endpoint.getPassword());
+                        builder.setIdentity(privateKey, endpoint.getKeystore().getCertificateChain(endpoint.getAlias()));
                     }
-                    builder.setTrustStore(trustCerts.toArray(new Certificate[0]));
-                } catch (GeneralSecurityException | IOException e) {
-                    // TODO Auto-generated catch block
-                    e.printStackTrace();
+
+                    // Add all certificates from the truststore
+                    builder.setTrustStore(endpoint.getTrustedCerts());
+                } catch (GeneralSecurityException e) {
+                    throw new IllegalStateException("Error in configuring TLS", e);
                 }
 
-                builder.setSupportedCipherSuites(new String[] {"TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256"}); //TODO
+                if (endpoint.getConfiguredCipherSuites() != null) {
+                    builder.setSupportedCipherSuites(endpoint.getConfiguredCipherSuites());
+                }
 
                 DTLSConnector connector = new DTLSConnector(builder.build());
                 CoapEndpoint.Builder coapBuilder = new CoapEndpoint.Builder();