Fix and templatize the logic for external JWT AuthN and registry v2 Auth.

Make it explicit that the registry-v2 stuff is not ready for prime time.
This commit is contained in:
Jake Moshenko 2015-07-16 15:49:06 -04:00
parent 768192927a
commit bc29561f8f
11 changed files with 223 additions and 79 deletions

View file

@ -1,3 +1,6 @@
# XXX This code is not yet ready to be run in production, and should remain disabled until such
# XXX time as this notice is removed.
import logging
from flask import Blueprint, make_response
@ -25,7 +28,7 @@ def _require_repo_permission(permission_class, allow_public=False):
permission = permission_class(namespace, repo_name)
if (permission.can() or
(allow_public and
model.repository_is_public(namespace, repo_name))):
model.repository.repository_is_public(namespace, repo_name))):
return func(namespace, repo_name, *args, **kwargs)
raise abort(401)
return wrapped

View file

@ -1,3 +1,6 @@
# XXX This code is not yet ready to be run in production, and should remain disabled until such
# XXX time as this notice is removed.
import logging
from flask import make_response, url_for, request
@ -14,8 +17,11 @@ from util.http import abort
logger = logging.getLogger(__name__)
@v2_bp.route('/<namespace>/<repo_name>/blobs/<regex("' + digest_tools.DIGEST_PATTERN + '"):digest>',
methods=['HEAD'])
BASE_BLOB_ROUTE = '/<namespace>/<repo_name>/blobs/<regex("{0}"):digest>'
BLOB_DIGEST_ROUTE = BASE_BLOB_ROUTE.format(digest_tools.DIGEST_PATTERN)
@v2_bp.route(BLOB_DIGEST_ROUTE, methods=['HEAD'])
@process_jwt_auth
@require_repo_read
@anon_protect
@ -29,12 +35,12 @@ def check_blob_existence(namespace, repo_name, digest):
abort(404)
@v2_bp.route('/<namespace>/<repo_name>/blobs/<regex("' + digest_tools.DIGEST_PATTERN + '"):digest>',
methods=['GET'])
@v2_bp.route(BLOB_DIGEST_ROUTE, methods=['GET'])
@process_jwt_auth
@require_repo_read
@anon_protect
def download_blob(namespace, repo_name, digest):
# TODO Implement this
return make_response('')

View file

@ -1,3 +1,6 @@
# XXX This code is not yet ready to be run in production, and should remain disabled until such
# XXX time as this notice is removed.
import logging
import re
import jwt.utils

View file

@ -1,10 +1,15 @@
# XXX This code is not yet ready to be run in production, and should remain disabled until such
# XXX time as this notice is removed.
import logging
import re
import time
import jwt
from flask import request, jsonify, abort
from cachetools import lru_cache
from app import app
from data import model
from auth.auth import process_auth
from auth.auth_context import get_authenticated_user
@ -23,10 +28,25 @@ SCOPE_REGEX = re.compile(
)
@lru_cache(maxsize=1)
def load_certificate_bytes(certificate_file_path):
with open(certificate_file_path) as cert_file:
return ''.join(cert_file.readlines()[1:-1]).rstrip('\n')
@lru_cache(maxsize=1)
def load_private_key(private_key_file_path):
with open(private_key_file_path) as private_key_file:
return private_key_file.read()
@v2_bp.route('/auth')
@process_auth
@no_cache
def generate_registry_jwt():
""" This endpoint will generate a JWT conforming to the Docker registry v2 auth spec:
https://docs.docker.com/registry/spec/auth/token/
"""
audience_param = request.args.get('service')
logger.debug('Request audience: %s', audience_param)
@ -81,14 +101,12 @@ def generate_registry_jwt():
'access': access,
}
with open('/Users/jake/Projects/registry-v2/ca/quay.host.crt') as cert_file:
certificate = ''.join(cert_file.readlines()[1:-1]).rstrip('\n')
certificate = load_certificate_bytes(app.config['JWT_AUTH_CERTIFICATE_PATH'])
token_headers = {
'x5c': [certificate],
}
with open('/Users/jake/Projects/registry-v2/ca/quay.host.key.insecure') as private_key_file:
private_key = private_key_file.read()
private_key = load_private_key(app.config['JWT_AUTH_PRIVATE_KEY_PATH'])
return jsonify({'token':jwt.encode(token_data, private_key, 'RS256', headers=token_headers)})
return jsonify({'token':jwt.encode(token_data, private_key, 'RS256', headers=token_headers)})