[Pulp-list] Integrating Pulp with Kerberos authentication and LDAP authorisation

Nick Coghlan ncoghlan at redhat.com
Wed Jun 27 01:26:46 UTC 2012

I've been working on an internal Pulp deployment for a while now, and
one of the challenges is keeping Pulp's authentication and authorization
for the REST API up to date with respect to the authoritative records in
LDAP. I really don't want to be creating user records in every Pulp
instance in advance just in case people want in, but nor do I want to
have a manual process for requesting access if it turns out someone
*does* need to connect directly to the back end.

I've finally decided to bite the bullet and just patch Pulp to implement
the behaviour I want. However, since I want to submit the patch upstream
when it's done, I figure it makes sense to run the draft design by the list.

1. Web server pre-authentication (Bugzilla RFE:

I don't intend to implement Kerberos authentication in Pulp per se.
Instead, I intend to update Pulp to check for a HTTP_REMOTE_USER entry
before checking for HTTP_AUTHORIZATION and rely on mod_auth_kerb for the
actual authentication part. If HTTP_REMOTE_USER is set, the username (up
to the first @ character, if any) is assumed to have been
pre-authenticated by Apache. If they already exist as a user, then their
existing record will be used, otherwise a new record will be created
according to the external authorization rules below.

This selective pre-authentication can then be configured in Apache 2.2
by using SetEnvIf to filter on the Authorization field, and Specify Any
to allow users that fail pre-authentication through to Pulp's internal
authentication mechanisms. Example config changes for Pulp's REST API
web service:

<Files webservices.wsgi>
    # This allows everything except Kerberos auth through to Pulp
    SetEnvIfNoCase ^Authorization$ "Negotiate.*" USE_APACHE_AUTH=1
    Order allow,deny
    Allow from env=!USE_APACHE_AUTH
    Satisfy Any
    # Installation specific Kerberos config details go here
    # Standard Pulp REST API web service config details go here

If desired, the Apache level filters can be tightened up to only allow
pass through authentication options that Pulp is known to understand
(which would have the added bonus of interacting properly with clients
like web browsers that try unauthenticated access first, and only try to
pass a Kerberos ticket after receiving the relevant headers in a 401
error response)

The advantage of this general approach is that it isn't Kerberos (or
even Apache) specific - it should work for *any* web server level
authentication method that can be set up to pass HTTP_REMOTE_USER
through to the application.

2. External authorization (Bugzilla RFE:

The current LDAP authorization support is rather limited - consisting
solely of the "filter" option in the [ldap] config settings, along with
the "default-role" setting in that section.

This is limited in three ways:
- it doesn't handle web server level preauthentication in the absence of
- it only allows LDAP filters against users (not LDAP groups), which is
a problem if the LDAP server doesn't provide "memberOf" attributes on
user records
- it doesn't allow for per-role LDAP filters

To deal with the first limitation, I plan to add a "default-role" option
to the [security] section of the config file that is automatically
granted to *all* users when first created. LDAP authenticated users
would then get both the security default role *and* the ldap default
role (if any) when they first logged in. Both default-role entries
become optional.

For the latter two limitations, I plan to implement a couple of new
configuration sections: "ldap-user-roles" and "ldap-group-roles"

The format of these new sections are currently going to be:

role-name: <LDAP user filter>

role-name: <LDAP group filter>

The role names are only checked against the database when a user logs in
via web server preauthentication. If the role name doesn't exist, that
results in a warning in the Pulp log file but is otherwise ignored.

When a user is created implicitly (either via LDAP authentication or web
server preauthentication) the following automatic role assignment checks
will be performed:

If security.default-role is defined:
    the new user is granted that role
If LDAP is configured and the username matches a uid in LDAP (taking
ldap.filter into account):
    If ldap.default-role is defined:
        the new user is granted that role
    For each role:role-filter pair in ldap-user-roles:
        If (&(uid=<username>)<role-filter>) returns a non-empty list:
            the new user is granted that role
    For each role:role-filter pair in ldap-group-roles:
        If (&(uid=<username>)<role-filter>) returns a non-empty list:
            the new user is granted that role
If, after all this, the user has no roles assigned:
    They are not authorized for any access, and the login attempt fails
Otherwise, the user is created and more specific role-based
authorization checks proceed as usual

Writing automated tests for this new behaviour may prove to be a bit
tricky, so any advice on that front would be appreciated.


Nick Coghlan
Red Hat Infrastructure Engineering & Development, Brisbane

More information about the Pulp-list mailing list