Skip to content

Commit

Permalink
Merge pull request #1918 from dbungert/use-zfs-keystore
Browse files Browse the repository at this point in the history
Use zfs keystore
  • Loading branch information
dbungert authored Feb 27, 2024
2 parents d886dcd + 922d1bd commit 0aaade5
Show file tree
Hide file tree
Showing 5 changed files with 50 additions and 8 deletions.
18 changes: 17 additions & 1 deletion subiquity/common/filesystem/manipulator.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
from subiquity.common.filesystem import boot, gaps
from subiquity.common.types import Bootloader
from subiquity.models.filesystem import Partition, align_up
from subiquitycore.utils import write_named_tempfile

log = logging.getLogger("subiquity.common.filesystem.manipulator")

Expand Down Expand Up @@ -188,7 +189,16 @@ def create_cryptoswap(self, device):
self.create_filesystem(dmc, dict(fstype="swap"))
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(
atime=None,
acltype="posixacl",
Expand All @@ -201,6 +211,10 @@ def create_zpool(self, device, pool, mountpoint, boot=False, canmount="on"):
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)
default_features = True
if boot:
Expand All @@ -217,6 +231,8 @@ def create_zpool(self, device, pool, mountpoint, boot=False, canmount="on"):
default_features=default_features,
fs_properties=fs_properties,
pool_properties=pool_properties,
encryption_style=encryption_style,
keyfile=keyfile,
)

def delete(self, obj):
Expand Down
12 changes: 8 additions & 4 deletions subiquity/models/filesystem.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
from probert.storage import StorageInfo

from subiquity.common.types import Bootloader, OsProber, RecoveryKey
from subiquitycore.utils import write_named_tempfile

log = logging.getLogger("subiquity.models.filesystem")

Expand Down Expand Up @@ -1135,10 +1136,7 @@ def __post_init__(self) -> None:

def serialize_key(self):
if self.key and not self.keyfile:
f = tempfile.NamedTemporaryFile(prefix="luks-key-", mode="w", delete=False)
f.write(self.key)
f.close()
return {"keyfile": f.name}
return {"keyfile": write_named_tempfile("luks-key-", self.key)}
else:
return {}

Expand Down Expand Up @@ -1312,6 +1310,8 @@ class ZPool:
fs_properties: Optional[dict] = None

default_features: Optional[bool] = True
encryption_style: Optional[str] = None
keyfile: Optional[str] = None

component_name = "vdev"

Expand Down Expand Up @@ -2257,6 +2257,8 @@ def add_zpool(
default_features=True,
fs_properties=None,
pool_properties=None,
encryption_style=None,
keyfile=None,
):
zpool = ZPool(
m=self,
Expand All @@ -2266,6 +2268,8 @@ def add_zpool(
default_features=default_features,
pool_properties=pool_properties,
fs_properties=fs_properties,
encryption_style=encryption_style,
keyfile=keyfile,
)
self._actions.append(zpool)
return zpool
Expand Down
15 changes: 12 additions & 3 deletions subiquity/server/controllers/filesystem.py
Original file line number Diff line number Diff line change
Expand Up @@ -565,7 +565,9 @@ def guided_zfs(self, gap, choice: GuidedChoiceV2):
bootfs_size = align_up(sizes.get_bootfs_size(gap.size), part_align)
gap_boot, gap_rest = gap.split(bootfs_size)
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
swap_size = align_down(swap.suggested_swapsize(avail=avail), part_align)
Expand All @@ -586,7 +588,14 @@ def guided_zfs(self, gap, choice: GuidedChoiceV2):
bpool.create_zfs("BOOT", canmount="off", mountpoint="none")
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(f"ROOT/ubuntu_{uuid}", mountpoint="/")
rpool.create_zfs(f"ROOT/ubuntu_{uuid}/var", canmount="off")
Expand Down Expand Up @@ -1396,7 +1405,7 @@ async def run_autoinstall_guided(self, layout):
assert mode == "reformat_disk"
elif name == "zfs":
if password is not None:
capability = GuidedCapability.ZFS_LUKS
capability = GuidedCapability.ZFS_LUKS_KEYSTORE
else:
capability = GuidedCapability.ZFS
else:
Expand Down
5 changes: 5 additions & 0 deletions subiquity/server/controllers/tests/test_filesystem.py
Original file line number Diff line number Diff line change
Expand Up @@ -581,6 +581,8 @@ async def test_guided_zfs(self, bootloader, ptable, p1mnt):
[rpool] = self.model._all(type="zpool", pool="rpool")
self.assertIsNone(rpool.path)
self.assertEqual([root], rpool.vdevs)
self.assertIsNone(rpool.encryption_style)
self.assertIsNone(rpool.keyfile)
[bpool] = self.model._all(type="zpool", pool="bpool")
self.assertIsNone(bpool.path)
self.assertEqual([boot], bpool.vdevs)
Expand Down Expand Up @@ -618,6 +620,9 @@ async def test_guided_zfs_luks_keystore(self, bootloader, ptable, p1mnt):
[rpool] = self.model._all(type="zpool", pool="rpool")
self.assertIsNone(rpool.path)
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")
self.assertIsNone(bpool.path)
self.assertEqual([boot], bpool.vdevs)
Expand Down
8 changes: 8 additions & 0 deletions subiquitycore/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import os
import random
import subprocess
import tempfile
from typing import Any, Dict, List, Sequence

log = logging.getLogger("subiquitycore.utils")
Expand Down Expand Up @@ -282,3 +283,10 @@ def gen_zsys_uuid():
"""Create a 6 character identifier. Functionally equivalent to
`head -100 /dev/urandom | tr -dc 'a-z0-9' | head -c6`"""
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

0 comments on commit 0aaade5

Please sign in to comment.