Skip to content

Commit

Permalink
[Service] Delegate TPM-based encryption to YaST
Browse files Browse the repository at this point in the history
  • Loading branch information
ancorgs committed Oct 27, 2023
1 parent eec3080 commit 37453b9
Show file tree
Hide file tree
Showing 4 changed files with 47 additions and 93 deletions.
12 changes: 2 additions & 10 deletions service/etc/agama.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand All @@ -66,6 +61,7 @@ ALP-Dolomite:
encryption:
method: luks2
pbkd_function: pbkdf2
tpm_luks_open: true
volumes:
- "/"
volume_templates:
Expand Down Expand Up @@ -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:
Expand All @@ -297,6 +288,7 @@ Leap16:
encryption:
method: luks2
pbkd_function: pbkdf2
tpm_luks_open: true
volumes:
- "/"
volume_templates:
Expand Down
7 changes: 7 additions & 0 deletions service/lib/agama/dbus/y2dir/manager/modules/Package.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
106 changes: 24 additions & 82 deletions service/lib/agama/storage/finisher.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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),
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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"
Expand Down Expand Up @@ -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
Expand Down
15 changes: 14 additions & 1 deletion service/lib/agama/storage/proposal_settings_reader.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down

0 comments on commit 37453b9

Please sign in to comment.