refactoring and reshuffling

This commit is contained in:
Roland Hedberg
2010-03-11 20:49:48 +01:00
parent e14b4dd2ae
commit bc450c96f4

View File

@@ -23,10 +23,12 @@ import shelve
from saml2 import saml, samlp, VERSION
from saml2.utils import issuer_factory, conditions_factory, audience_restriction_factory
from saml2.utils import issuer_factory, conditions_factory
from saml2.utils import audience_restriction_factory
from saml2.utils import sid, decode_base64_and_inflate, make_instance
from saml2.utils import audience_factory, name_id_factory, assertion_factory
from saml2.utils import subject_factory, subject_confirmation_factory, response_factory
from saml2.utils import subject_factory, subject_confirmation_factory
from saml2.utils import response_factory, do_ava_statement
from saml2.utils import authn_statement_factory, MissingValue
from saml2.utils import subject_confirmation_data_factory, success_status_factory
from saml2.utils import filter_attribute_value_assertions
@@ -206,115 +208,6 @@ class Server(object):
# default is a hour
return in_a_while(**{"hours":1})
def do_sso_response(self, consumer_url, in_response_to,
sp_entity_id, identity, name_id=None, status=None ):
""" Create a Response the follows the ??? profile.
:param consumer_url: The URL which should receive the response
:param in_response_to: The session identifier of the request
:param sp_entity_id: The entity identifier of the SP
:param identity: A dictionary with attributes and values that are
expected to be the bases for the assertion in the response.
:param name_id: The identifier of the subject
:return: A Response instance
"""
attr_statement = do_attribute_statement(identity)
# start using now and for a hour
conds = conditions_factory(
not_before=instant(),
# How long might depend on who's getting it
not_on_or_after=self._not_on_or_after(sp_entity_id),
audience_restriction=audience_restriction_factory(
audience=audience_factory(sp_entity_id)))
# temporary identifier or ??
if not name_id:
name_id = name_id_factory(sid(), format=saml.NAMEID_FORMAT_TRANSIENT)
assertion = assertion_factory(
attribute_statement = attr_statement,
authn_statement= authn_statement_factory(
authn_instant=instant(),
session_index=sid()),
conditions=conds,
subject=subject_factory(
name_id=name_id,
method=saml.SUBJECT_CONFIRMATION_METHOD_BEARER,
subject_confirmation=subject_confirmation_factory(
subject_confirmation_data=subject_confirmation_data_factory(
in_response_to=in_response_to))),
),
if not status:
status = success_status_factory()
tmp = response_factory(
issuer=self.issuer(),
in_response_to = in_response_to,
destination = consumer_url,
status = status,
assertion=assertion,
)
# Store which assertion that has been sent to which SP about which
# subject.
self.cache.set(name_id["text"], sp_entity_id, assertion,
conds["not_on_or_after"])
return make_instance(samlp.Response, tmp)
def do_aa_response(self, consumer_url, in_response_to,
sp_entity_id, identity,
name_id=None, ip_address="", issuer=None, sign=False):
attr_statement = do_attribute_statement(identity)
# start using now and for a hour
conds = conditions_factory(
not_before=instant(),
# an hour from now
not_on_or_after=self._not_on_or_after(sp_entity_id),
audience_restriction=audience_restriction_factory(
audience=audience_factory(sp_entity_id)))
# temporary identifier or ??
if not name_id:
name_id = name_id_factory(sid(), format=saml.NAMEID_FORMAT_TRANSIENT)
assertion = assertion_factory(
subject = subject_factory(
name_id = name_id,
method = saml.SUBJECT_CONFIRMATION_METHOD_BEARER,
subject_confirmation = subject_confirmation_factory(
subject_confirmation_data = subject_confirmation_data_factory(
in_response_to = in_response_to,
not_on_or_after = self._not_on_or_after(sp_entity_id),
address = ip_address,
recipient = consumer_url))),
attribute_statement = attr_statement,
authn_statement = authn_statement_factory(
authn_instant = instant(),
session_index = sid()),
conditions=conds,
)
if sign:
assertion["signature"] = pre_signature_part(assertion["id"])
self.cache.set(name_id["text"], sp_entity_id, assertion,
conds["not_on_or_after"])
tmp = response_factory(
issuer=issuer,
in_response_to=in_response_to,
destination=consumer_url,
status=success_status_factory(),
assertion=assertion,
)
return make_instance(samlp.Response, tmp)
def filter_ava(self, ava, sp_entity_id, required=None, optional=None,
typ="idp"):
""" What attribute and attribute values returns depends on what
@@ -347,6 +240,7 @@ class Server(object):
restrictions = None
if restrictions:
print restrictions
ava = filter_attribute_value_assertions(ava, restrictions)
if required or optional:
@@ -354,6 +248,154 @@ class Server(object):
return ava
def restrict_ava(self, identity, spid):
""" Identity attribute names are expected to be expressed in
the local lingo (== friendlyName)
:param identity: A dictionary with attributes and values
:return: A filtered ava according to the IdPs/AAs rules and
the list of required/optional attributes according to the SP.
If the requirements can't be met an exception is raised.
"""
(required, optional) = self.conf["metadata"].attribute_consumer(spid)
return self.filter_ava(identity, spid, required, optional)
def _conditions(self, sp_entity_id):
return conditions_factory(
not_before=instant(),
# How long might depend on who's getting it
not_on_or_after=self._not_on_or_after(sp_entity_id),
audience_restriction=audience_restriction_factory(
audience=audience_factory(sp_entity_id)))
def _authn_statement(self):
return authn_statement_factory(authn_instant = instant(),
session_index = sid()),
def do_response(self, consumer_url, in_response_to,
sp_entity_id, identity=None, name_id=None,
status=None ):
""" Create a Response that adhers to the ??? profile.
:param consumer_url: The URL which should receive the response
:param in_response_to: The session identifier of the request
:param sp_entity_id: The entity identifier of the SP
:param identity: A dictionary with attributes and values that are
expected to be the bases for the assertion in the response.
:param name_id: The identifier of the subject
:return: A Response instance
"""
if not status:
status = success_status_factory()
tmp = response_factory(
issuer=self.issuer(),
in_response_to = in_response_to,
destination = consumer_url,
status = status,
)
if identity:
attr_statement = do_ava_statement(identity,
self.conf["am_backward"])
# temporary identifier or ??
if not name_id:
name_id = name_id_factory(sid(),
format=saml.NAMEID_FORMAT_TRANSIENT)
# start using now and for a hour
conds = self._conditions(sp_entity_id)
assertion = assertion_factory(
attribute_statement = attr_statement,
authn_statement = self._authn_statement(),
conditions = conds,
subject=subject_factory(
name_id=name_id,
method=saml.SUBJECT_CONFIRMATION_METHOD_BEARER,
subject_confirmation=subject_confirmation_factory(
subject_confirmation_data = \
subject_confirmation_data_factory(
in_response_to=in_response_to))),
),
# Store which assertion that has been sent to which SP about which
# subject.
self.cache.set(name_id["text"], sp_entity_id, assertion,
conds["not_on_or_after"])
tmp.update({"assertion":assertion})
return make_instance(samlp.Response, tmp)
# ----------------------------
def error_response(self, destination, in_response_to, spid, exc,
name_id = None):
return self.do_response(
destination, # consumer_url
in_response_to, # in_response_to
spid, # sp_entity_id
name_id,
status = status_from_exception_factory(exc)
)
def do_aa_response(self, consumer_url, in_response_to,
sp_entity_id, identity,
name_id=None, ip_address="", issuer=None, sign=False):
try:
identity = self.restrict_ava(identity, sp_entity_id)
except MissingValue, exc:
tmp = self.error_response( consumer_url, in_response_to,
sp_entity_id, exc, name_id)
return make_instance(samlp.Response, tmp)
attr_statement = do_ava_statement(identity, self.conf["am_backward"])
# temporary identifier or ??
if not name_id:
name_id = name_id_factory(sid(), format=saml.NAMEID_FORMAT_TRANSIENT)
conds = self._conditions(sp_entity_id)
assertion = assertion_factory(
subject = subject_factory(
name_id = name_id,
method = saml.SUBJECT_CONFIRMATION_METHOD_BEARER,
subject_confirmation = subject_confirmation_factory(
subject_confirmation_data = \
subject_confirmation_data_factory(
in_response_to = in_response_to,
not_on_or_after = self._not_on_or_after(sp_entity_id),
address = ip_address,
recipient = consumer_url))),
attribute_statement = attr_statement,
authn_statement = self._authn_statement(),
conditions = conds
)
if sign:
assertion["signature"] = pre_signature_part(assertion["id"])
print name_id
print conds
self.cache.set(name_id["text"], sp_entity_id, assertion,
conds["not_on_or_after"])
tmp = response_factory(
issuer=issuer,
in_response_to=in_response_to,
destination=consumer_url,
status=success_status_factory(),
assertion=assertion,
)
return make_instance(samlp.Response, tmp)
def authn_response(self, identity, in_response_to, destination, spid,
name_id_policy, userid):
""" Constructs an AuthenticationResponse
@@ -367,6 +409,7 @@ class Server(object):
:param userid: The subject identifier
:return: A XML string representing an authentication response
"""
name_id = None
if name_id_policy.sp_name_qualifier:
try:
@@ -385,11 +428,10 @@ class Server(object):
format=saml.NAMEID_FORMAT_PERSISTENT,
sp_name_qualifier=name_id_policy.sp_name_qualifier)
# Do attribute filtering
(required, optional) = self.conf["metadata"].attribute_consumer(spid)
# Do attribute-value filtering
try:
identity = self.filter_ava( identity, spid, required, optional)
resp = self.do_sso_response(
identity = self.restrict_ava(identity, spid)
resp = self.do_response(
destination, # consumer_url
in_response_to, # in_response_to
spid, # sp_entity_id
@@ -397,15 +439,8 @@ class Server(object):
name_id,
)
except MissingValue, exc:
resp = self.do_sso_response(
destination, # consumer_url
in_response_to, # in_response_to
spid, # sp_entity_id
name_id,
status = status_from_exception_factory(exc)
)
resp = self.error_response( destination, in_response_to, spid,
exc, name_id)
return ("%s" % resp).split("\n")