Example #1
0
    def test_broken_contenttype(self):
        """
        Crossbar rejects broken content-types.
        """
        session = MockPublisherSession(self)
        resource = PublisherResource({}, session)

        with LogCapturer("debug") as l:
            request = self.successResultOf(renderResource(
                resource, b"/", method=b"POST",
                headers={b"Content-Type": [b"application/json;charset=blarg;charset=boo"]},
                body=b'{"foo": "\xe2\x98\x83"}'))

        errors = l.get_category("AR450")
        self.assertEqual(len(errors), 1)
        self.assertEqual(errors[0]["code"], 400)

        del l

        with LogCapturer("debug") as l:
            request = self.successResultOf(renderResource(
                resource, b"/", method=b"POST",
                headers={b"Content-Type": [b"charset=blarg;application/json"]},
                body=b'{"foo": "\xe2\x98\x83"}'))

        self.assertEqual(request.code, 400)

        errors = l.get_category("AR452")
        self.assertEqual(len(errors), 1)
        self.assertEqual(errors[0]["code"], 400)
Example #2
0
    def test_broken_contenttype(self):
        """
        Crossbar rejects broken content-types.
        """
        session = MockPublisherSession(self)
        resource = PublisherResource({}, session)

        with LogCapturer("debug") as l:
            request = self.successResultOf(renderResource(
                resource, b"/", method=b"POST",
                headers={b"Content-Type": [b"application/json;charset=blarg;charset=boo"]},
                body=b'{"foo": "\xe2\x98\x83"}'))

        errors = l.get_category("AR450")
        self.assertEqual(len(errors), 1)
        self.assertEqual(errors[0]["code"], 400)

        del l

        with LogCapturer("debug") as l:
            request = self.successResultOf(renderResource(
                resource, b"/", method=b"POST",
                headers={b"Content-Type": [b"charset=blarg;application/json"]},
                body=b'{"foo": "\xe2\x98\x83"}'))

        self.assertEqual(request.code, 400)

        errors = l.get_category("AR452")
        self.assertEqual(len(errors), 1)
        self.assertEqual(errors[0]["code"], 400)
Example #3
0
    def test_basic_publish(self):
        """
        Test a very basic publish to a topic.
        """
        session = MockPublisherSession(self)
        resource = PublisherResource({}, session)

        with LogCapturer() as l:
            request = yield renderResource(
                resource,
                b"/",
                method=b"POST",
                headers={b"Content-Type": [b"application/json"]},
                body=b'{"topic": "com.test.messages", "args": [1]}')

        self.assertEqual(len(session._published_messages), 1)
        self.assertEqual(session._published_messages[0]["args"], (1, ))

        self.assertEqual(request.code, 200)

        logs = l.get_category("AR200")
        self.assertEqual(len(logs), 1)
        self.assertEqual(logs[0]["code"], 200)

        self.assertEqual(json.loads(native_string(request.get_written_data())),
                         {"id": session._published_messages[0]["id"]})
        # ensure we have all the format-keys AR200 asks for (can we
        # extract these from the _log_categories string instead?)
        self.assertIn('code', logs[0])
        self.assertIn('reason', logs[0])
Example #4
0
    def test_cb_failure(self):
        """
        Test that calls with no procedure in the request body are rejected.
        """
        resource = CallerResource({}, None)

        with LogCapturer() as l:
            request = yield renderResource(
                resource,
                b"/",
                method=b"POST",
                headers={b"Content-Type": [b"application/json"]},
                body=b'{"procedure": "foo"}')

        self.assertEqual(request.code, 500)
        self.assertEqual(
            json.loads(native_string(request.get_written_data())), {
                "error": "wamp.error.runtime_error",
                "args": ["Sorry, Crossbar.io has encountered a problem."],
                "kwargs": {}
            })

        errors = l.get_category("AR500")
        self.assertEqual(len(errors), 1)

        # We manually logged the errors; we can flush them from the log
        self.flushLoggedErrors()
Example #5
0
    def test_github_signature_fail(self):
        """
        Error if we're to check github signatures, but they're missing entirely
        """
        session = MockPublisherSession(self)
        resource = WebhookResource(
            options={
                u"topic": u"com.test.webhook",
                u"github_secret": u"deadbeef",
            },
            session=session,
        )

        request = yield renderResource(
            resource, b"/",
            method=b"POST",
            headers={b"Content-Type": []},
            body=b'{"foo": "has happened"}')

        self.assertEqual(len(session._published_messages), 0)
        self.assertEqual(request.code, 400)
        received_json = json.loads(request.get_written_data().decode('utf8'))
        self.assertEqual(
            received_json,
            {
                "error": "Malformed request to the REST bridge.",
                "args": [],
                "kwargs": {}
            }
        )
Example #6
0
    def test_github_signature_valid(self):
        """
        A correctly-formatted GitHub signature
        """
        session = MockPublisherSession(self)
        resource = WebhookResource(
            options={
                u"topic": u"com.test.webhook",
                u"github_secret": github_test_token,
            },
            session=session,
        )

        yield renderResource(
            resource, b"/webhook",
            method=b"POST",
            headers={
                b"Content-Type": [],
                b"X-Hub-Signature": [b"sha1=5054d1d2e6f5d293fbea8fdeed5117f2854ccf7a"],
            },
            body=github_request_data,
        )

        self.assertEqual(len(session._published_messages), 1)
        msg = session._published_messages[0]
        data = msg['args'][0]
        self.assertEqual(
            data['body'].encode('utf8'),
            github_request_data.strip(),
        )
