def test_protocol_test_suite(self): for case_path in TEST_SUITE.cases(): parser = ProtocolTestSuiteParser(case_path) request_signable = RequestSignable(**parser.request_attributes) signed_headers_v2 = TEST_SUITE.signer.signed_headers_v2( request_signable, TEST_SUITE.additional_attributes) if "authentication-only" not in case_path: with self.subTest(test="string_to_sign_v2", case_name=parser.case_name): string_to_sign = request_signable.string_to_sign_v2( TEST_SUITE.additional_attributes) self.assertEqual(string_to_sign.decode("utf-8"), parser.sts) with self.subTest(test="signature", case_name=parser.case_name): self.assertEqual( TEST_SUITE.signer.signature_v2(parser.sts), parser.sig) with self.subTest(test="authentication headers", case_name=parser.case_name): self.assertEqual(signed_headers_v2, parser.auth_headers) with self.subTest(test="authentication", case_name=parser.case_name): signed = Signed.from_headers(signed_headers_v2) authenticator = LocalAuthenticator(request_signable, signed, self.logger) self.assertTrue(authenticator._authenticate())
def setUp(self): with open(os.path.join(os.path.dirname(__file__), "keys", "fake_mauth.priv.key"), "r") as key_file: self.private_key = key_file.read() self.signer = Signer(APP_UUID, self.private_key, "v1,v2") self.signer_v1_only = Signer(APP_UUID, self.private_key, "v1") self.signer_v2_only = Signer(APP_UUID, self.private_key, "v2") self.signable = RequestSignable(**REQUEST_ATTRIBUTES) self.signable_with_binary_body = RequestSignable(**REQUEST_ATTRIBUTES_WITH_BINARY_BODY)
def test_authentication_v1_does_not_authenticate_a_false_message(self): self.authenticator.signable = RequestSignable(method="GET", url=URL, body=BODY) with self.assertRaises(InauthenticError) as exc: self.authenticator._authenticate() self.assertEqual(str(exc.exception), "Signature verification failed for request.")
def make_headers(self, request): """Make headers for the request. :param requests.models.PreparedRequest request: the Request object """ request_signable = RequestSignable(method=request.method, url=request.url, body=request.body) return {**self.signer.signed_headers(request_signable)}
def authenticate(self, signed_request): """ Authenticates a request :param signed_request: Request object :type request: werkzeug.wrappers.BaseRequest :return: Is the request authentic, Status Code, Message :rtype: bool, int, str """ signable = RequestSignable(method=signed_request.method, url=signed_request.path, body=signed_request.data) return self._authenticator(signable, Signed.from_headers(signed_request.headers), logger).is_authentic()
def setUp(self): self.__get_public_key__ = KeyHolder.get_public_key KeyHolder.get_public_key = MagicMock(return_value=load_key("rsapub")) Config.V2_ONLY_AUTHENTICATE = False self.logger = logging.getLogger() self.v1_headers = copy.deepcopy(X_MWS_HEADERS) self.v2_headers = copy.deepcopy(MWSV2_HEADERS) self.signable = RequestSignable(method="POST", url=URL, body=BODY) self.authenticator = LocalAuthenticator( self.signable, Signed.from_headers(self.v1_headers), self.logger)
def setUp(self): Config.V2_ONLY_AUTHENTICATE = False RemoteAuthenticator._MAUTH = { "auth": MagicMock(), "url": MAUTH_AUTHENTICATION_URL } self.logger = logging.getLogger() self.v1_headers = copy.deepcopy(X_MWS_HEADERS) self.v2_headers = copy.deepcopy(MWSV2_HEADERS) self.signable = RequestSignable(method="POST", url=URL, body=BODY) self.signed = Signed.from_headers(self.v1_headers) self.authenticator = RemoteAuthenticator(self.signable, self.signed, self.logger)
def __init__(self, headers, v2_only_authenticate=False, method="POST"): Config.V2_ONLY_AUTHENTICATE = v2_only_authenticate signable = RequestSignable(method=method, url=URL, body=BODY) super().__init__(signable, Signed.from_headers(headers), logging.getLogger())
def __init__(self, method, url, headers, body): logger = logging.getLogger() signable = RequestSignable(method=method, url=url, body=body) authenticator = LocalAuthenticator if Config.MAUTH_MODE == "local" else RemoteAuthenticator self._authenticator = authenticator(signable, Signed.from_headers(headers), logger)
class SignerTest(unittest.TestCase): def setUp(self): with open(os.path.join(os.path.dirname(__file__), "keys", "fake_mauth.priv.key"), "r") as key_file: self.private_key = key_file.read() self.signer = Signer(APP_UUID, self.private_key, "v1,v2") self.signer_v1_only = Signer(APP_UUID, self.private_key, "v1") self.signer_v2_only = Signer(APP_UUID, self.private_key, "v2") self.signable = RequestSignable(**REQUEST_ATTRIBUTES) self.signable_with_binary_body = RequestSignable(**REQUEST_ATTRIBUTES_WITH_BINARY_BODY) @freeze_time(EPOCH_DATETIME) def test_signed_headers(self): expected = { "X-MWS-Authentication": r"\AMWS {}:".format(APP_UUID), "X-MWS-Time": EPOCH, "MCC-Authentication": r"MWSV2 {}:[^;]*;".format(APP_UUID), "MCC-Time": EPOCH, } signed_headers = self.signer.signed_headers(self.signable, ADDITIONAL_ATTRIBUTES) self.assertEqual(signed_headers.keys(), expected.keys()) self.assertRegex(signed_headers["X-MWS-Authentication"], expected["X-MWS-Authentication"]) self.assertRegex(signed_headers["MCC-Authentication"], expected["MCC-Authentication"]) self.assertEqual(signed_headers["X-MWS-Time"], expected["X-MWS-Time"]) self.assertEqual(signed_headers["MCC-Time"], expected["MCC-Time"]) @freeze_time(EPOCH_DATETIME) def test_signed_headers_v1_only(self): expected = {"X-MWS-Authentication": r"\AMWS {}:".format(APP_UUID), "X-MWS-Time": EPOCH} signed_headers = self.signer_v1_only.signed_headers(self.signable, ADDITIONAL_ATTRIBUTES) self.assertEqual(signed_headers.keys(), expected.keys()) self.assertRegex(signed_headers["X-MWS-Authentication"], expected["X-MWS-Authentication"]) self.assertEqual(signed_headers["X-MWS-Time"], expected["X-MWS-Time"]) @freeze_time(EPOCH_DATETIME) def test_signed_headers_v2_only(self): expected = {"MCC-Authentication": r"MWSV2 {}:[^;]*;".format(APP_UUID), "MCC-Time": EPOCH} signed_headers = self.signer_v2_only.signed_headers(self.signable, ADDITIONAL_ATTRIBUTES) self.assertEqual(signed_headers.keys(), expected.keys()) self.assertRegex(signed_headers["MCC-Authentication"], expected["MCC-Authentication"]) self.assertEqual(signed_headers["MCC-Time"], expected["MCC-Time"]) def test_signature_v1(self): tested = self.signer.signature_v1("Hello world") self.assertEqual( tested, "1oTyoecqng4TE7ycGoW6qFMSPpA4C9TiZVDANHN4T/76LxtcCqmTTn9VCsVIDRWGKl3O5EzJEUYIfbI2QjsMdxtOk1BmMJspX08nAhRxZA" "j3urNaBDkKPKmCiDgpaBNwJHlAVPi9LuVun6rFqRASkjz7jDTt+EVgrWHnJxcikXYMx32VYFteQXPQNpYmPqrduJVuadcgCZWqBqVWGVHR" "pRdb2OXYPkJ3FEnvPZtSnufcgrticJBD5PDY6LKYmhNwgvVOXjSPRDxsDnqc5fSn4+zQYAZHo4ZbarRpPoj9C+YXp+BDb8gfm7wyuwKLSt" "UE5cck4dbWae+Vvle5QrObNw==", ) def test_signature_v1_unicode(self): tested = self.signer.signature_v1("こんにちはÆ") self.assertEqual( tested, "F7t8/AJCbGFDbIsE41u0CqsT4VB2lm0hXlQdCw2Io/5fBjJOGMZTiHEUj604YSb/zWKgFZYYUNpY+aVXZH7EjkB/Lg1l8MIid1OMV9Ok/U" "bhMzvcPrHoi8DqOzvbx/+be4hN9GpDiY5woBak2E7NgI0x8sagpUXjMqnRR47O3PCLsE0x0PjkSGztWFt2aRWYSlRASi96Z8ESLhF76KbI" "G7iekW54/EusK+qGA3sewlWbCuBisVBoF8yRtukwq065vz7VZx1GPNGbmB+MF6uGvxh+hhcYbq/kbcuHoAtqrp0oJJqXRbvPzrUZKZW86O" "tQzekMkzapDDMfJhE0V+SxNw==", ) def test_signature_v2(self): tested = self.signer.signature_v2("Hello world") self.assertEqual( tested, "G7jZk1nf5kd+oOzHfMsTS18pNkZea22pT6XsJaH5XCKqP4tYoua5isDWtipagwmjveEr3dG2tUC9KwiOLDGO30xiO4fdZwhyUb3mBrtELC" "rBz0nXoH7BlhV4LmRVtiPtVwLHauRb01KglPx0WoyuOEbrCO4ikwls75s/wv22Xk6kVFYx2y1r+HQWpeqQETarQs/x/2W610TqDjNdXU0V" "FRKJ8w0ERWlt5lJGBhp0zaoguyyVMvC8fjNHFORNIZHYVd0DOQAOlHmJD+0JdNo+2qcrA2d3G4+vc/pWRV+lI2buudyOGSnURZhKan/S0j" "Ue9yF2tS+3wXulqfLM3pFhwA==", ) def test_signature_v2_unicode(self): tested = self.signer.signature_v2("こんにちはÆ") self.assertEqual( tested, "eHvTMmEH31a9Tz6ZikHNUQPtii5iSjbkukQcFflQR6BtWL+HlZGgyjcL8jOT9oVMxkFV2eITrBA4hBPGznJlQ22yRca82tcOBKznllqTPT" "0vk8t2oX4ruPjFO1vaw/Eiko3r29+VflYibAEmP5m+SqhUZn5BWeDlFAkp6UqVOtfQzX7I6J/M7tsgw8PZQp6FUUDtXPSLFAkIPpcW/wND" "siV5wjlQzdlDAMc+Onc0lMFUcG0uH2W3ciUe5I2+ID4EvuprEUFDy8FYzXativ9p3k5TGtt7u0BXd39ll4r7p6pdby6+JgFjT2ITg3N5iC" "q17UFV5tFUABZ3dak/wT0apA==", ) def test_signature_v1_binary_body(self): string_to_sign_v1 = self.signable_with_binary_body.string_to_sign_v1(ADDITIONAL_ATTRIBUTES) tested = self.signer.signature_v1(string_to_sign_v1) self.assertEqual( tested, "19C27KyNwGA3KByjpQi7MssyDGBAha4ByuPmIobaZ9PRnXa42ZD1njD5ZQVuNMDHtL+Zfo851UGmPphaqgJeSK4niqUOM2dhwMuj6QAE+z" "0IFfhJvIXrIp1FAavMSlrdeDRqsVWjlwfoZeqY3HJk1vfY+7YMYApIPagmZH/3OoSB84k3o6WYplGtT8KvKRi8GDlq6D+gLLtAo9ocgQAO" "OhSzNyCowNcMUKXq8LlVXFguekawC8oEz+zJ0zJhDh9NnXMfp3fIg0a2MBDZhQSRLFUo/AMczZBGMl63nIQWq029/0f3xdiiQf3Trv4wBS" "zCiMSnPMg4uOjfDZY0tMR1JA==", ) def test_signature_v2_binary_body(self): string_to_sign_v2 = self.signable_with_binary_body.string_to_sign_v2(ADDITIONAL_ATTRIBUTES) tested = self.signer.signature_v2(string_to_sign_v2) self.assertEqual( tested, "s9cqo1kIqiw9lvCxXq2ObAIJOU/m0tap79ox8mvKKS8QabGvIJblwRn5YiUwYb2VHix0q3teU4+CYuLe5+wuxhwtraAfNwZQt0eIfyO3AX" "Q001BVaROq75GW7bEFKoy0TOx4dgaFTHTs56Pr6A3cC4IPGBpV5Utlx6ck0Wd6u6rU7BDtZLawVl6wg3fvXn23iFP1D0QwouldyCtL9y9E" "TjWzTnFSz9cRPrZ4dzKyVeUwsCCGSkcYTz+jYTfvsv51OVOdxaTscyGWyTC2V4QRScONESHZ7Yhs8C6YgTgMdtNGyozqHreLB4ptP2HdII" "a7Nv2jIZUozyjkED+G0OEisA==", ) def test_sign_versions(self): signer = Signer(APP_UUID, self.private_key, "v1, V2,v777") self.assertEqual(signer.sign_versions, ["v1", "v2", "v777"]) def test_sign_versions_bad_version(self): with self.assertRaises(ValueError) as exc: Signer(APP_UUID, self.private_key, "v1,vv2") self.assertEqual( str(exc.exception), "SIGN_VERSIONS must be comma-separated MAuth protocol versions (e.g. 'v1,v2')" )