service keys: add rotation_duration field
This commit is contained in:
parent
6577ac3e62
commit
370ac3ecd0
5 changed files with 21 additions and 46 deletions
|
@ -898,6 +898,7 @@ class ServiceKey(BaseModel):
|
||||||
metadata = JSONField()
|
metadata = JSONField()
|
||||||
created_date = DateTimeField(default=datetime.utcnow)
|
created_date = DateTimeField(default=datetime.utcnow)
|
||||||
expiration_date = DateTimeField(null=True)
|
expiration_date = DateTimeField(null=True)
|
||||||
|
rotation_duration = IntegerField(null=True)
|
||||||
approval = ForeignKeyField(ServiceKeyApproval, index=True, null=True)
|
approval = ForeignKeyField(ServiceKeyApproval, index=True, null=True)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -31,8 +31,7 @@ def upgrade(tables):
|
||||||
[{'name':'service_key_submitted'}],
|
[{'name':'service_key_submitted'}],
|
||||||
)
|
)
|
||||||
|
|
||||||
op.bulk_insert(tables.logentrykind,
|
op.bulk_insert(tables.logentrykind, [
|
||||||
[
|
|
||||||
{'name':'service_key_create'},
|
{'name':'service_key_create'},
|
||||||
{'name':'service_key_approve'},
|
{'name':'service_key_approve'},
|
||||||
{'name':'service_key_delete'},
|
{'name':'service_key_delete'},
|
||||||
|
@ -53,6 +52,7 @@ def upgrade(tables):
|
||||||
sa.Column('metadata', UTF8LongText(), nullable=False),
|
sa.Column('metadata', UTF8LongText(), nullable=False),
|
||||||
sa.Column('created_date', sa.DateTime(), nullable=False),
|
sa.Column('created_date', sa.DateTime(), nullable=False),
|
||||||
sa.Column('expiration_date', sa.DateTime(), nullable=True),
|
sa.Column('expiration_date', sa.DateTime(), nullable=True),
|
||||||
|
sa.Column('rotation_duration', sa.Integer(), nullable=True),
|
||||||
sa.Column('approval_id', sa.Integer(), nullable=True),
|
sa.Column('approval_id', sa.Integer(), nullable=True),
|
||||||
sa.ForeignKeyConstraint(['approval_id'], ['servicekeyapproval.id'],
|
sa.ForeignKeyConstraint(['approval_id'], ['servicekeyapproval.id'],
|
||||||
name=op.f('fk_servicekey_approval_id_servicekeyapproval')),
|
name=op.f('fk_servicekey_approval_id_servicekeyapproval')),
|
||||||
|
@ -70,35 +70,12 @@ def upgrade(tables):
|
||||||
|
|
||||||
|
|
||||||
def downgrade(tables):
|
def downgrade(tables):
|
||||||
op.execute(
|
op.execute(tables.logentrykind.delete().where(tables.logentrykind.c.name == op.inline_literal('service_key_create')))
|
||||||
(tables.logentrykind.delete()
|
op.execute(tables.logentrykind.delete().where(tables.logentrykind.c.name == op.inline_literal('service_key_approve')))
|
||||||
.where(tables.logentrykind.c.name == op.inline_literal('service_key_create')))
|
op.execute(tables.logentrykind.delete().where(tables.logentrykind.c.name == op.inline_literal('service_key_delete')))
|
||||||
)
|
op.execute(tables.logentrykind.delete().where(tables.logentrykind.c.name == op.inline_literal('service_key_modify')))
|
||||||
|
op.execute(tables.logentrykind.delete().where(tables.logentrykind.c.name == op.inline_literal('service_key_extend')))
|
||||||
op.execute(
|
op.execute(tables.logentrykind.delete().where(tables.logentrykind.c.name == op.inline_literal('service_key_rotate')))
|
||||||
(tables.logentrykind.delete()
|
|
||||||
.where(tables.logentrykind.c.name == op.inline_literal('service_key_approve')))
|
|
||||||
)
|
|
||||||
|
|
||||||
op.execute(
|
|
||||||
(tables.logentrykind.delete()
|
|
||||||
.where(tables.logentrykind.c.name == op.inline_literal('service_key_delete')))
|
|
||||||
)
|
|
||||||
|
|
||||||
op.execute(
|
|
||||||
(tables.logentrykind.delete()
|
|
||||||
.where(tables.logentrykind.c.name == op.inline_literal('service_key_modify')))
|
|
||||||
)
|
|
||||||
|
|
||||||
op.execute(
|
|
||||||
(tables.logentrykind.delete()
|
|
||||||
.where(tables.logentrykind.c.name == op.inline_literal('service_key_extend')))
|
|
||||||
)
|
|
||||||
|
|
||||||
op.execute(
|
|
||||||
(tables.logentrykind.delete()
|
|
||||||
.where(tables.logentrykind.c.name == op.inline_literal('service_key_rotate')))
|
|
||||||
)
|
|
||||||
|
|
||||||
op.drop_column(u'notification', 'lookup_path')
|
op.drop_column(u'notification', 'lookup_path')
|
||||||
op.drop_table('servicekey')
|
op.drop_table('servicekey')
|
||||||
|
|
|
@ -47,9 +47,9 @@ def _notify_superusers(key):
|
||||||
lookup_path='/service_key_approval/{0}/{1}'.format(key.kid, superuser.id))
|
lookup_path='/service_key_approval/{0}/{1}'.format(key.kid, superuser.id))
|
||||||
|
|
||||||
|
|
||||||
def create_service_key(name, kid, service, jwk, metadata, expiration_date):
|
def create_service_key(name, kid, service, jwk, metadata, expiration_date, rotation_duration=None):
|
||||||
key = ServiceKey.create(name=name, kid=kid, service=service, jwk=jwk, metadata=metadata,
|
key = ServiceKey.create(name=name, kid=kid, service=service, jwk=jwk, metadata=metadata,
|
||||||
expiration_date=expiration_date)
|
expiration_date=expiration_date, rotation_duration=rotation_duration)
|
||||||
|
|
||||||
_notify_superusers(key)
|
_notify_superusers(key)
|
||||||
_gc_expired(service)
|
_gc_expired(service)
|
||||||
|
@ -75,7 +75,7 @@ def replace_service_key(old_kid, kid, jwk, metadata, expiration_date):
|
||||||
|
|
||||||
ServiceKey.create(name=key.name, kid=kid, service=key.service, jwk=jwk,
|
ServiceKey.create(name=key.name, kid=kid, service=key.service, jwk=jwk,
|
||||||
metadata=key.metadata, expiration_date=expiration_date,
|
metadata=key.metadata, expiration_date=expiration_date,
|
||||||
approval=key.approval)
|
rotation_duration=key.rotation_duration, approval=key.approval)
|
||||||
key.delete_instance()
|
key.delete_instance()
|
||||||
except ServiceKey.DoesNotExist:
|
except ServiceKey.DoesNotExist:
|
||||||
raise ServiceKeyDoesNotExist
|
raise ServiceKeyDoesNotExist
|
||||||
|
|
|
@ -95,6 +95,7 @@ def get_service_key(service, kid):
|
||||||
def put_service_key(service, kid):
|
def put_service_key(service, kid):
|
||||||
metadata = {'ip': request.remote_addr}
|
metadata = {'ip': request.remote_addr}
|
||||||
|
|
||||||
|
rotation_duration = request.args.get('rotation', None)
|
||||||
expiration_date = request.args.get('expiration', None)
|
expiration_date = request.args.get('expiration', None)
|
||||||
if expiration_date is not None:
|
if expiration_date is not None:
|
||||||
try:
|
try:
|
||||||
|
@ -103,10 +104,6 @@ def put_service_key(service, kid):
|
||||||
logger.exception('Error parsing expiration date on key')
|
logger.exception('Error parsing expiration date on key')
|
||||||
abort(400)
|
abort(400)
|
||||||
|
|
||||||
rotation_ttl = request.args.get('rotation', None)
|
|
||||||
if rotation_ttl is not None:
|
|
||||||
metadata['rotation_ttl'] = rotation_ttl
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
jwk = request.get_json()
|
jwk = request.get_json()
|
||||||
except ValueError:
|
except ValueError:
|
||||||
|
@ -128,7 +125,8 @@ def put_service_key(service, kid):
|
||||||
if kid == signer_kid or signer_kid is None:
|
if kid == signer_kid or signer_kid is None:
|
||||||
# The key is self-signed. Create a new instance and await approval.
|
# The key is self-signed. Create a new instance and await approval.
|
||||||
_validate_jwt(encoded_jwt, jwk, service)
|
_validate_jwt(encoded_jwt, jwk, service)
|
||||||
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,
|
||||||
|
rotation_duration=rotation_duration)
|
||||||
|
|
||||||
key_log_metadata = {
|
key_log_metadata = {
|
||||||
'kid': kid,
|
'kid': kid,
|
||||||
|
|
|
@ -28,7 +28,6 @@ from data.queue import WorkQueue
|
||||||
from app import app, storage as store, tf
|
from app import app, storage as store, tf
|
||||||
from storage.basestorage import StoragePaths
|
from storage.basestorage import StoragePaths
|
||||||
from endpoints.v2.manifest import _generate_and_store_manifest
|
from endpoints.v2.manifest import _generate_and_store_manifest
|
||||||
from util import canonicalize
|
|
||||||
|
|
||||||
|
|
||||||
from workers import repositoryactioncounter
|
from workers import repositoryactioncounter
|
||||||
|
|
Reference in a new issue