Example #7
0
    def test_basic(self):
        """
        A message, when a request has gone through to it, publishes a WAMP
        message on the configured topic.
        """
        session = MockPublisherSession(self)
        resource = WebhookResource({u"topic": u"com.test.webhook"}, session)

        with LogCapturer() as l:
            request = yield renderResource(
                resource, b"/",
                method=b"POST",
                headers={b"Content-Type": []},
                body=b'{"foo": "has happened"}')

        self.assertEqual(len(session._published_messages), 1)
        self.assertEqual(
            {
                u"body": u'{"foo": "has happened"}',
                u"headers": {
                    u"Content-Type": [],
                    u'Date': [u'Sun, 1 Jan 2013 15:21:01 GMT'],
                    u'Host': [u'localhost:8000']
                }
            },
            session._published_messages[0]["args"][0])

        self.assertEqual(request.code, 202)
        self.assertEqual(request.get_written_data(), b"OK")

        logs = l.get_category("AR201")
        self.assertEqual(len(logs), 1)
        self.assertEqual(logs[0]["code"], 202)
Example #8
0
    def test_publish_error(self):
        """
        A publish that errors will return the error to the client.
        """
        class RejectingPublisherSession(object):
            """
            A mock WAMP session.
            """
            def publish(self, topic, *args, **kwargs):
                return maybeDeferred(self._publish, topic, *args, **kwargs)

            def _publish(self, topic, *args, **kwargs):
                raise ApplicationError(u'wamp.error.not_authorized', foo="bar")

        session = RejectingPublisherSession()
        resource = PublisherResource({}, session)

        with LogCapturer() as l:
            request = yield renderResource(
                resource, b"/",
                method=b"POST",
                headers={b"Content-Type": [b"application/json"]},
                body=b'{"topic": "com.test.messages", "args": [1]}')

        self.assertEqual(request.code, 200)

        logs = l.get_category("AR456")
        self.assertEqual(len(logs), 1)
        self.assertEqual(logs[0]["code"], 200)

        self.assertEqual(json.loads(native_string(request.get_written_data())),
                         {"error": "wamp.error.not_authorized",
                          "args": [], "kwargs": {"foo": "bar"}})
Example #9
0
    def test_github_signature_valid(self):
        """
        A correctly-formatted GitHub signature
        """
        session = MockPublisherSession(self)
        resource = WebhookResource(
            options={
                u"topic": u"com.test.webhook",
                u"github_secret": github_test_token,
            },
            session=session,
        )

        yield renderResource(
            resource, b"/webhook",
            method=b"POST",
            headers={
                b"Content-Type": [],
                b"X-Hub-Signature": [b"sha1=5054d1d2e6f5d293fbea8fdeed5117f2854ccf7a"],
            },
            body=github_request_data,
        )

        self.assertEqual(len(session._published_messages), 1)
        msg = session._published_messages[0]
        data = msg['args'][0]
        self.assertEqual(
            data['body'].encode('utf8'),
            github_request_data.strip(),
        )
Example #10
0
    def test_basic(self):
        """
        A message, when a request has gone through to it, publishes a WAMP
        message on the configured topic.
        """
        session = MockPublisherSession(self)
        resource = WebhookResource({u"topic": u"com.test.webhook"}, session)

        with LogCapturer() as l:
            request = yield renderResource(
                resource, b"/",
                method=b"POST",
                headers={b"Content-Type": []},
                body=b'{"foo": "has happened"}')

        self.assertEqual(len(session._published_messages), 1)
        self.assertEqual(
            {
                u"body": u'{"foo": "has happened"}',
                u"headers": {
                    u"Content-Type": [],
                    u'Date': [u'Sun, 1 Jan 2013 15:21:01 GMT'],
                    u'Host': [u'localhost:8000']
                }
            },
            session._published_messages[0]["args"][0])

        self.assertEqual(request.code, 202)
        self.assertEqual(request.get_written_data(), b"OK")

        logs = l.get_category("AR201")
        self.assertEqual(len(logs), 1)
        self.assertEqual(logs[0]["code"], 202)
Example #11
0
    def test_publish_needs_topic(self):
        """
        Test that attempted publishes without a topic will be rejected.
        """
        session = MockPublisherSession(self)
        resource = PublisherResource({}, session)

        with LogCapturer() as l:
            request = yield renderResource(
                resource,
                b"/",
                method=b"POST",
                headers={b"Content-Type": [b"application/json"]},
                body=b'{}')

        self.assertEqual(len(session._published_messages), 0)

        self.assertEqual(request.code, 400)
        errors = l.get_category("AR455")
        self.assertEqual(len(errors), 1)
        self.assertEqual(errors[0]["code"], 400)

        self.assertEqual(
            json.loads(native_string(request.get_written_data())), {
                "error": log_categories["AR455"].format(key="topic"),
                "args": [],
                "kwargs": {}
            })
