parent
343d293001
commit
681f975df5
5 changed files with 84 additions and 2 deletions
|
@ -340,6 +340,37 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<!-- BitTorrent pull -->
|
||||
<div class="co-panel">
|
||||
<div class="co-panel-heading">
|
||||
<i class="fa fa-cloud-download"></i> BitTorrent-based download
|
||||
</div>
|
||||
<div class="co-panel-body">
|
||||
<div class="description">
|
||||
<p>If enabled, all images in the registry can be downloaded using the <a href="http://github.com/coreos/quayctl" ng-safenewtab>quayctl</a> tool via the BitTorrent protocol. A JWT-compatible BitTorrent tracker such as <a href="https://tectonic.com/quay-enterprise/docs/latest/running-chihaya.html">Chihaya</a> must be run.
|
||||
</div>
|
||||
|
||||
<div class="config-bool-field" binding="config.FEATURE_BITTORRENT">
|
||||
Enable BitTorrent downloads
|
||||
</div>
|
||||
|
||||
<table class="config-table" ng-if="config.FEATURE_BITTORRENT">
|
||||
<tr>
|
||||
<td>Announce URL:</td>
|
||||
<td>
|
||||
<span class="config-string-field" binding="config.BITTORRENT_ANNOUNCE_URL"
|
||||
placeholder="Announce URL for the torrent tracker (Example: http://mytracker/announce)"
|
||||
pattern="http(s)?://.+"></span>
|
||||
<div class="help-text">
|
||||
The HTTP URL at which the torrents should be announced. A JWT-compatible tracker such as <a href="https://github.com/chihaya/chihaya" ng-safenewtab>Chihaya</a> must be run to ensure proper security. Documentation on running Chihaya with
|
||||
this support can be found at <a href="https://tectonic.com/quay-enterprise/docs/latest/running-chihaya.html">Running Chihaya for Quay Enterprise</a>.
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ACI Conversion -->
|
||||
<div class="co-panel">
|
||||
<div class="co-panel-heading">
|
||||
|
|
|
@ -67,6 +67,10 @@ angular.module("core-config-setup", ['angularFileUpload'])
|
|||
|
||||
{'id': 'security-scanner', 'title': 'Quay Security Scanner', 'condition': function(config) {
|
||||
return config.FEATURE_SECURITY_SCANNER;
|
||||
}},
|
||||
|
||||
{'id': 'bittorrent', 'title': 'BitTorrent downloads', 'condition': function(config) {
|
||||
return config.FEATURE_BITTORRENT;
|
||||
}}
|
||||
];
|
||||
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
from random import SystemRandom
|
||||
from uuid import uuid4
|
||||
|
||||
def generate_secret_key():
|
||||
cryptogen = SystemRandom()
|
||||
|
@ -52,6 +53,10 @@ def add_enterprise_config_defaults(config_obj, current_secret_key, hostname):
|
|||
if not 'SECRET_KEY' in config_obj:
|
||||
config_obj['SECRET_KEY'] = current_secret_key
|
||||
|
||||
# Default torrent pepper.
|
||||
if not 'BITTORRENT_FILENAME_PEPPER' in config_obj:
|
||||
config_obj['BITTORRENT_FILENAME_PEPPER'] = str(uuid4())
|
||||
|
||||
# Default storage configuration.
|
||||
if not 'DISTRIBUTED_STORAGE_CONFIG' in config_obj:
|
||||
config_obj['DISTRIBUTED_STORAGE_PREFERENCE'] = ['default']
|
||||
|
|
|
@ -12,6 +12,7 @@ import redis
|
|||
|
||||
from flask import Flask
|
||||
from flask_mail import Mail, Message
|
||||
from hashlib import sha1
|
||||
|
||||
from app import app, config_provider, get_app_url, OVERRIDE_CONFIG_DIRECTORY
|
||||
from auth.auth_context import get_authenticated_user
|
||||
|
@ -25,6 +26,7 @@ from data.users.keystone import KeystoneUsers
|
|||
from storage import get_storage_driver
|
||||
from util.config.oauth import GoogleOAuthConfig, GithubOAuthConfig, GitLabOAuthConfig
|
||||
from util.secscan.api import SecurityScannerAPI
|
||||
from util.registry.torrent import torrent_jwt
|
||||
from util.security.signing import SIGNING_ENGINES
|
||||
|
||||
|
||||
|
@ -452,6 +454,42 @@ def _validate_security_scanner(config, _):
|
|||
raise Exception('Could not ping security scanner: %s' % message)
|
||||
|
||||
|
||||
def _validate_bittorrent(config, _):
|
||||
""" Validates the configuration for using BitTorrent for downloads. """
|
||||
|
||||
# Ensure that the tracker is reachable and accepts requests signed with a registry key.
|
||||
client = app.config['HTTPCLIENT']
|
||||
|
||||
params = {
|
||||
'info_hash': sha1('somedata').digest(),
|
||||
'peer_id': '-QUAY00-6wfG2wk6wWLc',
|
||||
'uploaded': 0,
|
||||
'downloaded': 0,
|
||||
'left': 0,
|
||||
'numwant': 0,
|
||||
'port': 80,
|
||||
}
|
||||
|
||||
encoded_jwt = torrent_jwt(params)
|
||||
params['jwt'] = encoded_jwt
|
||||
|
||||
resp = client.get(config['BITTORRENT_ANNOUNCE_URL'], timeout=5, params=params)
|
||||
logger.debug('Got tracker response: %s: %s', resp.status_code, resp.text)
|
||||
|
||||
if resp.status_code == 404:
|
||||
raise Exception('Announce path not found; did you forget `/announce`?')
|
||||
|
||||
if resp.status_code == 500:
|
||||
raise Exception('Did not get expected response from Tracker; please check your settings')
|
||||
|
||||
if resp.status_code == 200:
|
||||
if 'invalid jwt' in resp.text:
|
||||
raise Exception('Could not authorize to Tracker; is your Tracker properly configured?')
|
||||
|
||||
if 'failure reason' in resp.text:
|
||||
raise Exception('Could not validate signed announce request: ' + resp.text)
|
||||
|
||||
|
||||
_VALIDATORS = {
|
||||
'database': _validate_database,
|
||||
'redis': _validate_redis,
|
||||
|
@ -468,4 +506,5 @@ _VALIDATORS = {
|
|||
'keystone': _validate_keystone,
|
||||
'signer': _validate_signer,
|
||||
'security-scanner': _validate_security_scanner,
|
||||
'bittorrent': _validate_bittorrent,
|
||||
}
|
||||
|
|
|
@ -21,7 +21,10 @@ def _load_private_key(private_key_file_path):
|
|||
with open(private_key_file_path) as private_key_file:
|
||||
return private_key_file.read()
|
||||
|
||||
def _torrent_jwt(info_dict):
|
||||
def torrent_jwt(info_dict):
|
||||
""" Returns an encoded JWT for the given information dictionary, signed by the local instance's
|
||||
private key.
|
||||
"""
|
||||
token_data = {
|
||||
'iss': instance_keys.service_name,
|
||||
'aud': ANNOUNCE_URL,
|
||||
|
@ -45,7 +48,7 @@ def make_torrent(name, webseed, length, piece_length, pieces):
|
|||
}
|
||||
|
||||
return bencode.bencode({
|
||||
'announce': ANNOUNCE_URL + "?jwt=" + _torrent_jwt(info_dict),
|
||||
'announce': ANNOUNCE_URL + "?jwt=" + torrent_jwt(info_dict),
|
||||
'url-list': webseed,
|
||||
'encoding': 'UTF-8',
|
||||
'created by': REGISTRY_TITLE,
|
||||
|
|
Reference in a new issue