summaryrefslogtreecommitdiff
path: root/src/saml2
diff options
context:
space:
mode:
authorRoland Hedberg <roland.hedberg@adm.umu.se>2013-04-22 13:45:25 +0200
committerRoland Hedberg <roland.hedberg@adm.umu.se>2013-04-22 13:45:25 +0200
commitf806786f6dad8fc2b03daa0e1d55682daead3ec8 (patch)
tree6c80119e02bb29761fc7854c5a2f2a144451ca5a /src/saml2
parent7c14eb8451081b041a7be0bea75b4d27d806f67a (diff)
downloadpysaml2-f806786f6dad8fc2b03daa0e1d55682daead3ec8.tar.gz
Cleaned up some added another test.
Diffstat (limited to 'src/saml2')
-rw-r--r--src/saml2/assertion.py63
-rw-r--r--src/saml2/attribute_converter.py127
2 files changed, 133 insertions, 57 deletions
diff --git a/src/saml2/assertion.py b/src/saml2/assertion.py
index 466e7f4b..78e761c4 100644
--- a/src/saml2/assertion.py
+++ b/src/saml2/assertion.py
@@ -454,14 +454,37 @@ class Assertion(dict):
def __init__(self, dic=None):
dict.__init__(self, dic)
- def _authn_context_decl_ref(self, authn_class):
- # authn_class: saml.AUTHN_PASSWORD
- return factory(saml.AuthnContext,
- authn_context_decl_ref=factory(
- saml.AuthnContextDeclRef, text=authn_class))
+ def _authn_context_decl(self, decl, authn_auth=None):
+ """
+ Construct the authn context with a authn context declaration
+ :param decl: The authn context declaration
+ :param authn_auth: Authenticating Authority
+ :return: An AuthnContext instance
+ """
+ return factory(saml.AuthnContext,
+ authn_context_decl=decl,
+ authenticating_authority=factory(
+ saml.AuthenticatingAuthority, text=authn_auth))
+
+ def _authn_context_decl_ref(self, decl_ref, authn_auth=None):
+ """
+ Construct the authn context with a authn context declaration reference
+ :param decl_ref: The authn context declaration reference
+ :param authn_auth: Authenticating Authority
+ :return: An AuthnContext instance
+ """
+ return factory(saml.AuthnContext,
+ authn_context_decl_ref=decl_ref,
+ authenticating_authority=factory(
+ saml.AuthenticatingAuthority, text=authn_auth))
def _authn_context_class_ref(self, authn_class, authn_auth=None):
- # authn_class: saml.AUTHN_PASSWORD
+ """
+ Construct the authn context with a authn context class reference
+ :param authn_class: The authn context class reference
+ :param authn_auth: Authenticating Authority
+ :return: An AuthnContext instance
+ """
cntx_class = factory(saml.AuthnContextClassRef, text=authn_class)
if authn_auth:
return factory(saml.AuthnContext,
@@ -473,7 +496,15 @@ class Assertion(dict):
authn_context_class_ref=cntx_class)
def _authn_statement(self, authn_class=None, authn_auth=None,
- authn_decl=None):
+ authn_decl=None, authn_decl_ref=None):
+ """
+ Construct the AuthnStatement
+ :param authn_class: Authentication Context Class reference
+ :param authn_auth: Authenticating Authority
+ :param authn_decl: Authentication Context Declaration
+ :param authn_decl_ref: Authentication Context Declaration reference
+ :return: An AuthnContext instance
+ """
if authn_class:
return factory(
saml.AuthnStatement,
@@ -486,7 +517,14 @@ class Assertion(dict):
saml.AuthnStatement,
authn_instant=instant(),
session_index=sid(),
- authn_context=self._authn_context_decl_ref(authn_decl))
+ authn_context=self._authn_context_decl(authn_decl, authn_auth))
+ elif authn_decl_ref:
+ return factory(
+ saml.AuthnStatement,
+ authn_instant=instant(),
+ session_index=sid(),
+ authn_context=self._authn_context_decl_ref(authn_decl_ref,
+ authn_auth))
else:
return factory(
saml.AuthnStatement,
@@ -496,7 +534,7 @@ class Assertion(dict):
def construct(self, sp_entity_id, in_response_to, consumer_url,
name_id, attrconvs, policy, issuer, authn_class=None,
authn_auth=None, authn_decl=None, encrypt=None,
- sec_context=None):
+ sec_context=None, authn_decl_ref=None):
""" Construct the Assertion
:param sp_entity_id: The entityid of the SP
@@ -509,9 +547,10 @@ class Assertion(dict):
:param issuer: Who is issuing the statement
:param authn_class: The authentication class
:param authn_auth: The authentication instance
- :param authn_decl:
+ :param authn_decl: An Authentication Context declaration
:param encrypt: Whether to encrypt parts or all of the Assertion
:param sec_context: The security context used when encrypting
+ :param authn_decl_ref: An Authentication Context declaration reference
:return: An Assertion instance
"""
@@ -536,9 +575,9 @@ class Assertion(dict):
# start using now and for some time
conds = policy.conditions(sp_entity_id)
- if authn_auth or authn_class or authn_decl:
+ if authn_auth or authn_class or authn_decl or authn_decl_ref:
_authn_statement = self._authn_statement(authn_class, authn_auth,
- authn_decl)
+ authn_decl, authn_decl_ref)
else:
_authn_statement = None
diff --git a/src/saml2/attribute_converter.py b/src/saml2/attribute_converter.py
index 2965dab5..fd69c81b 100644
--- a/src/saml2/attribute_converter.py
+++ b/src/saml2/attribute_converter.py
@@ -23,9 +23,11 @@ from saml2.s_utils import factory, do_ava
from saml2 import saml, extension_elements_to_elements
from saml2.saml import NAME_FORMAT_URI
+
class UnknownNameFormat(Exception):
pass
+
def load_maps(dirspec):
""" load the attribute maps
@@ -34,7 +36,7 @@ def load_maps(dirspec):
map as value. The map itself is a dictionary with two keys:
"to" and "fro". The values for those keys are the actual mapping.
"""
- map = {}
+ mapd = {}
if dirspec not in sys.path:
sys.path.insert(0, dirspec)
@@ -45,9 +47,10 @@ def load_maps(dirspec):
if key.startswith("__"):
continue
if isinstance(item, dict) and "to" in item and "fro" in item:
- map[item["identifier"]] = item
+ mapd[item["identifier"]] = item
+
+ return mapd
- return map
def ac_factory(path=""):
"""Attribute Converter factory
@@ -68,13 +71,14 @@ def ac_factory(path=""):
for key, item in mod.__dict__.items():
if key.startswith("__"):
continue
- if isinstance(item, dict) and "to" in item and "fro" in item:
+ if isinstance(item,
+ dict) and "to" in item and "fro" in item:
atco = AttributeConverter(item["identifier"])
atco.from_dict(item)
acs.append(atco)
else:
- for map in ["basic", "saml_uri", "shibboleth_uri"]:
- mod = import_module(".%s" % map, "saml2.attributemaps")
+ for typ in ["basic", "saml_uri", "shibboleth_uri"]:
+ mod = import_module(".%s" % typ, "saml2.attributemaps")
for key, item in mod.__dict__.items():
if key.startswith("__"):
continue
@@ -85,9 +89,11 @@ def ac_factory(path=""):
return acs
+
def ac_factory_II(path):
return ac_factory(path)
+
def ava_fro(acs, statement):
""" Translates attributes according to their name_formats into the local
names.
@@ -98,11 +104,12 @@ def ava_fro(acs, statement):
"""
if not statement:
return {}
-
+
acsdic = dict([(ac.name_format, ac) for ac in acs])
- acsdic[None] = acsdic[NAME_FORMAT_URI]
+ acsdic[None] = acsdic[NAME_FORMAT_URI]
return dict([acsdic[a.name_format].ava_from(a) for a in statement])
+
def to_local(acs, statement):
""" Replaces the attribute names in a attribute value assertion with the
equivalent name from a local name format.
@@ -110,7 +117,7 @@ def to_local(acs, statement):
"""
if not acs:
acs = [AttributeConverter()]
-
+
ava = []
for aconv in acs:
try:
@@ -120,15 +127,17 @@ def to_local(acs, statement):
pass
return ava
+
def from_local(acs, ava, name_format):
for aconv in acs:
#print ac.format, name_format
if aconv.name_format == name_format:
#print "Found a name_form converter"
return aconv.to_(ava)
-
+
return None
-
+
+
def from_local_name(acs, attr, name_format):
"""
:param acs: List of AttributeConverter instances
@@ -142,7 +151,8 @@ def from_local_name(acs, attr, name_format):
#print "Found a name_form converter"
return aconv.to_format(attr)
return attr
-
+
+
def to_local_name(acs, attr):
"""
:param acs: List of AttributeConverter instances
@@ -156,6 +166,7 @@ def to_local_name(acs, attr):
return attr.friendly_name
+
def d_to_local_name(acs, attr):
"""
:param acs: List of AttributeConverter instances
@@ -173,24 +184,27 @@ def d_to_local_name(acs, attr):
except KeyError:
raise Exception("Could not find local name for %s" % attr)
+
class AttributeConverter(object):
""" Converts from an attribute statement to a key,value dictionary and
vice-versa """
-
+
def __init__(self, name_format=""):
self.name_format = name_format
self._to = None
self._fro = None
-
+
def adjust(self):
""" If one of the transformations is not defined it is expected to
be the mirror image of the other.
"""
-
+
if self._fro is None and self._to is not None:
- self._fro = dict([(value.lower(), key) for key, value in self._to.items()])
+ self._fro = dict(
+ [(value.lower(), key) for key, value in self._to.items()])
if self._to is None and self.fro is not None:
- self._to = dict([(value.lower, key) for key, value in self._fro.items()])
+ self._to = dict(
+ [(value.lower, key) for key, value in self._fro.items()])
def from_dict(self, mapdict):
""" Import the attribute map from a dictionary
@@ -200,11 +214,12 @@ class AttributeConverter(object):
self.name_format = mapdict["identifier"]
try:
- self._fro = dict([(k.lower(),v) for k,v in mapdict["fro"].items()])
+ self._fro = dict(
+ [(k.lower(), v) for k, v in mapdict["fro"].items()])
except KeyError:
pass
try:
- self._to = dict([(k.lower(),v) for k,v in mapdict["to"].items()])
+ self._to = dict([(k.lower(), v) for k, v in mapdict["to"].items()])
except KeyError:
pass
@@ -214,7 +229,6 @@ class AttributeConverter(object):
if self._fro is None or self._to is None:
self.adjust()
-
def fail_safe_fro(self, statement):
""" In case there is not formats defined """
result = {}
@@ -229,9 +243,9 @@ class AttributeConverter(object):
if not value.text:
result[name].append('')
else:
- result[name].append(value.text.strip())
+ result[name].append(value.text.strip())
return result
-
+
def ava_from(self, attribute):
try:
attr = self._fro[attribute.name.strip().lower()]
@@ -248,44 +262,44 @@ class AttributeConverter(object):
[saml])
for ex in ext:
cval = {}
- for key, (name, type, mul) in ex.c_attributes.items():
+ for key, (name, typ, mul) in ex.c_attributes.items():
exv = getattr(ex, name)
if exv:
cval[name] = exv
if ex.text:
cval["value"] = ex.text.strip()
- val.append({ex.c_tag:cval})
+ val.append({ex.c_tag: cval})
elif not value.text:
val.append('')
else:
val.append(value.text.strip())
return attr, val
-
+
def fro(self, statement):
""" Get the attributes and the attribute values
:param statement: The AttributeStatement.
:return: A dictionary containing attributes and values
"""
-
+
if not self.name_format:
return self.fail_safe_fro(statement)
-
+
result = {}
for attribute in statement.attribute:
if attribute.name_format and self.name_format and \
- attribute.name_format != self.name_format:
+ attribute.name_format != self.name_format:
raise UnknownNameFormat
-
+
(key, val) = self.ava_from(attribute)
result[key] = val
-
+
if not result:
- return self.fail_safe_fro(statement)
+ return self.fail_safe_fro(statement)
else:
return result
-
+
def to_format(self, attr):
""" Creates an Attribute instance with name, name_format and
friendly_name
@@ -295,12 +309,12 @@ class AttributeConverter(object):
"""
try:
return factory(saml.Attribute,
- name=self._to[attr],
- name_format=self.name_format,
- friendly_name=attr)
+ name=self._to[attr],
+ name_format=self.name_format,
+ friendly_name=attr)
except KeyError:
return factory(saml.Attribute, name=attr)
-
+
def from_format(self, attr):
""" Find out the local name of an attribute
@@ -313,7 +327,7 @@ class AttributeConverter(object):
return self._fro[attr.name.lower()]
except KeyError:
pass
- else: #don't know the name format so try all I have
+ else: # don't know the name format so try all I have
try:
return self._fro[attr.name.lower()]
except KeyError:
@@ -333,7 +347,7 @@ class AttributeConverter(object):
return self._fro[attr["name"].lower()]
except KeyError:
pass
- else: #don't know the name format so try all I have
+ else: # don't know the name format so try all I have
try:
return self._fro[attr["name"].lower()]
except KeyError:
@@ -352,13 +366,36 @@ class AttributeConverter(object):
key = key.lower()
try:
attributes.append(factory(saml.Attribute,
- name=self._to[key],
- name_format=self.name_format,
- friendly_name=key,
- attribute_value=do_ava(value)))
+ name=self._to[key],
+ name_format=self.name_format,
+ friendly_name=key,
+ attribute_value=do_ava(value)))
except KeyError:
attributes.append(factory(saml.Attribute,
- name=key,
- attribute_value=do_ava(value)))
-
+ name=key,
+ attribute_value=do_ava(value)))
+
+ return attributes
+
+
+class AttributeConverterNOOP(AttributeConverter):
+ """ Does a NOOP conversion, that is no conversion is made """
+
+ def __init__(self, name_format=""):
+ AttributeConverter.__init__(self, name_format)
+
+ def to_(self, attrvals):
+ """ Create a list of Attribute instances.
+
+ :param attrvals: A dictionary of attributes and values
+ :return: A list of Attribute instances
+ """
+ attributes = []
+ for key, value in attrvals.items():
+ key = key.lower()
+ attributes.append(factory(saml.Attribute,
+ name=key,
+ name_format=self.name_format,
+ attribute_value=do_ava(value)))
+
return attributes