Example #12
0
    def test_basic_publish(self):
        """
        Test a very basic publish to a topic.
        """
        session = MockPublisherSession(self)
        resource = PublisherResource({}, session)

        with LogCapturer() as l:
            request = yield renderResource(
                resource, b"/",
                method=b"POST",
                headers={b"Content-Type": [b"application/json"]},
                body=b'{"topic": "com.test.messages", "args": [1]}')

        self.assertEqual(len(session._published_messages), 1)
        self.assertEqual(session._published_messages[0]["args"], (1,))

        self.assertEqual(request.code, 200)

        logs = l.get_category("AR200")
        self.assertEqual(len(logs), 1)
        self.assertEqual(logs[0]["code"], 200)

        self.assertEqual(json.loads(native_string(request.get_written_data())),
                         {"id": session._published_messages[0]["id"]})
        # ensure we have all the format-keys AR200 asks for (can we
        # extract these from the _log_categories string instead?)
        self.assertIn('code', logs[0])
        self.assertIn('reason', logs[0])
Example #13
0
    def test_add2(self):
        """
        Test a very basic call where you square root a number. This has one
        arg, no kwargs, and no authorisation.
        """
        session = TestSession(types.ComponentConfig(u'realm1'))
        self.session_factory.add(session, authrole=u"test_role")

        session2 = ApplicationSession(types.ComponentConfig(u'realm1'))
        self.session_factory.add(session2, authrole=u"test_role")
        resource = CallerResource({}, session2)

        with LogCapturer() as l:
            request = yield renderResource(
                resource, b"/",
                method=b"POST",
                headers={b"Content-Type": [b"application/json"]},
                body=b'{"procedure": "com.myapp.sqrt", "args": [2]}')

        self.assertEqual(request.code, 200)
        self.assertEqual(json.loads(native_string(request.get_written_data())),
                         {"args": [1.4142135623730951]})

        logs = l.get_category("AR202")
        self.assertEqual(len(logs), 1)
        self.assertEqual(logs[0]["code"], 200)
Example #14
0
    def test_undecodable_UTF8(self):
        """
        Undecodable UTF-8 will return an error.
        """
        session = MockPublisherSession(self)
        resource = PublisherResource({}, session)

        with LogCapturer("debug") as l:
            request = self.successResultOf(
                renderResource(
                    resource,
                    b"/",
                    method=b"POST",
                    headers={
                        b"Content-Type": [b"application/json;charset=utf-8"]
                    },
                    body=
                    b'{"topic": "com.test.messages", "args": ["\x61\x62\x63\xe9"]}'
                ))

        self.assertEqual(request.code, 400)

        errors = l.get_category("AR451")
        self.assertEqual(len(errors), 1)
        self.assertEqual(errors[0]["code"], 400)
Example #15
0
    def test_github_signature_fail(self):
        """
        Error if we're to check github signatures, but they're missing entirely
        """
        session = MockPublisherSession(self)
        resource = WebhookResource(
            options={
                u"topic": u"com.test.webhook",
                u"github_secret": u"deadbeef",
            },
            session=session,
        )

        request = yield renderResource(
            resource, b"/",
            method=b"POST",
            headers={b"Content-Type": []},
            body=b'{"foo": "has happened"}')

        self.assertEqual(len(session._published_messages), 0)
        self.assertEqual(request.code, 400)
        received_json = json.loads(request.get_written_data().decode('utf8'))
        self.assertEqual(
            received_json,
            {
                "error": "Malformed request to the REST bridge.",
                "args": [],
                "kwargs": {}
            }
        )
Example #16
0
    def test_github_signature_invalid(self):
        """
        A correctly-formatted GitHub signature, but it's invalid
        """
        session = MockPublisherSession(self)
        resource = WebhookResource(
            options={
                "topic": "com.test.webhook",
                "github_secret": "deadbeef",
            },
            session=session,
        )

        request = yield renderResource(resource,
                                       b"/",
                                       method=b"POST",
                                       headers={b"Content-Type": []},
                                       body=b'{"foo": "has happened"}')

        self.assertEqual(len(session._published_messages), 0)
        self.assertEqual(request.code, 400)
        received_json = json.loads(request.get_written_data().decode('utf8'))
        self.assertEqual(received_json, {
            "error": "Malformed request to the REST bridge.",
            "args": [],
            "kwargs": {},
        })
Example #17
0
    def test_add2(self):
        """
        Test a very basic call where you square root a number. This has one
        arg, no kwargs, and no authorisation.
        """
        session = TestSession(types.ComponentConfig(u'realm1'))
        self.session_factory.add(session, authrole=u"test_role")

        session2 = ApplicationSession(types.ComponentConfig(u'realm1'))
        self.session_factory.add(session2, authrole=u"test_role")
        resource = CallerResource({}, session2)

        with LogCapturer() as l:
            request = yield renderResource(
                resource,
                b"/",
                method=b"POST",
                headers={b"Content-Type": [b"application/json"]},
                body=b'{"procedure": "com.myapp.sqrt", "args": [2]}')

        self.assertEqual(request.code, 200)
        self.assertEqual(json.loads(native_string(request.get_written_data())),
                         {"args": [1.4142135623730951]})

        logs = l.get_category("AR202")
        self.assertEqual(len(logs), 1)
        self.assertEqual(logs[0]["code"], 200)
