Skip to content

Commit

Permalink
Merge pull request #24 from chevah/24-ssh-os-error
Browse files Browse the repository at this point in the history
[#24] Convert IOErrors into keycert errors. Raise ssh errors from KeyCertErrors.
  • Loading branch information
adiroiban committed Apr 28, 2015
2 parents 62fdd01 + ee428f2 commit cc73c99
Show file tree
Hide file tree
Showing 8 changed files with 82 additions and 34 deletions.
15 changes: 15 additions & 0 deletions chevah/keycert/exceptions.py
Expand Up @@ -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.
"""
37 changes: 11 additions & 26 deletions chevah/keycert/ssh.py
Expand Up @@ -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
Expand All @@ -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'):
"""
Expand Down Expand Up @@ -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)

Expand Down Expand Up @@ -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):
Expand Down
11 changes: 7 additions & 4 deletions chevah/keycert/ssl.py
Expand Up @@ -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))
22 changes: 21 additions & 1 deletion chevah/keycert/tests/test_ssh.py
Expand Up @@ -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,
Expand Down Expand Up @@ -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)
18 changes: 18 additions & 0 deletions chevah/keycert/tests/test_ssl.py
Expand Up @@ -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)
4 changes: 2 additions & 2 deletions keycert-demo.py
Expand Up @@ -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)
7 changes: 7 additions & 0 deletions release-notes.rst
Expand Up @@ -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
==================

Expand Down
2 changes: 1 addition & 1 deletion setup.py
Expand Up @@ -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):
Expand Down

0 comments on commit cc73c99

Please sign in to comment.