You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@qpid.apache.org by ro...@apache.org on 2012/11/04 22:03:37 UTC
svn commit: r1405636 - in /qpid/trunk/qpid: doc/book/src/java-broker/
java/common/src/main/java/org/apache/qpid/transport/network/io/
java/systests/src/main/java/org/apache/qpid/client/ssl/
java/systests/src/main/java/org/apache/qpid/server/security/au...
Author: robbie
Date: Sun Nov 4 21:03:36 2012
New Revision: 1405636
URL: http://svn.apache.org/viewvc?rev=1405636&view=rev
Log:
QPID-4420: add documentation for SSL and the Anonymous + External AuthenticationManagers along with some general cleanup and expanded testing
Added:
qpid/trunk/qpid/java/systests/src/main/java/org/apache/qpid/server/security/auth/manager/ExternalAuthenticationTest.java
Modified:
qpid/trunk/qpid/doc/book/src/java-broker/Java-Broker-Security-Authentication-Providers.xml
qpid/trunk/qpid/doc/book/src/java-broker/Java-Broker-Security-SSL.xml
qpid/trunk/qpid/java/common/src/main/java/org/apache/qpid/transport/network/io/IoNetworkTransport.java
qpid/trunk/qpid/java/systests/src/main/java/org/apache/qpid/client/ssl/SSLTest.java
qpid/trunk/qpid/java/systests/src/main/java/org/apache/qpid/test/utils/QpidBrokerTestCase.java
qpid/trunk/qpid/java/test-profiles/CPPExcludes
Modified: qpid/trunk/qpid/doc/book/src/java-broker/Java-Broker-Security-Authentication-Providers.xml
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/doc/book/src/java-broker/Java-Broker-Security-Authentication-Providers.xml?rev=1405636&r1=1405635&r2=1405636&view=diff
==============================================================================
--- qpid/trunk/qpid/doc/book/src/java-broker/Java-Broker-Security-Authentication-Providers.xml (original)
+++ qpid/trunk/qpid/doc/book/src/java-broker/Java-Broker-Security-Authentication-Providers.xml Sun Nov 4 21:03:36 2012
@@ -26,55 +26,22 @@
<para>
In order to successfully establish a connection to the Java Broker, the connection must be
authenticated. The Java Broker supports a number of different authentication schemes, each
- with its own "authentication manager". Different managers may be used on different ports.
- Each manager has its own configuration element, the presence of which within the
- <security> section denotes the use of that authentication provider. Where only one
- such manager is configured, that manager will be used on all ports (including JMX). Where
- more than one authentication manager is configured the configuration must define which
- manager is the "default", and (if required) the mapping of non-default authentication
- managers to other ports.
- </para>
- <para>
- The following configuration sets up three authentication managers, using a password file as
- the default (e.g. for the JMX port), Kerberos on port 5672 and Anonymous on 5673.
+ with its own "authentication manager". Each of these are outlined below, along with details
+ of <link linkend="MultipleAuthProviders"> using more than one at a time</link>.
</para>
- <example>
- <title>Configuring different authentication schemes on different ports</title>
- <programlisting><![CDATA[
-<security>
- <pd-auth-manager>
- <principal-database>
- <class>org.apache.qpid.server.security.auth.database.PlainPasswordFilePrincipalDatabase</class>
- <attributes>
- <attribute>
- <name>passwordFile</name>
- <value>${conf}/passwd</value>
- </attribute>
- </attributes>
- </principal-database>
- </pd-auth-manager>
- <kerberos-auth-manager><auth-name>sib</auth-name></kerberos-auth-manager>
- <anonymous-auth-manager></anonymous-auth-manager>
- <default-auth-manager>PrincipalDatabaseAuthenticationManager</default-auth-manager>
- <port-mappings>
- <port-mapping>
- <port>5672</port>
- <auth-manager>KerberosAuthenticationManager</auth-manager>
- </port-mapping>
- <port-mapping>
- <port>5673</port>
- <auth-manager>AnonymousAuthenticationManager</auth-manager>
- </port-mapping>
- </port-mappings>
-</security>]]>
- </programlisting>
- </example>
+ <section>
+ <title>Password File</title>
+ <para>
+ TODO
+ </para>
- <section><title>Password File</title></section>
- <section><title>LDAP</title>
+ </section>
+
+ <section>
+ <title>LDAP</title>
<example>
- <title>Configuring a LDAP authentication</title>
+ <title>Configuring LDAP authentication</title>
<programlisting><![CDATA[
<security>
<simple-ldap-auth-manager>
@@ -82,8 +49,8 @@
<search-context>dc=example\,dc=com</search-context>
<search-filter>(uid={0})</search-filter>
</simple-ldap-auth-manager>
-</security>]]>
- </programlisting>
+ ...
+</security>]]></programlisting>
</example>
<para>
@@ -111,9 +78,10 @@
By default com.sun.jndi.ldap.LdapCtxFactory is used to create the context, however this can be
overridden by specifying <ldap-context-factory> in the configuration.
</para>
-
</section>
- <section><title>Kerberos</title>
+
+ <section>
+ <title>Kerberos</title>
<para>
Kereberos Authentication is configured using the <kerberos-auth-manager> element within
@@ -128,30 +96,30 @@
</para>
<example>
- <title>Configuring a Kerberos authentication</title>
+ <title>Configuring Kerberos authentication</title>
<programlisting><![CDATA[
<security>
- <pd-auth-manager>
- <principal-database>
- <class>org.apache.qpid.server.security.auth.database.PlainPasswordFilePrincipalDatabase</class>
- <attributes>
- <attribute>
- <name>passwordFile</name>
- <value>${conf}/passwd</value>
- </attribute>
- </attributes>
- </principal-database>
- </pd-auth-manager>
- <kerberos-auth-manager></kerberos-auth-manager>
- <default-auth-manager>PrincipalDatabaseAuthenticationManager</default-auth-manager>
- <port-mappings>
- <port-mapping>
- <port>5672</port>
- <auth-manager>KerberosAuthenticationManager</auth-manager>
- </port-mapping>
- </port-mappings>
-</security>]]>
- </programlisting>
+ <pd-auth-manager>
+ <principal-database>
+ <class>org.apache.qpid.server.security.auth.database.PlainPasswordFilePrincipalDatabase</class>
+ <attributes>
+ <attribute>
+ <name>passwordFile</name>
+ <value>${conf}/passwd</value>
+ </attribute>
+ </attributes>
+ </principal-database>
+ </pd-auth-manager>
+ <kerberos-auth-manager/>
+ <default-auth-manager>PrincipalDatabaseAuthenticationManager</default-auth-manager>
+ <port-mappings>
+ <port-mapping>
+ <port>5672</port>
+ <auth-manager>KerberosAuthenticationManager</auth-manager>
+ </port-mapping>
+ </port-mappings>
+ ...
+</security>]]></programlisting>
</example>
<para>
@@ -177,8 +145,7 @@ com.sun.security.jgss.accept {
kdc="kerberos.example.com"
keyTab="/path/to/keytab-file"
principal="<name>/<host>";
-};]]>
- </programlisting>
+};]]></programlisting>
<para>
Where realm, kdc, keyTab and principal should obviously be set correctly for the environment
@@ -191,7 +158,137 @@ com.sun.security.jgss.accept {
Jurisdiction Policy Files" appropriate for your JDK in order to get Kerberos support working.
</para>
</section>
- <section><title>SSL Client Certificates</title></section>
- <section><title>Anonymous</title></section>
+
+ <section id="ExternalAuthManager">
+ <title>External (SSL Client Certificates)</title>
+
+ <para>
+ When <link linkend="SSL-Truststore-ClientCertificate"> requiring SSL Client Certificates</link> be
+ presented the ExternalAuthenticationManager can be used, such that the user is authenticated based on
+ trust of their certificate alone, and the X500Principal from the SSL session is then used as the username
+ for the connection, instead of also requiring the user to present a valid username and password.
+ </para>
+
+ <para>
+ The ExternalAuthenticationManager may be enabled by adding an empty <external-auth-manager> element to
+ the <security> section, as shown below. When referencing it from the default-auth-manager or port-mapping
+ sections, its name is ExternalAuthenticationManager.
+ </para>
+
+ <para>
+ <emphasis role="bold">Note:</emphasis> The ExternalAuthenticationManager should typically only be used on the
+ AMQP ports, in conjunction with <link linkend="SSL-Truststore-ClientCertificate">SSL client certificate
+ authentication</link>. It is not intended for other uses such as the JMX management port and will treat any
+ non-sasl authentication processes on these ports as successfull with the given username. As such you should
+ <link linkend="MultipleAuthProviders">include another Authentication Manager for use on non-AMQP ports</link>,
+ as is done in the example below. Perhaps the only exception to this would be where the broker is embedded in a
+ container that is itself externally protecting the HTTP interface and then providing the remote users name.
+ </para>
+
+ <example>
+ <title>Configuring external authentication (SSL client auth)</title>
+ <programlisting><![CDATA[
+<security>
+ <pd-auth-manager>
+ <principal-database>
+ <class>org.apache.qpid.server.security.auth.database.PlainPasswordFilePrincipalDatabase</class>
+ <attributes>
+ <attribute>
+ <name>passwordFile</name>
+ <value>${conf}/passwd</value>
+ </attribute>
+ </attributes>
+ </principal-database>
+ </pd-auth-manager>
+ <external-auth-manager/>
+ <default-auth-manager>PrincipalDatabaseAuthenticationManager</default-auth-manager>
+ <port-mappings>
+ <port-mapping>
+ <port>5672</port>
+ <auth-manager>ExternalAuthenticationManager</auth-manager>
+ </port-mapping>
+ </port-mappings>
+ ...
+</security>]]></programlisting>
+ </example>
+
+ </section>
+
+ <section id="AnonymousAuthManager">
+ <title>Anonymous</title>
+
+ <para>
+ The AnonymousAuthenticationManager will allow users to connect with or without credentials and result
+ in their identification on the broker as the user ANONYMOUS. It may be enabled by adding an empty
+ anonymous-auth-manager element to the security configuration section, as shown below.
+ </para>
+
+ <example>
+ <title>Configuring anonymous authentication</title>
+
+ <programlisting><![CDATA[
+<security>
+ <anonymous-auth-manager/>
+ ...
+</security>]]></programlisting>
+ </example>
+
+ <para>
+ When referencing it from the default-auth-manager or port-mapping sections, its name is
+ AnonymousAuthenticationManager.
+ </para>
+ </section>
+
+ <section id="MultipleAuthProviders">
+ <title>Configuring multiple Authentication Providers</title>
+ <para>
+ Different managers may be used on different ports. Each manager has its own configuration element,
+ the presence of which within the <security> section denotes the use of that authentication
+ provider. Where only one such manager is configured, it will be used on all ports (including JMX
+ and HTTP). Where more than one authentication manager is configured the configuration must define
+ which is the "default", and (if required) the mapping of non-default authentication managers to
+ other ports.
+ </para>
+ <para>
+ The following configuration sets up three authentication managers, using a password file as the
+ default (e.g. for the JMX and HTTP ports), Kerberos on port 5672 (the regular AMQP port) and Anonymous
+ on port 5673 (e.g a second AMQP port the broker could have been configured with).
+ </para>
+
+ <example>
+ <title>Configuring multiple (per-port) authentication schemes</title>
+ <programlisting><![CDATA[
+<security>
+ <pd-auth-manager>
+ <principal-database>
+ <class>org.apache.qpid.server.security.auth.database.PlainPasswordFilePrincipalDatabase</class>
+ <attributes>
+ <attribute>
+ <name>passwordFile</name>
+ <value>${conf}/passwd</value>
+ </attribute>
+ </attributes>
+ </principal-database>
+ </pd-auth-manager>
+ <kerberos-auth-manager>
+ <auth-name>sib</auth-name>
+ </kerberos-auth-manager>
+ <anonymous-auth-manager/>
+ <default-auth-manager>PrincipalDatabaseAuthenticationManager</default-auth-manager>
+ <port-mappings>
+ <port-mapping>
+ <port>5672</port>
+ <auth-manager>KerberosAuthenticationManager</auth-manager>
+ </port-mapping>
+ <port-mapping>
+ <port>5673</port>
+ <auth-manager>AnonymousAuthenticationManager</auth-manager>
+ </port-mapping>
+ </port-mappings>
+ ...
+</security>]]></programlisting>
+ </example>
+ </section>
+
</section>
Modified: qpid/trunk/qpid/doc/book/src/java-broker/Java-Broker-Security-SSL.xml
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/doc/book/src/java-broker/Java-Broker-Security-SSL.xml?rev=1405636&r1=1405635&r2=1405636&view=diff
==============================================================================
--- qpid/trunk/qpid/doc/book/src/java-broker/Java-Broker-Security-SSL.xml (original)
+++ qpid/trunk/qpid/doc/book/src/java-broker/Java-Broker-Security-SSL.xml Sun Nov 4 21:03:36 2012
@@ -21,6 +21,85 @@
-->
<section id="Java-Broker-Security-SSL">
-<title>SSL</title>
+ <title>SSL</title>
+ <para>
+ This section will show how to use SSL to enable secure
+ connections between an AMQP message client and the broker.
+ </para>
+ <section role="h2" id="SSL-Keystore">
+ <title>Keystore Configuration</title>
+ <para>
+ The broker configuration file (config.xml) needs to be updated to include the required SSL keystore
+ configuration, an example of which can be found below.
+ </para>
+
+ <example>
+ <title>Configuring an SSL Keystore</title>
+ <programlisting><![CDATA[
+<connector>
+ ...
+ <ssl>
+ <enabled>true</enabled>
+ <port>5671</port>
+ <sslOnly>false</sslOnly>
+ <keyStorePath>/path/to/keystore.ks</keyStorePath>
+ <keyStorePassword>keystorepass</keyStorePassword>
+ <certAlias>alias<certAlias>
+ </ssl>
+ ...
+<connector>]]></programlisting>
+ </example>
+
+ <para>
+ The certAlias element is an optional way of specifying which certificate the broker should use
+ if the keystore contains multiple entries.
+ </para>
+
+ <para>
+ The sslOnly element controls whether the broker will <emphasis role="bold">only</emphasis> bind
+ the configured SSL port(s) or will also bind the non-SSL port(s). Setting sslOnly to true will
+ disable the non-SSL ports.
+ </para>
+ </section>
+
+ <section role="h2" id="SSL-Truststore-ClientCertificate">
+ <title>Truststore / Client Certificate Authentication</title>
+ <para>
+ The SSL trustore and related Client Certificate Authentication behaviour can be configured with
+ additional configuration as shown in the example below, in which the broker requires client
+ certificate authentication.
+ </para>
+
+ <example>
+ <title>Configuring an SSL Truststore and client auth</title>
+ <programlisting><![CDATA[
+<connector>
+ ...
+ <ssl>
+ ...
+ <trustStorePath>/path/to/truststore.ks</trustStorePath>
+ <trustStorePassword>truststorepass</trustStorePassword>
+ <needClientAuth>true</needClientAuth>
+ <wantClientAuth>false</wantClientAuth>
+ ...
+ </ssl>
+ ...
+<connector>]]></programlisting>
+ </example>
+
+ <para>
+ The needClientAuth and wantClientAuth elements allow control of whether the client must present an
+ SSL certificate. Only one of these elements is needed but both may be used at the same time.
+ A socket's client authentication setting is one of three states: required (needClientAuth = true),
+ requested (wantClientAuth = true), or none desired (both false, the default). If both elements are
+ set to true, needClientAuth takes precedence.
+ </para>
+
+ <para>
+ When using Client Certificate Authentication it may be desirable to use the External Authentication
+ Manager, for details see <xref linkend="ExternalAuthManager"></xref>
+ </para>
+
+ </section>
</section>
Modified: qpid/trunk/qpid/java/common/src/main/java/org/apache/qpid/transport/network/io/IoNetworkTransport.java
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/java/common/src/main/java/org/apache/qpid/transport/network/io/IoNetworkTransport.java?rev=1405636&r1=1405635&r2=1405636&view=diff
==============================================================================
--- qpid/trunk/qpid/java/common/src/main/java/org/apache/qpid/transport/network/io/IoNetworkTransport.java (original)
+++ qpid/trunk/qpid/java/common/src/main/java/org/apache/qpid/transport/network/io/IoNetworkTransport.java Sun Nov 4 21:03:36 2012
@@ -130,7 +130,6 @@ public class IoNetworkTransport implemen
public void accept(NetworkTransportConfiguration config, ProtocolEngineFactory factory, SSLContext sslContext)
{
-
try
{
_acceptor = new AcceptingThread(config, factory, sslContext);
@@ -141,8 +140,6 @@ public class IoNetworkTransport implemen
{
throw new TransportException("Unable to start server socket", e);
}
-
-
}
private class AcceptingThread extends Thread
@@ -155,8 +152,7 @@ public class IoNetworkTransport implemen
private AcceptingThread(NetworkTransportConfiguration config,
ProtocolEngineFactory factory,
- SSLContext sslContext)
- throws IOException
+ SSLContext sslContext) throws IOException
{
_config = config;
_factory = factory;
@@ -172,15 +168,19 @@ public class IoNetworkTransport implemen
{
SSLServerSocketFactory socketFactory = _sslContext.getServerSocketFactory();
_serverSocket = socketFactory.createServerSocket();
- ((SSLServerSocket)_serverSocket).setNeedClientAuth(config.needClientAuth());
- ((SSLServerSocket)_serverSocket).setWantClientAuth(config.wantClientAuth());
+ if(config.needClientAuth())
+ {
+ ((SSLServerSocket)_serverSocket).setNeedClientAuth(true);
+ }
+ else if(config.wantClientAuth())
+ {
+ ((SSLServerSocket)_serverSocket).setWantClientAuth(true);
+ }
}
_serverSocket.setReuseAddress(true);
_serverSocket.bind(address);
-
-
}
@@ -224,7 +224,6 @@ public class IoNetworkTransport implemen
socket.setSendBufferSize(sendBufferSize);
socket.setReceiveBufferSize(receiveBufferSize);
-
ProtocolEngine engine = _factory.newProtocolEngine();
NetworkConnection connection = new IoNetworkConnection(socket, engine, sendBufferSize, receiveBufferSize, TIMEOUT);
Modified: qpid/trunk/qpid/java/systests/src/main/java/org/apache/qpid/client/ssl/SSLTest.java
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/java/systests/src/main/java/org/apache/qpid/client/ssl/SSLTest.java?rev=1405636&r1=1405635&r2=1405636&view=diff
==============================================================================
--- qpid/trunk/qpid/java/systests/src/main/java/org/apache/qpid/client/ssl/SSLTest.java (original)
+++ qpid/trunk/qpid/java/systests/src/main/java/org/apache/qpid/client/ssl/SSLTest.java Sun Nov 4 21:03:36 2012
@@ -25,11 +25,13 @@ import static org.apache.qpid.test.utils
import static org.apache.qpid.test.utils.TestSSLConstants.TRUSTSTORE;
import static org.apache.qpid.test.utils.TestSSLConstants.TRUSTSTORE_PASSWORD;
+import org.apache.commons.configuration.ConfigurationException;
import org.apache.qpid.client.AMQConnectionURL;
import org.apache.qpid.client.AMQTestConnection_0_10;
import org.apache.qpid.test.utils.QpidBrokerTestCase;
import javax.jms.Connection;
+import javax.jms.JMSException;
import javax.jms.Session;
import java.io.ByteArrayOutputStream;
import java.io.PrintStream;
@@ -42,33 +44,24 @@ public class SSLTest extends QpidBrokerT
@Override
protected void setUp() throws Exception
{
- if(isJavaBroker())
- {
- setTestClientSystemProperty("profile.use_ssl", "true");
- setConfigurationProperty("connector.ssl.enabled", "true");
- setConfigurationProperty("connector.ssl.sslOnly", "true");
- setConfigurationProperty("connector.ssl.wantClientAuth", "true");
- }
-
- // set the ssl system properties
- setSystemProperty("javax.net.ssl.keyStore", KEYSTORE);
- setSystemProperty("javax.net.ssl.keyStorePassword", KEYSTORE_PASSWORD);
- setSystemProperty("javax.net.ssl.trustStore", TRUSTSTORE);
- setSystemProperty("javax.net.ssl.trustStorePassword", TRUSTSTORE_PASSWORD);
setSystemProperty("javax.net.debug", "ssl");
- super.setUp();
+
+ setSslStoreSystemProperties();
+
+ //We dont call super.setUp, the tests start the broker after deciding
+ //whether to run and then configuring it appropriately
}
public void testCreateSSLConnectionUsingConnectionURLParams() throws Exception
{
- if (Boolean.getBoolean("profile.use_ssl"))
+ if (shouldPerformTest())
{
- // Clear the ssl system properties
- setSystemProperty("javax.net.ssl.keyStore", null);
- setSystemProperty("javax.net.ssl.keyStorePassword", null);
- setSystemProperty("javax.net.ssl.trustStore", null);
- setSystemProperty("javax.net.ssl.trustStorePassword", null);
+ clearSslStoreSystemProperties();
+ //Start the broker (NEEDing client certificate authentication)
+ configureJavaBrokerIfNecessary(true, true, true, false);
+ super.setUp();
+
String url = "amqp://guest:guest@test/?brokerlist='tcp://localhost:%s" +
"?ssl='true'&ssl_verify_hostname='true'" +
"&key_store='%s'&key_store_password='%s'" +
@@ -82,13 +75,16 @@ public class SSLTest extends QpidBrokerT
assertNotNull("connection should be successful", con);
Session ssn = con.createSession(false,Session.AUTO_ACKNOWLEDGE);
assertNotNull("create session should be successful", ssn);
- }
+ }
}
public void testCreateSSLConnectionUsingSystemProperties() throws Exception
{
- if (Boolean.getBoolean("profile.use_ssl"))
+ if (shouldPerformTest())
{
+ //Start the broker (NEEDing client certificate authentication)
+ configureJavaBrokerIfNecessary(true, true, true, false);
+ super.setUp();
String url = "amqp://guest:guest@test/?brokerlist='tcp://localhost:%s?ssl='true''";
@@ -103,8 +99,12 @@ public class SSLTest extends QpidBrokerT
public void testMultipleCertsInSingleStore() throws Exception
{
- if (Boolean.getBoolean("profile.use_ssl"))
+ if (shouldPerformTest())
{
+ //Start the broker (NEEDing client certificate authentication)
+ configureJavaBrokerIfNecessary(true, true, true, false);
+ super.setUp();
+
String url = "amqp://guest:guest@test/?brokerlist='tcp://localhost:" +
QpidBrokerTestCase.DEFAULT_SSL_PORT +
"?ssl='true'&ssl_cert_alias='" + CERT_ALIAS_APP1 + "''";
@@ -127,10 +127,14 @@ public class SSLTest extends QpidBrokerT
}
}
- public void testVerifyHostNameWithIncorrectHostname()
+ public void testVerifyHostNameWithIncorrectHostname() throws Exception
{
- if (Boolean.getBoolean("profile.use_ssl"))
+ if (shouldPerformTest())
{
+ //Start the broker (WANTing client certificate authentication)
+ configureJavaBrokerIfNecessary(true, true, false, true);
+ super.setUp();
+
String url = "amqp://guest:guest@test/?brokerlist='tcp://127.0.0.1:" +
QpidBrokerTestCase.DEFAULT_SSL_PORT +
"?ssl='true'&ssl_verify_hostname='true''";
@@ -142,19 +146,27 @@ public class SSLTest extends QpidBrokerT
}
catch (Exception e)
{
- ByteArrayOutputStream bout = new ByteArrayOutputStream();
- e.printStackTrace(new PrintStream(bout));
- String strace = bout.toString();
- assertTrue("Correct exception not thrown",strace.contains("SSL hostname verification failed"));
+ verifyExceptionCausesContains(e, "SSL hostname verification failed");
}
-
}
}
+
+ private void verifyExceptionCausesContains(Exception e, String expectedString)
+ {
+ ByteArrayOutputStream bout = new ByteArrayOutputStream();
+ e.printStackTrace(new PrintStream(bout));
+ String strace = bout.toString();
+ assertTrue("Correct exception not thrown", strace.contains(expectedString));
+ }
public void testVerifyLocalHost() throws Exception
{
- if (Boolean.getBoolean("profile.use_ssl"))
+ if (shouldPerformTest())
{
+ //Start the broker (WANTing client certificate authentication)
+ configureJavaBrokerIfNecessary(true, true, false, true);
+ super.setUp();
+
String url = "amqp://guest:guest@test/?brokerlist='tcp://localhost:" +
QpidBrokerTestCase.DEFAULT_SSL_PORT +
"?ssl='true'&ssl_verify_hostname='true''";
@@ -166,8 +178,12 @@ public class SSLTest extends QpidBrokerT
public void testVerifyLocalHostLocalDomain() throws Exception
{
- if (Boolean.getBoolean("profile.use_ssl"))
+ if (shouldPerformTest())
{
+ //Start the broker (WANTing client certificate authentication)
+ configureJavaBrokerIfNecessary(true, true, false, true);
+ super.setUp();
+
String url = "amqp://guest:guest@test/?brokerlist='tcp://localhost.localdomain:" +
QpidBrokerTestCase.DEFAULT_SSL_PORT +
"?ssl='true'&ssl_verify_hostname='true''";
@@ -179,13 +195,14 @@ public class SSLTest extends QpidBrokerT
public void testCreateSSLConnectionUsingConnectionURLParamsTrustStoreOnly() throws Exception
{
- if (Boolean.getBoolean("profile.use_ssl"))
+ if (shouldPerformTest())
{
- // Clear the ssl system properties
- setSystemProperty("javax.net.ssl.keyStore", null);
- setSystemProperty("javax.net.ssl.keyStorePassword", null);
- setSystemProperty("javax.net.ssl.trustStore", null);
- setSystemProperty("javax.net.ssl.trustStorePassword", null);
+ clearSslStoreSystemProperties();
+
+ //Start the broker (WANTing client certificate authentication)
+ configureJavaBrokerIfNecessary(true, true, false, true);
+ super.setUp();
+
String url = "amqp://guest:guest@test/?brokerlist='tcp://localhost:%s" +
"?ssl='true'&ssl_verify_hostname='true'" +
@@ -200,4 +217,120 @@ public class SSLTest extends QpidBrokerT
assertNotNull("create session should be successful", ssn);
}
}
+
+ /**
+ * Verifies that when the broker is configured to NEED client certificates,
+ * a client which doesn't supply one fails to connect.
+ */
+ public void testClientCertMissingWhilstNeeding() throws Exception
+ {
+ missingClientCertWhileNeedingOrWantingTestImpl(true, false, false);
+ }
+
+ /**
+ * Verifies that when the broker is configured to WANT client certificates,
+ * a client which doesn't supply one succeeds in connecting.
+ */
+ public void testClientCertMissingWhilstWanting() throws Exception
+ {
+ missingClientCertWhileNeedingOrWantingTestImpl(false, true, true);
+ }
+
+ /**
+ * Verifies that when the broker is configured to WANT and NEED client certificates
+ * that a client which doesn't supply one fails to connect.
+ */
+ public void testClientCertMissingWhilstWantingAndNeeding() throws Exception
+ {
+ missingClientCertWhileNeedingOrWantingTestImpl(true, true, false);
+ }
+
+ private void missingClientCertWhileNeedingOrWantingTestImpl(boolean needClientCerts,
+ boolean wantClientCerts, boolean shouldSucceed) throws Exception
+ {
+ if (shouldPerformTest())
+ {
+ clearSslStoreSystemProperties();
+
+ //Start the broker
+ configureJavaBrokerIfNecessary(true, true, needClientCerts, wantClientCerts);
+ super.setUp();
+
+ String url = "amqp://guest:guest@test/?brokerlist='tcp://localhost:%s" +
+ "?ssl='true'&trust_store='%s'&trust_store_password='%s''";
+
+ url = String.format(url,QpidBrokerTestCase.DEFAULT_SSL_PORT,TRUSTSTORE,TRUSTSTORE_PASSWORD);
+ try
+ {
+ Connection con = getConnection(new AMQConnectionURL(url));
+ if(!shouldSucceed)
+ {
+ fail("Connection succeeded, expected exception was not thrown");
+ }
+ else
+ {
+ //Use the connection to verify it works
+ con.createSession(true, Session.SESSION_TRANSACTED);
+ }
+ }
+ catch(JMSException e)
+ {
+ if(shouldSucceed)
+ {
+ _logger.error("Caught unexpected exception",e);
+ fail("Connection failed, unexpected exception thrown");
+ }
+ else
+ {
+ //expected
+ verifyExceptionCausesContains(e, "Caused by: javax.net.ssl.SSLException:");
+ }
+ }
+ }
+ }
+
+ private boolean shouldPerformTest()
+ {
+ // We run the SSL tests on all the Java broker profiles
+ if(isJavaBroker())
+ {
+ setTestClientSystemProperty(PROFILE_USE_SSL, "true");
+ }
+
+ return Boolean.getBoolean(PROFILE_USE_SSL);
+ }
+
+ private void configureJavaBrokerIfNecessary(boolean sslEnabled, boolean sslOnly, boolean needClientAuth, boolean wantClientAuth) throws ConfigurationException
+ {
+ if(isJavaBroker())
+ {
+ setConfigurationProperty("connector.ssl.enabled", String.valueOf(sslEnabled));
+ setConfigurationProperty("connector.ssl.sslOnly", String.valueOf(sslOnly));
+ setConfigurationProperty("connector.ssl.needClientAuth", String.valueOf(needClientAuth));
+ setConfigurationProperty("connector.ssl.wantClientAuth", String.valueOf(wantClientAuth));
+
+ if(needClientAuth || wantClientAuth)
+ {
+ //TODO: make a broker trust store?
+ setConfigurationProperty("connector.ssl.trustStorePath", TRUSTSTORE);
+ setConfigurationProperty("connector.ssl.trustStorePassword", TRUSTSTORE_PASSWORD);
+ }
+ }
+ }
+
+ private void setSslStoreSystemProperties()
+ {
+ setSystemProperty("javax.net.ssl.keyStore", KEYSTORE);
+ setSystemProperty("javax.net.ssl.keyStorePassword", KEYSTORE_PASSWORD);
+ setSystemProperty("javax.net.ssl.trustStore", TRUSTSTORE);
+ setSystemProperty("javax.net.ssl.trustStorePassword", TRUSTSTORE_PASSWORD);
+ }
+
+ private void clearSslStoreSystemProperties()
+ {
+ setSystemProperty("javax.net.ssl.keyStore", null);
+ setSystemProperty("javax.net.ssl.keyStorePassword", null);
+ setSystemProperty("javax.net.ssl.trustStore", null);
+ setSystemProperty("javax.net.ssl.trustStorePassword", null);
+ }
}
Added: qpid/trunk/qpid/java/systests/src/main/java/org/apache/qpid/server/security/auth/manager/ExternalAuthenticationTest.java
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/java/systests/src/main/java/org/apache/qpid/server/security/auth/manager/ExternalAuthenticationTest.java?rev=1405636&view=auto
==============================================================================
--- qpid/trunk/qpid/java/systests/src/main/java/org/apache/qpid/server/security/auth/manager/ExternalAuthenticationTest.java (added)
+++ qpid/trunk/qpid/java/systests/src/main/java/org/apache/qpid/server/security/auth/manager/ExternalAuthenticationTest.java Sun Nov 4 21:03:36 2012
@@ -0,0 +1,171 @@
+/*
+ * 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.qpid.server.security.auth.manager;
+
+import javax.jms.Connection;
+import javax.jms.JMSException;
+
+import org.apache.commons.configuration.ConfigurationException;
+import org.apache.qpid.client.AMQConnectionURL;
+import org.apache.qpid.test.utils.QpidBrokerTestCase;
+
+public class ExternalAuthenticationTest extends QpidBrokerTestCase
+{
+ private static final String EXTERNAL_AUTH_MANAGER = ExternalAuthenticationManager.class.getSimpleName();
+ private static final String KEYSTORE = "test-profiles/test_resources/ssl/java_client_keystore.jks";
+ private static final String KEYSTORE_PASSWORD = "password";
+ private static final String TRUSTSTORE = "test-profiles/test_resources/ssl/java_client_truststore.jks";
+ private static final String TRUSTSTORE_PASSWORD = "password";
+
+ @Override
+ protected void setUp() throws Exception
+ {
+ // not calling super.setUp() to avoid broker start-up
+ }
+
+ /**
+ * Tests that when EXTERNAL authentication is used on the SSL port, clients presenting certificates are able to connect.
+ * Also, checks that default authentication manager PrincipalDatabaseAuthenticationManager is used on non SSL port.
+ */
+ public void testExternalAuthenticationManagerOnSSLPort() throws Exception
+ {
+ setCommonBrokerSSLProperties(true);
+ setConfigurationProperty("security.port-mappings.port-mapping.port", String.valueOf(QpidBrokerTestCase.DEFAULT_SSL_PORT));
+ setConfigurationProperty("security.port-mappings.port-mapping.auth-manager", EXTERNAL_AUTH_MANAGER);
+ setConfigurationProperty("security.default-auth-manager", PrincipalDatabaseAuthenticationManager.class.getSimpleName());
+ super.setUp();
+
+ setClientKeystoreProperties();
+ setClientTrustoreProperties();
+
+ try
+ {
+ getExternalSSLConnection(false);
+ }
+ catch (JMSException e)
+ {
+ fail("Should be able to create a connection to the SSL port: " + e.getMessage());
+ }
+
+ try
+ {
+ getConnection();
+ }
+ catch (JMSException e)
+ {
+ fail("Should be able to create a connection with credentials to the standard port: " + e.getMessage());
+ }
+
+ }
+
+ /**
+ * Tests that when EXTERNAL authentication manager is set as the default, clients presenting certificates are able to connect.
+ * Also, checks a client with valid username and password but not using ssl is unable to connect to the non SSL port.
+ */
+ public void testExternalAuthenticationManagerAsDefault() throws Exception
+ {
+ setCommonBrokerSSLProperties(true);
+ setConfigurationProperty("security.default-auth-manager", EXTERNAL_AUTH_MANAGER);
+ super.setUp();
+
+ setClientKeystoreProperties();
+ setClientTrustoreProperties();
+
+ try
+ {
+ getConnection();
+ fail("Connection should not succeed");
+ }
+ catch (JMSException e)
+ {
+ // pass
+ }
+
+ try
+ {
+ getExternalSSLConnection(false);
+ }
+ catch (JMSException e)
+ {
+ fail("Should be able to create a connection to the SSL port. " + e.getMessage());
+ }
+ }
+
+ /**
+ * Tests that when EXTERNAL authentication manager is set as the default, clients without certificates are unable to connect to the SSL port
+ * even with valid username and password.
+ */
+ public void testExternalAuthenticationManagerWithoutClientKeyStore() throws Exception
+ {
+ setCommonBrokerSSLProperties(false);
+ setConfigurationProperty("security.default-auth-manager", EXTERNAL_AUTH_MANAGER);
+ super.setUp();
+
+ setClientTrustoreProperties();
+
+ try
+ {
+ getExternalSSLConnection(true);
+ fail("Connection should not succeed");
+ }
+ catch (JMSException e)
+ {
+ // pass
+ }
+ }
+
+ private Connection getExternalSSLConnection(boolean includeUserNameAndPassword) throws Exception
+ {
+ String url = "amqp://%s@test/?brokerlist='tcp://localhost:%s?ssl='true'&sasl_mechs='EXTERNAL''";
+ if (includeUserNameAndPassword)
+ {
+ url = String.format(url, "guest:guest", String.valueOf(QpidBrokerTestCase.DEFAULT_SSL_PORT));
+ }
+ else
+ {
+ url = String.format(url, ":", String.valueOf(QpidBrokerTestCase.DEFAULT_SSL_PORT));
+ }
+ return getConnection(new AMQConnectionURL(url));
+ }
+
+ private void setCommonBrokerSSLProperties(boolean needClientAuth) throws ConfigurationException
+ {
+ setConfigurationProperty("connector.ssl.enabled", "true");
+ setConfigurationProperty("connector.ssl.sslOnly", "false");
+ setConfigurationProperty("connector.ssl.trustStorePath", TRUSTSTORE);
+ setConfigurationProperty("connector.ssl.trustStorePassword", TRUSTSTORE_PASSWORD);
+ setConfigurationProperty("connector.ssl.needClientAuth", String.valueOf(needClientAuth));
+ setConfigurationProperty("security.external-auth-manager", "");
+ }
+
+ private void setClientKeystoreProperties()
+ {
+ setSystemProperty("javax.net.ssl.keyStore", KEYSTORE);
+ setSystemProperty("javax.net.ssl.keyStorePassword", KEYSTORE_PASSWORD);
+ }
+
+ private void setClientTrustoreProperties()
+ {
+ setSystemProperty("javax.net.ssl.trustStore", TRUSTSTORE);
+ setSystemProperty("javax.net.ssl.trustStorePassword", TRUSTSTORE_PASSWORD);
+ setSystemProperty("javax.net.debug", "ssl");
+ }
+}
Modified: qpid/trunk/qpid/java/systests/src/main/java/org/apache/qpid/test/utils/QpidBrokerTestCase.java
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/java/systests/src/main/java/org/apache/qpid/test/utils/QpidBrokerTestCase.java?rev=1405636&r1=1405635&r2=1405636&view=diff
==============================================================================
--- qpid/trunk/qpid/java/systests/src/main/java/org/apache/qpid/test/utils/QpidBrokerTestCase.java (original)
+++ qpid/trunk/qpid/java/systests/src/main/java/org/apache/qpid/test/utils/QpidBrokerTestCase.java Sun Nov 4 21:03:36 2012
@@ -129,6 +129,7 @@ public class QpidBrokerTestCase extends
private static final String BROKER_PERSITENT = "broker.persistent";
public static final String BROKER_PROTOCOL_EXCLUDES = "broker.protocol.excludes";
public static final String BROKER_PROTOCOL_INCLUDES = "broker.protocol.includes";
+ public static final String PROFILE_USE_SSL = "profile.use_ssl";
// values
protected static final String JAVA = "java";
@@ -1066,7 +1067,7 @@ public class QpidBrokerTestCase extends
_logger.info("get ConnectionFactory");
if (_connectionFactory == null)
{
- if (Boolean.getBoolean("profile.use_ssl"))
+ if (Boolean.getBoolean(PROFILE_USE_SSL))
{
_connectionFactory = getConnectionFactory("default.ssl");
}
@@ -1356,11 +1357,6 @@ public class QpidBrokerTestCase extends
_messageSize = byteSize;
}
- public ConnectionURL getConnectionURL() throws NamingException
- {
- return getConnectionFactory().getConnectionURL();
- }
-
public BrokerDetails getBroker()
{
try
Modified: qpid/trunk/qpid/java/test-profiles/CPPExcludes
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/java/test-profiles/CPPExcludes?rev=1405636&r1=1405635&r2=1405636&view=diff
==============================================================================
--- qpid/trunk/qpid/java/test-profiles/CPPExcludes (original)
+++ qpid/trunk/qpid/java/test-profiles/CPPExcludes Sun Nov 4 21:03:36 2012
@@ -178,3 +178,6 @@ org.apache.qpid.systest.rest.acl.*
// Exclude failover tests requiring virtual host functionality
org.apache.qpid.client.failover.MultipleBrokersFailoverTest#*
+
+// Uses Java broker specific configuration
+org.apache.qpid.client.ssl.SSLTest#testClientCertMissingWhilstWanting
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org