Example #18
0
    def test_outdated_delta(self):
        """
        If the delta between now and the timestamp in the request is larger than
        C{timestamp_delta_limit}, the request is rejected.
        """
        custOpts = {"timestamp_delta_limit": 1}
        custOpts.update(resourceOptions)
        session = MockPublisherSession(self)
        resource = PublisherResource(custOpts, session)

        signedParams = makeSignedArguments({}, "bazapp", "foobar", publishBody)
        signedParams[b'timestamp'] = [b"2011-10-14T16:59:51.123Z"]

        with LogCapturer() as l:
            request = yield renderResource(
                resource,
                b"/",
                method=b"POST",
                headers={b"Content-Type": [b"application/json"]},
                body=publishBody,
                params=signedParams)

        self.assertEqual(request.code, 400)

        errors = l.get_category("AR464")
        self.assertEqual(len(errors), 1)
        self.assertEqual(errors[0]["code"], 400)
Example #19
0
    def test_required_tls_with_tls(self):
        """
        Required TLS, plus a request over TLS, will allow the request.
        """
        session = MockPublisherSession(self)
        resource = PublisherResource({"require_tls": True}, session)

        request = self.successResultOf(renderResource(
            resource, b"/", method=b"POST",
            headers={b"Content-Type": [b"application/json"]},
            body=publishBody, isSecure=True))

        self.assertEqual(request.code, 200)
Example #20
0
    def test_allowed_IP_range(self):
        """
        The client having an IP in an allowed address range allows the request.
        """
        session = MockPublisherSession(self)
        resource = PublisherResource({"require_ip": ["127.0.0.0/8"]}, session)

        request = self.successResultOf(renderResource(
            resource, b"/", method=b"POST",
            headers={b"Content-Type": [b"application/json"]},
            body=publishBody))

        self.assertEqual(request.code, 200)
Example #21
0
    def test_allowed_IP_range(self):
        """
        The client having an IP in an allowed address range allows the request.
        """
        session = MockPublisherSession(self)
        resource = PublisherResource({"require_ip": ["127.0.0.0/8"]}, session)

        request = self.successResultOf(renderResource(
            resource, b"/", method=b"POST",
            headers={b"Content-Type": [b"application/json"]},
            body=publishBody))

        self.assertEqual(request.code, 200)
Example #22
0
    def test_required_tls_with_tls(self):
        """
        Required TLS, plus a request over TLS, will allow the request.
        """
        session = MockPublisherSession(self)
        resource = PublisherResource({"require_tls": True}, session)

        request = self.successResultOf(renderResource(
            resource, b"/", method=b"POST",
            headers={b"Content-Type": [b"application/json"]},
            body=publishBody, isSecure=True))

        self.assertEqual(request.code, 200)
Example #23
0
    def test_allow_charset_in_content_type(self):
        """
        A charset in the content-type will be allowed.
        """
        session = MockPublisherSession(self)
        resource = PublisherResource({}, session)

        request = self.successResultOf(renderResource(
            resource, b"/", method=b"POST",
            headers={b"Content-Type": [b"application/json; charset=utf-8"]},
            body=publishBody))

        self.assertEqual(request.code, 200)
        self.assertIn(b'{"id":',
                      request.get_written_data())
Example #24
0
    def test_allow_caps_in_content_type(self):
        """
        Differently-capitalised content-type headers will be allowed.
        """
        session = MockPublisherSession(self)
        resource = PublisherResource({}, session)

        request = self.successResultOf(renderResource(
            resource, b"/", method=b"POST",
            headers={b"CONTENT-TYPE": [b"APPLICATION/JSON"]},
            body=publishBody))

        self.assertEqual(request.code, 200)
        self.assertIn(b'{"id":',
                      request.get_written_data())
Example #25
0
    def test_UTF8_assumption(self):
        """
        A body, when the Content-Type has no charset, is assumed to be UTF-8.
        """
        session = MockPublisherSession(self)
        resource = PublisherResource({}, session)

        request = self.successResultOf(renderResource(
            resource, b"/", method=b"POST",
            headers={b"Content-Type": [b"application/json"]},
            body=b'{"topic": "com.test.messages", "args": ["\xe2\x98\x83"]}'))

        self.assertEqual(request.code, 200)
        self.assertIn(b'{"id":',
                      request.get_written_data())
Example #26
0
    def test_disallowed_IP_range(self):
        """
        The client having an IP not in allowed address range denies the request.
        """
        session = MockPublisherSession(self)
        resource = PublisherResource({"require_ip": ["192.168.0.0/16", "10.0.0.0/8"]}, session)

        request = self.successResultOf(renderResource(
            resource, b"/", method=b"POST",
            headers={b"Content-Type": [b"application/json"]},
            body=publishBody))

        self.assertEqual(request.code, 400)
        self.assertIn(b"Request denied based on IP address",
                      request.get_written_data())
