auth2_ssl: simplify and adapt for nginx
This commit is contained in:
parent
dc16ce9e81
commit
833191a3df
|
@ -103,6 +103,22 @@ 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:
|
||||
|
@ -117,3 +133,48 @@ def myusernamegen(ssl_info):
|
|||
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
|
||||
|
|
|
@ -6,10 +6,12 @@ import sys
|
|||
class AppSettings(object):
|
||||
'''Thanks django-allauth'''
|
||||
__DEFAULTS = dict(
|
||||
# settings for TEST only, make it easy to simulate the SSL
|
||||
# environment
|
||||
FORCE_ENV={},
|
||||
ACCEPT_SELF_SIGNED=False,
|
||||
STRICT_MATCH=False,
|
||||
SUBJECT_MATCH_KEYS=(),
|
||||
SUBJECT_MATCH_KEYS=('subject_dn', 'issuer_dn'),
|
||||
CREATE_USERNAME_CALLBACK=None,
|
||||
USE_COOKIE=False,
|
||||
CREATE_USER=False,
|
||||
|
|
|
@ -53,14 +53,8 @@ settings')
|
|||
return None
|
||||
query = Q(cert=ssl_info.cert)
|
||||
else:
|
||||
# compare according to SSLAUTH_SUBJECT_MATCH_KEYS
|
||||
if app_settings.SUBJECT_MATCH_KEYS:
|
||||
match_keys = app_settings.SUBJECT_MATCH_KEYS
|
||||
else:
|
||||
match_keys = ( 'subject_dn', 'issuer_dn')
|
||||
|
||||
query_args = {}
|
||||
for key in match_keys:
|
||||
for key in app_settings.SUBJECT_MATCH_KEYS:
|
||||
if not ssl_info.get(key):
|
||||
logging.error('SSLAuth: key %s is missing from ssl_info' \
|
||||
% key)
|
||||
|
@ -103,14 +97,7 @@ settings')
|
|||
user = build_user(username, ssl_info)
|
||||
|
||||
# create the certificate record and save
|
||||
cert = models.ClientCertificate()
|
||||
cert.user = user
|
||||
cert.subject_dn = ssl_info.subject_dn
|
||||
cert.issuer_dn = ssl_info.issuer_dn
|
||||
cert.cert = ssl_info.cert
|
||||
cert.serial = ssl_info.serial
|
||||
cert.save()
|
||||
|
||||
self.link_user(ssl_info, user)
|
||||
return user
|
||||
|
||||
@transaction.commit_on_success
|
||||
|
@ -120,9 +107,6 @@ settings')
|
|||
for the passed certificate info. It does not create an issuer record,
|
||||
just a subject for the ClientCertificate.
|
||||
"""
|
||||
if not user:
|
||||
return None
|
||||
|
||||
# create the certificate record and save
|
||||
cert = models.ClientCertificate()
|
||||
cert.user = user
|
||||
|
@ -134,14 +118,6 @@ settings')
|
|||
|
||||
return user
|
||||
|
||||
def build_username(self, ssl_info):
|
||||
"""
|
||||
create a valid django username from the certificate info. this method
|
||||
can be "overwritten" by using the SSLAUTH_CREATE_USERNAME_CALLBACK
|
||||
setting
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
|
||||
def build_user(self, username, ssl_info):
|
||||
"""
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
from django.contrib.auth import authenticate, login, get_user
|
||||
from django.contrib.auth.models import AnonymousUser
|
||||
from django.contrib.auth import authenticate, login
|
||||
|
||||
|
||||
from . import util, app_settings, backends
|
||||
from . import util, app_settings
|
||||
|
||||
|
||||
class SSLAuthMiddleware(object):
|
||||
|
@ -10,23 +9,9 @@ class SSLAuthMiddleware(object):
|
|||
attempts to find a valid user based on the client certificate info
|
||||
"""
|
||||
def process_request(self, request):
|
||||
|
||||
USE_COOKIE = app_settings.USE_COOKIE
|
||||
|
||||
if USE_COOKIE:
|
||||
request.user = get_user(request)
|
||||
if request.user.is_authenticated():
|
||||
return
|
||||
|
||||
if app_settings.USE_COOKIE and request.user.is_authenticated():
|
||||
return
|
||||
ssl_info = util.SSLInfo(request)
|
||||
user = authenticate(ssl_info=ssl_info) or AnonymousUser()
|
||||
|
||||
if not user.is_authenticated() and ssl_info.verify \
|
||||
and app_settings.CREATE_USER:
|
||||
if backends.SSLAuthBackend().create_user(ssl_info):
|
||||
user = authenticate(ssl_info=ssl_info) or AnonymousUser()
|
||||
|
||||
if user.is_authenticated() and USE_COOKIE:
|
||||
user = authenticate(ssl_info=ssl_info)
|
||||
if user and request.user != user:
|
||||
login(request, user)
|
||||
else:
|
||||
request.user = user
|
||||
|
|
Loading…
Reference in New Issue