Beispiel #1
0
    def validate(cls, validator_context):
        """
        Validates the configuration for using BitTorrent for downloads.
        """
        config = validator_context.config
        client = validator_context.http_client

        announce_url = config.get("BITTORRENT_ANNOUNCE_URL")
        if not announce_url:
            raise ConfigValidationException("Missing announce URL")

        # Ensure that the tracker is reachable and accepts requests signed with a registry key.
        params = {
            "info_hash": sha1("test").digest(),
            "peer_id": "-QUAY00-6wfG2wk6wWLc",
            "uploaded": 0,
            "downloaded": 0,
            "left": 0,
            "numwant": 0,
            "port": 80,
        }

        torrent_config = TorrentConfiguration.for_testing(
            validator_context.instance_keys, announce_url,
            validator_context.registry_title)
        encoded_jwt = jwt_from_infohash(torrent_config, params["info_hash"])
        params["jwt"] = encoded_jwt

        resp = client.get(announce_url, timeout=5, params=params)
        logger.debug("Got tracker response: %s: %s", resp.status_code,
                     resp.text)

        if resp.status_code == 404:
            raise ConfigValidationException(
                "Announce path not found; did you forget `/announce`?")

        if resp.status_code == 500:
            raise ConfigValidationException(
                "Did not get expected response from Tracker; " +
                "please check your settings")

        if resp.status_code == 200:
            if "invalid jwt" in resp.text:
                raise ConfigValidationException(
                    "Could not authorize to Tracker; is your Tracker " +
                    "properly configured?")

            if "failure reason" in resp.text:
                raise ConfigValidationException(
                    "Could not validate signed announce request: " + resp.text)

            if "go_goroutines" in resp.text:
                raise ConfigValidationException(
                    "Could not validate signed announce request: " +
                    "provided port is used for Prometheus")
Beispiel #2
0
def _torrent_for_blob(blob, is_public):
    """
    Returns a response containing the torrent file contents for the given blob.

    May abort with an error if the state is not valid (e.g. non-public, non-user request).
    """
    # Make sure the storage has a size.
    if not blob.compressed_size:
        abort(404)

    # Lookup the torrent information for the storage.
    torrent_info = registry_model.get_torrent_info(blob)
    if torrent_info is None:
        abort(404)

    # Lookup the webseed path for the storage.
    webseed = storage.get_direct_download_url(
        blob.placements,
        blob.storage_path,
        expires_in=app.config["BITTORRENT_WEBSEED_LIFETIME"])
    if webseed is None:
        # We cannot support webseeds for storages that cannot provide direct downloads.
        exact_abort(501, "Storage engine does not support seeding.")

    # Load the config for building torrents.
    torrent_config = TorrentConfiguration.from_app_config(
        instance_keys, app.config)

    # Build the filename for the torrent.
    if is_public:
        name = public_torrent_filename(blob.uuid)
    else:
        user = get_authenticated_user()
        if not user:
            abort(403)

        name = per_user_torrent_filename(torrent_config, user.uuid, blob.uuid)

    # Return the torrent file.
    torrent_file = make_torrent(
        torrent_config,
        name,
        webseed,
        blob.compressed_size,
        torrent_info.piece_length,
        torrent_info.pieces,
    )

    headers = {
        "Content-Type": "application/x-bittorrent",
        "Content-Disposition": "attachment; filename={0}.torrent".format(name),
    }

    return make_response(torrent_file, 200, headers)
Beispiel #3
0
    def validate(cls, validator_context):
        """ Validates the configuration for using BitTorrent for downloads. """
        config = validator_context.config
        client = validator_context.http_client

        announce_url = config.get('BITTORRENT_ANNOUNCE_URL')
        if not announce_url:
            raise ConfigValidationException('Missing announce URL')

        # Ensure that the tracker is reachable and accepts requests signed with a registry key.
        params = {
            'info_hash': sha1('test').digest(),
            'peer_id': '-QUAY00-6wfG2wk6wWLc',
            'uploaded': 0,
            'downloaded': 0,
            'left': 0,
            'numwant': 0,
            'port': 80,
        }

        torrent_config = TorrentConfiguration.for_testing(
            validator_context.instance_keys, announce_url,
            validator_context.registry_title)
        encoded_jwt = jwt_from_infohash(torrent_config, params['info_hash'])
        params['jwt'] = encoded_jwt

        resp = client.get(announce_url, timeout=5, params=params)
        logger.debug('Got tracker response: %s: %s', resp.status_code,
                     resp.text)

        if resp.status_code == 404:
            raise ConfigValidationException(
                'Announce path not found; did you forget `/announce`?')

        if resp.status_code == 500:
            raise ConfigValidationException(
                'Did not get expected response from Tracker; ' +
                'please check your settings')

        if resp.status_code == 200:
            if 'invalid jwt' in resp.text:
                raise ConfigValidationException(
                    'Could not authorize to Tracker; is your Tracker ' +
                    'properly configured?')

            if 'failure reason' in resp.text:
                raise ConfigValidationException(
                    'Could not validate signed announce request: ' + resp.text)

            if 'go_goroutines' in resp.text:
                raise ConfigValidationException(
                    'Could not validate signed announce request: ' +
                    'provided port is used for Prometheus')