Merge lp:~maxiberta/launchpad/sshkeyadditionerror-msg-format into lp:launchpad

Proposed by Maximiliano Bertacchini
Status: Merged
Merged at revision: 18689
Proposed branch: lp:~maxiberta/launchpad/sshkeyadditionerror-msg-format
Merge into: lp:launchpad
Diff against target: 112 lines (+38/-8)
4 files modified
lib/lp/registry/interfaces/ssh.py (+25/-1)
lib/lp/registry/model/person.py (+4/-6)
lib/lp/registry/tests/test_ssh.py (+7/-0)
lib/lp/testing/__init__.py (+2/-1)
To merge this branch: bzr merge lp:~maxiberta/launchpad/sshkeyadditionerror-msg-format
Reviewer Review Type Date Requested Status
Colin Watson (community) code Approve
Review via email: mp+348230@code.launchpad.net

Commit message

Fix crash while adding an ssh key with unknown type.

Description of the change

Fix encoding crash while adding an ssh key with unknown type. E.g. on an attempt to add this key in SSO /ssh-keys:

    ssh-rsa asdfasdf comment

LP raises an encoding error and crashes. See https://sentry.ols.canonical.com/canonical/sso/issues/669/.

Also, add a warning to try to prevent a mismatch with SSO regex matching.

To post a comment you must log in.
Revision history for this message
Colin Watson (cjwatson) :
Revision history for this message
Maximiliano Bertacchini (maxiberta) :
Revision history for this message
Colin Watson (cjwatson) :
review: Approve (code)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'lib/lp/registry/interfaces/ssh.py'
2--- lib/lp/registry/interfaces/ssh.py 2018-02-24 09:11:39 +0000
3+++ lib/lp/registry/interfaces/ssh.py 2018-06-20 14:48:20 +0000
4@@ -25,6 +25,7 @@
5 export_as_webservice_entry,
6 exported,
7 )
8+import six
9 from zope.interface import Interface
10 from zope.schema import (
11 Choice,
12@@ -124,4 +125,27 @@
13
14 @error_status(httplib.BAD_REQUEST)
15 class SSHKeyAdditionError(Exception):
16- """Raised when the SSH public key is invalid."""
17+ """Raised when the SSH public key is invalid.
18+
19+ WARNING: Be careful when changing the message format as
20+ SSO uses a regex to recognize it.
21+ """
22+
23+ def __init__(self, *args, **kwargs):
24+ msg = ""
25+ if 'key' in kwargs:
26+ key = kwargs.pop('key')
27+ msg = "Invalid SSH key data: '%s'" % key
28+ if 'kind' in kwargs:
29+ kind = kwargs.pop('kind')
30+ msg = "Invalid SSH key type: '%s'" % kind
31+ if 'exception' in kwargs:
32+ exception = kwargs.pop('exception')
33+ try:
34+ exception_text = six.text_type(exception)
35+ except UnicodeDecodeError:
36+ # On Python 2, Key.fromString can raise exceptions with
37+ # non-UTF-8 messages.
38+ exception_text = bytes(exception).decode('unicode_escape')
39+ msg = "%s (%s)" % (msg, exception_text)
40+ super(SSHKeyAdditionError, self).__init__(msg, *args, **kwargs)
41
42=== modified file 'lib/lp/registry/model/person.py'
43--- lib/lp/registry/model/person.py 2018-05-14 10:59:35 +0000
44+++ lib/lp/registry/model/person.py 2018-06-20 14:48:20 +0000
45@@ -4137,8 +4137,7 @@
46 try:
47 Key.fromString(sshkey)
48 except Exception as e:
49- raise SSHKeyAdditionError(
50- "Invalid SSH key data: '%s' (%s)" % (sshkey, e))
51+ raise SSHKeyAdditionError(key=sshkey, exception=e)
52
53 if send_notification:
54 person.security_field_changed(
55@@ -4171,15 +4170,14 @@
56 try:
57 kind, keytext, comment = sshkey.split(' ', 2)
58 except (ValueError, AttributeError):
59- raise SSHKeyAdditionError("Invalid SSH key data: '%s'" % sshkey)
60+ raise SSHKeyAdditionError(key=sshkey)
61
62 if not (kind and keytext and comment):
63- raise SSHKeyAdditionError("Invalid SSH key data: '%s'" % sshkey)
64+ raise SSHKeyAdditionError(key=sshkey)
65
66 keytype = SSH_TEXT_TO_KEY_TYPE.get(kind)
67 if keytype is None:
68- raise SSHKeyAdditionError(
69- "Invalid SSH key type: '%s'" % kind)
70+ raise SSHKeyAdditionError(kind=kind)
71 return keytype, keytext, comment
72
73
74
75=== modified file 'lib/lp/registry/tests/test_ssh.py'
76--- lib/lp/registry/tests/test_ssh.py 2018-02-24 09:11:39 +0000
77+++ lib/lp/registry/tests/test_ssh.py 2018-06-20 14:48:20 +0000
78@@ -172,6 +172,13 @@
79 )
80 self.assertRaisesWithContent(
81 SSHKeyAdditionError,
82+ "Invalid SSH key data: 'ssh-rsa asdfasdf comment' "
83+ u"(unknown blob type: \xc7_)",
84+ keyset.new,
85+ person, 'ssh-rsa asdfasdf comment'
86+ )
87+ self.assertRaisesWithContent(
88+ SSHKeyAdditionError,
89 "Invalid SSH key data: 'None'",
90 keyset.new,
91 person, None
92
93=== modified file 'lib/lp/testing/__init__.py'
94--- lib/lp/testing/__init__.py 2018-06-04 14:02:57 +0000
95+++ lib/lp/testing/__init__.py 2018-06-20 14:48:20 +0000
96@@ -95,6 +95,7 @@
97 import pytz
98 import scandir
99 import simplejson
100+import six
101 from storm.store import Store
102 import subunit
103 import testtools
104@@ -651,7 +652,7 @@
105 match what was raised an AssertionError is raised.
106 """
107 err = self.assertRaises(exception, func, *args, **kwargs)
108- self.assertEqual(exception_content, str(err))
109+ self.assertEqual(exception_content, six.text_type(err))
110
111 def assertBetween(self, lower_bound, variable, upper_bound):
112 """Assert that 'variable' is strictly between two boundaries."""