Esempio n. 1
0
    def post(self, request):
        """
        Registers a Relay
        `````````````````

        Registers the relay with the sentry installation.  If a relay boots
        it will always attempt to invoke this endpoint.
        """

        try:
            json_data = json.loads(request.body)
        except ValueError:
            return Response({"detail": "No valid json body"},
                            status=status.HTTP_400_BAD_REQUEST)

        serializer = RelayRegisterResponseSerializer(data=json_data)

        if not serializer.is_valid():
            return Response(serializer.errors,
                            status=status.HTTP_400_BAD_REQUEST)

        sig = get_header_relay_signature(request)
        if not sig:
            return Response({"detail": "Missing relay signature"},
                            status=status.HTTP_400_BAD_REQUEST)

        relay_id = six.text_type(get_register_response_relay_id(request.body))
        if relay_id != get_header_relay_id(request):
            return Response(
                {"detail": "relay_id in payload did not match header"},
                status=status.HTTP_400_BAD_REQUEST,
            )

        params = default_cache.get("relay-auth:%s" % relay_id)
        if params is None:
            return Response({"detail": "Challenge expired"},
                            status=status.HTTP_401_UNAUTHORIZED)

        key = PublicKey.parse(params["public_key"])

        try:
            validate_register_response(key, request.body, sig)
        except Exception as exc:
            return Response({"detail": str(exc).splitlines()[0]},
                            status=status.HTTP_400_BAD_REQUEST)

        is_internal = is_internal_relay(request, params["public_key"])
        try:
            relay = Relay.objects.get(relay_id=relay_id)
        except Relay.DoesNotExist:
            relay = Relay.objects.create(relay_id=relay_id,
                                         public_key=params["public_key"],
                                         is_internal=is_internal)
        else:
            relay.last_seen = timezone.now()
            relay.is_internal = is_internal
            relay.save()
        default_cache.delete("relay-auth:%s" % relay_id)

        return Response(serialize({"relay_id": relay.relay_id}))
Esempio n. 2
0
    def post(self, request):
        """
        Registers a Relay
        `````````````````

        Registers the relay with the sentry installation.  If a relay boots
        it will always attempt to invoke this endpoint.
        """

        try:
            json_data = json.loads(request.body)
        except ValueError:
            return Response({"detail": "No valid json body"},
                            status=status.HTTP_400_BAD_REQUEST)

        serializer = RelayRegisterResponseSerializer(data=json_data)

        if not serializer.is_valid():
            return Response(serializer.errors,
                            status=status.HTTP_400_BAD_REQUEST)

        sig = get_header_relay_signature(request)
        if not sig:
            return Response({"detail": "Missing relay signature"},
                            status=status.HTTP_400_BAD_REQUEST)

        secret = options.get("system.secret-key")

        try:
            validated = validate_register_response(request.body, sig, secret)
        except UnpackErrorSignatureExpired:
            return Response({"detail": "Challenge expired"},
                            status=status.HTTP_401_UNAUTHORIZED)
        except Exception as exc:
            return Response({"detail": str(exc).splitlines()[0]},
                            status=status.HTTP_400_BAD_REQUEST)

        relay_id = six.text_type(validated["relay_id"])
        public_key = validated["public_key"]

        if relay_id != get_header_relay_id(request):
            return Response(
                {"detail": "relay_id in payload did not match header"},
                status=status.HTTP_400_BAD_REQUEST,
            )

        is_internal = is_internal_relay(request, public_key)
        try:
            relay = Relay.objects.get(relay_id=relay_id)
        except Relay.DoesNotExist:
            relay = Relay.objects.create(relay_id=relay_id,
                                         public_key=public_key,
                                         is_internal=is_internal)
        else:
            relay.last_seen = timezone.now()
            relay.is_internal = is_internal
            relay.save()

        return Response(serialize({"relay_id": relay.relay_id}))
Esempio n. 3
0
 def authenticate(self, request):
     relay_id = get_header_relay_id(request)
     relay_sig = get_header_relay_signature(request)
     if not relay_id:
         raise AuthenticationFailed('Invalid relay ID')
     if not relay_sig:
         raise AuthenticationFailed('Missing relay signature')
     return self.authenticate_credentials(relay_id, relay_sig, request)
