From 907936e6343240d4abb6b5635928bda4cee1ae64 Mon Sep 17 00:00:00 2001 From: Vojtech Trefny Date: Mon, 12 Aug 2024 18:32:03 +0200 Subject: [PATCH] Add support for creating LUKS HW-OPAL devices This adds support for creating encrypted devices using the OPAL self-encrypting drives. Anaconda only needs to make sure to pass the OPAL administrator passphrase to Blivet when creating the LUKS device, everything else will be taken care by either Blivet or pykickstart -- whether a "normal" or OPAL LUKS device will be created is controlled by the "--luks-version" kickstart option specified by the user which is passed "as is" to Blivet. --- pyanaconda/core/kickstart/commands.py | 6 +++--- .../modules/common/structures/partitioning.py | 19 +++++++++++++++++-- .../automatic/automatic_module.py | 5 +++++ .../automatic/automatic_partitioning.py | 1 + .../custom/custom_partitioning.py | 6 ++++-- .../test_module_part_automatic.py | 4 ++++ 6 files changed, 34 insertions(+), 7 deletions(-) diff --git a/pyanaconda/core/kickstart/commands.py b/pyanaconda/core/kickstart/commands.py index da96f35c45b..029ece1094f 100644 --- a/pyanaconda/core/kickstart/commands.py +++ b/pyanaconda/core/kickstart/commands.py @@ -24,7 +24,7 @@ # Supported kickstart commands. from pykickstart.commands.authselect import F28_Authselect as Authselect -from pykickstart.commands.autopart import F38_AutoPart as AutoPart +from pykickstart.commands.autopart import F41_AutoPart as AutoPart from pykickstart.commands.bootloader import F39_Bootloader as Bootloader from pykickstart.commands.btrfs import F23_BTRFS as BTRFS from pykickstart.commands.cdrom import FC3_Cdrom as Cdrom @@ -54,7 +54,7 @@ from pykickstart.commands.nvdimm import F40_Nvdimm as Nvdimm from pykickstart.commands.ostreecontainer import F38_OSTreeContainer as OSTreeContainer from pykickstart.commands.ostreesetup import F38_OSTreeSetup as OSTreeSetup -from pykickstart.commands.partition import F34_Partition as Partition +from pykickstart.commands.partition import F41_Partition as Partition from pykickstart.commands.raid import F29_Raid as Raid from pykickstart.commands.realm import F19_Realm as Realm from pykickstart.commands.reboot import F23_Reboot as Reboot @@ -93,7 +93,7 @@ from pykickstart.commands.mount import F27_MountData as MountData from pykickstart.commands.network import F39_NetworkData as NetworkData from pykickstart.commands.nvdimm import F28_NvdimmData as NvdimmData -from pykickstart.commands.partition import F29_PartData as PartData +from pykickstart.commands.partition import F41_PartData as PartData from pykickstart.commands.raid import F29_RaidData as RaidData from pykickstart.commands.repo import F30_RepoData as RepoData from pykickstart.commands.snapshot import F26_SnapshotData as SnapshotData diff --git a/pyanaconda/modules/common/structures/partitioning.py b/pyanaconda/modules/common/structures/partitioning.py index ddcb290b151..0ffef6bce41 100644 --- a/pyanaconda/modules/common/structures/partitioning.py +++ b/pyanaconda/modules/common/structures/partitioning.py @@ -47,6 +47,8 @@ def __init__(self): self._escrow_certificate = "" self._backup_passphrase_enabled = False + self._opal_admin_passphrase = "" + @property def partitioning_scheme(self) -> Int: """The partitioning scheme. @@ -255,12 +257,25 @@ def backup_passphrase_enabled(self) -> Bool: def backup_passphrase_enabled(self, enabled: Bool): self._backup_passphrase_enabled = enabled + @property + def opal_admin_passphrase(self) -> Str: + """OPAL admin passphrase to be used when configuring hardware encryption + + :return: a string with the OPAL admin passphrase + """ + return self._opal_admin_passphrase + + @opal_admin_passphrase.setter + def opal_admin_passphrase(self, value: Str): + self._opal_admin_passphrase = value + def __repr__(self): """Generate a string representation.""" return generate_string_from_data( self, - skip=["passphrase"], - add={"passphrase_set": bool(self.passphrase)} + skip=["passphrase", "opal_admin_passphrase"], + add={"passphrase_set": bool(self.passphrase), + "opal_admin_passphrase_set": bool(self.opal_admin_passphrase)} ) diff --git a/pyanaconda/modules/storage/partitioning/automatic/automatic_module.py b/pyanaconda/modules/storage/partitioning/automatic/automatic_module.py index e7ac5bff47a..4e3c7363851 100644 --- a/pyanaconda/modules/storage/partitioning/automatic/automatic_module.py +++ b/pyanaconda/modules/storage/partitioning/automatic/automatic_module.py @@ -92,6 +92,8 @@ def process_kickstart(self, data): request.escrow_certificate = data.autopart.escrowcert request.backup_passphrase_enabled = data.autopart.backuppassphrase + request.opal_admin_passphrase = data.autopart.hw_passphrase + self.set_request(request) def setup_kickstart(self, data): @@ -123,6 +125,9 @@ def setup_kickstart(self, data): data.autopart.escrowcert = self.request.escrow_certificate data.autopart.backuppassphrase = self.request.backup_passphrase_enabled + # Don't generate sensitive information. + data.autopart.hw_passphrase = "" + @property def request(self): """The partitioning request.""" diff --git a/pyanaconda/modules/storage/partitioning/automatic/automatic_partitioning.py b/pyanaconda/modules/storage/partitioning/automatic/automatic_partitioning.py index 5d8c4da3896..507e96c96bc 100644 --- a/pyanaconda/modules/storage/partitioning/automatic/automatic_partitioning.py +++ b/pyanaconda/modules/storage/partitioning/automatic/automatic_partitioning.py @@ -119,6 +119,7 @@ def _get_luks_format_args(storage, request): "pbkdf_args": pbkdf_args, "escrow_cert": escrow_cert, "add_backup_passphrase": request.backup_passphrase_enabled, + "opal_admin_passphrase": request.opal_admin_passphrase, } @staticmethod diff --git a/pyanaconda/modules/storage/partitioning/custom/custom_partitioning.py b/pyanaconda/modules/storage/partitioning/custom/custom_partitioning.py index e59509975f1..4cf899c8ca9 100644 --- a/pyanaconda/modules/storage/partitioning/custom/custom_partitioning.py +++ b/pyanaconda/modules/storage/partitioning/custom/custom_partitioning.py @@ -410,7 +410,8 @@ def _execute_partition_data(self, storage, data, partition_data): escrow_cert=cert, add_backup_passphrase=partition_data.backuppassphrase, luks_version=partition_data.luks_version, - pbkdf_args=pbkdf_args + pbkdf_args=pbkdf_args, + opal_admin_passphrase=partition_data.hw_passphrase, ) luksdev = LUKSDevice( "luks%d" % storage.next_id, @@ -426,7 +427,8 @@ def _execute_partition_data(self, storage, data, partition_data): escrow_cert=cert, add_backup_passphrase=partition_data.backuppassphrase, luks_version=partition_data.luks_version, - pbkdf_args=pbkdf_args + pbkdf_args=pbkdf_args, + opal_admin_passphrase=partition_data.hw_passphrase, ) luksdev = LUKSDevice("luks%d" % storage.next_id, fmt=luksformat, diff --git a/tests/unit_tests/pyanaconda_tests/modules/storage/partitioning/test_module_part_automatic.py b/tests/unit_tests/pyanaconda_tests/modules/storage/partitioning/test_module_part_automatic.py index 384dd8e39ce..79aa2b16bc3 100644 --- a/tests/unit_tests/pyanaconda_tests/modules/storage/partitioning/test_module_part_automatic.py +++ b/tests/unit_tests/pyanaconda_tests/modules/storage/partitioning/test_module_part_automatic.py @@ -102,6 +102,7 @@ def test_request_property(self): 'pbkdf-iterations': get_variant(Int, 1000), 'escrow-certificate': get_variant(Str, 'file:///tmp/escrow.crt'), 'backup-passphrase-enabled': get_variant(Bool, True), + 'opal-admin-passphrase': get_variant(Str, '123456'), } self._check_dbus_property( "Request", @@ -200,6 +201,7 @@ def test_luks1_format_args(self): request.cipher = "aes-xts-plain64" request.escrow_certificate = "file:///tmp/escrow.crt" request.backup_passphrase_enabled = True + request.opal_admin_passphrase = "passphrase" args = AutomaticPartitioningTask._get_luks_format_args(storage, request) assert args == { @@ -209,6 +211,7 @@ def test_luks1_format_args(self): "pbkdf_args": None, "escrow_cert": "CERTIFICATE", "add_backup_passphrase": True, + "opal_admin_passphrase": "passphrase", } def test_luks2_format_args(self): @@ -231,6 +234,7 @@ def test_luks2_format_args(self): "luks_version": "luks2", "escrow_cert": None, "add_backup_passphrase": False, + "opal_admin_passphrase": "", } assert isinstance(pbkdf_args, LUKS2PBKDFArgs)