Using Cosign with Apache

This page provides instructions on using the Informatics Cosign servers to protect Apache websites running on DICE machines.

Cosign Overview

Cosign is a single sign-on (SSO) web login technology developed at the University of Michigan. It uses a centralised sign-on mechanism to authenticate users (for Informatics users, this means authenticating with your Kerberos principal). It uses login and service cookies to manage the authorization for a cosign-protected web site. More information on how Cosign works can be found on the Cosign web site

Note that all Cosign communication between machines is SSL-protected.

It is planned that Cosign will eventually replace KX509 for all Kerberised web site authorization within Informatics.

LCFG Configuration

If you are setting up a new web service, it is highly recommended that you use the apacheconf component as detailed towards the end of this document. To add cosign protection to an existing service, you can follow the instructions here to do so, although you should definitely consider switching to apacheconf.

The first step in Cosign-protecting your web site is to add the following header to the machine's profile

#include <dice/options/cosign-client.h>

Once the profile has compiled, run om updaterpms run to install the cosign software on your machine. This software consists of the cosign component and the client-side cosign filter itself, which is implemented as an Apache module (for both Apache 1 and Apache 2). You should start the component at this point with om cosign start.

The cosign client needs to know which user the web server is running as, primarily so it can make files and directories readable. This currently defaults to apache. To change this, set the following resources to the appropriate user and group:

!cosign.user                    mSET(apache) 
!cosign.group                   mSET(apache)

Next, your Cosign service needs a service name - email the infrastructure unit to request one of these - it needs to be unique. The common name in your service's SSL certificate is the logical choice for this service name. Once you have this, you should set the following resource to the appropriate value:

!cosign.servicename             mSET(myservicename)

The cosign servers maintain a dynamically-generated services list, which determines which machines can connect to them. To add your web server to this, add the service details to cosign.services, e.g.:

