Esempio n. 1
0
    def setUp(self):
        super(RelayPublicKeysConfigTest, self).setUp()

        self.key_pair = generate_key_pair()

        self.public_key = self.key_pair[1]
        self.private_key = self.key_pair[0]

        self.non_existing_key = six.text_type(uuid4())

        self.internal_relay = Relay.objects.create(
            relay_id=six.text_type(uuid4()),
            public_key=six.binary_type(self.public_key),
            is_internal=True,
        )

        self.external_relay = Relay.objects.create(
            relay_id=six.text_type(uuid4()),
            public_key=six.binary_type(self.public_key),
            is_internal=False,
        )
        self.relay_a = Relay.objects.create(
            relay_id=six.text_type(uuid4()),
            public_key=six.binary_type(self.public_key),
            is_internal=False,
        )
        self.relay_b = Relay.objects.create(
            relay_id=six.text_type(uuid4()),
            public_key=six.binary_type(self.public_key),
            is_internal=True,
        )

        self.project = self.create_project()
        self.path = reverse("sentry-api-0-relay-publickeys")
Esempio n. 2
0
    def test_multiple_relay_versions_tracked(self):
        """
        Test that updating the relay version would properly be
        reflected in the relay analytics. Also that tests that
        multiple relays
        """
        key_pair = generate_key_pair()
        relay_id = str(uuid4())
        before_registration = timezone.now()
        self.register_relay(key_pair, "1.1.1", relay_id)
        after_first_relay = timezone.now()
        self.register_relay(key_pair, "2.2.2", relay_id)
        after_second_relay = timezone.now()

        v1 = Relay.objects.get(relay_id=relay_id)
        assert v1 is not None

        rv1 = RelayUsage.objects.get(relay_id=relay_id, version="1.1.1")
        assert rv1 is not None
        rv2 = RelayUsage.objects.get(relay_id=relay_id, version="2.2.2")
        assert rv2 is not None

        assert rv1.first_seen > before_registration
        assert rv1.last_seen > before_registration
        assert rv1.first_seen < after_first_relay
        assert rv1.last_seen < after_first_relay

        assert rv2.first_seen > after_first_relay
        assert rv2.last_seen > after_first_relay
        assert rv2.first_seen < after_second_relay
        assert rv2.last_seen < after_second_relay
Esempio n. 3
0
def test_registered_relay(internal):
    sk, pk = generate_key_pair()
    relay_id = str(uuid.uuid4())

    data = {"some_data": "hello"}
    packed, signature = sk.pack(data)
    request = RequestFactory().post("/", data=packed, content_type="application/json")
    request.META["HTTP_X_SENTRY_RELAY_SIGNATURE"] = signature
    request.META["HTTP_X_SENTRY_RELAY_ID"] = relay_id
    request.META["REMOTE_ADDR"] = "200.200.200.200"  # something that is NOT local network

    Relay.objects.create(relay_id=relay_id, public_key=str(pk))
    if internal:
        white_listed_pk = [str(pk)]  # mark the relay as internal
    else:
        white_listed_pk = []

    authenticator = RelayAuthentication()
    with override_settings(SENTRY_RELAY_WHITELIST_PK=white_listed_pk):
        authenticator.authenticate(request)

    # now the request should contain a relay
    relay = request.relay
    assert relay.is_internal == internal
    assert relay.public_key == str(pk)
    # data should be deserialized in request.relay_request_data
    assert request.relay_request_data == data
Esempio n. 4
0
def test_basic_key_functions():
    sk, pk = sentry_relay.generate_key_pair()
    signature = sk.sign(b"some secret data")
    assert pk.verify(b"some secret data", signature)
    assert not pk.verify(b"some other data", signature)

    packed, signature = sk.pack({"foo": "bar"})
    pk.unpack(packed, signature)
    with pytest.raises(sentry_relay.UnpackErrorBadSignature):
        pk.unpack(b"haha", signature)
