Send patches - preferably formatted by git format-patch - to patches at archlinux32 dot org.
summaryrefslogtreecommitdiff
path: root/archinstall/lib/installer.py
diff options
context:
space:
mode:
authorAnton Hvornum <anton@hvornum.se>2021-11-23 23:09:33 +0000
committerGitHub <noreply@github.com>2021-11-24 00:09:33 +0100
commite729457b6c12a00b17207254ee72e98b78912f8d (patch)
tree554c13c7a363ccc5ef2c25873af15598df9a2ba3 /archinstall/lib/installer.py
parent29736c4a051d2c72bcbf0b20abdebc6992a92e4b (diff)
Support encrypting multiple partitions (#759)
* Added support for storing disk encryption keyfiles and add them to a keyslot. * Added a luks2().add_key() function in order to inject a keyfile into a keyslot on a encrypted volume. * Simplified 'missing encryption password' logic in Filesystem(). Added a call to luks2().add_key() after the root-password is set on the volume, to add the keyfile in slot 2 * Adding in password handling in luks2().add_key(). It's required to enter a previous passphrase to unlock the volume and add a new keyslot. Also simplified the handling of partition in Installer().mount_ordered_layout() * Adding in encryption on all partitions except /boot when encryption is opted in * Removed setting size on Partition() as it's a read only value. No idea how Partition().size = size hasn't caused an issue before. Removed size=X argument to Partition() * Added a uniqueness to the loopdevice name. This should ensure that multiple encrypted volumes can be opened at the same time, except for Partition().detect_inner_filesystem() operations which can only happen one at a time since they share namespace. This should never be an issue since archinstall is single threaded and no concurrent operations can/should happen. * Added partprobe() as part of disk/helpers.py, added a /dev/ -> UUID mapper function called convert_device_to_uuid(path). Added a luks2().crypttab() function that sets up a /etc/crypttab entry. * Moved the responsability for telling archinstall to generate a keyfile from Filesystem() to user_interaction.py. This should in the future be a user-input based value, and not something the Filesystem() automatically dictates. * Added a retry mechanism to luks2().encrypt() to avoid having to re-start the installation when a device simply wasn't up yet. * Swapping UUID= lookup from loopdev to physdev.
Diffstat (limited to 'archinstall/lib/installer.py')
-rw-r--r--archinstall/lib/installer.py35
1 files changed, 26 insertions, 9 deletions
diff --git a/archinstall/lib/installer.py b/archinstall/lib/installer.py
index 07de94e0..2629c0f7 100644
--- a/archinstall/lib/installer.py
+++ b/archinstall/lib/installer.py
@@ -8,7 +8,7 @@ import pathlib
import subprocess
import glob
from .disk import get_partitions_in_use, Partition
-from .general import SysCommand
+from .general import SysCommand, generate_password
from .hardware import has_uefi, is_vm, cpu_vendor
from .locale_helpers import verify_keyboard_layout, verify_x11_keyboard_layout
from .disk.helpers import get_mount_info
@@ -187,18 +187,35 @@ class Installer:
mountpoints[partition['mountpoint']] = partition
for mountpoint in sorted(mountpoints.keys()):
- if mountpoints[mountpoint].get('encrypted', False):
- loopdev = storage.get('ENC_IDENTIFIER', 'ai') + 'loop'
- if not (password := mountpoints[mountpoint].get('!password', None)):
- raise RequirementError(f"Missing mountpoint {mountpoint} encryption password in layout: {mountpoints[mountpoint]}")
+ partition = mountpoints[mountpoint]
+
+ if partition.get('encrypted', False):
+ loopdev = f"{storage.get('ENC_IDENTIFIER', 'ai')}{pathlib.Path(partition['mountpoint']).name}loop"
+ if not (password := partition.get('!password', None)):
+ raise RequirementError(f"Missing mountpoint {mountpoint} encryption password in layout: {partition}")
+
+ with (luks_handle := luks2(partition['device_instance'], loopdev, password, auto_unmount=False)) as unlocked_device:
+ if partition.get('generate-encryption-key-file'):
+ if not (cryptkey_dir := pathlib.Path(f"{self.target}/etc/cryptsetup-keys.d")).exists():
+ cryptkey_dir.mkdir(parents=True, exist_ok=True)
+
+ # Once we store the key as ../xyzloop.key systemd-cryptsetup can automatically load this key
+ # if we name the device to "xyzloop".
+ encryption_key_path = f"/etc/cryptsetup-keys.d/{pathlib.Path(partition['mountpoint']).name}loop.key"
+ with open(f"{self.target}{encryption_key_path}", "w") as keyfile:
+ keyfile.write(generate_password(length=512))
+
+ os.chmod(encryption_key_path, 0o400)
+
+ luks_handle.add_key(pathlib.Path(f"{self.target}{encryption_key_path}"), password=password)
+ luks_handle.crypttab(self, encryption_key_path, options=["luks", "key-slot=1"])
- with luks2(mountpoints[mountpoint]['device_instance'], loopdev, password, auto_unmount=False) as unlocked_device:
log(f"Mounting {mountpoint} to {self.target}{mountpoint} using {unlocked_device}", level=logging.INFO)
unlocked_device.mount(f"{self.target}{mountpoint}")
else:
- log(f"Mounting {mountpoint} to {self.target}{mountpoint} using {mountpoints[mountpoint]['device_instance']}", level=logging.INFO)
- mountpoints[mountpoint]['device_instance'].mount(f"{self.target}{mountpoint}")
+ log(f"Mounting {mountpoint} to {self.target}{mountpoint} using {partition['device_instance']}", level=logging.INFO)
+ partition['device_instance'].mount(f"{self.target}{mountpoint}")
time.sleep(1)
try:
@@ -206,7 +223,7 @@ class Installer:
except DiskError:
raise DiskError(f"Target {self.target}{mountpoint} never got mounted properly (unable to get mount information using findmnt).")
- if (subvolumes := mountpoints[mountpoint].get('btrfs', {}).get('subvolumes', {})):
+ if (subvolumes := partition.get('btrfs', {}).get('subvolumes', {})):
for name, location in subvolumes.items():
create_subvolume(self, location)
mount_subvolume(self, location)