Apache lookup module: Difference between revisions

From RavenWiki
Jump to navigationJump to search
(→‎Basic documentation: Replacing webauth link to wiki)
 
(16 intermediate revisions by one other user not shown)
Line 1: Line 1:
This is an Apache2 module (which appears to work in Apache 2.0 and Apache 2.2) designed to perform authorization functions for an existing REMOTE_USER (as derived from Raven or otherwise) by querying lookup.
This is an Apache2 module (which appears to work in Apache 2.0 and Apache 2.2, but '''not''' later versions) designed to perform authorization functions for an existing REMOTE_USER (as derived from Raven or otherwise) by querying lookup.


* [[Media:Ucam_lookupquery-0.90.tar.gz]] - Source tar ball
* [[Media:Ucam_lookupquery-0.90.tar.gz]] - Source tar ball
Line 5: Line 5:


Please send questions about this module to [mailto:lookup-support@ucs.cam.ac.uk lookup-support@ucs.cam.ac.uk].
Please send questions about this module to [mailto:lookup-support@ucs.cam.ac.uk lookup-support@ucs.cam.ac.uk].
<span style="color: red;">'''If you are planning to build and use this then be sure to read and understands the sections [[#Portability|'Portability']] and [[#Bugs and potential enhancements|'Bugs and potential enhancements']] below'''.</span>
<span style="color: red;">'''Note also that this module doesn't (and won't) work with Apache 2.4 and later. Similar functionality has been available built in to Apache since Apache 2.2 so continued use of this module is now deprecated. See [[Mod authnz ldap | seperate information]] in this wiki on how to do this, and for information on how to move away from using this module.'''.</span>


==Building the module==
==Building the module==
Line 12: Line 16:
creates:
creates:


   tar zxf mod_ucam_lookupquery-<ver>.tar.gz
   tar zxf Ucam_lookupquery-0.90.tar.gz
   cd mod_ucam_lookupquery-<ver>
   cd Ucam_lookupquery


then issue the following command as root:
then issue the following command as root:
Line 20: Line 24:


apxs may not be on root's default path and may be renamed, e.g. to apxs2, on some
apxs may not be on root's default path and may be renamed, e.g. to apxs2, on some
platforms. apxs and related files are sometimes provided by a httpd-devel, apache-devel, or apache2-devel package which will need to be installed. You will also need the OpenLDAP development files which will probably be provided by an openldap2-devel package or similar.
platforms. apxs and related files are sometimes provided by a httpd-devel, apache-devel, or apache2-devel package which will need to be installed. You will also need the OpenLDAP libraries and development files which will probably be provided by openldap and openldap2-devel packages, or similar. You may or may not also need to explicitly include the ldap libraries when building the module (the error message "undefined symbol: ldap_first_attribute" or similar when restarting Apache after adding the module suggests that you do and you haven't), in which case try
 
  apxs -c -i -lldap -llber mod_ucam_lookupquery.


Version 0.90 of the module isn't as portable as one might like. Depending on your platform details (Apache version, OpenLDAP version, C compiler, etc.) you may need to make some or all of the following changes:
Building under MacOS is more complicated still, because MacOS supports multiple architectures (e.g. i386 and x86_64) and you need to build the module so that it matches the architecture under which Apache runs. For most recent version (at least Leopard & Snow Leopard  (10.5/10.6)) the following incantation should work (it builds a 2-way fat binary supporting both i386 and x86_64 architectures):
 
  apxs -c -i -lldap -llber -Wc,'-arch i386 -arch x86_64' -Wl,'-arch i386 -arch x86_64' mod_ucam_lookupquery.c
 
[Note that most earlier versions of MacOS shipped with Apache version 1 with which this module is not compatible] Under MacOS, the edit below for line 575 is also needed to get the module to compile.
 
==Portability==
 
Version 0.90 of the module isn't as portable as one might like. Depending on your platform details (Apache version, OpenLDAP version, C compiler, etc.) you may need to make some or all of the following changes. Some, though not all, of these changes are included in the source RPM above but won't be included by default except when built on RedHat systems.


* Add, around line 26:
* Add, around line 26:
Line 45: Line 59:
to
to
  while (s > fakeuser && apr_isspace(s[-1])) s--;
  while (s > fakeuser && apr_isspace(s[-1])) s--;
In addition you might want to change a number of instances (e.g. at lines 877, 910, and 196) of APLOG_ERR to APLOG_INFO to reduce the noise in your Apache error log.


==Basic documentation==
==Basic documentation==
Line 55: Line 71:
'modules/mod_ucamlookupquery.so' if necessary with the path to the the
'modules/mod_ucamlookupquery.so' if necessary with the path to the the
file containing the module, relative to ServerRoot if it doesn't start
file containing the module, relative to ServerRoot if it doesn't start
'/'.  
'/'. You can work out that this path should be by looking at other LoadModule directives in the file.


To use it, include something like
To use it, include something like
Line 61: Line 77:
   Require LookupInst CS
   Require LookupInst CS


in a protection block. See below for other configuration options.
in a protection block (<span style="color: red;">except that due to a design mistake, 'Require LookupInst CS' probably won't actually do what you want</span> - see below). For example to protect URLs starting /restricted to members of the institution lookup knows as 'CS' as identified by Raven you might want
 
  <Location /restricted>
      AuthType Uam-WebAuth
      Require LookupInst CS
  </Location>
 
You'd also need the ucam_webauth module loaded and an AACookieKey and perhaps a AAKeyDir directive elsewhere in the configuration (see the [[Apache_authentication_module | mod_ucam_webauth documentation]]).  See also the official Apache documenation on [http://httpd.apache.org/docs/2.2/mod/core.html#location <Location>], [http://httpd.apache.org/docs/2.2/mod/core.html#directory <Directory>], and [http://httpd.apache.org/docs/2.2/howto/auth.html Authentication, Authorization and Access Control in general].
 
'''Problem with 'Require LookupInst CS'''': the problem is that this actually implements the rule 'is a member of CS and nothing else'. While this will be OK for most people in lookup (people normally only belong to one institution), anyone in more than one institution will not get access. This might be fixed in a future version of the module, but in the meantime as a work around you can use the equivalent:
 
  Require LookupQuery ou=people sub (&(uid=%u)(instID=CS))
 
===Specification===


<pre><nowiki>
<pre><nowiki>
Line 166: Line 195:
* What about Apache 1.3?
* What about Apache 1.3?
* Is there any way to keep a cached connection to ldap.lookup.cam.ac.uk? If so, should it be done?
* Is there any way to keep a cached connection to ldap.lookup.cam.ac.uk? If so, should it be done?
* 'Require LookupInst[Match]' expects exactly one attribute value, which won't be the case for someone affiliated to multiple institutions. To confuse matters, it reports a 'Temporary failure accessing the database' (becasue it gets an unexpected number of attributes). It should require ''at least one'' attribute value, which must match one of the names. As a work around, you can use something like
* 'Require LookupInst[Match]' expects exactly one attribute value, which won't be the case for someone affiliated to multiple institutions. To confuse matters, it reports a 'Temporary failure accessing the database' (because it gets an unexpected number of attributes). It should require ''at least one'' attribute value, which must match one of the names. As a work around, you can use something like
  Require LookupQuery ou=people sub (&(uid=%u)(instID=CS))
  Require LookupQuery ou=people sub (&(uid=%u)(instID=CS))
* The same applies (without the convenient work around) to LookupParentInst[Match]
* There is no scope for matching against the allUid when checking group membership using a privileged account. Probably needs to run
* There is no scope for matching against the allUid when checking group membership using a privileged account. Probably needs to run
  ou=groups sub (&(uid=%u)(allUid=%u)) groupID
  ou=groups sub (&(uid=%u)(allUid=%u)) groupID
* Authenticated binds force the use of TLS and require that the OpenLDAP client libraries are configured to verify the JANET certificate used by lookup. Error messages in the Apache log such as '<tt>ldap_start_tls_s: Connect error (-11)</tt>' indicate that this isn't the case.
** The module doesn't provide any way to customise the location of trusted CA certificates. For OpenLDAP the default location of a file listing trusted CA certificates and/or a directory containing 'OpenSSL-hashed' trusted CA certificates can be set per-user from ~/.ldaprc or system-wide from ldap.conf (perhaps in /etc/openlap or /etc/ldap) using the TLS_CACERT and TLS_CACERTDIR directives. See 'man ldap.conf'.
** The CA certificate curently (July 2011) required for loolup is one for the 'AddTrust External CA Root' - it is included by default in many Linux distributions, but not SuSE. It can be obtained from Comodo at https://support.comodo.com/index.php?_m=downloads&_a=viewdownload&downloaditemid=11&nav=0,1
** Setting 'TLS_REQCERT allow' in ldap.conf/.ldaprc will disable all certificate checking, which is fine for testing but a BAD IDEA otherwise.
** Versions of OpenLDAP linked against GnuTLS (rather than OpenSSL - Debian/Ubuntu in particular) don't support TLS_CACERTDIR. Further some (esp. that included with Ubuntu 8.04 'Hardy Herron') don't seem to be able to successfully verify lookup's certificate at all.

Latest revision as of 13:52, 10 October 2019

This is an Apache2 module (which appears to work in Apache 2.0 and Apache 2.2, but not later versions) designed to perform authorization functions for an existing REMOTE_USER (as derived from Raven or otherwise) by querying lookup.

Please send questions about this module to lookup-support@ucs.cam.ac.uk.

If you are planning to build and use this then be sure to read and understands the sections 'Portability' and 'Bugs and potential enhancements' below.

Note also that this module doesn't (and won't) work with Apache 2.4 and later. Similar functionality has been available built in to Apache since Apache 2.2 so continued use of this module is now deprecated. See seperate information in this wiki on how to do this, and for information on how to move away from using this module..

Building the module

To build the module from source and copy it into the correct Apache directory, first unpack the distribution tar file and cd into the directory it creates:

 tar zxf Ucam_lookupquery-0.90.tar.gz
 cd Ucam_lookupquery

then issue the following command as root:

 apxs -c -i mod_ucam_lookupquery.c

apxs may not be on root's default path and may be renamed, e.g. to apxs2, on some platforms. apxs and related files are sometimes provided by a httpd-devel, apache-devel, or apache2-devel package which will need to be installed. You will also need the OpenLDAP libraries and development files which will probably be provided by openldap and openldap2-devel packages, or similar. You may or may not also need to explicitly include the ldap libraries when building the module (the error message "undefined symbol: ldap_first_attribute" or similar when restarting Apache after adding the module suggests that you do and you haven't), in which case try

 apxs -c -i -lldap -llber mod_ucam_lookupquery.

