I propose to change the Java Broker to allow users to plug-in alternative Authentication Manager implementations. The primary driver for this change is to allow authentication decisions to be delegated to another system, for instance, an Enterprise Directory.

Why do we need a pluggable Authentication Manager?

It is true we already have pluggable Principal Databases. Why does this not suffice? I would argue that the abstraction offered by PrincipalDatabase does not map well to a large organization. In a large organization functions such as creation/deletion of users and changing passwords are delegated to other systems. These functions are not core to Qpid’s use-case, and the offering of such functions can raise security concerns and can be a barrier to the adoption of Qpid.

To fulfill it's messaging use-cases, Qpid needs only to be able to authenticate users and authorise their actions. We already have a fully pluggable authorisation system (SecurityPlugin), but we lack the ability to cleanly plug-in authentication.

I am not suggesting that we remove the functionality offered by the PrincipalDatabase implementations (Plain/MD5 password databases backed by flat file). I can see these are useful for many users. The proposal retains these implementations although the configuration will change .

Proposal:

Currently Qpid makes Authentication decisions in two places: Qpid client authentication decisions (via SASL) are made in AuthenticationManager.authenticate(), and operator (JMX interaction) authentication decisions are made separately in RMIPasswordAuthenticator. To be able to cleanly abstract authentication, these functions must be exposed by a single façade. I propose to make AuthenticationManager that façade.

Key changes:

1) AuthenticationManager implementations take responsibility for all authentication decisions. In other words, they retain the responsibility for SASL authentication decisions and acquire the responsibility for non-SASL authentication decisions where the caller provides userid/password. 2) AuthenticationManager implementations retain the responsibility for registering the SASL mechanism(s) with JCA. 3) Implementations of the authenticate() method take responsibility for populating a JAAS Subject. This will allow the authentication manager to expose the user's identity (UsernamePrincipal) and group memberships (GroupPrincipal) to remainder of the application. The group information could be used by a SecurityPlugin to make access decisions based on group information from a Directory. 4) It will be mandatory for an implementation of an AuthenticationManager to be declared in config.xml. 5) PrincipalDatabaseAuthenticationManager will become a pluggable implementation. This implementation will continue to authenticate against a PrincipalDatabase - thus maintaining our current offering. 6) Other AuthenticationManager implementations would allow authentication decisions to be made in other ways, for instance, we might have a LDAPAuthentionationManager to delegate authentication decisions to an Enterprise Directory.

Config Illustration:

To illustrate, here is a config.xml snippet for a Qpid instance secured by a etc/password file. This illustrates how the current functionality would be maintained:

<security>
<authentication-manager>
<class> org.apache.qpid.server.security.auth.manager.PrincipalDatabaseAuthenticationManager< /class>
               <principal-database>
<class> org.apache.qpid.server.security.auth.manager.database.PlainPasswordFilePrincipalDatabase< /class>
                              <attributes>
<attribute><name>passwordFile</name><value>etc/password</value></ attribute>
                              </attributes>
               </principle-database>
</authentication-manager>
…
</security>

and here’s an imagined configuration of an AuthenticationManager that authenticates against a Directory. The configuration items are for illustration purposes only.

<security>
<authentication-manager>
<class> org.apache.qpid.server.security.auth.manager.LdapAuthenticationManager< /class>
               <ldap-server>ldaps://myldap.apache.org</ldap-server>
               <port>389</port>
               <usessl>true</usessl>
<user-dn-query>uid={0},ou=staff,dc=example,dc=com</ user-dn-query> <!-- group(s) from the Directory made available to SecurityPlugins via the JAAS subject --> <group-query>(&(objectCategory=group)(member=uid= {0},ou=staff,dc=example,dc=com))</group-query>
</authentication-manager>
…
</security>

I have annotated class diagrams to further illustrate the proposal. These can be found here:

https://cwiki.apache.org/confluence/display/qpid/Java+Pluggable+Authentication+Managers

Any thoughts? Please comment on this thread, rather than commenting on the Wiki page.


Reply via email to