You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by da...@apache.org on 2013/07/11 18:09:25 UTC
[3/3] git commit: CAMEL-6540: Added option to enrich Camel message
with client certificate information for SSL consumers.
CAMEL-6540: Added option to enrich Camel message with client certificate information for SSL consumers.
Project: http://git-wip-us.apache.org/repos/asf/camel/repo
Commit: http://git-wip-us.apache.org/repos/asf/camel/commit/dc281f36
Tree: http://git-wip-us.apache.org/repos/asf/camel/tree/dc281f36
Diff: http://git-wip-us.apache.org/repos/asf/camel/diff/dc281f36
Branch: refs/heads/master
Commit: dc281f360e1e5548057409a7bb9120c70e59f085
Parents: 6406914
Author: Claus Ibsen <da...@apache.org>
Authored: Thu Jul 11 18:04:18 2013 +0200
Committer: Claus Ibsen <da...@apache.org>
Committed: Thu Jul 11 18:04:39 2013 +0200
----------------------------------------------------------------------
.../camel/component/netty/NettyConstants.java | 5 ++
.../camel/component/netty/NettyEndpoint.java | 48 ++++++++++++-
.../NettyServerBootstrapConfiguration.java | 10 ++-
.../netty/NettySSLClientCertHeadersTest.java | 74 ++++++++++++++++++++
4 files changed, 134 insertions(+), 3 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/camel/blob/dc281f36/components/camel-netty/src/main/java/org/apache/camel/component/netty/NettyConstants.java
----------------------------------------------------------------------
diff --git a/components/camel-netty/src/main/java/org/apache/camel/component/netty/NettyConstants.java b/components/camel-netty/src/main/java/org/apache/camel/component/netty/NettyConstants.java
index 1ea260c..4082c7d 100644
--- a/components/camel-netty/src/main/java/org/apache/camel/component/netty/NettyConstants.java
+++ b/components/camel-netty/src/main/java/org/apache/camel/component/netty/NettyConstants.java
@@ -29,6 +29,11 @@ public final class NettyConstants {
public static final String NETTY_REMOTE_ADDRESS = "CamelNettyRemoteAddress";
public static final String NETTY_LOCAL_ADDRESS = "CamelNettyLocalAddress";
public static final String NETTY_SSL_SESSION = "CamelNettySSLSession";
+ public static final String NETTY_SSL_CLIENT_CERT_SUBJECT_NAME = "CamelNettySSLClientCertSubjectName";
+ public static final String NETTY_SSL_CLIENT_CERT_ISSUER_NAME = "CamelNettySSLClientCertIssuerName";
+ public static final String NETTY_SSL_CLIENT_CERT_SERIAL_NO = "CamelNettySSLClientCertSerialNumber";
+ public static final String NETTY_SSL_CLIENT_CERT_NOT_BEFORE = "CamelNettySSLClientCertNotBefore";
+ public static final String NETTY_SSL_CLIENT_CERT_NOT_AFTER = "CamelNettySSLClientCertNotAfter";
private NettyConstants() {
// Utility class
http://git-wip-us.apache.org/repos/asf/camel/blob/dc281f36/components/camel-netty/src/main/java/org/apache/camel/component/netty/NettyEndpoint.java
----------------------------------------------------------------------
diff --git a/components/camel-netty/src/main/java/org/apache/camel/component/netty/NettyEndpoint.java b/components/camel-netty/src/main/java/org/apache/camel/component/netty/NettyEndpoint.java
index a712b7e..7b464fa 100644
--- a/components/camel-netty/src/main/java/org/apache/camel/component/netty/NettyEndpoint.java
+++ b/components/camel-netty/src/main/java/org/apache/camel/component/netty/NettyEndpoint.java
@@ -16,7 +16,11 @@
*/
package org.apache.camel.component.netty;
+import java.math.BigInteger;
+import java.security.Principal;
+import javax.net.ssl.SSLPeerUnverifiedException;
import javax.net.ssl.SSLSession;
+import javax.security.cert.X509Certificate;
import org.apache.camel.Consumer;
import org.apache.camel.Exchange;
@@ -106,7 +110,7 @@ public class NettyEndpoint extends DefaultEndpoint {
}
return sslSession;
}
-
+
protected void updateMessageHeader(Message in, ChannelHandlerContext ctx, MessageEvent messageEvent) {
in.setHeader(NettyConstants.NETTY_CHANNEL_HANDLER_CONTEXT, ctx);
in.setHeader(NettyConstants.NETTY_MESSAGE_EVENT, messageEvent);
@@ -115,7 +119,47 @@ public class NettyEndpoint extends DefaultEndpoint {
if (configuration.isSsl()) {
// setup the SslSession header
- in.setHeader(NettyConstants.NETTY_SSL_SESSION, getSSLSession(ctx));
+ SSLSession sslSession = getSSLSession(ctx);
+ in.setHeader(NettyConstants.NETTY_SSL_SESSION, sslSession);
+
+ // enrich headers with details from the client certificate if option is enabled
+ if (configuration.isSslClientCertHeaders()) {
+ enrichWithClientCertInformation(sslSession, in);
+ }
+ }
+ }
+
+ /**
+ * Enriches the message with client certificate details such as subject name, serial number etc.
+ * <p/>
+ * If the certificate is unverified then the headers is not enriched.
+ *
+ * @param sslSession the SSL session
+ * @param message the message to enrich
+ */
+ protected void enrichWithClientCertInformation(SSLSession sslSession, Message message) {
+ try {
+ X509Certificate[] certificates = sslSession.getPeerCertificateChain();
+ if (certificates != null && certificates.length > 0) {
+ X509Certificate cert = certificates[0];
+
+ Principal subject = cert.getSubjectDN();
+ if (subject != null) {
+ message.setHeader(NettyConstants.NETTY_SSL_CLIENT_CERT_SUBJECT_NAME, subject.getName());
+ }
+ Principal issuer = cert.getIssuerDN();
+ if (issuer != null) {
+ message.setHeader(NettyConstants.NETTY_SSL_CLIENT_CERT_ISSUER_NAME, issuer.getName());
+ }
+ BigInteger serial = cert.getSerialNumber();
+ if (serial != null) {
+ message.setHeader(NettyConstants.NETTY_SSL_CLIENT_CERT_SERIAL_NO, serial.toString());
+ }
+ message.setHeader(NettyConstants.NETTY_SSL_CLIENT_CERT_NOT_BEFORE, cert.getNotBefore());
+ message.setHeader(NettyConstants.NETTY_SSL_CLIENT_CERT_NOT_AFTER, cert.getNotAfter());
+ }
+ } catch (SSLPeerUnverifiedException e) {
+ // ignore
}
}
http://git-wip-us.apache.org/repos/asf/camel/blob/dc281f36/components/camel-netty/src/main/java/org/apache/camel/component/netty/NettyServerBootstrapConfiguration.java
----------------------------------------------------------------------
diff --git a/components/camel-netty/src/main/java/org/apache/camel/component/netty/NettyServerBootstrapConfiguration.java b/components/camel-netty/src/main/java/org/apache/camel/component/netty/NettyServerBootstrapConfiguration.java
index 7df49b0..e7972fb 100644
--- a/components/camel-netty/src/main/java/org/apache/camel/component/netty/NettyServerBootstrapConfiguration.java
+++ b/components/camel-netty/src/main/java/org/apache/camel/component/netty/NettyServerBootstrapConfiguration.java
@@ -18,7 +18,6 @@ package org.apache.camel.component.netty;
import java.io.File;
import java.util.Map;
-import java.util.concurrent.ExecutorService;
import org.apache.camel.util.jsse.SSLContextParameters;
import org.jboss.netty.channel.socket.nio.BossPool;
@@ -46,6 +45,7 @@ public class NettyServerBootstrapConfiguration implements Cloneable {
protected Map<String, Object> options;
// SSL options is also part of the server bootstrap as the server listener on port X is either plain or SSL
protected boolean ssl;
+ protected boolean sslClientCertHeaders;
protected SslHandler sslHandler;
protected SSLContextParameters sslContextParameters;
protected boolean needClientAuth;
@@ -187,6 +187,14 @@ public class NettyServerBootstrapConfiguration implements Cloneable {
this.ssl = ssl;
}
+ public boolean isSslClientCertHeaders() {
+ return sslClientCertHeaders;
+ }
+
+ public void setSslClientCertHeaders(boolean sslClientCertHeaders) {
+ this.sslClientCertHeaders = sslClientCertHeaders;
+ }
+
public SslHandler getSslHandler() {
return sslHandler;
}
http://git-wip-us.apache.org/repos/asf/camel/blob/dc281f36/components/camel-netty/src/test/java/org/apache/camel/component/netty/NettySSLClientCertHeadersTest.java
----------------------------------------------------------------------
diff --git a/components/camel-netty/src/test/java/org/apache/camel/component/netty/NettySSLClientCertHeadersTest.java b/components/camel-netty/src/test/java/org/apache/camel/component/netty/NettySSLClientCertHeadersTest.java
new file mode 100644
index 0000000..7469d1c
--- /dev/null
+++ b/components/camel-netty/src/test/java/org/apache/camel/component/netty/NettySSLClientCertHeadersTest.java
@@ -0,0 +1,74 @@
+/**
+ * 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
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.camel.component.netty;
+
+import java.io.File;
+
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.impl.JndiRegistry;
+import org.junit.Test;
+
+public class NettySSLClientCertHeadersTest extends BaseNettyTest {
+
+ @Override
+ protected JndiRegistry createRegistry() throws Exception {
+ JndiRegistry registry = super.createRegistry();
+ registry.bind("ksf", new File("src/test/resources/keystore.jks"));
+ registry.bind("tsf", new File("src/test/resources/keystore.jks"));
+ return registry;
+ }
+
+ @Override
+ public boolean isUseRouteBuilder() {
+ return false;
+ }
+
+ @Test
+ public void testSSLInOutWithNettyConsumer() throws Exception {
+ // ibm jdks dont have sun security algorithms
+ if (isJavaVendor("ibm")) {
+ return;
+ }
+
+ getMockEndpoint("mock:input").expectedMessageCount(1);
+
+ getMockEndpoint("mock:input").expectedHeaderReceived(NettyConstants.NETTY_SSL_CLIENT_CERT_SUBJECT_NAME,
+ "CN=arlu15, OU=Sun Java System Application Server, O=Sun Microsystems, L=Santa Clara, ST=California, C=US");
+ getMockEndpoint("mock:input").expectedHeaderReceived(NettyConstants.NETTY_SSL_CLIENT_CERT_ISSUER_NAME,
+ "CN=arlu15, OU=Sun Java System Application Server, O=Sun Microsystems, L=Santa Clara, ST=California, C=US");
+ getMockEndpoint("mock:input").expectedHeaderReceived(NettyConstants.NETTY_SSL_CLIENT_CERT_SERIAL_NO, "1210701502");
+
+ context.addRoutes(new RouteBuilder() {
+ public void configure() {
+ // needClientAuth=true so we can get the client certificate details
+ from("netty:tcp://localhost:{{port}}?sync=true&ssl=true&passphrase=changeit&keyStoreFile=#ksf&trustStoreFile=#tsf"
+ + "&needClientAuth=true&sslClientCertHeaders=true")
+ .to("mock:input")
+ .transform().constant("Bye World");
+ }
+ });
+ context.start();
+
+ String response = template.requestBody(
+ "netty:tcp://localhost:{{port}}?sync=true&ssl=true&passphrase=changeit&keyStoreFile=#ksf&trustStoreFile=#tsf",
+ "Hello World", String.class);
+ assertEquals("Bye World", response);
+
+ assertMockEndpointsSatisfied();
+ }
+
+}