Merge pull request #15 from Aghoreyshi/master
Update the client library and keep to comply with the MIME type revamp (merged on behalf of Doug!)
This commit is contained in:
@@ -1 +1 @@
|
||||
"""Barbican Client Library Binding"""
|
||||
"""Barbican Client Library Binding"""
|
||||
|
||||
@@ -11,7 +11,6 @@ from barbicanclient.common import auth
|
||||
from barbicanclient.openstack.common import log
|
||||
from barbicanclient.common.exceptions import ClientException
|
||||
from barbicanclient.openstack.common.gettextutils import _
|
||||
from openstack.common.timeutils import parse_isotime
|
||||
from urlparse import urljoin
|
||||
|
||||
|
||||
@@ -95,8 +94,8 @@ class Connection(object):
|
||||
|
||||
self._session = requests.Session()
|
||||
|
||||
#headers = {"Client-Id": self._client_id}
|
||||
#self._session.headers.update(headers)
|
||||
# headers = {"Client-Id": self._client_id}
|
||||
# self._session.headers.update(headers)
|
||||
self._session.verify = True
|
||||
|
||||
if token:
|
||||
@@ -171,9 +170,10 @@ class Connection(object):
|
||||
return secrets, prev_ref, next_ref
|
||||
|
||||
def create_secret(self,
|
||||
mime_type,
|
||||
plain_text=None,
|
||||
name=None,
|
||||
payload=None,
|
||||
payload_content_type=None,
|
||||
payload_content_encoding=None,
|
||||
algorithm=None,
|
||||
bit_length=None,
|
||||
cypher_type=None,
|
||||
@@ -181,21 +181,24 @@ class Connection(object):
|
||||
"""
|
||||
Creates and returns a Secret object with all of its metadata filled in.
|
||||
|
||||
:param mime_type: The MIME type of the secret
|
||||
:param plain_text: The unencrypted secret
|
||||
:param name: A friendly name for the secret
|
||||
:param payload: The unencrypted secret
|
||||
:param payload_content_type: The format/type of the secret
|
||||
:param payload_content_encoding: The encoding of the secret
|
||||
:param algorithm: The algorithm the secret is used with
|
||||
:param bit_length: The bit length of the secret
|
||||
:param cypher_type: The cypher type (e.g. block cipher mode)
|
||||
:param expiration: The expiration time of the secret in ISO 8601 format
|
||||
"""
|
||||
LOG.debug(_("Creating secret of mime_type {0}").format(mime_type))
|
||||
LOG.debug(_("Creating secret of payload content type {0}").format(
|
||||
payload_content_type))
|
||||
href = "{0}/{1}".format(self._tenant, self.SECRETS_PATH)
|
||||
LOG.debug(_("href: {0}").format(href))
|
||||
secret_dict = {}
|
||||
secret_dict['mime_type'] = mime_type
|
||||
secret_dict['plain_text'] = plain_text
|
||||
secret_dict['name'] = name
|
||||
secret_dict['payload'] = payload
|
||||
secret_dict['payload_content_type'] = payload_content_type
|
||||
secret_dict['payload_content_encoding'] = payload_content_encoding
|
||||
secret_dict['algorithm'] = algorithm
|
||||
secret_dict['cypher_type'] = cypher_type
|
||||
secret_dict['bit_length'] = bit_length
|
||||
@@ -249,25 +252,25 @@ class Connection(object):
|
||||
LOG.debug(_("Response - headers: {0}\nbody: {1}").format(hdrs, body))
|
||||
return Secret(self._conn, body)
|
||||
|
||||
def get_raw_secret_by_id(self, secret_id, mime_type):
|
||||
def get_raw_secret_by_id(self, secret_id, payload_content_type):
|
||||
"""
|
||||
Returns the raw secret
|
||||
|
||||
:param secret_id: The UUID of the secret
|
||||
:param mime_type: The MIME type of the secret
|
||||
:param payload_content_type: The data type of the secret
|
||||
"""
|
||||
LOG.debug(_("Getting raw secret - Secret ID: {0}").format(secret_id))
|
||||
href = "{0}/{1}/{2}".format(self._tenant, self.SECRETS_PATH, secret_id)
|
||||
return self.get_raw_secret(href, mime_type)
|
||||
return self.get_raw_secret(href, payload_content_type)
|
||||
|
||||
def get_raw_secret(self, href, mime_type):
|
||||
def get_raw_secret(self, href, payload_content_type):
|
||||
"""
|
||||
Returns the raw secret
|
||||
|
||||
:param href: The reference to the secret
|
||||
:param mime_type: The MIME type of the secret
|
||||
:param payload_content_type: The data type of the secret
|
||||
"""
|
||||
hdrs = {"Accept": mime_type}
|
||||
hdrs = {"Accept": payload_content_type}
|
||||
hdrs, body = self._perform_http(href=href, method='GET', headers=hdrs,
|
||||
parse_json=False)
|
||||
LOG.debug(_("Response - headers: {0}\nbody: {1}").format(hdrs, body))
|
||||
@@ -317,29 +320,32 @@ class Connection(object):
|
||||
return orders, prev_ref, next_ref
|
||||
|
||||
def create_order(self,
|
||||
mime_type,
|
||||
name=None,
|
||||
algorithm=None,
|
||||
bit_length=None,
|
||||
cypher_type=None):
|
||||
payload_content_type='application/octet-stream',
|
||||
algorithm='aes',
|
||||
bit_length=256,
|
||||
cypher_type='cbc',
|
||||
expiration=None):
|
||||
"""
|
||||
Creates and returns an Order object with all of its metadata filled in.
|
||||
|
||||
:param mime_type: The MIME type of the secret
|
||||
:param name: A friendly name for the secret
|
||||
:param algorithm: The algorithm the secret is used with
|
||||
:param bit_length: The bit length of the secret
|
||||
:param cypher_type: The cypher type (e.g. block cipher mode)
|
||||
:param expiration: The expiration time of the secret in ISO 8601 format
|
||||
"""
|
||||
LOG.debug(_("Creating order of mime_type {0}").format(mime_type))
|
||||
LOG.debug(_("Creating order"))
|
||||
href = "{0}/{1}".format(self._tenant, self.ORDERS_PATH)
|
||||
LOG.debug("href: {0}".format(href))
|
||||
order_dict = {'secret': {}}
|
||||
order_dict['secret']['name'] = name
|
||||
order_dict['secret']['mime_type'] = mime_type
|
||||
order_dict['secret'][
|
||||
'payload_content_type'] = payload_content_type
|
||||
order_dict['secret']['algorithm'] = algorithm
|
||||
order_dict['secret']['bit_length'] = bit_length
|
||||
order_dict['secret']['cypher_type'] = cypher_type
|
||||
order_dict['secret']['expiration'] = expiration
|
||||
self._remove_empty_keys(order_dict['secret'])
|
||||
LOG.debug(_("Request body: {0}").format(order_dict['secret']))
|
||||
hdrs, body = self._perform_http(href=href,
|
||||
|
||||
@@ -64,7 +64,7 @@ def authenticate(auth_url, user, key, tenant, **kwargs):
|
||||
filter_value=region,
|
||||
service_type=service_type,
|
||||
endpoint_type=endpoint_type)
|
||||
except exceptions.EndpointNotFound as ex:
|
||||
except exceptions.EndpointNotFound:
|
||||
raise ClientException('Endpoint not found in service catalog')
|
||||
|
||||
return endpoint, _ksclient.auth_token
|
||||
|
||||
@@ -23,6 +23,7 @@ import logging.handlers
|
||||
import os
|
||||
import sys
|
||||
|
||||
from barbicanclient.openstack.common.gettextutils import _
|
||||
from barbicanclient.version import __version__
|
||||
from oslo.config import cfg
|
||||
|
||||
|
||||
@@ -7,4 +7,4 @@ def proc_template(template, **kwargs):
|
||||
dictionary args and returning the strings.
|
||||
"""
|
||||
return template.format(**dict([(k, urllib.quote(v))
|
||||
for k, v in kwargs.items()]))
|
||||
for k, v in kwargs.items()]))
|
||||
|
||||
@@ -46,24 +46,34 @@ class Keep:
|
||||
def add_create_args(self):
|
||||
create_parser = self.subparsers.add_parser('create', help='Create a '
|
||||
'secret or an order')
|
||||
create_parser.add_argument('--mime_type', '-m', default='text/plain',
|
||||
help='the MIME type of the raw secret (defa'
|
||||
'ult: %(default)s)')
|
||||
create_parser.add_argument('--name', '-n', help='a human-friendly name'
|
||||
' used only for reference')
|
||||
create_parser.add_argument('--algorithm', '-a', help='the algorithm us'
|
||||
'ed only for reference')
|
||||
create_parser.add_argument('--name', '-n',
|
||||
help='a human-friendly name')
|
||||
create_parser.add_argument('--algorithm', '-a', default='aes', help='t'
|
||||
'he algorithm; used only for reference (def'
|
||||
'ault: %(default)s)')
|
||||
create_parser.add_argument('--bit_length', '-b', default=256,
|
||||
help='the bit length of the secret used '
|
||||
help='the bit length of the secret; used '
|
||||
'only for reference (default: %(default)s)',
|
||||
type=int)
|
||||
create_parser.add_argument('--cypher_type', '-c', help='the cypher typ'
|
||||
'e used only for reference')
|
||||
create_parser.add_argument('--plain_text', '-p', help='the unencrypted'
|
||||
' secret (only used for secrets)')
|
||||
create_parser.add_argument('--cypher_type', '-c', default="cbc",
|
||||
help='the cypher type; used only for refere'
|
||||
'nce (default: %(default)s)')
|
||||
create_parser.add_argument('--payload', '-p', help='the unencrypted'
|
||||
' secret; if provided, you must also provid'
|
||||
'e a payload_content_type (only used for se'
|
||||
'crets)')
|
||||
create_parser.add_argument('--payload_content_type', '-t',
|
||||
help='the type/format of the provided '
|
||||
'secret data; "text/plain" is assumed to be'
|
||||
' UTF-8; required when --payload is su'
|
||||
'pplied and when creating orders')
|
||||
create_parser.add_argument('--payload_content_encoding', '-d',
|
||||
help='required if --payload_content_type is'
|
||||
' "application/octet-stream" (only used for'
|
||||
' secrets)')
|
||||
|
||||
create_parser.add_argument('--expiration', '-e', help='the expiration '
|
||||
'time for the secret in ISO 8601 format '
|
||||
'(only used for secrets)')
|
||||
'time for the secret in ISO 8601 format')
|
||||
create_parser.set_defaults(func=self.create)
|
||||
|
||||
def add_delete_args(self):
|
||||
@@ -81,10 +91,12 @@ class Keep:
|
||||
get_parser.add_argument('UUID', help='the universally unique identi'
|
||||
'fier of the the secret or order')
|
||||
get_parser.add_argument('--raw', '-r', help='if specified, gets the ra'
|
||||
'w secret of type specified with --mime_type ('
|
||||
'only used for secrets)', action='store_true')
|
||||
get_parser.add_argument('--mime_type', '-m', default='text/plain',
|
||||
help='the MIME type of the raw secret (defa'
|
||||
'w secret of type specified with --payload_con'
|
||||
'tent_type (only used for secrets)',
|
||||
action='store_true')
|
||||
get_parser.add_argument('--payload_content_type', '-t',
|
||||
default='text/plain',
|
||||
help='the content type of the raw secret (defa'
|
||||
'ult: %(default)s; only used for secrets)')
|
||||
get_parser.set_defaults(func=self.get)
|
||||
|
||||
@@ -105,20 +117,22 @@ class Keep:
|
||||
|
||||
def create(self, args):
|
||||
if args.type == 'secret':
|
||||
secret = self.conn.create_secret(args.mime_type,
|
||||
args.plain_text,
|
||||
args.name,
|
||||
secret = self.conn.create_secret(args.name,
|
||||
args.payload,
|
||||
args.payload_content_type,
|
||||
args.payload_content_encoding,
|
||||
args.algorithm,
|
||||
args.bit_length,
|
||||
args.cypher_type,
|
||||
args.expiration)
|
||||
print secret
|
||||
else:
|
||||
order = self.conn.create_order(args.mime_type,
|
||||
args.name,
|
||||
order = self.conn.create_order(args.name,
|
||||
args.payload_content_type,
|
||||
args.algorithm,
|
||||
args.bit_length,
|
||||
args.cypher_type)
|
||||
args.cypher_type,
|
||||
args.expiration)
|
||||
print order
|
||||
|
||||
def delete(self, args):
|
||||
@@ -130,7 +144,8 @@ class Keep:
|
||||
def get(self, args):
|
||||
if args.type == 'secret':
|
||||
if args.raw:
|
||||
print self.conn.get_raw_secret_by_id(args.UUID, args.mime_type)
|
||||
print self.conn.get_raw_secret_by_id(args.UUID,
|
||||
args.payload_content_type)
|
||||
else:
|
||||
print self.conn.get_secret_by_id(args.UUID)
|
||||
else:
|
||||
|
||||
@@ -10,11 +10,12 @@ class Order(object):
|
||||
connection object for subtasks.
|
||||
"""
|
||||
self.connection = connection
|
||||
self.status = order_dict.get('status')
|
||||
self.secret = order_dict.get('secret')
|
||||
self.secret = order_dict['secret']
|
||||
self.order_ref = order_dict['order_ref']
|
||||
self.created = parse_isotime(order_dict['created'])
|
||||
self.secret_ref = order_dict.get('secret_ref')
|
||||
self.order_ref = order_dict.get('order_ref')
|
||||
self.created = parse_isotime(order_dict.get('created'))
|
||||
self.status = order_dict.get('status')
|
||||
|
||||
if order_dict.get('updated') is not None:
|
||||
self.updated = parse_isotime(order_dict['updated'])
|
||||
else:
|
||||
|
||||
@@ -3,24 +3,29 @@ from openstack.common.timeutils import parse_isotime
|
||||
|
||||
|
||||
class Secret(object):
|
||||
|
||||
"""
|
||||
A secret is any data the user has stored in the key management system.
|
||||
"""
|
||||
|
||||
def __init__(self, connection, secret_dict):
|
||||
"""
|
||||
Builds a secret object from a json representation. Includes the
|
||||
connection object for subtasks.
|
||||
"""
|
||||
self.connection = connection
|
||||
self.secret_ref = secret_dict['secret_ref']
|
||||
self.secret_ref = secret_dict.get('secret_ref')
|
||||
self.created = parse_isotime(secret_dict.get('created'))
|
||||
self.status = secret_dict.get('status')
|
||||
|
||||
self.algorithm = secret_dict.get('algorithm')
|
||||
self.bit_length = secret_dict.get('bit_length')
|
||||
self.mime_type = secret_dict.get('mime_type')
|
||||
self.name = secret_dict.get('name')
|
||||
self.payload_content_type = secret_dict.get('payload_content_type')
|
||||
self.payload_content_encoding = secret_dict.get(
|
||||
'payload_content_encoding')
|
||||
|
||||
self.cypher_type = secret_dict.get('cypher_type')
|
||||
self.name = secret_dict.get('name')
|
||||
|
||||
if secret_dict.get('expiration') is not None:
|
||||
self.expiration = parse_isotime(secret_dict['expiration'])
|
||||
@@ -43,12 +48,15 @@ class Secret(object):
|
||||
" reference: {1}\n"
|
||||
" name: {2}\n"
|
||||
" created: {3}\n"
|
||||
" MIME type: {4}\n"
|
||||
" status: {5}\n"
|
||||
" bit length: {6}\n"
|
||||
" algorithm: {7}\n"
|
||||
" cypher type: {8}\n"
|
||||
" status: {4}\n"
|
||||
" payload content type: {5}\n"
|
||||
" payload content encoding: {6}\n"
|
||||
" bit length: {7}\n"
|
||||
" algorithm: {8}\n"
|
||||
" cypher type: {9}\n"
|
||||
" expiration: {10}\n"
|
||||
.format(self.id, self.secret_ref, self.name, self.created,
|
||||
self.mime_type, self.status, self.bit_length,
|
||||
self.algorithm, self.cypher_type)
|
||||
self.status, self.payload_content_type,
|
||||
self.payload_content_encoding, self.bit_length,
|
||||
self.algorithm, self.cypher_type, self.expiration)
|
||||
)
|
||||
|
||||
@@ -17,5 +17,5 @@
|
||||
Cloudkeep's Barbican Client version
|
||||
"""
|
||||
|
||||
__version__ = '0.2.1dev'
|
||||
__version__ = '0.3.0'
|
||||
__version_info__ = tuple(__version__.split('.'))
|
||||
|
||||
2
clientrc
2
clientrc
@@ -2,5 +2,5 @@ export OS_TENANT_NAME=demo
|
||||
export OS_USERNAME=demo
|
||||
export OS_PASSWORD=password
|
||||
export OS_AUTH_URL="http://keystone-int.cloudkeep.io:5000/v2.0/"
|
||||
export BARBICAN_ENDPOINT="http://api-01-int.cloudkeep.io:9311/v1/"
|
||||
export BARBICAN_ENDPOINT="http://localhost:9311/v1/"
|
||||
export AUTH_TOKEN=''
|
||||
|
||||
@@ -104,10 +104,9 @@ class WhenTestingConnection(unittest.TestCase):
|
||||
endpoint=self.endpoint)
|
||||
|
||||
def test_should_create_secret(self):
|
||||
body = {'status': 'ACTIVE',
|
||||
'content_types': {'default': 'text/plain'},
|
||||
body = {'status': "ACTIVE",
|
||||
'updated': '2013-06-07T16:13:38.889857',
|
||||
'cypher_type': 'CDC',
|
||||
'cypher_type': 'cbc',
|
||||
'name': 'test_secret',
|
||||
'algorithm': 'aes',
|
||||
'created': '2013-06-07T16:13:38.889851',
|
||||
@@ -115,19 +114,20 @@ class WhenTestingConnection(unittest.TestCase):
|
||||
'b5e-3738-408e-aaba-05a7177cade5',
|
||||
'expiration': '2015-06-07T16:13:38.889851',
|
||||
'bit_length': 256,
|
||||
'mime_type': 'text/plain'
|
||||
'payload_content_type': 'text/plain'
|
||||
}
|
||||
|
||||
secret = client.Secret(self.connection, body)
|
||||
self.request.return_value.content = json.dumps(body)
|
||||
created = self.connection.create_secret('text/plain',
|
||||
'Test secret',
|
||||
name='test_secret',
|
||||
created = self.connection.create_secret(name='test_secret',
|
||||
payload='Test secret',
|
||||
algorithm='aes',
|
||||
bit_length=256,
|
||||
cypher_type='CDC',
|
||||
cypher_type='cbc',
|
||||
expiration='2015-06-07T16:13'
|
||||
':38.889851')
|
||||
':38.889851',
|
||||
payload_content_type=
|
||||
'text/plain')
|
||||
self.assertTrue(self._are_equivalent(secret, created))
|
||||
|
||||
def test_should_create_order(self):
|
||||
@@ -137,12 +137,13 @@ class WhenTestingConnection(unittest.TestCase):
|
||||
"updated": "2013-06-07T19:00:37.338386",
|
||||
"created": "2013-06-07T19:00:37.298704",
|
||||
"secret": {
|
||||
"cypher_type": "CDC",
|
||||
"name": "test_secret",
|
||||
"algorithm": "aes",
|
||||
"expiration": "2015-06-07T19:00:37.298704",
|
||||
"bit_length": 256,
|
||||
"mime_type": "text/plain"
|
||||
'cypher_type': 'cbc',
|
||||
'name': 'test_secret',
|
||||
'algorithm': 'aes',
|
||||
'created': '2013-06-07T16:13:38.889851',
|
||||
'expiration': '2015-06-07T16:13:38.889851',
|
||||
'bit_length': 256,
|
||||
'payload_content_type': 'application/octet-stream'
|
||||
},
|
||||
"order_ref": "http://localhost:9311/v1/12345/orders/003f2b91-"
|
||||
"2f53-4c0a-a0f3-33796671efc3"
|
||||
@@ -150,11 +151,11 @@ class WhenTestingConnection(unittest.TestCase):
|
||||
|
||||
order = client.Order(self.connection, body)
|
||||
self.request.return_value.content = json.dumps(body)
|
||||
created = self.connection.create_order('text/plain',
|
||||
name='test_secret',
|
||||
bit_length=256,
|
||||
created = self.connection.create_order(name='test_secret',
|
||||
payload_content_type='application/octet-stream',
|
||||
algorithm='aes',
|
||||
cypher_type='CDC')
|
||||
bit_length=256,
|
||||
cypher_type='cbc')
|
||||
self.assertTrue(self._are_equivalent(order, created))
|
||||
|
||||
def test_list_no_secrets(self):
|
||||
|
||||
Reference in New Issue
Block a user