Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .codeclimate.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
languages:
JavaScript: false
Python: true
5 changes: 3 additions & 2 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ addons:
apt:
packages:
- expect-dev # provides unbuffer utility
- unixodbc-dev

language: python

Expand All @@ -15,7 +14,8 @@ virtualenv:
install:
- pip install coveralls
- pip install codecov --user
- pip install -r test_requirements.txt
- pip install codeclimate-test-reporter
- pip install -r requirements.txt
- pip install .

# command to run tests
Expand All @@ -25,3 +25,4 @@ script:
after_success:
- coveralls
- codecov
- codeclimate-test-reporter
32 changes: 30 additions & 2 deletions README.rst
Original file line number Diff line number Diff line change
@@ -1,2 +1,30 @@
# cfssl-py
Python Library for CloudFlare CFSSL
| |Build Status| | |Coveralls Status| | |Codecov Status| | |Code Climate|

Python CFSSL Library
====================

This library allows you to interact with a remote CFSSL using Python.

Installation
------------

Setup
-----

Usage
-----

Known Issues / Road Map
-----------------------

- Installation, setup, usage - in ReadMe
- Add a Certificate Request data structure

.. |Build Status| image:: https://api.travis-ci.org/laslabs/Python-CFSSL.svg?branch=master
:target: https://travis-ci.org/laslabs/Python-CFSSL
.. |Coveralls Status| image:: https://coveralls.io/repos/laslabs/Python-CFSSL/badge.svg?branch=master
:target: https://coveralls.io/r/laslabs/Python-CFSSL?branch=master
.. |Codecov Status| image:: https://codecov.io/gh/laslabs/Python-CFSSL/branch/master/graph/badge.svg
:target: https://codecov.io/gh/laslabs/Python-CFSSL
.. |Code Climate| image:: https://codeclimate.com/github/laslabs/Python-CFSSL/badges/gpa.svg
:target: https://codeclimate.com/github/laslabs/Python-CFSSL
5 changes: 5 additions & 0 deletions cfssl/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# -*- coding: utf-8 -*-
# Copyright 2016 LasLabs Inc.
# License MIT (https://opensource.org/licenses/MIT).

from .cfssl import CFSSL
381 changes: 381 additions & 0 deletions cfssl/cfssl.py

Large diffs are not rendered by default.

13 changes: 13 additions & 0 deletions cfssl/exceptions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# -*- coding: utf-8 -*-
# Copyright 2016 LasLabs Inc.
# License MIT (https://opensource.org/licenses/MIT).

import requests


class CFSSLException(EnvironmentError):
""" This exception is raised from errors in the CFSSL Library. """


class CFSSLRemoteException(CFSSLException):
""" This exception is raised to indicate issues returned from API. """
3 changes: 3 additions & 0 deletions cfssl/tests/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# -*- coding: utf-8 -*-
# Copyright 2016 LasLabs Inc.
# License MIT (https://opensource.org/licenses/MIT).
171 changes: 171 additions & 0 deletions cfssl/tests/test_cfssl.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
# -*- coding: utf-8 -*-
# Copyright 2016 LasLabs Inc.
# License MIT (https://opensource.org/licenses/MIT).

import mock
import unittest

from ..cfssl import CFSSL, CFSSLRemoteException, requests


class TestCFSSL(unittest.TestCase):

def setUp(self):
super(TestCFSSL, self).setUp()
self.cfssl = CFSSL('test', 1)

def test_uri_base_https(self):
""" It should have an HTTP URI by default """
self.assertIn('https://', self.cfssl.uri_base)

def test_uri_base_http(self):
""" It should have an HTTP URI if someone decides to be crazy """
cfssl = CFSSL('test', 1, False)
self.assertIn('http://', cfssl.uri_base)

@mock.patch.object(CFSSL, 'call')
def test_auth_sign(self, call):
""" It should call with proper args """
expect = {
'token': 'token',
'request': 'request',
}
self.cfssl.auth_sign(**expect)
call.assert_called_once_with(
'authsign', 'POST', data=expect
)

@mock.patch.object(CFSSL, 'call')
def test_bundle(self, call):
""" It should call with proper args """
expect = {
'certificate': 'certificate',
'flavor': 'flavor',
}
self.cfssl.bundle(**expect)
call.assert_called_once_with(
'bundle', 'POST', data=expect
)

