From e2f430eb491a19e2df57008d53702d992abf7424 Mon Sep 17 00:00:00 2001 From: Fabien Dupont Date: Thu, 7 Nov 2019 06:36:27 -0500 Subject: [PATCH 1/8] Add ability to use a LUKS keys vault --- wrapper/hosts.py | 6 ++++++ wrapper/tests/test_v2v_args.py | 7 +++++++ wrapper/virt_v2v_wrapper.py | 16 ++++++++++++++++ 3 files changed, 29 insertions(+) diff --git a/wrapper/hosts.py b/wrapper/hosts.py index 97e19c4d..381a7011 100644 --- a/wrapper/hosts.py +++ b/wrapper/hosts.py @@ -483,6 +483,12 @@ def prepare_command(self, data, v2v_args, v2v_env, v2v_caps): v2v_args.extend([ '-oo', 'verify-server-certificate=false' ]) + if 'luks_keys_files' in data: + for luks_key in data['luks_keys_files']: + v2v_args.extend([ + '--key', + '%s:file:%s' % (luks_key['device'], luks_key['filename']) + ]) return v2v_args, v2v_env def set_user(self, data): diff --git a/wrapper/tests/test_v2v_args.py b/wrapper/tests/test_v2v_args.py index 7a7fcd85..bd771496 100644 --- a/wrapper/tests/test_v2v_args.py +++ b/wrapper/tests/test_v2v_args.py @@ -46,6 +46,11 @@ def assert_has_args(self, arg_list, expected, msg=None): 'install_drivers': False, 'output_format': 'raw', 'insecure_connection': False, + + 'luks_keys_files': { + '/dev/sda1': '/tmp/luks/sda1', + '/dev/sda2': '/tmp/luks/sda2', + } } def test_vddk_basic(self): @@ -62,6 +67,8 @@ def test_vddk_basic(self): '-io', 'vddk-libdir=/opt/vmware-vix-disklib-distrib', '-io', 'vddk-thumbprint=01:23:45:67:89:AB:CD:EA:DB:EE:F0:12:34:56:78:9A:BC:DE:F0:12', # NOQA E501 '--password-file', '/vmware/password', + '--key', '/dev/sda1:file:/tmp/luks/sda1', + '--key', '/dev/sda2:file:/tmp/luks/sda2', ] v2v_args, v2v_env = wrapper.prepare_command(data, []) self.assertEqual(v2v_args, expected) diff --git a/wrapper/virt_v2v_wrapper.py b/wrapper/virt_v2v_wrapper.py index 523e059b..884255c2 100644 --- a/wrapper/virt_v2v_wrapper.py +++ b/wrapper/virt_v2v_wrapper.py @@ -487,6 +487,22 @@ def main(): host.get_uid(), host.get_gid()) + if 'luks_keys_vault' in data: + if not os.exists(data['luks_keys_vault']): + hard_error("LUKS keys vault doesn't exist") + luks_keys_vault = json.load(data['luks_keys_vault']) + if data['vm_name'] not in luks_keys_vault: + hard_error('Virtual machine not found in LUKS keys file') + data['luks_keys_files'] = [] + for luks_key in luks_keys_vault[data['vm_name']]: + data['luks_keys_files'].append({ + 'device': luks_key['device'], + 'filename': write_password(luks_key['key'], + password_files, + host.get_uid(), + host.get_gid()) + }) + try: if 'source_disks' in data: logging.debug('Initializing disk list from %r', From bf6368015b689dc3c80917cdb6ddcc9b10e3684c Mon Sep 17 00:00:00 2001 From: Fabien Dupont Date: Thu, 7 Nov 2019 06:52:52 -0500 Subject: [PATCH 2/8] Add a default path for LUKS keys vault --- wrapper/virt_v2v_wrapper.py | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/wrapper/virt_v2v_wrapper.py b/wrapper/virt_v2v_wrapper.py index 884255c2..38dd6f6a 100644 --- a/wrapper/virt_v2v_wrapper.py +++ b/wrapper/virt_v2v_wrapper.py @@ -487,21 +487,20 @@ def main(): host.get_uid(), host.get_gid()) - if 'luks_keys_vault' in data: - if not os.exists(data['luks_keys_vault']): - hard_error("LUKS keys vault doesn't exist") + if 'luks_keys_vault' not in data: + data['luks_keys_vault'] = '/tmp/v2v_luks_keys_vault.json' + if os.exists(data['luks_keys_vault']): luks_keys_vault = json.load(data['luks_keys_vault']) - if data['vm_name'] not in luks_keys_vault: - hard_error('Virtual machine not found in LUKS keys file') - data['luks_keys_files'] = [] - for luks_key in luks_keys_vault[data['vm_name']]: - data['luks_keys_files'].append({ - 'device': luks_key['device'], - 'filename': write_password(luks_key['key'], - password_files, - host.get_uid(), - host.get_gid()) - }) + if data['vm_name'] in luks_keys_vault: + data['luks_keys_files'] = [] + for luks_key in luks_keys_vault[data['vm_name']]: + data['luks_keys_files'].append({ + 'device': luks_key['device'], + 'filename': write_password(luks_key['key'], + password_files, + host.get_uid(), + host.get_gid()) + }) try: if 'source_disks' in data: From 4188d2750d97628c8b5a5a869a0ac7e42634b904 Mon Sep 17 00:00:00 2001 From: Fabien Dupont Date: Thu, 7 Nov 2019 07:02:49 -0500 Subject: [PATCH 3/8] Updating test with valid 'luks_keys_files' entry --- wrapper/tests/test_v2v_args.py | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/wrapper/tests/test_v2v_args.py b/wrapper/tests/test_v2v_args.py index bd771496..531bc923 100644 --- a/wrapper/tests/test_v2v_args.py +++ b/wrapper/tests/test_v2v_args.py @@ -47,10 +47,16 @@ def assert_has_args(self, arg_list, expected, msg=None): 'output_format': 'raw', 'insecure_connection': False, - 'luks_keys_files': { - '/dev/sda1': '/tmp/luks/sda1', - '/dev/sda2': '/tmp/luks/sda2', - } + 'luks_keys_files': [ + { + 'device': '/dev/sda1', + 'filename': '/tmp/luks/sda1', + }, + { + 'device': '/dev/sda2', + 'filename': '/tmp/luks/sda2', + } + ] } def test_vddk_basic(self): From f66d2be3af6a91eba9e9f4c50079ef779914b7aa Mon Sep 17 00:00:00 2001 From: Fabien Dupont Date: Thu, 7 Nov 2019 08:52:53 -0500 Subject: [PATCH 4/8] Add the feature to VDSMHost --- wrapper/hosts.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/wrapper/hosts.py b/wrapper/hosts.py index 381a7011..baeae44e 100644 --- a/wrapper/hosts.py +++ b/wrapper/hosts.py @@ -755,6 +755,15 @@ def prepare_command(self, data, v2v_args, v2v_env, v2v_caps): ('false' if data['insecure_connection'] else 'true')]) + if 'luks_keys_files' in data: + for luks_key in data['luks_keys_files']: + v2v_args.extend([ + '--key', + '%s:file:%s' % ( + luks_key['device'], + luks_key['filename'] + ) + ]) elif 'export_domain' in data: v2v_args.extend([ '-o', 'rhv', From 9345bfcfb007a1b9d361a4b5a440e7efd1ca7154 Mon Sep 17 00:00:00 2001 From: Fabien Dupont Date: Fri, 8 Nov 2019 08:39:12 -0500 Subject: [PATCH 5/8] Update tests for RHV to use LUKS keys vault --- wrapper/hosts.py | 6 +++++- wrapper/tests/test_rhv.py | 14 ++++++++++++++ wrapper/tests/test_v2v_args.py | 13 ------------- 3 files changed, 19 insertions(+), 14 deletions(-) diff --git a/wrapper/hosts.py b/wrapper/hosts.py index baeae44e..d271391c 100644 --- a/wrapper/hosts.py +++ b/wrapper/hosts.py @@ -487,7 +487,10 @@ def prepare_command(self, data, v2v_args, v2v_env, v2v_caps): for luks_key in data['luks_keys_files']: v2v_args.extend([ '--key', - '%s:file:%s' % (luks_key['device'], luks_key['filename']) + '%s:file:%s' % ( + luks_key['device'], + luks_key['filename'] + ) ]) return v2v_args, v2v_env @@ -755,6 +758,7 @@ def prepare_command(self, data, v2v_args, v2v_env, v2v_caps): ('false' if data['insecure_connection'] else 'true')]) + print("%s" % data) if 'luks_keys_files' in data: for luks_key in data['luks_keys_files']: v2v_args.extend([ diff --git a/wrapper/tests/test_rhv.py b/wrapper/tests/test_rhv.py index 35f3b146..0727fbab 100644 --- a/wrapper/tests/test_rhv.py +++ b/wrapper/tests/test_rhv.py @@ -87,6 +87,16 @@ def test_tools_iso_ordering(self): 'install_drivers': False, 'output_format': 'raw', 'insecure_connection': False, + 'luks_keys_files': [ + { + 'device': '/dev/sda1', + 'filename': '/tmp/luks/sda1', + }, + { + 'device': '/dev/sda2', + 'filename': '/tmp/luks/sda2', + } + ] } VDDK_EXPORT = { @@ -116,6 +126,8 @@ def test_vddk_rhv_basic(self): '-oo', 'rhv-cafile=/rhv/ca.pem', '-oo', 'rhv-cluster=Default', '-oo', 'rhv-direct', + '--key', '/dev/sda1:file:/tmp/luks/sda1', + '--key', '/dev/sda2:file:/tmp/luks/sda2', ] host = hosts.BaseHost.factory(hosts.BaseHost.TYPE_VDSM) v2v_args, v2v_env = host.prepare_command( @@ -136,6 +148,8 @@ def test_vddk_rhv_insecure(self): '-oo', 'rhv-cluster=Default', '-oo', 'rhv-direct', '-oo', 'rhv-verifypeer=false', + '--key', '/dev/sda1:file:/tmp/luks/sda1', + '--key', '/dev/sda2:file:/tmp/luks/sda2', ] host = hosts.BaseHost.factory(hosts.BaseHost.TYPE_VDSM) v2v_args, v2v_env = host.prepare_command( diff --git a/wrapper/tests/test_v2v_args.py b/wrapper/tests/test_v2v_args.py index 531bc923..7a7fcd85 100644 --- a/wrapper/tests/test_v2v_args.py +++ b/wrapper/tests/test_v2v_args.py @@ -46,17 +46,6 @@ def assert_has_args(self, arg_list, expected, msg=None): 'install_drivers': False, 'output_format': 'raw', 'insecure_connection': False, - - 'luks_keys_files': [ - { - 'device': '/dev/sda1', - 'filename': '/tmp/luks/sda1', - }, - { - 'device': '/dev/sda2', - 'filename': '/tmp/luks/sda2', - } - ] } def test_vddk_basic(self): @@ -73,8 +62,6 @@ def test_vddk_basic(self): '-io', 'vddk-libdir=/opt/vmware-vix-disklib-distrib', '-io', 'vddk-thumbprint=01:23:45:67:89:AB:CD:EA:DB:EE:F0:12:34:56:78:9A:BC:DE:F0:12', # NOQA E501 '--password-file', '/vmware/password', - '--key', '/dev/sda1:file:/tmp/luks/sda1', - '--key', '/dev/sda2:file:/tmp/luks/sda2', ] v2v_args, v2v_env = wrapper.prepare_command(data, []) self.assertEqual(v2v_args, expected) From b883c53f0997c4d01d03f451a2bb050046e1b8e1 Mon Sep 17 00:00:00 2001 From: Fabien Dupont Date: Fri, 8 Nov 2019 15:38:02 -0500 Subject: [PATCH 6/8] Move code to virt-v2v-wrapper.py. Add check on vault permissions --- wrapper/hosts.py | 20 -------------------- wrapper/tests/test_rhv.py | 14 -------------- wrapper/tests/test_v2v_args.py | 13 +++++++++++++ wrapper/virt_v2v_wrapper.py | 23 ++++++++++++++++++++++- 4 files changed, 35 insertions(+), 35 deletions(-) diff --git a/wrapper/hosts.py b/wrapper/hosts.py index d271391c..a2da2c37 100644 --- a/wrapper/hosts.py +++ b/wrapper/hosts.py @@ -483,15 +483,6 @@ def prepare_command(self, data, v2v_args, v2v_env, v2v_caps): v2v_args.extend([ '-oo', 'verify-server-certificate=false' ]) - if 'luks_keys_files' in data: - for luks_key in data['luks_keys_files']: - v2v_args.extend([ - '--key', - '%s:file:%s' % ( - luks_key['device'], - luks_key['filename'] - ) - ]) return v2v_args, v2v_env def set_user(self, data): @@ -757,17 +748,6 @@ def prepare_command(self, data, v2v_args, v2v_env, v2v_caps): v2v_args.extend(['-oo', 'rhv-verifypeer=%s' % ('false' if data['insecure_connection'] else 'true')]) - - print("%s" % data) - if 'luks_keys_files' in data: - for luks_key in data['luks_keys_files']: - v2v_args.extend([ - '--key', - '%s:file:%s' % ( - luks_key['device'], - luks_key['filename'] - ) - ]) elif 'export_domain' in data: v2v_args.extend([ '-o', 'rhv', diff --git a/wrapper/tests/test_rhv.py b/wrapper/tests/test_rhv.py index 0727fbab..35f3b146 100644 --- a/wrapper/tests/test_rhv.py +++ b/wrapper/tests/test_rhv.py @@ -87,16 +87,6 @@ def test_tools_iso_ordering(self): 'install_drivers': False, 'output_format': 'raw', 'insecure_connection': False, - 'luks_keys_files': [ - { - 'device': '/dev/sda1', - 'filename': '/tmp/luks/sda1', - }, - { - 'device': '/dev/sda2', - 'filename': '/tmp/luks/sda2', - } - ] } VDDK_EXPORT = { @@ -126,8 +116,6 @@ def test_vddk_rhv_basic(self): '-oo', 'rhv-cafile=/rhv/ca.pem', '-oo', 'rhv-cluster=Default', '-oo', 'rhv-direct', - '--key', '/dev/sda1:file:/tmp/luks/sda1', - '--key', '/dev/sda2:file:/tmp/luks/sda2', ] host = hosts.BaseHost.factory(hosts.BaseHost.TYPE_VDSM) v2v_args, v2v_env = host.prepare_command( @@ -148,8 +136,6 @@ def test_vddk_rhv_insecure(self): '-oo', 'rhv-cluster=Default', '-oo', 'rhv-direct', '-oo', 'rhv-verifypeer=false', - '--key', '/dev/sda1:file:/tmp/luks/sda1', - '--key', '/dev/sda2:file:/tmp/luks/sda2', ] host = hosts.BaseHost.factory(hosts.BaseHost.TYPE_VDSM) v2v_args, v2v_env = host.prepare_command( diff --git a/wrapper/tests/test_v2v_args.py b/wrapper/tests/test_v2v_args.py index 7a7fcd85..531bc923 100644 --- a/wrapper/tests/test_v2v_args.py +++ b/wrapper/tests/test_v2v_args.py @@ -46,6 +46,17 @@ def assert_has_args(self, arg_list, expected, msg=None): 'install_drivers': False, 'output_format': 'raw', 'insecure_connection': False, + + 'luks_keys_files': [ + { + 'device': '/dev/sda1', + 'filename': '/tmp/luks/sda1', + }, + { + 'device': '/dev/sda2', + 'filename': '/tmp/luks/sda2', + } + ] } def test_vddk_basic(self): @@ -62,6 +73,8 @@ def test_vddk_basic(self): '-io', 'vddk-libdir=/opt/vmware-vix-disklib-distrib', '-io', 'vddk-thumbprint=01:23:45:67:89:AB:CD:EA:DB:EE:F0:12:34:56:78:9A:BC:DE:F0:12', # NOQA E501 '--password-file', '/vmware/password', + '--key', '/dev/sda1:file:/tmp/luks/sda1', + '--key', '/dev/sda2:file:/tmp/luks/sda2', ] v2v_args, v2v_env = wrapper.prepare_command(data, []) self.assertEqual(v2v_args, expected) diff --git a/wrapper/virt_v2v_wrapper.py b/wrapper/virt_v2v_wrapper.py index 38dd6f6a..60a1d4a4 100644 --- a/wrapper/virt_v2v_wrapper.py +++ b/wrapper/virt_v2v_wrapper.py @@ -124,6 +124,16 @@ def prepare_command(data, v2v_caps, agent_sock=None): v2v_args.extend(['--bridge', '%s:%s' % (mapping['source'], mapping['destination'])]) + if 'luks_keys_files' in data: + for luks_key in data['luks_keys_files']: + v2v_args.extend([ + '--key', + '%s:file:%s' % ( + luks_key['device'], + luks_key['filename'] + ) + ]) + # Prepare environment v2v_env = os.environ.copy() v2v_env['LANG'] = 'C' @@ -488,8 +498,19 @@ def main(): host.get_gid()) if 'luks_keys_vault' not in data: - data['luks_keys_vault'] = '/tmp/v2v_luks_keys_vault.json' + data['luks_keys_vault'] = os.path.join( + os.environ['HOME'], + '.v2v_luks_keys_vault.json' + ) if os.exists(data['luks_keys_vault']): + file_stat = os.stat(data['luks_keys_vaul']) + if file_stat.st_uid != host.get_uid(): + hard_error('LUKS keys vault does\'nt belong to' + 'user running virt-v2v-wrapper') + if not bool(file_stat.st_mode & stat.S_IRWXO): + hard_error('LUKS keys vault is accessible to others') + if not bool(file_stat.st_mode & stat.S_IRWXG): + hard_error('LUKS keys vault is accessible to group') luks_keys_vault = json.load(data['luks_keys_vault']) if data['vm_name'] in luks_keys_vault: data['luks_keys_files'] = [] From 302c32b0be3b93529f9adf99e6c7e9a804a167f9 Mon Sep 17 00:00:00 2001 From: Fabien Dupont Date: Fri, 8 Nov 2019 15:45:12 -0500 Subject: [PATCH 7/8] Add missing module --- wrapper/virt_v2v_wrapper.py | 1 + 1 file changed, 1 insertion(+) diff --git a/wrapper/virt_v2v_wrapper.py b/wrapper/virt_v2v_wrapper.py index 60a1d4a4..9d520661 100644 --- a/wrapper/virt_v2v_wrapper.py +++ b/wrapper/virt_v2v_wrapper.py @@ -25,6 +25,7 @@ import re import signal import subprocess +import stat import sys import six import tempfile From 5ea1fd7fcb3bfe7789621fd8d9b128bd11877516 Mon Sep 17 00:00:00 2001 From: Fabien Dupont Date: Wed, 13 Nov 2019 15:23:44 -0500 Subject: [PATCH 8/8] Fixes --- wrapper/tests/test_v2v_args.py | 37 ++++++++++++++++++++++------------ wrapper/virt_v2v_wrapper.py | 4 ++-- 2 files changed, 26 insertions(+), 15 deletions(-) diff --git a/wrapper/tests/test_v2v_args.py b/wrapper/tests/test_v2v_args.py index 531bc923..c70954ea 100644 --- a/wrapper/tests/test_v2v_args.py +++ b/wrapper/tests/test_v2v_args.py @@ -46,17 +46,6 @@ def assert_has_args(self, arg_list, expected, msg=None): 'install_drivers': False, 'output_format': 'raw', 'insecure_connection': False, - - 'luks_keys_files': [ - { - 'device': '/dev/sda1', - 'filename': '/tmp/luks/sda1', - }, - { - 'device': '/dev/sda2', - 'filename': '/tmp/luks/sda2', - } - ] } def test_vddk_basic(self): @@ -73,12 +62,34 @@ def test_vddk_basic(self): '-io', 'vddk-libdir=/opt/vmware-vix-disklib-distrib', '-io', 'vddk-thumbprint=01:23:45:67:89:AB:CD:EA:DB:EE:F0:12:34:56:78:9A:BC:DE:F0:12', # NOQA E501 '--password-file', '/vmware/password', - '--key', '/dev/sda1:file:/tmp/luks/sda1', - '--key', '/dev/sda2:file:/tmp/luks/sda2', ] v2v_args, v2v_env = wrapper.prepare_command(data, []) self.assertEqual(v2v_args, expected) + def test_luks(self): + state = wrapper.State().instance + state.machine_readable_log = '/some/path' + data = self.VDDK_RHV.copy() + data['luks_keys_files'] = [ + { + 'device': '/dev/sda1', + 'filename': '/tmp/luks/sda1', + }, + { + 'device': '/dev/sda2', + 'filename': '/tmp/luks/sda2', + }, + ] + v2v_args, v2v_env = wrapper.prepare_command(data, []) + self.assert_has_args( + v2v_args, + ['--key', '/dev/sda1:file:/tmp/luks/sda1'], + 'Looking for LUKS key of device sda1 %r' % v2v_args) + self.assert_has_args( + v2v_args, + ['--key', '/dev/sda2:file:/tmp/luks/sda2'], + 'Looking for LUKS key of device sda2 %r' % v2v_args) + def test_network_mappings(self): data = self.VDDK_RHV.copy() data['network_mappings'] = [ diff --git a/wrapper/virt_v2v_wrapper.py b/wrapper/virt_v2v_wrapper.py index 9d520661..b179cd18 100644 --- a/wrapper/virt_v2v_wrapper.py +++ b/wrapper/virt_v2v_wrapper.py @@ -508,9 +508,9 @@ def main(): if file_stat.st_uid != host.get_uid(): hard_error('LUKS keys vault does\'nt belong to' 'user running virt-v2v-wrapper') - if not bool(file_stat.st_mode & stat.S_IRWXO): + if file_stat.st_mode & stat.S_IRWXO > 0: hard_error('LUKS keys vault is accessible to others') - if not bool(file_stat.st_mode & stat.S_IRWXG): + if file_stat.st_mode & stat.S_IRWXG > 0: hard_error('LUKS keys vault is accessible to group') luks_keys_vault = json.load(data['luks_keys_vault']) if data['vm_name'] in luks_keys_vault: