Merge ~dbungert/curtin:cryptoswap-dmc-type into curtin:master

Proposed by Dan Bungert
Status: Merged
Merged at revision: e01fe404124d6e03be3960d190dc0278334fb23a
Proposed branch: ~dbungert/curtin:cryptoswap-dmc-type
Merge into: curtin:master
Diff against target: 194 lines (+119/-7)
3 files modified
curtin/commands/block_meta.py (+10/-7)
tests/integration/test_block_meta.py (+7/-0)
tests/unittests/test_commands_block_meta.py (+102/-0)
Reviewer Review Type Date Requested Status
Server Team CI bot continuous-integration Approve
Michael Hudson-Doyle Approve
Review via email: mp+460874@code.launchpad.net

Commit message

dm_crypt: create and use cryptoswap as PLAIN

Previously, cryptoswap was acting strangely, in that at install time it
was considered to be a LUKS2 device and durign actual system use it
would be considered a PLAIN device, in the cryptsetup(8) meanings of
these terms.

This caused problems when attempting to reference the device, as we
would do get_volume_spec(), the returned /dev/disk/by-id/dm-uuid-...
value would be wrong - it would change from dm-uuid-CRYPT-LUKS2-... to
dm-uuid-CRYPT-PLAIN-...

As the real runtime behavior is to be a PLAIN device for cryptoswap,
stop creating it as a LUKS2 device and just use it as a PLAIN device,
which doesn't involve a "create" step at all, you just open it as PLAIN
directly.

To post a comment you must log in.
Revision history for this message
Server Team CI bot (server-team-bot) wrote :
review: Approve (continuous-integration)
Revision history for this message
Michael Hudson-Doyle (mwhudson) wrote :

Can you expand the commit message a whole bunch please? This is about the case where /dev/random is used as a keyfile, in which case the dm type of the device would be created as luks in the live system but then be plain in the installed system and changing to a world where it will be plain in both?

Code changes look good but I have a worry about temporary file handling.

review: Needs Fixing
Revision history for this message
Server Team CI bot (server-team-bot) wrote :
review: Approve (continuous-integration)
Revision history for this message
Dan Bungert (dbungert) wrote :

> Can you expand the commit message a whole bunch please?

Done, or let me know if you would prefer more.

Revision history for this message
Server Team CI bot (server-team-bot) wrote :
review: Approve (continuous-integration)
Revision history for this message
Michael Hudson-Doyle (mwhudson) wrote :

Thanks for the changes. Please remember to update the commit message in the MP if you are going to let jenkins squash merge this!

