authentic/src/authentic2/auth2_auth/auth2_ssl/README

181 lines
5.6 KiB
Plaintext

================================
Enable SSL Client authentication
================================
Intro
=====
Tested with Apache 2 and mod_ssl.
Django over mod_wsgi. From http://docs.djangoproject.com/en/dev/howto/deployment/modwsgi/
"Deploying Django with Apache and mod_wsgi is the recommended way to get Django into production."
Generate Keys
=============
* Create a CA (passphrase)
openssl genrsa -des3 -out ca.key 2048
openssl req -new -x509 -days 3650 -key ca.key -out ca.crt
openssl x509 -in ca.crt -text -noout
* Server key material (challenge)
openssl genrsa -des3 -out server.key 1024
openssl req -new -key server.key -out server.csr
openssl x509 -req -in server.csr -out server.crt -sha1 -CA ca.crt -CAkey ca.key -CAcreateserial -days 3650
openssl x509 -in server.crt -text -noout
* User Key material (challenge/password)
openssl genrsa -des3 -out c.key 1024
openssl req -new -key c.key -out c.csr
openssl x509 -req -in c.csr -out c.crt -sha1 -CA ca.crt -CAkey ca.key -CAcreateserial -days 3650
openssl pkcs12 -export -in c.crt -inkey c.key -name "Mikael Ates" -out c.p12
openssl pkcs12 -in c.p12 -clcerts -nokeys -info
Configure Apache and WSGI
=========================
Add a file django.wsgi, e.g.:
"""
import os
import sys
sys.path.append("/usr/local/lib/python2.6/site-packages/")
try:
import lasso
except:
print("Unable to import Lasso.", file=sys.stderr)
apache_configuration= os.path.dirname(__file__)
project = os.path.dirname(apache_configuration)
sys.path.append(project)
try:
import authentic2.settings
os.environ['DJANGO_SETTINGS_MODULE'] = 'authentic2.settings'
except:
print("Unable to import settings.", file=sys.stderr)
import django.core.handlers.wsgi
application = django.core.handlers.wsgi.WSGIHandler()
"""
Activate apache2 modules:
* a2enmod wsgi
* a2enmod ssl
Add a Apache vhost for SSL.
"""
<IfModule mod_ssl.c>
<VirtualHost *:443>
LimitInternalRecursion 1000
ServerAdmin webmaster@entrouvert.org
ServerName localhost
Alias /media/admin/ /usr/local/lib/python2.6/dist-packages/django/contrib/admin/media/
WSGIScriptAlias / /Donnees/devs/authentic/apache/django.wsgi
<Directory /Donnees/devs/authentic/>
SSLVerifyClient optional_no_ca
Options Indexes MultiViews FollowSymLinks
AllowOverride None
Order deny,allow
Allow from all
</Directory>
SSLEngine on
SSLCipherSuite HIGH:MEDIUM
SSLProtocol all -SSLv2
SSLCertificateFile /Donnees/devs/authentic/apache/key_mat/server.crt
SSLCertificateKeyFile /Donnees/devs/authentic/apache/key_mat/server.key
SSLCertificateChainFile /Donnees/devs/authentic/apache/key_mat/ca.crt
SSLCACertificateFile /Donnees/devs/authentic/apache/key_mat/ca.crt
SSLOptions +StdEnvVars +ExportCertData
BrowserMatch "MSIE [2-6]" \
nokeepalive ssl-unclean-shutdown \
downgrade-1.0 force-response-1.0
BrowserMatch "MSIE [17-9]" ssl-unclean-shutdown
</VirtualHost>
</IfModule>
"""
Give rights to Apache on your Authentic directory.
Reload Apache.
Configure Authentic
===================
Key Description
-------------------------- ----------------------------------------
ACCEPT_SELF_SIGNED accept certificate for which the validation failed,
default: False
STRICT_MATCH do a binary compare to match certificate and users,
default: False
SUBJECT_MATCH_KEYS SSL information to use to match recorded
certificates. default: ('subject_dn', 'issuer_dn'),
possible values: serial, subject_dn, issuer_dn, cert.
CREATE_USERNAME_CALLBACK function receiving a SSLInfo object as first
parameter and returning a username, default: None
CREATE_USER function receiving a SSLInfo object as first
parameter and returning a user, default: None
USE_COOKIE to be described
in settings.py:
Set AUTH_SSL = True
To create a user with the mail adress as identifier:
SSLAUTH_CREATE_USER = True
To use another identifier:
def myusernamegen(ssl_info):
import re
if(ssl_info.subject_cn):
return return re.sub('[^a-zA-Z0-9]', '_', ssl_info.subject_cn)
else:
return return re.sub('[^a-zA-Z0-9]', '_', ssl_info.serial)
SSLAUTH_CREATE_USERNAME_CALLBACK = myusernamegen
Nginx configuration
===================
You must be able to retrieve SSL environment variable, for example with the
SCGI backend you must add those lines to /etc/nginx/scgi_params::
scgi_param SSL_CLIENT_CERT $ssl_client_cert;
scgi_param SSL_CLIENT_RAW_CERT $ssl_client_raw_cert;
scgi_param SSL_CLIENT_S_DN $ssl_client_s_dn;
scgi_param SSL_CLIENT_I_DN $ssl_client_i_dn;
scgi_param SSL_CLIENT_SERIAL $ssl_client_serial;
scgi_param SSL_CLIENT_M_SERIAL $ssl_client_serial;
scgi_param SSL_CLIENT_VERIFY $ssl_client_verify;
It would be the same with FCGI but using the fcgi_param directive in the
fcgi_params file. It does not currently work when using proxy_pass.
A virtualhost configuration example::
server {
listen 80;
server_name authentic.localhost;
rewrite ^ https://$server_name$request_uri? permanent;
}
server {
listen 443;
server_name authentic.localhost;
ssl on;
ssl_certificate /etc/ssl/certs/ssl-cert-snakeoil.pem;
ssl_certificate_key /etc/ssl/private/ssl-cert-snakeoil.key;
ssl_verify_client optional_no_ca;
location / {
include scgi_params;
scgi_pass localhost:8000;
}
}
The serveur must be run using the SCGI protocol, with this command line for
example::
./manage.py runfcgi protocol=scgi method=threaded daemonize=false host=localhost port=8000