From 14e96d3342a984f05641bda0e256e8af4f923890 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 | 4 ++++ .../automatic/automatic_partitioning.py | 1 + .../custom/custom_partitioning.py | 6 ++++-- .../test_module_part_automatic.py | 4 ++++ 6 files changed, 33 insertions(+), 7 deletions(-) diff --git a/pyanaconda/core/kickstart/commands.py b/pyanaconda/core/kickstart/commands.py index da96f35c45b9..029ece1094f8 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 20adc6f5c1f8..6de271b66428 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 e7ac5bff47a7..c55cf5b75866 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.opal_admin_passphrase + self.set_request(request) def setup_kickstart(self, data): @@ -123,6 +125,8 @@ def setup_kickstart(self, data): data.autopart.escrowcert = self.request.escrow_certificate data.autopart.backuppassphrase = self.request.backup_passphrase_enabled + data.opal_admin_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 5d8c4da38969..507e96c96bc7 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 e59509975f1d..93c3bdc7522b 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.opal_admin_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.opal_admin_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 384dd8e39ce0..79aa2b16bc32 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)