basically finish superuser key api

This commit is contained in:
Jimmy Zelinskie 2016-03-28 14:52:20 -04:00 committed by Jimmy Zelinskie
parent 35ed73e195
commit aaf9e83278
3 changed files with 34 additions and 25 deletions

View file

@ -63,18 +63,22 @@ def get_service_keys(approved_only, kid=None, service=None):
query = ServiceKey.select() query = ServiceKey.select()
if approved_only:
query = query.where(~(ServiceKey.approval >> None))
if service is not None: if service is not None:
query = query.where(ServiceKey.service == service) query = query.where(ServiceKey.service == service)
if kid is not None: if kid is not None:
query.where(ServiceKey.kid == kid) query.where(ServiceKey.kid == kid)
if approved_only:
query = query.where(~(ServiceKey.approval >> None))
return query return query
def get_service_key(kid):
return get_service_keys(False, kid=kid).get()
def delete_service_key(service, kid): def delete_service_key(service, kid):
_gc_expired(service) _gc_expired(service)

View file

@ -1,13 +1,18 @@
""" Superuser API. """ """ Superuser API. """
import string import json
import logging import logging
import os import os
import string
from collections import OrderedDict
from datetime import datetime from datetime import datetime
from hashlib import sha256
from random import SystemRandom from random import SystemRandom
from Crypto.PublicKey import RSA
from flask import request, make_response, jsonify from flask import request, make_response, jsonify
from jwkest.jwk import RSAKey
import features import features
@ -21,6 +26,7 @@ from endpoints.api import (ApiResource, nickname, resource, validate_json_reques
page_support) page_support)
from endpoints.api.logs import get_logs, get_aggregate_logs from endpoints.api.logs import get_logs, get_aggregate_logs
from data import model from data import model
from data.database import ServiceKeyApprovalType
from util.useremails import send_confirmation_email, send_recovery_email from util.useremails import send_confirmation_email, send_recovery_email
@ -506,7 +512,7 @@ class SuperUserServiceKeyManagement(ApiResource):
@verify_not_prod @verify_not_prod
@nickname('getServiceKeys') @nickname('getServiceKeys')
@require_scope(scopes.SUPERUSER) @require_scope(scopes.SUPERUSER)
def get(): def get(self):
if SuperUserPermission().can(): if SuperUserPermission().can():
return jsonify(list(model.service_keys.get_service_keys(False))) return jsonify(list(model.service_keys.get_service_keys(False)))
abort(403) abort(403)
@ -515,11 +521,11 @@ class SuperUserServiceKeyManagement(ApiResource):
@nickname('createServiceKey') @nickname('createServiceKey')
@require_scope(scopes.SUPERUSER) @require_scope(scopes.SUPERUSER)
@validate_json_request('PutServiceKey') @validate_json_request('PutServiceKey')
def post(self, service): def post(self):
if SuperUserPermission().can(): if SuperUserPermission().can():
body = request.get_json() body = request.get_json()
expiration_date = body['expiration'] expiration_date = body.get('expiration', None)
if expiration_date is not None and expiration_date != '': if expiration_date is not None and expiration_date != '':
try: try:
expiration_date = datetime.utcfromtimestamp(float(expiration_date)) expiration_date = datetime.utcfromtimestamp(float(expiration_date))
@ -527,7 +533,7 @@ class SuperUserServiceKeyManagement(ApiResource):
abort(400) abort(400)
user = get_authenticate_user() user = get_authenticated_user()
metadata = body.get('metadata', {}) metadata = body.get('metadata', {})
metadata.update({ metadata.update({
'created_by': 'Quay SuperUser Panel', 'created_by': 'Quay SuperUser Panel',
@ -535,18 +541,17 @@ class SuperUserServiceKeyManagement(ApiResource):
'superuser ip': request.remote_addr, 'superuser ip': request.remote_addr,
}) })
key = RSAKey(key=RSA.generate(2048)) private_key = RSA.generate(2048)
key.serialize() jwk = RSAKey(key=private_key.publickey()).serialize()
jwk = json.dumps(key.to_dict(), "enc") canonical_jwk = OrderedDict(sorted(jwk.items()))
kid = sha256(json.dumps(canonical_jwk)).hexdigest()
public_key, private_key = generate_key_pair()
jwk = jwk(private_key)
kid = kid(private_key)
model.service_keys.create_service_key(body['name'] or '', kid, jwk, metadata, expiration_date) model.service_keys.create_service_key(body.get('name', ''), kid, body['service'], jwk,
model.service_keys.approve_service_key(kid, user, metadata, expiration_date)
return jsonify({'public_key': public_key, 'private_key': private_key}) model.service_keys.approve_service_key(kid, user, ServiceKeyApprovalType.SUPERUSER)
return jsonify({'private_key': private_key.exportKey('PEM')})
abort(403) abort(403)

View file

@ -46,7 +46,7 @@ def _validate_jwt(encoded_jwt, jwk, service):
abort(400) abort(400)
def _signer_jwk(encoded_jwt, jwk, service, kid): def _signer_jwk(encoded_jwt, jwk, kid):
decoded_jwt = jwt.decode(encoded_jwt, verify=False) decoded_jwt = jwt.decode(encoded_jwt, verify=False)
signer_kid = decoded_jwt.get('signer_kid', '') signer_kid = decoded_jwt.get('signer_kid', '')
@ -55,7 +55,7 @@ def _signer_jwk(encoded_jwt, jwk, service, kid):
return jwk return jwk
else: else:
try: try:
service_key = data.model.service_keys.get_service_keys(service, kid=signer_kid) service_key = data.model.service_keys.get_service_key(signer_kid)
except data.model.ServiceKeyDoesNotExist: except data.model.ServiceKeyDoesNotExist:
abort(404) abort(404)
@ -69,8 +69,8 @@ def get_service_keys(service):
@key_server.route('/services/<service>/keys/<kid>', methods=['GET']) @key_server.route('/services/<service>/keys/<kid>', methods=['GET'])
def get_service_key(service, kid): def get_service_key(kid):
key = data.model.service_keys.get_service_keys(service, kid=kid) key = data.model.service_keys.get_service_key(kid)
return jsonify(key.jwk) return jsonify(key.jwk)
@ -94,7 +94,7 @@ def put_service_keys(service, kid):
if not encoded_jwt: if not encoded_jwt:
abort(400) abort(400)
signer_jwk = _signer_jwk(encoded_jwt, jwk, service, kid) signer_jwk = _signer_jwk(encoded_jwt, jwk, kid)
_validate_jwt(encoded_jwt, signer_jwk, service) _validate_jwt(encoded_jwt, signer_jwk, service)
metadata = { metadata = {
@ -104,7 +104,7 @@ def put_service_keys(service, kid):
try: try:
data.model.service_keys.update_service_key('', kid, service, metadata, expiration_date) data.model.service_keys.update_service_key('', kid, metadata, expiration_date)
except data.model.ServiceKeyDoesNotExist: except data.model.ServiceKeyDoesNotExist:
data.model.service_keys.create_service_key('', kid, service, jwk, metadata, expiration_date) data.model.service_keys.create_service_key('', kid, service, jwk, metadata, expiration_date)
@ -115,7 +115,7 @@ def delete_service_key(service, kid):
if not encoded_jwt: if not encoded_jwt:
abort(400) abort(400)
signer_jwk = _signer_jwk(encoded_jwt, None, service, kid) signer_jwk = _signer_jwk(encoded_jwt, None, kid)
_validate_jwt(encoded_jwt, signer_jwk, service) _validate_jwt(encoded_jwt, signer_jwk, service)
try: try: