Update Client to use hrefs instead of parsing IDs

This commit is contained in:
Douglas Mendizabal
2013-09-04 00:19:30 -05:00
parent d783b44087
commit a8ba12f673
3 changed files with 65 additions and 97 deletions

View File

@@ -91,16 +91,14 @@ class Client(object):
self.secrets = secrets.SecretManager(self)
self.orders = orders.OrderManager(self)
def get(self, path, params=None):
url = '{0}/{1}/'.format(self.base_url, path)
def get(self, href, params=None):
headers = {'Accept': 'application/json'}
resp = self._session.get(url, params=params, headers=headers)
resp = self._session.get(href, params=params, headers=headers)
self._check_status_code(resp)
return resp.json()
def get_raw(self, path, headers):
url = '{0}/{1}/'.format(self.base_url, path)
resp = self._session.get(url, headers=headers)
def get_raw(self, href, headers):
resp = self._session.get(href, headers=headers)
self._check_status_code(resp)
return resp.content
@@ -111,9 +109,8 @@ class Client(object):
self._check_status_code(resp)
return resp.json()
def delete(self, path):
url = '{0}/{1}/'.format(self.base_url, path)
resp = self._session.delete(url)
def delete(self, href):
resp = self._session.delete(href)
self._check_status_code(resp)
def _check_status_code(self, resp):
@@ -122,10 +119,10 @@ class Client(object):
if status == 401:
LOG.error('Auth error: {0}'.format(resp.content))
raise HTTPAuthError('{0}'.format(resp.content))
if status >=500:
if status >= 500:
LOG.error('5xx Server error: {0}'.format(resp.content))
raise HTTPServerError('{0}'.format(resp.content))
if status >=400:
if status >= 400:
LOG.error('4xx Client error: {0}'.format(resp.content))
raise HTTPClientError('{0}'.format(resp.content))

View File

