Rewrite the implementation of the ssh block driver to use libssh instead of libssh2. The libssh library has various advantages over libssh2: - easier API for authentication (for example for using ssh-agent) - easier API for known_hosts handling - supports newer types of keys in known_hosts Use APIs/features available in libssh 0.8 conditionally, to support older versions (which are not recommended though). Adjust the iotest 207 according to the different error message, and to find the default key type for localhost (to properly compare the fingerprint with). Contributed-by: Max Reitz <mreitz@redhat.com> Adjust the various Docker/Travis scripts to use libssh when available instead of libssh2. The mingw/mxe testing is dropped for now, as there are no packages for it. Signed-off-by: Pino Toscano <ptoscano@redhat.com> Tested-by: Philippe Mathieu-Daudé <philmd@redhat.com> Acked-by: Alex Bennée <alex.bennee@linaro.org> Message-id: 20190620200840.17655-1-ptoscano@redhat.com Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com> Message-id: 5873173.t2JhDm7DL7@lindworm.usersys.redhat.com Signed-off-by: Max Reitz <mreitz@redhat.com>
254 lines
8.6 KiB
Python
Executable file
254 lines
8.6 KiB
Python
Executable file
#!/usr/bin/env python
|
|
#
|
|
# Test ssh image creation
|
|
#
|
|
# Copyright (C) 2018 Red Hat, Inc.
|
|
#
|
|
# Creator/Owner: Kevin Wolf <kwolf@redhat.com>
|
|
#
|
|
# This program is free software; you can redistribute it and/or modify
|
|
# it under the terms of the GNU General Public License as published by
|
|
# the Free Software Foundation; either version 2 of the License, or
|
|
# (at your option) any later version.
|
|
#
|
|
# This program is distributed in the hope that it will be useful,
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
# GNU General Public License for more details.
|
|
#
|
|
# You should have received a copy of the GNU General Public License
|
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
#
|
|
|
|
import iotests
|
|
import subprocess
|
|
import re
|
|
|
|
iotests.verify_image_format(supported_fmts=['raw'])
|
|
iotests.verify_protocol(supported=['ssh'])
|
|
|
|
def filter_hash(qmsg):
|
|
def _filter(key, value):
|
|
if key == 'hash' and re.match('[0-9a-f]+', value):
|
|
return 'HASH'
|
|
return value
|
|
return iotests.filter_qmp(qmsg, _filter)
|
|
|
|
def blockdev_create(vm, options):
|
|
result = vm.qmp_log('blockdev-create', job_id='job0', options=options,
|
|
filters=[iotests.filter_qmp_testfiles, filter_hash])
|
|
|
|
if 'return' in result:
|
|
assert result['return'] == {}
|
|
vm.run_job('job0')
|
|
iotests.log("")
|
|
|
|
with iotests.FilePath('t.img') as disk_path, \
|
|
iotests.VM() as vm:
|
|
|
|
remote_path = iotests.remote_filename(disk_path)
|
|
|
|
#
|
|
# Successful image creation (defaults)
|
|
#
|
|
iotests.log("=== Successful image creation (defaults) ===")
|
|
iotests.log("")
|
|
|
|
vm.launch()
|
|
blockdev_create(vm, { 'driver': 'ssh',
|
|
'location': {
|
|
'path': disk_path,
|
|
'server': {
|
|
'host': '127.0.0.1',
|
|
'port': '22'
|
|
}
|
|
},
|
|
'size': 4194304 })
|
|
vm.shutdown()
|
|
|
|
iotests.img_info_log(remote_path)
|
|
iotests.log("")
|
|
iotests.img_info_log(disk_path)
|
|
|
|
#
|
|
# Test host-key-check options
|
|
#
|
|
iotests.log("=== Test host-key-check options ===")
|
|
iotests.log("")
|
|
|
|
vm.launch()
|
|
blockdev_create(vm, { 'driver': 'ssh',
|
|
'location': {
|
|
'path': disk_path,
|
|
'server': {
|
|
'host': '127.0.0.1',
|
|
'port': '22'
|
|
},
|
|
'host-key-check': {
|
|
'mode': 'none'
|
|
}
|
|
},
|
|
'size': 8388608 })
|
|
vm.shutdown()
|
|
|
|
iotests.img_info_log(remote_path)
|
|
|
|
vm.launch()
|
|
blockdev_create(vm, { 'driver': 'ssh',
|
|
'location': {
|
|
'path': disk_path,
|
|
'server': {
|
|
'host': '127.0.0.1',
|
|
'port': '22'
|
|
},
|
|
'host-key-check': {
|
|
'mode': 'known_hosts'
|
|
}
|
|
},
|
|
'size': 4194304 })
|
|
vm.shutdown()
|
|
|
|
iotests.img_info_log(remote_path)
|
|
|
|
keys = subprocess.check_output(
|
|
'ssh-keyscan 127.0.0.1 2>/dev/null | grep -v "\\^#" | ' +
|
|
'cut -d" " -f3',
|
|
shell=True).rstrip().decode('ascii').split('\n')
|
|
|
|
# Mappings of base64 representations to digests
|
|
md5_keys = {}
|
|
sha1_keys = {}
|
|
|
|
for key in keys:
|
|
md5_keys[key] = subprocess.check_output(
|
|
'echo %s | base64 -d | md5sum -b | cut -d" " -f1' % key,
|
|
shell=True).rstrip().decode('ascii')
|
|
|
|
sha1_keys[key] = subprocess.check_output(
|
|
'echo %s | base64 -d | sha1sum -b | cut -d" " -f1' % key,
|
|
shell=True).rstrip().decode('ascii')
|
|
|
|
vm.launch()
|
|
|
|
# Find correct key first
|
|
matching_key = None
|
|
for key in keys:
|
|
result = vm.qmp('blockdev-add',
|
|
driver='ssh', node_name='node0', path=disk_path,
|
|
server={
|
|
'host': '127.0.0.1',
|
|
'port': '22',
|
|
}, host_key_check={
|
|
'mode': 'hash',
|
|
'type': 'md5',
|
|
'hash': md5_keys[key],
|
|
})
|
|
|
|
if 'error' not in result:
|
|
vm.qmp('blockdev-del', node_name='node0')
|
|
matching_key = key
|
|
break
|
|
|
|
if matching_key is None:
|
|
vm.shutdown()
|
|
iotests.notrun('Did not find a key that fits 127.0.0.1')
|
|
|
|
blockdev_create(vm, { 'driver': 'ssh',
|
|
'location': {
|
|
'path': disk_path,
|
|
'server': {
|
|
'host': '127.0.0.1',
|
|
'port': '22'
|
|
},
|
|
'host-key-check': {
|
|
'mode': 'hash',
|
|
'type': 'md5',
|
|
'hash': 'wrong',
|
|
}
|
|
},
|
|
'size': 2097152 })
|
|
blockdev_create(vm, { 'driver': 'ssh',
|
|
'location': {
|
|
'path': disk_path,
|
|
'server': {
|
|
'host': '127.0.0.1',
|
|
'port': '22'
|
|
},
|
|
'host-key-check': {
|
|
'mode': 'hash',
|
|
'type': 'md5',
|
|
'hash': md5_keys[matching_key],
|
|
}
|
|
},
|
|
'size': 8388608 })
|
|
vm.shutdown()
|
|
|
|
iotests.img_info_log(remote_path)
|
|
|
|
vm.launch()
|
|
blockdev_create(vm, { 'driver': 'ssh',
|
|
'location': {
|
|
'path': disk_path,
|
|
'server': {
|
|
'host': '127.0.0.1',
|
|
'port': '22'
|
|
},
|
|
'host-key-check': {
|
|
'mode': 'hash',
|
|
'type': 'sha1',
|
|
'hash': 'wrong',
|
|
}
|
|
},
|
|
'size': 2097152 })
|
|
blockdev_create(vm, { 'driver': 'ssh',
|
|
'location': {
|
|
'path': disk_path,
|
|
'server': {
|
|
'host': '127.0.0.1',
|
|
'port': '22'
|
|
},
|
|
'host-key-check': {
|
|
'mode': 'hash',
|
|
'type': 'sha1',
|
|
'hash': sha1_keys[matching_key],
|
|
}
|
|
},
|
|
'size': 4194304 })
|
|
vm.shutdown()
|
|
|
|
iotests.img_info_log(remote_path)
|
|
|
|
#
|
|
# Invalid path and user
|
|
#
|
|
iotests.log("=== Invalid path and user ===")
|
|
iotests.log("")
|
|
|
|
vm.launch()
|
|
blockdev_create(vm, { 'driver': 'ssh',
|
|
'location': {
|
|
'path': '/this/is/not/an/existing/path',
|
|
'server': {
|
|
'host': '127.0.0.1',
|
|
'port': '22'
|
|
},
|
|
'host-key-check': {
|
|
'mode': 'none'
|
|
}
|
|
},
|
|
'size': 4194304 })
|
|
blockdev_create(vm, { 'driver': 'ssh',
|
|
'location': {
|
|
'path': disk_path,
|
|
'user': 'invalid user',
|
|
'server': {
|
|
'host': '127.0.0.1',
|
|
'port': '22'
|
|
},
|
|
'host-key-check': {
|
|
'mode': 'none'
|
|
}
|
|
},
|
|
'size': 4194304 })
|
|
vm.shutdown()
|