!cosign.services mADD(hostname.inf.ed.ac.uk;0;;Test_Client_on_hostname;https://hostname.inf.ed.ac.uk/test/index.cgi)

See the man page for lcfg-cosign(8) for more details on what these fields are.

Note that any underscores in the 4th field will be replaced by spaces in the automatically generated services web page. Also note that it is no longer required that underscores are used - spaces are now accepted by the cosign component.

The cosign component will generate sections of an httpd.conf file to be included in your web server's Apache configuration. You should tell cosign where the server root for apache is, with the following resource:

!cosign.cient_serverroot        mSET(/etc/httpd)

The cosign component can automatically call the configure method of another LCFG component when resources change, e.g. to automatically restart an apache web server:

!cosign.client_reconfigure      mSET(apache)

SSL Certificates

You will need to configure the SSL certificates for a cosign-protected web site. If this is an existing https web server which is being converted to using cosign, then you will already have certificates installed. If not, the x509 component can be used to generate signed certificates for Informatics servers. The man page for lcfg-x509 gives further details on how to do this. As an example, the following resources...

_X509_SERVICE(hostname)
!x509.hashed_hostname             mSET(/etc/httpd/conf/CA)

... would lead to hostname.[chain|crt|key] being created in /etc/httpd/conf with hash files for each certificate in the chain file being created in /etc/httpd/conf/CA (the Cosign filter requires these).

Unfortunately, the x509 component doesn't work quite as well as it should do, in particular it won't create hash files for an already existing certificate and it also requires that the directory for the hash files is already in existence. You can generate the hash files manually, but it's probably easier to force the x509 component to regenerate the certificates completely. To do this:

  • Move the existing .crt file out of the way (i.e. in the example above, move the file /etc/httpd/conf/hostname.crt).
  • Create the CA directory (i.e. in the example above, create the dir /etc/httpd/conf/CA with username and group permissions that allow it to be read by the webserver.
  • om x509 run should cause the certificates to be newly generated. Note that you need to make sure that the x509 component has been installed (om updaterpms run) and started (om x509 start).

The cosign filter needs to know where to find these certificates and this is done by setting the following resources:

cosign.file_filter_key          /etc/httpd/conf/hostname.key
cosign.file_filter_crt          /etc/httpd/conf/hostname.crt
cosign.path_filter_ca           /etc/httpd/conf/CA

Complete LCFG Configuration

Putting all of this together for an example service running on hostname.inf.ed.ac.uk would lead to resources similar to the following being added to the machine's profile:

#include <dice/options/cosign-client.h>

cosign.servicename              myservicename

/* most existing web servers will already have their own certs
    so won't require the _X509_SERVICE line                    */
_X509_SERVICE(hostname)

!x509.hashed_hostname            mSET(/etc/httpd/conf/CA)

cosign.file_filter_key          /etc/httpd/conf/hostname.key
cosign.file_filter_crt          /etc/httpd/conf/hostname.crt
cosign.path_filter_ca           /etc/httpd/conf/CA

!cosign.services mADD(hostname.inf.ed.ac.uk;0;;Test_Client_on_hostname;https://hostname.inf.ed.ac.uk/test/index.cgi)

cosign.client_serverroot        /etc/httpd
cosign.client_reconfigure       apache

Apache Configuration

Important Note for Apache 2.2 Users: Note that cosign doesn't work (complains of authentication errors) with Apache 2.2 if you have AuthType Cosign and Require valid-user in the Apache configuration - these directives are automatically included in the Apache configuration snippets generated by the cosign component). Without these directives, Apache 2.2 should work fine.

The cosign component will generate sections of an httpd.conf file, which can be included in the httpd.conf file used by the web server. These files will be created by the cosign component in a directory conf.d under the location specified by cosign.client_serverroot (e.g. /etc/httpd/conf.d/).

You can find some docs on the the Cosign apache directives at http://webapps.itcs.umich.edu/cosign/index.php/Cosign_Wiki:CosignInstallation

Before including these in your configuration you will need to tell Apache to load the cosign module. In the LoadModule section of your apache configuration file, add the following (selecting the appropriate line for the version of Apache you are using)...

# Apache1:
LoadModule cosign_module /usr/lib/apache/mod_cosign.so

# Apache2:
LoadModule cosign_module /usr/lib/httpd/modules/mod_cosign.so

In the virtual host that you want to add cosign-protection to (or at the top-level if you want to cosign-protect all virtual hosts), include:

Include /etc/httpd/conf.d/cosign-client

For each location that you wish to restrict access to, either include:

Include /etc/httpd/conf.d/cosign-vhost-all

... to require cosign for every location served by that virtual host, or create a Location directive containing

CosignProtected On
and suitable Require directives (see the cosign-vhost-all configuration file for an example).

If all has gone according to plan, visiting the cosign-protected service (https://hostname.inf.ed.ac.uk/test/index.cgi in the example above) will re-direct you to the cosign server (https://weblogin.inf.ed.ac.uk) and ask you to authenticate (for DICE users using Firefox and with existing kerberos credentials, this part will happen automatically)

Cosign in an .htaccess file.

Mainly from my experience of trying to Cosign protect www.inf.ed.ac.uk.

The recommended use of Cosign Protection is on HTTPS URLs. However, on www.inf the way we've done authorisation is to have an .htaccess file in the root of the container you want to protect, and the first thing you do is redirect the browser back to the same page, but over HTTPS if they weren't already using it, then you have the Apache auth directives (possibly prompting for a password, or relying on the older kx509 auth). If you try the same with Cosign, eg in your .htaccess file have something like:

 RewriteEngine On
 RewriteCond %{ENV:HTTPS} !on
 RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [R,L]

 CosignProtected On

What you want to happen is for the HTTP to HTTPS redirect to happen first, and then for Cosign to do its stuff if necessary. Unfortunately Cosign gets there first and bounces the browser off to weblogin.inf, now if this was initialed on a HTTP connection you end up getting HTTPS traffic over the HTTP port which confuses the browser.

To solve the problem you need to have CosignHttpOnly On set, but you can't put that in .htaccess files, so you need to put it in the server config file for the web site. This does lead to the problem of the possibility of someone snooping on the wire and stealing the users Cosign Cookie, which can then be used to impersonate that user to the web service. To slightly mitigate this, you can use the CosignCheckIP Always option to at least check the IP address is consistent, but doesn't help if the snooper uses a browser on the original users machine.

The real solution is to not use the CosignProtected On directive on HTTP web servers.

Using Apacheconf

Apacheconf is a new component for configuring Apache which supports modular service construction, allowing the simple configuration of multiple services on the same machine. It also offers mechanisms for simply configuring cosign at the LCFG level. A full overview of Apacheconf can be found in it's man page, however here are some pointers in using it to configure a cosign protected service...

Firstly, you need to obtain an X509 certificate for your service. Even if your service isn't TLS protected, you need a certificate to allow you to communicate with the cosignd. In addition to obtaining the certificate, you need to ensure that it is readable by the user your webserver runs as, and has the hashed datastructure required by cosign.

#include                          <dice/options/x509-client.h>
_X509_SERVICE(hostname)
!x509.certificates                mADD(servicename)
!x509.hashed_hostname             mSET(/etc/pki/tls/certs/servicename.CAs)
!x509.uid_hostname                mSET(<%apacheconf.user%>)
!x509.gid_hostname                mSET(<%apacheconf.group%>)

Then, you need to setup the Apacheconf component. Firstly pick whether you want an Apache-1.3 (deprecated) or Apache-2.0 based service, and include apacheconf-13.h or apacheconf-20.h as appropriate. Then, set it up as an SSL service (if appropriate), and as a cosign protected one.

#define DICE_OPTIONS_APACHECONF_USER myusername
#define DICE_OPTIONS_APACHECONF_GROUP mygroupname
#include                          <dice/options/apacheconf-13.h>

#include                          <dice/options/apacheconf-ssl.h>

#define DICE_OPTIONS_COSIGN_X509TAG hostname
#define DICE_OPTIONS_COSIGN_DESCRIPTION My_Cosign_Service
#include                          <dice/options/apacheconf-cosign.h>

myusername and mygroupname should be the username and groupname that you want the Apache server to run as. hostname is the same as you set in the X509 definitions earlier, and allows cosign to find your certificates. DICE_OPTIONS_COSIGN_DESCRIPTION is set to the description of the service you want to appear in the cosign service list, and must not include spaces.

The apacheconf-cosign header takes other options, which are documented at the begining of that header file.

Then, you must set up your virtual host, in the same way as for any other apacheconf governed service

!apacheconf.vhosts                mADD(myservice)
!apacheconf.vhostname_myserv      mSET(servicename)
!apacheconf.vhostport_myserv      mSET(443)
!apacheconf.vhostssl_myserv       mSET(yes)
!apacheconf.vhostsslcert_myserv   mSET(<%x509.certfile_hostname%>)
!apacheconf.vhostsslkey_myserv    mSET(<%x509.keyfile_hostname%>)
!apacheconf.vhostsslchain_myserv  mSET(<%x509.chainfile_hostname%>)
!apacheconf.vhostfile_nagios      mSET(cosign-client cosign-vhost-all)
!apacheconf.vhostfile_nagios      mADD(myservice.conf)

The above sets up an SSL Virtual Host for servicename. Including the configuration file cosign-client sets up all of the cosign settings for that host. Including cosign-vhost-all protects all locations on that virtual host with cosign. Finally, myservice.conf is included to incorporate any service specific configuration.

Alternate ports

If you are planning on using an SSL port other than the default 443, it would be wise to add:

!apacheconf.verbatim            mADD(cpport)
apacheconf.verbatimline_cpport  UseCanonicalPhysicalPort On

Otherwise, weblogin will redirect any authenticating users back to your host, without a port.

-- SimonWilkinson - 27 Aug 2007

Topic revision: r11 - 24 Jul 2014 - 17:27:49 - GrahamDutton
 
This site is powered by the TWiki collaboration platformCopyright © by the contributing authors. All material on this collaboration platform is the property of the contributing authors.
Ideas, requests, problems regarding TWiki? Send feedback
This Wiki uses Cookies