summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoland Hedberg <roland.hedberg@adm.umu.se>2012-06-27 07:50:13 +0200
committerRoland Hedberg <roland.hedberg@adm.umu.se>2012-06-27 07:50:13 +0200
commit2495375de47d0a4bb77aaac91d2ea9421a03bde4 (patch)
tree759721f6b72f4de534f813ff8543077306e255f6
parentce1eb1502587d1b51fafca4caa36fd3e6c2db98c (diff)
downloadpysaml2-2495375de47d0a4bb77aaac91d2ea9421a03bde4.tar.gz
Changed logging setup
-rw-r--r--src/saml2/assertion.py2
-rw-r--r--src/saml2/attribute_resolver.py9
-rw-r--r--src/saml2/binding.py3
-rw-r--r--src/saml2/cache.py3
-rw-r--r--src/saml2/client.py228
-rw-r--r--src/saml2/config.py4
-rw-r--r--src/saml2/ecp.py22
-rw-r--r--src/saml2/ecp_client.py24
-rw-r--r--src/saml2/encdec.py3
-rw-r--r--src/saml2/httplib2cookie.py3
-rw-r--r--src/saml2/httputil.py4
-rw-r--r--src/saml2/mcache.py2
-rw-r--r--src/saml2/mdbcache.py3
-rw-r--r--src/saml2/metadata.py21
-rw-r--r--src/saml2/population.py10
-rw-r--r--src/saml2/request.py54
-rw-r--r--src/saml2/response.py5
-rw-r--r--src/saml2/s_utils.py35
-rw-r--r--src/saml2/server.py12
-rw-r--r--src/saml2/sigver.py78
-rw-r--r--src/saml2/soap.py21
-rw-r--r--src/saml2/virtual_org.py27
22 files changed, 245 insertions, 328 deletions
diff --git a/src/saml2/assertion.py b/src/saml2/assertion.py
index 845e011a..3105f12c 100644
--- a/src/saml2/assertion.py
+++ b/src/saml2/assertion.py
@@ -14,6 +14,7 @@
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
+import logging
import re
import sys
@@ -28,6 +29,7 @@ from saml2.s_utils import sid, MissingValue
from saml2.s_utils import factory
from saml2.s_utils import assertion_factory
+logger = logging.getLogger(__name__)
def _filter_values(vals, vlist=None, must=False):
""" Removes values from *vals* that does not appear in vlist
diff --git a/src/saml2/attribute_resolver.py b/src/saml2/attribute_resolver.py
index f6d07334..786a22f6 100644
--- a/src/saml2/attribute_resolver.py
+++ b/src/saml2/attribute_resolver.py
@@ -21,6 +21,11 @@ to do attribute aggregation.
"""
import saml2
+import logging
+from saml2.client import Saml2Client
+
+logger = logging.getLogger(__name__)
+
DEFAULT_BINDING = saml2.BINDING_SOAP
class AttributeResolver(object):
@@ -32,7 +37,7 @@ class AttributeResolver(object):
self.saml2client = saml2client
self.metadata = saml2client.config.metadata
else:
- self.saml2client = saml2.client.Saml2Client(config)
+ self.saml2client = Saml2Client(config)
def extend(self, subject_id, issuer, vo_members, name_id_format=None,
sp_name_qualifier=None, log=None, real_id=None):
@@ -42,7 +47,7 @@ class AttributeResolver(object):
:param issuer: Who am I the poses the query
:param vo_members: The entity IDs of the IdP who I'm going to ask
for extra attributes
- :param nameid_format: Used to make the IdPs aware of what's going
+ :param name_id_format: Used to make the IdPs aware of what's going
on here
:param log: Where to log exciting information
:return: A dictionary with all the collected information about the
diff --git a/src/saml2/binding.py b/src/saml2/binding.py
index acef290d..8fbd91a2 100644
--- a/src/saml2/binding.py
+++ b/src/saml2/binding.py
@@ -28,6 +28,9 @@ import base64
import urllib
from saml2.s_utils import deflate_and_base64_encode
from saml2.soap import SOAPClient, HTTPClient
+import logging
+
+logger = logging.getLogger(__name__)
try:
from xml.etree import cElementTree as ElementTree
diff --git a/src/saml2/cache.py b/src/saml2/cache.py
index 62258dbe..fc7b57c4 100644
--- a/src/saml2/cache.py
+++ b/src/saml2/cache.py
@@ -2,6 +2,9 @@
import shelve
from saml2 import time_util
+import logging
+
+logger = logging.getLogger(__name__)
# The assumption is that any subject may consist of data
# gathered from several different sources, all with their own
diff --git a/src/saml2/client.py b/src/saml2/client.py
index 50c150c2..831c31ef 100644
--- a/src/saml2/client.py
+++ b/src/saml2/client.py
@@ -58,6 +58,9 @@ from saml2 import BINDING_HTTP_REDIRECT
from saml2 import BINDING_SOAP
from saml2 import BINDING_HTTP_POST
from saml2 import BINDING_PAOS
+import logging
+
+logger = logging.getLogger(__name__)
SSO_BINDING = saml2.BINDING_HTTP_REDIRECT
@@ -82,9 +85,8 @@ class LogoutError(Exception):
class Saml2Client(object):
""" The basic pySAML2 service provider class """
- def __init__(self, config=None,
- identity_cache=None, state_cache=None,
- virtual_organization=None, config_file="", logger=None):
+ def __init__(self, config=None, identity_cache=None, state_cache=None,
+ virtual_organization=None, config_file=""):
"""
:param config: A saml2.config.Config instance
:param identity_cache: Where the class should store identity information
@@ -110,18 +112,12 @@ class Saml2Client(object):
self.metadata = self.config.metadata
- if logger is None:
- self.logger = self.config.setup_logger()
- else:
- self.logger = logger
-
# we copy the config.debug variable in an internal
# field for convenience and because we may need to
# change it during the tests
self.debug = self.config.debug
- self.sec = security_context(self.config, log=self.logger,
- debug=self.debug)
+ self.sec = security_context(self.config)
if virtual_organization:
self.vorg = VirtualOrg(self, virtual_organization)
@@ -173,8 +169,7 @@ class Saml2Client(object):
try:
return self.config.single_sign_on_services(entityid, binding)[0]
except IndexError:
- if self.logger:
- self.logger.info("_sso_location: %s, %s" % (entityid,
+ logger.info("_sso_location: %s, %s" % (entityid,
binding))
raise IdpUnspecified("No IdP to send to given the premises")
@@ -205,15 +200,13 @@ class Saml2Client(object):
else:
return None
- def response(self, post, outstanding, log=None, decode=True,
- asynchop=True):
+ def response(self, post, outstanding, decode=True, asynchop=True):
""" Deal with an AuthnResponse or LogoutResponse
:param post: The reply as a dictionary
:param outstanding: A dictionary with session IDs as keys and
the original web request from the user before redirection
as values.
- :param log: where loggin should go.
:param decode: Whether the response is Base64 encoded or not
:param asynchop: Whether the response was return over a asynchronous
connection. SOAP for instance is synchronous
@@ -230,39 +223,33 @@ 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
if saml_response:
try:
resp = response_factory(saml_response, self.config,
- reply_addr, outstanding, log,
- debug=self.debug, decode=decode,
+ reply_addr, outstanding, decode=decode,
asynchop=asynchop,
allow_unsolicited=self.allow_unsolicited)
except Exception, exc:
- if log:
- log.error("%s" % exc)
+ logger.error("%s" % exc)
return None
- if log:
- log.debug(">> %s", resp)
+ logger.debug(">> %s", resp)
resp = resp.verify()
if isinstance(resp, AuthnResponse):
self.users.add_information_about_person(resp.session_info())
- if log:
- log.info("--- ADDED person info ----")
+ logger.info("--- ADDED person info ----")
elif isinstance(resp, LogoutResponse):
- self.handle_logout_response(resp, log)
- elif log:
- log.error("Response type not supported: %s" % saml2.class_name(resp))
+ self.handle_logout_response(resp)
+ else:
+ logger.error("Response type not supported: %s" % (
+ saml2.class_name(resp),))
return resp
def authn_request(self, query_id, destination, service_url, spentityid,
- my_name="", vorg="", scoping=None, log=None, sign=None,
+ my_name="", vorg="", scoping=None, sign=None,
binding=saml2.BINDING_HTTP_POST,
nameid_format=saml.NAMEID_FORMAT_TRANSIENT):
""" Creates an authentication request.
@@ -274,7 +261,6 @@ class Saml2Client(object):
:param my_name: The name of this service.
:param vorg: The vitual organization the service belongs to.
:param scoping: The scope of the request
- :param log: A service to which logs should be written
:param sign: Whether the request should be signed or not.
:param binding: The protocol to use for the Response !!
:return: <samlp:AuthnRequest> instance
@@ -321,11 +307,7 @@ 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)
+ logger.info("REQUEST: %s" % request)
return signed_instance_factory(request, self.sec, to_sign)
@@ -357,16 +339,11 @@ class Saml2Client(object):
my_name = self._my_name()
- if log is None:
- log = self.logger
-
- if log:
- log.info("spentityid: %s" % spentityid)
- log.info("service_url: %s" % service_url)
- log.info("my_name: %s" % my_name)
+ logger.info("spentityid: %s\nservice_url: %s\nmy_name: %s" % (
+ spentityid, service_url, my_name))
return self.authn_request(session_id, location, service_url,
- spentityid, my_name, vorg, scoping, log,
+ spentityid, my_name, vorg, scoping,
sign, binding=binding)
def authenticate(self, entityid=None, relay_state="",
@@ -471,7 +448,7 @@ class Saml2Client(object):
def attribute_query(self, subject_id, destination, issuer_id=None,
attribute=None, sp_name_qualifier=None, name_qualifier=None,
- nameid_format=None, log=None, real_id=None):
+ nameid_format=None, real_id=None):
""" Does a attribute request to an attribute authority, this is
by default done over SOAP. Other bindings could be used but not
supported right now.
@@ -486,60 +463,49 @@ class Saml2Client(object):
:param name_qualifier: The unique identifier of the identity
provider that generated the identifier.
:param nameid_format: The format of the name ID
- :param log: Function to use for logging
:param real_id: The identifier which is the key to this entity in the
identity database
:return: The attributes returned
"""
- if log is None:
- log = self.logger
-
session_id = sid()
issuer = self._issuer(issuer_id)
request = self.create_attribute_query(session_id, subject_id,
destination, issuer, attribute, sp_name_qualifier,
name_qualifier, nameid_format=nameid_format)
-
- if log:
- log.info("Request, created: %s" % request)
+
+ logger.info("Request, created: %s" % request)
soapclient = SOAPClient(destination, self.config.key_file,
self.config.cert_file,
ca_certs=self.config.ca_certs)
- if log:
- log.info("SOAP client initiated")
+ logger.info("SOAP client initiated")
try:
response = soapclient.send(request)
except Exception, exc:
- if log:
- log.info("SoapClient exception: %s" % (exc,))
+ logger.info("SoapClient exception: %s" % (exc,))
return None
- if log:
- log.info("SOAP request sent and got response: %s" % response)
+ logger.info("SOAP request sent and got response: %s" % response)
# fil = open("response.xml", "w")
# fil.write(response)
# fil.close()
if response:
- if log:
- log.info("Verifying response")
+ logger.info("Verifying response")
try:
# synchronous operation
- aresp = attribute_response(self.config, issuer, log=log)
+ aresp = attribute_response(self.config, issuer)
except Exception, exc:
- if log:
- log.error("%s", (exc,))
+ logger.error("%s", (exc,))
return None
_resp = aresp.loads(response, False, soapclient.response).verify()
if _resp is None:
- if log:
- log.error("Didn't like the response")
+ logger.error("Didn't like the response")
return None
session_info = _resp.session_info()
@@ -548,13 +514,11 @@ class Saml2Client(object):
if real_id is not None:
session_info["name_id"] = real_id
self.users.add_information_about_person(session_info)
-
- if log:
- log.info("session: %s" % session_info)
+
+ logger.info("session: %s" % session_info)
return session_info
else:
- if log:
- log.info("No response")
+ logger.info("No response")
return None
def construct_logout_request(self, subject_id, destination,
@@ -595,8 +559,8 @@ class Saml2Client(object):
return request
- def global_logout(self, subject_id, reason="", expire=None,
- sign=None, log=None, return_to="/"):
+ def global_logout(self, subject_id, reason="", expire=None, sign=None,
+ return_to="/"):
""" More or less a layer of indirection :-/
Bootstrapping the whole thing by finding all the IdPs that should
be notified.
@@ -607,7 +571,6 @@ class Saml2Client(object):
:param expire: The latest the log out should happen.
:param sign: Whether the request should be signed or not.
This also depends on what binding is used.
- :param log: A logging function
:param return_to: Where to send the user after she has been
logged out.
:return: Depends on which binding is used:
@@ -616,17 +579,13 @@ class Saml2Client(object):
conversation.
"""
- if log is None:
- log = self.logger
-
- if log:
- log.info("logout request for: %s" % subject_id)
+ logger.info("logout request for: %s" % subject_id)
# find out which IdPs/AAs I should notify
entity_ids = self.users.issuers_of_info(subject_id)
return self._logout(subject_id, entity_ids, reason, expire,
- sign, log, return_to)
+ sign, return_to)
def _logout(self, subject_id, entity_ids, reason, expire,
sign=None, log=None, return_to="/"):
@@ -640,8 +599,6 @@ 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
@@ -654,9 +611,8 @@ class Saml2Client(object):
continue
destination = destinations[0]
-
- if log:
- log.info("destination to provider: %s" % destination)
+
+ logger.info("destination to provider: %s" % destination)
request = self.construct_logout_request(subject_id, destination,
entity_id, reason, expire)
@@ -670,9 +626,8 @@ class Saml2Client(object):
request.signature = pre_signature_part(request.id,
self.sec.my_cert, 1)
to_sign = [(class_name(request), request.id)]
-
- if log:
- log.info("REQUEST: %s" % request)
+
+ logger.info("REQUEST: %s" % request)
request = signed_instance_factory(request, self.sec, to_sign)
@@ -683,17 +638,14 @@ class Saml2Client(object):
log=log,
ca_certs=self.config.ca_certs)
if response:
- if log:
- log.info("Verifying response")
+ logger.info("Verifying response")
response = self.logout_response(response, log)
if response:
not_done.remove(entity_id)
- if log:
- log.info("OK response from %s" % destination)
+ logger.info("OK response from %s" % destination)
else:
- if log:
- log.info(
+ logger.info(
"NOT OK response from %s" % destination)
else:
@@ -737,25 +689,19 @@ class Saml2Client(object):
self.users.remove_person(subject_id)
return True
- def handle_logout_response(self, response, log):
+ def handle_logout_response(self, response):
""" handles a Logout response
:param response: A response.Response instance
- :param log: A logging function
: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,))
+ logger.info("state: %s" % (self.state,))
status = self.state[response.in_response_to]
- if log:
- log.info("status: %s" % (status,))
+ logger.info("status: %s" % (status,))
issuer = response.issuer()
- if log:
- log.info("issuer: %s" % issuer)
+ logger.info("issuer: %s" % issuer)
del self.state[response.in_response_to]
if status["entity_ids"] == [issuer]: # done
self.local_logout(status["subject_id"])
@@ -766,14 +712,12 @@ class Saml2Client(object):
status["entity_ids"],
status["reason"],
status["not_on_or_after"],
- status["sign"],
- log, )
+ status["sign"])
- def logout_response(self, xmlstr, log=None, binding=BINDING_SOAP):
+ def logout_response(self, xmlstr, binding=BINDING_SOAP):
""" Deal with a LogoutResponse
:param xmlstr: The response as a xml string
- :param log: logging function
:param binding: What type of binding this message came through.
:return: None if the reply doesn't contain a valid SAML LogoutResponse,
otherwise the reponse if the logout was successful and None if it
@@ -781,8 +725,6 @@ class Saml2Client(object):
"""
response = None
- if log is None:
- log = self.logger
if xmlstr:
try:
@@ -790,16 +732,13 @@ class Saml2Client(object):
return_addr = self.config.endpoint("single_logout_service",
binding=binding)[0]
except Exception:
- if log:
- log.info("Not supposed to handle this!")
+ logger.info("Not supposed to handle this!")
return None
try:
- response = LogoutResponse(self.sec, return_addr,
- debug=self.debug, log=log)
+ response = LogoutResponse(self.sec, return_addr)
except Exception, exc:
- if log:
- log.info("%s" % exc)
+ logger.info("%s" % exc)
return None
if binding == BINDING_HTTP_REDIRECT:
@@ -807,8 +746,7 @@ class Saml2Client(object):
elif binding == BINDING_HTTP_POST:
xmlstr = base64.b64decode(xmlstr)
- if log:
- log.debug("XMLSTR: %s" % xmlstr)
+ logger.debug("XMLSTR: %s" % xmlstr)
response = response.loads(xmlstr, False)
@@ -817,11 +755,10 @@ class Saml2Client(object):
if not response:
return None
-
- if log:
- log.debug(response)
- return self.handle_logout_response(response, log)
+ logger.debug(response)
+
+ return self.handle_logout_response(response)
return response
@@ -836,8 +773,6 @@ class Saml2Client(object):
"""
headers = []
success = False
- if log is None:
- log = self.logger
try:
saml_request = get['SAMLRequest']
@@ -848,8 +783,7 @@ class Saml2Client(object):
xml = decode_base64_and_inflate(saml_request)
request = samlp.logout_request_from_string(xml)
- if log:
- log.debug(request)
+ logger.debug(request)
if request.name_id.text == subject_id:
status = samlp.STATUS_SUCCESS
@@ -862,8 +796,7 @@ class Saml2Client(object):
request.id,
status)
- if log:
- log.info("RESPONSE: {0:>s}".format(response))
+ logger.info("RESPONSE: {0:>s}".format(response))
if 'RelayState' in get:
rstate = get['RelayState']
@@ -876,7 +809,7 @@ class Saml2Client(object):
return headers, success
- def logout_request(self, request, subject_id, log=None,
+ def logout_request(self, request, subject_id,
binding=BINDING_HTTP_REDIRECT):
""" Deal with a LogoutRequest
@@ -885,11 +818,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)
+ return self.http_redirect_logout_request(request, subject_id)
def make_logout_response(self, idp_entity_id, request_id,
status_code, binding=BINDING_HTTP_REDIRECT):
@@ -951,7 +882,7 @@ class Saml2Client(object):
action=None,
resource=None, subject=None,
binding=saml2.BINDING_HTTP_REDIRECT,
- log=None, sign=False):
+ sign=False):
""" Makes an authz decision query.
:param entityid: The entity ID of the IdP to send the request to
@@ -960,7 +891,6 @@ class Saml2Client(object):
:param resource:
:param subject:
:param binding: Which binding to use for sending the request
- :param log: Where to write log messages
:param sign: Whether the request should be signed or not.
:return: AuthzDecisionQuery instance
"""
@@ -977,13 +907,12 @@ class Saml2Client(object):
_action,
saml.Evidence(assertion=assertion),
resource, subject,
- binding, log, sign)
+ binding, sign)
#noinspection PyUnusedLocal
def authz_decision_query(self, entityid, action,
evidence=None, resource=None, subject=None,
- binding=saml2.BINDING_HTTP_REDIRECT,
- log=None, sign=None):
+ binding=saml2.BINDING_HTTP_REDIRECT, sign=None):
""" Creates an authz decision query.
:param entityid: The entity ID of the IdP to send the request to
@@ -992,7 +921,6 @@ class Saml2Client(object):
:param resource: The resource you want to perform the action on
:param subject: Who wants to do the thing
:param binding: Which binding to use for sending the request
- :param log: Where to write log messages
:param sign: Whether the request should be signed or not.
:return: AuthzDecisionQuery instance
"""
@@ -1001,14 +929,8 @@ class Saml2Client(object):
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("service_url: %s" % service_url)
- log.info("my_name: %s" % my_name)
-
+ logger.info("spentityid: %s\nservice_url: %s\nmy_name: %s" % (
+ spentityid, service_url, my_name))
# authen_req = self.authn_request(session_id, location,
# service_url, spentityid, my_name, vorg,
@@ -1026,13 +948,13 @@ class Saml2Client(object):
#noinspection PyUnusedLocal
- def authz_decision_query_response(self, response, log=None):
+ def authz_decision_query_response(self, response):
""" Verify that the response is OK """
pass
#noinspection PyUnusedLocal
def do_authz_decision_query(self, entityid, assertion=None,
- log=None, sign=False):
+ sign=False):
authz_decision_query = self.authz_decision_query(entityid, assertion)
@@ -1051,21 +973,17 @@ class Saml2Client(object):
response = send_using_soap(authz_decision_query, destination,
self.config.key_file,
self.config.cert_file,
- log=log,
ca_certs=self.config.ca_certs)
if response:
- if log:
- log.info("Verifying response")
- response = self.authz_decision_query_response(response, log)
+ logger.info("Verifying response")
+ response = self.authz_decision_query_response(response)
if response:
#not_done.remove(entity_id)
- if log:
- log.info("OK response from %s" % destination)
+ logger.info("OK response from %s" % destination)
return response
else:
- if log:
- log.info("NOT OK response from %s" % destination)
+ logger.info("NOT OK response from %s" % destination)
return None
diff --git a/src/saml2/config.py b/src/saml2/config.py
index 2b126314..98c5db28 100644
--- a/src/saml2/config.py
+++ b/src/saml2/config.py
@@ -18,6 +18,8 @@ from saml2.attribute_converter import ac_factory
from saml2.assertion import Policy
from saml2.sigver import get_xmlsec_binary
+logger = logging.getLogger(__name__)
+
COMMON_ARGS = ["entityid", "xmlsec_binary", "debug", "key_file", "cert_file",
"secret", "accepted_time_diff", "name", "ca_certs",
"description",
@@ -84,8 +86,6 @@ LOG_HANDLER = {
}
LOG_FORMAT = "%(asctime)s %(name)s: %(levelname)s %(message)s"
-#LOG_FORMAT = "%(asctime)s %(name)s: %(levelname)s [%(sid)s][%(func)s] %
-# (message)s"
class ConfigurationError(Exception):
pass
diff --git a/src/saml2/ecp.py b/src/saml2/ecp.py
index 0cc4b9bf..69fc999f 100644
--- a/src/saml2/ecp.py
+++ b/src/saml2/ecp.py
@@ -18,6 +18,7 @@
"""
Contains classes used in the SAML ECP profile
"""
+import logging
from saml2 import element_to_extension_element
from saml2 import samlp
@@ -35,6 +36,8 @@ from saml2.s_utils import sid
from saml2.response import authn_response
+logger = logging.getLogger(__name__)
+
SERVICE = "urn:oasis:names:tc:SAML:2.0:profiles:SSO:ecp"
def ecp_capable(headers):
@@ -49,14 +52,12 @@ def ecp_capable(headers):
ACTOR = "http://schemas.xmlsoap.org/soap/actor/next"
#noinspection PyUnusedLocal
-def ecp_auth_request(cls, entityid=None, relay_state="",
- log=None, sign=False):
+def ecp_auth_request(cls, entityid=None, relay_state="", sign=False):
""" Makes an authentication request.
:param entityid: The entity ID of the IdP to send the request to
:param relay_state: To where the user should be returned after
successfull log in.
- :param log: Where to write log messages
:param sign: Whether the request should be signed or not.
:return: AuthnRequest response
"""
@@ -111,13 +112,11 @@ def ecp_auth_request(cls, entityid=None, relay_state="",
# <samlp:AuthnRequest>
# ----------------------------------------
- if log:
- log.info("entityid: %s, binding: %s" % (entityid, BINDING_SOAP))
+ logger.info("entityid: %s, binding: %s" % (entityid, BINDING_SOAP))
location = cls._sso_location(entityid, binding=BINDING_SOAP)
session_id = sid()
- authn_req = cls.authn(location, session_id, log=log,
- binding=BINDING_PAOS,
+ authn_req = cls.authn(location, session_id, binding=BINDING_PAOS,
service_url_binding=BINDING_PAOS)
body = soapenv.Body()
@@ -144,9 +143,7 @@ def handle_ecp_authn_response(cls, soap_message, outstanding=None):
item.c_namespace == ecp.NAMESPACE:
_relay_state = item
- response = authn_response(cls.config, cls.service_url(),
- outstanding, log=cls.logger,
- debug=cls.debug,
+ response = authn_response(cls.config, cls.service_url(), outstanding,
allow_unsolicited=True)
response.loads("%s" % rdict["body"], False, soap_message)
@@ -182,9 +179,8 @@ class ECPServer(Server):
TODO: Still tentative
"""
- def __init__(self, config_file="", config=None, _cache="",
- log=None, debug=0):
- Server.__init__(self, config_file, config, _cache, log, debug)
+ def __init__(self, config_file="", config=None, _cache=""):
+ Server.__init__(self, config_file, config, _cache)
def parse_ecp_authn_query(self):
pass
diff --git a/src/saml2/ecp_client.py b/src/saml2/ecp_client.py
index 2494b35e..d8bb938a 100644
--- a/src/saml2/ecp_client.py
+++ b/src/saml2/ecp_client.py
@@ -21,6 +21,7 @@ programs.
"""
import cookielib
+import logging
import sys
from saml2 import soap
@@ -37,11 +38,12 @@ from saml2.metadata import MetaData
SERVICE = "urn:oasis:names:tc:SAML:2.0:profiles:SSO:ecp"
PAOS_HEADER_INFO = 'ver="%s";"%s"' % (paos.NAMESPACE, SERVICE)
+logger = logging.getLogger(__name__)
+
class Client(object):
def __init__(self, user, passwd, sp="", idp=None, metadata_file=None,
xmlsec_binary=None, verbose=0, ca_certs="",
- disable_ssl_certificate_validation=True, logger=None,
- debug=False):
+ disable_ssl_certificate_validation=True):
"""
:param user: user name
:param passwd: user password
@@ -55,15 +57,11 @@ class Client(object):
:param disable_ssl_certificate_validation: If
disable_ssl_certificate_validation is true, SSL cert validation
will not be performed.
- :param logger: Somewhere to write logs to
- :param debug: Whether debug output is needed
"""
self._idp = idp
self._sp = sp
self.user = user
self.passwd = passwd
- self.log = logger
- self.debug = debug
self._verbose = verbose
if metadata_file:
@@ -83,9 +81,7 @@ class Client(object):
disable_ssl_certificate_validation=disable_ssl_certificate_validation)
def _debug_info(self, text):
- if self.debug:
- if self.log:
- self.log.debug(text)
+ logger.debug(text)
if self._verbose:
print >> sys.stderr, text
@@ -104,8 +100,7 @@ class Client(object):
binding=binding)
if ssos:
self._idp = ssos[0]
- if self.debug:
- self.log.debug("IdP endpoint: '%s'" % self._idp)
+ logger.debug("IdP endpoint: '%s'" % self._idp)
return self._idp
raise Exception("No suitable endpoint found for entity id '%s'" % (
@@ -244,8 +239,7 @@ class Client(object):
self._debug_info("[P3] IdP response: %s" % response)
self.done_ecp = True
- if self.debug:
- self.log.debug("Done ECP")
+ logger.debug("Done ECP")
return None
@@ -297,9 +291,7 @@ class Client(object):
# header blocks may also be present
try:
respdict = soap.class_instances_from_soap_enveloped_saml_thingies(
- response,
- [paos, ecp,
- samlp])
+ response,[paos, ecp,samlp])
self.ecp_conversation(respdict, idp_entity_id)
# should by now be authenticated so this should go smoothly
response = op(**opargs)
diff --git a/src/saml2/encdec.py b/src/saml2/encdec.py
index 239f5449..9898bf83 100644
--- a/src/saml2/encdec.py
+++ b/src/saml2/encdec.py
@@ -1,3 +1,4 @@
+import logging
import os
import sys
@@ -15,6 +16,8 @@ __author__ = 'rohe0002'
import xmlenc as enc
+logger = logging.getLogger(__name__)
+
#<EncryptedData
# xmlns="http://www.w3.org/2001/04/xmlenc#"
# Type="http://www.w3.org/2001/04/xmlenc#Element">
diff --git a/src/saml2/httplib2cookie.py b/src/saml2/httplib2cookie.py
index 912523f9..a6742cc6 100644
--- a/src/saml2/httplib2cookie.py
+++ b/src/saml2/httplib2cookie.py
@@ -32,6 +32,7 @@
# CookieJar class with httplib2.
#
#
+import logging
import re
import cookielib
@@ -40,6 +41,8 @@ from httplib2 import Http
import urllib
import urllib2
+logger = logging.getLogger(__name__)
+
class DummyRequest(object):
"""Simulated urllib2.Request object for httplib2
diff --git a/src/saml2/httputil.py b/src/saml2/httputil.py
index e29ccf1f..7a2a8e52 100644
--- a/src/saml2/httputil.py
+++ b/src/saml2/httputil.py
@@ -1,8 +1,12 @@
+import logging
+
__author__ = 'rohe0002'
import cgi
from urllib import quote
+logger = logging.getLogger(__name__)
+
class Response(object):
_template = None
_status = '200 OK'
diff --git a/src/saml2/mcache.py b/src/saml2/mcache.py
index a94f06cd..d2c200aa 100644
--- a/src/saml2/mcache.py
+++ b/src/saml2/mcache.py
@@ -1,4 +1,5 @@
#!/usr/bin/env python
+import logging
import memcache
from saml2 import time_util
@@ -8,6 +9,7 @@ from saml2.cache import ToOld, CacheError
# gathered from several different sources, all with their own
# timeout time.
+logger = logging.getLogger(__name__)
def _key(prefix, name):
return "%s_%s" % (prefix, name)
diff --git a/src/saml2/mdbcache.py b/src/saml2/mdbcache.py
index 28158973..d1347cca 100644
--- a/src/saml2/mdbcache.py
+++ b/src/saml2/mdbcache.py
@@ -1,4 +1,5 @@
#!/usr/bin/env python
+import logging
__author__ = 'rolandh'
@@ -11,6 +12,8 @@ from saml2 import time_util
from saml2.cache import ToOld
from saml2.time_util import TIME_FORMAT
+logger = logging.getLogger(__name__)
+
class Cache(object):
def __init__(self, server=None, debug=0, db=None):
if server:
diff --git a/src/saml2/metadata.py b/src/saml2/metadata.py
index df1384a9..e2526cac 100644
--- a/src/saml2/metadata.py
+++ b/src/saml2/metadata.py
@@ -18,6 +18,7 @@
"""
Contains classes and functions to alleviate the handling of SAML metadata
"""
+import logging
import httplib2
import sys
@@ -57,6 +58,8 @@ from saml2.sigver import pem_format
from saml2.validate import valid_instance, NotValid
from saml2.country_codes import D_COUNTRIES
+logger = logging.getLogger(__name__)
+
def metadata_extension_modules():
_pre = "saml2.extension"
res = []
@@ -86,8 +89,7 @@ def keep_updated(func, self=None, entity_id=None, *args, **kwargs):
class MetaData(object):
""" A class to manage metadata information """
- def __init__(self, xmlsec_binary=None, attrconv=None, log=None):
- self.log = log
+ def __init__(self, xmlsec_binary=None, attrconv=None):
self.xmlsec_binary = xmlsec_binary
self.attrconv = attrconv or []
self._loc_key = {}
@@ -388,15 +390,9 @@ class MetaData(object):
def do_entity_descriptor(self, entity_descr, source, valid_until=0):
try:
if not valid(entity_descr.valid_until):
- if self.log:
- self.log.info(
- "Entity descriptor (entity id:%s) to old" % \
- entity_descr.entity_id)
- else:
- print >> sys.stderr, \
- "Entity descriptor (entity id:%s) to old" % \
- entity_descr.entity_id
- return
+ logger.info("Entity descriptor (entity id:%s) to old" % (
+ entity_descr.entity_id,))
+ return
except AttributeError:
pass
@@ -483,8 +479,7 @@ class MetaData(object):
self.import_metadata(content, (url, cert))
return True
else:
- if self.log:
- self.log.info("Response status: %s" % response.status)
+ logger.info("Response status: %s" % response.status)
return False
@keep_updated
diff --git a/src/saml2/population.py b/src/saml2/population.py
index 78233abb..58ee1cd4 100644
--- a/src/saml2/population.py
+++ b/src/saml2/population.py
@@ -1,6 +1,8 @@
-
+import logging
from saml2.cache import Cache
+logger = logging.getLogger(__name__)
+
class Population(object):
def __init__(self, cache=None):
if cache:
@@ -33,8 +35,10 @@ class Population(object):
def issuers_of_info(self, subject_id):
return self.cache.entities(subject_id)
- def get_identity(self, subject_id, entities=None, check_not_on_or_after=True):
- return self.cache.get_identity(subject_id, entities, check_not_on_or_after)
+ def get_identity(self, subject_id, entities=None,
+ check_not_on_or_after=True):
+ return self.cache.get_identity(subject_id, entities,
+ check_not_on_or_after)
def get_info_from(self, subject_id, entity_id):
return self.cache.get(subject_id, entity_id)
diff --git a/src/saml2/request.py b/src/saml2/request.py
index 6053beda..f5fa8028 100644
--- a/src/saml2/request.py
+++ b/src/saml2/request.py
@@ -1,4 +1,4 @@
-import sys
+import logging
from attribute_converter import to_local
from saml2 import time_util
@@ -9,20 +9,16 @@ from saml2.validate import valid_instance
from saml2.validate import NotValid
from saml2.response import IncorrectlySigned
+logger = logging.getLogger(__name__)
+
def _dummy(_arg):
return None
class Request(object):
- def __init__(self, sec_context, receiver_addrs, log=None, timeslack=0,
- debug=0):
+ def __init__(self, sec_context, receiver_addrs, timeslack=0):
self.sec = sec_context
self.receiver_addrs = receiver_addrs
self.timeslack = timeslack
- self.log = log
- self.debug = debug
- if self.debug and not self.log:
- self.debug = 0
-
self.xmlstr = ""
self.name_id = ""
self.message = None
@@ -38,40 +34,32 @@ class Request(object):
def _loads(self, xmldata, decode=True):
if decode:
- if self.debug:
- self.log.debug("Expected to decode and inflate xml data")
+ logger.debug("Expected to decode and inflate xml data")
decoded_xml = s_utils.decode_base64_and_inflate(xmldata)
else:
decoded_xml = xmldata
# own copy
self.xmlstr = decoded_xml[:]
- if self.debug:
- self.log.info("xmlstr: %s" % (self.xmlstr,))
+ logger.info("xmlstr: %s" % (self.xmlstr,))
try:
self.message = self.signature_check(decoded_xml)
except TypeError:
raise
except Exception, excp:
- if self.log:
- self.log.info("EXCEPTION: %s", excp)
+ logger.info("EXCEPTION: %s", excp)
if not self.message:
- if self.log:
- self.log.error("Response was not correctly signed")
- self.log.info(decoded_xml)
+ logger.error("Response was not correctly signed")
+ logger.info(decoded_xml)
raise IncorrectlySigned()
-
- if self.debug:
- self.log.info("request: %s" % (self.message,))
+
+ logger.info("request: %s" % (self.message,))
try:
valid_instance(self.message)
except NotValid, exc:
- if self.log:
- self.log.error("Not valid request: %s" % exc.args[0])
- else:
- print >> sys.stderr, "Not valid request: %s" % exc.args[0]
+ logger.error("Not valid request: %s" % exc.args[0])
raise
return self
@@ -91,12 +79,8 @@ class Request(object):
assert self.message.version == "2.0"
if self.message.destination and \
self.message.destination not in self.receiver_addrs:
- if self.log:
- self.log.error("%s != %s" % (self.message.destination,
+ logger.error("%s != %s" % (self.message.destination,
self.receiver_addrs))
- else:
- print >> sys.stderr, "%s != %s" % (self.message.destination,
- self.receiver_addrs)
raise OtherError("Not destined for me!")
assert self.issue_instant_ok()
@@ -138,16 +122,14 @@ class Request(object):
class LogoutRequest(Request):
def __init__(self, sec_context, receiver_addrs, log=None, timeslack=0,
debug=0):
- Request.__init__(self, sec_context, receiver_addrs, log, timeslack,
- debug)
+ Request.__init__(self, sec_context, receiver_addrs, timeslack)
self.signature_check = self.sec.correctly_signed_logout_request
class AttributeQuery(Request):
def __init__(self, sec_context, receiver_addrs, log=None, timeslack=0,
debug=0):
- Request.__init__(self, sec_context, receiver_addrs, log, timeslack,
- debug)
+ Request.__init__(self, sec_context, receiver_addrs, timeslack)
self.signature_check = self.sec.correctly_signed_attribute_query
def attribute(self):
@@ -159,8 +141,7 @@ class AttributeQuery(Request):
class AuthnRequest(Request):
def __init__(self, sec_context, attribute_converters, receiver_addrs,
log=None, timeslack=0, debug=0):
- Request.__init__(self, sec_context, receiver_addrs, log, timeslack,
- debug)
+ Request.__init__(self, sec_context, receiver_addrs, timeslack)
self.attribute_converters = attribute_converters
self.signature_check = self.sec.correctly_signed_authn_request
@@ -172,8 +153,7 @@ class AuthnRequest(Request):
class AuthzRequest(Request):
def __init__(self, sec_context, receiver_addrs, log=None, timeslack=0,
debug=0):
- Request.__init__(self, sec_context, receiver_addrs, log, timeslack,
- debug)
+ Request.__init__(self, sec_context, receiver_addrs, timeslack)
self.signature_check = self.sec.correctly_signed_logout_request
def action(self):
diff --git a/src/saml2/response.py b/src/saml2/response.py
index 8bfaea6f..6bf726b3 100644
--- a/src/saml2/response.py
+++ b/src/saml2/response.py
@@ -17,6 +17,7 @@
import calendar
import base64
+import logging
import sys
from saml2 import samlp
@@ -38,6 +39,8 @@ from saml2.validate import valid_instance
from saml2.validate import valid_address
from saml2.validate import NotValid
+logger = logging.getLogger(__name__)
+
# ---------------------------------------------------------------------------
class IncorrectlySigned(Exception):
@@ -205,7 +208,7 @@ class StatusResponse(object):
# print "issue_instant: %s" % self.response.issue_instant
# print "%s < x < %s" % (lower, upper)
issued_at = str_to_time(self.response.issue_instant)
- return issued_at > lower and issued_at < upper
+ return lower < issued_at < upper
def _verify(self):
if self.request_id and self.in_response_to and \
diff --git a/src/saml2/s_utils.py b/src/saml2/s_utils.py
index 971f5b75..289e2381 100644
--- a/src/saml2/s_utils.py
+++ b/src/saml2/s_utils.py
@@ -1,4 +1,5 @@
#!/usr/bin/env python
+import logging
import time
import base64
@@ -22,6 +23,8 @@ except ImportError:
from md5 import md5
import zlib
+logger = logging.getLogger(__name__)
+
class VersionMismatch(Exception):
pass
@@ -304,3 +307,35 @@ def verify_signature(secret, parts):
return True
else:
return False
+
+
+FTICKS_FORMAT = "F-TICKS/SWAMID/2.0%s#"
+
+def fticks_log(sp, logf, idp_entity_id, user_id, secret, assertion):
+ """
+ 'F-TICKS/' federationIdentifier '/' version *('#' attribute '=' value ) '#'
+ Allowed attributes:
+ TS the login time stamp
+ RP the relying party entityID
+ AP the asserting party entityID (typcially the IdP)
+ PN a sha256-hash of the local principal name and a unique key
+ AM the authentication method URN
+
+ :param sp: Client instance
+ :param logf: The log function to use
+ :param idp_entity_id: IdP entity ID
+ :param user_id: The user identifier
+ :param secret: A salt to make the hash more secure
+ :param assertion: A SAML Assertion instance gotten from the IdP
+ """
+ csum = hmac.new(secret, digestmod=hashlib.sha1)
+ csum.update(user_id)
+
+ info = {
+ "TS": time.time(),
+ "RP": sp.entity_id,
+ "AP": idp_entity_id,
+ "PN": csum.hexdigest(),
+ "AM": assertion.AuthnStatement.AuthnContext.AuthnContextClassRef.text
+ }
+ logf.info(FTICKS_FORMAT % "#".join(["%s=%s" % (a,v) for a,v in info])) \ No newline at end of file
diff --git a/src/saml2/server.py b/src/saml2/server.py
index 5b9f3938..9af44b00 100644
--- a/src/saml2/server.py
+++ b/src/saml2/server.py
@@ -18,6 +18,7 @@
"""Contains classes and functions that a SAML2.0 Identity provider (IdP)
or attribute authority (AA) may use to conclude its tasks.
"""
+import logging
import shelve
import sys
@@ -57,20 +58,20 @@ from saml2.config import config_factory
from saml2.assertion import Assertion, Policy
+logger = logging.getLogger(__name__)
+
class UnknownVO(Exception):
pass
class Identifier(object):
""" A class that handles identifiers of objects """
- def __init__(self, db, voconf=None, debug=0, log=None):
+ def __init__(self, db, voconf=None):
if isinstance(db, basestring):
self.map = shelve.open(db, writeback=True)
else:
self.map = db
self.voconf = voconf
- self.debug = debug
- self.log = log
-
+
def _store(self, typ, entity_id, local, remote):
self.map["|".join([typ, entity_id, "f", local])] = remote
self.map["|".join([typ, entity_id, "b", remote])] = local
@@ -277,8 +278,7 @@ class Server(object):
idb = addr
if idb is not None:
- self.ident = Identifier(idb, self.conf.virtual_organization,
- self.debug, self.log)
+ self.ident = Identifier(idb, self.conf.virtual_organization)
else:
raise Exception("Couldn't open identity database: %s" %
(dbspec,))
diff --git a/src/saml2/sigver.py b/src/saml2/sigver.py
index 8c6d905c..2c26bc57 100644
--- a/src/saml2/sigver.py
+++ b/src/saml2/sigver.py
@@ -20,6 +20,7 @@ Based on the use of xmlsec1 binaries and not the python xmlsec module.
"""
import base64
+import logging
import random
import os
import sys
@@ -40,6 +41,8 @@ from saml2.time_util import instant
from tempfile import NamedTemporaryFile
from subprocess import Popen, PIPE
+logger = logging.getLogger(__name__)
+
SIG = "{%s#}%s" % (ds.NAMESPACE, "Signature")
def signed(item):
@@ -321,9 +324,12 @@ def parse_xmlsec_output(output):
__DEBUG = 0
+LOG_LINE = 60*"="+"\n%s\n"+60*"-"+"\n%s"+60*"="
+LOG_LINE_2 = 60*"="+"\n%s\n%s\n"+60*"-"+"\n%s"+60*"="
+
def verify_signature(enctext, xmlsec_binary, cert_file=None, cert_type="pem",
node_name=NODE_NAME, debug=False, node_id=None,
- log=None, id_attr=""):
+ id_attr=""):
""" Verifies the signature of a XML document.
:param enctext: The signed XML document
@@ -374,12 +380,7 @@ def verify_signature(enctext, xmlsec_binary, cert_file=None, cert_type="pem",
print p_err
verified = parse_xmlsec_output(p_err)
except XmlsecError, exc:
- if log:
- log.error(60*"=")
- log.error(p_out)
- log.error(60*"-")
- log.error("%s" % exc)
- log.error(60*"=")
+ logger.error(LOG_LINE % (p_out, exc))
raise SignatureError("%s" % (exc,))
return verified
@@ -421,12 +422,10 @@ def read_cert_from_file(cert_file, cert_type):
data = open(cert_file).read()
return base64.b64encode(str(data))
-def security_context(conf, log=None, debug=None):
+def security_context(conf, debug=None):
""" Creates a security context based on the configuration
:param conf: The configuration
- :param log: A logger if different from the one specified in the
- configuration
:return: A SecurityContext instance
"""
if not conf:
@@ -443,12 +442,11 @@ def security_context(conf, log=None, debug=None):
return SecurityContext(conf.xmlsec_binary, conf.key_file,
cert_file=conf.cert_file, metadata=metadata,
- log=log, debug=debug,
- only_use_keys_in_metadata=_only_md)
+ debug=debug, only_use_keys_in_metadata=_only_md)
class SecurityContext(object):
def __init__(self, xmlsec_binary, key_file="", key_type= "pem",
- cert_file="", cert_type="pem", metadata=None, log=None,
+ cert_file="", cert_type="pem", metadata=None,
debug=False, template="", encrypt_key_type="des-192",
only_use_keys_in_metadata=False):
@@ -465,7 +463,6 @@ class SecurityContext(object):
self.metadata = metadata
self.only_use_keys_in_metadata = only_use_keys_in_metadata
- self.log = log
self.debug = debug
if not template:
@@ -476,12 +473,8 @@ class SecurityContext(object):
self.key_type = encrypt_key_type
- if self.debug and not self.log:
- self.debug = 0
-
def correctly_signed(self, xml, must=False):
- if self.log:
- self.log.info("verify correct signature")
+ logger.info("verify correct signature")
return self.correctly_signed_response(xml, must)
def encrypt(self, text, recv_key="", template="", key_type=""):
@@ -501,8 +494,7 @@ class SecurityContext(object):
if not template:
template = self.template
- if self.log:
- self.log.info("input len: %d" % len(text))
+ logger.info("input len: %d" % len(text))
_, fil = make_temp("%s" % text, decode=False)
ntf = NamedTemporaryFile()
@@ -513,8 +505,7 @@ class SecurityContext(object):
"--output", ntf.name,
template]
- if self.debug:
- self.log.debug("Encryption command: %s" % " ".join(com_list))
+ logger.debug("Encryption command: %s" % " ".join(com_list))
pof = Popen(com_list, stderr=PIPE, stdout=PIPE)
@@ -522,14 +513,8 @@ class SecurityContext(object):
try:
parse_xmlsec_output(p_err)
except XmlsecError, exc:
- if self.debug:
- p_out = pof.stdout.read()
- self.log.error(60*"=")
- self.log.error(p_out)
- self.log.error(p_err)
- self.log.error(60*"-")
- self.log.error("%s" % exc)
- self.log.error(60*"=")
+ p_out = pof.stdout.read()
+ logger.error(LOG_LINE_2 % (p_out, p_err, exc))
raise DecryptError("%s" % (exc,))
ntf.seek(0)
@@ -542,8 +527,7 @@ class SecurityContext(object):
:return: The decrypted text
"""
- if self.log:
- self.log.info("input len: %d" % len(enctext))
+ logger.info("input len: %d" % len(enctext))
_, fil = make_temp("%s" % enctext, decode=False)
ntf = NamedTemporaryFile()
@@ -553,8 +537,7 @@ class SecurityContext(object):
"--id-attr:%s" % ID_ATTR, ENC_KEY_CLASS,
fil]
- if self.debug:
- self.log.debug("Decrypt command: %s" % " ".join(com_list))
+ logger.debug("Decrypt command: %s" % " ".join(com_list))
pof = Popen(com_list, stderr=PIPE, stdout=PIPE)
@@ -562,14 +545,8 @@ class SecurityContext(object):
try:
parse_xmlsec_output(p_err)
except XmlsecError, exc:
- if self.debug:
- p_out = pof.stdout.read()
- self.log.error(60*"=")
- self.log.error(p_out)
- self.log.error(p_err)
- self.log.error(60*"-")
- self.log.error("%s" % exc)
- self.log.error(60*"=")
+ p_out = pof.stdout.read()
+ logger.error(LOG_LINE_2 % (p_out, p_err, exc))
raise DecryptError("%s" % (exc,))
ntf.seek(0)
@@ -639,12 +616,10 @@ class SecurityContext(object):
verified = True
break
except XmlsecError, exc:
- if self.log:
- self.log.error("check_sig: %s" % exc)
+ logger.error("check_sig: %s" % exc)
pass
except Exception, exc:
- if self.log:
- self.log.error("check_sig: %s" % exc)
+ logger.error("check_sig: %s" % exc)
raise
if not verified:
@@ -776,21 +751,18 @@ class SecurityContext(object):
# Try to find the signing cert in the assertion
for assertion in response.assertion:
if not assertion.signature:
- if self.debug:
- self.log.debug("unsigned")
+ logger.debug("unsigned")
if must:
raise SignatureError("Signature missing")
continue
else:
- if self.debug:
- self.log.debug("signed")
+ logger.debug("signed")
try:
self._check_signature(decoded_xml, assertion,
class_name(assertion), origdoc)
except Exception, exc:
- if self.log:
- self.log.error("correctly_signed_response: %s" % exc)
+ logger.error("correctly_signed_response: %s" % exc)
raise
return response
diff --git a/src/saml2/soap.py b/src/saml2/soap.py
index a1e0ea1b..27d85c6d 100644
--- a/src/saml2/soap.py
+++ b/src/saml2/soap.py
@@ -18,6 +18,7 @@
"""
Suppport for the client part of the SAML2.0 SOAP binding.
"""
+import logging
from httplib2 import Http
@@ -37,6 +38,9 @@ except ImportError:
#noinspection PyUnresolvedReferences
from elementtree import ElementTree
+
+logger = logging.getLogger(__name__)
+
class XmlParseError(Exception):
pass
@@ -197,9 +201,8 @@ def soap_fault(message=None, actor=None, code=None, detail=None):
class HTTPClient(object):
""" For sending a message to a HTTP server using POST or GET """
- def __init__(self, path, keyfile=None, certfile=None, log=None,
- cookiejar=None, ca_certs="",
- disable_ssl_certificate_validation=True):
+ def __init__(self, path, keyfile=None, certfile=None, cookiejar=None,
+ ca_certs="", disable_ssl_certificate_validation=True):
self.path = path
if cookiejar is not None:
self.cj = True
@@ -210,7 +213,7 @@ class HTTPClient(object):
self.cj = False
self.server = Http(ca_certs=ca_certs,
disable_ssl_certificate_validation=disable_ssl_certificate_validation)
- self.log = log
+
self.response = None
if keyfile:
@@ -299,13 +302,12 @@ class HTTPClient(object):
class SOAPClient(object):
- def __init__(self, server_url, keyfile=None, certfile=None, log=None,
+ def __init__(self, server_url, keyfile=None, certfile=None,
cookiejar=None, ca_certs="",
disable_ssl_certificate_validation=True):
- self.server = HTTPClient(server_url, keyfile, certfile, log,
- cookiejar, ca_certs=ca_certs,
+ self.server = HTTPClient(server_url, keyfile, certfile, cookiejar,
+ ca_certs=ca_certs,
disable_ssl_certificate_validation=disable_ssl_certificate_validation)
- self.log = log
self.response = None
def send(self, request, path=None, headers=None, sign=None, sec=None):
@@ -325,8 +327,7 @@ class SOAPClient(object):
self.response = _response
if _response:
- if self.log:
- self.log.info("SOAP response: %s" % _response)
+ logger.info("SOAP response: %s" % _response)
return parse_soap_enveloped_saml_response(_response)
else:
return False
diff --git a/src/saml2/virtual_org.py b/src/saml2/virtual_org.py
index 13e713e1..a5d40f54 100644
--- a/src/saml2/virtual_org.py
+++ b/src/saml2/virtual_org.py
@@ -1,14 +1,13 @@
+import logging
from saml2.attribute_resolver import AttributeResolver
+logger = logging.getLogger(__name__)
+
class VirtualOrg(object):
def __init__(self, sp, vorg, log=None):
self.sp = sp # The parent SP client instance
self.config = sp.config
self.vorg_name = vorg
- if log is None:
- self.log = self.sp.logger
- else:
- self.log = log
self.vorg_conf = self.config.vo_conf(self.vorg_name)
def _cache_session(self, session_info):
@@ -44,8 +43,7 @@ class VirtualOrg(object):
# Remove the ones I have cached data from about this subject
vo_members = [m for m in vo_members if not self.sp.users.cache.active(
subject_id, m)]
- if self.log:
- self.log.info("VO members (not cached): %s" % vo_members)
+ logger.info("VO members (not cached): %s" % vo_members)
return vo_members
def get_common_identifier(self, subject_id):
@@ -61,12 +59,9 @@ class VirtualOrg(object):
return None
def do_aggregation(self, subject_id, log=None):
- if log is None:
- log = self.log
-
- if log:
- log.info("** Do VO aggregation **")
- log.info("SubjectID: %s, VO:%s" % (subject_id, self.vorg_name))
+
+ logger.info("** Do VO aggregation **\nSubjectID: %s, VO:%s" % (
+ subject_id, self.vorg_name))
to_ask = self.members_to_ask(subject_id)
if to_ask:
@@ -90,11 +85,9 @@ class VirtualOrg(object):
log=log, real_id=subject_id):
_ = self._cache_session(session_info)
- if log:
- log.info(
- ">Issuers: %s" % self.sp.users.issuers_of_info(subject_id))
- log.info(
- "AVA: %s" % (self.sp.users.get_identity(subject_id),))
+ logger.info(">Issuers: %s" % self.sp.users.issuers_of_info(
+ subject_id))
+ logger.info("AVA: %s" % (self.sp.users.get_identity(subject_id),))
return True
else: