Example #1
0
    def test(
        self,
        _,
        expression,
        expected_result,
        context=None,
        safe_classes=None,
        expected_exception=None,
    ):
        # Arrange
        parser = DSLParser()
        visitor = DSLEvaluationVisitor()
        evaluator = DSLEvaluator(parser, visitor)

        if safe_classes is None:
            safe_classes = []

        # Act
        if expected_exception:
            with pytest.raises(expected_exception):
                evaluator.evaluate(expression, context, safe_classes)
        else:
            result = evaluator.evaluate(expression, context, safe_classes)

            # Assert
            assert expected_result == result
Example #2
0
def validator_factory():
    metadata_parser = SAMLMetadataParser()
    parser = DSLParser()
    visitor = DSLEvaluationVisitor()
    evaluator = DSLEvaluator(parser, visitor)
    subject_filter = SAMLSubjectFilter(evaluator)

    return SAMLSettingsValidator(metadata_parser, subject_filter)
Example #3
0
    def test_validate(
        self,
        _,
        sp_xml_metadata,
        idp_xml_metadata,
        patron_id_regular_expression,
        expected_validation_result,
    ):
        """Ensure that SAMLSettingsValidator correctly validates the input data.

        :param sp_xml_metadata: SP SAML metadata
        :type sp_xml_metadata: str

        :param idp_xml_metadata: IdP SAML metadata
        :type idp_xml_metadata: str

        :param patron_id_regular_expression: Regular expression used to extract a unique patron ID from SAML attributes
        :type patron_id_regular_expression: str

        :param expected_validation_result: Expected result: ProblemDetail object if validation must fail, None otherwise
        :type expected_validation_result: Optional[ProblemDetail]
        """
        # Arrange
        submitted_form_data = MultiDict()

        if sp_xml_metadata is not None:
            submitted_form_data.add(
                SAMLConfiguration.service_provider_xml_metadata.key,
                sp_xml_metadata)
        if idp_xml_metadata is not None:
            submitted_form_data.add(
                SAMLConfiguration.non_federated_identity_provider_xml_metadata.
                key,
                idp_xml_metadata,
            )
        if patron_id_regular_expression is not None:
            submitted_form_data.add(
                SAMLConfiguration.patron_id_regular_expression.key,
                patron_id_regular_expression,
            )

        submitted_form = {"form": submitted_form_data}
        metadata_parser = SAMLMetadataParser()
        parser = DSLParser()
        visitor = DSLEvaluationVisitor()
        evaluator = DSLEvaluator(parser, visitor)
        subject_filter = SAMLSubjectFilter(evaluator)
        validator = SAMLSettingsValidator(metadata_parser, subject_filter)

        # Act
        settings = list(SAMLWebSSOAuthenticationProvider.SETTINGS)
        result = validator.validate(settings, submitted_form)

        # Assert
        if isinstance(result, ProblemDetail):
            assert expected_validation_result.response == result.response
        else:
            assert expected_validation_result == result
