Added a policy flag that if set to False will allow the IdP to send back an incomplete reply. Not containing attributes that the SP deemed important (that is marked required).
This commit is contained in:
@@ -78,7 +78,8 @@ def _match(attr, ava):
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
def filter_on_attributes(ava, required=None, optional=None, acs=None):
|
def filter_on_attributes(ava, required=None, optional=None, acs=None,
|
||||||
|
fail_on_unfulfilled_requirements=True):
|
||||||
""" Filter
|
""" Filter
|
||||||
|
|
||||||
:param ava: An attribute value assertion as a dictionary
|
:param ava: An attribute value assertion as a dictionary
|
||||||
@@ -86,6 +87,8 @@ def filter_on_attributes(ava, required=None, optional=None, acs=None):
|
|||||||
required
|
required
|
||||||
:param optional: list of RequestedAttribute instances defined to be
|
:param optional: list of RequestedAttribute instances defined to be
|
||||||
optional
|
optional
|
||||||
|
:param fail_on_unfulfilled_requirements: If required attributes
|
||||||
|
are missing fail or fail not depending on this parameter.
|
||||||
:return: The modified attribute value assertion
|
:return: The modified attribute value assertion
|
||||||
"""
|
"""
|
||||||
res = {}
|
res = {}
|
||||||
@@ -116,7 +119,7 @@ def filter_on_attributes(ava, required=None, optional=None, acs=None):
|
|||||||
values = []
|
values = []
|
||||||
res[_fn] = _filter_values(ava[_fn], values, True)
|
res[_fn] = _filter_values(ava[_fn], values, True)
|
||||||
continue
|
continue
|
||||||
else:
|
elif fail_on_unfulfilled_requirements:
|
||||||
desc = "Required attribute missing: '%s' (%s)" % (attr["name"],
|
desc = "Required attribute missing: '%s' (%s)" % (attr["name"],
|
||||||
_name)
|
_name)
|
||||||
raise MissingValue(desc)
|
raise MissingValue(desc)
|
||||||
@@ -434,6 +437,16 @@ class Policy(object):
|
|||||||
|
|
||||||
return self.get("attribute_restrictions", sp_entity_id)
|
return self.get("attribute_restrictions", sp_entity_id)
|
||||||
|
|
||||||
|
def get_fail_on_missing_requested(self, sp_entity_id):
|
||||||
|
""" Return the whether the IdP should should fail if the SPs
|
||||||
|
requested attributes could not be found.
|
||||||
|
|
||||||
|
:param sp_entity_id: The SP entity ID
|
||||||
|
:return: The restrictions
|
||||||
|
"""
|
||||||
|
|
||||||
|
return self.get("fail_on_missing_requested", sp_entity_id, True)
|
||||||
|
|
||||||
def entity_category_attributes(self, ec):
|
def entity_category_attributes(self, ec):
|
||||||
if not self._restrictions:
|
if not self._restrictions:
|
||||||
return None
|
return None
|
||||||
@@ -492,7 +505,9 @@ class Policy(object):
|
|||||||
|
|
||||||
if required or optional:
|
if required or optional:
|
||||||
logger.debug("required: %s, optional: %s" % (required, optional))
|
logger.debug("required: %s, optional: %s" % (required, optional))
|
||||||
ava = filter_on_attributes(ava, required, optional, self.acs)
|
ava = filter_on_attributes(
|
||||||
|
ava, required, optional, self.acs,
|
||||||
|
self.get_fail_on_missing_requested(sp_entity_id))
|
||||||
|
|
||||||
return ava
|
return ava
|
||||||
|
|
||||||
|
@@ -269,7 +269,8 @@ class Config(object):
|
|||||||
acs = ac_factory()
|
acs = ac_factory()
|
||||||
|
|
||||||
if not acs:
|
if not acs:
|
||||||
raise ConfigurationError("No attribute converters, something is wrong!!")
|
raise ConfigurationError(
|
||||||
|
"No attribute converters, something is wrong!!")
|
||||||
|
|
||||||
_acs = self.getattr("attribute_converters", typ)
|
_acs = self.getattr("attribute_converters", typ)
|
||||||
if _acs:
|
if _acs:
|
||||||
|
@@ -172,6 +172,8 @@ def test_ava_filter_2():
|
|||||||
"surName": "Jeter",
|
"surName": "Jeter",
|
||||||
"mail": "derek@example.com"}
|
"mail": "derek@example.com"}
|
||||||
|
|
||||||
|
# mail removed because it doesn't match the regular expression
|
||||||
|
# So this should fail.
|
||||||
raises(MissingValue, policy.filter, ava, 'urn:mace:umu.se:saml:roland:sp',
|
raises(MissingValue, policy.filter, ava, 'urn:mace:umu.se:saml:roland:sp',
|
||||||
None, [mail], [gn, sn])
|
None, [mail], [gn, sn])
|
||||||
|
|
||||||
@@ -183,6 +185,44 @@ def test_ava_filter_2():
|
|||||||
None, [gn, sn, mail])
|
None, [gn, sn, mail])
|
||||||
|
|
||||||
|
|
||||||
|
def test_ava_filter_dont_fail():
|
||||||
|
conf = {
|
||||||
|
"default": {
|
||||||
|
"lifetime": {"minutes": 15},
|
||||||
|
"attribute_restrictions": None, # means all I have
|
||||||
|
},
|
||||||
|
"urn:mace:umu.se:saml:roland:sp": {
|
||||||
|
"lifetime": {"minutes": 5},
|
||||||
|
"attribute_restrictions": {
|
||||||
|
"givenName": None,
|
||||||
|
"surName": None,
|
||||||
|
"mail": [".*@.*\.umu\.se"],
|
||||||
|
},
|
||||||
|
"fail_on_missing_requested": False
|
||||||
|
}}
|
||||||
|
|
||||||
|
policy = Policy(conf)
|
||||||
|
|
||||||
|
ava = {"givenName": "Derek",
|
||||||
|
"surName": "Jeter",
|
||||||
|
"mail": "derek@example.com"}
|
||||||
|
|
||||||
|
# mail removed because it doesn't match the regular expression
|
||||||
|
# So it should fail if the 'fail_on_ ...' flag wasn't set
|
||||||
|
_ava = policy.filter(ava,'urn:mace:umu.se:saml:roland:sp', None,
|
||||||
|
[mail], [gn, sn])
|
||||||
|
|
||||||
|
assert _ava
|
||||||
|
|
||||||
|
ava = {"givenName": "Derek",
|
||||||
|
"surName": "Jeter"}
|
||||||
|
|
||||||
|
# it wasn't there to begin with
|
||||||
|
_ava = policy.filter(ava, 'urn:mace:umu.se:saml:roland:sp',
|
||||||
|
None, [gn, sn, mail])
|
||||||
|
|
||||||
|
assert _ava
|
||||||
|
|
||||||
def test_filter_attribute_value_assertions_0(AVA):
|
def test_filter_attribute_value_assertions_0(AVA):
|
||||||
p = Policy({
|
p = Policy({
|
||||||
"default": {
|
"default": {
|
||||||
@@ -802,4 +842,4 @@ def test_assertion_with_authn_instant():
|
|||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
test_assertion_2()
|
test_ava_filter_dont_fail()
|
||||||
|
Reference in New Issue
Block a user