Merge pull request #1918 from dbungert/use-zfs-keystore

Use zfs keystore
This commit is contained in:
Dan Bungert 2024-02-27 15:37:19 -07:00 committed by GitHub
commit 0aaade5c53
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 50 additions and 8 deletions

View File

@ -20,6 +20,7 @@ from curtin.block import get_resize_fstypes
from subiquity.common.filesystem import boot, gaps from subiquity.common.filesystem import boot, gaps
from subiquity.common.types import Bootloader from subiquity.common.types import Bootloader
from subiquity.models.filesystem import Partition, align_up from subiquity.models.filesystem import Partition, align_up
from subiquitycore.utils import write_named_tempfile
log = logging.getLogger("subiquity.common.filesystem.manipulator") log = logging.getLogger("subiquity.common.filesystem.manipulator")
@ -188,7 +189,16 @@ class FilesystemManipulator:
self.create_filesystem(dmc, dict(fstype="swap")) self.create_filesystem(dmc, dict(fstype="swap"))
return dmc return dmc
def create_zpool(self, device, pool, mountpoint, boot=False, canmount="on"): def create_zpool(
self,
device,
pool,
mountpoint,
boot=False,
canmount="on",
encryption_style=None,
key=None,
):
fs_properties = dict( fs_properties = dict(
atime=None, atime=None,
acltype="posixacl", acltype="posixacl",
@ -201,6 +211,10 @@ class FilesystemManipulator:
xattr="sa", xattr="sa",
) )
keyfile = None
if key is not None:
keyfile = write_named_tempfile("zpool-key-", key)
pool_properties = dict(ashift=12, autotrim="on", version=None) pool_properties = dict(ashift=12, autotrim="on", version=None)
default_features = True default_features = True
if boot: if boot:
@ -217,6 +231,8 @@ class FilesystemManipulator:
default_features=default_features, default_features=default_features,
fs_properties=fs_properties, fs_properties=fs_properties,
pool_properties=pool_properties, pool_properties=pool_properties,
encryption_style=encryption_style,
keyfile=keyfile,
) )
def delete(self, obj): def delete(self, obj):

View File

@ -36,6 +36,7 @@ from curtin.util import human2bytes
from probert.storage import StorageInfo from probert.storage import StorageInfo
from subiquity.common.types import Bootloader, OsProber, RecoveryKey from subiquity.common.types import Bootloader, OsProber, RecoveryKey
from subiquitycore.utils import write_named_tempfile
log = logging.getLogger("subiquity.models.filesystem") log = logging.getLogger("subiquity.models.filesystem")
@ -1135,10 +1136,7 @@ class DM_Crypt(_Formattable):
def serialize_key(self): def serialize_key(self):
if self.key and not self.keyfile: if self.key and not self.keyfile:
f = tempfile.NamedTemporaryFile(prefix="luks-key-", mode="w", delete=False) return {"keyfile": write_named_tempfile("luks-key-", self.key)}
f.write(self.key)
f.close()
return {"keyfile": f.name}
else: else:
return {} return {}
@ -1312,6 +1310,8 @@ class ZPool:
fs_properties: Optional[dict] = None fs_properties: Optional[dict] = None
default_features: Optional[bool] = True default_features: Optional[bool] = True
encryption_style: Optional[str] = None
keyfile: Optional[str] = None
component_name = "vdev" component_name = "vdev"
@ -2257,6 +2257,8 @@ class FilesystemModel:
default_features=True, default_features=True,
fs_properties=None, fs_properties=None,
pool_properties=None, pool_properties=None,
encryption_style=None,
keyfile=None,
): ):
zpool = ZPool( zpool = ZPool(
m=self, m=self,
@ -2266,6 +2268,8 @@ class FilesystemModel:
default_features=default_features, default_features=default_features,
pool_properties=pool_properties, pool_properties=pool_properties,
fs_properties=fs_properties, fs_properties=fs_properties,
encryption_style=encryption_style,
keyfile=keyfile,
) )
self._actions.append(zpool) self._actions.append(zpool)
return zpool return zpool

View File

