Skip to content

Commit cc925cf

Browse files
committed
Add eIDAS application identifier support in config
- Adds support for setting the application identifier based on eIDAS Message Format v1.1-2 document - Adds validator for the existence of the identifier and the correct formatting - Adds tests for configuration validation related to the identifier and test for the existence as an entity attribute element
1 parent 5b76044 commit cc925cf

File tree

4 files changed

+72
-1
lines changed

4 files changed

+72
-1
lines changed

src/saml2/config.py

+24
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import re
99
import sys
1010
from functools import partial
11+
import re
1112
from iso3166 import countries
1213

1314
import six
@@ -101,6 +102,7 @@
101102
"sp_type_in_metadata",
102103
"requested_attributes",
103104
"node_country",
105+
"application_identifier"
104106
]
105107

106108
AA_IDP_ARGS = [
@@ -123,6 +125,7 @@
123125
"name_qualifier",
124126
"edu_person_targeted_id",
125127
"node_country",
128+
"application_identifier"
126129
]
127130

128131
PDP_ARGS = ["endpoints", "name_form", "name_id_format"]
@@ -595,6 +598,14 @@ def validate_node_country_format(node_country):
595598
except KeyError:
596599
return False
597600

601+
@staticmethod
602+
def validate_application_identifier_format(application_identifier):
603+
if not application_identifier:
604+
return True
605+
606+
return re.search(r"([a-zA-Z0-9])+:([a-zA-Z0-9():_\-])+:([0-9])+"
607+
r"(\.([0-9])+){1,2}", application_identifier)
608+
598609

599610
class eIDASSPConfig(SPConfig, eIDASConfig):
600611
def get_endpoint_element(self, element):
@@ -629,6 +640,19 @@ def validate(self):
629640
partial(must_error,
630641
message="be declared in ISO 3166-1 alpha-2 format")
631642
),
643+
RuleValidator(
644+
"application_identifier",
645+
getattr(self, "_sp_application_identifier", None),
646+
*self.assert_declared(should_warning)
647+
),
648+
RuleValidator(
649+
"application_identifier",
650+
getattr(self, "_sp_application_identifier", None),
651+
self.validate_application_identifier_format,
652+
partial(must_error,
653+
message="be in the form <vendor name>:<software identifier>"
654+
":<major-version>.<minor-version>[.<patch-version>]”")
655+
)
632656
]
633657

634658
for validator in validators:

src/saml2/metadata.py

+10
Original file line numberDiff line numberDiff line change
@@ -778,6 +778,16 @@ def entity_descriptor(confd):
778778
item = node_country.NodeCountry(text=conf_node_country)
779779
entd.extensions.add_extension_element(item)
780780

781+
app_identifer = confd.getattr("application_identifier", confd.context)
782+
if app_identifer:
783+
entd.extensions = entd.extensions or md.Extensions()
784+
ava = AttributeValue(text=app_identifer)
785+
attr = Attribute(
786+
attribute_value=ava,
787+
name="http://eidas.europa.eu/entity-attributes/application-identifier"
788+
)
789+
_add_attr_to_entity_attributes(entd.extensions, attr)
790+
781791
return entd
782792

783793

tests/eidas/sp_conf.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,8 @@
3030
"sp_type": "public",
3131
"sp_type_in_metadata": False,
3232
"force_authn": True,
33-
"node_country": "GR"
33+
"node_country": "GR",
34+
"application_identifier": "CEF:eIDAS-ref:2.0"
3435
}
3536
},
3637
"debug": 1,

tests/eidas/test_sp.py

+36
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,19 @@ def test_node_country_in_metadata(self):
6565
assert any(filter(lambda x: x.tag == "NodeCountry",
6666
entd.extensions.extension_elements))
6767

68+
def test_application_identifier_in_metadata(self):
69+
entd = metadata.entity_descriptor(self.conf)
70+
entity_attributes = next(filter(lambda x: x.tag == "EntityAttributes",
71+
entd.extensions.extension_elements))
72+
app_identifier = [
73+
x for x in entity_attributes.children
74+
if x.attributes["Name"] ==
75+
"http://eidas.europa.eu/entity-attributes/application-identifier"
76+
]
77+
assert len(app_identifier) == 1
78+
assert self.conf._sp_application_identifier \
79+
== next(x.text for y in app_identifier for x in y.children)
80+
6881

6982
class TestSPConfig:
7083
@pytest.fixture(scope="function")
@@ -128,3 +141,26 @@ def test_nodecountry_wrong_format(self, config):
128141

129142
with pytest.raises(ConfigValidationError):
130143
conf.validate()
144+
145+
def test_no_application_identifier_warning(self, config, raise_error_on_warning):
146+
del config["service"]["sp"]["application_identifier"]
147+
148+
conf = eIDASSPConfig()
149+
conf.load(config)
150+
151+
with pytest.raises(ConfigValidationError):
152+
conf.validate()
153+
154+
def test_application_identifier_wrong_format(self, config):
155+
config["service"]["sp"]["application_identifier"] = "TEST:Node.1"
156+
157+
conf = eIDASSPConfig()
158+
conf.load(config)
159+
160+
with pytest.raises(ConfigValidationError):
161+
conf.validate()
162+
163+
def test_application_identifier_ok_format(self, config):
164+
conf = eIDASSPConfig()
165+
conf.load(config)
166+
conf.validate()

0 commit comments

Comments
 (0)