Example #27
0
    def test_disallowed_IP_range(self):
        """
        The client having an IP not in allowed address range denies the request.
        """
        session = MockPublisherSession(self)
        resource = PublisherResource({"require_ip": ["192.168.0.0/16", "10.0.0.0/8"]}, session)

        request = self.successResultOf(renderResource(
            resource, b"/", method=b"POST",
            headers={b"Content-Type": [b"application/json"]},
            body=publishBody))

        self.assertEqual(request.code, 400)
        self.assertIn(b"Request denied based on IP address",
                      request.get_written_data())
Example #28
0
    def test_allow_caps_in_content_type(self):
        """
        Differently-capitalised content-type headers will be allowed.
        """
        session = MockPublisherSession(self)
        resource = PublisherResource({}, session)

        request = self.successResultOf(renderResource(
            resource, b"/", method=b"POST",
            headers={b"CONTENT-TYPE": [b"APPLICATION/JSON"]},
            body=publishBody))

        self.assertEqual(request.code, 200)
        self.assertIn(b'{"id":',
                      request.get_written_data())
Example #29
0
    def test_UTF8_assumption(self):
        """
        A body, when the Content-Type has no charset, is assumed to be UTF-8.
        """
        session = MockPublisherSession(self)
        resource = PublisherResource({}, session)

        request = self.successResultOf(renderResource(
            resource, b"/", method=b"POST",
            headers={b"Content-Type": [b"application/json"]},
            body=b'{"topic": "com.test.messages", "args": ["\xe2\x98\x83"]}'))

        self.assertEqual(request.code, 200)
        self.assertIn(b'{"id":',
                      request.get_written_data())
Example #30
0
    def test_allow_charset_in_content_type(self):
        """
        A charset in the content-type will be allowed.
        """
        session = MockPublisherSession(self)
        resource = PublisherResource({}, session)

        request = self.successResultOf(renderResource(
            resource, b"/", method=b"POST",
            headers={b"Content-Type": [b"application/json; charset=utf-8"]},
            body=publishBody))

        self.assertEqual(request.code, 200)
        self.assertIn(b'{"id":',
                      request.get_written_data())
Example #31
0
    def test_bad_method(self):
        """
        An incorrect method will mean the request is rejected.
        """
        session = MockPublisherSession(self)
        resource = PublisherResource({}, session)

        with LogCapturer("debug") as l:
            request = self.successResultOf(renderResource(
                resource, b"/", method=b"BLBLBLB",
                headers={b"Content-Type": [b"application/json"]},
                body=publishBody))

        self.assertEqual(request.code, 405)
        errors = l.get_category("AR405")
        self.assertEqual(len(errors), 1)
        self.assertEqual(errors[0]["code"], 405)
Example #32
0
    def test_no_body(self):
        """
        Test that calls with no body are rejected.
        """
        resource = CallerResource({}, None)

        with LogCapturer() as l:
            request = yield renderResource(
                resource, b"/",
                method=b"POST",
                headers={b"Content-Type": [b"application/json"]})

        self.assertEqual(request.code, 400)

        errors = l.get_category("AR453")
        self.assertEqual(len(errors), 1)
        self.assertEqual(errors[0]["code"], 400)
Example #33
0
    def test_bad_method(self):
        """
        An incorrect method will mean the request is rejected.
        """
        session = MockPublisherSession(self)
        resource = PublisherResource({}, session)

        with LogCapturer("debug") as l:
            request = self.successResultOf(renderResource(
                resource, b"/", method=b"BLBLBLB",
                headers={b"Content-Type": [b"application/json"]},
                body=publishBody))

        self.assertEqual(request.code, 405)
        errors = l.get_category("AR405")
        self.assertEqual(len(errors), 1)
        self.assertEqual(errors[0]["code"], 405)
Example #34
0
    def test_ASCII_denied(self):
        """
        A body with an ASCII charset is denied, it must be UTF-8.
        """
        session = MockPublisherSession(self)
        resource = PublisherResource({}, session)

        with LogCapturer("debug") as l:
            request = self.successResultOf(renderResource(
                resource, b"/", method=b"POST",
                headers={b"Content-Type": [b"application/json; charset=ascii"]},
                body=b''))

        self.assertEqual(request.code, 400)

        errors = l.get_category("AR450")
        self.assertEqual(len(errors), 1)
        self.assertEqual(errors[0]["code"], 400)
Example #35
0
    def test_undecodable_UTF8(self):
        """
        Undecodable UTF-8 will return an error.
        """
        session = MockPublisherSession(self)
        resource = PublisherResource({}, session)

        with LogCapturer("debug") as l:
            request = self.successResultOf(renderResource(
                resource, b"/", method=b"POST",
                headers={b"Content-Type": [b"application/json;charset=utf-8"]},
                body=b'{"topic": "com.test.messages", "args": ["\x61\x62\x63\xe9"]}'))

        self.assertEqual(request.code, 400)

        errors = l.get_category("AR451")
        self.assertEqual(len(errors), 1)
        self.assertEqual(errors[0]["code"], 400)
