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