Merge ~ogayot/curtin:recovery-key into curtin:master

Proposed by Olivier Gayot
Status: Merged
Approved by: Olivier Gayot
Approved revision: 2bfebabc9aa8be019b05d9c2eb0077f83f1a96de
Merge reported by: Server Team CI bot
Merged at revision: not available
Proposed branch: ~ogayot/curtin:recovery-key
Merge into: curtin:master
Diff against target: 97 lines (+66/-0)
2 files modified
curtin/commands/block_meta.py (+14/-0)
tests/unittests/test_commands_block_meta.py (+52/-0)
Reviewer Review Type Date Requested Status
Server Team CI bot continuous-integration Needs Fixing
Dan Bungert Approve
Michael Hudson-Doyle Approve
Review via email: mp+449362@code.launchpad.net

Commit message

block_meta: add luks recovery key if requested

If the storage configuration contains the key "recovery_keyfile", call
cryptsetup luksAddKey after cryptsetup luksFormat so that the key
specified is added as a recovery key (i.e., a normal key in the second
key slot).

Signed-off-by: Olivier Gayot <email address hidden>

Description of the change

This adds support for adding a LUKS recovery key. Something special probably needs to be done for s390x but that's all I have at the moment.

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 :

lgtm

review: Approve
Revision history for this message
Dan Bungert (dbungert) wrote :

I think it's fine to not have the zkey part sorted out yet, so long as the Subiquity side is programmed in a way that is consistent.

I suppose in this case it means we shouldn't be asking for a recovery key on s390x if we can't act on it.

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

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1diff --git a/curtin/commands/block_meta.py b/curtin/commands/block_meta.py
2index dd6992d..64bf393 100644
3--- a/curtin/commands/block_meta.py
4+++ b/curtin/commands/block_meta.py
5@@ -1645,6 +1645,8 @@ def dm_crypt_handler(info, storage_config, context):
6 else:
7 raise ValueError("encryption key or keyfile must be specified")
8
9+ recovery_keyfile = info.get('recovery_keyfile')
10+
11 create_dmcrypt = True
12 if preserve:
13 dm_crypt_verify(dmcrypt_dev, volume_path)
14@@ -1688,8 +1690,20 @@ def dm_crypt_handler(info, storage_config, context):
15 if keysize:
16 cmd.extend(["--key-size", keysize])
17 cmd.extend(["luksFormat", volume_path, keyfile])
18+
19 util.subp(cmd)
20
21+ # Should this be done as well if we are using zkey?
22+ if recovery_keyfile is not None:
23+ LOG.debug("Adding recovery key to %s", volume_path)
24+
25+ cmd = [
26+ "cryptsetup", "luksAddKey",
27+ "--key-file", keyfile,
28+ volume_path, recovery_keyfile]
29+
30+ util.subp(cmd)
31+
32 cmd = ["cryptsetup", "open", "--type", luks_type, volume_path, dm_name,
33 "--key-file", keyfile]
34
35diff --git a/tests/unittests/test_commands_block_meta.py b/tests/unittests/test_commands_block_meta.py
36index 87e46eb..1a1f65d 100644
37--- a/tests/unittests/test_commands_block_meta.py
38+++ b/tests/unittests/test_commands_block_meta.py
39@@ -2100,6 +2100,58 @@ class TestDmCryptHandler(CiTestCase):
40 self.m_subp.assert_has_calls(expected_calls)
41 self.assertEqual(len(util.load_file(self.crypttab).splitlines()), 1)
42
43+ def test_dm_crypt_calls_cryptsetup_with_recovery_key(self):
44+ """ verify dm_crypt calls (format, addKey, open) w/ correct params"""
45+ volume_path = self.random_string()
46+ self.m_getpath.return_value = volume_path
47+
48+ recovery_keyfile = self.random_string()
49+ config = {
50+ 'storage': {
51+ 'version': 1,
52+ 'config': [
53+ {'grub_device': True,
54+ 'id': 'sda',
55+ 'name': 'sda',
56+ 'path': '/wark/xxx',
57+ 'ptable': 'msdos',
58+ 'type': 'disk',
59+ 'wipe': 'superblock'},
60+ {'device': 'sda',
61+ 'id': 'sda-part1',
62+ 'name': 'sda-part1',
63+ 'number': 1,
64+ 'size': '511705088B',
65+ 'type': 'partition'},
66+ {'id': 'dmcrypt0',
67+ 'type': 'dm_crypt',
68+ 'dm_name': 'cryptroot',
69+ 'volume': 'sda-part1',
70+ 'cipher': self.cipher,
71+ 'keysize': self.keysize,
72+ 'keyfile': self.keyfile,
73+ 'recovery_keyfile': recovery_keyfile},
74+ ],
75+ }
76+ }
77+ storage_config = block_meta.extract_storage_ordered_dict(config)
78+
79+ info = storage_config['dmcrypt0']
80+
81+ block_meta.dm_crypt_handler(info, storage_config, empty_context)
82+ expected_calls = [
83+ call(['cryptsetup', '--cipher', self.cipher,
84+ '--key-size', self.keysize,
85+ 'luksFormat', volume_path, self.keyfile]),
86+ call(['cryptsetup', 'luksAddKey',
87+ '--key-file', self.keyfile,
88+ volume_path, recovery_keyfile]),
89+ call(['cryptsetup', 'open', '--type', 'luks', volume_path,
90+ info['dm_name'], '--key-file', self.keyfile])
91+ ]
92+ self.m_subp.assert_has_calls(expected_calls)
93+ self.assertEqual(len(util.load_file(self.crypttab).splitlines()), 1)
94+
95 def test_dm_crypt_defaults_dm_name_to_id(self):
96 """ verify dm_crypt_handler falls back to id with no dm_name. """
97 volume_path = self.random_string()

Subscribers

People subscribed via source and target branches