Example #36
0
    def test_JSON_list_body(self):
        """
        A body that is not a JSON dict will be rejected by the server.
        """
        session = MockPublisherSession(self)
        resource = PublisherResource({}, session)

        with LogCapturer("debug") as l:
            request = self.successResultOf(renderResource(
                resource, b"/", method=b"POST",
                headers={b"Content-Type": [b"application/json"]},
                body=b"[{},{}]"))

        self.assertEqual(request.code, 400)

        errors = l.get_category("AR454")
        self.assertEqual(len(errors), 1)
        self.assertEqual(errors[0]["code"], 400)
Example #37
0
    def test_JSON_list_body(self):
        """
        A body that is not a JSON dict will be rejected by the server.
        """
        session = MockPublisherSession(self)
        resource = PublisherResource({}, session)

        with LogCapturer("debug") as l:
            request = self.successResultOf(renderResource(
                resource, b"/", method=b"POST",
                headers={b"Content-Type": [b"application/json"]},
                body=b"[{},{}]"))

        self.assertEqual(request.code, 400)

        errors = l.get_category("AR454")
        self.assertEqual(len(errors), 1)
        self.assertEqual(errors[0]["code"], 400)
Example #38
0
    def test_ASCII_denied(self):
        """
        A body with an ASCII charset is denied, it must be UTF-8.
        """
        session = MockPublisherSession(self)
        resource = PublisherResource({}, session)

        with LogCapturer("debug") as l:
            request = self.successResultOf(renderResource(
                resource, b"/", method=b"POST",
                headers={b"Content-Type": [b"application/json; charset=ascii"]},
                body=b''))

        self.assertEqual(request.code, 400)

        errors = l.get_category("AR450")
        self.assertEqual(len(errors), 1)
        self.assertEqual(errors[0]["code"], 400)
Example #39
0
    def test_too_large_body(self):
        """
        A too large body will mean the request is rejected.
        """
        session = MockPublisherSession(self)
        resource = PublisherResource({"post_body_limit": 1}, session)

        with LogCapturer("debug") as l:
            request = self.successResultOf(renderResource(
                resource, b"/", method=b"POST",
                headers={b"Content-Type": [b"application/json"]},
                body=publishBody))

        self.assertEqual(request.code, 413)

        errors = l.get_category("AR413")
        self.assertEqual(len(errors), 1)
        self.assertEqual(errors[0]["code"], 413)
Example #40
0
    def test_too_large_body(self):
        """
        A too large body will mean the request is rejected.
        """
        session = MockPublisherSession(self)
        resource = PublisherResource({"post_body_limit": 1}, session)

        with LogCapturer("debug") as l:
            request = self.successResultOf(renderResource(
                resource, b"/", method=b"POST",
                headers={b"Content-Type": [b"application/json"]},
                body=publishBody))

        self.assertEqual(request.code, 413)

        errors = l.get_category("AR413")
        self.assertEqual(len(errors), 1)
        self.assertEqual(errors[0]["code"], 413)
Example #41
0
    def test_publish_cberror(self):
        """
        A publish that errors with a Crossbar failure will return a generic
        error to the client and log the exception.
        """
        class RejectingPublisherSession(object):
            """
            A mock WAMP session.
            """
            def publish(self, topic, *args, **kwargs):
                return maybeDeferred(self._publish, topic, *args, **kwargs)

            def _publish(self, topic, *args, **kwargs):
                raise ValueError("ono")

        session = RejectingPublisherSession()
        resource = PublisherResource({}, session)

        with LogCapturer() as l:
            request = yield renderResource(
                resource,
                b"/",
                method=b"POST",
                headers={b"Content-Type": [b"application/json"]},
                body=b'{"topic": "com.test.messages", "args": [1]}')

        self.assertEqual(request.code, 500)

        logs = l.get_category("AR456")
        self.assertEqual(len(logs), 1)
        self.assertEqual(logs[0]["code"], 500)

        logs = l.get_category("AR500")
        self.assertEqual(len(logs), 1)

        self.assertEqual(
            json.loads(native_string(request.get_written_data())), {
                "error": "wamp.error.runtime_error",
                "args": ["Sorry, Crossbar.io has encountered a problem."],
                "kwargs": {}
            })

        # We manually logged it, so this one is OK
        self.flushLoggedErrors(ValueError)
Example #42
0
    def test_unknown_key(self):
        """
        An unknown key in a request should mean the request is rejected.
        """
        session = MockPublisherSession(self)
        resource = PublisherResource(resourceOptions, session)

        with LogCapturer() as l:
            request = yield renderResource(
                resource, b"/", method=b"POST",
                headers={b"Content-Type": [b"application/json"]},
                body=publishBody,
                sign=True, signKey="spamapp", signSecret="foobar")

        self.assertEqual(request.code, 401)

        errors = l.get_category("AR460")
        self.assertEqual(len(errors), 1)
        self.assertEqual(errors[0]["code"], 401)
Example #43
0
    def test_multiple_content_length(self):
        """
        Requests with multiple Content-Length headers will be rejected.
        """
        session = MockPublisherSession(self)
        resource = PublisherResource({}, session)

        with LogCapturer("debug") as l:
            request = self.successResultOf(renderResource(
                resource, b"/", method=b"POST",
                headers={b"Content-Type": [b"application/json"],
                         b"Content-Length": ["1", "10"]},
                body=publishBody))

        self.assertEqual(request.code, 400)

        errors = l.get_category("AR463")
        self.assertEqual(len(errors), 1)
        self.assertEqual(errors[0]["code"], 400)