Building under MacOS is more complicated still, because MacOS supports multiple architectures (e.g. i386 and x86_64) and you need to build the module so that it matches the architecture under which Apache runs. For most recent version (at least Leopard & Snow Leopard (10.5/10.6)) the following incantation should work (it builds a 2-way fat binary supporting both i386 and x86_64 architectures):

 apxs -c -i -lldap -llber -Wc,'-arch i386 -arch x86_64' -Wl,'-arch i386 -arch x86_64' mod_ucam_lookupquery.c

[Note that most earlier versions of MacOS shipped with Apache version 1 with which this module is not compatible] Under MacOS, the edit below for line 575 is also needed to get the module to compile.

Portability

Version 0.90 of the module isn't as portable as one might like. Depending on your platform details (Apache version, OpenLDAP version, C compiler, etc.) you may need to make some or all of the following changes. Some, though not all, of these changes are included in the source RPM above but won't be included by default except when built on RedHat systems.

  • Add, around line 26:
#include "http_request.h"  /* for ap_hook_auth_checker */
#include "apr_lib.h"       /* for apr_isspace.h */
  • At line 150, change
int error_code;

to

int error_code = 0;
  • For some older versions of OpenLDAP, Change lines 187/8 from
else if (strcmp(scope, "one") == 0) intscope = LDAP_SCOPE_ONE;
else if (strcmp(scope, "sub") == 0) intscope = LDAP_SCOPE_SUB;

