barbican/barbican/common/resources.py
Arvind Tiwari d864b87386 Extend crypto plugin to support more key types
This change is part of "api-orders-add-more-types" BP phase 1 plan.
As per phase 1 we will extend the order resource to support asymmetric
and more symmetric keys.
This specific change is to address the crypto plug-in and extension
manager.

Partial-BP: api-orders-add-more-types

Change-Id: Idf0073c0703dff652e55e811538f86a8f7c7259b
2014-05-13 14:17:59 -06:00

144 lines
5.3 KiB
Python

# Copyright (c) 2013-2014 Rackspace, Inc.
#
# 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.
"""
Shared business logic.
"""
from barbican.common import exception
from barbican.common import utils
from barbican.common import validators
from barbican.model import models
LOG = utils.getLogger(__name__)
def get_or_create_tenant(keystone_id, tenant_repo):
"""Returns tenant with matching keystone_id.
Creates it if it does not exist.
:param keystone_id: The external-to-Barbican ID for this tenant.
:param tenant_repo: Tenant repository.
:return: Tenant model instance
"""
tenant = tenant_repo.find_by_keystone_id(keystone_id,
suppress_exception=True)
if not tenant:
LOG.debug('Creating tenant for {0}'.format(keystone_id))
tenant = models.Tenant()
tenant.keystone_id = keystone_id
tenant.status = models.States.ACTIVE
tenant_repo.create_from(tenant)
return tenant
def create_secret(data, tenant, crypto_manager,
secret_repo, tenant_secret_repo, datum_repo, kek_repo,
ok_to_generate=False):
"""Common business logic to create a secret."""
time_keeper = utils.TimeKeeper('Create Secret Resource')
new_secret = models.Secret(data)
time_keeper.mark('after Secret model create')
new_datum = None
content_type = data.get('payload_content_type',
'application/octet-stream')
if 'payload' in data:
payload = data.get('payload')
content_encoding = data.get('payload_content_encoding')
LOG.debug('Encrypting payload...')
new_datum = crypto_manager.encrypt(payload,
content_type,
content_encoding,
new_secret,
tenant,
kek_repo,
enforce_text_only=True)
time_keeper.mark('after encrypt')
elif ok_to_generate:
LOG.debug('Generating new secret...')
# TODO (atiwari): With new typed Order API proposal
# we need to translate new_secret to meta
# currently it is working as meta will have same attributes
new_datum = crypto_manager. \
generate_symmetric_encryption_key(new_secret,
content_type,
tenant,
kek_repo)
time_keeper.mark('after secret generate')
else:
LOG.debug('Creating metadata only for the new secret. '
'A subsequent PUT is required')
# Create Secret entities in datastore.
secret_repo.create_from(new_secret)
time_keeper.mark('after Secret datastore create')
new_assoc = models.TenantSecret()
time_keeper.mark('after TenantSecret model create')
new_assoc.tenant_id = tenant.id
new_assoc.secret_id = new_secret.id
new_assoc.role = "admin"
new_assoc.status = models.States.ACTIVE
tenant_secret_repo.create_from(new_assoc)
time_keeper.mark('after TenantSecret datastore create')
if new_datum:
new_datum.secret_id = new_secret.id
datum_repo.create_from(new_datum)
time_keeper.mark('after Datum datastore create')
time_keeper.dump()
return new_secret
def create_encrypted_datum(secret, payload,
content_type, content_encoding,
tenant, crypto_manager, datum_repo, kek_repo):
"""Modifies the secret to add the plain_text secret information.
:param secret: the secret entity to associate the secret data to
:param payload: secret data to store
:param content_type: payload content mime type
:param content_encoding: payload content encoding
:param tenant: the tenant (entity) who owns the secret
:param crypto_manager: the crypto plugin manager
:param datum_repo: the encrypted datum repository
:param kek_repo: the KEK metadata repository
:retval The response body, None if N/A
"""
if not payload:
raise exception.NoDataToProcess()
if validators.secret_too_big(payload):
raise exception.LimitExceeded()
if secret.encrypted_data:
raise ValueError('Secret already has encrypted data stored for it.')
# Encrypt payload
LOG.debug('Encrypting secret payload...')
new_datum = crypto_manager.encrypt(payload,
content_type,
content_encoding,
secret,
tenant,
kek_repo)
datum_repo.create_from(new_datum)
return new_datum