1) DTLS support
The first significant improvement is that the CoAP component has been updated to support DTLS, something that necessitated a major upgrade of the californium dependency. CoAP supports TLS / UDP using a "coaps" scheme, something it is now possible to use in Camel. To see how this all works, take a look at the following github test-case I put together:
- camel-coap - A test-case for the camel-coap component. It shows how to use the coap component with the Camel REST DSL + TLS.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<sslContextParameters id="serverSSLParameters" xmlns="http://camel.apache.org/schema/spring"> | |
<keyManagers keyPassword="security"> | |
<keyStore resource="service.jks" password="security"/> | |
</keyManagers> | |
</sslContextParameters> | |
<camelContext xmlns="http://camel.apache.org/schema/spring"> | |
<restConfiguration scheme="coaps" component="coap" port="{{https.port}}"> | |
<endpointProperty key="sslContextParameters" value="#serverSSLParameters" /> | |
</restConfiguration> | |
... | |
</camelContext> |
On the client side, the test-case shows how to configure a Camel producer to invoke on the coaps REST API:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<sslContextParameters id="clientSSLParameters" xmlns="http://camel.apache.org/schema/spring"> | |
<trustManagers> | |
<keyStore resource="truststore.jks" password="storepass"/> | |
</trustManagers> | |
<cipherSuites> | |
<cipherSuite>TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256</cipherSuite> | |
</cipherSuites> | |
</sslContextParameters> | |
<camelContext xmlns="http://camel.apache.org/schema/spring"> | |
... | |
<route> | |
<from uri="timer:start?repeatCount=1"/> | |
<to uri="coaps:localhost:{{https.port}}/data?sslContextParameters=#clientSSLParameters" /> | |
<log message="Data received: ${body}" /> | |
</route> | |
</camelContext> |
Note that a scheme of "coaps" is used, and that it refers to a sslContextParameters bean containing the truststore to use, as well as a specific CipherSuite (this is optional, I just put it in to show how to use it). As the logging output does not really show what is going on, here is the Wireshark output which shows that DTLS is in use:
2) Support for Raw Public Keys and Pre-Shared Keys
In the section above, we saw how to configure CoAP with DTLS by referring to a sslContextParameters bean, which in turn refers to keystores to extract private keys and certificates. This is one option to support DTLS. However we also have two other options instead of using certificates.
The first is called Raw Public Keys. This is when we may not have access to a certificate containing the (trusted) public key of the endpoint. In this case, we can configure TLS using a PrivateKey and/or PublicKey objects. Both are required for a service. The client needs to be configured with a trustedRpkStore parameter, which is an interface supplied by Californium, that determines trust in an identifier. If the service is configured with "clientAuthentication" of "REQUIRE", then the service must configure trustedRpkStore, and the client must also specify a privateKey parameter. Here is a sample code snippet from the Camel tests:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
KeyStore keyStore = ... | |
PrivateKey privateKey = (PrivateKey)keyStore.getKey("service", "security".toCharArray()); | |
PublicKey publicKey = keyStore.getCertificate("service").getPublicKey(); | |
TrustedRpkStore trustedRpkStore = id -> { | |
return true; | |
}; | |
context.getRegistry().bind("privateKey", privateKey); | |
context.getRegistry().bind("publicKey", publicKey); | |
context.getRegistry().bind("trustedRpkStore", trustedRpkStore); | |
fromF(getProtocol() + "://localhost:%d/TestResource?privateKey=#privateKey&publicKey=#publicKey", PORT5) | |
.transform(body().prepend("Hello ")); | |
from("direct:rpk") | |
.toF(getProtocol() + "://localhost:%d/TestResource?trustedRpkStore=#trustedRpkStore", PORT5) | |
.to("mock:result"); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
KeyGenerator keyGenerator = KeyGenerator.getInstance("AES"); | |
PskStore pskStore = new StaticPskStore("some-identity", keyGenerator.generateKey().getEncoded()); | |
context.getRegistry().bind("pskStore", pskStore); | |
fromF(getProtocol() + "://localhost:%d/TestResource?pskStore=#pskStore", PORT7) | |
.transform(body().prepend("Hello ")); | |
from("direct:psk") | |
.toF(getProtocol() + "://localhost:%d/TestResource?pskStore=#pskStore", PORT7) | |
.to("mock:result"); |
3) Support for TCP / TLS
A newer RFC (RFC-8323) extends the original RFC to add support for CoAP over TCP and Websockets. Camel 3.0.0 has added support for using CoAP over both TCP and also TLS over TCP. Websocket support is not currently available. RFC-8323 uses two new schemes for TCP, both of which are supported in Camel - "coap+tcp" for CoAP / TCP, and "coaps+tcp" for CoAP / TCP with TLS. Only the certificate method of configuring TLS is supported, which works in exactly the same way as for DTLS above. Pre-shared keys and Raw Public Keys are not supported over TCP now, only UDP.
To see how it works, simply alter the configuration in the github testcase and change "coaps" to "coaps+tcp" (in both locations). Now run the test-case again and it should work seemlessly:
No comments:
Post a Comment