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 39538df0660bc3fd1935970a25e95e219bd7cb00 Author: Colm O hEigeartaigh <cohei...@apache.org> AuthorDate: Wed Apr 24 11:52:08 2019 +0100 Added initial support for raw public keys --- .../camel-coap/src/main/docs/coap-component.adoc | 5 +- .../java/org/apache/camel/coap/CoAPEndpoint.java | 82 +++++++++++++++++++--- .../apache/camel/coap/CoAPComponentTLSTest.java | 36 ++++++++++ 3 files changed, 113 insertions(+), 10 deletions(-) diff --git a/components/camel-coap/src/main/docs/coap-component.adoc b/components/camel-coap/src/main/docs/coap-component.adoc index 0ac6390..1c7f280 100644 --- a/components/camel-coap/src/main/docs/coap-component.adoc +++ b/components/camel-coap/src/main/docs/coap-component.adoc @@ -50,7 +50,7 @@ with the following path and query parameters: |=== -==== Query Parameters (12 parameters): +==== Query Parameters (15 parameters): [width="100%",cols="2,5,^1,2",options="header"] @@ -60,6 +60,9 @@ with the following path and query parameters: | *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 +| *privateKey* (common) | Set the configured private key for use with Raw Public Key. | | PrivateKey +| *publicKey* (common) | Set the configured public key for use with Raw Public Key. | | PublicKey +| *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 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 e2d9dbb..926bc24 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 @@ -23,6 +23,7 @@ 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; import java.security.cert.X509Certificate; import java.util.ArrayList; @@ -41,6 +42,7 @@ import org.apache.camel.util.jsse.KeyStoreParameters; import org.eclipse.californium.core.CoapServer; import org.eclipse.californium.scandium.DTLSConnector; import org.eclipse.californium.scandium.config.DtlsConnectorConfig; +import org.eclipse.californium.scandium.dtls.rpkstore.TrustedRpkStore; /** * The coap component is used for sending and receiving messages from COAP capable devices. @@ -63,7 +65,16 @@ public class CoAPEndpoint extends DefaultEndpoint { @UriParam private KeyStore truststore; - + + @UriParam + private PrivateKey privateKey; + + @UriParam + private PublicKey publicKey; + + @UriParam + private TrustedRpkStore trustedRpkStore; + @UriParam private String alias; @@ -202,8 +213,50 @@ public class CoAPEndpoint extends DefaultEndpoint { public void setAlias(String alias) { this.alias = alias; } + + /** + * Get the TrustedRpkStore to use to determine trust in raw public keys. + */ + public TrustedRpkStore getTrustedRpkStore() { + return trustedRpkStore; + } + + /** + * Set the TrustedRpkStore to use to determine trust in raw public keys. + */ + public void setTrustedRpkStore(TrustedRpkStore trustedRpkStore) { + this.trustedRpkStore = trustedRpkStore; + } /** + * Get the configured private key for use with Raw Public Key. + */ + public PrivateKey getPrivateKey() { + return privateKey; + } + + /** + * Set the configured private key for use with Raw Public Key. + */ + public void setPrivateKey(PrivateKey privateKey) { + this.privateKey = privateKey; + } + + /** + * Get the configured public key for use with Raw Public Key. + */ + public PublicKey getPublicKey() { + return publicKey; + } + + /** + * Set the configured public key for use with Raw Public Key. + */ + public void setPublicKey(PublicKey publicKey) { + this.publicKey = publicKey; + } + + /** * Gets the password used to access an aliased {@link PrivateKey} in the KeyStore. */ public char[] getPassword() { @@ -293,19 +346,22 @@ public class CoAPEndpoint extends DefaultEndpoint { DtlsConnectorConfig.Builder builder = new DtlsConnectorConfig.Builder(); if (client) { - if (getTruststore() == null) { + if (trustedRpkStore == null && getTruststore() == null) { throw new IllegalStateException("A truststore must be configured to use TLS"); } builder.setClientOnly(); } else { - if (getKeystore() == null) { - throw new IllegalStateException("A keystore must be configured to use TLS"); + if (privateKey == null && getKeystore() == null) { + throw new IllegalStateException("A keystore or private key must be configured to use TLS"); + } + if (privateKey != null && publicKey == null) { + throw new IllegalStateException("A public key must be configured to use a Raw Public Key with TLS"); } - if (getAlias() == null) { + if (privateKey == null && getAlias() == null) { throw new IllegalStateException("An alias must be configured to use TLS"); } - if (getPassword() == null) { + if (privateKey == null && getPassword() == null) { throw new IllegalStateException("A password must be configured to use TLS"); } if ((isClientAuthenticationRequired() || isClientAuthenticationWanted()) @@ -319,15 +375,23 @@ public class CoAPEndpoint extends DefaultEndpoint { } try { - // Configure the identity if the keystore parameter is specified + // Configure the identity if the keystore or privateKey parameter is specified if (getKeystore() != null) { PrivateKey privateKey = (PrivateKey)getKeystore().getKey(getAlias(), getPassword()); builder.setIdentity(privateKey, getKeystore().getCertificateChain(getAlias())); + } else if (privateKey != null) { + builder.setIdentity(privateKey, publicKey); } - + // Add all certificates from the truststore - builder.setTrustStore(getTrustedCerts()); + Certificate[] certs = getTrustedCerts(); + if (certs.length > 0) { + builder.setTrustStore(certs); + } + if (trustedRpkStore != null) { + builder.setRpkTrustStore(trustedRpkStore); + } } catch (GeneralSecurityException e) { throw new IllegalStateException("Error in configuring TLS", e); } 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 f78bcb5..146fd1d 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,10 @@ */ package org.apache.camel.coap; +import java.security.KeyStore; +import java.security.PrivateKey; +import java.security.PublicKey; + import org.apache.camel.Exchange; import org.apache.camel.Message; import org.apache.camel.Processor; @@ -29,6 +33,7 @@ import org.apache.camel.test.junit4.CamelTestSupport; import org.apache.camel.util.jsse.KeyStoreParameters; import org.eclipse.californium.core.coap.CoAP; import org.eclipse.californium.core.coap.MediaTypeRegistry; +import org.eclipse.californium.scandium.dtls.rpkstore.TrustedRpkStore; import org.junit.Test; public class CoAPComponentTLSTest extends CamelTestSupport { @@ -37,6 +42,7 @@ public class CoAPComponentTLSTest extends CamelTestSupport { protected static final int PORT2 = AvailablePortFinder.getNextAvailable(); protected static final int PORT3 = AvailablePortFinder.getNextAvailable(); protected static final int PORT4 = AvailablePortFinder.getNextAvailable(); + protected static final int PORT5 = AvailablePortFinder.getNextAvailable(); @Produce(uri = "direct:start") protected ProducerTemplate sender; @@ -109,6 +115,17 @@ public class CoAPComponentTLSTest extends CamelTestSupport { assertMockEndpointsSatisfied(); } + @Test + public void testRawPublicKey() throws Exception { + MockEndpoint mock = getMockEndpoint("mock:result"); + mock.expectedMinimumMessageCount(1); + mock.expectedBodiesReceived("Hello Camel CoAP"); + mock.expectedHeaderReceived(Exchange.CONTENT_TYPE, MediaTypeRegistry.toString(MediaTypeRegistry.APPLICATION_OCTET_STREAM)); + mock.expectedHeaderReceived(CoAPConstants.COAP_RESPONSE_CODE, CoAP.ResponseCode.CONTENT.toString()); + sendBodyAndHeader("direct:rpk", "Camel CoAP", CoAPConstants.COAP_METHOD, "POST"); + assertMockEndpointsSatisfied(); + } + @Override protected JndiRegistry createRegistry() throws Exception { JndiRegistry registry = super.createRegistry(); @@ -117,6 +134,12 @@ public class CoAPComponentTLSTest extends CamelTestSupport { 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"); @@ -133,11 +156,16 @@ public class CoAPComponentTLSTest extends CamelTestSupport { truststoreParameters2.setResource("truststore2.jks"); truststoreParameters2.setPassword("storepass"); + TrustedRpkStore trustedRpkStore = id -> { return true;}; + registry.bind("keyParams", keystoreParameters); registry.bind("keyParams2", keystoreParameters2); registry.bind("keyParams3", keystoreParameters3); registry.bind("trustParams", truststoreParameters); registry.bind("trustParams2", truststoreParameters2); + registry.bind("privateKey", privateKey); + registry.bind("publicKey", publicKey); + registry.bind("trustedRpkStore", trustedRpkStore); return registry; } @@ -165,6 +193,10 @@ public class CoAPComponentTLSTest extends CamelTestSupport { + "keyStoreParameters=#keyParams&cipherSuites=TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8", PORT4) .transform(body().prepend("Hello ")); + fromF("coaps://localhost:%d/TestResource?alias=service&password=security&" + + "privateKey=#privateKey&publicKey=#publicKey", PORT5) + .transform(body().prepend("Hello ")); + from("direct:start") .toF("coaps://localhost:%d/TestResource?trustStoreParameters=#trustParams", PORT) .to("mock:result"); @@ -195,6 +227,10 @@ public class CoAPComponentTLSTest extends CamelTestSupport { .toF("coaps://localhost:%d/TestResource?trustStoreParameters=#trustParams&" + "cipherSuites=TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8", PORT4) .to("mock:result"); + + from("direct:rpk") + .toF("coaps://localhost:%d/TestResource?trustedRpkStore=#trustedRpkStore", PORT5) + .to("mock:result"); } }; }