def lists_of_dicts_protected(): return [{ "key": "value", "password": ProtectedPassword("12345678"), }, { "key": "value", "password": ProtectedPassword("87654321"), }]
def nested_dicts_protected(): return { "key": "value", "nested": { "password": ProtectedPassword("12345678"), "nested": { "key": "value", "password": ProtectedPassword("87654321"), } } }
def nested_lists_of_dicts_protected(): return { "key": "value", "nested": [{ "key": "value", "nested": [{ "key": "value", "_X_key": ProtectedPassword("secret"), "password": ProtectedPassword("12345678"), }] }] }
def test_protect_log_passwords(self, monkeypatch): monkeypatch.setattr(commands, "log", fakelib.FakeLogger()) secret = ProtectedPassword("top-secret") args = ["echo", "-n", secret] commands.run(args) for level, msg, kwargs in commands.log.messages: assert str(secret.value) not in msg
def testGetExternalVMsWithXMLDescFailure(self): specs = list(VM_SPECS) def internal_error(flags=0): raise fake.Error(libvirt.VIR_ERR_INTERNAL_ERROR) fake_vms = [MockVirDomain(*spec) for spec in specs] # Cause vm 1 to fail, so it would not appear in results fake_vms[1].XMLDesc = internal_error del specs[1] def _connect(uri, username, passwd): return MockVirConnect(vms=fake_vms) with MonkeyPatchScope([(libvirtconnection, 'open_connection', _connect) ]): vms = v2v.get_external_vms('esx://mydomain', 'user', ProtectedPassword('password'), None)['vmList'] self.assertEqual(len(vms), len(specs)) for vm, spec in zip(vms, specs): self._assertVmMatchesSpec(vm, spec) self._assertVmDisksMatchSpec(vm, spec)
def get_password(options): if not options.password_file: return None if options.verbose: write_output('>>> Reading password from file %s' % options.password_file) with open(options.password_file, 'r') as f: return ProtectedPassword(f.read())
def _commonConvertExternalVM(self, url): with namedTemporaryDir() as v2v._V2V_DIR, \ namedTemporaryDir() as v2v._LOG_DIR: v2v.convert_external_vm(url, 'root', ProtectedPassword('mypassword'), self.vminfo, self.job_id, FakeIRS()) job = v2v._jobs[self.job_id] job.wait() self.assertEqual(job.status, v2v.STATUS.DONE)
def testGetExternalVMNames(self): def _connect(uri, username, passwd): return MockVirConnect(vms=self._vms) with MonkeyPatchScope([(libvirtconnection, 'open_connection', _connect) ]): vms = v2v.get_external_vm_names( 'esx://mydomain', 'user', ProtectedPassword('password'))['vmNames'] self.assertEqual(sorted(vms), sorted(spec.name for spec in VM_SPECS))
def testLegacyGetExternalVMsFailure(self): def _connect(uri, username, passwd): mock = MockVirConnect(vms=self._vms) mock.listAllDomains = legacylistAllDomainsWrongRaise return mock with MonkeyPatchScope([(libvirtconnection, 'open_connection', _connect) ]): self.assertRaises(libvirt.libvirtError, v2v.get_external_vms, 'esx://mydomain', 'user', ProtectedPassword('password'), None)
def testLegacyGetExternalVMs(self): def _connect(uri, username, passwd): mock = MockVirConnect(vms=self._vms) mock.listAllDomains = legacylistAllDomains return mock with MonkeyPatchScope([(libvirtconnection, 'open_connection', _connect) ]): vms = v2v.get_external_vms('esx://mydomain', 'user', ProtectedPassword('password'), None)['vmList'] self.assertEqual(len(vms), len(self._vms))
def testBlockDevice(self): def _connect(uri, username, passwd): return MockVirConnect(vms=self._vms) with MonkeyPatchScope([(libvirtconnection, 'open_connection', _connect) ]): vms = v2v.get_external_vms(self.xen_url, 'user', ProtectedPassword('password'), None)['vmList'] self.assertEqual(len(vms), len(VM_SPECS)) self.assertEqual(BLOCK_DEV_PATH, vms[4]['disks'][0]['alias']) self.assertEqual(BLOCK_DEV_PATH, vms[5]['disks'][1]['alias'])
def testLookupFailure(self, methodname, fakemethod, active): def _connect(uri, username, passwd): mock = MockVirConnect(vms=self._vms) mock.listAllDomains = legacylistAllDomains setattr(mock, methodname, fakemethod) return mock with MonkeyPatchScope([(libvirtconnection, 'open_connection', _connect) ]): vms = v2v.get_external_vms('esx://mydomain', 'user', ProtectedPassword('password'), None)['vmList'] assert sorted(vm['vmName'] for vm in vms) == \ sorted(spec.name for spec in VM_SPECS if spec.active == active)
def testXenBlockDevice(self): def _connect(uri, username, passwd): self._vms[0].setDiskType('block') conn = MockVirConnect(vms=self._vms) conn.setType('Xen') return conn with MonkeyPatchScope([(libvirtconnection, 'open_connection', _connect) ]): vms = v2v.get_external_vms(self.xen_url, 'user', ProtectedPassword('password'), None)['vmList'] self.assertEqual(len(vms), len(VM_SPECS) - 1) self.assertTrue(self._vms[0] not in vms)
def testGetExternalVMsWithoutDisksInfo(self): def internal_error(name): raise fake.Error(libvirt.VIR_ERR_INTERNAL_ERROR) # we need a sequence of just one vm mock = MockVirConnect(vms=self._vms[:1]) mock.storageVolLookupByPath = internal_error def _connect(uri, username, passwd): return mock with MonkeyPatchScope([(libvirtconnection, 'open_connection', _connect) ]): vms = v2v.get_external_vms('esx://mydomain', 'user', ProtectedPassword('password'), None)['vmList'] self.assertEqual(len(vms), 0)
def testGetExternalVMs(self): def _connect(uri, username, passwd): return MockVirConnect(vms=self._vms_with_snapshot) with MonkeyPatchScope([(libvirtconnection, 'open_connection', _connect) ]): vms = v2v.get_external_vms('esx://mydomain', 'user', ProtectedPassword('password'), None)['vmList'] self.assertEqual(len(vms), len(VM_SPECS) - 1) self.assertNotIn(self._vms_with_snapshot[4].ID, [vm['vmId'] for vm in vms]) for vm, spec in zip(vms, VM_SPECS): self._assertVmMatchesSpec(vm, spec) self._assertVmDisksMatchSpec(vm, spec)
def testXenBlockDevice(self): def _connect(uri, username, passwd): conn = MockVirConnect(vms=self._vms) conn.setType('Xen') return conn with MonkeyPatchScope([(libvirtconnection, 'open_connection', _connect) ]): vms = v2v.get_external_vms(self.xen_url, 'user', ProtectedPassword('password'), None)['vmList'] # Import of VMs with block devices is not supported for Xen source # so the VMs RHEL_4 and RHEL_5 should not be in the list. self.assertEqual(len(vms), len(VM_SPECS) - 2) vm_names = [vm['vmName'] for vm in vms] self.assertTrue('RHEL_4' not in vm_names) self.assertTrue('RHEL_5' not in vm_names)
def testGetExternalVMs(self): def _connect(uri, username, passwd): return MockVirConnect(vms=self._vms_with_snapshot) with MonkeyPatchScope([(libvirtconnection, 'open_connection', _connect) ]): vms = v2v.get_external_vms('esx://mydomain', 'user', ProtectedPassword('password'), None)['vmList'] # Make sure that VM nr. 4 is now in the returned list # (the one with snapshot, see setUp()) assert len(vms) == len(VM_SPECS) assert self._vms_with_snapshot[4].ID not in \ [vm['vmId'] for vm in vms] specs = list(VM_SPECS) for vm, spec in zip(vms, specs): self._assertVmMatchesSpec(vm, spec) self._assertVmDisksMatchSpec(vm, spec)
def testGetExternalVMsList(self): def _connect(uri, username, passwd): return MockVirConnect(vms=self._vms_with_snapshot) vmIDs = [1, 3, 4] names = [vm.name for vm in VM_SPECS if vm.id in vmIDs] # Add a non-existent name to check that nothing bad happens. names.append('Some nonexistent name') with MonkeyPatchScope([(libvirtconnection, 'open_connection', _connect) ]): vms = v2v.get_external_vms('esx://mydomain', 'user', ProtectedPassword('password'), names)['vmList'] self.assertEqual(len(vms), len(vmIDs) - 1) self.assertNotIn(self._vms_with_snapshot[4].ID, [vm['vmId'] for vm in vms]) for vm, vmID in zip(vms, vmIDs): spec = VM_SPECS[vmID] self._assertVmMatchesSpec(vm, spec) self._assertVmDisksMatchSpec(vm, spec)
def test_valid(self): obj = self.Cls() obj.password = ProtectedPassword("12345678") assert obj.password.value == "12345678"
def test_pickle_copy(self): p1 = ProtectedPassword("12345678") p2 = pickle.loads(pickle.dumps(p1)) self.assertEqual(p1, p2)
def test_no_marshal(self): p1 = ProtectedPassword("12345678") self.assertRaises(ValueError, marshal.dumps, p1)
def test_no_json(self): p1 = ProtectedPassword("12345678") self.assertRaises(TypeError, json.dumps, p1)
def get(target=None, killOnFailure=True): """Return current connection to libvirt or open a new one. Use target to get/create the connection object linked to that object. target must have a callable attribute named 'dispatchLibvirtEvents' which will be registered as a callback on libvirt events. Wrap methods of connection object so that they catch disconnection, and take the current process down. """ def wrapMethod(f): @functools.wraps(f) def wrapper(*args, **kwargs): try: ret = f(*args, **kwargs) if isinstance(ret, libvirt.virDomain): for name in dir(ret): method = getattr(ret, name) if callable(method) and name[0] != '_': setattr(ret, name, wrapMethod(function.weakmethod(method))) return ret except libvirt.libvirtError as e: edom = e.get_error_domain() ecode = e.get_error_code() EDOMAINS = (libvirt.VIR_FROM_REMOTE, libvirt.VIR_FROM_RPC) ECODES = (libvirt.VIR_ERR_SYSTEM_ERROR, libvirt.VIR_ERR_INTERNAL_ERROR, libvirt.VIR_ERR_NO_CONNECT, libvirt.VIR_ERR_INVALID_CONN) if edom in EDOMAINS and ecode in ECODES: try: __connections.get(id(target)).pingLibvirt() except libvirt.libvirtError as e: edom = e.get_error_domain() ecode = e.get_error_code() if edom in EDOMAINS and ecode in ECODES: log.warning( 'connection to libvirt broken.' ' ecode: %d edom: %d', ecode, edom) if killOnFailure: log.critical('taking calling process down.') os.kill(os.getpid(), signal.SIGTERM) else: raise raise return wrapper with __connectionLock: conn = __connections.get(id(target)) if not conn: log.debug('trying to connect libvirt') password = ProtectedPassword(libvirt_password()) conn = open_connection('qemu:///system', SASL_USERNAME, password) __connections[id(target)] = conn setattr(conn, 'pingLibvirt', getattr(conn, 'getLibVersion')) for name in dir(libvirt.virConnect): method = getattr(conn, name) if callable(method) and name[0] != '_': setattr(conn, name, wrapMethod(function.weakmethod(method))) if target is not None: for ev in (libvirt.VIR_DOMAIN_EVENT_ID_LIFECYCLE, libvirt.VIR_DOMAIN_EVENT_ID_REBOOT, libvirt.VIR_DOMAIN_EVENT_ID_RTC_CHANGE, libvirt.VIR_DOMAIN_EVENT_ID_IO_ERROR_REASON, libvirt.VIR_DOMAIN_EVENT_ID_GRAPHICS, libvirt.VIR_DOMAIN_EVENT_ID_BLOCK_JOB, libvirt.VIR_DOMAIN_EVENT_ID_WATCHDOG, libvirt.VIR_DOMAIN_EVENT_ID_JOB_COMPLETED, libvirt.VIR_DOMAIN_EVENT_ID_DEVICE_REMOVED, libvirt.VIR_DOMAIN_EVENT_ID_BLOCK_THRESHOLD): conn.domainEventRegisterAny(None, ev, target.dispatchLibvirtEvents, ev) # In case we're running into troubles with keeping the connections # alive we should place here: # conn.setKeepAlive(interval=5, count=3) # However the values need to be considered wisely to not affect # hosts which are hosting a lot of virtual machines return conn
def test_unprotect_passwords(self): secret = ProtectedPassword("top-secret") args = ["echo", "-n", secret] out = commands.run(args) assert out.decode() == secret.value
def test_protect_password_error(self): secret = ProtectedPassword("top-secret") args = ["false", secret] with pytest.raises(cmdutils.Error) as e: commands.run(args) assert secret.value not in str(e.value)
def make_password(value): return ProtectedPassword(base64.b64encode(value.encode('utf8')))
def test_unencoded_password(self): params = make_secret() params["password"] = ProtectedPassword("not base64 value") self.assertRaises(ValueError, secret.Secret, params)
def test_invalid(self): obj = self.Cls() with pytest.raises(ValueError): obj.password = ProtectedPassword("not base64 value")
def test_protected_password(self): secret = ProtectedPassword("secret!") line = "'" + str(secret) + "'" self.assertEqual(cmdutils._list2cmdline([secret]), line)
def test_decode(self): obj = self.Cls() data = b"\x80\x81\x82\x83" obj.password = ProtectedPassword(base64.b64encode(data)) assert obj.password.value == data