Example #44
0
    def test_unknown_encoding(self):
        """
        A body, when the Content-Type has been set to something other than
        charset=utf-8, will error out.
        """
        session = MockPublisherSession(self)
        resource = PublisherResource({}, session)

        with LogCapturer("debug") as l:
            request = self.successResultOf(renderResource(
                resource, b"/", method=b"POST",
                headers={b"Content-Type": [b"application/json;charset=blarg"]},
                body=b'{"args": ["\x61\x62\x63\xe9"]}'))

        self.assertEqual(request.code, 400)

        errors = l.get_category("AR450")
        self.assertEqual(len(errors), 1)
        self.assertEqual(errors[0]["code"], 400)
Example #45
0
    def test_multiple_content_length(self):
        """
        Requests with multiple Content-Length headers will be rejected.
        """
        session = MockPublisherSession(self)
        resource = PublisherResource({}, session)

        with LogCapturer("debug") as l:
            request = self.successResultOf(renderResource(
                resource, b"/", method=b"POST",
                headers={b"Content-Type": [b"application/json"],
                         b"Content-Length": ["1", "10"]},
                body=publishBody))

        self.assertEqual(request.code, 400)

        errors = l.get_category("AR463")
        self.assertEqual(len(errors), 1)
        self.assertEqual(errors[0]["code"], 400)
Example #46
0
    def test_unknown_encoding(self):
        """
        A body, when the Content-Type has been set to something other than
        charset=utf-8, will error out.
        """
        session = MockPublisherSession(self)
        resource = PublisherResource({}, session)

        with LogCapturer("debug") as l:
            request = self.successResultOf(renderResource(
                resource, b"/", method=b"POST",
                headers={b"Content-Type": [b"application/json;charset=blarg"]},
                body=b'{"args": ["\x61\x62\x63\xe9"]}'))

        self.assertEqual(request.code, 400)

        errors = l.get_category("AR450")
        self.assertEqual(len(errors), 1)
        self.assertEqual(errors[0]["code"], 400)
Example #47
0
    def test_failure(self):
        """
        A failed call returns the error to the client.
        """
        session = TestSession(types.ComponentConfig(u'realm1'))
        self.session_factory.add(session, authrole=u"test_role")

        session2 = ApplicationSession(types.ComponentConfig(u'realm1'))
        self.session_factory.add(session2, authrole=u"test_role")
        resource = CallerResource({}, session2)

        tests = [
            (u"com.myapp.sqrt", (0,),
             {u"error": u"wamp.error.runtime_error", u"args": [u"don't ask foolish questions ;)"], u"kwargs": {}}),
            (u"com.myapp.checkname", ("foo",),
             {u"error": u"com.myapp.error.reserved", u"args": [], u"kwargs": {}}),
            (u"com.myapp.checkname", ("*",),
             {u"error": u"com.myapp.error.invalid_length", u"args": [], u"kwargs": {"min": 3, "max": 10}}),
            (u"com.myapp.checkname", ("hello",),
             {u"error": u"com.myapp.error.mixed_case", u"args": ["hello", "HELLO"], u"kwargs": {}}),
            (u"com.myapp.compare", (1, 10),
             {u"error": u"com.myapp.error1", u"args": [9], u"kwargs": {}}),
        ]

        for procedure, args, err in tests:
            with LogCapturer() as l:
                request = yield renderResource(
                    resource, b"/",
                    method=b"POST",
                    headers={b"Content-Type": [b"application/json"]},
                    body=dump_json({"procedure": procedure, "args": args}).encode('utf8'))

            self.assertEqual(request.code, 200)
            self.assertEqual(json.loads(native_string(request.get_written_data())),
                             err)

            logs = l.get_category("AR458")
            self.assertEqual(len(logs), 1)
            self.assertEqual(logs[0]["code"], 200)

        # We manually logged the errors; we can flush them from the log
        self.flushLoggedErrors()
Example #48
0
    def test_not_matching_bodylength(self):
        """
        A body length that is different than the Content-Length header will mean
        the request is rejected.
        """
        session = MockPublisherSession(self)
        resource = PublisherResource({"post_body_limit": 1}, session)

        with LogCapturer("debug") as l:
            request = self.successResultOf(renderResource(
                resource, b"/", method=b"POST",
                headers={b"Content-Type": [b"application/json"],
                         b"Content-Length": [1]},
                body=publishBody))

        self.assertEqual(request.code, 400)

        errors = l.get_category("AR465")
        self.assertEqual(len(errors), 1)
        self.assertEqual(errors[0]["code"], 400)
Example #49
0
    def test_good_signature(self):
        """
        A valid, correct signature will mean the request is processed.
        """
        session = MockPublisherSession(self)
        resource = PublisherResource(resourceOptions, session)

        with LogCapturer() as l:
            request = yield renderResource(
                resource, b"/", method=b"POST",
                headers={b"Content-Type": [b"application/json"]},
                body=publishBody,
                sign=True, signKey="bazapp", signSecret="foobar")

        self.assertEqual(request.code, 200)
        self.assertEqual(json.loads(native_string(request.get_written_data())),
                         {"id": session._published_messages[0]["id"]})

        logs = l.get_category("AR203")
        self.assertEqual(len(logs), 1)