Esempio n. 5
0
    def setUp(self):
        super().setUp()

        self.key_pair = generate_key_pair()

        self.public_key = self.key_pair[1]
        settings.SENTRY_RELAY_WHITELIST_PK.append(str(self.public_key))

        self.private_key = self.key_pair[0]
        self.relay_id = str(uuid4())

        self.path = reverse("sentry-api-0-relay-register-challenge")
Esempio n. 6
0
    def setUp(self):
        super(RelayRegisterTest, self).setUp()

        self.key_pair = generate_key_pair()

        self.public_key = self.key_pair[1]
        settings.SENTRY_RELAY_WHITELIST_PK.append(
            six.binary_type(self.public_key))

        self.private_key = self.key_pair[0]
        self.relay_id = six.binary_type(six.text_type(uuid4()).encode("ascii"))

        self.path = reverse("sentry-api-0-relay-register-challenge")
Esempio n. 7
0
    def test_no_db_for_static_relays(self):
        """
        Tests that statically authenticated relays do not access
        the database during registration
        """
        key_pair = generate_key_pair()
        relay_id = str(uuid4())
        public_key = key_pair[1]
        static_auth = {relay_id: {"internal": True, "public_key": str(public_key)}}

        with self.assertNumQueries(0):
            with self.settings(SENTRY_OPTIONS={"relay.static_auth": static_auth}):
                self.register_relay(key_pair, "1.1.1", relay_id)
Esempio n. 8
0
    def test_forge_public_key(self):
        data = {
            "public_key": six.binary_type(self.public_key),
            "relay_id": self.relay_id
        }

        raw_json, signature = self.private_key.pack(data)

        resp = self.client.post(
            self.path,
            data=raw_json,
            content_type="application/json",
            HTTP_X_SENTRY_RELAY_ID=self.relay_id,
            HTTP_X_SENTRY_RELAY_SIGNATURE=signature,
        )

        assert resp.status_code == 200, resp.content
        result = json.loads(resp.content)

        raw_json, signature = self.private_key.pack(result)

        self.client.post(
            reverse("sentry-api-0-relay-register-response"),
            data=raw_json,
            content_type="application/json",
            HTTP_X_SENTRY_RELAY_ID=self.relay_id,
            HTTP_X_SENTRY_RELAY_SIGNATURE=signature,
        )

        keys = generate_key_pair()

        settings.SENTRY_RELAY_WHITELIST_PK.append(six.binary_type(keys[1]))

        data = {
            "public_key": six.binary_type(keys[1]),
            "relay_id": self.relay_id
        }

        raw_json, signature = keys[0].pack(data)

        resp = self.client.post(
            self.path,
            data=raw_json,
            content_type="application/json",
            HTTP_X_SENTRY_RELAY_ID=self.relay_id,
            HTTP_X_SENTRY_RELAY_SIGNATURE=signature,
        )

        assert resp.status_code == 400, resp.content
Esempio n. 9
0
    def test_expired_challenge(self):
        data = {
            "public_key": six.binary_type(self.public_key),
            "relay_id": self.relay_id
        }

        raw_json, signature = self.private_key.pack(data)

        resp = self.client.post(
            self.path,
            data=raw_json,
            content_type="application/json",
            HTTP_X_SENTRY_RELAY_ID=self.relay_id,
            HTTP_X_SENTRY_RELAY_SIGNATURE=signature,
        )

        assert resp.status_code == 200, resp.content
        result = json.loads(resp.content)

        raw_json, signature = self.private_key.pack(result)

        self.client.post(
            reverse("sentry-api-0-relay-register-response"),
            data=raw_json,
            content_type="application/json",
            HTTP_X_SENTRY_RELAY_ID=self.relay_id,
            HTTP_X_SENTRY_RELAY_SIGNATURE=signature,
        )

        keys = generate_key_pair()

        data = {
            "token": six.binary_type(result.get("token")),
            "relay_id": self.relay_id
        }

        raw_json, signature = keys[0].pack(data)

        resp = self.client.post(
            reverse("sentry-api-0-relay-register-response"),
            data=raw_json,
            content_type="application/json",
            HTTP_X_SENTRY_RELAY_ID=self.relay_id,
            HTTP_X_SENTRY_RELAY_SIGNATURE=signature,
        )

        assert resp.status_code == 401, resp.content