Example #4
0
    def test_start_authentication(self, _, service_provider,
                                  identity_providers):
        configuration = create_autospec(spec=SAMLConfiguration)
        configuration.service_provider_debug_mode = MagicMock(
            return_value=False)
        configuration.service_provider_strict_mode = MagicMock(
            return_value=False)
        configuration.get_service_provider = MagicMock(
            return_value=service_provider)
        configuration.get_identity_providers = MagicMock(
            return_value=identity_providers)
        onelogin_configuration = SAMLOneLoginConfiguration(configuration)
        subject_parser = SAMLSubjectParser()
        parser = DSLParser()
        visitor = DSLEvaluationVisitor()
        evaluator = DSLEvaluator(parser, visitor)
        subject_filter = SAMLSubjectFilter(evaluator)
        authentication_manager = SAMLAuthenticationManager(
            onelogin_configuration, subject_parser, subject_filter)

        with self.app.test_request_context("/"):
            result = authentication_manager.start_authentication(
                self._db, fixtures.IDP_1_ENTITY_ID, "")

            query_items = parse_qs(urlsplit(result).query)
            saml_request = query_items["SAMLRequest"][0]
            decoded_saml_request = OneLogin_Saml2_Utils.decode_base64_and_inflate(
                saml_request)

            validation_result = OneLogin_Saml2_XML.validate_xml(
                decoded_saml_request, "saml-schema-protocol-2.0.xsd", False)
            assert isinstance(validation_result,
                              OneLogin_Saml2_XML._element_class)

            saml_request_dom = fromstring(decoded_saml_request)

            acs_url = saml_request_dom.get("AssertionConsumerServiceURL")
            assert acs_url == SERVICE_PROVIDER_WITH_UNSIGNED_REQUESTS.acs_service.url

            acs_binding = saml_request_dom.get("ProtocolBinding")
            assert (acs_binding == SERVICE_PROVIDER_WITH_UNSIGNED_REQUESTS.
                    acs_service.binding.value)

            sso_url = saml_request_dom.get("Destination")
            assert sso_url == IDENTITY_PROVIDERS[0].sso_service.url

            name_id_policy_nodes = OneLogin_Saml2_XML.query(
                saml_request_dom, "./samlp:NameIDPolicy")

            assert name_id_policy_nodes is not None
            assert len(name_id_policy_nodes) == 1

            name_id_policy_node = name_id_policy_nodes[0]
            name_id_format = name_id_policy_node.get("Format")

            assert (name_id_format ==
                    SERVICE_PROVIDER_WITH_UNSIGNED_REQUESTS.name_id_format)
    def test_authentication_document(self, _, identity_providers,
                                     expected_result):
        # Arrange
        configuration = create_autospec(spec=SAMLConfiguration)
        configuration.get_service_provider = MagicMock(
            return_value=SERVICE_PROVIDER)
        configuration.get_identity_providers = MagicMock(
            return_value=identity_providers)
        configuration.patron_id_use_name_id = "true"
        configuration.patron_id_attributes = []
        configuration.patron_id_regular_expression = None

        configuration_factory_create_context_manager = MagicMock()
        configuration_factory_create_context_manager.__enter__ = MagicMock(
            return_value=configuration)

        configuration_factory = create_autospec(spec=SAMLConfigurationFactory)
        configuration_factory.create = MagicMock(
            return_value=configuration_factory_create_context_manager)

        onelogin_configuration = SAMLOneLoginConfiguration(configuration)
        subject_parser = SAMLSubjectParser()
        parser = DSLParser()
        visitor = DSLEvaluationVisitor()
        evaluator = DSLEvaluator(parser, visitor)
        subject_filter = SAMLSubjectFilter(evaluator)
        authentication_manager = SAMLAuthenticationManager(
            onelogin_configuration, subject_parser, subject_filter)

        authentication_manager_factory = create_autospec(
            spec=SAMLAuthenticationManagerFactory)
        authentication_manager_factory.create = MagicMock(
            return_value=authentication_manager)

        with patch("api.saml.provider.SAMLAuthenticationManagerFactory"
                   ) as authentication_manager_factory_constructor_mock, patch(
                       "api.saml.provider.SAMLConfigurationFactory"
                   ) as configuration_factory_constructor_mock:
            authentication_manager_factory_constructor_mock.return_value = (
                authentication_manager_factory)
            configuration_factory_constructor_mock.return_value = configuration_factory

            # Act
            provider = SAMLWebSSOAuthenticationProvider(
                self._default_library, self._integration)

            self.app.config["SERVER_NAME"] = "localhost"

            with self.app.test_request_context("/"):
                result = provider.authentication_flow_document(self._db)

            # Assert
            assert expected_result == result
Example #6
0
    def test_validate(self, _, expression, expected_exception):
        # Arrange
        parser = DSLParser()
        visitor = DSLEvaluationVisitor()
        evaluator = DSLEvaluator(parser, visitor)
        subject_filter = SAMLSubjectFilter(evaluator)

        # Act
        if expected_exception:
            with pytest.raises(expected_exception):
                subject_filter.validate(expression)
        else:
            subject_filter.validate(expression)