review: Approve
Revision history for this message
Server Team CI bot (server-team-bot) wrote :
review: Approve (continuous-integration)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
diff --git a/curtin/commands/block_meta.py b/curtin/commands/block_meta.py
index c7bd0dd..ff72193 100644
--- a/curtin/commands/block_meta.py
+++ b/curtin/commands/block_meta.py
@@ -1633,28 +1633,29 @@ def dm_crypt_handler(info, storage_config, context):
1633 volume_path = get_path_to_storage_volume(volume, storage_config)1633 volume_path = get_path_to_storage_volume(volume, storage_config)
1634 volume_byid_path = block.disk_to_byid_path(volume_path)1634 volume_byid_path = block.disk_to_byid_path(volume_path)
16351635
1636 create_dmcrypt = True
1637 open_dmcrypt = False
1636 if 'keyfile' in info:1638 if 'keyfile' in info:
1637 if 'key' in info:1639 if 'key' in info:
1638 raise ValueError("cannot specify both key and keyfile")1640 raise ValueError("cannot specify both key and keyfile")
1639 keyfile = info['keyfile']1641 keyfile = info['keyfile']
1640 if keyfile in ("/dev/random", "/dev/urandom"):1642 if keyfile in ("/dev/random", "/dev/urandom"):
1641 crypttab_keyfile = keyfile1643 crypttab_keyfile = keyfile
1642 keyfile = tempfile.mkstemp()[1]1644 luks_type = "plain"
1643 keyfile_is_tmp = True1645 open_dmcrypt = True
1644 else:1646 create_dmcrypt = False
1645 keyfile_is_tmp = False1647 remove_keyfile = False
1646 elif 'key' in info:1648 elif 'key' in info:
1647 # TODO: this is insecure, find better way to do this1649 # TODO: this is insecure, find better way to do this
1648 key = info.get('key')1650 key = info.get('key')
1649 keyfile = tempfile.mkstemp()[1]1651 keyfile = tempfile.mkstemp()[1]
1650 keyfile_is_tmp = True1652 remove_keyfile = True
1651 util.write_file(keyfile, key, mode=0o600)1653 util.write_file(keyfile, key, mode=0o600)
1652 else:1654 else:
1653 raise ValueError("encryption key or keyfile must be specified")1655 raise ValueError("encryption key or keyfile must be specified")
16541656
1655 recovery_keyfile = info.get('recovery_keyfile')1657 recovery_keyfile = info.get('recovery_keyfile')
16561658
1657 create_dmcrypt = True
1658 if preserve:1659 if preserve:
1659 dm_crypt_verify(dmcrypt_dev, volume_path)1660 dm_crypt_verify(dmcrypt_dev, volume_path)
1660 LOG.debug('dm_crypt %s already present, skipping create', dmcrypt_dev)1661 LOG.debug('dm_crypt %s already present, skipping create', dmcrypt_dev)
@@ -1664,6 +1665,7 @@ def dm_crypt_handler(info, storage_config, context):
1664 # if zkey is available, attempt to generate and use it; if it's not1665 # if zkey is available, attempt to generate and use it; if it's not
1665 # available or fails to setup properly, fallback to normal cryptsetup1666 # available or fails to setup properly, fallback to normal cryptsetup
1666 # passing strict=False downgrades log messages to warnings1667 # passing strict=False downgrades log messages to warnings
1668 open_dmcrypt = True
1667 zkey_used = None1669 zkey_used = None
1668 if block.zkey_supported(strict=False):1670 if block.zkey_supported(strict=False):
1669 volume_name = "%s:%s" % (volume_byid_path, dm_name)1671 volume_name = "%s:%s" % (volume_byid_path, dm_name)
@@ -1710,12 +1712,13 @@ def dm_crypt_handler(info, storage_config, context):
17101712
1711 util.subp(cmd)1713 util.subp(cmd)
17121714
1715 if open_dmcrypt:
1713 cmd = ["cryptsetup", "open", "--type", luks_type, volume_path, dm_name,1716 cmd = ["cryptsetup", "open", "--type", luks_type, volume_path, dm_name,
1714 "--key-file", keyfile]1717 "--key-file", keyfile]
17151718
1716 util.subp(cmd)1719 util.subp(cmd)
17171720
1718 if keyfile_is_tmp:1721 if remove_keyfile:
1719 os.remove(keyfile)1722 os.remove(keyfile)
17201723
1721 wipe_mode = info.get('wipe')1724 wipe_mode = info.get('wipe')
diff --git a/tests/integration/test_block_meta.py b/tests/integration/test_block_meta.py
index 568f466..2fc7c7d 100644
--- a/tests/integration/test_block_meta.py
+++ b/tests/integration/test_block_meta.py
@@ -1327,6 +1327,13 @@ table-length: 256'''.encode()
1327 self.assertEqual("/dev/urandom", tokens[2])1327 self.assertEqual("/dev/urandom", tokens[2])
1328 self.assertEqual("swap,initramfs", tokens[3])1328 self.assertEqual("swap,initramfs", tokens[3])
13291329
1330 cmd = ["cryptsetup", "status", cryptoswap]
1331 status = util.subp(cmd, capture=True)[0]
1332 for line in status.splitlines():
1333 key, _, value = line.strip().partition(':')
1334 if key == "type":
1335 self.assertEqual("PLAIN", value.strip())
1336
1330 @parameterized.expand(((1,), (2,)))1337 @parameterized.expand(((1,), (2,)))
1331 def test_msftres(self, sv):1338 def test_msftres(self, sv):
1332 self.img = self.tmp_path('image.img')1339 self.img = self.tmp_path('image.img')
diff --git a/tests/unittests/test_commands_block_meta.py b/tests/unittests/test_commands_block_meta.py
index c2d592d..727fba5 100644
--- a/tests/unittests/test_commands_block_meta.py
+++ b/tests/unittests/test_commands_block_meta.py
@@ -2413,6 +2413,108 @@ class TestDmCryptHandler(DmCryptCommon):
2413 info, self.storage_config, empty_context)2413 info, self.storage_config, empty_context)
24142414
24152415
2416class TestDmCryptKeyfileRemoval(DmCryptCommon):
2417 def setUp(self):
2418 super().setUp()
2419 self.tempkey = self.tmp_path('test_dm_crypt_key')
2420 basepath = 'curtin.commands.block_meta.'
2421 self.add_patch(basepath + 'os.remove', 'm_os_remove')
2422
2423 @patch('curtin.commands.block_meta.tempfile.mkstemp')
2424 def test_dm_crypt_removes_tmpfile_if_key(self, m_mkstemp):
2425 m_mkstemp.return_value = (None, self.tempkey)
2426 self.setUpStorageConfig({
2427 'storage': {
2428 'version': 1,
2429 'config': [
2430 {'grub_device': True,
2431 'id': 'sda',
2432 'name': 'sda',
2433 'path': '/wark/xxx',
2434 'ptable': 'msdos',
2435 'type': 'disk',
2436 'wipe': 'superblock'},
2437 {'device': 'sda',
2438 'id': 'sda-part1',
2439 'name': 'sda-part1',
2440 'number': 1,
2441 'size': '511705088B',
2442 'type': 'partition'},
2443 {'id': 'dmcrypt0',
2444 'type': 'dm_crypt',
2445 'dm_name': 'cryptroot',
2446 'volume': 'sda-part1',
2447 'key': 'passw0rd'},
2448 ],
2449 }
2450 })
2451 info = self.storage_config['dmcrypt0']
2452 block_meta.dm_crypt_handler(info, self.storage_config, empty_context)
2453 self.m_os_remove.assert_called_once_with(self.tempkey)
2454
2455 @patch('curtin.commands.block_meta.os.remove')
2456 def test_dm_crypt_not_remove_keyfile(self, m_os_remove):
2457 self.setUpStorageConfig({
2458 'storage': {
2459 'version': 1,
2460 'config': [
2461 {'grub_device': True,
2462 'id': 'sda',
2463 'name': 'sda',
2464 'path': '/wark/xxx',
2465 'ptable': 'msdos',
2466 'type': 'disk',
2467 'wipe': 'superblock'},
2468 {'device': 'sda',
2469 'id': 'sda-part1',
2470 'name': 'sda-part1',
2471 'number': 1,
2472 'size': '511705088B',
2473 'type': 'partition'},
2474 {'id': 'dmcrypt0',
2475 'type': 'dm_crypt',
2476 'dm_name': 'cryptroot',
2477 'volume': 'sda-part1',
2478 'keyfile': self.tempkey},
2479 ],
2480 }
2481 })
2482 info = self.storage_config['dmcrypt0']
2483 block_meta.dm_crypt_handler(info, self.storage_config, empty_context)
2484 self.m_os_remove.assert_not_called()
2485
2486 @patch('curtin.commands.block_meta.os.remove')
2487 def test_dm_crypt_not_remove_dev_random(self, m_os_remove):
2488 self.setUpStorageConfig({
2489 'storage': {
2490 'version': 1,
2491 'config': [
2492 {'grub_device': True,
2493 'id': 'sda',
2494 'name': 'sda',
2495 'path': '/wark/xxx',
2496 'ptable': 'msdos',
2497 'type': 'disk',
2498 'wipe': 'superblock'},
2499 {'device': 'sda',
2500 'id': 'sda-part1',
2501 'name': 'sda-part1',
2502 'number': 1,
2503 'size': '511705088B',
2504 'type': 'partition'},
2505 {'id': 'dmcrypt0',
2506 'type': 'dm_crypt',
2507 'dm_name': 'cryptroot',
2508 'volume': 'sda-part1',
2509 'keyfile': '/dev/random'},
2510 ],
2511 }
2512 })
2513 info = self.storage_config['dmcrypt0']
2514 block_meta.dm_crypt_handler(info, self.storage_config, empty_context)
2515 self.m_os_remove.assert_not_called()
2516
2517
2416class TestCrypttab(DmCryptCommon):2518class TestCrypttab(DmCryptCommon):
24172519
2418 def test_multi_dm_crypt(self):2520 def test_multi_dm_crypt(self):

Subscribers

People subscribed via source and target branches