admin saml: handle binary content in metadata http response (#55455)

This commit is contained in:
Emmanuel Cazenave 2021-07-07 17:59:30 +02:00
parent 426705531e
commit 6787982330
2 changed files with 44 additions and 1 deletions

View File

@ -19,6 +19,7 @@ import xml.etree.ElementTree as ET
import requests
from django import forms
from django.core.exceptions import ValidationError
from django.utils.encoding import force_text
from django.utils.translation import ugettext_lazy as _
from authentic2.a2_rbac.utils import get_default_ou
@ -50,7 +51,7 @@ class AddLibertyProviderFromUrlForm(forms.Form):
try:
response = requests.get(url)
response.raise_for_status()
content = response.content
content = force_text(response.content)
except requests.RequestException as e:
raise ValidationError(
_('Retrieval of %(url)s failed: %(exception)s') % {'url': url, 'exception': e}

View File

@ -17,8 +17,11 @@
from urllib.parse import urlparse
import httmock
from authentic2.custom_user.models import User
from authentic2.models import Attribute
from authentic2.saml.models import LibertyProvider
from . import utils
@ -90,3 +93,42 @@ def test_app_setting_login_url(app, db, settings):
response = response.follow()
assert urlparse(response['Location']).path == settings.A2_MANAGER_LOGIN_URL
assert urlparse(response['Location']).query == 'next=/admin/'
def test_saml_libertyprovider_add_from_url(db, app, superuser):
utils.login(app, superuser)
resp = app.get(
'/admin/saml/libertyprovider/add-from-url/?entity_id=http%3A%2F%2F127.0.0.1%3A8003%2Faccounts%2Fmellon%2Fmetadata%2F'
)
# in URL : entity_id = http://127.0.0.1:8003/accounts/mellon/metadata/
resp.form.set('name', 'Some SAML client')
resp.form.set('slug', 'some-saml-client')
metadata = '''<EntityDescriptor entityID="http://127.0.0.1:8003/accounts/mellon/metadata/" xmlns="urn:oasis:names:tc:SAML:2.0:metadata">
<SPSSODescriptor AuthnRequestsSigned="true" WantAssertionsSigned="true" protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol">
<KeyDescriptor>
<ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<ds:X509Data>
<ds:X509Certificate>MIICPTCCAaagAwIBAgIJALokqqFKWl7+MA0GCSqGSIb3DQEBCwUAMDYxNDAyBgNVBAMMK2Nvbm5leGlvbi1wYXJpc25hbnRlcnJlLnRlc3QuZW50cm91dmVydC5vcmcwHhcNMTkwNDE2MTE1NDQxWhcNMjkwNDE1MTE1NDQxWjA2MTQwMgYDVQQDDCtjb25uZXhpb24tcGFyaXNuYW50ZXJyZS50ZXN0LmVudHJvdXZlcnQub3JnMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQD5ztXvBzQDQm2Ckfm4hk5J0OczQZmCoxLiI1zi7PuBEeaMxrSrH8pdv1kxsnToPILrA8kR1855wny98BQjmWsDZ9/UWst1TVHmoZmo811Zu2ucWl34nBlSjNDwNna9VCL4uFC9C0Oza2AQU7B45E//3PlihV2hAYhtzm5XACh9kQIDAQABo1MwUTAdBgNVHQ4EFgQU49GRX35TqEpcTZGdNIwOO3k5eNcwHwYDVR0jBBgwFoAU49GRX35TqEpcTZGdNIwOO3k5eNcwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOBgQC6bLxzOSKa76+6KS2pUb4I35VG9Sku2FlffZsM0jyJqfhroXWEYxduIZbjamGSOo5UoZuiBwaWof6QHcy34zuJolw1upKxjxPALSCgGfRcxbuk4yN3CroRKmeDvy1rHzVcfC1PXip3DVup/qUu81cnTA/ENRgnOwThgiZ4Ip2ZHg==</ds:X509Certificate>
</ds:X509Data>
</ds:KeyInfo>
</KeyDescriptor>
<SingleLogoutService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" Location="http://127.0.0.1:8003/accounts/mellon/logout/"/>
<AssertionConsumerService index="0" Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact" Location="http://127.0.0.1:8003/accounts/mellon/login/"/>
<AssertionConsumerService index="1" isDefault="true" Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="http://127.0.0.1:8003/accounts/mellon/login/"/>
</SPSSODescriptor>
</EntityDescriptor>'''
def metadata_response(url, request):
headers = {'content-type': 'text/xml'}
return httmock.response(
status_code=200, content=metadata.encode('utf-8'), headers=headers, request=request
)
with httmock.HTTMock(httmock.urlmatch(path=r'.*/accounts/mellon/metadata/$')(metadata_response)):
resp = resp.form.submit('_continue').follow()
assert resp.form.get('metadata_0').value == metadata
resp = resp.form.submit('_continue').follow()
liberty_provider = LibertyProvider.objects.get(slug='some-saml-client')
assert liberty_provider.metadata == metadata