@@ -28,8 +28,7 @@ class Order(object):
def __init__(self, order_dict):
"""
Builds an order object from a json representation. Includes the
connection object for subtasks.
Builds an order object from a dictionary.
"""
self.order_ref = order_dict['order_ref']
self.status = order_dict.get('status')
@@ -38,30 +37,19 @@ class Order(object):
self.updated = timeutils.parse_isotime(order_dict['updated'])
else:
self.updated = None
secret_dict = order_dict['secret']
#TODO(dmend): This is a hack because secret_ref is in different
# spots. Secret will be missing content_types also.
# Maybe we should fetch the secret for this?
secret_dict.update({'secret_ref': order_dict['secret_ref'],
'created': order_dict['created']})
self.secret = secrets.Secret(secret_dict)
self.id = urlparse.urlparse(self.order_ref).path.split('/').pop()
self.secret_ref = order_dict.get('secret_ref')
def __str__(self):
return ("Order - ID: {0}\n"
" order href: {1}\n"
" secret href: {2}\n"
" created: {3}\n"
" status: {4}\n"
.format(self.id, self.order_ref, self.secret.secret_ref,
return ("Order - order href: {0}\n"
" secret href: {1}\n"
" created: {2}\n"
" status: {3}\n"
.format(self.order_ref, self.secret.secret_ref,
self.created, self.status)
)
def __repr__(self):
return 'Order(id="{0}", secret=Secret(id="{1}")'.format(
self.id, self.secret.id
)
return 'Order(order_ref={0})'.format(self.order_ref)
class OrderManager(base.BaseEntityManager):
@@ -79,14 +67,14 @@ class OrderManager(base.BaseEntityManager):
"""
Creates a new Order in Barbican
:param name: A friendly name for the
:param name: A friendly name for the secret
:param payload_content_type: The format/type of the secret data
:param algorithm: The algorithm the secret is used with
:param algorithm: The algorithm the secret associated with
:param bit_length: The bit length of the secret
:param mode: The algorithm mode (e.g. CBC or CTR mode)
:param expiration: The expiration time of the secret in ISO 8601
format
:returns: Order ID for the created order
:returns: Order href for the created order
"""
LOG.debug(_("Creating order"))
@@ -96,42 +84,36 @@ class OrderManager(base.BaseEntityManager):
'payload_content_type'] = payload_content_type
order_dict['secret']['algorithm'] = algorithm
order_dict['secret']['bit_length'] = bit_length
#TODO(dmend): Change this to mode
order_dict['secret']['cypher_type'] = mode
order_dict['secret']['mode'] = mode
order_dict['secret']['expiration'] = expiration
self._remove_empty_keys(order_dict['secret'])
LOG.debug(_("Request body: {0}").format(order_dict['secret']))
resp = self.api.post(self.entity, order_dict)
#TODO(dmend): return order object?
order_id = resp['order_ref'].split('/')[-1]
return resp['order_ref']
return order_id
def get(self, order_id):
def get(self, order_ref):
"""
Returns an Order object
:param order_id: The UUID of the order
:param order_ref: The href for the order
"""
LOG.debug(_("Getting order - Order ID: {0}").format(order_id))
if not order_id:
raise ValueError('order_id is required.')
path = '{0}/{1}'.format(self.entity, order_id)
resp = self.api.get(path)
LOG.debug(_("Getting order - Order href: {0}").format(secret_ref))
if not order_ref:
raise ValueError('order_ref is required.')
resp = self.api.get(order_ref)
return Order(resp)
def delete(self, order_id):
def delete(self, order_ref):
"""
Deletes an order
:param order_id: The UUID of the order
:param order_ref: The href for the order
"""
if not order_id:
raise ValueError('order_id is required.')
path = '{0}/{1}'.format(self.entity, order_id)
self.api.delete(path)
if not order_ref:
raise ValueError('order_ref is required.')
self.api.delete(order_ref)
def list(self, limit=10, offset=0):
params = {'limit': limit, 'offset': offset}

View File

@@ -34,6 +34,7 @@ class Secret(object):
self.secret_ref = secret_dict.get('secret_ref')
self.name = secret_dict.get('name')
self.status = secret_dict.get('status')
self.content_types = secret_dict.get('content_types')
self.created = parse_isotime(secret_dict.get('created'))
if secret_dict.get('expiration') is not None:
@@ -47,23 +48,19 @@ class Secret(object):
self.algorithm = secret_dict.get('algorithm')
self.bit_length = secret_dict.get('bit_length')
self.mode = secret_dict.get('cypher_type')
self.content_types = secret_dict.get('content_types')
self.id = urlparse.urlparse(self.secret_ref).path.split('/').pop()
self.mode = secret_dict.get('mode')
def __str__(self):
return ("Secret - ID: {0}\n"
" href: {1}\n"
" name: {2}\n"
" created: {3}\n"
" status: {4}\n"
" content types: {5}\n"
" algorithm: {6}\n"
" bit length: {7}\n"
" mode: {8}\n"
" expiration: {9}\n"
.format(self.id, self.secret_ref, self.name, self.created,
return ("Secret - href: {0}\n"
" name: {1}\n"
" created: {2}\n"
" status: {3}\n"
" content types: {4}\n"
" algorithm: {5}\n"
" bit length: {6}\n"
" mode: {7}\n"
" expiration: {8}\n"
.format(self.secret_ref, self.name, self.created,
self.status, self.content_types, self.algorithm,
self.bit_length, self.mode, self.expiration)
)
@@ -93,12 +90,12 @@ class SecretManager(base.BaseEntityManager):
:param payload: The unencrypted secret data
:param payload_content_type: The format/type of the secret data
:param payload_content_encoding: The encoding of the secret data
:param algorithm: The algorithm barbican should use to encrypt
:param bit_length: The bit length of the key used for ecnryption
:param mode: The algorithm mode (e.g. CBC or CTR mode)
:param algorithm: The algorithm associated with this secret key
:param bit_length: The bit length of this secret key
:param mode: The algorithm mode used with this secret key
:param expiration: The expiration time of the secret in ISO 8601
format
:returns: Secret ID for the stored secret
:returns: Secret href for the stored secret
"""
LOG.debug("Creating secret of payload content type {0}".format(
payload_content_type))
@@ -109,8 +106,7 @@ class SecretManager(base.BaseEntityManager):
secret_dict['payload_content_type'] = payload_content_type
secret_dict['payload_content_encoding'] = payload_content_encoding
secret_dict['algorithm'] = algorithm
#TODO(dmend): Change this to 'mode'
secret_dict['cypher_type'] = mode
secret_dict['mode'] = mode
secret_dict['bit_length'] = bit_length
secret_dict['expiration'] = expiration
self._remove_empty_keys(secret_dict)
@@ -118,48 +114,41 @@ class SecretManager(base.BaseEntityManager):
LOG.debug("Request body: {0}".format(secret_dict))
resp = self.api.post(self.entity, secret_dict)
#TODO(dmend): return secret object?
#secret = Secret(resp)
secret_id = resp['secret_ref'].split('/')[-1]
return resp['secret_ref']
return secret_id
def get(self, secret_id):
def get(self, secret_ref):
"""
Returns a Secret object with information about the secret.
:param secret_id: The UUID of the secret
:param secret_ref: The href for the secret
"""
if not secret_id:
raise ValueError('secret_id is required.')
path = '{0}/{1}'.format(self.entity, secret_id)
resp = self.api.get(path)
if not secret_ref:
raise ValueError('secret_ref is required.')
resp = self.api.get(secret_ref)
return Secret(resp)
def raw(self, secret_id, content_type):
def decrypt(self, secret_ref, content_type):
"""
Returns the actual secret data stored in Barbican.
:param secret_id: The UUID of the secret
:param secret_ref: The href for the secret
:param content_type: The content_type of the secret
:returns: secret data
"""
if not all([secret_id, content_type]):
raise ValueError('secret_id and content_type are required.')
path = '{0}/{1}'.format(self.entity, secret_id)
if not all([secret_ref, content_type]):
raise ValueError('secret_ref and content_type are required.')
headers = {'Accept': content_type}
return self.api.get_raw(path, headers)
return self.api.get_raw(secret_ref, headers)
def delete(self, secret_id):
def delete(self, secret_ref):
"""
Deletes a secret
:param secret_id: The UUID of the secret
:param secret_ref: The href for the secret
"""
if not secret_id:
raise ValueError('secret_id is required.')
path = '{0}/{1}'.format(self.entity, secret_id)
self.api.delete(path)
if not secret_ref:
raise ValueError('secret_ref is required.')
self.api.delete(secret_ref)
def list(self, limit=10, offset=0):