Esempio n. 4
0
 def authenticate(self, request):
     relay_id = get_header_relay_id(request)
     relay_sig = get_header_relay_signature(request)
     if not relay_id:
         raise AuthenticationFailed('Invalid relay ID')
     if not relay_sig:
         raise AuthenticationFailed('Missing relay signature')
     return self.authenticate_credentials(relay_id, relay_sig, request)
Esempio n. 5
0
    def post(self, request):
        """
        Requests to Register a Relay
        ````````````````````````````

        Registers the relay with the sentry installation.  If a relay boots
        it will always attempt to invoke this endpoint.
        """
        try:
            json_data = json.loads(request.body)
        except ValueError:
            return Response({
                'detail': 'No valid json body',
            }, status=status.HTTP_400_BAD_REQUEST)

        serializer = RelayRegisterChallengeSerializer(data=json_data)

        if not serializer.is_valid():
            return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

        if not self.check_allowed_relay(request, json_data):
            return Response({
                'detail': 'Relay is not allowed to register',
            }, status=status.HTTP_401_UNAUTHORIZED)

        sig = get_header_relay_signature(request)
        if not sig:
            return Response({
                'detail': 'Missing relay signature',
            }, status=status.HTTP_400_BAD_REQUEST)

        try:
            challenge = create_register_challenge(request.body, sig)
        except Exception as exc:
            return Response({
                'detail': str(exc).splitlines()[0],
            }, status=status.HTTP_400_BAD_REQUEST)

        relay_id = six.text_type(challenge['relay_id'])
        if relay_id != get_header_relay_id(request):
            return Response({
                'detail': 'relay_id in payload did not match header',
            }, status=status.HTTP_400_BAD_REQUEST)

        try:
            relay = Relay.objects.get(relay_id=relay_id)
        except Relay.DoesNotExist:
            pass
        else:
            if relay.public_key != six.text_type(challenge['public_key']):
                # This happens if we have an ID collision or someone copies an existing id
                return Response({
                    'detail': 'Attempted to register agent with a different public key',
                }, status=status.HTTP_400_BAD_REQUEST)

        default_cache.set('relay-auth:%s' % relay_id, {
            'token': challenge['token'],
            'public_key': six.text_type(challenge['public_key']),
        }, 60)
        return Response(serialize({
            'relay_id': six.text_type(challenge['relay_id']),
            'token': challenge['token'],
        }))
Esempio n. 6
0
    def post(self, request):
        """
        Requests to Register a Relay
        ````````````````````````````

        Registers the relay with the sentry installation.  If a relay boots
        it will always attempt to invoke this endpoint.
        """
        try:
            json_data = json.loads(request.body)
        except ValueError:
            return Response({
                'detail': 'No valid json body',
            }, status=status.HTTP_400_BAD_REQUEST)

        serializer = RelayRegisterChallengeSerializer(data=json_data)

        if not serializer.is_valid():
            return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

        if not settings.SENTRY_RELAY_OPEN_REGISTRATION and \
           not is_internal_relay(request, json_data.get('public_key')):
            return Response({
                'detail': 'Relay is not allowed to register',
            }, status=status.HTTP_401_UNAUTHORIZED)

        sig = get_header_relay_signature(request)
        if not sig:
            return Response({
                'detail': 'Missing relay signature',
            }, status=status.HTTP_400_BAD_REQUEST)

        try:
            challenge = create_register_challenge(request.body, sig)
        except Exception as exc:
            return Response({
                'detail': str(exc).splitlines()[0],
            }, status=status.HTTP_400_BAD_REQUEST)

        relay_id = six.text_type(challenge['relay_id'])
        if relay_id != get_header_relay_id(request):
            return Response({
                'detail': 'relay_id in payload did not match header',
            }, status=status.HTTP_400_BAD_REQUEST)

        try:
            relay = Relay.objects.get(relay_id=relay_id)
        except Relay.DoesNotExist:
            pass
        else:
            if relay.public_key != six.text_type(challenge['public_key']):
                # This happens if we have an ID collision or someone copies an existing id
                return Response({
                    'detail': 'Attempted to register agent with a different public key',
                }, status=status.HTTP_400_BAD_REQUEST)

        default_cache.set('relay-auth:%s' % relay_id, {
            'token': challenge['token'],
            'public_key': six.text_type(challenge['public_key']),
        }, 60)
        return Response(serialize({
            'relay_id': six.text_type(challenge['relay_id']),
            'token': challenge['token'],
        }))
