keys ui WIP

This commit is contained in:
Joseph Schorr 2016-04-01 13:55:29 -04:00 committed by Jimmy Zelinskie
parent dc593c0197
commit 11ff3e9b59
25 changed files with 1154 additions and 74 deletions

View file

@ -694,9 +694,11 @@ class LogEntryKind(BaseModel):
name = CharField(index=True, unique=True)
_LogEntryAccountProxy = Proxy()
class LogEntry(BaseModel):
kind = ForeignKeyField(LogEntryKind, index=True)
account = QuayUserField(index=True, related_name='account')
account = ForeignKeyField(_LogEntryAccountProxy, index=True, null=True, related_name='account')
performer = QuayUserField(allows_robots=True, index=True, null=True,
related_name='performer', robot_null_delete=True)
repository = ForeignKeyField(Repository, index=True, null=True)
@ -715,6 +717,8 @@ class LogEntry(BaseModel):
(('repository', 'datetime', 'kind'), False),
)
_LogEntryAccountProxy.initialize(User)
class RepositoryActionCount(BaseModel):
repository = ForeignKeyField(Repository, index=True)
@ -875,12 +879,14 @@ class ServiceKeyApprovalType(Enum):
SUPERUSER = 'Super User API'
KEY_ROTATION = 'Key Rotation'
_ServiceKeyApproverProxy = Proxy()
class ServiceKeyApproval(BaseModel):
approver = ForeignKeyField(_ServiceKeyApproverProxy, null=True)
approval_type = CharField(index=True)
approved_date = DateTimeField(default=datetime.utcnow)
notes = TextField()
notes = TextField(default='')
_ServiceKeyApproverProxy.initialize(User)

View file

@ -103,4 +103,5 @@ config = Config()
# moving the minimal number of things to _basequery
# TODO document the methods and modules for each one of the submodules below.
from data.model import (blob, build, image, log, notification, oauth, organization, permission,
repository, storage, tag, team, token, user, release, modelutil)
repository, service_keys, storage, tag, team, token, user, release,
modelutil)

View file

