Making a few MORE modules hacking 0.9.2 compliant

Global requirements has updating the version of hacking to a minimum of
0.9.2 and it has brought a whole slew of changes. This is tackling most
of the controllers, middleware, common code, and plugins (excluding
Symantec and kmip)

Change-Id: I8ee9713842be76d1f4be4abb2349105f1c020fdb
This commit is contained in:
Adam Harwell 2014-08-27 21:47:36 -05:00
parent 7fcf415515
commit 5240acee9b
23 changed files with 208 additions and 179 deletions

View File

@ -16,9 +16,10 @@
"""
API handler for Cloudkeep's Barbican
"""
import pkgutil
from oslo.config import cfg
import pecan
import pkgutil
from barbican.common import exception
from barbican.common import utils
@ -47,6 +48,7 @@ class ApiResource(object):
def load_body(req, resp=None, validator=None):
"""Helper function for loading an HTTP request body from JSON.
This body is placed into into a Python dictionary.
:param req: The HTTP request instance to load the body from.
@ -61,7 +63,7 @@ def load_body(req, resp=None, validator=None):
pecan.abort(500, 'Read Error')
try:
#TODO(jwood): Investigate how to get UTF8 format via openstack
# TODO(jwood): Investigate how to get UTF8 format via openstack
# jsonutils:
# parsed_body = json.loads(raw_json, 'utf-8')
parsed_body = json.loads(body)
@ -169,9 +171,9 @@ def generate_safe_exception_message(operation_name, excep):
@pkgutil.simplegeneric
def get_items(obj):
"""This is used to get items from either
a list or a dictionary. While false
generator is need to process scalar object
"""This is used to get items from either a list or a dictionary.
While false generator is need to process scalar object
"""
while False:
@ -189,9 +191,7 @@ def _json_array(obj):
def strip_whitespace(json_data):
"""This function will recursively trim values from the
object passed in using the get_items
"""
"""Recursively trim values from the object passed in using get_items()."""
for key, value in get_items(json_data):
if hasattr(value, 'strip'):

View File

