Skip to content

Commit a445870

Browse files
committed
Add eIDAs protocol version suppert in config
- Adds support for setting the protocol versions supported based on eIDAS Message Format v1.1-2 document - Adds validator for the existence of the protocol version and issues a warning if it doesn't exist - Adds tests for configuration validation and for the existence of protocol version as an entity attribute element - Adds helper functions `make_type` and `make_list` to make parsing the protocol version easier regardless of it being a single element or a list of elements
1 parent cc925cf commit a445870

File tree

5 files changed

+71
-3
lines changed

5 files changed

+71
-3
lines changed

src/saml2/config.py

+8-1
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,8 @@
102102
"sp_type_in_metadata",
103103
"requested_attributes",
104104
"node_country",
105-
"application_identifier"
105+
"application_identifier",
106+
"protocol_version"
106107
]
107108

108109
AA_IDP_ARGS = [
@@ -126,6 +127,7 @@
126127
"edu_person_targeted_id",
127128
"node_country",
128129
"application_identifier"
130+
"protocol_version"
129131
]
130132

131133
PDP_ARGS = ["endpoints", "name_form", "name_id_format"]
@@ -652,6 +654,11 @@ def validate(self):
652654
partial(must_error,
653655
message="be in the form <vendor name>:<software identifier>"
654656
":<major-version>.<minor-version>[.<patch-version>]”")
657+
),
658+
RuleValidator(
659+
"protocol_version",
660+
getattr(self, "_sp_protocol_version", None),
661+
*self.assert_declared(should_warning)
655662
)
656663
]
657664

src/saml2/metadata.py

+11
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
from saml2 import BINDING_SOAP
2222
from saml2 import samlp
2323
from saml2 import class_name
24+
from saml2.utility import make_list
2425

2526
from saml2 import xmldsig as ds
2627
import six
@@ -788,6 +789,16 @@ def entity_descriptor(confd):
788789
)
789790
_add_attr_to_entity_attributes(entd.extensions, attr)
790791

792+
protocol_version = confd.getattr("protocol_version", confd.context)
793+
if protocol_version:
794+
entd.extensions = entd.extensions or md.Extensions()
795+
ava = [AttributeValue(text=str(c)) for c in make_list(protocol_version)]
796+
attr = Attribute(
797+
attribute_value=ava,
798+
name="http://eidas.europa.eu/entity-attributes/protocol-version"
799+
)
800+
_add_attr_to_entity_attributes(entd.extensions, attr)
801+
791802
return entd
792803

793804

src/saml2/utility/__init__.py

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
def make_type(mtype, *args):
2+
t_args = []
3+
similar_type = tuple if mtype is list else list
4+
for x in args:
5+
t_args.extend([x] if not isinstance(x, (list, tuple)) else similar_type(x))
6+
return mtype(t_args)
7+
8+
9+
def make_list(*args):
10+
return make_type(list, *args)

tests/eidas/sp_conf.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,8 @@
3131
"sp_type_in_metadata": False,
3232
"force_authn": True,
3333
"node_country": "GR",
34-
"application_identifier": "CEF:eIDAS-ref:2.0"
34+
"application_identifier": "CEF:eIDAS-ref:2.0",
35+
"protocol_version": [1.1, 2.2]
3536
}
3637
},
3738
"debug": 1,

tests/eidas/test_sp.py

+40-1
Original file line numberDiff line numberDiff line change
@@ -71,13 +71,43 @@ def test_application_identifier_in_metadata(self):
7171
entd.extensions.extension_elements))
7272
app_identifier = [
7373
x for x in entity_attributes.children
74-
if x.attributes["Name"] ==
74+
if getattr(x, "attributes", {}).get("Name") ==
7575
"http://eidas.europa.eu/entity-attributes/application-identifier"
7676
]
7777
assert len(app_identifier) == 1
7878
assert self.conf._sp_application_identifier \
7979
== next(x.text for y in app_identifier for x in y.children)
8080

81+
def test_multiple_protocol_version_in_metadata(self):
82+
entd = metadata.entity_descriptor(self.conf)
83+
entity_attributes = next(filter(lambda x: x.tag == "EntityAttributes",
84+
entd.extensions.extension_elements))
85+
protocol_version = next(
86+
x for x in entity_attributes.children
87+
if getattr(x, "name", "") ==
88+
"http://eidas.europa.eu/entity-attributes/protocol-version"
89+
)
90+
assert len(protocol_version.attribute_value) == 2
91+
assert set(str(x) for x in self.conf._sp_protocol_version) \
92+
== set([x.text for x in protocol_version.attribute_value])
93+
94+
def test_protocol_version_in_metadata(self, config):
95+
config["service"]["sp"]["protocol_version"] = 1.2
96+
97+
conf = eIDASSPConfig()
98+
conf.load(config)
99+
100+
entd = metadata.entity_descriptor(conf)
101+
entity_attributes = next(filter(lambda x: x.tag == "EntityAttributes",
102+
entd.extensions.extension_elements))
103+
protocol_version = next(
104+
x for x in entity_attributes.children
105+
if getattr(x, "name", "") ==
106+
"http://eidas.europa.eu/entity-attributes/protocol-version"
107+
)
108+
assert len(protocol_version.attribute_value) == 1
109+
assert {str(conf._sp_protocol_version)} \
110+
== set([x.text for x in protocol_version.attribute_value])
81111

82112
class TestSPConfig:
83113
@pytest.fixture(scope="function")
@@ -164,3 +194,12 @@ def test_application_identifier_ok_format(self, config):
164194
conf = eIDASSPConfig()
165195
conf.load(config)
166196
conf.validate()
197+
198+
def test_no_protocol_version_warning(self, config, raise_error_on_warning):
199+
del config["service"]["sp"]["protocol_version"]
200+
201+
conf = eIDASSPConfig()
202+
conf.load(config)
203+
204+
with pytest.raises(ConfigValidationError):
205+
conf.validate()

0 commit comments

Comments
 (0)