xref: /qemu/tests/qemu-iotests/207 (revision c5955f4f)
1#!/usr/bin/env python3
2# group: rw
3#
4# Test ssh image creation
5#
6# Copyright (C) 2018 Red Hat, Inc.
7#
8# Creator/Owner: Kevin Wolf <kwolf@redhat.com>
9#
10# This program is free software; you can redistribute it and/or modify
11# it under the terms of the GNU General Public License as published by
12# the Free Software Foundation; either version 2 of the License, or
13# (at your option) any later version.
14#
15# This program is distributed in the hope that it will be useful,
16# but WITHOUT ANY WARRANTY; without even the implied warranty of
17# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18# GNU General Public License for more details.
19#
20# You should have received a copy of the GNU General Public License
21# along with this program.  If not, see <http://www.gnu.org/licenses/>.
22#
23
24import iotests
25import subprocess
26import re
27
28iotests.script_initialize(
29    supported_fmts=['raw'],
30    supported_protocols=['ssh'],
31)
32
33def filter_hash(qmsg):
34    def _filter(key, value):
35        if key == 'hash' and re.match('[0-9a-f]+', value):
36            return 'HASH'
37        return value
38    if isinstance(qmsg, str):
39        # Strip key type and fingerprint
40        p = r"\S+ (key fingerprint) '(md5|sha1|sha256):[0-9a-f]+'"
41        return re.sub(p, r"\1 '\2:HASH'", qmsg)
42    else:
43        return iotests.filter_qmp(qmsg, _filter)
44
45def blockdev_create(vm, options):
46    vm.blockdev_create(options, filters=[iotests.filter_qmp_testfiles, filter_hash])
47
48with iotests.FilePath('t.img') as disk_path, \
49     iotests.VM() as vm:
50
51    remote_path = iotests.remote_filename(disk_path)
52
53    #
54    # Successful image creation (defaults)
55    #
56    iotests.log("=== Successful image creation (defaults) ===")
57    iotests.log("")
58
59    vm.launch()
60    blockdev_create(vm, { 'driver': 'ssh',
61                          'location': {
62                              'path': disk_path,
63                              'server': {
64                                  'host': '127.0.0.1',
65                                  'port': '22'
66                              }
67                          },
68                          'size': 4194304 })
69    vm.shutdown()
70
71    iotests.img_info_log(remote_path)
72    iotests.log("")
73    iotests.img_info_log(disk_path)
74
75    #
76    # Test host-key-check options
77    #
78    iotests.log("=== Test host-key-check options ===")
79    iotests.log("")
80
81    iotests.log("--- no host key checking --")
82    iotests.log("")
83
84    vm.launch()
85    blockdev_create(vm, { 'driver': 'ssh',
86                          'location': {
87                              'path': disk_path,
88                              'server': {
89                                  'host': '127.0.0.1',
90                                  'port': '22'
91                              },
92                              'host-key-check': {
93                                  'mode': 'none'
94                              }
95                          },
96                          'size': 8388608 })
97    vm.shutdown()
98
99    iotests.img_info_log(remote_path)
100
101    iotests.log("--- known_hosts key checking --")
102    iotests.log("")
103
104    vm.launch()
105    blockdev_create(vm, { 'driver': 'ssh',
106                          'location': {
107                              'path': disk_path,
108                              'server': {
109                                  'host': '127.0.0.1',
110                                  'port': '22'
111                              },
112                              'host-key-check': {
113                                  'mode': 'known_hosts'
114                              }
115                          },
116                          'size': 4194304 })
117    vm.shutdown()
118
119    iotests.img_info_log(remote_path)
120
121    keys = subprocess.check_output(
122        'ssh-keyscan 127.0.0.1 2>/dev/null | grep -v "\\^#" | ' +
123        'cut -d" " -f3',
124        shell=True).rstrip().decode('ascii').split('\n')
125
126    # Mappings of base64 representations to digests
127    md5_keys = {}
128    sha1_keys = {}
129    sha256_keys = {}
130
131    for key in keys:
132        md5_keys[key] = subprocess.check_output(
133            'echo %s | base64 -d | md5sum -b | cut -d" " -f1' % key,
134            shell=True).rstrip().decode('ascii')
135
136        sha1_keys[key] = subprocess.check_output(
137            'echo %s | base64 -d | sha1sum -b | cut -d" " -f1' % key,
138            shell=True).rstrip().decode('ascii')
139
140        sha256_keys[key] = subprocess.check_output(
141            'echo %s | base64 -d | sha256sum -b | cut -d" " -f1' % key,
142            shell=True).rstrip().decode('ascii')
143
144    vm.launch()
145
146    # Find correct key first
147    matching_key = None
148    for key in keys:
149        result = vm.qmp('blockdev-add',
150                        driver='ssh', node_name='node0', path=disk_path,
151                        server={
152                             'host': '127.0.0.1',
153                             'port': '22',
154                        }, host_key_check={
155                             'mode': 'hash',
156                             'type': 'md5',
157                             'hash': md5_keys[key],
158                        })
159
160        if 'error' not in result:
161            vm.qmp('blockdev-del', node_name='node0')
162            matching_key = key
163            break
164
165    if matching_key is None:
166        vm.shutdown()
167        iotests.notrun('Did not find a key that fits 127.0.0.1')
168
169    iotests.log("--- explicit md5 key checking --")
170    iotests.log("")
171
172    blockdev_create(vm, { 'driver': 'ssh',
173                          'location': {
174                              'path': disk_path,
175                              'server': {
176                                  'host': '127.0.0.1',
177                                  'port': '22'
178                              },
179                              'host-key-check': {
180                                  'mode': 'hash',
181                                  'type': 'md5',
182                                  'hash': 'wrong',
183                              }
184                          },
185                          'size': 2097152 })
186
187    blockdev_create(vm, { 'driver': 'ssh',
188                          'location': {
189                              'path': disk_path,
190                              'server': {
191                                  'host': '127.0.0.1',
192                                  'port': '22'
193                              },
194                              'host-key-check': {
195                                  'mode': 'hash',
196                                  'type': 'md5',
197                                  'hash': md5_keys[matching_key],
198                              }
199                          },
200                          'size': 8388608 })
201    vm.shutdown()
202
203    iotests.img_info_log(remote_path)
204
205    iotests.log("--- explicit sha1 key checking --")
206    iotests.log("")
207
208    vm.launch()
209    blockdev_create(vm, { 'driver': 'ssh',
210                          'location': {
211                              'path': disk_path,
212                              'server': {
213                                  'host': '127.0.0.1',
214                                  'port': '22'
215                              },
216                              'host-key-check': {
217                                  'mode': 'hash',
218                                  'type': 'sha1',
219                                  'hash': 'wrong',
220                              }
221                          },
222                          'size': 2097152 })
223    blockdev_create(vm, { 'driver': 'ssh',
224                          'location': {
225                              'path': disk_path,
226                              'server': {
227                                  'host': '127.0.0.1',
228                                  'port': '22'
229                              },
230                              'host-key-check': {
231                                  'mode': 'hash',
232                                  'type': 'sha1',
233                                  'hash': sha1_keys[matching_key],
234                              }
235                          },
236                          'size': 4194304 })
237    vm.shutdown()
238
239    iotests.img_info_log(remote_path)
240
241    iotests.log("--- explicit sha256 key checking --")
242    iotests.log("")
243
244    vm.launch()
245    blockdev_create(vm, { 'driver': 'ssh',
246                          'location': {
247                              'path': disk_path,
248                              'server': {
249                                  'host': '127.0.0.1',
250                                  'port': '22'
251                              },
252                              'host-key-check': {
253                                  'mode': 'hash',
254                                  'type': 'sha256',
255                                  'hash': 'wrong',
256                              }
257                          },
258                          'size': 2097152 })
259    blockdev_create(vm, { 'driver': 'ssh',
260                          'location': {
261                              'path': disk_path,
262                              'server': {
263                                  'host': '127.0.0.1',
264                                  'port': '22'
265                              },
266                              'host-key-check': {
267                                  'mode': 'hash',
268                                  'type': 'sha256',
269                                  'hash': sha256_keys[matching_key],
270                              }
271                          },
272                          'size': 4194304 })
273    vm.shutdown()
274
275    iotests.img_info_log(remote_path)
276
277    #
278    # Invalid path and user
279    #
280    iotests.log("=== Invalid path and user ===")
281    iotests.log("")
282
283    vm.launch()
284    blockdev_create(vm, { 'driver': 'ssh',
285                          'location': {
286                              'path': '/this/is/not/an/existing/path',
287                              'server': {
288                                  'host': '127.0.0.1',
289                                  'port': '22'
290                              },
291                              'host-key-check': {
292                                  'mode': 'none'
293                              }
294                          },
295                          'size': 4194304 })
296    blockdev_create(vm, { 'driver': 'ssh',
297                          'location': {
298                              'path': disk_path,
299                              'user': 'invalid user',
300                              'server': {
301                                  'host': '127.0.0.1',
302                                  'port': '22'
303                              },
304                              'host-key-check': {
305                                  'mode': 'none'
306                              }
307                          },
308                          'size': 4194304 })
309    vm.shutdown()
310