@ -109,7 +109,9 @@ def handle_exceptions(operation_name=u._('System')):
def _do_enforce_content_types(pecan_req, valid_content_types):
"""Check to see that content type in the request is one of the valid
"""Content type enforcement
Check to see that content type in the request is one of the valid
types passed in by our caller.
"""
if pecan_req.content_type not in valid_content_types:

View File

@ -133,8 +133,9 @@ class ContainerConsumersController(object):
new_consumer.tenant_id = tenant.id
self.consumer_repo.create_from(new_consumer)
pecan.response.headers['Location'] = '/{0}/containers/{1}/consumers' \
.format(keystone_id, new_consumer.container_id)
pecan.response.headers['Location'] = (
'/containers/{0}/consumers'.format(new_consumer.container_id)
)
return self._return_container_data(self.container_id, keystone_id)

View File

@ -38,7 +38,7 @@ class ContainerController(object):
def __init__(self, container_id, tenant_repo=None, container_repo=None,
consumer_repo=None):
#TODO(rm_work): refactor this to use repo-factory method
# TODO(rm_work): refactor this to use repo-factory method
self.container_id = container_id
self.tenant_repo = tenant_repo or repo.TenantRepo()
self.container_repo = container_repo or repo.ContainerRepo()
@ -86,7 +86,7 @@ class ContainersController(object):
def __init__(self, tenant_repo=None, container_repo=None,
secret_repo=None, consumer_repo=None):
#TODO(rm_work): refactor this to use repo-factory method
# TODO(rm_work): refactor this to use repo-factory method
self.tenant_repo = tenant_repo or repo.TenantRepo()
self.container_repo = container_repo or repo.ContainerRepo()
self.secret_repo = secret_repo or repo.SecretRepo()
@ -152,7 +152,7 @@ class ContainersController(object):
new_container = models.Container(data)
new_container.tenant_id = tenant.id
#TODO(hgedikli): performance optimizations
# TODO(hgedikli): performance optimizations
for secret_ref in new_container.container_secrets:
secret = self.secret_repo.get(entity_id=secret_ref.secret_id,
keystone_id=keystone_id,
@ -166,8 +166,8 @@ class ContainersController(object):
self.container_repo.create_from(new_container)
pecan.response.status = 201
pecan.response.headers['Location'] = '/{0}/containers/{1}'.format(
keystone_id, new_container.id
pecan.response.headers['Location'] = '/containers/{0}'.format(
new_container.id
)
url = hrefs.convert_container_to_href(new_container.id)
return {'container_ref': url}

View File

@ -174,11 +174,9 @@ class OrdersController(object):
LOG.debug('Start orders on_get '
'for tenant-ID %s:', keystone_id)
result = self.order_repo \
.get_by_create_date(keystone_id,
offset_arg=kw.get('offset', 0),
limit_arg=kw.get('limit', None),
suppress_exception=True)
result = self.order_repo.get_by_create_date(
keystone_id, offset_arg=kw.get('offset', 0),
limit_arg=kw.get('limit', None), suppress_exception=True)
orders, offset, limit, total = result
if not orders:
@ -210,8 +208,8 @@ class OrdersController(object):
tenant = res.get_or_create_tenant(keystone_id, self.tenant_repo)
#Note(atiwari): trying to preserve backward compatibility
#This will be removed as part of bug1335171
# Note(atiwari): trying to preserve backward compatibility
# This will be removed as part of bug1335171
raw_body = pecan.request.body
order_type = None
if raw_body:
@ -225,7 +223,7 @@ class OrdersController(object):
new_order.meta = body.get('meta')
new_order.type = order_type
#TODO(john-wood-w) These are required attributes currently, but
# TODO(john-wood-w) These are required attributes currently, but
# will eventually be removed once we drop the legacy orders
# request.
new_order.secret_name = 'N/A'
@ -257,7 +255,7 @@ class OrdersController(object):
self.order_repo.create_from(new_order)
# Send to workers to process.
#TODO(atiwari) - bug 1335171
# TODO(atiwari) - bug 1335171
if order_type:
self.queue.process_type_order(order_id=new_order.id,
keystone_id=keystone_id)

View File

@ -71,7 +71,7 @@ class SecretController(object):
LOG.debug('=== Creating SecretController ===')
self.secret_id = secret_id
#TODO(john-wood-w) Remove passed-in repositories in favor of
# TODO(john-wood-w) Remove passed-in repositories in favor of
# repository factories and patches in unit tests.
self.repos = repo.Repositories(tenant_repo=tenant_repo,
secret_repo=secret_repo,
@ -215,6 +215,9 @@ class SecretsController(object):
@controllers.handle_exceptions(u._('Secret(s) retrieval'))
@controllers.enforce_rbac('secrets:get')
def index(self, keystone_id, **kw):
def secret_fields(field):
return putil.mime_types.augment_fields_with_content_types(field)
LOG.debug('Start secrets on_get '
'for tenant-ID %s:', keystone_id)
@ -247,8 +250,6 @@ class SecretsController(object):
secrets_resp_overall = {'secrets': [],
'total': total}
else:
secret_fields = lambda sf: putil.mime_types\
.augment_fields_with_content_types(sf)
secrets_resp = [
hrefs.convert_to_hrefs(secret_fields(s))
for s in secrets

View File

@ -17,6 +17,7 @@
Barbican middleware modules.
"""
import sys
import webob.dec
from barbican.common import utils
@ -25,7 +26,9 @@ LOG = utils.getLogger(__name__)
class Middleware(object):
"""Base WSGI middleware wrapper. These classes require an application to be
"""Base WSGI middleware wrapper
These classes require an application to be
initialized that will be called next. By default the middleware will
simply call its wrapped app, or you can override __call__ to customize its
behavior.
@ -66,7 +69,9 @@ class Middleware(object):
# Brought over from an OpenStack project
class Debug(Middleware):
"""Helper class that can be inserted into any WSGI application chain
"""Debug helper class
This class can be inserted into any WSGI application chain
to get information about the request and response.
"""
@ -89,9 +94,7 @@ class Debug(Middleware):
@staticmethod
def print_generator(app_iter):
"""Iterator that prints the contents of a wrapper string iterator
when iterated.
"""
"""Iterator that prints the contents of a wrapper string iterator."""
LOG.debug(("*" * 40) + " BODY")
for part in app_iter:
sys.stdout.write(part)

View File

@ -14,11 +14,10 @@
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import json
import webob.exc
from oslo.config import cfg
import webob.exc
from barbican.api import middleware as mw
from barbican.common import utils
@ -103,13 +102,13 @@ class ContextMiddleware(BaseContextMiddleware):
return barbican.context.RequestContext(**kwargs)
def _get_authenticated_context(self, req):
#NOTE(bcwaldon): X-Roles is a csv string, but we need to parse
# NOTE(bcwaldon): X-Roles is a csv string, but we need to parse
# it into a list to be useful
roles_header = req.headers.get('X-Roles', '')
roles = [r.strip().lower() for r in roles_header.split(',')]
#NOTE(bcwaldon): This header is deprecated in favor of X-Auth-Token
#(mkbhanda) keeping this just-in-case for swift
# NOTE(bcwaldon): This header is deprecated in favor of X-Auth-Token
# NOTE(mkbhanda): keeping this just-in-case for swift
deprecated_token = req.headers.get('X-Storage-Token')
service_catalog = None

View File

@ -121,7 +121,7 @@ class ProtectedImageDelete(Forbidden):
message = u._("Image %(image_id)s is protected and cannot be deleted.")
#NOTE(bcwaldon): here for backwards-compatibility, need to deprecate.
# NOTE(bcwaldon): here for backwards-compatibility, need to deprecate.
class NotAuthorized(Forbidden):
message = u._("You are not authorized to complete this action.")

View File

@ -49,7 +49,7 @@ def convert_transport_key_to_href(transport_key_id):
return utils.hostname_for_refs(resource=resource)
#TODO(hgedikli) handle list of fields in here
# TODO(hgedikli) handle list of fields in here
def convert_to_hrefs(fields):
"""Convert id's within a fields dict to HATEOS-style hrefs."""
if 'secret_id' in fields:

View File

@ -121,7 +121,9 @@ def generate_fullname_for(instance):
class TimeKeeper(object):
"""Keeps track of elapsed times and then allows for dumping a summary to
"""TimeKeeper object
Keeps track of elapsed times and then allows for dumping a summary to
logs. This class can be used to profile a method as a fine grain level.
"""
@ -133,9 +135,9 @@ class TimeKeeper(object):
self.elapsed = []
def mark(self, note=None):
"""Mark a moment in time, with an optional note as to what is
occurring at the time.
:param note: Optional note
"""Mark a moment in time, with an optional note
:param note: Optional note about what is occurring at this time
"""
time_curr = time.time()
self.elapsed.append((time_curr, time_curr - self.time_last, note))

View File