Esempio n. 7
0
    def post(self, request):
        """
        Registers a Relay
        `````````````````

        Registers the relay with the sentry installation.  If a relay boots
        it will always attempt to invoke this endpoint.
        """

        try:
            json_data = json.loads(request.body)
        except ValueError:
            return Response({
                'detail': 'No valid json body',
            }, status=status.HTTP_400_BAD_REQUEST)

        serializer = RelayRegisterResponseSerializer(data=json_data)

        if not serializer.is_valid():
            return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

        sig = get_header_relay_signature(request)
        if not sig:
            return Response({
                'detail': 'Missing relay signature',
            }, status=status.HTTP_400_BAD_REQUEST)

        relay_id = six.text_type(get_register_response_relay_id(request.body))
        if relay_id != get_header_relay_id(request):
            return Response({
                'detail': 'relay_id in payload did not match header',
            }, status=status.HTTP_400_BAD_REQUEST)

        params = default_cache.get('relay-auth:%s' % relay_id)
        if params is None:
            return Response({
                'detail': 'Challenge expired'
            }, status=status.HTTP_401_UNAUTHORIZED)

        key = PublicKey.parse(params['public_key'])

        try:
            validate_register_response(key, request.body, sig)
        except Exception as exc:
            return Response({
                'detail': str(exc).splitlines()[0],
            }, status=status.HTTP_400_BAD_REQUEST)

        is_internal = is_internal_relay(request, params['public_key'])
        try:
            relay = Relay.objects.get(relay_id=relay_id)
        except Relay.DoesNotExist:
            relay = Relay.objects.create(
                relay_id=relay_id,
                public_key=params['public_key'],
                is_internal=is_internal
            )
        else:
            relay.last_seen = timezone.now()
            relay.is_internal = is_internal
            relay.save()
        default_cache.delete('relay-auth:%s' % relay_id)

        return Response(serialize({
            'relay_id': relay.relay_id,
        }))
Esempio n. 8
0
    def post(self, request):
        """
        Requests to Register a Relay
        ````````````````````````````

        Registers the relay with the sentry installation.  If a relay boots
        it will always attempt to invoke this endpoint.
        """
        try:
            json_data = json.loads(request.body)
        except ValueError:
            return Response({"detail": "No valid json body"}, status=status.HTTP_400_BAD_REQUEST)

        serializer = RelayRegisterChallengeSerializer(data=json_data)

        if not serializer.is_valid():
            return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

        if not settings.SENTRY_RELAY_OPEN_REGISTRATION and not is_internal_relay(
            request, json_data.get("public_key")
        ):
            return Response(
                {"detail": "Relay is not allowed to register"}, status=status.HTTP_401_UNAUTHORIZED
            )

        sig = get_header_relay_signature(request)
        if not sig:
            return Response(
                {"detail": "Missing relay signature"}, status=status.HTTP_400_BAD_REQUEST
            )

        try:
            challenge = create_register_challenge(request.body, sig)
        except Exception as exc:
            return Response(
                {"detail": str(exc).splitlines()[0]}, status=status.HTTP_400_BAD_REQUEST
            )

        relay_id = six.text_type(challenge["relay_id"])
        if relay_id != get_header_relay_id(request):
            return Response(
                {"detail": "relay_id in payload did not match header"},
                status=status.HTTP_400_BAD_REQUEST,
            )

        try:
            relay = Relay.objects.get(relay_id=relay_id)
        except Relay.DoesNotExist:
            pass
        else:
            if relay.public_key != six.text_type(challenge["public_key"]):
                # This happens if we have an ID collision or someone copies an existing id
                return Response(
                    {"detail": "Attempted to register agent with a different public key"},
                    status=status.HTTP_400_BAD_REQUEST,
                )

        default_cache.set(
            "relay-auth:%s" % relay_id,
            {"token": challenge["token"], "public_key": six.text_type(challenge["public_key"])},
            60,
        )
        return Response(
            serialize(
                {"relay_id": six.text_type(challenge["relay_id"]), "token": challenge["token"]}
            )
        )
