From 733ca394f640f62712173aa430dc752938bf5b5b Mon Sep 17 00:00:00 2001 From: Colm O hEigeartaigh Date: Thu, 2 May 2019 12:53:32 +0100 Subject: [PATCH] Refactoring Coap component to use sslContextParameters for TLS certificates --- .../src/main/docs/coap-component.adoc | 13 +- .../org/apache/camel/coap/CoAPComponent.java | 3 +- .../org/apache/camel/coap/CoAPEndpoint.java | 234 ++++++++---------- .../org/apache/camel/coap/CoAPProducer.java | 3 +- .../camel/coap/CoAPComponentTLSTest.java | 181 ++++++++++---- .../camel/coap/CoAPRestComponentTLSTest.java | 26 +- 6 files changed, 258 insertions(+), 202 deletions(-) diff --git a/components/camel-coap/src/main/docs/coap-component.adoc b/components/camel-coap/src/main/docs/coap-component.adoc index 5bcdb86d9edf6..d365cf32594b4 100644 --- a/components/camel-coap/src/main/docs/coap-component.adoc +++ b/components/camel-coap/src/main/docs/coap-component.adoc @@ -50,28 +50,25 @@ with the following path and query parameters: |=== -==== Query Parameters (16 parameters): +==== Query Parameters (13 parameters): [width="100%",cols="2,5,^1,2",options="header"] |=== | Name | Description | Default | Type -| *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 +| *alias* (common) | Sets the alias used to query the KeyStore for the private key and certificate. This parameter is used when we are enabling TLS with certificates on the service side, and similarly on the client side when TLS is used with certificates and client authentication. If the parameter is not specified then the default behavior is to use the first alias in the keystore that contains a key entry. This configuration parameter does not apply to configuring TLS via a Raw Public Key or a Pre-Shared Key. | | String +| *cipherSuites* (common) | Sets the cipherSuites String. This is a comma separated String of ciphersuites to configure. If it is not specified, then it falls back to getting the ciphersuites from the sslContextParameters object. | | String +| *clientAuthentication* (common) | Sets the configuration options for server-side client-authentication requirements. The value must be one of NONE, WANT, REQUIRE. If this value is not specified, then it falls back to checking the sslContextParameters.getServerParameters().getClientAuthentication() value. | | String | *privateKey* (common) | Set the configured private key for use with Raw Public Key. | | PrivateKey | *pskStore* (common) | Set the PskStore to use for pre-shared key. | | PskStore | *publicKey* (common) | Set the configured public key for use with Raw Public Key. | | PublicKey +| *sslContextParameters* (common) | Set the SSLContextParameters object for setting up TLS. This is required for coapstcp, and for coaps when we are using certificates for TLS (as opposed to RPK or PKS). | | SSLContextParameters | *trustedRpkStore* (common) | Set the TrustedRpkStore to use to determine trust in raw public keys. | | TrustedRpkStore -| *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 c36317f113db8..2f0b2dc579c1e 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,6 +16,7 @@ */ package org.apache.camel.coap; +import java.io.IOException; import java.net.InetSocketAddress; import java.util.HashMap; import java.util.Locale; @@ -55,7 +56,7 @@ public class CoAPComponent extends DefaultComponent implements RestConsumerFacto public CoAPComponent() { } - public synchronized CoapServer getServer(int port, CoAPEndpoint endpoint) { + public synchronized CoapServer getServer(int port, CoAPEndpoint endpoint) throws IOException { CoapServer server = servers.get(port); if (server == null && port == -1) { server = getServer(DEFAULT_PORT, endpoint); 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 36954cac725ea..04d67ae18d395 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 @@ -21,7 +21,6 @@ import java.net.URI; import java.security.GeneralSecurityException; import java.security.KeyStore; -import java.security.KeyStoreException; import java.security.PrivateKey; import java.security.PublicKey; import java.security.cert.Certificate; @@ -38,7 +37,8 @@ import org.apache.camel.spi.UriPath; import org.apache.camel.support.DefaultEndpoint; import org.apache.camel.support.jsse.ClientAuthentication; -import org.apache.camel.support.jsse.KeyStoreParameters; +import org.apache.camel.support.jsse.KeyManagersParameters; +import org.apache.camel.support.jsse.SSLContextParameters; import org.eclipse.californium.core.CoapServer; import org.eclipse.californium.scandium.DTLSConnector; import org.eclipse.californium.scandium.config.DtlsConnectorConfig; @@ -56,18 +56,6 @@ public class CoAPEndpoint extends DefaultEndpoint { @UriParam(label = "consumer") private String coapMethodRestrict; - @UriParam - private KeyStoreParameters keyStoreParameters; - - @UriParam - private KeyStore keystore; - - @UriParam - private KeyStoreParameters trustStoreParameters; - - @UriParam - private KeyStore truststore; - @UriParam private PrivateKey privateKey; @@ -80,21 +68,22 @@ public class CoAPEndpoint extends DefaultEndpoint { @UriParam private PskStore pskStore; - @UriParam - private String alias; - - @UriParam(label = "security", javaType = "java.lang.String", secret = true) - private char[] password; - @UriParam private String cipherSuites; private String[] configuredCipherSuites; + @UriParam private String clientAuthentication; + @UriParam + private String alias; + + @UriParam + private SSLContextParameters sslContextParameters; + private CoAPComponent component; - + public CoAPEndpoint(String uri, CoAPComponent component) { super(uri, component); try { @@ -116,10 +105,12 @@ public String getCoapMethodRestrict() { return this.coapMethodRestrict; } + @Override public Producer createProducer() throws Exception { return new CoAPProducer(this); } + @Override public Consumer createConsumer(Processor processor) throws Exception { return new CoAPConsumer(this, processor); } @@ -127,7 +118,7 @@ public Consumer createConsumer(Processor processor) throws Exception { public void setUri(URI u) { uri = u; } - + /** * The URI for the CoAP endpoint */ @@ -135,84 +126,46 @@ public URI getUri() { return uri; } - public CoapServer getCoapServer() { + public CoapServer getCoapServer() throws IOException { return component.getServer(getUri().getPort(), this); } /** - * 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) 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. + * Gets the alias used to query the KeyStore for the private key and certificate. This parameter is used + * when we are enabling TLS with certificates on the service side, and similarly on the client side when + * TLS is used with certificates and client authentication. If the parameter is not specified then the + * default behavior is to use the first alias in the keystore that contains a key entry. This configuration + * parameter does not apply to configuring TLS via a Raw Public Key or a Pre-Shared Key. */ - 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; + public String getAlias() { + return alias; } /** - * Sets the TLS trust store. Alternatively, a "trustStoreParameters" object can be configured instead. - * All certificates in the truststore are used to establish trust. + * Sets the alias used to query the KeyStore for the private key and certificate. This parameter is used + * when we are enabling TLS with certificates on the service side, and similarly on the client side when + * TLS is used with certificates and client authentication. If the parameter is not specified then the + * default behavior is to use the first alias in the keystore that contains a key entry. This configuration + * parameter does not apply to configuring TLS via a Raw Public Key or a Pre-Shared Key. */ - public void setTruststore(KeyStore truststore) { - this.truststore = truststore; + public void setAlias(String alias) { + this.alias = alias; } /** - * Gets the alias used to query the KeyStore for the private key and certificate. + * Get the SSLContextParameters object for setting up TLS. This is required for coaps+tcp, and for coaps when we are + * using certificates for TLS (as opposed to RPK or PKS). */ - public String getAlias() { - return alias; + public SSLContextParameters getSslContextParameters() { + return sslContextParameters; } /** - * Sets the alias used to query the KeyStore for the private key and certificate. + * Set the SSLContextParameters object for setting up TLS. This is required for coaps+tcp, and for coaps when we are + * using certificates for TLS (as opposed to RPK or PKS). */ - public void setAlias(String alias) { - this.alias = alias; + public void setSslContextParameters(SSLContextParameters sslContextParameters) { + this.sslContextParameters = sslContextParameters; } /** @@ -272,28 +225,16 @@ public void setPublicKey(PublicKey publicKey) { } /** - * 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. + * Gets the cipherSuites String. This is a comma separated String of ciphersuites to configure. If it is not + * specified, then it falls back to getting the ciphersuites from the sslContextParameters object. */ public String getCipherSuites() { return cipherSuites; } /** - * Sets the cipherSuites String. This is a comma separated String of ciphersuites to configure. + * Sets the cipherSuites String. This is a comma separated String of ciphersuites to configure. If it is not + * specified, then it falls back to getting the ciphersuites from the sslContextParameters object. */ public void setCipherSuites(String cipherSuites) { this.cipherSuites = cipherSuites; @@ -303,12 +244,18 @@ public void setCipherSuites(String cipherSuites) { } private String[] getConfiguredCipherSuites() { - return configuredCipherSuites; + if (configuredCipherSuites != null) { + return configuredCipherSuites; + } else if (sslContextParameters != null && sslContextParameters.getCipherSuites() != null) { + return sslContextParameters.getCipherSuites().getCipherSuite().toArray(new String[0]); + } + return null; } /** * Gets the configuration options for server-side client-authentication requirements. The value is - * either null or one of NONE, WANT, REQUIRE. + * either null or one of NONE, WANT, REQUIRE. If this value is not specified, then it falls back + * to checking the sslContextParameters.getServerParameters().getClientAuthentication() value. */ public String getClientAuthentication() { return clientAuthentication; @@ -316,42 +263,54 @@ public String getClientAuthentication() { /** * Sets the configuration options for server-side client-authentication requirements. - * The value must be one of NONE, WANT, REQUIRE. - * - * @param value the desired configuration options or {@code null} to use the defaults + * The value must be one of NONE, WANT, REQUIRE. If this value is not specified, then it falls back + * to checking the sslContextParameters.getServerParameters().getClientAuthentication() value. */ public void setClientAuthentication(String clientAuthentication) { this.clientAuthentication = clientAuthentication; } private boolean isClientAuthenticationRequired() { - return clientAuthentication != null - && ClientAuthentication.valueOf(clientAuthentication) == ClientAuthentication.REQUIRE; + String clientAuth = clientAuthentication; + if (clientAuth == null && sslContextParameters != null && sslContextParameters.getServerParameters() != null) { + clientAuth = sslContextParameters.getServerParameters().getClientAuthentication(); + } + + return clientAuth != null && ClientAuthentication.valueOf(clientAuth) == ClientAuthentication.REQUIRE; } private boolean isClientAuthenticationWanted() { - return clientAuthentication != null - && ClientAuthentication.valueOf(clientAuthentication) == ClientAuthentication.WANT; + String clientAuth = clientAuthentication; + if (clientAuth == null && sslContextParameters != null && sslContextParameters.getServerParameters() != null) { + clientAuth = sslContextParameters.getServerParameters().getClientAuthentication(); + } + + return clientAuth != null && ClientAuthentication.valueOf(clientAuth) == ClientAuthentication.WANT; } - private Certificate[] getTrustedCerts() throws KeyStoreException { - if (truststore != null) { - Enumeration aliases = truststore.aliases(); + /** + * Get all the certificates contained in the sslContextParameters truststore + */ + private Certificate[] getTrustedCerts() throws GeneralSecurityException, IOException { + if (sslContextParameters != null && sslContextParameters.getTrustManagers() != null) { + KeyStore trustStore = sslContextParameters.getTrustManagers().getKeyStore().createKeyStore(); + Enumeration aliases = trustStore.aliases(); List trustCerts = new ArrayList<>(); while (aliases.hasMoreElements()) { String alias = aliases.nextElement(); - X509Certificate cert = (X509Certificate) truststore.getCertificate(alias); + X509Certificate cert = (X509Certificate) trustStore.getCertificate(alias); if (cert != null) { trustCerts.add(cert); } } - + return trustCerts.toArray(new Certificate[0]); } - + return new Certificate[0]; } + public static boolean enableTLS(URI uri) { return "coaps".equals(uri.getScheme()); } @@ -360,30 +319,26 @@ public static boolean enableTCP(URI uri) { return uri.getScheme().endsWith("+tcp"); } - public DTLSConnector createDTLSConnector(InetSocketAddress address, boolean client) { + public DTLSConnector createDTLSConnector(InetSocketAddress address, boolean client) throws IOException { DtlsConnectorConfig.Builder builder = new DtlsConnectorConfig.Builder(); if (client) { - if (trustedRpkStore == null && getTruststore() == null && pskStore == null) { - throw new IllegalStateException("A truststore must be configured to use TLS"); + if (trustedRpkStore == null && sslContextParameters == null && pskStore == null) { + throw new IllegalStateException("Either a trustedRpkStore, sslContextParameters or pskStore object " + + "must be configured for a TLS client"); } builder.setClientOnly(); } else { - if (privateKey == null && getKeystore() == null && pskStore == null) { - throw new IllegalStateException("A keystore or private key must be configured to use TLS"); + if (privateKey == null && sslContextParameters == null && pskStore == null) { + throw new IllegalStateException("Either a privateKey, sslContextParameters or pskStore object " + + "must be configured for a TLS service"); } if (privateKey != null && publicKey == null) { throw new IllegalStateException("A public key must be configured to use a Raw Public Key with TLS"); } - if (privateKey == null && pskStore == null && getAlias() == null) { - throw new IllegalStateException("An alias must be configured to use TLS"); - } - if (privateKey == null && pskStore == null && getPassword() == null) { - throw new IllegalStateException("A password must be configured to use TLS"); - } if ((isClientAuthenticationRequired() || isClientAuthenticationWanted()) - && (getTruststore() == null && publicKey == null)) { + && (sslContextParameters == null || sslContextParameters.getTrustManagers() == null) && publicKey == null) { throw new IllegalStateException("A truststore must be configured to support TLS client authentication"); } @@ -393,11 +348,30 @@ public DTLSConnector createDTLSConnector(InetSocketAddress address, boolean clie } try { - // Configure the identity if the keystore or privateKey parameter is specified - if (getKeystore() != null) { + // Configure the identity if the sslContextParameters or privateKey parameter is specified + if (sslContextParameters != null && sslContextParameters.getKeyManagers() != null) { + KeyManagersParameters keyManagers = sslContextParameters.getKeyManagers(); + KeyStore keyStore = keyManagers.getKeyStore().createKeyStore(); + + // Use the configured alias or fall back to the first alias in the keystore that contains a key + String alias = getAlias(); + if (alias == null) { + Enumeration aliases = keyStore.aliases(); + while (aliases.hasMoreElements()) { + String ksAlias = aliases.nextElement(); + if (keyStore.isKeyEntry(ksAlias)) { + alias = ksAlias; + break; + } + } + } + if (alias == null) { + throw new IllegalStateException("The sslContextParameters keystore must contain a key entry"); + } + PrivateKey privateKey = - (PrivateKey)getKeystore().getKey(getAlias(), getPassword()); - builder.setIdentity(privateKey, getKeystore().getCertificateChain(getAlias())); + (PrivateKey)keyStore.getKey(alias, keyManagers.getKeyPassword().toCharArray()); + builder.setIdentity(privateKey, keyStore.getCertificateChain(alias)); } else if (privateKey != null) { builder.setIdentity(privateKey, publicKey); } 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 a76485791a474..8e001e124ce0f 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,6 +16,7 @@ */ package org.apache.camel.coap; +import java.io.IOException; import java.net.URI; import org.apache.camel.Exchange; @@ -88,7 +89,7 @@ public void process(Exchange exchange) throws Exception { } } - private synchronized CoapClient getClient(Exchange exchange) { + private synchronized CoapClient getClient(Exchange exchange) throws IOException { if (client == null) { URI uri = exchange.getIn().getHeader(CoAPConstants.COAP_URI, URI.class); if (uri == null) { diff --git a/components/camel-coap/src/test/java/org/apache/camel/coap/CoAPComponentTLSTest.java b/components/camel-coap/src/test/java/org/apache/camel/coap/CoAPComponentTLSTest.java index da989838d4ae3..058ac6667c5bd 100644 --- a/components/camel-coap/src/test/java/org/apache/camel/coap/CoAPComponentTLSTest.java +++ b/components/camel-coap/src/test/java/org/apache/camel/coap/CoAPComponentTLSTest.java @@ -16,6 +16,8 @@ */ package org.apache.camel.coap; +import java.io.IOException; +import java.security.GeneralSecurityException; import java.security.KeyStore; import java.security.PrivateKey; import java.security.PublicKey; @@ -27,7 +29,11 @@ import org.apache.camel.Processor; import org.apache.camel.builder.RouteBuilder; import org.apache.camel.component.mock.MockEndpoint; +import org.apache.camel.support.jsse.KeyManagersParameters; import org.apache.camel.support.jsse.KeyStoreParameters; +import org.apache.camel.support.jsse.SSLContextParameters; +import org.apache.camel.support.jsse.SSLContextServerParameters; +import org.apache.camel.support.jsse.TrustManagersParameters; import org.apache.camel.test.AvailablePortFinder; import org.apache.camel.test.junit4.CamelTestSupport; import org.eclipse.californium.core.coap.CoAP; @@ -189,65 +195,23 @@ public void testPreSharedKeyX509() throws Exception { @Override protected RouteBuilder createRouteBuilder() throws Exception { - KeyStoreParameters keystoreParameters = new KeyStoreParameters(); - keystoreParameters.setResource("service.jks"); - keystoreParameters.setPassword("security"); - KeyStore keyStore = keystoreParameters.createKeyStore(); - PrivateKey privateKey = (PrivateKey)keyStore.getKey("service", "security".toCharArray()); - PublicKey publicKey = keyStore.getCertificate("service").getPublicKey(); - - KeyStoreParameters keystoreParameters2 = new KeyStoreParameters(); - keystoreParameters2.setResource("selfsigned.jks"); - keystoreParameters2.setPassword("security"); - - KeyStoreParameters keystoreParameters3 = new KeyStoreParameters(); - keystoreParameters3.setResource("client.jks"); - keystoreParameters3.setPassword("security"); - - KeyStoreParameters truststoreParameters = new KeyStoreParameters(); - truststoreParameters.setResource("truststore.jks"); - truststoreParameters.setPassword("storepass"); - - KeyStoreParameters truststoreParameters2 = new KeyStoreParameters(); - truststoreParameters2.setResource("truststore2.jks"); - truststoreParameters2.setPassword("storepass"); - - TrustedRpkStore trustedRpkStore = id -> { - return true; - }; - TrustedRpkStore failedTrustedRpkStore = id -> { - return false; - }; - KeyGenerator keyGenerator = KeyGenerator.getInstance("AES"); - PskStore pskStore = new StaticPskStore("some-identity", keyGenerator.generateKey().getEncoded()); - - context.getRegistry().bind("keyParams", keystoreParameters); - context.getRegistry().bind("keyParams2", keystoreParameters2); - context.getRegistry().bind("keyParams3", keystoreParameters3); - context.getRegistry().bind("trustParams", truststoreParameters); - context.getRegistry().bind("trustParams2", truststoreParameters2); - context.getRegistry().bind("privateKey", privateKey); - context.getRegistry().bind("publicKey", publicKey); - context.getRegistry().bind("trustedRpkStore", trustedRpkStore); - context.getRegistry().bind("failedTrustedRpkStore", failedTrustedRpkStore); - context.getRegistry().bind("pskStore", pskStore); + registerTLSConfiguration(); return new RouteBuilder() { @Override public void configure() throws Exception { - fromF("coaps://localhost:%d/TestResource?alias=service&password=security&keyStoreParameters=#keyParams", PORT) + fromF("coaps://localhost:%d/TestResource?sslContextParameters=#serviceSSLContextParameters", PORT) .transform(body().prepend("Hello ")); - fromF("coaps://localhost:%d/TestResource?alias=selfsigned&password=security&keyStoreParameters=#keyParams2", PORT2) + fromF("coaps://localhost:%d/TestResource?alias=selfsigned&sslContextParameters=#selfSignedServiceSSLContextParameters", PORT2) .transform(body().prepend("Hello ")); - fromF("coaps://localhost:%d/TestResource?alias=service&password=security&trustStoreParameters=#trustParams&" - + "keyStoreParameters=#keyParams&clientAuthentication=REQUIRE", PORT3) + fromF("coaps://localhost:%d/TestResource?sslContextParameters=#clientAuthServiceSSLContextParameters", PORT3) .transform(body().prepend("Hello ")); - fromF("coaps://localhost:%d/TestResource?alias=service&password=security&keyStoreParameters=#keyParams&cipherSuites=TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8", PORT4) + fromF("coaps://localhost:%d/TestResource?sslContextParameters=#serviceSSLContextParameters&cipherSuites=TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8", PORT4) .transform(body().prepend("Hello ")); fromF("coaps://localhost:%d/TestResource?privateKey=#privateKey&publicKey=#publicKey", PORT5) @@ -259,11 +223,11 @@ public void configure() throws Exception { fromF("coaps://localhost:%d/TestResource?pskStore=#pskStore", PORT7) .transform(body().prepend("Hello ")); - fromF("coaps://localhost:%d/TestResource?alias=service&password=security&keyStoreParameters=#keyParams&pskStore=#pskStore", PORT8) + fromF("coaps://localhost:%d/TestResource?sslContextParameters=#serviceSSLContextParameters&pskStore=#pskStore", PORT8) .transform(body().prepend("Hello ")); from("direct:start") - .toF("coaps://localhost:%d/TestResource?trustStoreParameters=#trustParams", PORT) + .toF("coaps://localhost:%d/TestResource?sslContextParameters=#clientSSLContextParameters", PORT) .to("mock:result"); from("direct:notruststore") @@ -271,23 +235,23 @@ public void configure() throws Exception { .to("mock:result"); from("direct:failedtrust") - .toF("coaps://localhost:%d/TestResource?trustStoreParameters=#trustParams2", PORT) + .toF("coaps://localhost:%d/TestResource?sslContextParameters=#clientSSLContextParameters2", PORT) .to("mock:result"); from("direct:selfsigned") - .toF("coaps://localhost:%d/TestResource?trustStoreParameters=#keyParams2", PORT2) + .toF("coaps://localhost:%d/TestResource?sslContextParameters=#selfSignedClientSSLContextParameters", PORT2) .to("mock:result"); from("direct:clientauth") - .toF("coaps://localhost:%d/TestResource?trustStoreParameters=#trustParams&keyStoreParameters=#keyParams3&alias=client&password=security", PORT3) + .toF("coaps://localhost:%d/TestResource?sslContextParameters=#clientAuthClientSSLContextParameters", PORT3) .to("mock:result"); from("direct:failedclientauth") - .toF("coaps://localhost:%d/TestResource?trustStoreParameters=#trustParams&keyStoreParameters=#keyParams2&alias=selfsigned&password=security", PORT3) + .toF("coaps://localhost:%d/TestResource?sslContextParameters=#clientAuthClientSSLContextParameters2", PORT3) .to("mock:result"); from("direct:ciphersuites") - .toF("coaps://localhost:%d/TestResource?trustStoreParameters=#trustParams&cipherSuites=TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8", PORT4) + .toF("coaps://localhost:%d/TestResource?sslContextParameters=#clientSSLContextParameters&cipherSuites=TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8", PORT4) .to("mock:result"); from("direct:rpk") @@ -315,12 +279,119 @@ public void configure() throws Exception { .to("mock:result"); from("direct:pskx509") - .toF("coaps://localhost:%d/TestResource?pskStore=#pskStore&trustStoreParameters=#trustParams", PORT8) + .toF("coaps://localhost:%d/TestResource?pskStore=#pskStore&sslContextParameters=#clientSSLContextParameters", PORT8) .to("mock:result"); } }; } + private void registerTLSConfiguration() throws GeneralSecurityException, IOException { + KeyStoreParameters serviceKeystoreParameters = new KeyStoreParameters(); + serviceKeystoreParameters.setResource("service.jks"); + serviceKeystoreParameters.setPassword("security"); + + KeyStoreParameters selfSignedKeyStoreParameters = new KeyStoreParameters(); + selfSignedKeyStoreParameters.setResource("selfsigned.jks"); + selfSignedKeyStoreParameters.setPassword("security"); + + KeyStoreParameters clientKeystoreParameters = new KeyStoreParameters(); + clientKeystoreParameters.setResource("client.jks"); + clientKeystoreParameters.setPassword("security"); + + KeyStoreParameters truststoreParameters = new KeyStoreParameters(); + truststoreParameters.setResource("truststore.jks"); + truststoreParameters.setPassword("storepass"); + + KeyStoreParameters truststoreParameters2 = new KeyStoreParameters(); + truststoreParameters2.setResource("truststore2.jks"); + truststoreParameters2.setPassword("storepass"); + + SSLContextParameters serviceSSLContextParameters = new SSLContextParameters(); + KeyManagersParameters serviceSSLKeyManagers = new KeyManagersParameters(); + serviceSSLKeyManagers.setKeyPassword("security"); + serviceSSLKeyManagers.setKeyStore(serviceKeystoreParameters); + serviceSSLContextParameters.setKeyManagers(serviceSSLKeyManagers); + + SSLContextParameters selfSignedServiceSSLContextParameters = new SSLContextParameters(); + KeyManagersParameters selfSignedServiceSSLKeyManagers = new KeyManagersParameters(); + selfSignedServiceSSLKeyManagers.setKeyPassword("security"); + selfSignedServiceSSLKeyManagers.setKeyStore(selfSignedKeyStoreParameters); + selfSignedServiceSSLContextParameters.setKeyManagers(selfSignedServiceSSLKeyManagers); + + SSLContextParameters clientAuthServiceSSLContextParameters = new SSLContextParameters(); + KeyManagersParameters clientAuthServiceSSLKeyManagers = new KeyManagersParameters(); + clientAuthServiceSSLKeyManagers.setKeyPassword("security"); + clientAuthServiceSSLKeyManagers.setKeyStore(serviceKeystoreParameters); + clientAuthServiceSSLContextParameters.setKeyManagers(clientAuthServiceSSLKeyManagers); + TrustManagersParameters clientAuthServiceSSLTrustManagers = new TrustManagersParameters(); + clientAuthServiceSSLTrustManagers.setKeyStore(truststoreParameters); + clientAuthServiceSSLContextParameters.setTrustManagers(clientAuthServiceSSLTrustManagers); + SSLContextServerParameters clientAuthSSLContextServerParameters = new SSLContextServerParameters(); + clientAuthSSLContextServerParameters.setClientAuthentication("REQUIRE"); + clientAuthServiceSSLContextParameters.setServerParameters(clientAuthSSLContextServerParameters); + + SSLContextParameters clientSSLContextParameters = new SSLContextParameters(); + TrustManagersParameters clientSSLTrustManagers = new TrustManagersParameters(); + clientSSLTrustManagers.setKeyStore(truststoreParameters); + clientSSLContextParameters.setTrustManagers(clientSSLTrustManagers); + + SSLContextParameters clientSSLContextParameters2 = new SSLContextParameters(); + TrustManagersParameters clientSSLTrustManagers2 = new TrustManagersParameters(); + clientSSLTrustManagers2.setKeyStore(truststoreParameters2); + clientSSLContextParameters2.setTrustManagers(clientSSLTrustManagers2); + + SSLContextParameters clientAuthClientSSLContextParameters = new SSLContextParameters(); + TrustManagersParameters clientAuthClientSSLTrustManagers = new TrustManagersParameters(); + clientAuthClientSSLTrustManagers.setKeyStore(truststoreParameters); + clientAuthClientSSLContextParameters.setTrustManagers(clientAuthClientSSLTrustManagers); + KeyManagersParameters clientAuthClientSSLKeyManagers = new KeyManagersParameters(); + clientAuthClientSSLKeyManagers.setKeyPassword("security"); + clientAuthClientSSLKeyManagers.setKeyStore(clientKeystoreParameters); + clientAuthClientSSLContextParameters.setKeyManagers(clientAuthClientSSLKeyManagers); + + SSLContextParameters clientAuthClientSSLContextParameters2 = new SSLContextParameters(); + TrustManagersParameters clientAuthClientSSLTrustManagers2 = new TrustManagersParameters(); + clientAuthClientSSLTrustManagers2.setKeyStore(truststoreParameters2); + clientAuthClientSSLContextParameters2.setTrustManagers(clientAuthClientSSLTrustManagers2); + KeyManagersParameters clientAuthClientSSLKeyManagers2 = new KeyManagersParameters(); + clientAuthClientSSLKeyManagers2.setKeyPassword("security"); + clientAuthClientSSLKeyManagers2.setKeyStore(clientKeystoreParameters); + clientAuthClientSSLContextParameters2.setKeyManagers(clientAuthClientSSLKeyManagers2); + + SSLContextParameters selfSignedClientSSLContextParameters = new SSLContextParameters(); + TrustManagersParameters selfSignedClientSSLTrustManagers = new TrustManagersParameters(); + selfSignedClientSSLTrustManagers.setKeyStore(selfSignedKeyStoreParameters); + selfSignedClientSSLContextParameters.setTrustManagers(selfSignedClientSSLTrustManagers); + + KeyStore keyStore = serviceKeystoreParameters.createKeyStore(); + PrivateKey privateKey = (PrivateKey)keyStore.getKey("service", "security".toCharArray()); + PublicKey publicKey = keyStore.getCertificate("service").getPublicKey(); + + TrustedRpkStore trustedRpkStore = id -> { + return true; + }; + TrustedRpkStore failedTrustedRpkStore = id -> { + return false; + }; + KeyGenerator keyGenerator = KeyGenerator.getInstance("AES"); + PskStore pskStore = new StaticPskStore("some-identity", keyGenerator.generateKey().getEncoded()); + + context.getRegistry().bind("serviceSSLContextParameters", serviceSSLContextParameters); + context.getRegistry().bind("selfSignedServiceSSLContextParameters", selfSignedServiceSSLContextParameters); + context.getRegistry().bind("clientAuthServiceSSLContextParameters", clientAuthServiceSSLContextParameters); + context.getRegistry().bind("clientSSLContextParameters", clientSSLContextParameters); + context.getRegistry().bind("clientSSLContextParameters2", clientSSLContextParameters2); + context.getRegistry().bind("clientAuthClientSSLContextParameters", clientAuthClientSSLContextParameters); + context.getRegistry().bind("clientAuthClientSSLContextParameters2", clientAuthClientSSLContextParameters2); + context.getRegistry().bind("selfSignedClientSSLContextParameters", selfSignedClientSSLContextParameters); + + context.getRegistry().bind("privateKey", privateKey); + context.getRegistry().bind("publicKey", publicKey); + context.getRegistry().bind("trustedRpkStore", trustedRpkStore); + context.getRegistry().bind("failedTrustedRpkStore", failedTrustedRpkStore); + context.getRegistry().bind("pskStore", pskStore); + } + protected void sendBodyAndHeader(String endpointUri, final Object body, String headerName, String headerValue) { template.send(endpointUri, new Processor() { public void process(Exchange exchange) { diff --git a/components/camel-coap/src/test/java/org/apache/camel/coap/CoAPRestComponentTLSTest.java b/components/camel-coap/src/test/java/org/apache/camel/coap/CoAPRestComponentTLSTest.java index 3a01947fb046c..26a4b29abdca1 100644 --- a/components/camel-coap/src/test/java/org/apache/camel/coap/CoAPRestComponentTLSTest.java +++ b/components/camel-coap/src/test/java/org/apache/camel/coap/CoAPRestComponentTLSTest.java @@ -22,7 +22,10 @@ import org.apache.camel.ProducerTemplate; import org.apache.camel.builder.RouteBuilder; import org.apache.camel.component.mock.MockEndpoint; +import org.apache.camel.support.jsse.KeyManagersParameters; import org.apache.camel.support.jsse.KeyStoreParameters; +import org.apache.camel.support.jsse.SSLContextParameters; +import org.apache.camel.support.jsse.TrustManagersParameters; import org.apache.camel.test.AvailablePortFinder; import org.apache.camel.test.junit4.CamelTestSupport; import org.eclipse.californium.core.coap.CoAP; @@ -56,25 +59,34 @@ public void testGET() throws Exception { @Override protected RouteBuilder createRouteBuilder() throws Exception { - + KeyStoreParameters keystoreParameters = new KeyStoreParameters(); keystoreParameters.setResource("service.jks"); keystoreParameters.setPassword("security"); + SSLContextParameters serviceSSLContextParameters = new SSLContextParameters(); + KeyManagersParameters serviceSSLKeyManagers = new KeyManagersParameters(); + serviceSSLKeyManagers.setKeyPassword("security"); + serviceSSLKeyManagers.setKeyStore(keystoreParameters); + serviceSSLContextParameters.setKeyManagers(serviceSSLKeyManagers); + KeyStoreParameters truststoreParameters = new KeyStoreParameters(); truststoreParameters.setResource("truststore.jks"); truststoreParameters.setPassword("storepass"); - context.getRegistry().bind("keystoreParameters", keystoreParameters); - context.getRegistry().bind("truststoreParameters", truststoreParameters); + SSLContextParameters clientSSLContextParameters = new SSLContextParameters(); + TrustManagersParameters clientSSLTrustManagers = new TrustManagersParameters(); + clientSSLTrustManagers.setKeyStore(truststoreParameters); + clientSSLContextParameters.setTrustManagers(clientSSLTrustManagers); + + context.getRegistry().bind("serviceSSLContextParameters", serviceSSLContextParameters); + context.getRegistry().bind("clientSSLContextParameters", clientSSLContextParameters); return new RouteBuilder() { @Override public void configure() throws Exception { restConfiguration().component("coap").scheme("coaps").host("localhost").port(PORT) - .endpointProperty("keyStoreParameters", "#keystoreParameters") - .endpointProperty("alias", "service") - .endpointProperty("password", "security"); + .endpointProperty("sslContextParameters", "#serviceSSLContextParameters"); rest("/TestResource") .get().to("direct:get1") @@ -93,7 +105,7 @@ public void process(Exchange exchange) throws Exception { }); from("direct:start") - .toF("coaps://localhost:%d/TestResource?trustStoreParameters=#truststoreParameters", PORT) + .toF("coaps://localhost:%d/TestResource?sslContextParameters=#clientSSLContextParameters", PORT) .to("mock:result"); } };