Esempio n. 10
0
def test_statically_configured_relay(settings, internal):
    sk, pk = generate_key_pair()
    relay_id = str(uuid.uuid4())

    data = {"some_data": "hello"}
    packed, signature = sk.pack(data)
    request = RequestFactory().post("/", data=packed, content_type="application/json")
    request.META["HTTP_X_SENTRY_RELAY_SIGNATURE"] = signature
    request.META["HTTP_X_SENTRY_RELAY_ID"] = relay_id
    request.META["REMOTE_ADDR"] = "200.200.200.200"  # something that is NOT local network

    relay_options = {relay_id: {"internal": internal, "public_key": str(pk)}}

    settings.SENTRY_OPTIONS["relay.static_auth"] = relay_options
    authenticator = RelayAuthentication()
    authenticator.authenticate(request)

    # now the request should contain a relay
    relay = request.relay
    assert relay.is_internal == internal
    assert relay.public_key == str(pk)
    # data should be deserialized in request.relay_request_data
    assert request.relay_request_data == data
Esempio n. 11
0
    def test_relay_usage_is_updated_at_registration(self):
        """
        Tests that during registration the proper relay usage information
        is updated
        """

        key_pair = generate_key_pair()
        relay_id = str(uuid4())
        before_registration = timezone.now()
        # register one relay
        self.register_relay(key_pair, "1.1.1", relay_id)
        after_first_relay = timezone.now()
        # register another one that should not be updated after this
        self.register_relay(key_pair, "2.2.2", relay_id)
        after_second_relay = timezone.now()
        # re register the first one in order to update the last used time
        self.register_relay(key_pair, "1.1.1", relay_id)
        after_re_register = timezone.now()

        rv1 = RelayUsage.objects.get(relay_id=relay_id, version="1.1.1")
        assert rv1 is not None
        rv2 = RelayUsage.objects.get(relay_id=relay_id, version="2.2.2")
        assert rv2 is not None

        # check first seen is not modified by re register
        assert rv1.first_seen > before_registration
        assert rv1.first_seen < after_first_relay
        # check last seen shows the time at re-registration
        assert rv1.last_seen > after_second_relay
        assert rv1.last_seen < after_re_register

        # check version 2.2.2 is not affected by version 1.1.1
        assert rv2.first_seen > after_first_relay
        assert rv2.last_seen > after_first_relay
        assert rv2.first_seen < after_second_relay
        assert rv2.last_seen < after_second_relay
Esempio n. 12
0
def test_basic_key_functions():
    sk, pk = sentry_relay.generate_key_pair()
    signature = sk.sign(b"some secret data")
    assert pk.verify(b"some secret data", signature)
    assert not pk.verify(b"some other data", signature)
