Merge lp:~gmb/lpsetup/dont-blow-away-ssh-keys-bug-1018823 into lp:lpsetup

Proposed by Graham Binns
Status: Merged
Approved by: Graham Binns
Approved revision: 41
Merged at revision: 40
Proposed branch: lp:~gmb/lpsetup/dont-blow-away-ssh-keys-bug-1018823
Merge into: lp:lpsetup
Diff against target: 70 lines (+50/-3)
1 file modified
lpsetup/subcommands/inithost.py (+50/-3)
To merge this branch: bzr merge lp:~gmb/lpsetup/dont-blow-away-ssh-keys-bug-1018823
Reviewer Review Type Date Requested Status
Benji York (community) code Approve
Review via email: mp+113192@code.launchpad.net

Commit message

lp-setup will no longer allow you to overwrite your existing SSH keys with new values. Instead, if it encounters an existing SSH key with a value different from the one it's trying to write, it will exit with an error.

Description of the change

This branch fixes the initialize step in init_host so as to prevent the user's SSH keys being overwritten with garbage if they happen to not be paying attention to what they're doing.

I couldn't find any direct tests for initialize(), so I moved the functionality that overwrites the SSH keyfiles out into a utility function and added a doctest for it. The new functionality is to raise an error if the file already exists with different contents from those we're trying to write to it (so opening the file, reading it and then writing its contents back again - our existing behaviour - shouldn't cause problems). I've also updated python-shelltoolboxes generate_ssh_keys() function to ensure that it raises an error should you try to generate new SSH keys with the same name as existing ones.

To post a comment you must log in.
Revision history for this message
Benji York (benji) wrote :

This looks good.

I am a little worried that mode could be something like "w+" or "a+" and that would break the function. Perhaps an assertion that the mode is "w" or "r" and nothing else.

review: Approve (code)
41. By Graham Binns

Added a test to ensure mode sanity.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'lpsetup/subcommands/inithost.py'
2--- lpsetup/subcommands/inithost.py 2012-06-28 10:33:46 +0000
3+++ lpsetup/subcommands/inithost.py 2012-07-03 16:47:18 +0000
4@@ -40,6 +40,55 @@
5 from lpsetup.utils import call
6
7
8+def write_file_contents(filename, contents, mode):
9+ """Write `contents` to filename and chmod it to 0644.
10+
11+ >>> write_file_contents('/tmp/foo', 'Hello, world', 'w')
12+ >>> print open('/tmp/foo', 'r').read()
13+ Hello, world
14+ <BLANKLINE>
15+ >>> os.remove('/tmp/foo')
16+
17+ If the file already exists, `mode` is set to 'w', and the file's
18+ contents differ from `contents`, write_file_contents() raises an
19+ Exception.
20+
21+ >>> write_file_contents('/tmp/foo', 'Hello, world', 'w')
22+ >>> write_file_contents(
23+ ... '/tmp/foo', 'Hello again, world', 'w') # doctest: +ELLIPSIS
24+ Traceback (most recent call last):
25+ Exception: File /tmp/foo already exists with different contents...
26+ >>> os.remove('/tmp/foo')
27+
28+ If the existing file's contents don't differ from `contents`,
29+ write_file_contents() will simply return.
30+
31+ >>> write_file_contents('/tmp/foo', 'Hello, world', 'w')
32+ >>> write_file_contents(
33+ ... '/tmp/foo', 'Hello, world', 'w') # doctest: +ELLIPSIS
34+ >>> os.remove('/tmp/foo')
35+
36+ Passing a `mode` other than "a" or "w' will cause an Exception.
37+
38+ >>> write_file_contents(
39+ ... '/tmp/foo', 'Hello, world', 'w+') # doctest: +ELLIPSIS
40+ Traceback (most recent call last):
41+ AssertionError: Mode should be 'w' or 'a' only...
42+ """
43+ assert mode in ('w', 'a'), "Mode should be 'w' or 'a' only."
44+ if mode == 'w' and os.path.exists(filename):
45+ with open(filename, 'r') as existing_file:
46+ file_contents = existing_file.read()
47+ if file_contents.strip() != contents.strip():
48+ raise Exception(
49+ "File %s already exists with different contents." % filename)
50+ else:
51+ return
52+ with open(filename, mode) as f:
53+ f.write(contents + '\n')
54+ os.chmod(filename, 0644)
55+
56+
57 def initialize(
58 user, full_name, email, lpuser, private_key, public_key, valid_ssh_keys,
59 ssh_key_path, feed_random):
60@@ -71,9 +120,7 @@
61 (auth_file, public_key, 'a'),
62 (known_hosts, known_host_content, 'a'),
63 ]:
64- with open(filename, mode) as f:
65- f.write(contents + '\n')
66- os.chmod(filename, 0644)
67+ write_file_contents(filename, contents, mode)
68 os.chmod(ssh_key_path, 0600)
69 # Set up bzr and Launchpad authentication.
70 call('bzr', 'whoami', formataddr([full_name, email]))

Subscribers

People subscribed via source and target branches