Skip to content

Commit

Permalink
Fixed writing correct keyfile path to etc/crypttab
Browse files Browse the repository at this point in the history
The keyfile path was not correctly set in etc/crypttab which
caused systemd not being able to read the keyfile, consequently
asking for a passphrase. This commit fixes the writing of the
crypttab and also fixes a python name clash with the "os"
namespace.
  • Loading branch information
schaefi committed Jul 25, 2023
1 parent 600a6f9 commit b3047fb
Show file tree
Hide file tree
Showing 4 changed files with 41 additions and 27 deletions.
7 changes: 4 additions & 3 deletions kiwi/builder/disk.py
Original file line number Diff line number Diff line change
Expand Up @@ -370,10 +370,11 @@ def create_disk(self) -> Result:
True if self.boot_is_crypto or self.luks == '' else False
luks_root.create_crypto_luks(
passphrase=self.luks,
os=self.luks_os,
osname=self.luks_os,
options=self.luks_format_options,
keyfile=self.luks_boot_keyfile if luks_need_keyfile else '',
randomize=self.luks_randomize
keyfile=self.luks_boot_keyname if luks_need_keyfile else '',
randomize=self.luks_randomize,
root_dir=self.root_dir
)
if luks_need_keyfile:
self.luks_boot_keyfile_setup = ''.join(
Expand Down
28 changes: 16 additions & 12 deletions kiwi/storage/luks_device.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ def __init__(self, storage_provider: DeviceProvider) -> None:
self.storage_provider = storage_provider

self.luks_device: Optional[str] = None
self.luks_keyfile: Optional[str] = None
self.luks_keyfile: str = ''
self.luks_name = 'luksRoot'

self.option_map = {
Expand All @@ -72,31 +72,33 @@ def get_device(self) -> Optional[MappedDevice]:
return None

def create_crypto_luks(
self, passphrase: str, os: str = None,
options: list = None, keyfile: str = '', randomize: bool = True
self, passphrase: str, osname: str = None,
options: list = None, keyfile: str = '', randomize: bool = True,
root_dir: str = ''
) -> None:
"""
Create luks device. Please note the passphrase is readable
at creation time of this image. Make sure your host system
is secure while this process runs
:param string passphrase: credentials
:param string os:
:param string osname:
distribution name to match distribution specific
options for cryptsetup
:param list options: further cryptsetup options
:param string keyfile: file path name
file path name which contains an alternative key
to unlock the luks device
:param string root_dir: root dir path
"""
if not options:
options = []
if os:
if os in self.option_map:
options += self.option_map[os]
if osname:
if osname in self.option_map:
options += self.option_map[osname]
else:
raise KiwiLuksSetupError(
'no custom option configuration found for OS %s' % os
'no custom option configuration found for OS %s' % osname
)
extra_options = []
storage_device = self.storage_provider.get_device()
Expand Down Expand Up @@ -141,12 +143,15 @@ def create_crypto_luks(
)
if keyfile:
self.luks_keyfile = keyfile
LuksDevice.create_random_keyfile(keyfile)
keyfile_path = os.path.normpath(
os.sep.join([root_dir, self.luks_keyfile])
)
LuksDevice.create_random_keyfile(keyfile_path)
Command.run(
[
'cryptsetup', '--key-file', passphrase_file
] + extra_options + [
'luksAddKey', storage_device, keyfile
'luksAddKey', storage_device, keyfile_path
]
)
Command.run(
Expand All @@ -170,8 +175,7 @@ def create_crypttab(self, filename: str) -> None:
if self.luks_keyfile:
crypttab.write(
'luks UUID={0} /{1}{2}'.format(
luks_uuid, os.path.basename(self.luks_keyfile),
os.linesep
luks_uuid, self.luks_keyfile.lstrip(os.sep), os.linesep
)
)
else:
Expand Down
14 changes: 8 additions & 6 deletions test/unit/builder/disk_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -1045,9 +1045,10 @@ def test_create_disk_luks_root(
self.disk_builder.create_disk()

self.luks_root.create_crypto_luks.assert_called_once_with(
passphrase='passphrase', os=None,
options=[], keyfile='root_dir/root/.root.keyfile',
randomize=True
passphrase='passphrase', osname=None,
options=[], keyfile='/root/.root.keyfile',
randomize=True,
root_dir='root_dir'
)
self.luks_root.create_crypttab.assert_called_once_with(
'root_dir/etc/crypttab'
Expand Down Expand Up @@ -1089,9 +1090,10 @@ def test_create_disk_luks_root_with_disk_password(
self.disk_builder.create_disk()

self.luks_root.create_crypto_luks.assert_called_once_with(
passphrase='passphrase', os=None,
options=[], keyfile='root_dir/root/.root.keyfile',
randomize=True
passphrase='passphrase', osname=None,
options=[], keyfile='/root/.root.keyfile',
randomize=True,
root_dir='root_dir'
)
self.luks_root.create_crypttab.assert_called_once_with(
'root_dir/etc/crypttab'
Expand Down
19 changes: 13 additions & 6 deletions test/unit/storage/luks_device_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,8 @@ def test_create_crypto_luks_empty_passphrase(
):
with patch('builtins.open', create=True):
self.luks.create_crypto_luks(
passphrase='', os='sle12', keyfile='some-keyfile'
passphrase='', osname='sle12',
keyfile='some-keyfile', root_dir='root'
)
assert mock_command.call_args_list == [
call(
Expand All @@ -74,7 +75,7 @@ def test_create_crypto_luks_empty_passphrase(
[
'cryptsetup', '--key-file', '/dev/zero',
'--keyfile-size', '32',
'luksAddKey', '/dev/some-device', 'some-keyfile'
'luksAddKey', '/dev/some-device', 'root/some-keyfile'
]
),
call(
Expand All @@ -87,18 +88,20 @@ def test_create_crypto_luks_empty_passphrase(
]
self.luks.luks_device = None

@patch('kiwi.storage.luks_device.LuksDevice')
@patch('kiwi.storage.luks_device.Command.run')
@patch('kiwi.storage.luks_device.Temporary.new_file')
@patch('os.chmod')
def test_create_crypto_luks(
self, mock_os_chmod, mock_tmpfile, mock_command
self, mock_os_chmod, mock_tmpfile, mock_command, mock_LuksDevice
):
tmpfile = Mock()
tmpfile.name = 'tmpfile'
mock_tmpfile.return_value = tmpfile
with patch('builtins.open', create=True):
self.luks.create_crypto_luks(
passphrase='passphrase', os='sle12', keyfile='some-keyfile'
passphrase='passphrase', osname='sle12',
keyfile='some-keyfile', root_dir='root'
)
assert mock_command.call_args_list == [
call(
Expand All @@ -118,7 +121,7 @@ def test_create_crypto_luks(
call(
[
'cryptsetup', '--key-file', 'tmpfile', 'luksAddKey',
'/dev/some-device', 'some-keyfile'
'/dev/some-device', 'root/some-keyfile'
]
),
call(
Expand All @@ -128,7 +131,11 @@ def test_create_crypto_luks(
]
)
]
self.luks.luks_device = None
mock_LuksDevice.create_random_keyfile.assert_called_once_with(
'root/some-keyfile'
)
assert self.luks.luks_keyfile == 'some-keyfile'
self.luks.luks_device = ''

def test_create_crypttab(self):
self.luks.luks_device = '/dev/mapper/luksRoot'
Expand Down

0 comments on commit b3047fb

Please sign in to comment.