diff --git a/chevah/keycert/exceptions.py b/chevah/keycert/exceptions.py index ebb3287..cdfc028 100644 --- a/chevah/keycert/exceptions.py +++ b/chevah/keycert/exceptions.py @@ -14,3 +14,18 @@ def __init__(self, message): def __str__(self): return self.message.encode('utf-8') + + +class BadKeyError(KeyCertException): + """ + Raised when a key isn't what we expected from it. + + XXX: we really need to check for bad keys + """ + + +class EncryptedKeyError(KeyCertException): + """ + Raised when an encrypted key is presented to fromString/fromFile without + a password. + """ diff --git a/chevah/keycert/ssh.py b/chevah/keycert/ssh.py index 43f3b47..3cb1765 100644 --- a/chevah/keycert/ssh.py +++ b/chevah/keycert/ssh.py @@ -23,9 +23,12 @@ from chevah.compat import local_filesystem -from chevah.keycert import _path -from chevah.keycert import common, sexpy - +from chevah.keycert import common, sexpy, _path +from chevah.keycert.exceptions import ( + BadKeyError, + EncryptedKeyError, + KeyCertException, + ) DEFAULT_PUBLIC_KEY_EXTENSION = u'.pub' DEFAULT_KEY_SIZE = 1024 @@ -35,27 +38,6 @@ ID_SHA1 = '\x30\x21\x30\x09\x06\x05\x2b\x0e\x03\x02\x1a\x05\x00\x04\x14' -class BadKeyError(Exception): - """ - Raised when a key isn't what we expected from it. - - XXX: we really need to check for bad keys - """ - - -class EncryptedKeyError(Exception): - """ - Raised when an encrypted key is presented to fromString/fromFile without - a password. - """ - - -class KeyCertException(Exception): - """ - General exception raised by this module. - """ - - def generate_ssh_key_parser( subparsers, name, default_key_size=2048, default_key_type='rsa'): """ @@ -157,9 +139,12 @@ def generate_ssh_key(options, open_method=None): exit_code = 0 - except KeyCertException, error: + except KeyCertException as error: exit_code = 1 message = error.message + except Exception as error: + exit_code = 1 + message = str(error) return (exit_code, message, key) @@ -1607,7 +1592,7 @@ def objectType(obj): try: return keyDataMapping[tuple(obj.keydata)] except (KeyError, AttributeError): - raise BadKeyError("invalid key object", obj) + raise BadKeyError("invalid key object") def pkcs1Pad(data, messageLength): diff --git a/chevah/keycert/ssl.py b/chevah/keycert/ssl.py index b5805d8..66e217e 100644 --- a/chevah/keycert/ssl.py +++ b/chevah/keycert/ssl.py @@ -228,8 +228,11 @@ def generate_and_store_csr(options, encoding='utf-8'): result = generate_csr(options) - with open(_path(options.key_file, encoding), 'wb') as store_file: - store_file.write(result['key_pem']) + try: + with open(_path(options.key_file, encoding), 'wb') as store_file: + store_file.write(result['key_pem']) - with open(_path(csr_name, encoding), 'wb') as store_file: - store_file.write(result['csr_pem']) + with open(_path(csr_name, encoding), 'wb') as store_file: + store_file.write(result['csr_pem']) + except Exception, error: + raise KeyCertException(str(error)) diff --git a/chevah/keycert/tests/test_ssh.py b/chevah/keycert/tests/test_ssh.py index 526f3ef..a5150d7 100644 --- a/chevah/keycert/tests/test_ssh.py +++ b/chevah/keycert/tests/test_ssh.py @@ -16,10 +16,12 @@ # Twisted test compatibility. from chevah.keycert import ssh as keys, common, sexpy -from chevah.keycert.ssh import ( +from chevah.keycert.exceptions import ( BadKeyError, KeyCertException, EncryptedKeyError, + ) +from chevah.keycert.ssh import ( Key, generate_ssh_key, generate_ssh_key_parser, @@ -1961,3 +1963,21 @@ def test_generate_ssh_key_public_exist(self): self.assertEqual(u'Public key already exists. %s' % path, message) # Open is not called. self.assertIsEmpty(open_method.calls) + + def test_generate_ssh_key_fail_to_write(self): + """ + Will return an error when failing to write the key. + """ + options = self.parseArguments([ + self.sub_command_name, + '--key-type=RSA', + '--key-size=1024', + '--key-file', 'no-such-parent/ssh.key', + ]) + + exit_code, message, key = generate_ssh_key(options) + + self.assertEqual(1, exit_code) + self.assertEqual( + "[Errno 2] No such file or directory: 'no-such-parent/ssh.key'", + message) diff --git a/chevah/keycert/tests/test_ssl.py b/chevah/keycert/tests/test_ssl.py index 09710f7..6b39785 100644 --- a/chevah/keycert/tests/test_ssl.py +++ b/chevah/keycert/tests/test_ssl.py @@ -358,3 +358,21 @@ def test_key_and_csr(self): csr_content = mk.fs.getFileContent(csr_segments) csr = crypto.load_certificate_request(crypto.FILETYPE_PEM, csr_content) self.assertEqual(u'domain.com', csr.get_subject().CN) + + def test_store_error(self): + """ + Raise an exception when failing to write the file. + """ + options = self.parseArguments([ + self.command_name, + '--common-name=domain.com', + '--key-file', 'no-such/parent/key.file', + '--key-size=512', + ]) + + with self.assertRaises(KeyCertException) as context: + generate_and_store_csr(options) + + self.assertEqual( + "[Errno 2] No such file or directory: 'no-such/parent/key.file'", + context.exception.message) diff --git a/keycert-demo.py b/keycert-demo.py index 1571a8f..2023afd 100644 --- a/keycert-demo.py +++ b/keycert-demo.py @@ -32,8 +32,8 @@ options = parser.parse_args() try: - options.handler(options) - print('command succeed') + result = options.handler(options) + print(result) except KeyCertException as error: print(error) sys.exit(1) diff --git a/release-notes.rst b/release-notes.rst index 0ff5a58..0010fa2 100644 --- a/release-notes.rst +++ b/release-notes.rst @@ -2,6 +2,13 @@ Relese notes for Chevah KeyCert ############################### +1.3.5 - 27/04/2015 +================== + +* Handle all errors when writing files on disk. +* Raise all public errors based on exceptions.KeyCertException + + 1.3.4 - 20/04/2015 ================== diff --git a/setup.py b/setup.py index ad43d73..4087528 100644 --- a/setup.py +++ b/setup.py @@ -6,7 +6,7 @@ from setuptools import setup, find_packages from setuptools.command.test import test as TestCommand -VERSION = '1.3.4' +VERSION = '1.3.5' class NoseTestCommand(TestCommand):