From 087c6828addfd532ec4b902cde03c9093969754d Mon Sep 17 00:00:00 2001 From: Jimmy Zelinskie Date: Thu, 7 Jan 2016 19:07:23 -0500 Subject: [PATCH] add feature.BITTORRENT and jwk set URI --- config.py | 2 +- endpoints/verbs.py | 4 +++ endpoints/web.py | 70 ++++++++++++++++++++++++++-------------- util/registry/torrent.py | 6 ++-- 4 files changed, 53 insertions(+), 29 deletions(-) diff --git a/config.py b/config.py index b0b5ed1bb..0051cbe89 100644 --- a/config.py +++ b/config.py @@ -275,7 +275,7 @@ class DefaultConfig(object): } # Torrent management flags + FEATURE_BITTORRENT = True TORRENT_PIECE_SIZE = 512 * 1024 TORRENT_ANNOUNCE_URL = 'https://localhost:6881/announce' TORRENT_NAMING_SALT = '3ae93fef-c30a-427e-9ba0-eea0fd710419' - diff --git a/endpoints/verbs.py b/endpoints/verbs.py index a2c330af6..4cc9c7535 100644 --- a/endpoints/verbs.py +++ b/endpoints/verbs.py @@ -22,6 +22,9 @@ from util.registry.gzipstream import SizeInfo from formats.squashed import SquashedDockerImage from formats.aci import ACIImage from endpoints.v2.blob import BLOB_DIGEST_ROUTE +from endpoints.common import route_show_if + +import features verbs = Blueprint('verbs', __name__) @@ -294,6 +297,7 @@ def get_squashed_tag(namespace, repository, tag): return _repo_verb(namespace, repository, tag, 'squash', SquashedDockerImage()) +@route_show_if(features.BITTORRENT) @anon_protect @verbs.route('/torrent{0}'.format(BLOB_DIGEST_ROUTE), methods=['GET']) @process_auth diff --git a/endpoints/web.py b/endpoints/web.py index 0fa19ef9b..ab6611237 100644 --- a/endpoints/web.py +++ b/endpoints/web.py @@ -1,51 +1,51 @@ +import json import logging +from base64 import urlsafe_b64encode +from cachetools import lru_cache +from cryptography.x509 import load_pem_x509_certificate +from cryptography.hazmat.backends import default_backend from flask import (abort, redirect, request, url_for, make_response, Response, Blueprint, send_from_directory, jsonify, send_file) - from flask.ext.login import current_user from urlparse import urlparse -from health.healthcheck import get_healthchecker -from data import model -from data.database import db +import features + from app import app, billing as stripe, build_logs, avatar, signer, log_archive, config_provider +from auth import scopes from auth.auth import require_session_login, process_oauth from auth.permissions import (AdministerOrganizationPermission, ReadRepositoryPermission, SuperUserPermission, AdministerRepositoryPermission, ModifyRepositoryPermission) - -from util.invoice import renderInvoiceToPdf -from util.seo import render_snapshot -from util.cache import no_cache -from endpoints.common import common_login, render_page_template, route_show_if, param_required -from endpoints.decorators import anon_protect, anon_allowed -from endpoints.csrf import csrf_protect, generate_csrf_token, verify_csrf - -from buildtrigger.customhandler import CustomBuildTrigger -from buildtrigger.bitbuckethandler import BitbucketBuildTrigger -from buildtrigger.triggerutil import TriggerProviderException from buildtrigger.basehandler import BuildTriggerHandler - -from util.names import parse_repository_name, parse_repository_name_and_tag -from util.useremails import send_email_changed -from util.systemlogs import build_logs_archive +from buildtrigger.bitbuckethandler import BitbucketBuildTrigger +from buildtrigger.customhandler import CustomBuildTrigger +from buildtrigger.triggerutil import TriggerProviderException +from data import model +from data.database import db +from endpoints.common import common_login, render_page_template, route_show_if, param_required +from endpoints.csrf import csrf_protect, generate_csrf_token, verify_csrf +from endpoints.decorators import anon_protect, anon_allowed +from health.healthcheck import get_healthchecker +from util.cache import no_cache from util.headers import parse_basic_auth -from auth import scopes +from util.invoice import renderInvoiceToPdf +from util.names import parse_repository_name, parse_repository_name_and_tag +from util.seo import render_snapshot +from util.systemlogs import build_logs_archive +from util.useremails import send_email_changed -import features -import json - - -logger = logging.getLogger(__name__) # Capture the unverified SSL errors. +logger = logging.getLogger(__name__) logging.captureWarnings(True) web = Blueprint('web', __name__) STATUS_TAGS = app.config['STATUS_TAGS'] +JWT_ISSUER = app.config.get('JWT_AUTH_TOKEN_ISSUER') @web.route('/', methods=['GET'], defaults={'path': ''}) @@ -676,3 +676,23 @@ def redirect_to_namespace(namespace): return redirect(url_for('web.org_view', path=namespace)) else: return redirect(url_for('web.user_view', path=namespace)) + +@lru_cache(maxsize=1) +def _load_certificate_bytes(certificate_file_path): + with open(certificate_file_path) as cert_file: + return load_pem_x509_certificate(cert_file.read(), default_backend()).public_key() + +@web.route('/jwk_set', methods=['GET']) +@route_show_if(features.BITTORRENT) +def jwk_set_uri(): + certificate = _load_certificate_bytes(app.config['JWT_AUTH_CERTIFICATE_PATH']) + return jsonify({ + 'keys': [{ + 'kty': 'RSA', + 'alg': 'RSA256', + 'use': 'sig', + 'n': urlsafe_b64encode(str(certificate.public_numbers().n)), + 'e': urlsafe_b64encode(str(certificate.public_numbers().e)), + }], + 'issuer': JWT_ISSUER, + }) diff --git a/util/registry/torrent.py b/util/registry/torrent.py index fc392a801..bd325d26a 100644 --- a/util/registry/torrent.py +++ b/util/registry/torrent.py @@ -2,13 +2,13 @@ import time import hashlib import urllib +from cryptography.x509 import load_pem_x509_certificate +from cryptography.hazmat.backends import default_backend + import bencode import resumablehashlib import jwt -from cryptography.x509 import load_pem_x509_certificate -from cryptography.hazmat.backends import default_backend - from cachetools import lru_cache from app import app