add support for Organization and ContactPerson elements in metadata (fixes #6656)

This commit is contained in:
Benjamin Dauvergne 2016-02-26 13:15:42 +01:00
parent aa95501d8b
commit 33d305f7a7
5 changed files with 169 additions and 0 deletions

View File

@ -30,6 +30,8 @@ class AppSettings(object):
'VERIFY_SSL_CERTIFICATE': True,
'OPENED_SESSION_COOKIE_NAME': None,
'OPENED_SESSION_COOKIE_DOMAIN': None,
'ORGANIZATION': None,
'CONTACT_PERSONS': [],
}
@property

View File

@ -36,5 +36,51 @@
Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"
Location="{{ login_url }}" />
</SPSSODescriptor>
{% if organization and organization.NAMES and organization.DISPLAY_NAMES and organization.URLS %}
<Organization>
{% for name in organization.NAMES %}
{% if name.LABEL %}
<OrganizationName {% if name.LANG %}xml:lang="{{ name.LANG }}"{% endif %}>{{ name.LABEL }}</OrganizationName>
{% else %}
<OrganizationName>{{ name }}</OrganizationName>
{% endif %}
{% endfor %}
{% for display_name in organization.DISPLAY_NAMES %}
{% if display_name.LABEL %}
<OrganizationDisplayName {% if display_name.LANG %}xml:lang="{{ display_name.LANG }}"{% endif %}>{{ display_name.LABEL }}</OrganizationDisplayName>
{% else %}
<OrganizationDisplayName>{{ display_name }}</OrganizationDisplayName>
{% endif %}
{% endfor %}
{% for url in organization.URLS %}
{% if url.URL %}
<OrganizationURL {% if url.LANG %}xml:lang="{{ url.LANG }}"{% endif %}>{{ url.URL }}</OrganizationURL>
{% else %}
<OrganizationURL>{{ url }}</OrganizationURL>
{% endif %}
{% endfor %}
</Organization>
{% endif %}
{% for contact_person in contact_persons %}
{% if contact_person.CONTACT_TYPE %}
<ContactPerson contactType="{{ contact_person.CONTACT_TYPE }}">
{% if contact_person.COMPANY %}
<Company>{{ contact_person.COMPANY }}</Company>
{% endif %}
{% if contact_person.GIVEN_NAME %}
<GivenName>{{ contact_person.GIVEN_NAME }}</GivenName>
{% endif %}
{% if contact_person.SURNAME %}
<SurName>{{ contact_person.SURNAME }}</SurName>
{% endif %}
{% for email_address in contact_person.EMAIL_ADDRESSES %}
<EmailAddress>{{ email_address }}</EmailAddress>
{% endfor %}
{% for telephone_number in contact_person.TELEPHONE_NUMBERS %}
<TelephoneNumber>{{ telephone_number }}</TelephoneNumber>
{% endfor %}
</ContactPerson>
{% endif %}
{% endfor %}
</EntityDescriptor>

View File

@ -36,6 +36,8 @@ def create_metadata(request):
'public_keys': public_keys,
'name_id_formats': name_id_formats,
'default_assertion_consumer_binding': app_settings.DEFAULT_ASSERTION_CONSUMER_BINDING,
'organization': app_settings.ORGANIZATION,
'contact_persons': app_settings.CONTACT_PERSONS,
})
settings._MELLON_METADATA_CACHE = cache
return settings._MELLON_METADATA_CACHE[entity_id]

View File

@ -19,3 +19,16 @@ def concurrency(settings):
return 20
else:
return 100
@pytest.fixture
def private_settings(request):
import django.conf
from django.conf import UserSettingsHolder
old = django.conf.settings._wrapped
django.conf.settings._wrapped = UserSettingsHolder(old)
def finalizer():
django.conf.settings._wrapped = old
request.addfinalizer(finalizer)
return django.conf.settings

View File

