If we use apache for services with user authentication we want to it to talk to Active Directory. It is possible to have Linux talk to the AD servers for user authentication. Apache can be configured to piggy back on top of this setup. There are 2 steps
This is pretty easy and already documented at ActiveDirectory.
There are many ways to make apache use external authentication systems. the few we are interested in:
mod-auth-pam
mod-authnz-external
mod-auth-ldap
Apache::AuthPAM
It sounds simple but has not been easy to do this. For some security reasons having apache talk to pam (the linux authentication system) is not common.
I want to configure winbind+pam like I do on the other services so that I'm not maintaning and configuring multiple authentications systems.
This module is no longer maintained. For this reason I do not want to use it but it is the closest I have gotten to getting this stuff to work the way I want. Using other modules introduces more dependencies on other systems.http://pam.sourceforge.net/mod_auth_pam/
You must add these two lines into the Directory section of your apache config
AuthPAM_Enabled on AuthBasicAuthoritative off
For AuthBasicAuthoritative details see http://www.nabble.com/Bug-394097%3A-libapache2-mod-auth-pam-with-apache-%3E%3D-2.1-needs-AuthBasicAuthoritative-Off-tt7549314.html#a7549314
If authenticating against local users in the system you must also give the apache process read access to /etc/shadow. THIS IS A HUGE SECURITY RISK. The good news is that we don't really need that because we are authenticating againstActiveDirectory.
Check /etc/pam.d/httpd or /etc/pam.d/apache2 to make sure that the apache pam process is using the common pam authentication rather than some other modules or settings.
Debian
apt-get install libapache2-mod-auth-pam
Check /etc/pam.d/apache2
@include common-auth @include common-account
Since the module is not a built in package in RedHat I prefer to CompileFromSource. There are a few repositories on the web which have the module pre-compiled. WARNING It is risky to use software compiled by other people. You need to be able to trust the entity creating your software. This sounds paranoid because it is. Paranoia is the best way to keep systems secure.
Check /etc/pam.d/httpd. create it if it does not exist.
#%PAM-1.0 auth include system-auth account required pam_nologin.so account include system-auth password include system-auth session include system-auth
http://search.cpan.org/~hdaniel/Apache-AuthPAM-0.01/AuthPAM.pm
This is a module that allows apache to use an external source for authentication. Unfortunately, I havent' found documentation on how to use pam as the external source.
LDAP can be used to talk to ActiveDirectory but I don't want to configure two systems.
First I setup pam to authenticate against ActiveDirectory and tested with ssh. Next I modified apache's configs to use pam authentication.
If you want to password protect the main website on the server you need to modify the main configuration file for apache.
Modify /etc/apache2/sites-available/default
NameVirtualHost * <VirtualHost *> ServerAdmin webmaster@domain.com ServerName hg.domain.com DocumentRoot /var/www/ <Directory /> AuthType basic AuthName "Active Directory Authentication Required" AuthPAM_Enabled on AuthBasicAuthoritative off Require valid-user Options FollowSymLinks AllowOverride None </Directory> ErrorLog /var/log/apache2/error.log LogLevel warn CustomLog /var/log/apache2/access.log combined ServerSignature On </VirtualHost>
Edit /etc/httpd/conf/httpd.conf
<Directory /> AuthType basic AuthName "Active Directory Authentication Required" AuthPAM_Enabled on AuthBasicAuthoritative off Require valid-user Options FollowSymLinks AllowOverride None </Directory>
If the password protected site is only one of many virtual hosts you will need to configure it outside of the main website config.
I suggest creating a file to contain the virtual hosts or append to one if you already have it. Put the following section in /etc/httpd/conf.d/vhosts.conf
NameVirtualHost *:80 <VirtualHost *:80> ServerAdmin webmaster@domain.com DocumentRoot /var/www/vhosts/domain.com ServerName mysite.domain.com <Directory /> AuthType basic AuthName "Active Directory Authentication Required" AuthPAM_Enabled on AuthBasicAuthoritative off Require valid-user Options FollowSymLinks AllowOverride None </Directory> </VirtualHost>
Now create the directory for the virtual site
mkdir -p /var/www/vhosts/hg.domain.com
Put a test index.html file in place and see if it works
printf "<html><body>It works\!</body></html>\n" > /var/www/vhosts/hg.domain.com/index.html
Each new site can be appended to this file.
Assuming that you do not already have virtual hosts: By default the configuration exports /var/www for the entire web tree. Backup the original default file and change it so that we can put the virtual hosts inside /var/www.
mv /etc/apache2/sites-available/default /etc/sites-available/default.orig
We will move the main site to /var/www/html. Create a new file /etc/apache2/sites-available/default with the following contents
NameVirtualHost *:80 <VirtualHost *:80> ServerAdmin webmaster@localhost DocumentRoot /var/www/html <Directory /> Options FollowSymLinks AllowOverride None </Directory> <Directory /var/www/html> Options Indexes FollowSymLinks MultiViews AllowOverride None Order allow,deny allow from all </Directory> ScriptAlias /cgi-bin/ /usr/lib/cgi-bin/ <Directory "/usr/lib/cgi-bin"> AllowOverride None Options +ExecCGI -MultiViews +SymLinksIfOwnerMatch Order allow,deny Allow from all </Directory> ErrorLog /var/log/apache2/error.log # Possible values include: debug, info, notice, warn, error, crit, alert, emerg. LogLevel warn CustomLog /var/log/apache2/access.log combined ServerSignature On Alias /doc/ "/usr/share/doc/" <Directory "/usr/share/doc/"> Options Indexes MultiViews FollowSymLinks AllowOverride None Order deny,allow Deny from all Allow from 127.0.0.0/255.0.0.0 ::1/128 </Directory> </VirtualHost>
Next we create another file for the virtual host site. You might call it mysite.
LoadModule auth_pam_module modules/mod_auth_pam.so NameVirtualHost *:80 <VirtualHost *:80> ServerAdmin webmaster@localhost ServerName mysite.domain.com DocumentRoot /var/www/vhosts/mysite.domain.com <Directory /> Options FollowSymLinks AllowOverride None </Directory> <Directory /var/www/vhosts/mysite.domain.com> Options Indexes FollowSymLinks MultiViews AllowOverride None Order allow,deny allow from all </Directory> </VirtualHost>
Create the two new directories
mkdir -p /var/www/html mkdir -p /var/www/vhosts/mysite.domain.com
Enable the virtual host in apache with a2ensite. If that does not work then manually link the site
ln -s ../sites-available/mysite /etc/apache2/sites-enabled/mysite
Since this site is authenticating you may want to use SSL to encrypt the session. Note the use of port 443 in the examples below and the addition of the SSL lines in the apache configs.
Generate a certificate for use on the SSL site.
cd /etc/pki/tls/certs make mysite.domain.com.pem
If you want to only use ssl change the following section in /etc/httpd/conf.d/vhosts.conf. If you want both ssl and non ssl add this to the already existing file.
LoadModule auth_pam_module modules/mod_auth_pam.so NameVirtualHost *:443 <VirtualHost *:443> ServerAdmin webmaster@domain.com DocumentRoot /var/www/vhosts/domain.com ServerName mysite.domain.com SSLEngine On SSLCertificateFile /etc/pki/tls/certs/mysite.domain.com.pem <Directory /> AuthType basic AuthName "Active Directory Authentication Required" AuthPAM_Enabled on AuthBasicAuthoritative off Require valid-user Options FollowSymLinks AllowOverride None </Directory> </VirtualHost>
Install the ssl-cert package and generate a certificate. Fill in the appropriate values when asked.
apt-get install ssl-cert /usr/sbin/make-ssl-cert /usr/share/ssl-cert/ssleay.cnf /etc/ssl/certs/mysite.domain.com.pem
Enable ssl.
a2enmod ssl
Modify the mysite configuration. If you want only ssl change to the text below. If you want both ssl and non ssl add this text to the file.
NameVirtualHost *:443 <VirtualHost *:443> ServerAdmin webmaster@localhost ServerName mysite.domain.com SSLEngine On SSLCertificateFile /etc/ssl/certs/mysite.domain.com.pem DocumentRoot /var/www/vhosts/mysite.domain.com <Directory /> Options FollowSymLinks AllowOverride None </Directory> <Directory /var/www/vhosts/mysite.domain.com> Options Indexes FollowSymLinks MultiViews AllowOverride None Order allow,deny allow from all </Directory> ScriptAlias /cgi-bin/ /usr/lib/cgi-bin/ <Directory "/usr/lib/cgi-bin"> AllowOverride None Options +ExecCGI -MultiViews +SymLinksIfOwnerMatch Order allow,deny Allow from all </Directory> </VirtualHost>
If the user will not authenticate after doing all this stuff try restarting the system. It may be that some service is affected that I don't know about. Restarting seems to allow the authentication to work.
SELinux is stopping pam from responding properly to apache. If I turn it off it works ok. I'll create a custom SELINUX policy to allow this to work.
tail /var/log/audit/audit.log | audit2allow -m modauthpam > modauthpam.te checkmodule -m -M -omodauthpam.mod modauthpam.te semodule_package -o modauthpam.pp -m modauthpam.mod semodule -i modauthpam.pp
After running this in loops to create custom rules I ended up with this for modauthpam.te
module modauthpam 1.0; require { type httpd_t; class netlink_audit_socket create; } require { type httpd_t; class netlink_audit_socket write; } require { type httpd_t; class netlink_audit_socket read; } require { type httpd_t; class netlink_audit_socket { write nlmsg_relay }; } require { type httpd_t; class netlink_audit_socket { nlmsg_relay read }; } #============= httpd_t ============== allow httpd_t self:netlink_audit_socket { nlmsg_relay read }; allow httpd_t self:netlink_audit_socket create; allow httpd_t self:netlink_audit_socket { write nlmsg_relay }; allow httpd_t self:netlink_audit_socket write; allow httpd_t self:netlink_audit_socket read;