@ -565,7 +565,9 @@ class FilesystemController(SubiquityController, FilesystemManipulator):
bootfs_size = align_up(sizes.get_bootfs_size(gap.size), part_align) bootfs_size = align_up(sizes.get_bootfs_size(gap.size), part_align)
gap_boot, gap_rest = gap.split(bootfs_size) gap_boot, gap_rest = gap.split(bootfs_size)
bpart = self.create_partition(device, gap_boot, dict(fstype=None)) bpart = self.create_partition(device, gap_boot, dict(fstype=None))
encrypted = choice.password is not None encryption_style = None
if encrypted := choice.password is not None:
encryption_style = "luks_keystore"
avail = gap_rest.size - self._info.min_size avail = gap_rest.size - self._info.min_size
swap_size = align_down(swap.suggested_swapsize(avail=avail), part_align) swap_size = align_down(swap.suggested_swapsize(avail=avail), part_align)
@ -586,7 +588,14 @@ class FilesystemController(SubiquityController, FilesystemManipulator):
bpool.create_zfs("BOOT", canmount="off", mountpoint="none") bpool.create_zfs("BOOT", canmount="off", mountpoint="none")
bpool.create_zfs(f"BOOT/ubuntu_{uuid}", mountpoint="/boot") bpool.create_zfs(f"BOOT/ubuntu_{uuid}", mountpoint="/boot")
rpool = self.create_zpool(rpart, "rpool", "/", canmount="off") rpool = self.create_zpool(
rpart,
"rpool",
"/",
canmount="off",
encryption_style=encryption_style,
key=choice.password,
)
rpool.create_zfs("ROOT", canmount="off", mountpoint="none") rpool.create_zfs("ROOT", canmount="off", mountpoint="none")
rpool.create_zfs(f"ROOT/ubuntu_{uuid}", mountpoint="/") rpool.create_zfs(f"ROOT/ubuntu_{uuid}", mountpoint="/")
rpool.create_zfs(f"ROOT/ubuntu_{uuid}/var", canmount="off") rpool.create_zfs(f"ROOT/ubuntu_{uuid}/var", canmount="off")
@ -1396,7 +1405,7 @@ class FilesystemController(SubiquityController, FilesystemManipulator):
assert mode == "reformat_disk" assert mode == "reformat_disk"
elif name == "zfs": elif name == "zfs":
if password is not None: if password is not None:
capability = GuidedCapability.ZFS_LUKS capability = GuidedCapability.ZFS_LUKS_KEYSTORE
else: else:
capability = GuidedCapability.ZFS capability = GuidedCapability.ZFS
else: else:

View File

@ -581,6 +581,8 @@ class TestGuided(IsolatedAsyncioTestCase):
[rpool] = self.model._all(type="zpool", pool="rpool") [rpool] = self.model._all(type="zpool", pool="rpool")
self.assertIsNone(rpool.path) self.assertIsNone(rpool.path)
self.assertEqual([root], rpool.vdevs) self.assertEqual([root], rpool.vdevs)
self.assertIsNone(rpool.encryption_style)
self.assertIsNone(rpool.keyfile)
[bpool] = self.model._all(type="zpool", pool="bpool") [bpool] = self.model._all(type="zpool", pool="bpool")
self.assertIsNone(bpool.path) self.assertIsNone(bpool.path)
self.assertEqual([boot], bpool.vdevs) self.assertEqual([boot], bpool.vdevs)
@ -618,6 +620,9 @@ class TestGuided(IsolatedAsyncioTestCase):
[rpool] = self.model._all(type="zpool", pool="rpool") [rpool] = self.model._all(type="zpool", pool="rpool")
self.assertIsNone(rpool.path) self.assertIsNone(rpool.path)
self.assertEqual([root], rpool.vdevs) self.assertEqual([root], rpool.vdevs)
self.assertEqual("luks_keystore", rpool.encryption_style)
with open(rpool.keyfile) as fp:
self.assertEqual("passw0rd", fp.read())
[bpool] = self.model._all(type="zpool", pool="bpool") [bpool] = self.model._all(type="zpool", pool="bpool")
self.assertIsNone(bpool.path) self.assertIsNone(bpool.path)
self.assertEqual([boot], bpool.vdevs) self.assertEqual([boot], bpool.vdevs)

View File

@ -19,6 +19,7 @@ import logging
import os import os
import random import random
import subprocess import subprocess
import tempfile
from typing import Any, Dict, List, Sequence from typing import Any, Dict, List, Sequence
log = logging.getLogger("subiquitycore.utils") log = logging.getLogger("subiquitycore.utils")
@ -282,3 +283,10 @@ def gen_zsys_uuid():
"""Create a 6 character identifier. Functionally equivalent to """Create a 6 character identifier. Functionally equivalent to
`head -100 /dev/urandom | tr -dc 'a-z0-9' | head -c6`""" `head -100 /dev/urandom | tr -dc 'a-z0-9' | head -c6`"""
return "".join([random.choice(_zsys_uuid_charset()) for i in range(6)]) return "".join([random.choice(_zsys_uuid_charset()) for i in range(6)])
def write_named_tempfile(prefix, contents):
f = tempfile.NamedTemporaryFile(prefix=prefix, mode="w", delete=False)
with f:
f.write(contents)
return f.name