@ -1,4 +1,110 @@
import mock
import lasso
from django.core.urlresolvers import reverse
from xml_utils import assert_xml_constraints
def test_null_character_on_samlresponse_post(app):
app.post(reverse('mellon_login'), {'SAMLResponse': '\x00'}, status=400)
def test_metadata(private_settings, client):
ns = {
'sm': 'urn:oasis:names:tc:SAML:2.0:metadata',
'ds': 'http://www.w3.org/2000/09/xmldsig#',
}
private_settings.MELLON_PUBLIC_KEYS = ['xxx', '/yyy']
private_settings.MELLON_NAME_ID_FORMATS = [lasso.SAML2_NAME_IDENTIFIER_FORMAT_UNSPECIFIED]
private_settings.MELLON_DEFAULT_ASSERTION_CONSUMER_BINDING = 'artifact'
private_settings.MELLON_ORGANIZATION = {
'NAMES': [
'Foobar',
{
'LABEL': 'FoobarEnglish',
'LANG': 'en',
}
],
'DISPLAY_NAMES': [
'Foobar',
{
'LABEL': 'FoobarEnglish',
'LANG': 'en',
}
],
'URLS': [
'http://foobar.com/',
{
'URL': 'http://foobar.com/en/',
'LANG': 'en',
}
],
}
private_settings.MELLON_CONTACT_PERSONS = [
{
'CONTACT_TYPE': 'administrative',
'COMPANY': 'FooBar',
'GIVENNAME': 'John',
'SURNAME': 'Doe',
'EMAIL_ADDRESSES': [
'john.doe@foobar.com',
'john.doe@personal-email.com',
],
'TELEPHONE_NUMBERS': [
'+abcd',
'+1234',
],
},
{
'CONTACT_TYPE': 'technical',
'COMPANY': 'FooBar2',
'GIVENNAME': 'John',
'SURNAME': 'Doe',
'EMAIL_ADDRESSES': [
'john.doe@foobar.com',
'john.doe@personal-email.com',
],
'TELEPHONE_NUMBERS': [
'+abcd',
'+1234',
],
},
]
with mock.patch('mellon.utils.file', mock.mock_open(read_data='BEGIN\nyyy\nEND'), create=True):
response = client.get('/metadata/')
assert_xml_constraints(
response.content,
('/sm:EntityDescriptor[@entityID="http://testserver/metadata/"]', 1,
('/*', 4),
('/sm:SPSSODescriptor', 1,
('/*', 6),
('/sm:NameIDFormat', 1),
('/sm:SingleLogoutService', 1),
('/sm:AssertionConsumerService', None,
('[@isDefault="true"]', None,
('[@Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact"]', 1),
('[@Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"]', 0)),
('[@Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"]', 1)),
('/sm:KeyDescriptor/ds:KeyInfo/ds:X509Data', 2,
('/ds:X509Certificate', 2),
('/ds:X509Certificate[text()="xxx"]', 1),
('/ds:X509Certificate[text()="yyy"]', 1))),
('/sm:Organization', 1,
('/sm:OrganizationName', 2),
('/sm:OrganizationName[text()="Foobar"]', 1),
('/sm:OrganizationName[text()="FoobarEnglish"]', 1,
('[@xml:lang="en"]', 1)),
('/sm:OrganizationDisplayName', 2),
('/sm:OrganizationDisplayName[text()="Foobar"]', 1),
('/sm:OrganizationDisplayName[text()="FoobarEnglish"]', 1,
('[@xml:lang="en"]', 1)),
('/sm:OrganizationURL', 2),
('/sm:OrganizationURL[text()="http://foobar.com/"]', 1),
('/sm:OrganizationURL[text()="http://foobar.com/en/"]', 1,
('[@xml:lang="en"]', 1))),
('/sm:ContactPerson', 2,
('[@contactType="technical"]', 1),
('[@contactType="administrative"]', 1))),
namespaces=ns)