@ -70,7 +70,9 @@ class ValidatorBase(object):
"""
def _full_name(self, parent_schema=None):
"""Returns the full schema name for this validator,
"""Validator schema name accessor
Returns the full schema name for this validator,
including parent name.
"""
schema_name = self.name
@ -80,8 +82,7 @@ class ValidatorBase(object):
return schema_name
def _assert_schema_is_valid(self, json_data, schema_name):
"""Assert that the JSON structure is valid according to the given
schema.
"""Assert that the JSON structure is valid for the given schema.
:raises: InvalidObject exception if the data is not schema compliant.
"""
@ -190,8 +191,9 @@ class NewSecretValidator(ValidatorBase):
return expiration
def _assert_expiration_is_valid(self, expiration, schema_name):
"""Asserts that the given expiration date is valid. Which means that
it should not be in the past.
"""Asserts that the given expiration date is valid.
Expiration dates must be in the future, not the past.
"""
if expiration:
# Verify not already expired.
@ -202,7 +204,9 @@ class NewSecretValidator(ValidatorBase):
def _validate_content_parameters(self, content_type, content_encoding,
schema_name):
"""Check that the content_type, content_encoding and the parameters
"""Content parameter validator.
Check that the content_type, content_encoding and the parameters
that they affect are valid.
"""
self._assert_validity(
@ -247,7 +251,7 @@ class NewSecretValidator(ValidatorBase):
return payload.strip()
#TODO(atiwari) - Split this validator module and unit tests
# TODO(atiwari) - Split this validator module and unit tests
# into smaller modules
class TypeOrderValidator(ValidatorBase):
"""Validate a new typed order."""
@ -274,7 +278,7 @@ class TypeOrderValidator(ValidatorBase):
property=get_invalid_property(e))
order_type = json_data.get('type').lower()
#Note(atiwari): No support for certificate so far
# Note(atiwari): No support for certificate so far
if order_type == models.OrderType.CERTIFICATE:
certificate_meta = json_data.get('meta')
self._validate_certificate_meta(certificate_meta, schema_name)
@ -292,7 +296,7 @@ class TypeOrderValidator(ValidatorBase):
return json_data
def _validate_key_meta(self, key_meta, schema_name):
"""validation specific to meta for key type order"""
"""Validation specific to meta for key type order."""
self._assert_validity(key_meta is not None,
schema_name,
@ -308,8 +312,8 @@ class TypeOrderValidator(ValidatorBase):
# Validation secret generation related fields.
# TODO(jfwood): Invoke the crypto plugin for this purpose
if key_meta.get('payload_content_type', '').lower() !=\
'application/octet-stream':
if (key_meta.get('payload_content_type', '').lower() !=
'application/octet-stream'):
raise exception.UnsupportedField(field='payload_content_type',
schema=schema_name,
reason=u._("Only 'application/oc"
@ -331,14 +335,14 @@ class TypeOrderValidator(ValidatorBase):
self._validate_bit_length(key_meta, schema_name)
def _validate_asymmetric_meta(self, asymmetric_meta, schema_name):
"""validation specific to meta for asymmetric type order"""
"""Validation specific to meta for asymmetric type order."""
self._assert_validity(asymmetric_meta is not None,
schema_name,
u._("'meta' attributes is required"), "meta")
self._raise_feature_not_implemented('asymmetric', schema_name)
def _validate_certificate_meta(self, certificate_meta, schema_name):
"""validation specific to meta for certificate type order"""
"""Validation specific to meta for certificate type order."""
self._assert_validity(certificate_meta is not None,
schema_name,
u._("'meta' attributes is required"), "meta")
@ -388,7 +392,7 @@ class TypeOrderValidator(ValidatorBase):
.format(order_type))
#TODO(atiwari) - Remove this Validator for bug 1335171
# TODO(atiwari) - Remove this Validator for bug 1335171
class NewOrderValidator(ValidatorBase):
"""Validate a new order."""
@ -455,7 +459,7 @@ class NewOrderValidator(ValidatorBase):
class ContainerConsumerValidator(ValidatorBase):
""" Validate a Consumer"""
"""Validate a Consumer."""
def __init__(self):
self.name = 'Consumer'
@ -476,7 +480,7 @@ class ContainerConsumerValidator(ValidatorBase):
class ContainerValidator(ValidatorBase):
""" Validator for all types of Container"""
"""Validator for all types of Container."""
def __init__(self):
self.name = 'Container'
@ -486,7 +490,7 @@ class ContainerValidator(ValidatorBase):
"name": {"type": "string"},
"type": {
"type": "string",
# TODO: (hgedikli) move this to a common location
# TODO(hgedikli): move this to a common location
"enum": ["generic", "rsa", "certificate"]
},
"secret_refs": {

View File

@ -10,11 +10,9 @@
# implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import abc
from oslo.config import cfg
import six
from barbican.common import exception
@ -67,7 +65,7 @@ class CryptoPrivateKeyFailureException(exception.BarbicanException):
)
#TODO(john-wood-w) Need to harmonize these lower-level constants with the
# TODO(john-wood-w) Need to harmonize these lower-level constants with the
# higher level constants in secret_store.py.
class PluginSupportTypes(object):
"""Class to hold the type enumeration that plugins may support."""
@ -84,7 +82,9 @@ class PluginSupportTypes(object):
class KEKMetaDTO(object):
"""Key Encryption Keys (KEKs) in Barbican are intended to represent a
"""Key Encryption Key Meta DTO
Key Encryption Keys (KEKs) in Barbican are intended to represent a
distinct key that is used to perform encryption on secrets for a particular
project (tenant).
@ -140,9 +140,9 @@ class KEKMetaDTO(object):
"""
def __init__(self, kek_datum):
"""kek_datum is typically a barbican.model.models.EncryptedDatum
instance. Plugins should never have to create their own instance of
this class.
"""Plugins should not have to create their own instance of this class.
kek_datum is typically a barbican.model.models.EncryptedDatum instance.
"""
self.kek_label = kek_datum.kek_label
self.plugin_name = kek_datum.plugin_name
@ -153,7 +153,9 @@ class KEKMetaDTO(object):
class GenerateDTO(object):
"""Data Transfer Object used to pass all the necessary data for the plugin
"""Secret Generation DTO
Data Transfer Object used to pass all the necessary data for the plugin
to generate a secret on behalf of the user.
.. attribute:: generation_type
@ -195,7 +197,9 @@ class ResponseDTO(object):
class DecryptDTO(object):
"""Data Transfer Object used to pass all the necessary data for the plugin
"""Secret Decryption DTO
Data Transfer Object used to pass all the necessary data for the plugin
to perform decryption of a secret.
Currently, this DTO only contains the data produced by the plugin during
@ -216,7 +220,9 @@ class DecryptDTO(object):
class EncryptDTO(object):
"""Data Transfer Object used to pass all the necessary data for the plugin
"""Secret Encryption DTO
Data Transfer Object used to pass all the necessary data for the plugin
to perform encryption of a secret.
Currently, this DTO only contains the raw bytes to be encrypted by the
@ -233,9 +239,10 @@ class EncryptDTO(object):
@six.add_metaclass(abc.ABCMeta)
class CryptoPluginBase(object):
"""Base class for all Crypto plugins. Implementations of this abstract
base class will be used by Barbican to perform cryptographic operations on
secrets.
"""Base class for all Crypto plugins.
Implementations of this abstract base class will be used by Barbican to
perform cryptographic operations on secrets.
Barbican requests operations by invoking the methods on an instance of the
implementing class. Barbican's plugin manager handles the life-cycle of
@ -243,10 +250,12 @@ class CryptoPluginBase(object):
persist the data that is assigned to these DTOs by the plugin.
"""
#TODO(atiwari): fix 1331815
# TODO(atiwari): fix 1331815
@abc.abstractmethod
def encrypt(self, encrypt_dto, kek_meta_dto, keystone_id):
"""This method will be called by Barbican when requesting an encryption
"""Encryption handler function
This method will be called by Barbican when requesting an encryption
operation on a secret on behalf of a project (tenant).
:param encrypt_dto: :class:`EncryptDTO` instance containing the raw
@ -300,7 +309,9 @@ class CryptoPluginBase(object):
@abc.abstractmethod
def bind_kek_metadata(self, kek_meta_dto):
"""Bind a key encryption key (KEK) metadata to the sub-system
"""Key Encryption Key Metadata binding function
Bind a key encryption key (KEK) metadata to the sub-system
handling encryption/decryption, updating information about the
key encryption key (KEK) metadata in the supplied 'kek_metadata'
data-transfer-object instance, and then returning this instance.
@ -357,7 +368,7 @@ class CryptoPluginBase(object):
"""
raise NotImplementedError # pragma: no cover
#TODO(atiwari): fix 1331815
# TODO(atiwari): fix 1331815
@abc.abstractmethod
def supports(self, type_enum, algorithm=None, bit_length=None,
mode=None):

View File

@ -24,7 +24,9 @@ CONF = cfg.CONF
class _CryptoPluginManager(named.NamedExtensionManager):
def __init__(self, conf=CONF, invoke_on_load=True,
invoke_args=(), invoke_kwargs={}):
"""Each time this class is initialized it will load a new instance
"""Crypto Plugin Manager
Each time this class is initialized it will load a new instance
of each enabled crypto plugin. This is undesirable, so rather than
initializing a new instance of this class use the PLUGIN_MANAGER
at the module level.

View File

@ -21,10 +21,9 @@ import base64
from oslo.config import cfg
from barbican.common import exception
from barbican.plugin.crypto import crypto as plugin
from barbican.openstack.common import gettextutils as u
from barbican.openstack.common import jsonutils as json
from barbican.plugin.crypto import crypto as plugin
CONF = cfg.CONF
@ -51,6 +50,7 @@ class P11CryptoPluginException(exception.BarbicanException):
class P11CryptoPlugin(plugin.CryptoPluginBase):
"""PKCS11 supporting implementation of the crypto plugin.
Generates a key per tenant and encrypts using AES-256-GCM.
This implementation currently relies on an unreleased fork of PyKCS11.
"""

View File

@ -10,16 +10,13 @@
# implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import os
from Crypto.PublicKey import DSA
from Crypto.PublicKey import RSA
from Crypto.Util import asn1
from cryptography import fernet
from oslo.config import cfg
import six
from barbican.openstack.common import gettextutils as u
@ -94,7 +91,8 @@ class SimpleCryptoPlugin(c.CryptoPluginBase):
keystone_id)
def generate_asymmetric(self, generate_dto, kek_meta_dto, keystone_id):
"""Generate asymmetric keys based on below rule
"""Generate asymmetric keys based on below rules:
- RSA, with passphrase (supported)
- RSA, without passphrase (supported)
- DSA, without passphrase (supported)
@ -108,8 +106,8 @@ class SimpleCryptoPlugin(c.CryptoPluginBase):
DSA keys and DER formated keys, later we need to pick better
crypto lib.
"""
if generate_dto.algorithm is None\
or generate_dto.algorithm.lower() == 'rsa':
if(generate_dto.algorithm is None or generate_dto
.algorithm.lower() == 'rsa'):
private_key = RSA.generate(
generate_dto.bit_length, None, None, 65537)
elif generate_dto.algorithm.lower() == 'dsa':
@ -139,8 +137,8 @@ class SimpleCryptoPlugin(c.CryptoPluginBase):
passphrase_dto = None
if generate_dto.passphrase:
if isinstance(generate_dto.passphrase, six.text_type):
generate_dto.passphrase = \
generate_dto.passphrase.encode('utf-8')
generate_dto.passphrase = generate_dto.passphrase.encode(
'utf-8')
passphrase_dto = self.encrypt(c.EncryptDTO(generate_dto.
passphrase),
@ -179,14 +177,16 @@ class SimpleCryptoPlugin(c.CryptoPluginBase):
pub_seq = asn1.DerSequence()
pub_seq[:] = [0, public_key.p, public_key.q,
public_key.g, public_key.y]
public_key = "-----BEGIN DSA PUBLIC KEY-----\n%s"\
"-----END DSA PUBLIC KEY-----" % pub_seq.encode().encode("base64")
public_key = ("-----BEGIN DSA PUBLIC KEY-----\n{0}"
"-----END DSA PUBLIC KEY-----"
.format(pub_seq.encode().encode("base64")))
prv_seq = asn1.DerSequence()
prv_seq[:] = [0, private_key.p, private_key.q,
private_key.g, private_key.y, private_key.x]
private_key = "-----BEGIN DSA PRIVATE KEY-----\n%s"\
"-----END DSA PRIVATE KEY-----" % prv_seq.encode().encode("base64")
private_key = ("-----BEGIN DSA PRIVATE KEY-----\n{0}"
"-----END DSA PRIVATE KEY-----"
.format(prv_seq.encode().encode("base64")))
return public_key, private_key
@ -195,11 +195,12 @@ class SimpleCryptoPlugin(c.CryptoPluginBase):
if algorithm is None or bit_length is None:
return False
if algorithm.lower() in c.PluginSupportTypes.SYMMETRIC_ALGORITHMS \
and bit_length in c.PluginSupportTypes.SYMMETRIC_KEY_LENGTHS:
if (algorithm.lower() in
c.PluginSupportTypes.SYMMETRIC_ALGORITHMS and bit_length in
c.PluginSupportTypes.SYMMETRIC_KEY_LENGTHS):
return True
elif algorithm.lower() in c.PluginSupportTypes.ASYMMETRIC_ALGORITHMS \
and bit_length in c.PluginSupportTypes.ASYMMETRIC_KEY_LENGTHS:
elif (algorithm.lower() in c.PluginSupportTypes.ASYMMETRIC_ALGORITHMS
and bit_length in c.PluginSupportTypes.ASYMMETRIC_KEY_LENGTHS):
return True
else:
return False

View File

@ -105,7 +105,7 @@ class DogtagKRAPlugin(sstore.SecretStoreBase):
crypto, create_nss_db = setup_nss_db(conf)
connection = create_connection(conf, 'kra')
#create kraclient
# create kraclient
kraclient = pki.kra.KRAClient(connection, crypto)
self.keyclient = kraclient.keys
self.systemcert_client = kraclient.system_certs
@ -270,6 +270,7 @@ class DogtagKRAPlugin(sstore.SecretStoreBase):
@staticmethod
def _map_algorithm(algorithm):
"""Map Barbican algorithms to Dogtag plugin algorithms.
Note that only algorithms supported by Dogtag will be mapped.
"""
if algorithm == sstore.KeyAlgorithm.AES:
@ -288,7 +289,7 @@ class DogtagKRAPlugin(sstore.SecretStoreBase):
# asymmetric keys not yet supported
return None
elif algorithm == sstore.KeyAlgorithm.RSA:
#asymmetric keys not yet supported
# asymmetric keys not yet supported
return None
else:
return None
@ -346,6 +347,7 @@ class DogtagCAPlugin(cm.CertificatePluginBase):
def check_certificate_status(self, order_id, order_meta, plugin_meta):
"""Check the status of a certificate request.
:param order_id: ID of the order associated with this request
:param order_meta: order_metadata associated with this order
:param plugin_meta: data populated by previous calls for this order,
@ -431,7 +433,7 @@ class DogtagCAPlugin(cm.CertificatePluginBase):
raise cm.CertificateGeneralException(
"No request returned in enrollment_results")
#store the request_id in the plugin metadata
# store the request_id in the plugin metadata
plugin_meta[self.REQUEST_ID] = request.request_id
cert = enrollment_result.cert

View File

@ -14,9 +14,9 @@
# limitations under the License.
import abc
import six
from oslo.config import cfg
import six
from stevedore import named
from barbican.common import exception
@ -56,9 +56,7 @@ class SecretStorePluginNotFound(exception.BarbicanException):
class SecretStoreSupportedPluginNotFound(exception.BarbicanException):
"""Raised when no plugins are found that support the requested
operation.
"""
"""Raised if no plugins are found that support the requested operation."""
message = "Secret store plugin not found for requested operation."
@ -153,8 +151,9 @@ class SecretStorePluginsNotConfigured(exception.BarbicanException):
class SecretType(object):
"""Constant to define the symmetric key type. Used by getSecret to retrieve
a symmetric key.
"""Constant to define the symmetric key type.
Used by getSecret to retrieve a symmetric key.
"""
SYMMETRIC = "symmetric"
"""Constant to define the public key type. Used by getSecret to retrieve a
@ -225,13 +224,14 @@ class KeySpec(object):
class SecretDTO(object):
"""This object is a secret data transfer object (DTO). This object
encapsulates a key and attributes about the key. The attributes include a
KeySpec that contains the algorithm and bit length. The attributes also
include information on the encoding of the key.
"""This object is a secret data transfer object (DTO).
This object encapsulates a key and attributes about the key. The attributes
include a KeySpec that contains the algorithm and bit length. The
attributes also include information on the encoding of the key.
"""
#TODO(john-wood-w) Remove 'content_type' once secret normalization work is
# TODO(john-wood-w) Remove 'content_type' once secret normalization work is
# completed.
def __init__(self, type, secret, key_spec, content_type,
transport_key=None):
@ -257,9 +257,9 @@ class SecretDTO(object):
class AsymmetricKeyMetadataDTO(object):
"""This DTO encapsulates metadata(s) for asymmetric key
components. These components are private_key_meta,
public_key_meta and passphrase_meta.
"""This DTO encapsulates metadata(s) for asymmetric key components.
These components are private_key_meta, public_key_meta and passphrase_meta.
"""
def __init__(self, private_key_meta=None,
@ -276,7 +276,7 @@ class AsymmetricKeyMetadataDTO(object):
self.passphrase_meta = passphrase_meta
#TODO(john-wood-w) Remove this class once repository factory work is
# TODO(john-wood-w) Remove this class once repository factory work is
# completed.
class SecretStoreContext(object):
"""Context for secret store plugins.
@ -294,9 +294,9 @@ class SecretStoreContext(object):
@six.add_metaclass(abc.ABCMeta)
class SecretStoreBase(object):
#TODO(john-wood-w) Remove 'context' once repository factory and secret
# TODO(john-wood-w) Remove 'context' once repository factory and secret
# normalization work is completed.
#TODO(john-wood-w) Combine generate_symmetric_key() and
# TODO(john-wood-w) Combine generate_symmetric_key() and
# generate_asymmetric_key() into one method: generate_key(), that will
# return a dict with this structure:
# { SecretType.xxxxx: {secret-meta dict}
@ -467,6 +467,7 @@ class SecretStorePluginManager(named.NamedExtensionManager):
def get_plugin_store(self, key_spec, plugin_name=None,
transport_key_needed=False):
"""Gets a secret store plugin.
:param: plugin_name: set to plugin_name to get specific plugin
:param: key_spec: KeySpec of key that will be stored
:param: transport_key_needed: set to True if a transport
@ -487,8 +488,8 @@ class SecretStorePluginManager(named.NamedExtensionManager):
else:
for ext in self.extensions:
if ext.obj.get_transport_key() is not None and\
ext.obj.store_secret_supports(key_spec):
if (ext.obj.get_transport_key() is not None and
ext.obj.store_secret_supports(key_spec)):
return ext.obj
raise SecretStoreSupportedPluginNotFound()

View File

@ -22,8 +22,9 @@ def get_transport_key_model(key_spec, repos, transport_key_needed):
if transport_key_needed:
# get_plugin_store() will throw an exception if no suitable
# plugin with transport key is found
store_plugin = secret_store.SecretStorePluginManager(). \
get_plugin_store(key_spec=key_spec, transport_key_needed=True)
plugin_manager = secret_store.SecretStorePluginManager()
store_plugin = plugin_manager.get_plugin_store(
key_spec=key_spec, transport_key_needed=True)
plugin_name = utils.generate_fullname_for(store_plugin)
key_repo = repos.transport_key_repo
@ -94,18 +95,19 @@ def store_secret(unencrypted_raw, content_type_raw, content_encoding,
repos, transport_key_id)
# Locate a suitable plugin to store the secret.
store_plugin = secret_store.SecretStorePluginManager().\
get_plugin_store(key_spec=key_spec, plugin_name=plugin_name)
plugin_manager = secret_store.SecretStorePluginManager()
store_plugin = plugin_manager.get_plugin_store(
key_spec=key_spec, plugin_name=plugin_name)
# Normalize inputs prior to storage.
#TODO(john-wood-w) Normalize all secrets to base64, so we don't have to
# TODO(john-wood-w) Normalize all secrets to base64, so we don't have to
# pass in 'content' type to the store_secret() call below.
unencrypted, content_type = tr.normalize_before_encryption(
unencrypted_raw, content_type_raw, content_encoding,
enforce_text_only=True)
# Store the secret securely.
#TODO(john-wood-w) Remove the SecretStoreContext once repository factory
# TODO(john-wood-w) Remove the SecretStoreContext once repository factory
# and unit test patch work is completed.
context = secret_store.SecretStoreContext(secret_model=secret_model,
tenant_model=tenant_model,
@ -140,11 +142,12 @@ def get_secret(requesting_content_type, secret_model, tenant_model,
secret_metadata['transport_key'] = transport_key
# Locate a suitable plugin to store the secret.
retrieve_plugin = secret_store.SecretStorePluginManager()\
.get_plugin_retrieve_delete(secret_metadata.get('plugin_name'))
plugin_manager = secret_store.SecretStorePluginManager()
retrieve_plugin = plugin_manager.get_plugin_retrieve_delete(
secret_metadata.get('plugin_name'))
# Retrieve the secret.
#TODO(john-wood-w) Remove the SecretStoreContext once repository factory
# TODO(john-wood-w) Remove the SecretStoreContext once repository factory
# and unit test patch work is completed.
context = secret_store.SecretStoreContext(secret_model=secret_model,
tenant_model=tenant_model)
@ -165,8 +168,9 @@ def get_transport_key_id_for_retrieval(secret_model):
secret_metadata = dict((k, v.value) for (k, v) in
secret_model.secret_store_metadata.items())
retrieve_plugin = secret_store.SecretStorePluginManager()\
.get_plugin_retrieve_delete(secret_metadata.get('plugin_name'))
plugin_manager = secret_store.SecretStorePluginManager()
retrieve_plugin = plugin_manager.get_plugin_retrieve_delete(
secret_metadata.get('plugin_name'))
transport_key_id = retrieve_plugin.get_transport_key()
return transport_key_id
@ -180,24 +184,24 @@ def generate_secret(spec, content_type,
key_spec = secret_store.KeySpec(alg=spec.get('algorithm'),
bit_length=spec.get('bit_length'),
mode=spec.get('mode'))
generate_plugin = secret_store.SecretStorePluginManager()\
.get_plugin_generate(key_spec)
plugin_manager = secret_store.SecretStorePluginManager()
generate_plugin = plugin_manager.get_plugin_generate(key_spec)
# Create secret model to eventually save metadata to.
secret_model = models.Secret(spec)
# Generate the secret.
#TODO(john-wood-w) Remove the SecretStoreContext once repository factory
# TODO(john-wood-w) Remove the SecretStoreContext once repository factory
# and unit test patch work is completed.
context = secret_store.SecretStoreContext(content_type=content_type,
secret_model=secret_model,
tenant_model=tenant_model,
repos=repos)
#TODO(john-wood-w) Replace with single 'generate_key()' call once
# TODO(john-wood-w) Replace with single 'generate_key()' call once
# asymmetric and symmetric generation is combined.
secret_metadata = generate_plugin.\
generate_symmetric_key(key_spec, context)
secret_metadata = generate_plugin.generate_symmetric_key(key_spec, context)
# Save secret and metadata.
_save_secret(secret_model, tenant_model, repos)
@ -209,36 +213,35 @@ def generate_secret(spec, content_type,
def generate_asymmetric_secret(spec, content_type,
tenant_model, repos):
"""Generate an asymmetric secret and store
into a secure backend.
"""
"""Generate an asymmetric secret and store into a secure backend."""
# Locate a suitable plugin to store the secret.
key_spec = secret_store.KeySpec(alg=spec.get('algorithm'),
bit_length=spec.get('bit_length'),
passphrase=spec.get('passphrase'))
generate_plugin = secret_store.SecretStorePluginManager()\
.get_plugin_generate(key_spec)
plugin_manager = secret_store.SecretStorePluginManager()
generate_plugin = plugin_manager.get_plugin_generate(key_spec)
# Create secret models to eventually save metadata to.
private_secret_model = models.Secret(spec)
public_secret_model = models.Secret(spec)
passphrase_secret_model = models.Secret(spec)\
if spec.get('passphrase') else None
passphrase_secret_model = (models.Secret(spec)
if spec.get('passphrase') else None)
# Generate the secret.
# TODO(john-wood-w) Remove the SecretStoreContext once repository factory
# and unit test patch work is completed.
context = secret_store.\
SecretStoreContext(content_type=content_type,
private_secret_model=private_secret_model,
public_secret_model=public_secret_model,
passphrase_secret_model=passphrase_secret_model,
tenant_model=tenant_model,
repos=repos)
context = secret_store.SecretStoreContext(
content_type=content_type,
private_secret_model=private_secret_model,
public_secret_model=public_secret_model,
passphrase_secret_model=passphrase_secret_model,
tenant_model=tenant_model,
repos=repos)
asymmetric_meta_dto = generate_plugin.\
generate_asymmetric_key(key_spec, context)
asymmetric_meta_dto = generate_plugin.generate_asymmetric_key(
key_spec, context
)
# Save secret and metadata.
_save_secret(private_secret_model, tenant_model, repos)
@ -278,8 +281,9 @@ def delete_secret(secret_model, project_id, repos):
secret_model.secret_store_metadata.items())
# Locate a suitable plugin to delete the secret from.
delete_plugin = secret_store.SecretStorePluginManager()\
.get_plugin_retrieve_delete(secret_metadata.get('plugin_name'))
plugin_manager = secret_store.SecretStorePluginManager()
delete_plugin = plugin_manager.get_plugin_retrieve_delete(
secret_metadata.get('plugin_name'))
# Delete the secret from plugin storage.
delete_plugin.delete_secret(secret_metadata)
@ -296,8 +300,7 @@ def _save_secret_metadata(secret_model, secret_metadata,
if not secret_metadata:
secret_metadata = dict()
secret_metadata['plugin_name'] = utils\
.generate_fullname_for(store_plugin)
secret_metadata['plugin_name'] = utils.generate_fullname_for(store_plugin)
secret_metadata['content_type'] = content_type

View File

@ -89,8 +89,7 @@ class SimpleCertificatePlugin(cert.CertificatePluginBase):
return cert.ResultDTO(cert.CertificateStatus.WAITING_FOR_CA)
def supports(self, certificate_spec):
"""Returns a boolean indicating if the plugin supports the
certificate type.
"""Indicates whether the plugin supports the certificate type.
:param certificate_spec: Contains details on the certificate to
generate the certificate order

View File

@ -65,7 +65,7 @@ class StoreCryptoAdapterPlugin(sstore.SecretStoreBase):
encrypt_dto, kek_meta_dto, context.tenant_model.keystone_id
)
# Convert binary data into a text-based format.
#TODO(jwood) Figure out by storing binary (BYTEA) data in Postgres
# TODO(jwood) Figure out by storing binary (BYTEA) data in Postgres
# isn't working.
self._store_secret_and_datum(context,
context.secret_model,
@ -76,11 +76,11 @@ class StoreCryptoAdapterPlugin(sstore.SecretStoreBase):
def get_secret(self, secret_metadata, context):
"""Retrieve a secret."""
if not context.secret_model \
or not context.secret_model.encrypted_data:
if (not context.secret_model or
not context.secret_model.encrypted_data):
raise sstore.SecretNotFoundException()
#TODO(john-wood-w) Need to revisit 1 to many datum relationship.
# TODO(john-wood-w) Need to revisit 1 to many datum relationship.
datum_model = context.secret_model.encrypted_data[0]
# Find HSM-style 'crypto' plugin.
@ -91,7 +91,7 @@ class StoreCryptoAdapterPlugin(sstore.SecretStoreBase):
kek_meta_dto = crypto.KEKMetaDTO(datum_model.kek_meta_tenant)
# Convert from text-based storage format to binary.
#TODO(jwood) Figure out by storing binary (BYTEA) data in
# TODO(jwood) Figure out by storing binary (BYTEA) data in
# Postgres isn't working.
encrypted = base64.b64decode(datum_model.cypher_text)
decrypt_dto = crypto.DecryptDTO(encrypted)
@ -137,9 +137,8 @@ class StoreCryptoAdapterPlugin(sstore.SecretStoreBase):
key_spec.bit_length,
key_spec.mode, None)
# Create the encrypted meta.
response_dto = generating_plugin.\
generate_symmetric(generate_dto, kek_meta_dto,
context.tenant_model.keystone_id)
response_dto = generating_plugin.generate_symmetric(
generate_dto, kek_meta_dto, context.tenant_model.keystone_id)
# Convert binary data into a text-based format.
# TODO(jwood) Figure out by storing binary (BYTEA) data in Postgres
@ -164,11 +163,8 @@ class StoreCryptoAdapterPlugin(sstore.SecretStoreBase):
if crypto.PluginSupportTypes.ASYMMETRIC_KEY_GENERATION != plugin_type:
raise sstore.SecretAlgorithmNotSupportedException(key_spec.alg)
generating_plugin = manager.PLUGIN_MANAGER\
.get_plugin_store_generate(plugin_type,
key_spec.alg,
key_spec.bit_length,
None)
generating_plugin = manager.PLUGIN_MANAGER.get_plugin_store_generate(
plugin_type, key_spec.alg, key_spec.bit_length, None)
# Find or create a key encryption key metadata.
kek_datum_model, kek_meta_dto = self._find_or_create_kek_objects(
@ -179,9 +175,11 @@ class StoreCryptoAdapterPlugin(sstore.SecretStoreBase):
None, key_spec.passphrase)
# Create the encrypted meta.
private_key_dto, public_key_dto, passwd_dto = generating_plugin.\
generate_asymmetric(generate_dto, kek_meta_dto,
context.tenant_model.keystone_id)
private_key_dto, public_key_dto, passwd_dto = (
generating_plugin.generate_asymmetric(
generate_dto, kek_meta_dto, context.tenant_model.keystone_id
)
)
self._store_secret_and_datum(context,
context.private_secret_model,
@ -281,10 +279,11 @@ class StoreCryptoAdapterPlugin(sstore.SecretStoreBase):
kek_datum.mode = kek_meta_dto.mode
kek_datum.plugin_meta = kek_meta_dto.plugin_meta
#TODO(john-wood-w) Move this to the more generic secret_store.py?
# TODO(john-wood-w) Move this to the more generic secret_store.py?
def _determine_generation_type(self, algorithm):
"""Determines the type (symmetric and asymmetric for now)
based on algorithm
"""Determines the type based on the given algorithm.
For now this is either symmetric or asymmetric.
"""
symmetric_algs = crypto.PluginSupportTypes.SYMMETRIC_ALGORITHMS
asymmetric_algs = crypto.PluginSupportTypes.ASYMMETRIC_ALGORITHMS

View File

@ -307,7 +307,7 @@ class BeginTypeOrder(BaseTask):
class UpdateOrder(BaseTask):
"""Handles updating an order"""
"""Handles updating an order."""
def get_name(self):
return u._('Update Order')

View File

@ -18,7 +18,6 @@ This test module focuses on typical-flow business logic tests with the API
resource classes. For RBAC tests of these classes, see the
'resources_policy_test.py' module.
"""
import base64
import logging
import mimetypes
@ -1996,6 +1995,7 @@ class WhenCreatingContainersUsingContainersResource(FunctionalTest):
self.container_req
)
self.assertEqual(resp.status_int, 201)
self.assertNotIn(self.tenant_keystone_id, resp.headers['Location'])
args, kwargs = self.container_repo.create_from.call_args
container = args[0]
@ -2179,6 +2179,7 @@ class WhenCreatingConsumersUsingConsumersResource(FunctionalTest):
self.consumer_ref
)
self.assertEqual(resp.status_int, 200)
self.assertNotIn(self.tenant_keystone_id, resp.headers['Location'])
args, kwargs = self.consumer_repo.create_from.call_args
consumer = args[0]