diff --git a/passbook/saml_idp/base.py b/passbook/saml_idp/base.py index 83fc4ff56..177c3a1b1 100644 --- a/passbook/saml_idp/base.py +++ b/passbook/saml_idp/base.py @@ -7,7 +7,7 @@ from logging import getLogger from bs4 import BeautifulSoup from passbook.lib.config import CONFIG -from passbook.saml_idp import codex, exceptions, xml_render +from passbook.saml_idp import exceptions, utils, xml_render MINUTES = 60 HOURS = 60 * MINUTES @@ -110,7 +110,7 @@ class Processor: def _decode_request(self): """Decodes _request_xml from _saml_request.""" - self._request_xml = codex.decode_base64_and_inflate(self._saml_request).decode('utf-8') + self._request_xml = utils.decode_base64_and_inflate(self._saml_request).decode('utf-8') self._logger.debug('SAML request decoded') @@ -140,7 +140,7 @@ class Processor: def _encode_response(self): """Encodes _response_xml to _encoded_xml.""" - self._saml_response = codex.nice64(str.encode(self._response_xml)) + self._saml_response = utils.nice64(str.encode(self._response_xml)) def _extract_saml_request(self): """Retrieves the _saml_request AuthnRequest from the _django_request.""" @@ -187,7 +187,7 @@ class Processor: 'acs_url': self._request_params['ACS_URL'], 'saml_response': self._saml_response, 'relay_state': self._relay_state, - 'autosubmit': self._remote.application, + 'autosubmit': self._remote.application.skip_authorization, } def _parse_request(self): @@ -295,11 +295,11 @@ class Processor: # Return proper template params. return self._get_django_response_params() - def init_deep_link(self, request, sp_config, url): + def init_deep_link(self, request, url): """Initialize this Processor to make an IdP-initiated call to the SP's deep-linked URL.""" - self._reset(request, sp_config) - acs_url = self._remote['acs_url'] + self._reset(request) + acs_url = self._remote.acs_url # NOTE: The following request params are made up. Some are blank, # because they comes over in the AuthnRequest, but we don't have an # AuthnRequest in this case: diff --git a/passbook/saml_idp/codex.py b/passbook/saml_idp/codex.py deleted file mode 100644 index dabab0859..000000000 --- a/passbook/saml_idp/codex.py +++ /dev/null @@ -1,22 +0,0 @@ -"""Wrappers to de/encode and de/inflate strings""" - -import base64 -import zlib - - -def decode_base64_and_inflate(b64string): - """Base64 decode and ZLib decompress b64string""" - decoded_data = base64.b64decode(b64string) - return zlib.decompress(decoded_data, -15) - - -def deflate_and_base64_encode(string_val): - """Base64 and ZLib Compress b64string""" - zlibbed_str = zlib.compress(string_val) - compressed_string = zlibbed_str[2:-4] - return base64.b64encode(compressed_string) - - -def nice64(src): - """ Returns src base64-encoded and formatted nicely for our XML. """ - return base64.b64encode(src).decode('utf-8').replace('\n', '') diff --git a/passbook/saml_idp/forms.py b/passbook/saml_idp/forms.py index 797c16896..99341ee5b 100644 --- a/passbook/saml_idp/forms.py +++ b/passbook/saml_idp/forms.py @@ -3,6 +3,7 @@ from django import forms from passbook.saml_idp.models import SAMLProvider, get_provider_choices +from passbook.saml_idp.utils import CertificateBuilder class SAMLProviderForm(forms.ModelForm): @@ -10,6 +11,13 @@ class SAMLProviderForm(forms.ModelForm): processor_path = forms.ChoiceField(choices=get_provider_choices(), label='Processor') + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + builder = CertificateBuilder() + builder.build() + self.fields['signing_cert'].initial = builder.certificate + self.fields['signing_key'].initial = builder.private_key + class Meta: model = SAMLProvider diff --git a/passbook/saml_idp/models.py b/passbook/saml_idp/models.py index a21617136..0988a28f4 100644 --- a/passbook/saml_idp/models.py +++ b/passbook/saml_idp/models.py @@ -1,10 +1,11 @@ """passbook saml_idp Models""" from django.db import models +from django.shortcuts import reverse from django.utils.translation import gettext as _ from passbook.core.models import Provider -from passbook.lib.utils.reflection import class_to_path +from passbook.lib.utils.reflection import class_to_path, path_to_class from passbook.saml_idp.base import Processor @@ -21,14 +22,26 @@ class SAMLProvider(Provider): signing_key = models.TextField() form = 'passbook.saml_idp.forms.SAMLProviderForm' + _processor = None def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self._meta.get_field('processor_path').choices = get_provider_choices() + @property + def processor(self): + if not self._processor: + self._processor = path_to_class(self.processor_path)(self) + return self._processor + def __str__(self): return "SAMLProvider %s (processor=%s)" % (self.name, self.processor_path) + def link_download_metadata(self): + """Get link to download XML metadata for admin interface""" + return reverse('passbook_saml_idp:metadata_xml', + kwargs={'provider_id': self.pk}) + class Meta: verbose_name = _('SAML Provider') diff --git a/passbook/saml_idp/registry.py b/passbook/saml_idp/registry.py deleted file mode 100644 index 99caed9f8..000000000 --- a/passbook/saml_idp/registry.py +++ /dev/null @@ -1,28 +0,0 @@ -"""Registers and loads Processor classes from settings.""" -from logging import getLogger - -from passbook.lib.utils.reflection import path_to_class -from passbook.saml_idp.exceptions import CannotHandleAssertion -from passbook.saml_idp.models import SAMLProvider - -LOGGER = getLogger(__name__) - - -def get_processor(remote): - """Get an instance of the processor with config.""" - proc = path_to_class(remote.processor_path) - return proc(remote) - - -def find_processor(request): - """Returns the Processor instance that is willing to handle this request.""" - for remote in SAMLProvider.objects.all(): - proc = get_processor(remote) - try: - if proc.can_handle(request): - return proc, remote - except CannotHandleAssertion as exc: - # Log these, but keep looking. - LOGGER.debug('%s %s', proc, exc) - - raise CannotHandleAssertion('No Processors to handle this request.') diff --git a/passbook/saml_idp/templates/saml/idp/base.html b/passbook/saml_idp/templates/saml/idp/base.html deleted file mode 100644 index 98132b5b2..000000000 --- a/passbook/saml_idp/templates/saml/idp/base.html +++ /dev/null @@ -1,8 +0,0 @@ -{% extends "core/base.html" %} - -{% comment %} -This is a placeholder template. You can override this saml2idp/base.html -template to make all the saml2idp templates fit better into your site's -look-and-feel. That may be easier than overriding all the saml2idp templates -individually. -{% endcomment %} diff --git a/passbook/saml_idp/templates/saml/idp/login.html b/passbook/saml_idp/templates/saml/idp/login.html index 94d7fac52..7c2087045 100644 --- a/passbook/saml_idp/templates/saml/idp/login.html +++ b/passbook/saml_idp/templates/saml/idp/login.html @@ -1,47 +1,49 @@ -{% extends "core/skel.html" %} +{% extends "login/base.html" %} {% load utils %} {% load i18n %} {% block title %} -{% title 'SSO - Authorize External Source' %} +{% title 'Authorize Application' %} {% endblock %} -{% block body %} -
-
- {% csrf_token %} - - - - - -