From 3cbb45fa4cce9c83bab08f91a537cd8d7aa596a0 Mon Sep 17 00:00:00 2001 From: Colin Date: Sun, 29 Sep 2024 01:52:34 +0000 Subject: [PATCH] hosts/common/fs: remoteHome: remove use of sane.fs.*.mount part of an effort to simplify sane.fs --- hosts/common/fs.nix | 80 +++++++++++++++++++++++++-------------------- 1 file changed, 45 insertions(+), 35 deletions(-) diff --git a/hosts/common/fs.nix b/hosts/common/fs.nix index a8933929d..5c26e73ca 100644 --- a/hosts/common/fs.nix +++ b/hosts/common/fs.nix @@ -77,48 +77,58 @@ let ifSshAuthorized = lib.mkIf config.sane.hosts.by-name."${config.networking.hostName}".ssh.authorized; - remoteHome = name: { host ? name }: { + remoteHome = name: { host ? name }: let + mountpoint = "/mnt/${name}/home"; + device = "sshfs#colin@${host}:/home/colin"; + fsType = "fuse3"; + options = fsOpts.sshColin ++ fsOpts.lazyMount ++ [ + # drop_privileges: after `mount.fuse3` opens /dev/fuse, it will drop all capabilities before invoking sshfs + "drop_privileges" + "auto_unmount" #< ensures that when the fs exits, it releases its mountpoint. then systemd can recognize it as failed. + # disable defaults: don't require this to be mount as part of local-fs.target + "noauto" + "nofail" + ]; + in { sane.programs.sshfs-fuse.enableFor.system = true; system.fsPackages = [ config.sane.programs.sshfs-fuse.package ]; - fileSystems."/mnt/${name}/home" = { - device = "sshfs#colin@${host}:/home/colin"; - fsType = "fuse3"; - options = fsOpts.sshColin ++ fsOpts.lazyMount ++ [ - # drop_privileges: after `mount.fuse3` opens /dev/fuse, it will drop all capabilities before invoking sshfs - "drop_privileges" - "auto_unmount" #< ensures that when the fs exits, it releases its mountpoint. then systemd can recognize it as failed. - ]; + fileSystems."${mountpoint}" = { + inherit device fsType options; noCheck = true; }; - sane.fs."/mnt/${name}/home" = { - dir.acl.user = "colin"; - dir.acl.group = "users"; - dir.acl.mode = "0700"; + # tell systemd about the mount so that i can sandbox it + systemd.mounts = [{ + where = mountpoint; + what = device; + type = fsType; + options = lib.concatStringsSep "," options; wantedBy = [ "default.target" ]; - mount.depends = [ "network-online.target" ]; - mount.mountConfig.ExecSearchPath = [ "/run/current-system/sw/bin" ]; - mount.mountConfig.User = "colin"; - mount.mountConfig.AmbientCapabilities = "CAP_SETPCAP CAP_SYS_ADMIN"; + after = [ "network-online.target" ]; + requires = [ "network-online.target" ]; + + mountConfig.ExecSearchPath = [ "/run/current-system/sw/bin" ]; + mountConfig.User = "colin"; + mountConfig.AmbientCapabilities = "CAP_SETPCAP CAP_SYS_ADMIN"; # hardening (systemd-analyze security mnt-desko-home.mount): # TODO: i can't use ProtectSystem=full here, because i can't create a new mount space; but... # with drop_privileges, i *could* sandbox the actual `sshfs` program using e.g. bwrap - mount.mountConfig.CapabilityBoundingSet = "CAP_SETPCAP CAP_SYS_ADMIN"; - mount.mountConfig.LockPersonality = true; - mount.mountConfig.MemoryDenyWriteExecute = true; - mount.mountConfig.NoNewPrivileges = true; - mount.mountConfig.ProtectClock = true; - mount.mountConfig.ProtectHostname = true; - mount.mountConfig.RemoveIPC = true; - mount.mountConfig.RestrictAddressFamilies = "AF_UNIX AF_INET AF_INET6"; + mountConfig.CapabilityBoundingSet = "CAP_SETPCAP CAP_SYS_ADMIN"; + mountConfig.LockPersonality = true; + mountConfig.MemoryDenyWriteExecute = true; + mountConfig.NoNewPrivileges = true; + mountConfig.ProtectClock = true; + mountConfig.ProtectHostname = true; + mountConfig.RemoveIPC = true; + mountConfig.RestrictAddressFamilies = "AF_UNIX AF_INET AF_INET6"; #VVV this includes anything it reads from, e.g. /bin/sh; /nix/store/... # see `systemd-analyze filesystems` for a full list - mount.mountConfig.RestrictFileSystems = "@common-block @basic-api fuse"; - mount.mountConfig.RestrictRealtime = true; - mount.mountConfig.RestrictSUIDSGID = true; - mount.mountConfig.SystemCallArchitectures = "native"; - mount.mountConfig.SystemCallFilter = [ + mountConfig.RestrictFileSystems = "@common-block @basic-api fuse"; + mountConfig.RestrictRealtime = true; + mountConfig.RestrictSUIDSGID = true; + mountConfig.SystemCallArchitectures = "native"; + mountConfig.SystemCallFilter = [ "@system-service" "@mount" "~@chown" @@ -127,12 +137,12 @@ let # could remove almost all io calls, however one has to keep `open`, and `write`, to communicate with the fuse device. # so that's pretty useless as a way to prevent write access ]; - mount.mountConfig.IPAddressDeny = "any"; - mount.mountConfig.IPAddressAllow = "10.0.0.0/8"; - mount.mountConfig.DevicePolicy = "closed"; # only allow /dev/{null,zero,full,random,urandom} - mount.mountConfig.DeviceAllow = "/dev/fuse"; + mountConfig.IPAddressDeny = "any"; + mountConfig.IPAddressAllow = "10.0.0.0/8"; + mountConfig.DevicePolicy = "closed"; # only allow /dev/{null,zero,full,random,urandom} + mountConfig.DeviceAllow = "/dev/fuse"; # mount.mountConfig.RestrictNamespaces = true; #< my sshfs sandboxing uses bwrap - }; + }]; }; remoteServo = subdir: let localPath = "/mnt/servo/${subdir}";