summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJenkins <jenkins@review.openstack.org>2015-05-20 21:58:02 +0000
committerGerrit Code Review <review@openstack.org>2015-05-20 21:58:02 +0000
commit32c6c74b3cd46667745014e18ea5b8bcbd27f650 (patch)
tree9459bbf119328ff5db7556ea8192f312a0dd0a1a
parentf67ae704012ec49bb937131b2c3dd7e467e055a4 (diff)
parentb5ef798446b4fc0b410641ee8c5653ded91a437a (diff)
downloadpython-barbicanclient-32c6c74b3cd46667745014e18ea5b8bcbd27f650.tar.gz
Merge "Add support for certificate order"
-rw-r--r--barbicanclient/barbican_cli/orders.py40
-rw-r--r--barbicanclient/orders.py99
-rw-r--r--barbicanclient/tests/test_orders.py87
3 files changed, 215 insertions, 11 deletions
diff --git a/barbicanclient/barbican_cli/orders.py b/barbicanclient/barbican_cli/orders.py
index d86bd66..60c81a6 100644
--- a/barbicanclient/barbican_cli/orders.py
+++ b/barbicanclient/barbican_cli/orders.py
@@ -47,14 +47,44 @@ class CreateOrder(show.ShowOne):
parser.add_argument('--expiration', '-x',
help='the expiration '
'time for the secret in ISO 8601 format.')
+ parser.add_argument('--request-type',
+ help='the type of the certificate request.')
+ parser.add_argument('--subject-dn',
+ help='the subject of the certificate.')
+ parser.add_argument('--source-container-ref',
+ help='the source of the certificate when using '
+ 'stored-key requests.')
+ parser.add_argument('--ca-id',
+ help='the identifier of the CA to use for the '
+ 'certificate request.')
+ parser.add_argument('--profile',
+ help='the profile of certificate to use.')
+ parser.add_argument('--request-file',
+ help='the file containing the CSR.')
return parser
def take_action(self, args):
- entity = self.app.client.orders.create(
- name=args.name, type=args.type,
- payload_content_type=args.payload_content_type,
- algorithm=args.algorithm, bit_length=args.bit_length,
- mode=args.mode, expiration=args.expiration)
+ if args.type == 'certificate':
+ request_data = None
+ if args.request_file:
+ try:
+ request_data = file(args.request_file).read()
+ except IOError:
+ raise ValueError(
+ 'Couldn\'t read request file %s.' % args.request_file)
+
+ entity = self.app.client.orders.create(
+ name=args.name, type=args.type, subject_dn=args.subject_dn,
+ request_type=args.request_type,
+ source_container_ref=args.source_container_ref,
+ ca_id=args.ca_id, profile=args.profile,
+ request_data=request_data)
+ else:
+ entity = self.app.client.orders.create(
+ name=args.name, type=args.type,
+ payload_content_type=args.payload_content_type,
+ algorithm=args.algorithm, bit_length=args.bit_length,
+ mode=args.mode, expiration=args.expiration)
entity.submit()
return entity._get_formatted_entity()
diff --git a/barbicanclient/orders.py b/barbicanclient/orders.py
index 59ae028..360cbc1 100644
--- a/barbicanclient/orders.py
+++ b/barbicanclient/orders.py
@@ -85,6 +85,31 @@ class AsymmetricOrderFormatter(formatter.EntityFormatter):
return data
+class CertificateOrderFormatter(formatter.EntityFormatter):
+
+ columns = ("Order href",
+ "Type",
+ "Container href",
+ "Secret href",
+ "Created",
+ "Status",
+ "Error code",
+ "Error message"
+ )
+
+ def _get_formatted_data(self):
+ data = (self.order_ref,
+ "Certificate",
+ self.container_ref,
+ "N/A",
+ self.created,
+ self.status,
+ self.error_status_code,
+ self.error_reason
+ )
+ return data
+
+
@six.add_metaclass(abc.ABCMeta)
class Order(object):
"""
@@ -308,6 +333,38 @@ class AsymmetricOrder(Order, AsymmetricOrderFormatter):
return 'AsymmetricOrder(order_ref={0})'.format(self.order_ref)
+class CertificateOrder(Order, CertificateOrderFormatter):
+ _type = 'certificate'
+
+ def __init__(self, api, name=None,
+ status=None, created=None, updated=None, order_ref=None,
+ container_ref=None, error_status_code=None, error_reason=None,
+ sub_status=None, sub_status_message=None, creator_id=None,
+ request_type=None, subject_dn=None,
+ source_container_ref=None, ca_id=None, profile=None,
+ request_data=None):
+ super(CertificateOrder, self).__init__(
+ api, self._type, status=status, created=created, updated=updated,
+ meta={
+ 'name': name,
+ 'request_type': request_type,
+ 'subject_dn': subject_dn,
+ 'container_ref': source_container_ref,
+ 'ca_id': ca_id,
+ 'profile': profile,
+ 'request_data': request_data
+ }, order_ref=order_ref, error_status_code=error_status_code,
+ error_reason=error_reason)
+ self._container_ref = container_ref
+
+ @property
+ def container_ref(self):
+ return self._container_ref
+
+ def __repr__(self):
+ return 'CertificateOrder(order_ref={0})'.format(self.order_ref)
+
+
class OrderManager(base.BaseEntityManager):
"""
Entity Manager for Order entitites
@@ -315,7 +372,8 @@ class OrderManager(base.BaseEntityManager):
_order_type_to_class_map = {
'key': KeyOrder,
- 'asymmetric': AsymmetricOrder
+ 'asymmetric': AsymmetricOrder,
+ 'certificate': CertificateOrder
}
def __init__(self, api):
@@ -345,12 +403,15 @@ class OrderManager(base.BaseEntityManager):
resp_type = response.pop('type').lower()
order_type = self._order_type_to_class_map.get(resp_type)
+ if (resp_type == 'certificate' and
+ 'container_ref' in response.get('meta', ())):
+ response['source_container_ref'] = response['meta'].pop(
+ 'container_ref')
+
response.update(response.pop('meta'))
- if order_type is KeyOrder:
- return KeyOrder(self._api, **response)
- elif order_type is AsymmetricOrder:
- return AsymmetricOrder(self._api, **response)
+ if order_type is not None:
+ return order_type(self._api, **response)
else:
raise TypeError('Unknown Order type "{0}"'.format(order_type))
@@ -412,6 +473,34 @@ class OrderManager(base.BaseEntityManager):
payload_content_type=payload_content_type,
expiration=expiration)
+ def create_certificate(self, name=None, request_type=None, subject_dn=None,
+ source_container_ref=None, ca_id=None,
+ profile=None, request_data=None):
+ """
+ Factory method for `CertificateOrder` objects
+
+ `CertificateOrder` objects returned by this method have not yet been
+ submitted to the Barbican service.
+
+ :param name: A friendly name for the container to be created
+ :param request_type: The type of the certificate request
+ :param subject_dn: A subject for the certificate
+ :param source_container_ref: A container with a public/private key pair
+ to use as source for stored-key requests
+ :param ca_id: The identifier of the CA to use
+ :param profile: The profile of certificate to use
+ :param request_data: The CSR content
+ :returns: CertificateOrder
+ :rtype: :class:`barbicanclient.orders.CertificateOrder`
+ """
+ return CertificateOrder(api=self._api, name=name,
+ request_type=request_type,
+ subject_dn=subject_dn,
+ source_container_ref=source_container_ref,
+ ca_id=ca_id,
+ profile=profile,
+ request_data=request_data)
+
def delete(self, order_ref):
"""
Delete an Order from Barbican
diff --git a/barbicanclient/tests/test_orders.py b/barbicanclient/tests/test_orders.py
index 34e1043..6cabea0 100644
--- a/barbicanclient/tests/test_orders.py
+++ b/barbicanclient/tests/test_orders.py
@@ -237,4 +237,89 @@ class WhenTestingOrderManager(OrdersTestCase):
def test_should_get_total(self):
self.responses.get(self.entity_base, json={'total': 1})
total = self.manager.total()
- self.assertEqual(total, 1)
+
+
+class WhenTestingCertificateOrders(test_client.BaseEntityResource):
+ def setUp(self):
+ self._setUp('orders', entity_id='d0460cc4-2876-4493-b7de-fc5c812883cc')
+
+ self.container_ref = (
+ self.endpoint + '/containers/a2292306-6da0-4f60-bd8a-84fc8d692716')
+ self.source_container_ref = (
+ self.endpoint + '/containers/c6f20480-c1e5-442b-94a0-cb3b5e0cf179')
+
+ self.cert_order_data = """{{
+ "status": "ACTIVE",
+ "container_ref": "{0}",
+ "updated": "2014-10-21T17:15:50.871596",
+ "meta": {{
+ "name": "secretname",
+ "subject_dn": "cn=server.example.com,o=example.com",
+ "request_type": "stored-key",
+ "container_ref": "{1}"
+ }},
+ "created": "2014-10-21T17:15:50.824202",
+ "type": "certificate",
+ "order_ref": "{2}"
+ }}""".format(self.container_ref, self.source_container_ref,
+ self.entity_href)
+
+ self.manager = self.client.orders
+
+ def _get_order_args(self, order_data):
+ order_args = json.loads(order_data)
+ order_args.update(order_args.pop('meta'))
+ order_args.pop('type')
+ return order_args
+
+ def test_get(self):
+ self.responses.get(self.entity_href, text=self.cert_order_data)
+
+ order = self.manager.get(order_ref=self.entity_href)
+ self.assertIsInstance(order, orders.CertificateOrder)
+ self.assertEqual(self.entity_href, order.order_ref)
+
+ # Verify the correct URL was used to make the call.
+ self.assertEqual(self.entity_href, self.responses.last_request.url)
+
+ def test_repr(self):
+ order_args = self._get_order_args(self.cert_order_data)
+ order_obj = orders.CertificateOrder(api=None, **order_args)
+ self.assertIn('order_ref=' + self.entity_href, repr(order_obj))
+
+ def test_constructor(self):
+ data = {'order_ref': self.entity_href}
+ self.responses.post(self.entity_base + '/', json=data)
+
+ order = self.manager.create_certificate(
+ name='name',
+ subject_dn='cn=server.example.com,o=example.com',
+ request_type='stored-key',
+ source_container_ref=self.source_container_ref
+ )
+ order_href = order.submit()
+
+ self.assertEqual(self.entity_href, order_href)
+
+ # Verify the correct URL was used to make the call.
+ self.assertEqual(self.entity_base + '/',
+ self.responses.last_request.url)
+
+ # Verify that correct information was sent in the call.
+ order_req = json.loads(self.responses.last_request.text)
+ self.assertEqual('name', order_req['meta']['name'])
+ self.assertEqual('cn=server.example.com,o=example.com',
+ order_req['meta']['subject_dn'])
+ self.assertEqual('stored-key',
+ order_req['meta']['request_type'])
+ self.assertEqual(self.source_container_ref,
+ order_req['meta']['container_ref'])
+
+ def test_list(self):
+ data = {"orders": [json.loads(self.cert_order_data) for _ in range(3)]}
+ self.responses.get(self.entity_base, json=data)
+
+ orders_list = self.manager.list(limit=10, offset=5)
+ self.assertEqual(len(orders_list), 3)
+ self.assertIsInstance(orders_list[0], orders.CertificateOrder)
+ self.assertEqual(self.entity_href, orders_list[0].order_ref)