diff options
| author | Roland Hedberg <roland.hedberg@adm.umu.se> | 2013-04-22 13:45:25 +0200 |
|---|---|---|
| committer | Roland Hedberg <roland.hedberg@adm.umu.se> | 2013-04-22 13:45:25 +0200 |
| commit | f806786f6dad8fc2b03daa0e1d55682daead3ec8 (patch) | |
| tree | 6c80119e02bb29761fc7854c5a2f2a144451ca5a /src/saml2 | |
| parent | 7c14eb8451081b041a7be0bea75b4d27d806f67a (diff) | |
| download | pysaml2-f806786f6dad8fc2b03daa0e1d55682daead3ec8.tar.gz | |
Cleaned up some added another test.
Diffstat (limited to 'src/saml2')
| -rw-r--r-- | src/saml2/assertion.py | 63 | ||||
| -rw-r--r-- | src/saml2/attribute_converter.py | 127 |
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 |
