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