Monday 14 February 2011

Apache configuration for LDAP access control

For some time now, HTTP access to the ADMIRAL file store has been restricted because we were unable to use a combination of Apache Require valid user, Require user and Require ldap-attribute directives to combine by-username and by-group access.  For example, we have been unable to realize access control for this scenario:

/data/private        all registered users have read-only access
/data/private/UserA  read/write access for UserA,
                     read-only access for research group leaders,
                     all others denied
/data/private/UserB  read/write access for UserB,
                     read-only access for research group leaders,
                     all others denied 

We had been finding that any attempt to put an access control statement on the /data/private directory resulted in the access control statements for the user private directories being ignored. Also, we were finding that we could not allow UserA to have read/write access to their personal area, while allowing read access to any user designated as a research group leader.

The Apache configuration we had been trying to use looked something like this:

# Default read access to  all areas for registered users
<Directory /home/data>
    Require valid user
</Directory>
# Define access to area for user $username
<Location /data/private/$username>
    Order Deny,Allow
    Allow from all
    <LimitExcept REPORT GET OPTIONS PROPFIND>
      Require ldap-user $username
    </LimitExcept>
    <Limit PROPFIND OPTIONS GET REPORT>
      Require user $username 
      Require ldap-attribute gidNumber=$RGLeaderGID
    </Limit>
</Location>

As this would not work as required, we ended up disabling access to the /data area, leaving users unable to use HTTP to browse between the different user areas, and configuring the research group leader's read-only access using a configured username, making the configuration very much more fragile than needed:

# Define access to area for user $username
<Location /data/private/$username>
    Order Deny,Allow
    Allow from all
    <LimitExcept REPORT GET OPTIONS PROPFIND>
      Require user $username
    </LimitExcept>
    <Limit PROPFIND OPTIONS GET REPORT>
      Require user $username $RGLeaderName
    </Limit>
</Location>

We recently realized that Apache recognizes different access control providers, and that access to a given area cannot be controlled by a combination of providers.  There is a default provider, invoked by Require user ... and Require valid user, and there is an LDAP provider. Thus, the presence of a matching Require ldap-attribute directive meant that any matching Require user directives were being ignored.
"When no LDAP-specific Require directives are used, authorization is allowed to fall back to other modules as if AuthzLDAPAuthoritative was set to off"
http://httpd.apache.org/docs/2.2/mod/mod_authnz_ldap.html
The overlooked implication here was that if any LDAP authorization directive is matched, the non-LDAP directives are ignored, even when applied to a more specific directory. The picture is further muddied by the fact that the non-LDAP authorization handlers have limited access to LDAP values (via an LDAP PAM module?), so that Require user would still respond to LDAP user entries.

Having identified the problem, the fix is easy.  Use Require ldap-user instead of Require user:
  
# Default access to  all areas
<Directory /home/data>
    Require ldap-attribute gidnumber=600
    Require ldap-attribute gidnumber=601
    Require ldap-attribute gidnumber=602
</Directory>
<Location /data/shared/$username>
    Order Deny,Allow
    Allow from all
    <LimitExcept REPORT GET OPTIONS PROPFIND>
      Require ldap-user $username
    </LimitExcept>
    <Limit PROPFIND OPTIONS GET REPORT>
      Require ldap-attribute gidNumber=$RGLeaderGID
      Require ldap-attribute gidNumber=$RGMemberGID
    </Limit>
</Location>

There is a lingering issue of the mixed <Directory> and <Location> directives: using <Location> for the /data URI path is not working, and right now we are not sure exactly why, but it seems to be related to either file system symlinks to the data directories, or Apache Alias directives controlling the mapping to same.

1 comment:

  1. I have just visited your blog. You have nice blog. Find best for Best House Protection. Read more for Best House Protection. Find Expert home security system opinions that help consumers choose the best home security systems by reading opinions of home security systems.
    For more informtion visit us at security system installation ct.

    ReplyDelete