@ -1,5 +1,6 @@
import json
from calendar import timegm
from peewee import JOIN_LEFT_OUTER, SQL, fn
from datetime import datetime, timedelta, date
from cachetools import lru_cache
@ -53,15 +54,33 @@ def get_logs_query(start_time, end_time, performer=None, repository=None, namesp
return query
def get_log_action_date(dtdata):
if dtdata is None:
return None
return
def _json_serialize(obj):
if isinstance(obj, datetime):
return timegm(obj.utctimetuple())
return obj
def log_action(kind_name, user_or_organization_name, performer=None, repository=None,
ip=None, metadata={}, timestamp=None):
if not timestamp:
timestamp = datetime.today()
account = None
if user_or_organization_name is not None:
account = User.get(User.username == user_or_organization_name).id
kind = LogEntryKind.get(LogEntryKind.name == kind_name)
account = User.get(User.username == user_or_organization_name)
metadata_json = json.dumps(metadata, default=_json_serialize)
LogEntry.create(kind=kind, account=account, performer=performer,
repository=repository, ip=ip, metadata_json=json.dumps(metadata),
repository=repository, ip=ip, metadata_json=metadata_json,
datetime=timestamp)

View file

@ -1,26 +1,21 @@
from calendar import timegm
from datetime import datetime, timedelta
from peewee import JOIN_LEFT_OUTER
from app import app
from data.database import db_for_update, User, ServiceKey, ServiceKeyApproval
from data.model import ServiceKeyDoesNotExist, ServiceKeyAlreadyApproved, db_transaction
from data.model import ServiceKeyDoesNotExist, ServiceKeyAlreadyApproved, db_transaction, config
from data.model.notification import create_notification, delete_all_notifications_by_path_prefix
# TODO ACTION_LOGS for keys
UNAPPROVED_TTL = timedelta(seconds=app.config['UNAPPROVED_SERVICE_KEY_TTL_SEC'])
def _expired_keys_clause(service):
return ((ServiceKey.service == service) &
(ServiceKey.expiration_date <= datetime.utcnow()))
def _stale_unapproved_keys_clause(service):
unapproved_ttl = timedelta(seconds=config.app_config['UNAPPROVED_SERVICE_KEY_TTL_SEC'])
return ((ServiceKey.service == service) &
(ServiceKey.approval >> None) &
(ServiceKey.created_date <= (datetime.utcnow() - UNAPPROVED_TTL)))
(ServiceKey.created_date <= (datetime.utcnow() - unapproved_ttl)))
def _gc_expired(service):
@ -36,10 +31,12 @@ def _notify_superusers(key):
'jwk': key.jwk,
'metadata': key.metadata,
'created_date': timegm(key.created_date.utctimetuple()),
'expiration_date': timegm(key.created_date.utctimetuple()),
}
superusers = User.select().where(User.username << app.config['SUPER_USERS'])
if key.expiration_date is not None:
notification_metadata['expiration_date'] = timegm(key.expiration_date.utctimetuple())
superusers = User.select().where(User.username << config.app_config['SUPER_USERS'])
for superuser in superusers:
create_notification('service_key_submitted', superuser, metadata=notification_metadata,
lookup_path='/service_key_approval/{0}'.format(key.kid))
@ -57,9 +54,11 @@ def replace_service_key(old_kid, kid, jwk, metadata, expiration_date):
try:
with db_transaction():
key = db_for_update(ServiceKey.select().where(ServiceKey.kid == old_kid)).get()
metadata = key.metadata.update(metadata)
key.metadata.update(metadata)
ServiceKey.create(name=key.name, kid=kid, service=key.service, jwk=jwk,
metadata=metadata, expiration_date=expiration_date, approval=key.approval)
metadata=key.metadata, expiration_date=expiration_date,
approval=key.approval)
key.delete_instance()
except ServiceKey.DoesNotExist:
raise ServiceKeyDoesNotExist
@ -69,13 +68,16 @@ def replace_service_key(old_kid, kid, jwk, metadata, expiration_date):
_gc_expired(key.service)
def update_service_key(name, kid, metadata, expiration_date):
def update_service_key(kid, name=None, metadata=None):
try:
with db_transaction():
key = db_for_update(ServiceKey.select().where(ServiceKey.kid == kid)).get()
key.name = name
key.metadata.update(metadata)
key.expiration_date = expiration_date
if name is not None:
key.name = name
if metadata is not None:
key.metadata.update(metadata)
key.save()
except ServiceKey.DoesNotExist:
raise ServiceKeyDoesNotExist
@ -83,15 +85,26 @@ def update_service_key(name, kid, metadata, expiration_date):
_gc_expired(key.service)
def delete_service_key(service, kid):
def delete_service_key(kid):
try:
ServiceKey.delete().where(ServiceKey.service == service,
ServiceKey.kid == kid).execute()
key = ServiceKey.get(kid=kid)
ServiceKey.delete().where(ServiceKey.kid == kid).execute()
except ServiceKey.DoesNotExist:
raise ServiceKeyDoesNotExist()
raise ServiceKeyDoesNotExist
delete_all_notifications_by_path_prefix('/service_key_approval/{0}'.format(kid))
_gc_expired(service)
_gc_expired(key.service)
return key
def set_key_expiration(kid, expiration_date):
try:
service_key = get_service_key(kid)
except ServiceKey.DoesNotExist:
raise ServiceKeyDoesNotExist
service_key.expiration_date = expiration_date
service_key.save()
def approve_service_key(kid, approver, approval_type, notes=''):
@ -129,7 +142,7 @@ def _list_service_keys_query(kid=None, service=None, approved_only=False):
return query
def list_keys():
def list_all_keys():
return list(_list_service_keys_query())