Esempio n. 9
0
    def post(self, request):
        """
        Requests to Register a Relay
        ````````````````````````````

        Registers the relay with the sentry installation.  If a relay boots
        it will always attempt to invoke this endpoint.
        """
        try:
            json_data = json.loads(request.body)
        except ValueError:
            return Response({"detail": "No valid json body"},
                            status=status.HTTP_400_BAD_REQUEST)

        serializer = RelayRegisterChallengeSerializer(data=json_data)

        if not serializer.is_valid():
            return Response(serializer.errors,
                            status=status.HTTP_400_BAD_REQUEST)

        if not is_version_supported(json_data.get("version")):
            return Response(
                {
                    "detail":
                    "Relay version no longer supported, please upgrade to a more recent version"
                },
                status=status.HTTP_403_FORBIDDEN,
            )

        public_key = json_data.get("public_key")
        if not public_key:
            return Response({"detail": "Missing public key"},
                            status=status.HTTP_400_FORBIDDEN)

        if not settings.SENTRY_RELAY_OPEN_REGISTRATION and not is_internal_relay(
                request, public_key):
            return Response({"detail": "Relay is not allowed to register"},
                            status=status.HTTP_403_FORBIDDEN)

        sig = get_header_relay_signature(request)
        if not sig:
            return Response({"detail": "Missing relay signature"},
                            status=status.HTTP_400_BAD_REQUEST)

        secret = options.get("system.secret-key")

        try:
            challenge = create_register_challenge(request.body, sig, secret)
        except Exception as exc:
            return Response({"detail": str(exc).splitlines()[0]},
                            status=status.HTTP_400_BAD_REQUEST)

        relay_id = six.text_type(challenge["relay_id"])
        if relay_id != get_header_relay_id(request):
            return Response(
                {"detail": "relay_id in payload did not match header"},
                status=status.HTTP_400_BAD_REQUEST,
            )

        try:
            relay = Relay.objects.get(relay_id=relay_id)
        except Relay.DoesNotExist:
            pass
        else:
            if relay.public_key != six.text_type(public_key):
                # This happens if we have an ID collision or someone copies an existing id
                return Response(
                    {
                        "detail":
                        "Attempted to register agent with a different public key"
                    },
                    status=status.HTTP_400_BAD_REQUEST,
                )

        return Response(serialize(challenge))
Esempio n. 10
0
    def post(self, request: Request) -> Response:
        """
        Registers a Relay
        `````````````````

        Registers the relay with the sentry installation.  If a relay boots
        it will always attempt to invoke this endpoint.
        """

        try:
            json_data = json.loads(request.body)
        except ValueError:
            return Response({"detail": "No valid json body"},
                            status=status.HTTP_400_BAD_REQUEST)

        serializer = RelayRegisterResponseSerializer(data=json_data)

        if not serializer.is_valid():
            return Response(serializer.errors,
                            status=status.HTTP_400_BAD_REQUEST)

        sig = get_header_relay_signature(request)
        if not sig:
            return Response({"detail": "Missing relay signature"},
                            status=status.HTTP_400_BAD_REQUEST)

        secret = options.get("system.secret-key")

        try:
            validated = validate_register_response(request.body, sig, secret)
        except UnpackErrorSignatureExpired:
            return Response({"detail": "Challenge expired"},
                            status=status.HTTP_401_UNAUTHORIZED)
        except Exception as exc:
            return Response({"detail": str(exc).splitlines()[0]},
                            status=status.HTTP_400_BAD_REQUEST)

        relay_id = str(validated["relay_id"])
        version = str(validated["version"])
        public_key = validated["public_key"]

        if relay_id != get_header_relay_id(request):
            return Response(
                {"detail": "relay_id in payload did not match header"},
                status=status.HTTP_400_BAD_REQUEST,
            )

        relay, static = relay_from_id(request, relay_id)

        if not static:
            is_internal = is_internal_relay(request, public_key)

            if relay is None:
                relay = Relay.objects.create(relay_id=relay_id,
                                             public_key=public_key,
                                             is_internal=is_internal)
            else:
                # update the internal flag in case it is changed
                relay.is_internal = is_internal
                relay.save()

            # only update usage for non static relays (static relays should not access the db)
            try:
                relay_usage = RelayUsage.objects.get(relay_id=relay_id,
                                                     version=version)
            except RelayUsage.DoesNotExist:
                RelayUsage.objects.create(relay_id=relay_id,
                                          version=version,
                                          public_key=public_key)
            else:
                relay_usage.last_seen = timezone.now()
                relay_usage.public_key = public_key
                relay_usage.save()

        return Response(serialize({"relay_id": relay.relay_id}))