to

else if (strcmp(scope, "one") == 0) intscope = LDAP_SCOPE_ONELEVEL;
else if (strcmp(scope, "sub") == 0) intscope = LDAP_SCOPE_SUBTREE;
  • Change line 575 from
regex_t *r = ap_pregcomp(p, w, REG_ICASE);

to

ap_regex_t *r = ap_pregcomp(p, w, AP_REG_ICASE);
  • Change line 829 from
while (s > fakeuser && isspace(s[-1])) s--;

to

while (s > fakeuser && apr_isspace(s[-1])) s--;

In addition you might want to change a number of instances (e.g. at lines 877, 910, and 196) of APLOG_ERR to APLOG_INFO to reduce the noise in your Apache error log.

Basic documentation

Load the module by including

 LoadModule ucam_lookupquery_module modules/mod_ucam_lookupquery.so

in the Apache configuration file, replacing 'modules/mod_ucamlookupquery.so' if necessary with the path to the the file containing the module, relative to ServerRoot if it doesn't start '/'. You can work out that this path should be by looking at other LoadModule directives in the file.

To use it, include something like

 Require LookupInst CS

in a protection block (except that due to a design mistake, 'Require LookupInst CS' probably won't actually do what you want - see below). For example to protect URLs starting /restricted to members of the institution lookup knows as 'CS' as identified by Raven you might want

 <Location /restricted>
     AuthType Uam-WebAuth
     Require LookupInst CS
 </Location>

You'd also need the ucam_webauth module loaded and an AACookieKey and perhaps a AAKeyDir directive elsewhere in the configuration (see the mod_ucam_webauth documentation). See also the official Apache documenation on <Location>, <Directory>, and Authentication, Authorization and Access Control in general.

Problem with 'Require LookupInst CS': the problem is that this actually implements the rule 'is a member of CS and nothing else'. While this will be OK for most people in lookup (people normally only belong to one institution), anyone in more than one institution will not get access. This might be fixed in a future version of the module, but in the meantime as a work around you can use the equivalent:

 Require LookupQuery ou=people sub (&(uid=%u)(instID=CS))

Specification

OPTIONS
-------

LookupAuthoritative   
  Value:    on|off                 
  Default:  on

LookupHostPort        
  Value:    space-separated list   
  Default:  ldap.lookup.cam.ac.uk:389        (actually uses LDAP_PORT)
  
(1) IPv6 literal addresses can be enclosed in []. 
(2) It tries each one till one answers, one way or another.
   
LookupBase
  Value:    string
  Default:  "o=University of Cambridge,dc=cam,dc=ac,dc=uk"
  

AUTHENTICATION
--------------

LookupBindDN
  Value:    string
  Default:  unset
  
LookupPwd
  Value:    string
  Default:  unset    
  
If both of these are set, a non-anonymous LDAP bind is done, first setting up 
an encrypted (TLS) session. If either one is not set, a non-encrypted, 
anonymous bind is done.

  

REQUIREMENTS
------------

Apart from LookupQuery, all these come in pairs, LookupXxx and LookupXxxMatch.
The former do exact matches on the data, the latter do regular expression
matches. Multiple data values for a Require implement OR. Multiple Requires 
implement AND. It is not clear if this is the True Apache Way or not - I have
failed to find a definitive statement - but it seems to me that whether
multiple Requires do AND or OR should be controlled from a higher level
(compare "satisfy any" for Require+Allow) because each run of the module just
deals with a single Require and returns yes/no. There would have to be a much 
more elaborate memory scheme to implement OR at this level.

Require LookupInst[Match] name1 [name2 ...]
  Runs:     ou=people sub (uid=%u) inst
  Needs:    (a) Exactly one entry
            (b) Exactly one attribute value, must match one of the names 
  Example:  Require LookupInst CS CL 
 
Require LookupAttr[Match] comma-separated-attrnames value1 [value2 ...]
  Runs:     ou=people sub (uid=%u) comma-separated-attrnames
  Needs:    (a) Exactly one entry
            (b) At least one attribute value must match something in the list
  Example:  Require LookupAttr cn,displayName "Jon Warbrick" "Philip Hazel"
  
Require LookupParentInst[Match] name1 [name2 ...]
  Runs:     ou=people sub (uid=%u) inst  
  Needs:    (a) Exactly one entry
            (b) Exactly one attribute value, must match one of the names 
  Else:     ou=insts sub (instID=inst) parentInstID
  Needs:    (a) Exactly one entry
            (b) Exactly one attribute value, must match one of the names
  Else:     Loop up the tree till ROOT (which is checked).
  Example:  Require LookupParentInst COLL
  
Require LookupUserInGroup[Match] name1 [name2 ...]
  Runs:     ou=groups sub (uid=%u) groupID
  Needs:    (a) One or more entries
            (b) At least one of the groupIDs to match one of the names.
  Example:  Require LookupUserInGroup 100001 100656
  
Require LookupQuery baseplus scope filter
  Runs:     baseplus scope filter
  Needs:    One or more entries (no attributes are looked up)
  Example:  RequireLookupQuery ou=groups sub 
              (&(uid=%u)(groupTitle=*Computing Service*))
  
The last rather artificial example checks that the user is a member of at least
one group that has "Computing Service" in its title. To run a query on the base 
itself, the first argument can be given as an empty string in quotes.

In the filter, literal characters * ( ) \ must be escaped as follows:

  *  =>  \2A
  (  =>  \28
  )  =>  \29
  \  =>  \5C

The sequence %u is replaced by the userid. To include a literal % before a 
lower case u, use \75.

Bugs and potential enhancements

  • What about Apache 1.3?
  • Is there any way to keep a cached connection to ldap.lookup.cam.ac.uk? If so, should it be done?
  • 'Require LookupInst[Match]' expects exactly one attribute value, which won't be the case for someone affiliated to multiple institutions. To confuse matters, it reports a 'Temporary failure accessing the database' (because it gets an unexpected number of attributes). It should require at least one attribute value, which must match one of the names. As a work around, you can use something like
Require LookupQuery ou=people sub (&(uid=%u)(instID=CS))
  • The same applies (without the convenient work around) to LookupParentInst[Match]
  • There is no scope for matching against the allUid when checking group membership using a privileged account. Probably needs to run
ou=groups sub (&(uid=%u)(allUid=%u)) groupID
  • Authenticated binds force the use of TLS and require that the OpenLDAP client libraries are configured to verify the JANET certificate used by lookup. Error messages in the Apache log such as 'ldap_start_tls_s: Connect error (-11)' indicate that this isn't the case.
    • The module doesn't provide any way to customise the location of trusted CA certificates. For OpenLDAP the default location of a file listing trusted CA certificates and/or a directory containing 'OpenSSL-hashed' trusted CA certificates can be set per-user from ~/.ldaprc or system-wide from ldap.conf (perhaps in /etc/openlap or /etc/ldap) using the TLS_CACERT and TLS_CACERTDIR directives. See 'man ldap.conf'.
    • The CA certificate curently (July 2011) required for loolup is one for the 'AddTrust External CA Root' - it is included by default in many Linux distributions, but not SuSE. It can be obtained from Comodo at https://support.comodo.com/index.php?_m=downloads&_a=viewdownload&downloaditemid=11&nav=0,1
    • Setting 'TLS_REQCERT allow' in ldap.conf/.ldaprc will disable all certificate checking, which is fine for testing but a BAD IDEA otherwise.
    • Versions of OpenLDAP linked against GnuTLS (rather than OpenSSL - Debian/Ubuntu in particular) don't support TLS_CACERTDIR. Further some (esp. that included with Ubuntu 8.04 'Hardy Herron') don't seem to be able to successfully verify lookup's certificate at all.