Repository: camel Updated Branches: refs/heads/master f4a81c8f4 -> a45fa8998
CAMEL-7281: Add support for certAlias in SSLContextParameters. Thanks to Colm for the patch. Project: http://git-wip-us.apache.org/repos/asf/camel/repo Commit: http://git-wip-us.apache.org/repos/asf/camel/commit/a45fa899 Tree: http://git-wip-us.apache.org/repos/asf/camel/tree/a45fa899 Diff: http://git-wip-us.apache.org/repos/asf/camel/diff/a45fa899 Branch: refs/heads/master Commit: a45fa89984f84bc8ddcbf8a29652319ae82b73c3 Parents: f4a81c8 Author: Claus Ibsen <davscl...@apache.org> Authored: Mon Mar 10 19:36:37 2014 +0100 Committer: Claus Ibsen <davscl...@apache.org> Committed: Mon Mar 10 19:36:37 2014 +0100 ---------------------------------------------------------------------- .../jsse/AliasedX509ExtendedKeyManager.java | 118 +++++++++++++++++++ .../camel/util/jsse/SSLContextParameters.java | 36 ++++++ .../util/jsse/KeyManagersParametersTest.java | 12 ++ ...AbstractSSLContextParametersFactoryBean.java | 12 ++ .../component/jetty/HttpsRouteAliasTest.java | 75 ++++++++++++ .../src/test/resources/jsse/localhost-alias.ks | Bin 0 -> 2507 bytes .../SSLContextParametersFactoryBeanTest.java | 1 + ...ContextParametersFactoryBeanTest-context.xml | 3 +- 8 files changed, 256 insertions(+), 1 deletion(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/camel/blob/a45fa899/camel-core/src/main/java/org/apache/camel/util/jsse/AliasedX509ExtendedKeyManager.java ---------------------------------------------------------------------- diff --git a/camel-core/src/main/java/org/apache/camel/util/jsse/AliasedX509ExtendedKeyManager.java b/camel-core/src/main/java/org/apache/camel/util/jsse/AliasedX509ExtendedKeyManager.java new file mode 100644 index 0000000..be63684 --- /dev/null +++ b/camel-core/src/main/java/org/apache/camel/util/jsse/AliasedX509ExtendedKeyManager.java @@ -0,0 +1,118 @@ +/** + * 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.util.jsse; + +import java.net.Socket; +import java.security.Principal; +import java.security.PrivateKey; +import java.security.cert.X509Certificate; + +import javax.net.ssl.SSLEngine; +import javax.net.ssl.X509ExtendedKeyManager; +import javax.net.ssl.X509KeyManager; + +/* ------------------------------------------------------------ */ +/** + * KeyManager to select a key with desired alias while delegating processing to specified KeyManager Can be + * used both with server and client sockets + */ +public class AliasedX509ExtendedKeyManager extends X509ExtendedKeyManager { + private String keyAlias; + private X509KeyManager keyManager; + + /* ------------------------------------------------------------ */ + /** + * Construct KeyManager instance + * + * @param keyAlias Alias of the key to be selected + * @param keyManager Instance of KeyManager to be wrapped + * @throws Exception + */ + public AliasedX509ExtendedKeyManager(String keyAlias, X509KeyManager keyManager) throws Exception { + this.keyAlias = keyAlias; + this.keyManager = keyManager; + } + + /* ------------------------------------------------------------ */ + /** + * @see javax.net.ssl.X509KeyManager#chooseClientAlias(java.lang.String[], java.security.Principal[], + * java.net.Socket) + */ + public String chooseClientAlias(String[] keyType, Principal[] issuers, Socket socket) { + return keyAlias == null ? keyManager.chooseClientAlias(keyType, issuers, socket) : keyAlias; + } + + /* ------------------------------------------------------------ */ + /** + * @see javax.net.ssl.X509KeyManager#chooseServerAlias(java.lang.String, java.security.Principal[], + * java.net.Socket) + */ + public String chooseServerAlias(String keyType, Principal[] issuers, Socket socket) { + return keyAlias == null ? keyManager.chooseServerAlias(keyType, issuers, socket) : keyAlias; + } + + /* ------------------------------------------------------------ */ + /** + * @see javax.net.ssl.X509KeyManager#getClientAliases(java.lang.String, java.security.Principal[]) + */ + public String[] getClientAliases(String keyType, Principal[] issuers) { + return keyManager.getClientAliases(keyType, issuers); + } + + /* ------------------------------------------------------------ */ + /** + * @see javax.net.ssl.X509KeyManager#getServerAliases(java.lang.String, java.security.Principal[]) + */ + public String[] getServerAliases(String keyType, Principal[] issuers) { + return keyManager.getServerAliases(keyType, issuers); + } + + /* ------------------------------------------------------------ */ + /** + * @see javax.net.ssl.X509KeyManager#getCertificateChain(java.lang.String) + */ + public X509Certificate[] getCertificateChain(String alias) { + return keyManager.getCertificateChain(alias); + } + + /* ------------------------------------------------------------ */ + /** + * @see javax.net.ssl.X509KeyManager#getPrivateKey(java.lang.String) + */ + public PrivateKey getPrivateKey(String alias) { + return keyManager.getPrivateKey(alias); + } + + /* ------------------------------------------------------------ */ + /** + * @see javax.net.ssl.X509ExtendedKeyManager#chooseEngineServerAlias(java.lang.String, + * java.security.Principal[], javax.net.ssl.SSLEngine) + */ + @Override + public String chooseEngineServerAlias(String keyType, Principal[] issuers, SSLEngine engine) { + return keyAlias == null ? super.chooseEngineServerAlias(keyType, issuers, engine) : keyAlias; + } + + /* ------------------------------------------------------------ */ + /** + * @see javax.net.ssl.X509ExtendedKeyManager#chooseEngineClientAlias(String[], Principal[], SSLEngine) + */ + @Override + public String chooseEngineClientAlias(String keyType[], Principal[] issuers, SSLEngine engine) { + return keyAlias == null ? super.chooseEngineClientAlias(keyType, issuers, engine) : keyAlias; + } +} http://git-wip-us.apache.org/repos/asf/camel/blob/a45fa899/camel-core/src/main/java/org/apache/camel/util/jsse/SSLContextParameters.java ---------------------------------------------------------------------- diff --git a/camel-core/src/main/java/org/apache/camel/util/jsse/SSLContextParameters.java b/camel-core/src/main/java/org/apache/camel/util/jsse/SSLContextParameters.java index aa8b49b..ab0eb9c 100644 --- a/camel-core/src/main/java/org/apache/camel/util/jsse/SSLContextParameters.java +++ b/camel-core/src/main/java/org/apache/camel/util/jsse/SSLContextParameters.java @@ -28,6 +28,7 @@ import javax.net.ssl.SSLEngine; import javax.net.ssl.SSLServerSocketFactory; import javax.net.ssl.SSLSocketFactory; import javax.net.ssl.TrustManager; +import javax.net.ssl.X509KeyManager; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -92,6 +93,12 @@ public class SSLContextParameters extends BaseSSLContextParameters { * standard protocol names. */ private String secureSocketProtocol; + + /** + * An optional certificate alias to use. This is useful when the keystore has multiple + * certificates. + */ + private String certAlias; public KeyManagersParameters getKeyManagers() { return keyManagers; @@ -213,6 +220,19 @@ public class SSLContextParameters extends BaseSSLContextParameters { this.secureSocketProtocol = secureSocketProtocol; } + public String getCertAlias() { + return certAlias; + } + + /** + * An optional certificate alias to use. This is useful when the keystore has multiple + * certificates. + * @param certAlias an optional certificate alias to use + */ + public void setCertAlias(String certAlias) { + this.certAlias = certAlias; + } + //////////////////////////////////////////// /** @@ -245,6 +265,19 @@ public class SSLContextParameters extends BaseSSLContextParameters { this.parsePropertyValue(this.getProvider())); } + if (this.getCertAlias() != null && keyManagers != null) { + for (int idx = 0; idx < keyManagers.length; idx++) { + if (keyManagers[idx] instanceof X509KeyManager) { + try { + keyManagers[idx] = new AliasedX509ExtendedKeyManager(this.getCertAlias(), + (X509KeyManager)keyManagers[idx]); + } catch (Exception e) { + throw new GeneralSecurityException(e); + } + } + } + } + LOG.debug("SSLContext [{}], initialized from [{}], is using provider [{}], protocol [{}], key managers {}, trust managers {}, and secure random [{}].", new Object[] {context, this, context.getProvider(), context.getProtocol(), keyManagers, trustManagers, secureRandom}); @@ -354,6 +387,8 @@ public class SSLContextParameters extends BaseSSLContextParameters { builder.append(provider); builder.append(", secureSocketProtocol="); builder.append(secureSocketProtocol); + builder.append(", certAlias="); + builder.append(certAlias); builder.append(", getCipherSuites()="); builder.append(getCipherSuites()); builder.append(", getCipherSuitesFilter()="); @@ -369,4 +404,5 @@ public class SSLContextParameters extends BaseSSLContextParameters { builder.append("]"); return builder.toString(); } + } http://git-wip-us.apache.org/repos/asf/camel/blob/a45fa899/camel-core/src/test/java/org/apache/camel/util/jsse/KeyManagersParametersTest.java ---------------------------------------------------------------------- diff --git a/camel-core/src/test/java/org/apache/camel/util/jsse/KeyManagersParametersTest.java b/camel-core/src/test/java/org/apache/camel/util/jsse/KeyManagersParametersTest.java index a6b7937..f3f55c8 100644 --- a/camel-core/src/test/java/org/apache/camel/util/jsse/KeyManagersParametersTest.java +++ b/camel-core/src/test/java/org/apache/camel/util/jsse/KeyManagersParametersTest.java @@ -128,6 +128,18 @@ public class KeyManagersParametersTest extends AbstractJsseParametersTest { // expected } } + + public void testAliasedKeyManager() throws Exception { + KeyManagersParameters kmp = this.createMinimalKeyManagersParameters(); + + KeyManager[] kms = kmp.createKeyManagers(); + assertEquals(1, kms.length); + assertTrue(kms[0] instanceof X509KeyManager); + + kms[0] = new AliasedX509ExtendedKeyManager("server", (X509KeyManager)kms[0]); + AliasedX509ExtendedKeyManager km = (AliasedX509ExtendedKeyManager) kms[0]; + assertNotNull(km.getPrivateKey("server")); + } protected void validateKeyManagers(KeyManager[] kms) { assertEquals(1, kms.length); http://git-wip-us.apache.org/repos/asf/camel/blob/a45fa899/components/camel-core-xml/src/main/java/org/apache/camel/core/xml/util/jsse/AbstractSSLContextParametersFactoryBean.java ---------------------------------------------------------------------- diff --git a/components/camel-core-xml/src/main/java/org/apache/camel/core/xml/util/jsse/AbstractSSLContextParametersFactoryBean.java b/components/camel-core-xml/src/main/java/org/apache/camel/core/xml/util/jsse/AbstractSSLContextParametersFactoryBean.java index 2121b94..81aeeef 100644 --- a/components/camel-core-xml/src/main/java/org/apache/camel/core/xml/util/jsse/AbstractSSLContextParametersFactoryBean.java +++ b/components/camel-core-xml/src/main/java/org/apache/camel/core/xml/util/jsse/AbstractSSLContextParametersFactoryBean.java @@ -32,6 +32,9 @@ public abstract class AbstractSSLContextParametersFactoryBean extends AbstractBa @XmlAttribute private String secureSocketProtocol; + + @XmlAttribute + private String certAlias; @Override protected SSLContextParameters createInstance() throws Exception { @@ -65,6 +68,7 @@ public abstract class AbstractSSLContextParametersFactoryBean extends AbstractBa newInstance.setProvider(provider); newInstance.setSecureSocketProtocol(secureSocketProtocol); + newInstance.setCertAlias(certAlias); newInstance.setCamelContext(getCamelContext()); return newInstance; @@ -90,6 +94,14 @@ public abstract class AbstractSSLContextParametersFactoryBean extends AbstractBa public void setSecureSocketProtocol(String secureSocketProtocol) { this.secureSocketProtocol = secureSocketProtocol; } + + public String getCertAlias() { + return certAlias; + } + + public void setCertAlias(String certAlias) { + this.certAlias = certAlias; + } protected abstract AbstractKeyManagersParametersFactoryBean getKeyManagers(); http://git-wip-us.apache.org/repos/asf/camel/blob/a45fa899/components/camel-jetty/src/test/java/org/apache/camel/component/jetty/HttpsRouteAliasTest.java ---------------------------------------------------------------------- diff --git a/components/camel-jetty/src/test/java/org/apache/camel/component/jetty/HttpsRouteAliasTest.java b/components/camel-jetty/src/test/java/org/apache/camel/component/jetty/HttpsRouteAliasTest.java new file mode 100644 index 0000000..47a3595 --- /dev/null +++ b/components/camel-jetty/src/test/java/org/apache/camel/component/jetty/HttpsRouteAliasTest.java @@ -0,0 +1,75 @@ +/** + * 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.jetty; + +import java.net.URISyntaxException; + +import org.apache.camel.Exchange; +import org.apache.camel.Processor; +import org.apache.camel.builder.RouteBuilder; +import org.apache.camel.util.jsse.KeyManagersParameters; +import org.apache.camel.util.jsse.KeyStoreParameters; +import org.apache.camel.util.jsse.SSLContextParameters; + +public class HttpsRouteAliasTest extends HttpsRouteTest { + + @Override + protected RouteBuilder createRouteBuilder() throws Exception { + return new RouteBuilder() { + public void configure() throws URISyntaxException { + // create jetty component + JettyHttpComponent jetty = new JettyHttpComponent(); + + KeyStoreParameters ksp = new KeyStoreParameters(); + ksp.setResource(this.getClass().getClassLoader().getResource("jsse/localhost-alias.ks").toString()); + ksp.setPassword(pwd); + + KeyManagersParameters kmp = new KeyManagersParameters(); + kmp.setKeyPassword(pwd); + kmp.setKeyStore(ksp); + + SSLContextParameters sslContextParameters = new SSLContextParameters(); + sslContextParameters.setKeyManagers(kmp); + + // Specify "server" cert alias + sslContextParameters.setCertAlias("server"); + + jetty.setSslContextParameters(sslContextParameters); + + // NOTE: These are here to check that they are properly ignored. + jetty.addSslSocketConnectorProperty("keyPassword", "sadfasdfasdfas"); + jetty.addSslSocketConnectorProperty("password", "asdfasdfasdfdasfs"); + jetty.addSslSocketConnectorProperty("keystore", ""); + jetty.addSslSocketConnectorProperty("truststoreType", "JKS"); + + // add jetty to camel context + context.addComponent("jetty", jetty); + + from("jetty:https://localhost:" + port1 + "/test").to("mock:a"); + + Processor proc = new Processor() { + public void process(Exchange exchange) throws Exception { + exchange.getOut().setBody("<b>Hello World</b>"); + } + }; + from("jetty:https://localhost:" + port1 + "/hello").process(proc); + + from("jetty:https://localhost:" + port2 + "/test").to("mock:b"); + } + }; + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/camel/blob/a45fa899/components/camel-jetty/src/test/resources/jsse/localhost-alias.ks ---------------------------------------------------------------------- diff --git a/components/camel-jetty/src/test/resources/jsse/localhost-alias.ks b/components/camel-jetty/src/test/resources/jsse/localhost-alias.ks new file mode 100644 index 0000000..33fb9b6 Binary files /dev/null and b/components/camel-jetty/src/test/resources/jsse/localhost-alias.ks differ http://git-wip-us.apache.org/repos/asf/camel/blob/a45fa899/components/camel-spring/src/test/java/org/apache/camel/util/spring/SSLContextParametersFactoryBeanTest.java ---------------------------------------------------------------------- diff --git a/components/camel-spring/src/test/java/org/apache/camel/util/spring/SSLContextParametersFactoryBeanTest.java b/components/camel-spring/src/test/java/org/apache/camel/util/spring/SSLContextParametersFactoryBeanTest.java index ce3496f..5f322bf 100644 --- a/components/camel-spring/src/test/java/org/apache/camel/util/spring/SSLContextParametersFactoryBeanTest.java +++ b/components/camel-spring/src/test/java/org/apache/camel/util/spring/SSLContextParametersFactoryBeanTest.java @@ -44,6 +44,7 @@ public class SSLContextParametersFactoryBeanTest { assertEquals("provider", scp.getProvider()); assertEquals("protocol", scp.getSecureSocketProtocol()); + assertEquals("alice", scp.getCertAlias()); validateBaseSSLContextParameters(scp); http://git-wip-us.apache.org/repos/asf/camel/blob/a45fa899/components/camel-spring/src/test/resources/org/apache/camel/util/spring/SSLContextParametersFactoryBeanTest-context.xml ---------------------------------------------------------------------- diff --git a/components/camel-spring/src/test/resources/org/apache/camel/util/spring/SSLContextParametersFactoryBeanTest-context.xml b/components/camel-spring/src/test/resources/org/apache/camel/util/spring/SSLContextParametersFactoryBeanTest-context.xml index dc60b10..b9dfde6 100644 --- a/components/camel-spring/src/test/resources/org/apache/camel/util/spring/SSLContextParametersFactoryBeanTest-context.xml +++ b/components/camel-spring/src/test/resources/org/apache/camel/util/spring/SSLContextParametersFactoryBeanTest-context.xml @@ -28,7 +28,8 @@ id="scp" sessionTimeout="1" secureSocketProtocol="protocol" - provider="provider"> + provider="provider" + certAlias="alice"> <camel:cipherSuites> <camel:cipherSuite>cipherSuite</camel:cipherSuite>