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 return iotests.filter_qmp(qmsg, _filter) 39 40def blockdev_create(vm, options): 41 vm.blockdev_create(options, filters=[iotests.filter_qmp_testfiles, filter_hash]) 42 43with iotests.FilePath('t.img') as disk_path, \ 44 iotests.VM() as vm: 45 46 remote_path = iotests.remote_filename(disk_path) 47 48 # 49 # Successful image creation (defaults) 50 # 51 iotests.log("=== Successful image creation (defaults) ===") 52 iotests.log("") 53 54 vm.launch() 55 blockdev_create(vm, { 'driver': 'ssh', 56 'location': { 57 'path': disk_path, 58 'server': { 59 'host': '127.0.0.1', 60 'port': '22' 61 } 62 }, 63 'size': 4194304 }) 64 vm.shutdown() 65 66 iotests.img_info_log(remote_path) 67 iotests.log("") 68 iotests.img_info_log(disk_path) 69 70 # 71 # Test host-key-check options 72 # 73 iotests.log("=== Test host-key-check options ===") 74 iotests.log("") 75 76 iotests.log("--- no host key checking --") 77 iotests.log("") 78 79 vm.launch() 80 blockdev_create(vm, { 'driver': 'ssh', 81 'location': { 82 'path': disk_path, 83 'server': { 84 'host': '127.0.0.1', 85 'port': '22' 86 }, 87 'host-key-check': { 88 'mode': 'none' 89 } 90 }, 91 'size': 8388608 }) 92 vm.shutdown() 93 94 iotests.img_info_log(remote_path) 95 96 iotests.log("--- known_hosts key checking --") 97 iotests.log("") 98 99 vm.launch() 100 blockdev_create(vm, { 'driver': 'ssh', 101 'location': { 102 'path': disk_path, 103 'server': { 104 'host': '127.0.0.1', 105 'port': '22' 106 }, 107 'host-key-check': { 108 'mode': 'known_hosts' 109 } 110 }, 111 'size': 4194304 }) 112 vm.shutdown() 113 114 iotests.img_info_log(remote_path) 115 116 keys = subprocess.check_output( 117 'ssh-keyscan 127.0.0.1 2>/dev/null | grep -v "\\^#" | ' + 118 'cut -d" " -f3', 119 shell=True).rstrip().decode('ascii').split('\n') 120 121 # Mappings of base64 representations to digests 122 md5_keys = {} 123 sha1_keys = {} 124 sha256_keys = {} 125 126 for key in keys: 127 md5_keys[key] = subprocess.check_output( 128 'echo %s | base64 -d | md5sum -b | cut -d" " -f1' % key, 129 shell=True).rstrip().decode('ascii') 130 131 sha1_keys[key] = subprocess.check_output( 132 'echo %s | base64 -d | sha1sum -b | cut -d" " -f1' % key, 133 shell=True).rstrip().decode('ascii') 134 135 sha256_keys[key] = subprocess.check_output( 136 'echo %s | base64 -d | sha256sum -b | cut -d" " -f1' % key, 137 shell=True).rstrip().decode('ascii') 138 139 vm.launch() 140 141 # Find correct key first 142 matching_key = None 143 for key in keys: 144 result = vm.qmp('blockdev-add', 145 driver='ssh', node_name='node0', path=disk_path, 146 server={ 147 'host': '127.0.0.1', 148 'port': '22', 149 }, host_key_check={ 150 'mode': 'hash', 151 'type': 'md5', 152 'hash': md5_keys[key], 153 }) 154 155 if 'error' not in result: 156 vm.qmp('blockdev-del', node_name='node0') 157 matching_key = key 158 break 159 160 if matching_key is None: 161 vm.shutdown() 162 iotests.notrun('Did not find a key that fits 127.0.0.1') 163 164 iotests.log("--- explicit md5 key checking --") 165 iotests.log("") 166 167 blockdev_create(vm, { 'driver': 'ssh', 168 'location': { 169 'path': disk_path, 170 'server': { 171 'host': '127.0.0.1', 172 'port': '22' 173 }, 174 'host-key-check': { 175 'mode': 'hash', 176 'type': 'md5', 177 'hash': 'wrong', 178 } 179 }, 180 'size': 2097152 }) 181 182 blockdev_create(vm, { 'driver': 'ssh', 183 'location': { 184 'path': disk_path, 185 'server': { 186 'host': '127.0.0.1', 187 'port': '22' 188 }, 189 'host-key-check': { 190 'mode': 'hash', 191 'type': 'md5', 192 'hash': md5_keys[matching_key], 193 } 194 }, 195 'size': 8388608 }) 196 vm.shutdown() 197 198 iotests.img_info_log(remote_path) 199 200 iotests.log("--- explicit sha1 key checking --") 201 iotests.log("") 202 203 vm.launch() 204 blockdev_create(vm, { 'driver': 'ssh', 205 'location': { 206 'path': disk_path, 207 'server': { 208 'host': '127.0.0.1', 209 'port': '22' 210 }, 211 'host-key-check': { 212 'mode': 'hash', 213 'type': 'sha1', 214 'hash': 'wrong', 215 } 216 }, 217 'size': 2097152 }) 218 blockdev_create(vm, { 'driver': 'ssh', 219 'location': { 220 'path': disk_path, 221 'server': { 222 'host': '127.0.0.1', 223 'port': '22' 224 }, 225 'host-key-check': { 226 'mode': 'hash', 227 'type': 'sha1', 228 'hash': sha1_keys[matching_key], 229 } 230 }, 231 'size': 4194304 }) 232 vm.shutdown() 233 234 iotests.img_info_log(remote_path) 235 236 iotests.log("--- explicit sha256 key checking --") 237 iotests.log("") 238 239 vm.launch() 240 blockdev_create(vm, { 'driver': 'ssh', 241 'location': { 242 'path': disk_path, 243 'server': { 244 'host': '127.0.0.1', 245 'port': '22' 246 }, 247 'host-key-check': { 248 'mode': 'hash', 249 'type': 'sha256', 250 'hash': 'wrong', 251 } 252 }, 253 'size': 2097152 }) 254 blockdev_create(vm, { 'driver': 'ssh', 255 'location': { 256 'path': disk_path, 257 'server': { 258 'host': '127.0.0.1', 259 'port': '22' 260 }, 261 'host-key-check': { 262 'mode': 'hash', 263 'type': 'sha256', 264 'hash': sha256_keys[matching_key], 265 } 266 }, 267 'size': 4194304 }) 268 vm.shutdown() 269 270 iotests.img_info_log(remote_path) 271 272 # 273 # Invalid path and user 274 # 275 iotests.log("=== Invalid path and user ===") 276 iotests.log("") 277 278 vm.launch() 279 blockdev_create(vm, { 'driver': 'ssh', 280 'location': { 281 'path': '/this/is/not/an/existing/path', 282 'server': { 283 'host': '127.0.0.1', 284 'port': '22' 285 }, 286 'host-key-check': { 287 'mode': 'none' 288 } 289 }, 290 'size': 4194304 }) 291 blockdev_create(vm, { 'driver': 'ssh', 292 'location': { 293 'path': disk_path, 294 'user': 'invalid user', 295 'server': { 296 'host': '127.0.0.1', 297 'port': '22' 298 }, 299 'host-key-check': { 300 'mode': 'none' 301 } 302 }, 303 'size': 4194304 }) 304 vm.shutdown() 305