Merge lp:~smoser/ubuntu/trusty/cloud-init/trusty-1461242 into lp:ubuntu/trusty/cloud-init
- Trusty (14.04)
- trusty-1461242
- Merge into trusty
Proposed by
Scott Moser
Status: | Merged |
---|---|
Merged at revision: | 351 |
Proposed branch: | lp:~smoser/ubuntu/trusty/cloud-init/trusty-1461242 |
Merge into: | lp:ubuntu/trusty/cloud-init |
Diff against target: |
411 lines (+294/-31) 6 files modified
.pc/applied-patches (+1/-0) .pc/lp-1461242-generate-ed25519-host-keys.patch/cloudinit/config/cc_ssh.py (+138/-0) cloudinit/config/cc_ssh.py (+33/-30) debian/changelog (+6/-1) debian/patches/lp-1461242-generate-ed25519-host-keys.patch (+115/-0) debian/patches/series (+1/-0) |
To merge this branch: | bzr merge lp:~smoser/ubuntu/trusty/cloud-init/trusty-1461242 |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Ben Howard (community) | Approve | ||
Dan Watkins | Pending | ||
Review via email: mp+270711@code.launchpad.net |
Commit message
Description of the change
To post a comment you must log in.
- 352. By Scott Moser
-
remove use of 'decode_binary'
there is no 'decode_binary' here.
the return values from subp in python2 are strings.
Revision history for this message
Ben Howard (darkmuggle-deactivatedaccount) wrote : | # |
review:
Approve
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file '.pc/applied-patches' | |||
2 | --- .pc/applied-patches 2015-09-10 16:24:44 +0000 | |||
3 | +++ .pc/applied-patches 2015-09-10 16:50:23 +0000 | |||
4 | @@ -14,3 +14,4 @@ | |||
5 | 14 | lp-1470890-include-regions-in-dynamic-mirror-discovery.patch | 14 | lp-1470890-include-regions-in-dynamic-mirror-discovery.patch |
6 | 15 | lp-1490796-azure-fix-mount_cb-for-symlinks.patch | 15 | lp-1490796-azure-fix-mount_cb-for-symlinks.patch |
7 | 16 | lp-1469260-fix-consumption-of-vendor-data.patch | 16 | lp-1469260-fix-consumption-of-vendor-data.patch |
8 | 17 | lp-1461242-generate-ed25519-host-keys.patch | ||
9 | 17 | 18 | ||
10 | === added directory '.pc/lp-1461242-generate-ed25519-host-keys.patch' | |||
11 | === added directory '.pc/lp-1461242-generate-ed25519-host-keys.patch/cloudinit' | |||
12 | === added directory '.pc/lp-1461242-generate-ed25519-host-keys.patch/cloudinit/config' | |||
13 | === added file '.pc/lp-1461242-generate-ed25519-host-keys.patch/cloudinit/config/cc_ssh.py' | |||
14 | --- .pc/lp-1461242-generate-ed25519-host-keys.patch/cloudinit/config/cc_ssh.py 1970-01-01 00:00:00 +0000 | |||
15 | +++ .pc/lp-1461242-generate-ed25519-host-keys.patch/cloudinit/config/cc_ssh.py 2015-09-10 16:50:23 +0000 | |||
16 | @@ -0,0 +1,138 @@ | |||
17 | 1 | # vi: ts=4 expandtab | ||
18 | 2 | # | ||
19 | 3 | # Copyright (C) 2009-2010 Canonical Ltd. | ||
20 | 4 | # Copyright (C) 2012, 2013 Hewlett-Packard Development Company, L.P. | ||
21 | 5 | # | ||
22 | 6 | # Author: Scott Moser <scott.moser@canonical.com> | ||
23 | 7 | # Author: Juerg Haefliger <juerg.haefliger@hp.com> | ||
24 | 8 | # | ||
25 | 9 | # This program is free software: you can redistribute it and/or modify | ||
26 | 10 | # it under the terms of the GNU General Public License version 3, as | ||
27 | 11 | # published by the Free Software Foundation. | ||
28 | 12 | # | ||
29 | 13 | # This program is distributed in the hope that it will be useful, | ||
30 | 14 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
31 | 15 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
32 | 16 | # GNU General Public License for more details. | ||
33 | 17 | # | ||
34 | 18 | # You should have received a copy of the GNU General Public License | ||
35 | 19 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
36 | 20 | |||
37 | 21 | import glob | ||
38 | 22 | import os | ||
39 | 23 | |||
40 | 24 | # Ensure this is aliased to a name not 'distros' | ||
41 | 25 | # since the module attribute 'distros' | ||
42 | 26 | # is a list of distros that are supported, not a sub-module | ||
43 | 27 | from cloudinit import distros as ds | ||
44 | 28 | |||
45 | 29 | from cloudinit import ssh_util | ||
46 | 30 | from cloudinit import util | ||
47 | 31 | |||
48 | 32 | DISABLE_ROOT_OPTS = ("no-port-forwarding,no-agent-forwarding," | ||
49 | 33 | "no-X11-forwarding,command=\"echo \'Please login as the user \\\"$USER\\\" " | ||
50 | 34 | "rather than the user \\\"root\\\".\';echo;sleep 10\"") | ||
51 | 35 | |||
52 | 36 | KEY_2_FILE = { | ||
53 | 37 | "rsa_private": ("/etc/ssh/ssh_host_rsa_key", 0600), | ||
54 | 38 | "rsa_public": ("/etc/ssh/ssh_host_rsa_key.pub", 0644), | ||
55 | 39 | "dsa_private": ("/etc/ssh/ssh_host_dsa_key", 0600), | ||
56 | 40 | "dsa_public": ("/etc/ssh/ssh_host_dsa_key.pub", 0644), | ||
57 | 41 | "ecdsa_private": ("/etc/ssh/ssh_host_ecdsa_key", 0600), | ||
58 | 42 | "ecdsa_public": ("/etc/ssh/ssh_host_ecdsa_key.pub", 0644), | ||
59 | 43 | } | ||
60 | 44 | |||
61 | 45 | PRIV_2_PUB = { | ||
62 | 46 | 'rsa_private': 'rsa_public', | ||
63 | 47 | 'dsa_private': 'dsa_public', | ||
64 | 48 | 'ecdsa_private': 'ecdsa_public', | ||
65 | 49 | } | ||
66 | 50 | |||
67 | 51 | KEY_GEN_TPL = 'o=$(ssh-keygen -yf "%s") && echo "$o" root@localhost > "%s"' | ||
68 | 52 | |||
69 | 53 | GENERATE_KEY_NAMES = ['rsa', 'dsa', 'ecdsa'] | ||
70 | 54 | |||
71 | 55 | KEY_FILE_TPL = '/etc/ssh/ssh_host_%s_key' | ||
72 | 56 | |||
73 | 57 | |||
74 | 58 | def handle(_name, cfg, cloud, log, _args): | ||
75 | 59 | |||
76 | 60 | # remove the static keys from the pristine image | ||
77 | 61 | if cfg.get("ssh_deletekeys", True): | ||
78 | 62 | key_pth = os.path.join("/etc/ssh/", "ssh_host_*key*") | ||
79 | 63 | for f in glob.glob(key_pth): | ||
80 | 64 | try: | ||
81 | 65 | util.del_file(f) | ||
82 | 66 | except: | ||
83 | 67 | util.logexc(log, "Failed deleting key file %s", f) | ||
84 | 68 | |||
85 | 69 | if "ssh_keys" in cfg: | ||
86 | 70 | # if there are keys in cloud-config, use them | ||
87 | 71 | for (key, val) in cfg["ssh_keys"].iteritems(): | ||
88 | 72 | if key in KEY_2_FILE: | ||
89 | 73 | tgt_fn = KEY_2_FILE[key][0] | ||
90 | 74 | tgt_perms = KEY_2_FILE[key][1] | ||
91 | 75 | util.write_file(tgt_fn, val, tgt_perms) | ||
92 | 76 | |||
93 | 77 | for (priv, pub) in PRIV_2_PUB.iteritems(): | ||
94 | 78 | if pub in cfg['ssh_keys'] or not priv in cfg['ssh_keys']: | ||
95 | 79 | continue | ||
96 | 80 | pair = (KEY_2_FILE[priv][0], KEY_2_FILE[pub][0]) | ||
97 | 81 | cmd = ['sh', '-xc', KEY_GEN_TPL % pair] | ||
98 | 82 | try: | ||
99 | 83 | # TODO(harlowja): Is this guard needed? | ||
100 | 84 | with util.SeLinuxGuard("/etc/ssh", recursive=True): | ||
101 | 85 | util.subp(cmd, capture=False) | ||
102 | 86 | log.debug("Generated a key for %s from %s", pair[0], pair[1]) | ||
103 | 87 | except: | ||
104 | 88 | util.logexc(log, "Failed generated a key for %s from %s", | ||
105 | 89 | pair[0], pair[1]) | ||
106 | 90 | else: | ||
107 | 91 | # if not, generate them | ||
108 | 92 | genkeys = util.get_cfg_option_list(cfg, | ||
109 | 93 | 'ssh_genkeytypes', | ||
110 | 94 | GENERATE_KEY_NAMES) | ||
111 | 95 | for keytype in genkeys: | ||
112 | 96 | keyfile = KEY_FILE_TPL % (keytype) | ||
113 | 97 | util.ensure_dir(os.path.dirname(keyfile)) | ||
114 | 98 | if not os.path.exists(keyfile): | ||
115 | 99 | cmd = ['ssh-keygen', '-t', keytype, '-N', '', '-f', keyfile] | ||
116 | 100 | try: | ||
117 | 101 | # TODO(harlowja): Is this guard needed? | ||
118 | 102 | with util.SeLinuxGuard("/etc/ssh", recursive=True): | ||
119 | 103 | util.subp(cmd, capture=False) | ||
120 | 104 | except: | ||
121 | 105 | util.logexc(log, "Failed generating key type %s to " | ||
122 | 106 | "file %s", keytype, keyfile) | ||
123 | 107 | |||
124 | 108 | try: | ||
125 | 109 | (users, _groups) = ds.normalize_users_groups(cfg, cloud.distro) | ||
126 | 110 | (user, _user_config) = ds.extract_default(users) | ||
127 | 111 | disable_root = util.get_cfg_option_bool(cfg, "disable_root", True) | ||
128 | 112 | disable_root_opts = util.get_cfg_option_str(cfg, "disable_root_opts", | ||
129 | 113 | DISABLE_ROOT_OPTS) | ||
130 | 114 | |||
131 | 115 | keys = cloud.get_public_ssh_keys() or [] | ||
132 | 116 | if "ssh_authorized_keys" in cfg: | ||
133 | 117 | cfgkeys = cfg["ssh_authorized_keys"] | ||
134 | 118 | keys.extend(cfgkeys) | ||
135 | 119 | |||
136 | 120 | apply_credentials(keys, user, disable_root, disable_root_opts) | ||
137 | 121 | except: | ||
138 | 122 | util.logexc(log, "Applying ssh credentials failed!") | ||
139 | 123 | |||
140 | 124 | |||
141 | 125 | def apply_credentials(keys, user, disable_root, disable_root_opts): | ||
142 | 126 | |||
143 | 127 | keys = set(keys) | ||
144 | 128 | if user: | ||
145 | 129 | ssh_util.setup_user_keys(keys, user) | ||
146 | 130 | |||
147 | 131 | if disable_root: | ||
148 | 132 | if not user: | ||
149 | 133 | user = "NONE" | ||
150 | 134 | key_prefix = disable_root_opts.replace('$USER', user) | ||
151 | 135 | else: | ||
152 | 136 | key_prefix = '' | ||
153 | 137 | |||
154 | 138 | ssh_util.setup_user_keys(keys, 'root', options=key_prefix) | ||
155 | 0 | 139 | ||
156 | === modified file 'cloudinit/config/cc_ssh.py' | |||
157 | --- cloudinit/config/cc_ssh.py 2013-07-10 13:35:59 +0000 | |||
158 | +++ cloudinit/config/cc_ssh.py 2015-09-10 16:50:23 +0000 | |||
159 | @@ -20,6 +20,7 @@ | |||
160 | 20 | 20 | ||
161 | 21 | import glob | 21 | import glob |
162 | 22 | import os | 22 | import os |
163 | 23 | import sys | ||
164 | 23 | 24 | ||
165 | 24 | # Ensure this is aliased to a name not 'distros' | 25 | # Ensure this is aliased to a name not 'distros' |
166 | 25 | # since the module attribute 'distros' | 26 | # since the module attribute 'distros' |
167 | @@ -33,27 +34,19 @@ | |||
168 | 33 | "no-X11-forwarding,command=\"echo \'Please login as the user \\\"$USER\\\" " | 34 | "no-X11-forwarding,command=\"echo \'Please login as the user \\\"$USER\\\" " |
169 | 34 | "rather than the user \\\"root\\\".\';echo;sleep 10\"") | 35 | "rather than the user \\\"root\\\".\';echo;sleep 10\"") |
170 | 35 | 36 | ||
179 | 36 | KEY_2_FILE = { | 37 | GENERATE_KEY_NAMES = ['rsa', 'dsa', 'ecdsa', 'ed25519'] |
180 | 37 | "rsa_private": ("/etc/ssh/ssh_host_rsa_key", 0600), | 38 | KEY_FILE_TPL = '/etc/ssh/ssh_host_%s_key' |
173 | 38 | "rsa_public": ("/etc/ssh/ssh_host_rsa_key.pub", 0644), | ||
174 | 39 | "dsa_private": ("/etc/ssh/ssh_host_dsa_key", 0600), | ||
175 | 40 | "dsa_public": ("/etc/ssh/ssh_host_dsa_key.pub", 0644), | ||
176 | 41 | "ecdsa_private": ("/etc/ssh/ssh_host_ecdsa_key", 0600), | ||
177 | 42 | "ecdsa_public": ("/etc/ssh/ssh_host_ecdsa_key.pub", 0644), | ||
178 | 43 | } | ||
181 | 44 | 39 | ||
187 | 45 | PRIV_2_PUB = { | 40 | CONFIG_KEY_TO_FILE = {} |
188 | 46 | 'rsa_private': 'rsa_public', | 41 | PRIV_TO_PUB = {} |
189 | 47 | 'dsa_private': 'dsa_public', | 42 | for k in GENERATE_KEY_NAMES: |
190 | 48 | 'ecdsa_private': 'ecdsa_public', | 43 | CONFIG_KEY_TO_FILE.update({"%s_private" % k: (KEY_FILE_TPL % k, 0o600)}) |
191 | 49 | } | 44 | CONFIG_KEY_TO_FILE.update( |
192 | 45 | {"%s_public" % k: (KEY_FILE_TPL % k + ".pub", 0o600)}) | ||
193 | 46 | PRIV_TO_PUB["%s_private" % k] = "%s_public" % k | ||
194 | 50 | 47 | ||
195 | 51 | KEY_GEN_TPL = 'o=$(ssh-keygen -yf "%s") && echo "$o" root@localhost > "%s"' | 48 | KEY_GEN_TPL = 'o=$(ssh-keygen -yf "%s") && echo "$o" root@localhost > "%s"' |
196 | 52 | 49 | ||
197 | 53 | GENERATE_KEY_NAMES = ['rsa', 'dsa', 'ecdsa'] | ||
198 | 54 | |||
199 | 55 | KEY_FILE_TPL = '/etc/ssh/ssh_host_%s_key' | ||
200 | 56 | |||
201 | 57 | 50 | ||
202 | 58 | def handle(_name, cfg, cloud, log, _args): | 51 | def handle(_name, cfg, cloud, log, _args): |
203 | 59 | 52 | ||
204 | @@ -69,15 +62,15 @@ | |||
205 | 69 | if "ssh_keys" in cfg: | 62 | if "ssh_keys" in cfg: |
206 | 70 | # if there are keys in cloud-config, use them | 63 | # if there are keys in cloud-config, use them |
207 | 71 | for (key, val) in cfg["ssh_keys"].iteritems(): | 64 | for (key, val) in cfg["ssh_keys"].iteritems(): |
211 | 72 | if key in KEY_2_FILE: | 65 | if key in CONFIG_KEY_TO_FILE: |
212 | 73 | tgt_fn = KEY_2_FILE[key][0] | 66 | tgt_fn = CONFIG_KEY_TO_FILE[key][0] |
213 | 74 | tgt_perms = KEY_2_FILE[key][1] | 67 | tgt_perms = CONFIG_KEY_TO_FILE[key][1] |
214 | 75 | util.write_file(tgt_fn, val, tgt_perms) | 68 | util.write_file(tgt_fn, val, tgt_perms) |
215 | 76 | 69 | ||
217 | 77 | for (priv, pub) in PRIV_2_PUB.iteritems(): | 70 | for (priv, pub) in PRIV_TO_PUB.items(): |
218 | 78 | if pub in cfg['ssh_keys'] or not priv in cfg['ssh_keys']: | 71 | if pub in cfg['ssh_keys'] or not priv in cfg['ssh_keys']: |
219 | 79 | continue | 72 | continue |
221 | 80 | pair = (KEY_2_FILE[priv][0], KEY_2_FILE[pub][0]) | 73 | pair = (CONFIG_KEY_TO_FILE[priv][0], CONFIG_KEY_TO_FILE[pub][0]) |
222 | 81 | cmd = ['sh', '-xc', KEY_GEN_TPL % pair] | 74 | cmd = ['sh', '-xc', KEY_GEN_TPL % pair] |
223 | 82 | try: | 75 | try: |
224 | 83 | # TODO(harlowja): Is this guard needed? | 76 | # TODO(harlowja): Is this guard needed? |
225 | @@ -92,18 +85,28 @@ | |||
226 | 92 | genkeys = util.get_cfg_option_list(cfg, | 85 | genkeys = util.get_cfg_option_list(cfg, |
227 | 93 | 'ssh_genkeytypes', | 86 | 'ssh_genkeytypes', |
228 | 94 | GENERATE_KEY_NAMES) | 87 | GENERATE_KEY_NAMES) |
229 | 88 | lang_c = os.environ.copy() | ||
230 | 89 | lang_c['LANG'] = 'C' | ||
231 | 95 | for keytype in genkeys: | 90 | for keytype in genkeys: |
232 | 96 | keyfile = KEY_FILE_TPL % (keytype) | 91 | keyfile = KEY_FILE_TPL % (keytype) |
233 | 92 | if os.path.exists(keyfile): | ||
234 | 93 | continue | ||
235 | 97 | util.ensure_dir(os.path.dirname(keyfile)) | 94 | util.ensure_dir(os.path.dirname(keyfile)) |
238 | 98 | if not os.path.exists(keyfile): | 95 | cmd = ['ssh-keygen', '-t', keytype, '-N', '', '-f', keyfile] |
239 | 99 | cmd = ['ssh-keygen', '-t', keytype, '-N', '', '-f', keyfile] | 96 | |
240 | 97 | # TODO(harlowja): Is this guard needed? | ||
241 | 98 | with util.SeLinuxGuard("/etc/ssh", recursive=True): | ||
242 | 100 | try: | 99 | try: |
249 | 101 | # TODO(harlowja): Is this guard needed? | 100 | out, err = util.subp(cmd, capture=True, env=lang_c) |
250 | 102 | with util.SeLinuxGuard("/etc/ssh", recursive=True): | 101 | sys.stdout.write(out) |
251 | 103 | util.subp(cmd, capture=False) | 102 | except util.ProcessExecutionError as e: |
252 | 104 | except: | 103 | err = e.stderr.lower() |
253 | 105 | util.logexc(log, "Failed generating key type %s to " | 104 | if (e.exit_code == 1 and |
254 | 106 | "file %s", keytype, keyfile) | 105 | err.lower().startswith("unknown key")): |
255 | 106 | log.debug("ssh-keygen: unknown key type '%s'", keytype) | ||
256 | 107 | else: | ||
257 | 108 | util.logexc(log, "Failed generating key type %s to " | ||
258 | 109 | "file %s", keytype, keyfile) | ||
259 | 107 | 110 | ||
260 | 108 | try: | 111 | try: |
261 | 109 | (users, _groups) = ds.normalize_users_groups(cfg, cloud.distro) | 112 | (users, _groups) = ds.normalize_users_groups(cfg, cloud.distro) |
262 | 110 | 113 | ||
263 | === modified file 'debian/changelog' | |||
264 | --- debian/changelog 2015-09-10 16:24:44 +0000 | |||
265 | +++ debian/changelog 2015-09-10 16:50:23 +0000 | |||
266 | @@ -1,10 +1,15 @@ | |||
267 | 1 | cloud-init (0.7.5-0ubuntu1.11) UNRELEASED; urgency=medium | 1 | cloud-init (0.7.5-0ubuntu1.11) UNRELEASED; urgency=medium |
268 | 2 | 2 | ||
269 | 3 | [ Felipe Reyes ] | ||
270 | 3 | * d/patches/fix-consumption-of-vendor-data.patch: | 4 | * d/patches/fix-consumption-of-vendor-data.patch: |
271 | 4 | - Fix consumption of vendor-data in OpenStack to allow namespacing | 5 | - Fix consumption of vendor-data in OpenStack to allow namespacing |
272 | 5 | (LP: #1469260). | 6 | (LP: #1469260). |
273 | 6 | 7 | ||
275 | 7 | -- Felipe Reyes <felipe.reyes@canonical.com> Thu, 10 Sep 2015 12:50:32 -0300 | 8 | [ Scott Moser ] |
276 | 9 | * d/patches/lp-1461242-generate-ed25519-host-keys.patch: | ||
277 | 10 | - ssh: generate ed25519 host keys if supported (LP: #1461242) | ||
278 | 11 | |||
279 | 12 | -- Scott Moser <smoser@ubuntu.com> Thu, 10 Sep 2015 12:36:14 -0400 | ||
280 | 8 | 13 | ||
281 | 9 | cloud-init (0.7.5-0ubuntu1.10) trusty; urgency=medium | 14 | cloud-init (0.7.5-0ubuntu1.10) trusty; urgency=medium |
282 | 10 | 15 | ||
283 | 11 | 16 | ||
284 | === added file 'debian/patches/lp-1461242-generate-ed25519-host-keys.patch' | |||
285 | --- debian/patches/lp-1461242-generate-ed25519-host-keys.patch 1970-01-01 00:00:00 +0000 | |||
286 | +++ debian/patches/lp-1461242-generate-ed25519-host-keys.patch 2015-09-10 16:50:23 +0000 | |||
287 | @@ -0,0 +1,115 @@ | |||
288 | 1 | Author: Scott Moser <smoser@ubuntu.com> | ||
289 | 2 | Bug: https://launchpad.net/bugs/1461242 | ||
290 | 3 | Applied-Upstream: yes | ||
291 | 4 | Origin: http://bazaar.launchpad.net/~cloud-init-dev/cloud-init/trunk/revision/1125 | ||
292 | 5 | Description: ssh: generate ed25519 host keys if supported | ||
293 | 6 | . | ||
294 | 7 | now we attempt to generate ed25519 host keys. | ||
295 | 8 | If ssh-keygen does not support it, a debug log message will be written. | ||
296 | 9 | |||
297 | 10 | === modified file 'cloudinit/config/cc_ssh.py' | ||
298 | 11 | --- a/cloudinit/config/cc_ssh.py | ||
299 | 12 | +++ b/cloudinit/config/cc_ssh.py | ||
300 | 13 | @@ -20,6 +20,7 @@ | ||
301 | 14 | |||
302 | 15 | import glob | ||
303 | 16 | import os | ||
304 | 17 | +import sys | ||
305 | 18 | |||
306 | 19 | # Ensure this is aliased to a name not 'distros' | ||
307 | 20 | # since the module attribute 'distros' | ||
308 | 21 | @@ -33,26 +34,18 @@ DISABLE_ROOT_OPTS = ("no-port-forwarding | ||
309 | 22 | "no-X11-forwarding,command=\"echo \'Please login as the user \\\"$USER\\\" " | ||
310 | 23 | "rather than the user \\\"root\\\".\';echo;sleep 10\"") | ||
311 | 24 | |||
312 | 25 | -KEY_2_FILE = { | ||
313 | 26 | - "rsa_private": ("/etc/ssh/ssh_host_rsa_key", 0600), | ||
314 | 27 | - "rsa_public": ("/etc/ssh/ssh_host_rsa_key.pub", 0644), | ||
315 | 28 | - "dsa_private": ("/etc/ssh/ssh_host_dsa_key", 0600), | ||
316 | 29 | - "dsa_public": ("/etc/ssh/ssh_host_dsa_key.pub", 0644), | ||
317 | 30 | - "ecdsa_private": ("/etc/ssh/ssh_host_ecdsa_key", 0600), | ||
318 | 31 | - "ecdsa_public": ("/etc/ssh/ssh_host_ecdsa_key.pub", 0644), | ||
319 | 32 | -} | ||
320 | 33 | - | ||
321 | 34 | -PRIV_2_PUB = { | ||
322 | 35 | - 'rsa_private': 'rsa_public', | ||
323 | 36 | - 'dsa_private': 'dsa_public', | ||
324 | 37 | - 'ecdsa_private': 'ecdsa_public', | ||
325 | 38 | -} | ||
326 | 39 | - | ||
327 | 40 | -KEY_GEN_TPL = 'o=$(ssh-keygen -yf "%s") && echo "$o" root@localhost > "%s"' | ||
328 | 41 | +GENERATE_KEY_NAMES = ['rsa', 'dsa', 'ecdsa', 'ed25519'] | ||
329 | 42 | +KEY_FILE_TPL = '/etc/ssh/ssh_host_%s_key' | ||
330 | 43 | |||
331 | 44 | -GENERATE_KEY_NAMES = ['rsa', 'dsa', 'ecdsa'] | ||
332 | 45 | +CONFIG_KEY_TO_FILE = {} | ||
333 | 46 | +PRIV_TO_PUB = {} | ||
334 | 47 | +for k in GENERATE_KEY_NAMES: | ||
335 | 48 | + CONFIG_KEY_TO_FILE.update({"%s_private" % k: (KEY_FILE_TPL % k, 0o600)}) | ||
336 | 49 | + CONFIG_KEY_TO_FILE.update( | ||
337 | 50 | + {"%s_public" % k: (KEY_FILE_TPL % k + ".pub", 0o600)}) | ||
338 | 51 | + PRIV_TO_PUB["%s_private" % k] = "%s_public" % k | ||
339 | 52 | |||
340 | 53 | -KEY_FILE_TPL = '/etc/ssh/ssh_host_%s_key' | ||
341 | 54 | +KEY_GEN_TPL = 'o=$(ssh-keygen -yf "%s") && echo "$o" root@localhost > "%s"' | ||
342 | 55 | |||
343 | 56 | |||
344 | 57 | def handle(_name, cfg, cloud, log, _args): | ||
345 | 58 | @@ -69,15 +62,15 @@ def handle(_name, cfg, cloud, log, _args | ||
346 | 59 | if "ssh_keys" in cfg: | ||
347 | 60 | # if there are keys in cloud-config, use them | ||
348 | 61 | for (key, val) in cfg["ssh_keys"].iteritems(): | ||
349 | 62 | - if key in KEY_2_FILE: | ||
350 | 63 | - tgt_fn = KEY_2_FILE[key][0] | ||
351 | 64 | - tgt_perms = KEY_2_FILE[key][1] | ||
352 | 65 | + if key in CONFIG_KEY_TO_FILE: | ||
353 | 66 | + tgt_fn = CONFIG_KEY_TO_FILE[key][0] | ||
354 | 67 | + tgt_perms = CONFIG_KEY_TO_FILE[key][1] | ||
355 | 68 | util.write_file(tgt_fn, val, tgt_perms) | ||
356 | 69 | |||
357 | 70 | - for (priv, pub) in PRIV_2_PUB.iteritems(): | ||
358 | 71 | + for (priv, pub) in PRIV_TO_PUB.items(): | ||
359 | 72 | if pub in cfg['ssh_keys'] or not priv in cfg['ssh_keys']: | ||
360 | 73 | continue | ||
361 | 74 | - pair = (KEY_2_FILE[priv][0], KEY_2_FILE[pub][0]) | ||
362 | 75 | + pair = (CONFIG_KEY_TO_FILE[priv][0], CONFIG_KEY_TO_FILE[pub][0]) | ||
363 | 76 | cmd = ['sh', '-xc', KEY_GEN_TPL % pair] | ||
364 | 77 | try: | ||
365 | 78 | # TODO(harlowja): Is this guard needed? | ||
366 | 79 | @@ -92,18 +85,28 @@ def handle(_name, cfg, cloud, log, _args | ||
367 | 80 | genkeys = util.get_cfg_option_list(cfg, | ||
368 | 81 | 'ssh_genkeytypes', | ||
369 | 82 | GENERATE_KEY_NAMES) | ||
370 | 83 | + lang_c = os.environ.copy() | ||
371 | 84 | + lang_c['LANG'] = 'C' | ||
372 | 85 | for keytype in genkeys: | ||
373 | 86 | keyfile = KEY_FILE_TPL % (keytype) | ||
374 | 87 | + if os.path.exists(keyfile): | ||
375 | 88 | + continue | ||
376 | 89 | util.ensure_dir(os.path.dirname(keyfile)) | ||
377 | 90 | - if not os.path.exists(keyfile): | ||
378 | 91 | - cmd = ['ssh-keygen', '-t', keytype, '-N', '', '-f', keyfile] | ||
379 | 92 | + cmd = ['ssh-keygen', '-t', keytype, '-N', '', '-f', keyfile] | ||
380 | 93 | + | ||
381 | 94 | + # TODO(harlowja): Is this guard needed? | ||
382 | 95 | + with util.SeLinuxGuard("/etc/ssh", recursive=True): | ||
383 | 96 | try: | ||
384 | 97 | - # TODO(harlowja): Is this guard needed? | ||
385 | 98 | - with util.SeLinuxGuard("/etc/ssh", recursive=True): | ||
386 | 99 | - util.subp(cmd, capture=False) | ||
387 | 100 | - except: | ||
388 | 101 | - util.logexc(log, "Failed generating key type %s to " | ||
389 | 102 | - "file %s", keytype, keyfile) | ||
390 | 103 | + out, err = util.subp(cmd, capture=True, env=lang_c) | ||
391 | 104 | + sys.stdout.write(out) | ||
392 | 105 | + except util.ProcessExecutionError as e: | ||
393 | 106 | + err = e.stderr.lower() | ||
394 | 107 | + if (e.exit_code == 1 and | ||
395 | 108 | + err.lower().startswith("unknown key")): | ||
396 | 109 | + log.debug("ssh-keygen: unknown key type '%s'", keytype) | ||
397 | 110 | + else: | ||
398 | 111 | + util.logexc(log, "Failed generating key type %s to " | ||
399 | 112 | + "file %s", keytype, keyfile) | ||
400 | 113 | |||
401 | 114 | try: | ||
402 | 115 | (users, _groups) = ds.normalize_users_groups(cfg, cloud.distro) | ||
403 | 0 | 116 | ||
404 | === modified file 'debian/patches/series' | |||
405 | --- debian/patches/series 2015-09-10 16:24:44 +0000 | |||
406 | +++ debian/patches/series 2015-09-10 16:50:23 +0000 | |||
407 | @@ -14,3 +14,4 @@ | |||
408 | 14 | lp-1470890-include-regions-in-dynamic-mirror-discovery.patch | 14 | lp-1470890-include-regions-in-dynamic-mirror-discovery.patch |
409 | 15 | lp-1490796-azure-fix-mount_cb-for-symlinks.patch | 15 | lp-1490796-azure-fix-mount_cb-for-symlinks.patch |
410 | 16 | lp-1469260-fix-consumption-of-vendor-data.patch | 16 | lp-1469260-fix-consumption-of-vendor-data.patch |
411 | 17 | lp-1461242-generate-ed25519-host-keys.patch |
Tested and okay for merger. It works as expected by creating ed25519 keys in /etc/ssh.
I would merge it, but bzr is complaining of a "readonly transport."