def test_valid_saml_auth(self, mock_datetime): mock_datetime.now.return_value = datetime(2019, 4, 9, 21, 35, 0, tzinfo=timezone.utc) mock_datetime.strptime = datetime.strptime a = SAMLAuthenticator() signed_xml = a._verify_saml_signature(self.metadata_etree, self.response_etree) assert etree.tostring(signed_xml) == etree.tostring( self.verified_signed_xml) response_is_valid, signed_xml = a._test_valid_saml_response( self.metadata_etree, self.response_etree) assert response_is_valid # Check the signed xml is the subset of the xml that is returned by signxml assert etree.tostring(signed_xml) == etree.tostring( self.verified_signed_xml)
def test_not_valid_xml(self, mock_b64decode): a = SAMLAuthenticator() fake_data = {a.login_post_field: 'this string isn\'t important'} mock_b64decode.return_value = 'bad xml string' assert a._get_saml_doc_etree(fake_data) is None
def test_tampered_response(self): a = SAMLAuthenticator() a.metadata_content = test_constants.sample_metadata_xml assert a._authenticate(None, { a.login_post_field: test_constants.tampered_sample_response_encoded }) is None
def test_check_username_invalid_username(self): a = SAMLAuthenticator() a._optional_user_add = MagicMock() assert not a._check_username_and_add_user('bluedata/') a._optional_user_add.assert_not_called()
def test_create_system_users_option(self): a = SAMLAuthenticator() a.create_system_users = False a._optional_user_add = MagicMock() assert a._check_username_and_add_user('bluedata') a._optional_user_add.assert_not_called()
def test_metadata_field(self): a = SAMLAuthenticator() a.metadata_url = 'bad_data' a.metadata_content = test_constants.sample_metadata_xml assert a._get_metadata_from_config( ) == test_constants.sample_metadata_xml self._test_high_level_metadata_retrieval_functions(a)
def test_get_handlers(self): a = SAMLAuthenticator() handler_list = a.get_handlers(None) for url_path, handler_class in handler_list: assert url_path in self.expected_handler_paths assert isinstance(handler_class, type) assert issubclass(handler_class, BaseHandler)
def test_no_xpath_no_roles_run_default(self): a = SAMLAuthenticator() a._valid_roles_in_assertion = unittest.mock.create_autospec( MagicMock(name='_valid_roles_in_assertion')) a.log.warning = MagicMock(name='warning') assert a._valid_config_and_roles(None, None) a._valid_roles_in_assertion.assert_not_called() a.log.warning.assert_not_called()
def test_no_not_before(self): a = SAMLAuthenticator() tampered_etree = etree.fromstring( test_constants.tampered_assertion_no_not_before) assert not a._verify_physical_constraints(tampered_etree) assert not a._verify_saml_response_fields(self.metadata_etree, tampered_etree)
def test_create_existing_user(self, mock_pwd, mock_subprocess): mock_pwd.getpwnam.return_value = True a = SAMLAuthenticator() assert a._optional_user_add('Bluedata') mock_pwd.getpwnam.assert_called_once_with('Bluedata') mock_subprocess.call.assert_not_called()
def test_get_username_from_saml_doc(self): a = SAMLAuthenticator() assert 'Bluedata' == a._get_username_from_saml_etree( self.verified_signed_xml) assert 'Bluedata' == a._get_username_from_saml_etree( self.response_etree) assert 'Bluedata' == a._get_username_from_saml_doc( self.verified_signed_xml, self.response_etree)
def test_get_invalid_xml_element(self): a = SAMLAuthenticator() a.metadata_content = test_constants.sample_metadata_xml mock_handler_self = MagicMock() with self.assertRaises(IndexError): a._get_redirect_from_metadata_and_redirect('md:BadElement', mock_handler_self)
def test_make_full_metadata_default(self): a = SAMLAuthenticator() mock_handler_self = MagicMock() mock_handler_self.request.protocol = 'https' mock_handler_self.request.host = 'localhost:8000' assert a._make_sp_metadata( mock_handler_self) == self.full_sp_meta_default
def test_create_user_fails(self, mock_pwd, mock_subprocess): mock_pwd.getpwnam.side_effect = KeyError('Bad username') mock_subprocess.call.return_value = 1 a = SAMLAuthenticator() assert not a._optional_user_add('Bluedata') mock_pwd.getpwnam.assert_called_once_with('Bluedata') mock_subprocess.call.assert_called_once_with(['useradd', 'Bluedata'])
def test_make_full_metadata_nameid_format(self): a = SAMLAuthenticator() a.nameid_format = 'urn:oasis:names:tc:SAML:2.0:nameid-format:persistent' mock_handler_self = MagicMock() mock_handler_self.request.protocol = 'https' mock_handler_self.request.host = 'localhost:8000' assert a._make_sp_metadata( mock_handler_self) == self.full_sp_meta_nameid_format
def test_assertion_no_issuer(self): a = SAMLAuthenticator() tampered_etree = etree.fromstring( test_constants.tampered_assertion_no_issuer) assert not a._verify_saml_response_against_metadata( self.metadata_etree, tampered_etree) assert not a._verify_saml_response_fields(self.metadata_etree, tampered_etree)
def test_make_full_metadata_org_name(self): a = SAMLAuthenticator() a.organization_name = 'org_name' mock_handler_self = MagicMock() mock_handler_self.request.protocol = 'https' mock_handler_self.request.host = 'localhost:8000' assert a._make_sp_metadata( mock_handler_self) == self.full_sp_meta_org_name
def test_signed_xml_no_audience(self): a = SAMLAuthenticator() a.audience = '''audience_should_exist''' tampered_etree = etree.fromstring( test_constants.tampered_assertion_no_audience) assert not a._verify_saml_response_against_configured_fields( tampered_etree) assert not a._verify_saml_response_fields(self.metadata_etree, tampered_etree)
def test_get_saml_doc_etree(self): # We expect the SAML Response to be coming in base 64 encoded a = SAMLAuthenticator() fake_data = { a.login_post_field: test_constants.b64encoded_response_xml } faked_etree = a._get_saml_doc_etree(fake_data) real_etree = etree.fromstring(test_constants.sample_response_xml) assert etree.tostring(faked_etree) == etree.tostring(real_etree)
def test_get_saml_doc_different_location(self): a = SAMLAuthenticator() a.login_post_field = 'test' fake_data = { a.login_post_field: test_constants.b64encoded_response_xml } faked_etree = a._get_saml_doc_etree(fake_data) real_etree = etree.fromstring(test_constants.sample_response_xml) assert etree.tostring(faked_etree) == etree.tostring(real_etree)
def test_signed_xml_no_recipient(self): a = SAMLAuthenticator() a.recipient = 'unimportant_recipient' tampered_etree = etree.fromstring( test_constants.tampered_assertion_no_recipient) assert not a._verify_saml_response_against_configured_fields( tampered_etree) assert not a._verify_saml_response_fields(self.metadata_etree, tampered_etree)
def test_create_user_alternate_binary_existing_user( self, mock_pwd, mock_subprocess): mock_pwd.getpwnam.return_value = True binary_value = 'test_binary' a = SAMLAuthenticator() a.create_system_user_binary = binary_value assert a._optional_user_add('Bluedata') mock_pwd.getpwnam.assert_called_once_with('Bluedata') mock_subprocess.call.assert_not_called()
def test_get_valid_logout_redirect(self): a = SAMLAuthenticator() a.metadata_content = test_constants.sample_metadata_xml mock_handler_self = MagicMock() a._get_redirect_from_metadata_and_redirect('md:SingleLogoutService', mock_handler_self) mock_handler_self.redirect.assert_called_once_with( 'https://bluedata-test-before-deploy.onelogin.com/trust/saml2/http-redirect/slo/719630', permanent=False)
def _confirm_tom(self, saml_data, mock_datetime, mock_pwd): mock_datetime.now.return_value = saml_data.datetime_stamp mock_datetime.strptime = datetime.strptime mock_pwd.getpwnam.return_value = True a = SAMLAuthenticator() a.metadata_content = saml_data.metadata_xml assert 'tom' == a._authenticate( None, {a.login_post_field: saml_data.b64encoded_response}) mock_datetime.now.assert_called_once_with(timezone.utc) mock_pwd.getpwnam.assert_called_once_with('tom')
def test_create_user_alternate_binary(self, mock_pwd, mock_subprocess): mock_pwd.getpwnam.side_effect = KeyError('Bad username') mock_subprocess.call.return_value = 0 binary_value = 'test_binary' a = SAMLAuthenticator() a.create_system_user_binary = binary_value assert a._optional_user_add('Bluedata') mock_pwd.getpwnam.assert_called_once_with('Bluedata') mock_subprocess.call.assert_called_once_with( [binary_value, 'Bluedata'])
def test_no_xpath_roles(self): a = SAMLAuthenticator() a.allowed_roles = 'value' a._valid_roles_in_assertion = unittest.mock.create_autospec( MagicMock(name='_valid_roles_in_assertion')) a.log.warning = MagicMock(name='warning') assert a._valid_config_and_roles(None, None) a._valid_roles_in_assertion.assert_not_called() print(a.log.warning.call_args_list) a.log.warning.assert_called() a.log.warning.assert_any_call(a._const_warn_explain) a.log.warning.assert_any_call(a._const_warn_no_role_xpath)
def test_no_metadata_cert(self): a = SAMLAuthenticator() no_cert_metadata_etree = etree.fromstring( test_constants.sample_metadata_no_cert_xml) bad_signed_xml = a._verify_saml_signature(no_cert_metadata_etree, self.response_etree) assert bad_signed_xml is None response_is_valid, signed_xml = a._test_valid_saml_response( no_cert_metadata_etree, self.response_etree) assert not response_is_valid assert signed_xml is None
def test_tampered_saml_response(self): a = SAMLAuthenticator() tampered_etree = etree.fromstring( test_constants.tampered_sample_response_xml) bad_signed_xml = a._verify_saml_signature(self.metadata_etree, tampered_etree) assert bad_signed_xml is None response_is_valid, signed_xml = a._test_valid_saml_response( self.metadata_etree, tampered_etree) assert not response_is_valid assert signed_xml is None
def test_metadata_no_entity(self): a = SAMLAuthenticator() no_metadata_entity_etree = etree.fromstring( test_constants.sample_metadata_no_entity) assert a._verify_saml_response_against_metadata( no_metadata_entity_etree, self.verified_signed_xml) is False assert a._verify_saml_response_fields( no_metadata_entity_etree, self.verified_signed_xml) is False response_is_valid, signed_xml = a._test_valid_saml_response( no_metadata_entity_etree, self.response_etree) assert not response_is_valid assert etree.tostring(signed_xml) == etree.tostring( self.verified_signed_xml)
def test_metadata_url(self, mock_urlopen): entered_obj = MagicMock() entered_obj.read.return_value = test_constants.sample_metadata_xml mock_urlopen().__enter__.return_value = entered_obj a = SAMLAuthenticator() a.metadata_url = 'http://foo' # Check that we're getting the right value assert a._get_metadata_from_url() == test_constants.sample_metadata_xml # Check that we have, at least once, called open with the provided url # TODO: Figure out how to do this so we can use 'assert_called_once_with' mock_urlopen.assert_any_call(a.metadata_url) # Check that we're reading the file entered_obj.read.assert_called_once() self._test_readable_mock(a, mock_urlopen)