Example #7
0
    def test_execute(
        self, _, expression, subject, expected_result, expected_exception=None
    ):
        # Arrange
        parser = DSLParser()
        visitor = DSLEvaluationVisitor()
        evaluator = DSLEvaluator(parser, visitor)
        subject_filter = SAMLSubjectFilter(evaluator)

        # Act
        if expected_exception:
            with pytest.raises(expected_exception):
                subject_filter.execute(expression, subject)
        else:
            result = subject_filter.execute(expression, subject)

            # Assert
            assert expected_result == result
Example #8
0
    def create(self, configuration):
        """
        Creates a new instance of SAMLAuthenticationManager class

        :param configuration: SAML authentication provider's configuration
        :type configuration: api.saml.configuration.model.SAMLConfiguration

        :return: SAML authentication manager
        :rtype: SAMLAuthenticationManager
        """
        onelogin_configuration = SAMLOneLoginConfiguration(configuration)
        subject_parser = SAMLSubjectParser()
        parser = DSLParser()
        visitor = DSLEvaluationVisitor()
        evaluator = DSLEvaluator(parser, visitor)
        subject_filter = SAMLSubjectFilter(evaluator)
        authentication_manager = SAMLAuthenticationManager(
            onelogin_configuration, subject_parser, subject_filter)

        return authentication_manager
Example #9
0
    def test_finish_authentication(
        self,
        _,
        saml_response,
        current_time,
        filter_expression,
        expected_value,
        mock_validation=False,
    ):
        # Arrange
        identity_provider_entity_id = "http://idp.hilbertteam.net/idp/shibboleth"
        service_provider_host_name = "opds.hilbertteam.net"

        identity_providers = [
            copy(identity_provider) for identity_provider in IDENTITY_PROVIDERS
        ]
        identity_providers[0].entity_id = identity_provider_entity_id

        if mock_validation:
            validate_mock = MagicMock(return_value=True)
        else:
            real_validate_sign = OneLogin_Saml2_Utils.validate_sign
            validate_mock = MagicMock(side_effect=lambda *args, **kwargs:
                                      real_validate_sign(*args, **kwargs))

        filter_expression_mock = PropertyMock(return_value=filter_expression)
        service_provider_debug_mode_mock = PropertyMock(return_value=False)
        service_provider_strict_mode = PropertyMock(return_value=False)

        configuration = create_autospec(spec=SAMLConfiguration)
        type(configuration).filter_expression = filter_expression_mock
        type(configuration
             ).service_provider_debug_mode = service_provider_debug_mode_mock
        type(configuration
             ).service_provider_strict_mode = service_provider_strict_mode
        configuration.get_service_provider = MagicMock(
            return_value=SERVICE_PROVIDER_WITH_UNSIGNED_REQUESTS)
        configuration.get_identity_providers = MagicMock(
            return_value=identity_providers)
        onelogin_configuration = SAMLOneLoginConfiguration(configuration)
        subject_parser = SAMLSubjectParser()
        parser = DSLParser()
        visitor = DSLEvaluationVisitor()
        evaluator = DSLEvaluator(parser, visitor)
        subject_filter = SAMLSubjectFilter(evaluator)
        authentication_manager = SAMLAuthenticationManager(
            onelogin_configuration, subject_parser, subject_filter)
        saml_response = base64.b64encode(saml_response)

        # Act
        with freeze_time(current_time):
            with patch(
                    "onelogin.saml2.response.OneLogin_Saml2_Utils.validate_sign",
                    validate_mock,
            ):
                self.app.config["SERVER_NAME"] = service_provider_host_name

                with self.app.test_request_context(
                        "/SAML2/POST", data={"SAMLResponse": saml_response}):
                    result = authentication_manager.finish_authentication(
                        self._db, identity_provider_entity_id)

                    # Assert
                    assert expected_value == result