From 37453b91cc6f25f52884c4579492980879fdc49d Mon Sep 17 00:00:00 2001 From: Ancor Gonzalez Sosa Date: Fri, 27 Oct 2023 17:32:33 +0200 Subject: [PATCH] [Service] Delegate TPM-based encryption to YaST --- service/etc/agama.yaml | 12 +- .../dbus/y2dir/manager/modules/Package.rb | 7 ++ service/lib/agama/storage/finisher.rb | 106 ++++-------------- .../agama/storage/proposal_settings_reader.rb | 15 ++- 4 files changed, 47 insertions(+), 93 deletions(-) diff --git a/service/etc/agama.yaml b/service/etc/agama.yaml index 8192ebf72a..dc4886da40 100644 --- a/service/etc/agama.yaml +++ b/service/etc/agama.yaml @@ -38,17 +38,12 @@ ALP-Dolomite: - alp_hardware optional_patterns: null # no optional pattern shared mandatory_packages: - - package: device-mapper # Apparently needed if devices at /dev/mapper are used at boot (eg. FDE) - - package: fde-tools # Needed for FDE with TPM, hardcoded here temporarily - archs: aarch64, x86_64 - - package: libtss2-tcti-device0 - package: ppc64-diag # Needed for hardware-based installations archs: ppc64 optional_packages: null base_product: ALP-Dolomite security: - tpm_luks_open: true lsm: selinux available_lsms: # apparmor: @@ -66,6 +61,7 @@ ALP-Dolomite: encryption: method: luks2 pbkd_function: pbkdf2 + tpm_luks_open: true volumes: - "/" volume_templates: @@ -271,15 +267,10 @@ Leap16: - alp_defaults optional_patterns: null # no optional pattern shared mandatory_packages: - - package: device-mapper # Apparently needed if devices at /dev/mapper are used at boot (eg. FDE) - - package: fde-tools # Needed for FDE with TPM, hardcoded here temporarily - archs: aarch64, x86_64 - - package: libtss2-tcti-device0 optional_packages: null base_product: Leap16 security: - tpm_luks_open: true lsm: selinux available_lsms: # apparmor: @@ -297,6 +288,7 @@ Leap16: encryption: method: luks2 pbkd_function: pbkdf2 + tpm_luks_open: true volumes: - "/" volume_templates: diff --git a/service/lib/agama/dbus/y2dir/manager/modules/Package.rb b/service/lib/agama/dbus/y2dir/manager/modules/Package.rb index 6aeed03f44..ec74593cc7 100644 --- a/service/lib/agama/dbus/y2dir/manager/modules/Package.rb +++ b/service/lib/agama/dbus/y2dir/manager/modules/Package.rb @@ -39,6 +39,13 @@ def Available(_package_name) true end + # Determines whether the package is available + # + # @todo Perform a real D-Bus call. + def AvailableAll(_package_names) + true + end + # Determines whether the package is available # # @see https://github.com/yast/yast-yast2/blob/b8cd178b7f341f6e3438782cb703f4a3ab0529ed/library/packages/src/modules/Package.rb#L121 diff --git a/service/lib/agama/storage/finisher.rb b/service/lib/agama/storage/finisher.rb index 1f8f300860..bfeb3c58c4 100644 --- a/service/lib/agama/storage/finisher.rb +++ b/service/lib/agama/storage/finisher.rb @@ -75,8 +75,8 @@ def possible_steps [ SecurityStep.new(logger, security), CopyFilesStep.new(logger), + StorageStep.new(logger), BootloaderStep.new(logger), - TpmStep.new(logger, config), IguanaStep.new(logger), SnapshotsStep.new(logger), CopyLogsStep.new(logger), @@ -113,18 +113,6 @@ def run? def wfm_write(function) Yast::WFM.CallFunction(function, ["Write"]) end - - # Representation on the staging devicegraph of the root mount point - # - # @return [Y2Storage::MountPoint] - def root_mount_point - staging_graph.mount_points.find(&:root?) - end - - # @return [Y2Storage::Devicegraph] - def staging_graph - Y2Storage::StorageManager.instance.staging - end end # Step to copy files from the inst-sys to the target system @@ -196,6 +184,17 @@ def cio_ignore_finish end end + # Step to finish the Y2Storage configuration + class StorageStep < Step + def label + "Adjusting storage configuration" + end + + def run + wfm_write("storage_finish") + end + end + # Step to configure the file-system snapshots class SnapshotsStep < Step def label @@ -229,75 +228,6 @@ def run end end - # Step to configure LUKS unlocking via TPMv2, if possible - class TpmStep < Step - # Constructor - def initialize(logger, config) - super(logger) - @config = config - end - - def label - "Preparing the system to unlock the encryption using the TPM" - end - - def run? - tpm_product? && tpm_proposal? && tpm_system? - end - - def run - keyfile_path = File.join("root", ".root.keyfile") - Yast::Execute.on_target!( - "fdectl", "add-secondary-key", "--keyfile", keyfile_path, - stdin: "#{luks.password}\n", - recorder: Yast::ReducedRecorder.new(skip: :stdin) - ) - - service = Yast2::Systemd::Service.find("fde-tpm-enroll.service") - logger.info "FDE: TPM enroll service: #{service}" - service&.enable - rescue Cheetah::ExecutionFailed - false - end - - private - - def tpm_proposal? - !!luks - end - - # LUKS device from the devicegraph - # - # @return [Y2Storage::Luks, nil] nil if the root mount point is not encrypted - def luks - root_mount_point.ancestors.find do |dev| - dev.is?(:luks) - end - end - - def tpm_system? - Y2Storage::Arch.new.efiboot? && tpm_present? - end - - def tpm_present? - return @tpm_present unless @tpm_present.nil? - - @tpm_present = - begin - Yast::Execute.on_target!("fdectl", "tpm-present") - logger.info "FDE: TPMv2 detected" - true - rescue Cheetah::ExecutionFailed - logger.info "FDE: TPMv2 not detected" - false - end - end - - def tpm_product? - @config.data.fetch("security", {}).fetch("tpm_luks_open", false) - end - end - # Step to write the mountlist file for Iguana, if needed class IguanaStep < Step IGUANA_PATH = "/iguana" @@ -336,6 +266,18 @@ def root_mount_options options.empty? ? "defaults" : options.join(",") end + + # Representation on the staging devicegraph of the root mount point + # + # @return [Y2Storage::MountPoint] + def root_mount_point + staging_graph.mount_points.find(&:root?) + end + + # @return [Y2Storage::Devicegraph] + def staging_graph + Y2Storage::StorageManager.instance.staging + end end end end diff --git a/service/lib/agama/storage/proposal_settings_reader.rb b/service/lib/agama/storage/proposal_settings_reader.rb index 28aeaa38df..8b04c0beac 100644 --- a/service/lib/agama/storage/proposal_settings_reader.rb +++ b/service/lib/agama/storage/proposal_settings_reader.rb @@ -69,13 +69,26 @@ def lvm_reader(settings, value) # @param settings [Agama::Storage::ProposalSettings] # @param encryption [Hash] def encryption_reader(settings, encryption) - method = Y2Storage::EncryptionMethod.find(encryption.fetch("method", "")) + method = + if try_tpm_fde?(encryption) + Y2Storage::EncryptionMethod::TPM_FDE + else + Y2Storage::EncryptionMethod.find(encryption.fetch("method", "")) + end pbkd_function = Y2Storage::PbkdFunction.find(encryption.fetch("pbkd_function", "")) settings.encryption.method = method if method settings.encryption.pbkd_function = pbkd_function if pbkd_function end + # @param encryption [Hash] + # @return [Boolean] + def try_tpm_fde?(encryption) + return false unless encryption["tpm_luks_open"] == true + + Y2Storage::EncryptionMethod::TPM_FDE.possible? + end + # @param settings [Agama::Storage::ProposalSettings] # @param value [String] def space_policy_reader(settings, value)