@mock.patch.object(CFSSL, 'call')
def test_info(self, call):
""" It should call with proper args """
expect = {
'label': 'label',
}
self.cfssl.info(**expect)
call.assert_called_once_with(
'info', 'POST', data=expect
)

@mock.patch.object(CFSSL, 'call')
def test_init_ca(self, call):
""" It should call with proper args """
expect = {
'hosts': 'hosts',
'names': 'names',
'common_name': 'cn'
}
self.cfssl.init_ca(**expect)
expect['CN'] = 'cn'
del expect['common_name']
call.assert_called_once_with(
'init_ca', 'POST', data=expect
)

@mock.patch.object(CFSSL, 'call')
def test_new_key(self, call):
""" It should call with proper args """
expect = {
'hosts': 'hosts',
'names': 'names',
'common_name': 'cn'
}
self.cfssl.new_key(**expect)
expect['CN'] = 'cn'
del expect['common_name']
call.assert_called_once_with(
'newkey', 'POST', data=expect
)

@mock.patch.object(CFSSL, 'call')
def test_new_cert(self, call):
""" It should call with proper args """
expect = {
'request': 'request',
'label': 'label',
}
self.cfssl.new_cert(**expect)
call.assert_called_once_with(
'newcert', 'POST', data=expect
)

@mock.patch.object(CFSSL, 'call')
def test_revoke(self, call):
""" It should call with proper args """
expect = {
'serial': 'Ben-S',
'authority_key_id': 'REVOKE!',
'reason': 'The derphead lost it',
}
self.cfssl.revoke(**expect)
call.assert_called_once_with(
'revoke', 'POST', data=expect
)

@mock.patch.object(CFSSL, 'call')
def test_scan(self, call):
""" It should call with proper args """
expect = {
'host': 'host',
}
self.cfssl.scan(**expect)
call.assert_called_once_with(
'scan', params=expect
)

@mock.patch.object(CFSSL, 'call')
def test_scan_info(self, call):
""" It should call with proper args """
self.cfssl.scan_info()
call.assert_called_once_with('scaninfo')

@mock.patch.object(CFSSL, 'call')
def test_sign(self, call):
""" It should call with proper args """
expect = {
'certificate_request': 'certificate_request',
}
self.cfssl.sign(**expect)
call.assert_called_once_with(
'sign', 'POST', data=expect
)

@mock.patch.object(requests, 'request')
def test_call_request(self, requests):
""" It should call requests with proper args """
self.cfssl.call('endpoint', 'method', 'params', 'data')
requests.assert_called_once_with(
method='method',
url='https://test:1/api/v1/cfssl/endpoint',
params='params',
data='data',
)

@mock.patch.object(requests, 'request')
def test_call_error(self, requests):
""" It should raise on non-success response """
requests().json.return_value = {'success': False}
with self.assertRaises(CFSSLRemoteException):
self.cfssl.call('None')

@mock.patch.object(requests, 'request')
def test_call_success(self, requests):
""" It should reteurn result on success response """
requests().json.return_value = {'success': True,
'result': 'result'}
res = self.cfssl.call(None)
self.assertEqual(res, 'result')

if __name__ == '__main__':
unittest.main()
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
'author_email': '[email protected]',
'description': 'This library will allow you to interact with CFSSL '
'using Python.',
'url': 'https://github.com/laslabs/cfssl-py',
'url': 'https://github.com/laslabs/Python-CFSSL',
'license': 'MIT',
'classifiers': [
'Development Status :: 4 - Beta',
Expand Down
11 changes: 2 additions & 9 deletions tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,7 @@
# License MIT (https://opensource.org/licenses/MIT).

from setuptools import Command

try:
from xmlrunner import XMLTestRunner
from unittest import TestLoader
except ImportError:
pass
from unittest import TestLoader, TextTestRunner


class FailTestException(Exception):
Expand All @@ -22,8 +17,6 @@ class Tests(Command):
MODULE_NAMES = [
'cfssl',
]
TEST_RESULTS = '_results'
COVERAGE_RESULTS = 'coverage.xml'
user_options = [] # < For Command API compatibility

def initialize_options(self, ):
Expand All @@ -35,7 +28,7 @@ def finalize_options(self, ):
def run(self, ):
loader = TestLoader()
tests = loader.discover('.', 'test_*.py')
t = XMLTestRunner(verbosity=1, output=self.TEST_RESULTS)
t = TextTestRunner(verbosity=1)
res = t.run(tests)
if not res.wasSuccessful():
raise FailTestException()