Esempio n. 13
0
def test_public_keys(mini_sentry, relay, caller, relays_to_fetch):
    """
    Tests the public key endpoint with dynamic and statically configured relays

    Create 2 normal relays r1 & r2 ( that will register normally to upstream)
    Create the configuration for 2 static relays sr1,sr2 (and add this config to r1)

    Send to r1 various requests for r2,sr1,sr2 from various relays (r2,sr1,sr2)
    """

    # create info for 2 statically configured relay
    sk1, pk1 = generate_key_pair()
    id1 = str(uuid.uuid4())
    sk2, pk2 = generate_key_pair()
    id2 = str(uuid.uuid4())

    # create configuration containing the static relays
    relays_conf = {
        id1: {
            "public_key": str(pk1),
            "internal": True
        },
        id2: {
            "public_key": str(pk2),
            "internal": False
        },
    }

    # create 2 normal relays
    relay1 = relay(mini_sentry,
                   wait_healthcheck=True,
                   static_relays=relays_conf)
    relay2 = relay(mini_sentry,
                   wait_healthcheck=True,
                   static_relays=relays_conf)

    # create info for our test parameters
    r1 = RelayInfo(
        id=relay1.relay_id,
        public_key=PublicKey.parse(relay1.public_key),
        secret_key=SecretKey.parse(relay1.secret_key),
        internal=True,
    )
    r2 = RelayInfo(
        id=relay2.relay_id,
        public_key=PublicKey.parse(relay2.public_key),
        secret_key=SecretKey.parse(relay2.secret_key),
        internal=True,
    )
    sr1 = RelayInfo(id=id1, public_key=pk1, secret_key=sk1, internal=True)
    sr2 = RelayInfo(id=id2, public_key=pk2, secret_key=sk2, internal=False)

    test_info = {"r1": r1, "r2": r2, "sr1": sr1, "sr2": sr2}

    caller = test_info[caller]

    relays_to_fetch = [test_info[r] for r in relays_to_fetch]

    request = {"relay_ids": [relay_info.id for relay_info in relays_to_fetch]}

    packed, signature = caller.secret_key.pack(request)

    resp = relay1.post(
        "/api/0/relays/publickeys/",
        data=packed,
        headers={
            "X-Sentry-Relay-Id": caller.id,
            "X-Sentry-Relay-Signature": signature
        },
    )
    assert resp.ok

    expected = {
        "relays": {
            ri.id: {
                "publicKey": str(ri.public_key),
                "internal": ri.internal
            }
            for ri in relays_to_fetch
        }
    }
    assert resp.json() == expected
Esempio n. 14
0
def test_dynamic_relays(mini_sentry, relay, caller, projects):
    sk1, pk1 = generate_key_pair()
    id1 = str(uuid.uuid4())
    sk2, pk2 = generate_key_pair()
    id2 = str(uuid.uuid4())

    # create configuration containing the static relays
    relays_conf = {
        id1: {"public_key": str(pk1), "internal": True},
        id2: {"public_key": str(pk2), "internal": False},
    }

    relay1 = relay(mini_sentry, wait_healthcheck=True, static_relays=relays_conf)
    relay2 = relay(
        mini_sentry, wait_healthcheck=True, external=True, static_relays=relays_conf,
    )

    # create info for our test parameters
    r1 = RelayInfo(
        id=relay1.relay_id,
        public_key=PublicKey.parse(relay1.public_key),
        secret_key=SecretKey.parse(relay1.secret_key),
        internal=True,
    )
    r2 = RelayInfo(
        id=relay2.relay_id,
        public_key=PublicKey.parse(relay2.public_key),
        secret_key=SecretKey.parse(relay2.secret_key),
        internal=True,
    )
    sr1 = RelayInfo(id=id1, public_key=pk1, secret_key=sk1, internal=True)
    sr2 = RelayInfo(id=id2, public_key=pk2, secret_key=sk2, internal=False)

    # add a project config for each relay key
    p1 = mini_sentry.add_basic_project_config(1)
    p2 = mini_sentry.add_basic_project_config(2)
    # add r2 to p2 since it is external
    p2["config"]["trustedRelays"].append(str(r2.public_key))
    p3 = mini_sentry.add_basic_project_config(3)
    p4 = mini_sentry.add_basic_project_config(4)
    # add sr2 to p4 (since it is external)
    p4["config"]["trustedRelays"].append(str(sr2.public_key))

    test_info = {"r1": r1, "r2": r2, "sr1": sr1, "sr2": sr2}

    proj_info = {
        "p1": p1,
        "p2": p2,
        "p3": p3,
        "p4": p4,
    }

    caller = test_info[caller]
    projects = [proj_info[proj] for proj in projects]

    public_keys = [str(p["publicKeys"][0]["publicKey"]) for p in projects]

    request = {"publicKeys": public_keys, "fullConfig": True}

    packed, signature = caller.secret_key.pack(request)

    resp = relay1.post(
        "/api/0/relays/projectconfigs/?version=2",
        data=packed,
        headers={"X-Sentry-Relay-Id": caller.id, "X-Sentry-Relay-Signature": signature},
    )

    assert resp.ok

    # test that it returns valid data
    data = resp.json()
    for p in public_keys:
        assert data["configs"][p] is not None