Added logger specification to the configuration

This commit is contained in:
Roland Hedberg
2011-03-31 12:41:52 +02:00
parent b0a2ab971f
commit ea8cf6dbcb
6 changed files with 217 additions and 13 deletions

View File

@@ -104,6 +104,8 @@ class Saml2Client(object):
self.metadata = self.config.metadata
self.sec = security_context(config)
self.logger = self.config.setup_logger()
if virtual_organization:
self.vorg = VirtualOrg(self, virtual_organization)
else:
@@ -180,6 +182,9 @@ class Saml2Client(object):
except KeyError:
raise Exception("Missing entity_id specification")
if log is None:
log = self.logger
reply_addr = self._service_url()
resp = None
@@ -255,7 +260,10 @@ class Saml2Client(object):
request.name_id_policy = name_id_policy
request.issuer = self.issuer(spentityid)
if log is None:
log = self.logger
if log:
log.info("REQUEST: %s" % request)
@@ -315,7 +323,10 @@ class Saml2Client(object):
location = self._sso_location(entityid)
service_url = self._service_url()
my_name = self._my_name()
if log is None:
log = self.logger
if log:
log.info("spentityid: %s" % spentityid)
log.info("location: %s" % location)
@@ -419,7 +430,10 @@ class Saml2Client(object):
:param log: Function to use for logging
:return: The attributes returned
"""
if log is None:
log = self.logger
session_id = sid()
issuer = self.issuer(issuer_id)
@@ -448,7 +462,7 @@ class Saml2Client(object):
log.info("Verifying response")
try:
aresp = attribute_response(self.config, "", issuer, log=log)
aresp = attribute_response(self.config, issuer, log)
except Exception, exc:
if log:
log.error("%s", (exc,))
@@ -468,8 +482,7 @@ class Saml2Client(object):
return None
def construct_logout_request(self, subject_id, destination,
issuer_entity_id,
reason=None, expire=None):
issuer_entity_id, reason=None, expire=None):
""" Constructs a LogoutRequest
:param subject_id: The identifier of the subject
@@ -526,7 +539,10 @@ class Saml2Client(object):
if SOAP binding has been used the just the result of that
conversation.
"""
if log is None:
log = self.logger
if log:
log.info("logout request for: %s" % subject_id)
@@ -548,7 +564,9 @@ class Saml2Client(object):
# for all where I can use the SOAP binding, do those first
not_done = entity_ids[:]
response = False
if log is None:
log = self.logger
for entity_id in entity_ids:
response = False
@@ -645,6 +663,9 @@ class Saml2Client(object):
:return: 4-tuple of (session_id of the last sent logout request,
response message, response headers and message)
"""
if log is None:
log = self.logger
if log:
log.info("state: %s" % (self.state,))
status = self.state[response.in_response_to]
@@ -679,6 +700,8 @@ class Saml2Client(object):
"""
response = None
if log is None:
log = self.logger
if xmlstr:
try:
@@ -732,6 +755,8 @@ class Saml2Client(object):
"""
headers = []
success = False
if log is None:
log = self.logger
try:
saml_request = get['SAMLRequest']
@@ -779,7 +804,9 @@ class Saml2Client(object):
:param subject_id: the id of the current logged user
:return: What is returned also depends on which binding is used.
"""
if log is None:
log = self.logger
if binding == BINDING_HTTP_REDIRECT:
return self.http_redirect_logout_request(request, subject_id, log)

View File

@@ -3,9 +3,15 @@
__author__ = 'rolandh'
import sys
import logging
import logging.handlers
from importlib import import_module
from saml2 import BINDING_SOAP, BINDING_HTTP_REDIRECT
from saml2 import metadata
from saml2 import root_logger
from saml2.attribute_converter import ac_factory
from saml2.assertion import Policy
@@ -16,6 +22,7 @@ COMMON_ARGS = ["entityid", "xmlsec_binary", "debug", "key_file", "cert_file",
"contact_person",
"name_form",
"virtual_organization",
"logger"
]
SP_ARGS = [
@@ -48,6 +55,24 @@ SPEC = {
"aa": COMMON_ARGS + COMPLEX_ARGS + AA_IDP_ARGS,
}
# --------------- Logging stuff ---------------
LOG_LEVEL = {'debug': logging.DEBUG,
'info': logging.INFO,
'warning': logging.WARNING,
'error': logging.ERROR,
'critical': logging.CRITICAL}
LOG_HANDLER = {
"rotating": logging.handlers.RotatingFileHandler,
"syslog": logging.handlers.SysLogHandler,
"timerotate": logging.handlers.TimedRotatingFileHandler,
}
LOG_FORMAT = "%(asctime)s - %(name)s - %(levelname)s - %(message)s"
# -----------------------------------------------------------------
class Config(object):
def_context = ""
@@ -193,6 +218,52 @@ class Config(object):
except IndexError:
return None
def setup_logger(self):
try:
_logconf = self.logger
except KeyError:
return None
if root_logger.level != logging.NOTSET: # Someone got there before me
return root_logger
if "loglevel" in _logconf:
root_logger.setLevel(LOG_LEVEL[_logconf["loglevel"]])
else: # reasonable default
root_logger.setLevel(logging.WARNING)
handler = None
for htyp in LOG_HANDLER:
if htyp in _logconf:
if htyp == "syslog":
args = _logconf[htyp]
if "socktype" in args:
import socket
if args["socktype"] == "dgram":
args["socktype"] = socket.SOCK_DGRAM
elif args["socktype"] == "stream":
args["socktype"] = socket.SOCK_STREAM
else:
raise Exception("Unknown socktype!")
handler = LOG_HANDLER[htyp](**args)
else:
handler = LOG_HANDLER[htyp](**_logconf[htyp])
break
if handler is None:
raise Exception("You have to define a log handler")
if "format" in _logconf:
formatter = logging.Formatter(_logconf["format"])
else:
formatter = logging.Formatter(LOG_FORMAT)
handler.setFormatter(formatter)
root_logger.addHandler(handler)
return root_logger
class SPConfig(Config):
def_context = "sp"
@@ -238,7 +309,7 @@ class SPConfig(Config):
return []
def idps(self, langpref=["en"]):
def idps(self, langpref=None):
""" Returns a dictionary of usefull IdPs, the keys being the
entity ID of the service and the names of the services as values
@@ -246,6 +317,9 @@ class SPConfig(Config):
is used.
:return: Dictionary
"""
if langpref is None:
langpref = ["en"]
if self.idp:
return dict([(e, nd[0]) for (e,
nd) in self.metadata.idps(langpref).items() if e in self.idp])

View File

@@ -214,9 +214,13 @@ class Server(object):
self.conf = config
else:
raise Exception("Missing configuration")
if self.log is None:
self.log = self.conf.setup_logger()
self.metadata = self.conf.metadata
self.sec = security_context(self.conf, log)
# if cache:
# if isinstance(cache, basestring):
# self.cache = Cache(cache)
@@ -638,7 +642,7 @@ class Server(object):
sp_entity_id = request.issuer.text.strip()
binding = None
destination = ""
destinations = []
for binding in bindings:
destinations = self.conf.single_logout_services(sp_entity_id,
binding)

View File

@@ -40,5 +40,13 @@ CONFIG={
"email_address": ["tech@eample.com", "tech@example.org"],
"contact_type": "technical"
},
]
],
"logger": {
"rotating": {
"filename": "sp.log",
"maxBytes": 100000,
"backupCount": 5,
},
"loglevel": "warning",
}
}

View File

@@ -0,0 +1,54 @@
__author__ = 'rolandh'
CONFIG={
"entityid" : "urn:mace:example.com:saml:roland:sp",
"name" : "urn:mace:example.com:saml:roland:sp",
"description": "My own SP",
"service": {
"sp": {
"endpoints":{
"assertion_consumer_service": ["http://lingon.catalogix.se:8087/"],
},
"required_attributes": ["surName", "givenName", "mail"],
"optional_attributes": ["title"],
"idp": ["urn:mace:example.com:saml:roland:idp"],
}
},
"debug" : 1,
"key_file" : "test.key",
"cert_file" : "test.pem",
"xmlsec_binary" : "/usr/local/bin/xmlsec1",
"metadata": {
"local": ["idp.xml", "vo_metadata.xml"],
},
"virtual_organization" : {
"urn:mace:example.com:it:tek":{
"nameid_format" : "urn:oid:1.3.6.1.4.1.1466.115.121.1.15-NameID",
"common_identifier": "umuselin",
}
},
"subject_data": "subject_data.db",
"accepted_time_diff": 60,
"attribute_map_dir" : "attributemaps",
"organization": {
"name": ("AB Exempel", "se"),
"display_name": ("AB Exempel", "se"),
"url": "http://www.example.org",
},
"contact_person": [{
"given_name": "Roland",
"sur_name": "Hedberg",
"telephone_number": "+46 70 100 0000",
"email_address": ["tech@eample.com", "tech@example.org"],
"contact_type": "technical"
},
],
"logger": {
"syslog": {
"address": ("localhost", 514),
"facility": "local3",
"socktype": "dgram",
},
"loglevel": "info",
}
}

View File

@@ -6,6 +6,9 @@ from saml2.config import SPConfig, IdPConfig, Config
from saml2.metadata import MetaData
from py.test import raises
from saml2 import root_logger
import logging
sp1 = {
"entityid" : "urn:mace:umu.se:saml:roland:sp",
"service": {
@@ -196,6 +199,40 @@ def test_wayf():
idps = c.idps(["se","en"])
assert idps == {'urn:mace:example.com:saml:roland:idp': 'Exempel AB'}
c.setup_logger()
assert root_logger.level != logging.NOTSET
assert root_logger.level == logging.WARNING
assert len(root_logger.handlers) == 1
assert isinstance(root_logger.handlers[0],
logging.handlers.RotatingFileHandler)
handler = root_logger.handlers[0]
assert handler.backupCount == 5
assert handler.maxBytes == 100000
assert handler.mode == "a"
assert root_logger.name == "pySAML2"
assert root_logger.level == 30
def test_conf_syslog():
c = SPConfig().load_file("server_conf_syslog")
c.context = "sp"
# otherwise the logger setting is not changed
root_logger.level == logging.NOTSET
c.setup_logger()
assert root_logger.level != logging.NOTSET
assert root_logger.level == logging.INFO
assert len(root_logger.handlers) == 1
assert isinstance(root_logger.handlers[0],
logging.handlers.SyslogHandler)
handler = root_logger.handlers[0]
assert handler.backupCount == 5
assert handler.maxBytes == 100000
assert handler.mode == "a"
assert root_logger.name == "pySAML2"
assert root_logger.level == 20
#noinspection PyUnresolvedReferences
def test_3():
cnf = Config()