Add logging capabilities
This commit is contained in:
parent
cd4b9846cd
commit
20aa4c0d74
68
README.rst
68
README.rst
@ -161,3 +161,71 @@ Authentication backend
|
|||||||
This is the default backend. The returned attributes are the fields available on the user model.
|
This is the default backend. The returned attributes are the fields available on the user model.
|
||||||
* mysql backend ``cas_server.auth.MysqlAuthUser``: see the 'Mysql backend settings' section.
|
* mysql backend ``cas_server.auth.MysqlAuthUser``: see the 'Mysql backend settings' section.
|
||||||
The returned attributes are those return by sql query ``CAS_SQL_USER_QUERY``.
|
The returned attributes are those return by sql query ``CAS_SQL_USER_QUERY``.
|
||||||
|
|
||||||
|
Logs
|
||||||
|
----
|
||||||
|
|
||||||
|
``django-cas-server`` logs most of its actions. To enable login, you must set the ``LOGGING``
|
||||||
|
(https://docs.djangoproject.com/en/dev/topics/logging) variable is ``settings.py``.
|
||||||
|
|
||||||
|
Users successful actions (login, logout) are logged with the level ``INFO``, failures are logged
|
||||||
|
with the level ``WARNING`` and user attributes transmitted to a service are logged with the level ``DEBUG``.
|
||||||
|
|
||||||
|
For exemple to log to syslog you can use :
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
LOGGING = {
|
||||||
|
'version': 1,
|
||||||
|
'disable_existing_loggers': False,
|
||||||
|
'formatters': {
|
||||||
|
'cas_syslog': {
|
||||||
|
'format': 'cas: %(levelname)s %(message)s'
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'handlers': {
|
||||||
|
'cas_syslog': {
|
||||||
|
'level': 'INFO',
|
||||||
|
'class': 'logging.handlers.SysLogHandler',
|
||||||
|
'address': '/dev/log',
|
||||||
|
'formatter': 'cas_syslog',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'loggers': {
|
||||||
|
'cas_server': {
|
||||||
|
'handlers': ['cas_syslog'],
|
||||||
|
'level': 'INFO',
|
||||||
|
'propagate': True,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Or to log to a file:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
LOGGING = {
|
||||||
|
'version': 1,
|
||||||
|
'disable_existing_loggers': False,
|
||||||
|
'formatters': {
|
||||||
|
'cas_file': {
|
||||||
|
'format': '%(asctime)s %(levelname)s %(message)s'
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'handlers': {
|
||||||
|
'cas_file': {
|
||||||
|
'level': 'INFO',
|
||||||
|
'class': 'logging.FileHandler',
|
||||||
|
'filename': '/tmp/cas_server.log',
|
||||||
|
'formatter': 'cas_file',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'loggers': {
|
||||||
|
'cas_server': {
|
||||||
|
'handlers': ['cas_file'],
|
||||||
|
'level': 'INFO',
|
||||||
|
'propagate': True,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
@ -22,6 +22,7 @@ from picklefield.fields import PickledObjectField
|
|||||||
import re
|
import re
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
|
import logging
|
||||||
from importlib import import_module
|
from importlib import import_module
|
||||||
from datetime import timedelta
|
from datetime import timedelta
|
||||||
from concurrent.futures import ThreadPoolExecutor
|
from concurrent.futures import ThreadPoolExecutor
|
||||||
@ -31,6 +32,8 @@ import cas_server.utils as utils
|
|||||||
|
|
||||||
SessionStore = import_module(settings.SESSION_ENGINE).SessionStore
|
SessionStore = import_module(settings.SESSION_ENGINE).SessionStore
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class User(models.Model):
|
class User(models.Model):
|
||||||
"""A user logged into the CAS"""
|
"""A user logged into the CAS"""
|
||||||
@ -82,6 +85,12 @@ class User(models.Model):
|
|||||||
try:
|
try:
|
||||||
future.result()
|
future.result()
|
||||||
except Exception as error:
|
except Exception as error:
|
||||||
|
logger.warning(
|
||||||
|
"Error during SLO for user %s: %s" % (
|
||||||
|
self.username,
|
||||||
|
error
|
||||||
|
)
|
||||||
|
)
|
||||||
if request is not None:
|
if request is not None:
|
||||||
error = utils.unpack_nested_exception(error)
|
error = utils.unpack_nested_exception(error)
|
||||||
messages.add_message(
|
messages.add_message(
|
||||||
@ -125,6 +134,7 @@ class User(models.Model):
|
|||||||
after a Service Ticket has been generated"""
|
after a Service Ticket has been generated"""
|
||||||
ticket = self.get_ticket(ServiceTicket, service, service_pattern, renew)
|
ticket = self.get_ticket(ServiceTicket, service, service_pattern, renew)
|
||||||
url = utils.update_url(service, {'ticket': ticket.value})
|
url = utils.update_url(service, {'ticket': ticket.value})
|
||||||
|
logger.info("Service ticket created for service %s by user %s." % (service, self.username))
|
||||||
return url
|
return url
|
||||||
|
|
||||||
|
|
||||||
@ -220,6 +230,7 @@ class ServicePattern(models.Model):
|
|||||||
def check_user(self, user):
|
def check_user(self, user):
|
||||||
"""Check if `user` if allowed to use theses services"""
|
"""Check if `user` if allowed to use theses services"""
|
||||||
if self.restrict_users and not self.usernames.filter(value=user.username):
|
if self.restrict_users and not self.usernames.filter(value=user.username):
|
||||||
|
logger.warning("Username %s not allowed on service %s" % (user.username, self.name))
|
||||||
raise BadUsername()
|
raise BadUsername()
|
||||||
for filtre in self.filters.all():
|
for filtre in self.filters.all():
|
||||||
if isinstance(user.attributs.get(filtre.attribut, []), list):
|
if isinstance(user.attributs.get(filtre.attribut, []), list):
|
||||||
@ -230,12 +241,28 @@ class ServicePattern(models.Model):
|
|||||||
if re.match(filtre.pattern, str(value)):
|
if re.match(filtre.pattern, str(value)):
|
||||||
break
|
break
|
||||||
else:
|
else:
|
||||||
|
logger.warning(
|
||||||
|
"User constraint failed for %s, service %s: %s do not match %s %s." % (
|
||||||
|
user.username,
|
||||||
|
self.name,
|
||||||
|
filtre.pattern,
|
||||||
|
filtre.attribut,
|
||||||
|
user.attributs.get(filtre.attribut)
|
||||||
|
)
|
||||||
|
)
|
||||||
raise BadFilter('%s do not match %s %s' % (
|
raise BadFilter('%s do not match %s %s' % (
|
||||||
filtre.pattern,
|
filtre.pattern,
|
||||||
filtre.attribut,
|
filtre.attribut,
|
||||||
user.attributs.get(filtre.attribut)
|
user.attributs.get(filtre.attribut)
|
||||||
))
|
))
|
||||||
if self.user_field and not user.attributs.get(self.user_field):
|
if self.user_field and not user.attributs.get(self.user_field):
|
||||||
|
logger.warning(
|
||||||
|
"Cannot use %s a loggin for user %s on service %s because it is absent" % (
|
||||||
|
self.user_field,
|
||||||
|
user.username,
|
||||||
|
self.name
|
||||||
|
)
|
||||||
|
)
|
||||||
raise UserFieldNotDefined()
|
raise UserFieldNotDefined()
|
||||||
return True
|
return True
|
||||||
|
|
||||||
@ -246,6 +273,7 @@ class ServicePattern(models.Model):
|
|||||||
for service_pattern in cls.objects.all().order_by('pos'):
|
for service_pattern in cls.objects.all().order_by('pos'):
|
||||||
if re.match(service_pattern.pattern, service):
|
if re.match(service_pattern.pattern, service):
|
||||||
return service_pattern
|
return service_pattern
|
||||||
|
logger.warning("Service %s not allowed." % service)
|
||||||
raise cls.DoesNotExist()
|
raise cls.DoesNotExist()
|
||||||
|
|
||||||
|
|
||||||
@ -378,6 +406,7 @@ class Ticket(models.Model):
|
|||||||
try:
|
try:
|
||||||
future.result()
|
future.result()
|
||||||
except Exception as error:
|
except Exception as error:
|
||||||
|
logger.warning("Error durring SLO %s" % error)
|
||||||
sys.stderr.write("%r\n" % error)
|
sys.stderr.write("%r\n" % error)
|
||||||
|
|
||||||
def logout(self, request, session, async_list=None):
|
def logout(self, request, session, async_list=None):
|
||||||
@ -386,6 +415,12 @@ class Ticket(models.Model):
|
|||||||
self.validate = True
|
self.validate = True
|
||||||
self.save()
|
self.save()
|
||||||
if self.validate and self.single_log_out:
|
if self.validate and self.single_log_out:
|
||||||
|
logger.info(
|
||||||
|
"Sending SLO requests to service %s for user %s" % (
|
||||||
|
self.service,
|
||||||
|
self.user.username
|
||||||
|
)
|
||||||
|
)
|
||||||
try:
|
try:
|
||||||
xml = u"""<samlp:LogoutRequest xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol"
|
xml = u"""<samlp:LogoutRequest xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol"
|
||||||
ID="%(id)s" Version="2.0" IssueInstant="%(datetime)s">
|
ID="%(id)s" Version="2.0" IssueInstant="%(datetime)s">
|
||||||
@ -409,8 +444,15 @@ class Ticket(models.Model):
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
except Exception as error:
|
except Exception as error:
|
||||||
|
error = utils.unpack_nested_exception(error)
|
||||||
|
logger.warning(
|
||||||
|
"Error durring SLO for user %s on service %s: %s" % (
|
||||||
|
self.user.username,
|
||||||
|
self.service,
|
||||||
|
error
|
||||||
|
)
|
||||||
|
)
|
||||||
if request is not None:
|
if request is not None:
|
||||||
error = utils.unpack_nested_exception(error)
|
|
||||||
messages.add_message(
|
messages.add_message(
|
||||||
request,
|
request,
|
||||||
messages.WARNING,
|
messages.WARNING,
|
||||||
|
@ -23,6 +23,8 @@ from django.views.decorators.csrf import csrf_exempt
|
|||||||
|
|
||||||
from django.views.generic import View
|
from django.views.generic import View
|
||||||
|
|
||||||
|
import logging
|
||||||
|
import pprint
|
||||||
import requests
|
import requests
|
||||||
from lxml import etree
|
from lxml import etree
|
||||||
from datetime import timedelta
|
from datetime import timedelta
|
||||||
@ -38,6 +40,8 @@ from .models import ServicePattern
|
|||||||
|
|
||||||
SessionStore = import_module(settings.SESSION_ENGINE).SessionStore
|
SessionStore = import_module(settings.SESSION_ENGINE).SessionStore
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class AttributesMixin(object):
|
class AttributesMixin(object):
|
||||||
"""mixin for the attributs methode"""
|
"""mixin for the attributs methode"""
|
||||||
@ -60,9 +64,14 @@ class LogoutMixin(object):
|
|||||||
"""destroy CAS session utils"""
|
"""destroy CAS session utils"""
|
||||||
def logout(self, all=False):
|
def logout(self, all=False):
|
||||||
"""effectively destroy CAS session"""
|
"""effectively destroy CAS session"""
|
||||||
|
username = self.request.session.get("username")
|
||||||
|
if username:
|
||||||
|
if all:
|
||||||
|
logger.info("Logging out user %s from all of they sessions." % username)
|
||||||
|
else:
|
||||||
|
logger.info("Logging out user %s." % username)
|
||||||
# logout the user from the current session
|
# logout the user from the current session
|
||||||
try:
|
try:
|
||||||
username = self.request.session.get("username")
|
|
||||||
user = models.User.objects.get(
|
user = models.User.objects.get(
|
||||||
username=username,
|
username=username,
|
||||||
session_key=self.request.session.session_key
|
session_key=self.request.session.session_key
|
||||||
@ -81,6 +90,7 @@ class LogoutMixin(object):
|
|||||||
session.flush()
|
session.flush()
|
||||||
user.logout(self.request)
|
user.logout(self.request)
|
||||||
user.delete()
|
user.delete()
|
||||||
|
logger.info("User %s logged out" % username)
|
||||||
|
|
||||||
|
|
||||||
class LogoutView(View, LogoutMixin):
|
class LogoutView(View, LogoutMixin):
|
||||||
@ -97,6 +107,7 @@ class LogoutView(View, LogoutMixin):
|
|||||||
|
|
||||||
def get(self, request, *args, **kwargs):
|
def get(self, request, *args, **kwargs):
|
||||||
"""methode called on GET request on this view"""
|
"""methode called on GET request on this view"""
|
||||||
|
logger.info("logout requested")
|
||||||
self.init_get(request)
|
self.init_get(request)
|
||||||
self.logout(self.request.GET.get("all"))
|
self.logout(self.request.GET.get("all"))
|
||||||
# if service is set, redirect to service after logout
|
# if service is set, redirect to service after logout
|
||||||
@ -212,6 +223,7 @@ class LoginView(View, LogoutMixin):
|
|||||||
# if not set a new LT and fail
|
# if not set a new LT and fail
|
||||||
values['lt'] = self.request.session['lt'][-1]
|
values['lt'] = self.request.session['lt'][-1]
|
||||||
self.init_form(values)
|
self.init_form(values)
|
||||||
|
logger.warning("Receive an invalid login ticket")
|
||||||
return self.INVALID_LOGIN_TICKET
|
return self.INVALID_LOGIN_TICKET
|
||||||
elif not self.request.session.get("authenticated") or self.renew:
|
elif not self.request.session.get("authenticated") or self.renew:
|
||||||
self.init_form(self.request.POST)
|
self.init_form(self.request.POST)
|
||||||
@ -222,10 +234,13 @@ class LoginView(View, LogoutMixin):
|
|||||||
self.request.session["authenticated"] = True
|
self.request.session["authenticated"] = True
|
||||||
self.renewed = True
|
self.renewed = True
|
||||||
self.warned = True
|
self.warned = True
|
||||||
|
logger.info("User %s successfully authenticated" % self.request.session["username"])
|
||||||
return self.USER_LOGIN_OK
|
return self.USER_LOGIN_OK
|
||||||
else:
|
else:
|
||||||
|
logger.warning("A logging attemps failed")
|
||||||
return self.USER_LOGIN_FAILURE
|
return self.USER_LOGIN_FAILURE
|
||||||
else:
|
else:
|
||||||
|
logger.warning("Receuve a logging attempt whereas the user is already logged")
|
||||||
return self.USER_ALREADY_LOGGED
|
return self.USER_ALREADY_LOGGED
|
||||||
|
|
||||||
def init_get(self, request):
|
def init_get(self, request):
|
||||||
@ -356,6 +371,11 @@ class LoginView(View, LogoutMixin):
|
|||||||
session_key=self.request.session.session_key
|
session_key=self.request.session.session_key
|
||||||
)
|
)
|
||||||
except models.User.DoesNotExist:
|
except models.User.DoesNotExist:
|
||||||
|
logger.warning(
|
||||||
|
"User %s seems authenticated but is not found in the database." % (
|
||||||
|
self.request.session.get("username"),
|
||||||
|
)
|
||||||
|
)
|
||||||
self.logout()
|
self.logout()
|
||||||
if self.ajax:
|
if self.ajax:
|
||||||
data = {
|
data = {
|
||||||
@ -503,10 +523,27 @@ class Validate(View):
|
|||||||
)
|
)
|
||||||
ticket.validate = True
|
ticket.validate = True
|
||||||
ticket.save()
|
ticket.save()
|
||||||
|
logger.info(
|
||||||
|
"Validate: Service ticket %s validated, user %s authenticated on service %s" % (
|
||||||
|
ticket.value,
|
||||||
|
ticket.user.username,
|
||||||
|
ticket.service
|
||||||
|
)
|
||||||
|
)
|
||||||
return HttpResponse("yes\n", content_type="text/plain")
|
return HttpResponse("yes\n", content_type="text/plain")
|
||||||
except ServiceTicket.DoesNotExist:
|
except ServiceTicket.DoesNotExist:
|
||||||
|
logger.warning(
|
||||||
|
(
|
||||||
|
"Validate: Service ticket %s not found or "
|
||||||
|
"already validated, auth to %s failed"
|
||||||
|
) % (
|
||||||
|
ticket,
|
||||||
|
service
|
||||||
|
)
|
||||||
|
)
|
||||||
return HttpResponse("no\n", content_type="text/plain")
|
return HttpResponse("no\n", content_type="text/plain")
|
||||||
else:
|
else:
|
||||||
|
logger.warning("Validate: service or ticket missing")
|
||||||
return HttpResponse("no\n", content_type="text/plain")
|
return HttpResponse("no\n", content_type="text/plain")
|
||||||
|
|
||||||
|
|
||||||
@ -548,6 +585,7 @@ class ValidateService(View, AttributesMixin):
|
|||||||
self.renew = True if request.GET.get('renew') else False
|
self.renew = True if request.GET.get('renew') else False
|
||||||
|
|
||||||
if not self.service or not self.ticket:
|
if not self.service or not self.ticket:
|
||||||
|
logger.warning("ValidateService: missing ticket or service")
|
||||||
return ValidateError(
|
return ValidateError(
|
||||||
'INVALID_REQUEST',
|
'INVALID_REQUEST',
|
||||||
"you must specify a service and a ticket"
|
"you must specify a service and a ticket"
|
||||||
@ -568,6 +606,18 @@ class ValidateService(View, AttributesMixin):
|
|||||||
if self.pgt_url and self.pgt_url.startswith("https://"):
|
if self.pgt_url and self.pgt_url.startswith("https://"):
|
||||||
return self.process_pgturl(params)
|
return self.process_pgturl(params)
|
||||||
else:
|
else:
|
||||||
|
logger.info(
|
||||||
|
"ValidateService: ticket %s validated for user %s on service %s." % (
|
||||||
|
self.ticket.value,
|
||||||
|
self.ticket.user.username,
|
||||||
|
self.ticket.service
|
||||||
|
)
|
||||||
|
)
|
||||||
|
logger.debug(
|
||||||
|
"ValidateService: User attributs are:\n%s" % (
|
||||||
|
pprint.pformat(self.ticket.attributs),
|
||||||
|
)
|
||||||
|
)
|
||||||
return render(
|
return render(
|
||||||
request,
|
request,
|
||||||
"cas_server/serviceValidate.xml",
|
"cas_server/serviceValidate.xml",
|
||||||
@ -575,6 +625,9 @@ class ValidateService(View, AttributesMixin):
|
|||||||
content_type="text/xml; charset=utf-8"
|
content_type="text/xml; charset=utf-8"
|
||||||
)
|
)
|
||||||
except ValidateError as error:
|
except ValidateError as error:
|
||||||
|
logger.warning(
|
||||||
|
"ValidateService: validation error: %s %s" % (error.code, error.msg)
|
||||||
|
)
|
||||||
return error.render(request)
|
return error.render(request)
|
||||||
|
|
||||||
def process_ticket(self):
|
def process_ticket(self):
|
||||||
@ -598,11 +651,11 @@ class ValidateService(View, AttributesMixin):
|
|||||||
for prox in ticket.proxies.all():
|
for prox in ticket.proxies.all():
|
||||||
proxies.append(prox.url)
|
proxies.append(prox.url)
|
||||||
else:
|
else:
|
||||||
raise ValidateError('INVALID_TICKET')
|
raise ValidateError('INVALID_TICKET', self.ticket)
|
||||||
ticket.validate = True
|
ticket.validate = True
|
||||||
ticket.save()
|
ticket.save()
|
||||||
if ticket.service != self.service:
|
if ticket.service != self.service:
|
||||||
raise ValidateError('INVALID_SERVICE')
|
raise ValidateError('INVALID_SERVICE', self.service)
|
||||||
return ticket, proxies
|
return ticket, proxies
|
||||||
except (ServiceTicket.DoesNotExist, ProxyTicket.DoesNotExist):
|
except (ServiceTicket.DoesNotExist, ProxyTicket.DoesNotExist):
|
||||||
raise ValidateError('INVALID_TICKET', 'ticket not found')
|
raise ValidateError('INVALID_TICKET', 'ticket not found')
|
||||||
@ -626,6 +679,22 @@ class ValidateService(View, AttributesMixin):
|
|||||||
params['proxyGrantingTicket'] = proxyid
|
params['proxyGrantingTicket'] = proxyid
|
||||||
else:
|
else:
|
||||||
pticket.delete()
|
pticket.delete()
|
||||||
|
logger.info(
|
||||||
|
(
|
||||||
|
"ValidateService: ticket %s validated for user %s on service %s. "
|
||||||
|
"Proxy Granting Ticket transmited to %s."
|
||||||
|
) % (
|
||||||
|
self.ticket.value,
|
||||||
|
self.ticket.user.username,
|
||||||
|
self.ticket.service,
|
||||||
|
self.pgt_url
|
||||||
|
)
|
||||||
|
)
|
||||||
|
logger.debug(
|
||||||
|
"ValidateService: User attributs are:\n%s" % (
|
||||||
|
pprint.pformat(self.ticket.attributs),
|
||||||
|
)
|
||||||
|
)
|
||||||
return render(
|
return render(
|
||||||
self.request,
|
self.request,
|
||||||
"cas_server/serviceValidate.xml",
|
"cas_server/serviceValidate.xml",
|
||||||
@ -668,6 +737,7 @@ class Proxy(View):
|
|||||||
"you must specify and pgt and targetService"
|
"you must specify and pgt and targetService"
|
||||||
)
|
)
|
||||||
except ValidateError as error:
|
except ValidateError as error:
|
||||||
|
logger.warning("Proxy: validation error: %s %s" % (error.code, error.msg))
|
||||||
return error.render(request)
|
return error.render(request)
|
||||||
|
|
||||||
def process_proxy(self):
|
def process_proxy(self):
|
||||||
@ -678,7 +748,7 @@ class Proxy(View):
|
|||||||
if not pattern.proxy:
|
if not pattern.proxy:
|
||||||
raise ValidateError(
|
raise ValidateError(
|
||||||
'UNAUTHORIZED_SERVICE',
|
'UNAUTHORIZED_SERVICE',
|
||||||
'the service do not allow proxy ticket'
|
'the service %s do not allow proxy ticket' % self.target_service
|
||||||
)
|
)
|
||||||
# is the proxy granting ticket valid
|
# is the proxy granting ticket valid
|
||||||
ticket = ProxyGrantingTicket.objects.get(
|
ticket = ProxyGrantingTicket.objects.get(
|
||||||
@ -694,6 +764,12 @@ class Proxy(View):
|
|||||||
pattern,
|
pattern,
|
||||||
renew=False)
|
renew=False)
|
||||||
models.Proxy.objects.create(proxy_ticket=pticket, url=ticket.service)
|
models.Proxy.objects.create(proxy_ticket=pticket, url=ticket.service)
|
||||||
|
logger.info(
|
||||||
|
"Proxy ticket created for user %s on service %s." % (
|
||||||
|
ticket.user.username,
|
||||||
|
self.target_service
|
||||||
|
)
|
||||||
|
)
|
||||||
return render(
|
return render(
|
||||||
self.request,
|
self.request,
|
||||||
"cas_server/proxy.xml",
|
"cas_server/proxy.xml",
|
||||||
@ -701,9 +777,9 @@ class Proxy(View):
|
|||||||
content_type="text/xml; charset=utf-8"
|
content_type="text/xml; charset=utf-8"
|
||||||
)
|
)
|
||||||
except ProxyGrantingTicket.DoesNotExist:
|
except ProxyGrantingTicket.DoesNotExist:
|
||||||
raise ValidateError('INVALID_TICKET', 'PGT not found')
|
raise ValidateError('INVALID_TICKET', 'PGT %s not found' % self.pgt)
|
||||||
except ServicePattern.DoesNotExist:
|
except ServicePattern.DoesNotExist:
|
||||||
raise ValidateError('UNAUTHORIZED_SERVICE')
|
raise ValidateError('UNAUTHORIZED_SERVICE', self.target_service)
|
||||||
except (models.BadUsername, models.BadFilter, models.UserFieldNotDefined):
|
except (models.BadUsername, models.BadFilter, models.UserFieldNotDefined):
|
||||||
raise ValidateError(
|
raise ValidateError(
|
||||||
'UNAUTHORIZED_USER',
|
'UNAUTHORIZED_USER',
|
||||||
@ -771,6 +847,17 @@ class SamlValidate(View, AttributesMixin):
|
|||||||
params['username'] = self.ticket.user.attributs.get(
|
params['username'] = self.ticket.user.attributs.get(
|
||||||
self.ticket.service_pattern.user_field
|
self.ticket.service_pattern.user_field
|
||||||
)
|
)
|
||||||
|
logger.info(
|
||||||
|
"SamlValidate: ticket %s validated for user %s on service %s." % (
|
||||||
|
self.ticket.value,
|
||||||
|
self.ticket.user.username,
|
||||||
|
self.ticket.service
|
||||||
|
)
|
||||||
|
)
|
||||||
|
logger.debug(
|
||||||
|
"SamlValidate: User attributs are:\n%s" % pprint.pformat(self.ticket.attributs)
|
||||||
|
)
|
||||||
|
|
||||||
return render(
|
return render(
|
||||||
request,
|
request,
|
||||||
"cas_server/samlValidate.xml",
|
"cas_server/samlValidate.xml",
|
||||||
@ -778,6 +865,7 @@ class SamlValidate(View, AttributesMixin):
|
|||||||
content_type="text/xml; charset=utf-8"
|
content_type="text/xml; charset=utf-8"
|
||||||
)
|
)
|
||||||
except SamlValidateError as error:
|
except SamlValidateError as error:
|
||||||
|
logger.warning("SamlValidate: validation error: %s %s" % (error.code, error.msg))
|
||||||
return error.render(request)
|
return error.render(request)
|
||||||
|
|
||||||
def process_ticket(self):
|
def process_ticket(self):
|
||||||
@ -800,17 +888,17 @@ class SamlValidate(View, AttributesMixin):
|
|||||||
else:
|
else:
|
||||||
raise SamlValidateError(
|
raise SamlValidateError(
|
||||||
'AuthnFailed',
|
'AuthnFailed',
|
||||||
'ticket should begin with PT- or ST-'
|
'ticket %s should begin with PT- or ST-' % ticket
|
||||||
)
|
)
|
||||||
ticket.validate = True
|
ticket.validate = True
|
||||||
ticket.save()
|
ticket.save()
|
||||||
if ticket.service != self.target:
|
if ticket.service != self.target:
|
||||||
raise SamlValidateError(
|
raise SamlValidateError(
|
||||||
'AuthnFailed',
|
'AuthnFailed',
|
||||||
'TARGET do not match ticket service'
|
'TARGET %s do not match ticket service' % self.target
|
||||||
)
|
)
|
||||||
return ticket
|
return ticket
|
||||||
except (IndexError, KeyError):
|
except (IndexError, KeyError):
|
||||||
raise SamlValidateError('VersionMismatch')
|
raise SamlValidateError('VersionMismatch')
|
||||||
except (ServiceTicket.DoesNotExist, ProxyTicket.DoesNotExist):
|
except (ServiceTicket.DoesNotExist, ProxyTicket.DoesNotExist):
|
||||||
raise SamlValidateError('AuthnFailed', 'ticket not found')
|
raise SamlValidateError('AuthnFailed', 'ticket %s not found' % ticket)
|
||||||
|
Loading…
Reference in New Issue
Block a user