From cc5fd1bac5698dbb67010c0765aae558adafb681 Mon Sep 17 00:00:00 2001 From: Dave Lasley Date: Tue, 20 Dec 2016 19:10:44 -0800 Subject: [PATCH] [IMP] Usability improvements for `init_ca` --- cfssl/cfssl.py | 29 ++++++++++------------------- cfssl/tests/test_cfssl.py | 21 ++++++++++++++++++--- setup.py | 2 +- 3 files changed, 29 insertions(+), 23 deletions(-) diff --git a/cfssl/cfssl.py b/cfssl/cfssl.py index 7ac9c35..7f6c09f 100644 --- a/cfssl/cfssl.py +++ b/cfssl/cfssl.py @@ -159,34 +159,25 @@ def info(self, label, profile=None): }) return self.call('info', 'POST', data=data) - def init_ca(self, hosts, names, common_name=None, key=None, ca=None): + def init_ca(self, certificate_request, ca=None): """ It initializes a new certificate authority. Args: - hosts (:obj:`iter` of :obj:`cfssl.Host`): Subject Alternative Name(s) for the - requested CA certificate. - names (:obj:`iter` of :obj:`cfssl.SubjectInfo`): The Subject Info(s) for the - requested CA certificate. - common_name (:obj:`str`): the common name for the certificate subject in - the requested CA certificate. - key (:obj:`cfssl.ConfigKey`): Cipher and strength to use for certificate. - ca (:obj:`cfssl.ConfigServer`): the CA configuration of the requested CA, - including CA pathlen and CA default expiry. + certificate_request (:obj:`cfssl.CertificateRequest`): The certificate + request to use when creating the CA. + ca (:obj:`cfssl.ConfigServer`, optional): The configuration of the + requested Certificate Authority. Returns: (:obj:`dict`) Mapping with two keys: * private key (:obj:`str`): a PEM-encoded CA private key. * certificate (:obj:`str`): a PEM-encoded self-signed CA certificate. """ - key = key or ConfigKey() + csr_api = certificate_request.to_api() data = self._clean_mapping({ - 'hosts': [ - host.to_api() for host in hosts - ], - 'names': [ - name.to_api() for name in names - ], - 'CN': common_name, - 'key': key and key.to_api() or ConfigKey().to_api(), + 'hosts': csr_api['hosts'], + 'names': csr_api['names'], + 'CN': csr_api['CN'], + 'key': csr_api['key'], 'ca': ca and ca.to_api() or None, }) return self.call('init_ca', 'POST', data=data) diff --git a/cfssl/tests/test_cfssl.py b/cfssl/tests/test_cfssl.py index 7d30490..01c56e1 100644 --- a/cfssl/tests/test_cfssl.py +++ b/cfssl/tests/test_cfssl.py @@ -2,10 +2,21 @@ # Copyright 2016 LasLabs Inc. # License MIT (https://opensource.org/licenses/MIT). +import logging import mock import unittest -from ..cfssl import CFSSL, CFSSLRemoteException, requests +from ..cfssl import (CFSSL, + CFSSLRemoteException, + requests, + ) + +_logger = logging.getLogger(__name__) + +try: + from cfssl import CertificateRequest +except ImportError: + _logger.info('CFSSL Python library not installed.') class TestCFSSL(unittest.TestCase): @@ -62,16 +73,20 @@ def test_info(self, call): @mock.patch.object(CFSSL, 'call') def test_init_ca(self, call): """ It should call with proper args """ - expect = { + csr_vals = { 'hosts': [mock.MagicMock()], 'names': [mock.MagicMock()], 'common_name': 'cn', 'key': mock.MagicMock(), - 'ca': mock.MagicMock(), } + csr = CertificateRequest(**csr_vals) + expect = {'ca': mock.MagicMock(), + 'certificate_request': csr} self.cfssl.init_ca(**expect) + expect.update(csr_vals) expect['CN'] = 'cn' del expect['common_name'] + del expect['certificate_request'] expect['hosts'][0]= expect['hosts'][0].to_api() expect['names'][0] = expect['names'][0].to_api() expect['key'] = expect['key'].to_api() diff --git a/setup.py b/setup.py index 83f2b5d..6a54047 100644 --- a/setup.py +++ b/setup.py @@ -9,7 +9,7 @@ setup_vals = { 'name': 'cfssl', - 'version': '0.0.1', + 'version': '0.0.2', 'author': 'LasLabs Inc.', 'author_email': 'support@laslabs.com', 'description': 'This library will allow you to interact with CFSSL '