Adds SecretMetadatum table

This patch is the first planned in a series to add KMIP support to Barbican.
Barbican currently returns metadata about secrets to the user, but adding
secret_metadata table will allow users to set additional metadata options
that are not supported by Barbican.

After this submission is accepted, another patch will be created to move the
current Secret attribute metadata to the new metadata table.

Change-Id: Ibc990f798b118eeda705360e40ecf439d5a1b0cd
Implements: blueprint add-metadata-to-secrets
This commit is contained in:
Kaitlin Farr 2014-04-29 11:15:39 -04:00
parent 0494edc559
commit 6966018eaa
2 changed files with 105 additions and 7 deletions

View File

@ -0,0 +1,51 @@
# Copyright (c) 2014 The Johns Hopkins University/Applied Physics Laboratory
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
"""create_secret_metadata_table
Revision ID: 13d127569afa
Revises: 1a0c2cdafb38
Create Date: 2014-04-24 13:15:41.858266
"""
# revision identifiers, used by Alembic.
revision = '13d127569afa'
down_revision = '1a0c2cdafb38'
from alembic import op
import sqlalchemy as sa
def upgrade():
meta = sa.MetaData()
meta.reflect(bind=rep._ENGINE, only=['secret_metadata'])
if 'secret_metadata' not in meta.tables.keys():
op.create_table('secret_metadata',
sa.Column('id', sa.String(length=36), nullable=False),
sa.Column('created_at', sa.DateTime(), nullable=False),
sa.Column('updated_at', sa.DateTime(), nullable=False),
sa.Column('deleted_at', sa.DateTime(), nullable=True),
sa.Column('deleted', sa.Boolean(), nullable=False),
sa.Column('status', sa.String(length=20), nullable=False),
sa.Column('secret_id', sa.String(length=36), nullable=False),
sa.Column('key', sa.String(length=255), nullable=False),
sa.Column('value', sa.String(length=255), nullable=False),
sa.ForeignKeyConstraint(['secret_id'], ['secrets.id'],),
sa.PrimaryKeyConstraint('id'),
)
def downgrade():
op.drop_table('secret_metadata')

View File

@ -21,6 +21,7 @@ from sqlalchemy.ext import compiler
from sqlalchemy.ext import declarative
from sqlalchemy import orm
from barbican.common import exception
from barbican.common import utils
from barbican.openstack.common import timeutils
@ -216,6 +217,7 @@ class Secret(BASE, ModelBase):
# metadata is retrieved.
# See barbican.api.resources.py::SecretsResource.on_get()
encrypted_data = orm.relationship("EncryptedDatum", lazy='joined')
secret_metadata = orm.relationship("SecretMetadatum", lazy='joined')
def __init__(self, parsed_request=None):
"""Creates secret from a dict."""
@ -232,6 +234,9 @@ class Secret(BASE, ModelBase):
def _do_delete_children(self, session):
"""Sub-class hook: delete children relationships."""
for datum in self.secret_metadata:
datum.delete(session)
for datum in self.encrypted_data:
datum.delete(session)
@ -240,16 +245,58 @@ class Secret(BASE, ModelBase):
def _do_extra_dict_fields(self):
"""Sub-class hook method: return dict of fields."""
return {'secret_id': self.id,
'name': self.name or self.id,
'expiration': self.expiration,
'algorithm': self.algorithm,
'bit_length': self.bit_length,
'mode': self.mode}
fields = {'secret_id': self.id,
'name': self.name or self.id,
'expiration': self.expiration,
'algorithm': self.algorithm,
'bit_length': self.bit_length,
'mode': self.mode}
#TODO(kaitlin.farr) will change implementation to avoid overwriting
# existing fields in a future patch
for m in self.secret_metadata:
metadata_field = m._do_extra_dict_fields()
fields.update({metadata_field['key']: metadata_field['value']})
return fields
class SecretMetadatum(BASE, ModelBase):
"""Represents the metadatum for a single key-value pair for a Secret"""
__tablename__ = "secret_metadata"
secret_id = sa.Column(sa.String(36), sa.ForeignKey('secrets.id'),
nullable=False)
key = sa.Column(sa.String(255), nullable=False)
value = sa.Column(sa.String(255), nullable=False)
def __init__(self, secret, key, value):
super(SecretMetadatum, self).__init__()
msg = ("Must supply non-None {0} argument for SecretMetadatum entry.")
if secret is None:
raise exception.MissingArgumentError(msg.format("secret"))
else:
self.secret_id = secret.id
if key is None:
raise exception.MissingArgumentError(msg.format("key"))
else:
self.key = key
if value is None:
raise exception.MissingArgumentError(msg.format("value"))
else:
self.value = value
def _do_extra_dict_fields(self):
"""Sub-class hook method: return dict of fields."""
return {'key': self.key,
'value': self.value}
class EncryptedDatum(BASE, ModelBase):
"""Represents a the encrypted data for a Secret."""
"""Represents the encrypted data for a Secret."""
__tablename__ = 'encrypted_data'