Example #50
0
    def test_not_matching_bodylength(self):
        """
        A body length that is different than the Content-Length header will mean
        the request is rejected.
        """
        session = MockPublisherSession(self)
        resource = PublisherResource({"post_body_limit": 1}, session)

        with LogCapturer("debug") as l:
            request = self.successResultOf(renderResource(
                resource, b"/", method=b"POST",
                headers={b"Content-Type": [b"application/json"],
                         b"Content-Length": [b"1"]},
                body=publishBody))

        self.assertEqual(request.code, 400)

        errors = l.get_category("AR465")
        self.assertEqual(len(errors), 1)
        self.assertEqual(errors[0]["code"], 400)
Example #51
0
    def test_publish_cberror(self):
        """
        A publish that errors with a Crossbar failure will return a generic
        error to the client and log the exception.
        """
        class RejectingPublisherSession(object):
            """
            A mock WAMP session.
            """
            def publish(self, topic, *args, **kwargs):
                return maybeDeferred(self._publish, topic, *args, **kwargs)

            def _publish(self, topic, *args, **kwargs):
                raise ValueError("ono")

        session = RejectingPublisherSession()
        resource = PublisherResource({}, session)

        with LogCapturer() as l:
            request = yield renderResource(
                resource, b"/",
                method=b"POST",
                headers={b"Content-Type": [b"application/json"]},
                body=b'{"topic": "com.test.messages", "args": [1]}')

        self.assertEqual(request.code, 500)

        logs = l.get_category("AR456")
        self.assertEqual(len(logs), 1)
        self.assertEqual(logs[0]["code"], 500)

        logs = l.get_category("AR500")
        self.assertEqual(len(logs), 1)

        self.assertEqual(json.loads(native_string(request.get_written_data())),
                         {"error": "wamp.error.runtime_error",
                          "args": ["Sorry, Crossbar.io has encountered a problem."],
                          "kwargs": {}})

        # We manually logged it, so this one is OK
        self.flushLoggedErrors(ValueError)
Example #52
0
    def test_wrong_seq(self):
        """
        A missing sequence in a request should mean the request is rejected.
        """
        session = MockPublisherSession(self)
        resource = PublisherResource(resourceOptions, session)

        signedParams = makeSignedArguments({}, "bazapp", "foobar", publishBody)
        signedParams[b'seq'] = [b"notaseq"]

        with LogCapturer() as l:
            request = yield renderResource(
                resource, b"/", method=b"POST",
                headers={b"Content-Type": [b"application/json"]},
                body=publishBody, params=signedParams)

        self.assertEqual(request.code, 400)

        errors = l.get_category("AR462")
        self.assertEqual(len(errors), 1)
        self.assertEqual(errors[0]["code"], 400)
Example #53
0
    def test_incorrect_secret(self):
        """
        An incorrect secret (but an otherwise well-formed signature) will mean
        the request is rejected.
        """
        session = MockPublisherSession(self)
        resource = PublisherResource(resourceOptions, session)

        with LogCapturer() as l:
            request = yield renderResource(
                resource, b"/",
                method=b"POST",
                headers={b"Content-Type": [b"application/json"]},
                body=publishBody,
                sign=True, signKey="bazapp", signSecret="foobar2")

        self.assertEqual(request.code, 401)

        errors = l.get_category("AR459")
        self.assertEqual(len(errors), 1)
        self.assertEqual(errors[0]["code"], 401)
Example #54
0
    def test_cb_failure(self):
        """
        Test that calls with no procedure in the request body are rejected.
        """
        resource = CallerResource({}, None)

        with LogCapturer() as l:
            request = yield renderResource(
                resource, b"/",
                method=b"POST",
                headers={b"Content-Type": [b"application/json"]},
                body=b'{"procedure": "foo"}')

        self.assertEqual(request.code, 500)
        self.assertEqual(json.loads(native_string(request.get_written_data())),
                         {"error": "wamp.error.runtime_error", "args": ["Sorry, Crossbar.io has encountered a problem."], "kwargs": {}})

        errors = l.get_category("AR500")
        self.assertEqual(len(errors), 1)

        # We manually logged the errors; we can flush them from the log
        self.flushLoggedErrors()
Example #55
0
    def test_publish_needs_topic(self):
        """
        Test that attempted publishes without a topic will be rejected.
        """
        session = MockPublisherSession(self)
        resource = PublisherResource({}, session)

        with LogCapturer() as l:
            request = yield renderResource(
                resource, b"/",
                method=b"POST",
                headers={b"Content-Type": [b"application/json"]},
                body=b'{}')

        self.assertEqual(len(session._published_messages), 0)

        self.assertEqual(request.code, 400)
        errors = l.get_category("AR455")
        self.assertEqual(len(errors), 1)
        self.assertEqual(errors[0]["code"], 400)

        self.assertEqual(json.loads(native_string(request.get_written_data())),
                         {"error": log_categories["AR455"].format(key="topic"),
                          "args": [], "kwargs": {}})