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 2013/04/01 03:36:18 UTC
svn commit: r1463074 - in /qpid/trunk/qpid/java/broker/src:
main/java/org/apache/qpid/server/security/auth/manager/
main/java/org/apache/qpid/server/security/auth/sasl/external/
test/java/org/apache/qpid/server/security/auth/manager/
Author: robbie
Date: Mon Apr 1 01:36:18 2013
New Revision: 1463074
URL: http://svn.apache.org/r1463074
Log:
QPID-4676: change External auth provider to create usernames of the form <CN>@<DC1>.<DC2>....<DCN> by default
- Allows for use of SSL Client Authentication in manner more consistent with the C++ broker
- Adds 'useFullDN' attribute to the auth provider to allow enabling use of the old behaviour
Added:
qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/ExternalAuthenticationProviderAttributeDescriptions.properties
Modified:
qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/ExternalAuthenticationManager.java
qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/ExternalAuthenticationManagerFactory.java
qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/external/ExternalSaslServer.java
qpid/trunk/qpid/java/broker/src/test/java/org/apache/qpid/server/security/auth/manager/ExternalAuthenticationManagerTest.java
Modified: qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/ExternalAuthenticationManager.java
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/ExternalAuthenticationManager.java?rev=1463074&r1=1463073&r2=1463074&view=diff
==============================================================================
--- qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/ExternalAuthenticationManager.java (original)
+++ qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/ExternalAuthenticationManager.java Mon Apr 1 01:36:18 2013
@@ -31,8 +31,11 @@ public class ExternalAuthenticationManag
{
private static final String EXTERNAL = "EXTERNAL";
- ExternalAuthenticationManager()
+ private boolean _useFullDN = false;
+
+ ExternalAuthenticationManager(boolean useFullDN)
{
+ _useFullDN = useFullDN;
}
@Override
@@ -52,7 +55,7 @@ public class ExternalAuthenticationManag
{
if(EXTERNAL.equals(mechanism))
{
- return new ExternalSaslServer(externalPrincipal);
+ return new ExternalSaslServer(externalPrincipal, _useFullDN);
}
else
{
Modified: qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/ExternalAuthenticationManagerFactory.java
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/ExternalAuthenticationManagerFactory.java?rev=1463074&r1=1463073&r2=1463074&view=diff
==============================================================================
--- qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/ExternalAuthenticationManagerFactory.java (original)
+++ qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/ExternalAuthenticationManagerFactory.java Mon Apr 1 01:36:18 2013
@@ -19,22 +19,32 @@
*/
package org.apache.qpid.server.security.auth.manager;
+import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Map;
import org.apache.qpid.server.plugin.AuthenticationManagerFactory;
+import org.apache.qpid.server.util.ResourceBundleLoader;
public class ExternalAuthenticationManagerFactory implements AuthenticationManagerFactory
{
+ public static final String RESOURCE_BUNDLE = "org.apache.qpid.server.security.auth.manager.ExternalAuthenticationProviderAttributeDescriptions";
public static final String PROVIDER_TYPE = "External";
+ public static final String ATTRIBUTE_USE_FULL_DN = "useFullDN";
+
+ public static final Collection<String> ATTRIBUTES = Collections.<String> unmodifiableList(Arrays.asList(
+ ATTRIBUTE_TYPE,
+ ATTRIBUTE_USE_FULL_DN));
@Override
public AuthenticationManager createInstance(Map<String, Object> attributes)
{
if (attributes != null && PROVIDER_TYPE.equals(attributes.get(ATTRIBUTE_TYPE)))
{
- return new ExternalAuthenticationManager();
+ boolean useFullDN = Boolean.valueOf(String.valueOf(attributes.get(ATTRIBUTE_USE_FULL_DN)));
+
+ return new ExternalAuthenticationManager(useFullDN);
}
return null;
}
@@ -42,7 +52,7 @@ public class ExternalAuthenticationManag
@Override
public Collection<String> getAttributeNames()
{
- return Collections.<String>singletonList(ATTRIBUTE_TYPE);
+ return ATTRIBUTES;
}
@Override
@@ -54,7 +64,7 @@ public class ExternalAuthenticationManag
@Override
public Map<String, String> getAttributeDescriptions()
{
- return null;
+ return ResourceBundleLoader.getResources(RESOURCE_BUNDLE);
}
}
Added: qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/ExternalAuthenticationProviderAttributeDescriptions.properties
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/ExternalAuthenticationProviderAttributeDescriptions.properties?rev=1463074&view=auto
==============================================================================
--- qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/ExternalAuthenticationProviderAttributeDescriptions.properties (added)
+++ qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/ExternalAuthenticationProviderAttributeDescriptions.properties Mon Apr 1 01:36:18 2013
@@ -0,0 +1,19 @@
+#
+# 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.
+
+useFullDN=Use the full DN as the Username
\ No newline at end of file
Modified: qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/external/ExternalSaslServer.java
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/external/ExternalSaslServer.java?rev=1463074&r1=1463073&r2=1463074&view=diff
==============================================================================
--- qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/external/ExternalSaslServer.java (original)
+++ qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/external/ExternalSaslServer.java Mon Apr 1 01:36:18 2013
@@ -19,19 +19,27 @@
package org.apache.qpid.server.security.auth.sasl.external;
import java.security.Principal;
+
+import javax.security.auth.x500.X500Principal;
import javax.security.sasl.SaslException;
import javax.security.sasl.SaslServer;
+import org.apache.log4j.Logger;
+import org.apache.qpid.server.security.auth.UsernamePrincipal;
public class ExternalSaslServer implements SaslServer
{
+ private static final Logger LOGGER = Logger.getLogger(ExternalSaslServer.class);
+
public static final String MECHANISM = "EXTERNAL";
private boolean _complete = false;
private final Principal _externalPrincipal;
+ private boolean _useFullDN = false;
- public ExternalSaslServer(Principal externalPrincipal)
+ public ExternalSaslServer(Principal externalPrincipal, boolean useFullDN)
{
+ _useFullDN = useFullDN;
_externalPrincipal = externalPrincipal;
}
@@ -77,6 +85,83 @@ public class ExternalSaslServer implemen
public Principal getAuthenticatedPrincipal()
{
- return _externalPrincipal;
+ if (_externalPrincipal instanceof X500Principal && !_useFullDN)
+ {
+ // Construct username as <CN>@<DC1>.<DC2>.<DC3>....<DCN>
+
+ String username;
+ String dn = ((X500Principal) _externalPrincipal).getName(X500Principal.RFC2253);
+
+ if(LOGGER.isDebugEnabled())
+ {
+ LOGGER.debug("Parsing username from Principal DN: " + dn);
+ }
+
+ if (dn.contains("CN="))
+ {
+ username = dn.substring(dn.indexOf("CN=") + 3, (dn.indexOf(",", dn.indexOf("CN=")) != -1) ? dn.indexOf(",", dn.indexOf("CN=")) : dn.length());
+
+ if (username.isEmpty())
+ {
+ // CN is empty => Cannot construct username => Authentication failed => return null
+ if(LOGGER.isDebugEnabled())
+ {
+ LOGGER.debug("CN value was empty in Principal name, unable to construct username");
+ }
+ return null;
+ }
+ else
+ {
+ if (dn.contains("DC="))
+ {
+ int start = 0;
+ String dc = "";
+
+ while (dn.indexOf("DC=", start) != -1)
+ {
+ int dcStart = dn.indexOf("DC=", start) + 3;
+ int dcEnd = (dn.indexOf(",", dn.indexOf("DC=", start)) != -1) ? dn.indexOf(",", dn.indexOf("DC=", start)) : dn.length();
+
+ if (dc.isEmpty())
+ {
+ dc = dn.substring(dcStart, dcEnd);
+ }
+ else
+ {
+ dc = dc.concat(".").concat(dn.substring(dcStart, dcEnd));
+ }
+
+ start = dn.indexOf("DC=", start) + 1;
+ }
+
+ username = username.concat("@").concat(dc);
+ }
+ }
+
+ if(LOGGER.isDebugEnabled())
+ {
+ LOGGER.debug("Constructing Principal with username: " + username);
+ }
+ return new UsernamePrincipal(username);
+ }
+ else
+ {
+ // No CN => Cannot construct username => Authentication failed => return null
+ if(LOGGER.isDebugEnabled())
+ {
+ LOGGER.debug("No CN= present in DN, unable to construct username");
+ }
+ return null;
+ }
+ }
+ else
+ {
+ if(LOGGER.isDebugEnabled())
+ {
+ LOGGER.debug("Using external Principal: " + _externalPrincipal);
+ }
+
+ return _externalPrincipal;
+ }
}
}
\ No newline at end of file
Modified: qpid/trunk/qpid/java/broker/src/test/java/org/apache/qpid/server/security/auth/manager/ExternalAuthenticationManagerTest.java
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/java/broker/src/test/java/org/apache/qpid/server/security/auth/manager/ExternalAuthenticationManagerTest.java?rev=1463074&r1=1463073&r2=1463074&view=diff
==============================================================================
--- qpid/trunk/qpid/java/broker/src/test/java/org/apache/qpid/server/security/auth/manager/ExternalAuthenticationManagerTest.java (original)
+++ qpid/trunk/qpid/java/broker/src/test/java/org/apache/qpid/server/security/auth/manager/ExternalAuthenticationManagerTest.java Mon Apr 1 01:36:18 2013
@@ -25,11 +25,13 @@ import javax.security.sasl.SaslException
import javax.security.sasl.SaslServer;
import org.apache.qpid.server.security.auth.AuthenticationResult;
+import org.apache.qpid.server.security.auth.UsernamePrincipal;
import org.apache.qpid.test.utils.QpidTestCase;
public class ExternalAuthenticationManagerTest extends QpidTestCase
{
- private AuthenticationManager _manager = new ExternalAuthenticationManager();
+ private AuthenticationManager _manager = new ExternalAuthenticationManager(false);
+ private AuthenticationManager _managerUsingFullDN = new ExternalAuthenticationManager(true);
public void testGetMechanisms() throws Exception
{
@@ -38,13 +40,23 @@ public class ExternalAuthenticationManag
public void testCreateSaslServer() throws Exception
{
- SaslServer server = _manager.createSaslServer("EXTERNAL", "example.example.com", null);
+ createSaslServerTestImpl(_manager);
+ }
+
+ public void testCreateSaslServerUsingFullDN() throws Exception
+ {
+ createSaslServerTestImpl(_managerUsingFullDN);
+ }
+
+ public void createSaslServerTestImpl(AuthenticationManager manager) throws Exception
+ {
+ SaslServer server = manager.createSaslServer("EXTERNAL", "example.example.com", null);
assertEquals("Sasl Server mechanism name is not as expected", "EXTERNAL", server.getMechanismName());
try
{
- server = _manager.createSaslServer("PLAIN", "example.example.com", null);
+ server = manager.createSaslServer("PLAIN", "example.example.com", null);
fail("Expected creating SaslServer with incorrect mechanism to throw an exception");
}
catch (SaslException e)
@@ -53,12 +65,16 @@ public class ExternalAuthenticationManag
}
}
- public void testAuthenticate() throws Exception
+ /**
+ * Test behaviour of the authentication when the useFullDN attribute is set true
+ * and the username is taken directly as the externally supplied Principal
+ */
+ public void testAuthenticateWithFullDN() throws Exception
{
X500Principal principal = new X500Principal("CN=person, DC=example, DC=com");
- SaslServer saslServer = _manager.createSaslServer("EXTERNAL", "example.example.com", principal);
+ SaslServer saslServer = _managerUsingFullDN.createSaslServer("EXTERNAL", "example.example.com", principal);
- AuthenticationResult result = _manager.authenticate(saslServer, new byte[0]);
+ AuthenticationResult result = _managerUsingFullDN.authenticate(saslServer, new byte[0]);
assertNotNull(result);
assertEquals("Expected authentication to be successful",
AuthenticationResult.AuthenticationStatus.SUCCESS,
@@ -66,15 +82,102 @@ public class ExternalAuthenticationManag
assertOnlyContainsWrapped(principal, result.getPrincipals());
+ saslServer = _managerUsingFullDN.createSaslServer("EXTERNAL", "example.example.com", null);
+ result = _managerUsingFullDN.authenticate(saslServer, new byte[0]);
+
+ assertNotNull(result);
+ assertEquals("Expected authentication to be unsuccessful",
+ AuthenticationResult.AuthenticationStatus.ERROR,
+ result.getStatus());
+ }
+
+ /**
+ * Test behaviour of the authentication when parsing the username from
+ * the Principals DN as <CN>@<DC1>.<DC2>.<DC3>....<DCN>
+ */
+ public void testAuthenticateWithUsernameBasedOnCNAndDC() throws Exception
+ {
+ X500Principal principal;
+ SaslServer saslServer;
+ AuthenticationResult result;
+ UsernamePrincipal expectedPrincipal;
+
+ // DN contains only CN
+ principal = new X500Principal("CN=person");
+ expectedPrincipal = new UsernamePrincipal("person");
+ saslServer = _manager.createSaslServer("EXTERNAL", "example.example.com", principal);
+
+ result = _manager.authenticate(saslServer, new byte[0]);
+ assertNotNull(result);
+ assertEquals("Expected authentication to be successful",
+ AuthenticationResult.AuthenticationStatus.SUCCESS,
+ result.getStatus());
+ assertOnlyContainsWrapped(expectedPrincipal, result.getPrincipals());
+
+ // Null princial
saslServer = _manager.createSaslServer("EXTERNAL", "example.example.com", null);
result = _manager.authenticate(saslServer, new byte[0]);
assertNotNull(result);
- assertEquals("Expected authentication to be unsuccessful",
- AuthenticationResult.AuthenticationStatus.ERROR,
- result.getStatus());
+ assertEquals("Expected authentication to be unsuccessful",
+ AuthenticationResult.AuthenticationStatus.ERROR,
+ result.getStatus());
+
+ // DN doesn't contain CN
+ principal = new X500Principal("DC=example, DC=com, O=My Company Ltd, L=Newbury, ST=Berkshire, C=GB");
+ saslServer = _manager.createSaslServer("EXTERNAL", "example.example.com", principal);
+ result = _manager.authenticate(saslServer, new byte[0]);
- }
+ assertNotNull(result);
+ assertEquals("Expected authentication to be unsuccessful",
+ AuthenticationResult.AuthenticationStatus.ERROR,
+ result.getStatus());
+
+ // DN contains empty CN
+ principal = new X500Principal("CN=, DC=example, DC=com, O=My Company Ltd, L=Newbury, ST=Berkshire, C=GB");
+ saslServer = _manager.createSaslServer("EXTERNAL", "example.example.com", principal);
+ result = _manager.authenticate(saslServer, new byte[0]);
+
+ assertNotNull(result);
+ assertEquals("Expected authentication to be unsuccessful",
+ AuthenticationResult.AuthenticationStatus.ERROR,
+ result.getStatus());
+
+ // DN contains CN and DC
+ principal = new X500Principal("CN=person, DC=example, DC=com");
+ expectedPrincipal = new UsernamePrincipal("person@example.com");
+ saslServer = _manager.createSaslServer("EXTERNAL", "example.example.com", principal);
+
+ result = _manager.authenticate(saslServer, new byte[0]);
+ assertNotNull(result);
+ assertEquals("Expected authentication to be successful",
+ AuthenticationResult.AuthenticationStatus.SUCCESS,
+ result.getStatus());
+ assertOnlyContainsWrapped(expectedPrincipal, result.getPrincipals());
+
+ // DN contains CN and DC and other components
+ principal = new X500Principal("CN=person, DC=example, DC=com, O=My Company Ltd, L=Newbury, ST=Berkshire, C=GB");
+ expectedPrincipal = new UsernamePrincipal("person@example.com");
+ saslServer = _manager.createSaslServer("EXTERNAL", "example.example.com", principal);
+
+ result = _manager.authenticate(saslServer, new byte[0]);
+ assertNotNull(result);
+ assertEquals("Expected authentication to be successful",
+ AuthenticationResult.AuthenticationStatus.SUCCESS,
+ result.getStatus());
+ assertOnlyContainsWrapped(expectedPrincipal, result.getPrincipals());
+
+ // DN contains CN and DC and other components
+ principal = new X500Principal("CN=person, O=My Company Ltd, L=Newbury, ST=Berkshire, C=GB");
+ expectedPrincipal = new UsernamePrincipal("person");
+ saslServer = _manager.createSaslServer("EXTERNAL", "example.example.com", principal);
+ result = _manager.authenticate(saslServer, new byte[0]);
+ assertNotNull(result);
+ assertEquals("Expected authentication to be successful",
+ AuthenticationResult.AuthenticationStatus.SUCCESS,
+ result.getStatus());
+ assertOnlyContainsWrapped(expectedPrincipal, result.getPrincipals());
+ }
}
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org