gocryptfs: sandbox with bunpen
This commit is contained in:
@@ -1,11 +1,13 @@
|
||||
{ ... }:
|
||||
{
|
||||
sane.programs.gocryptfs = {
|
||||
sandbox.method = "landlock";
|
||||
sandbox.method = "bunpen";
|
||||
sandbox.autodetectCliPaths = "existing";
|
||||
sandbox.capabilities = [
|
||||
# CAP_SYS_ADMIN is only required if directly invoking gocryptfs
|
||||
# i.e. not leverage a mount helper like `mount.fuse3-sane`.
|
||||
# CAP_SYS_ADMIN is only required if directly invoking gocryptfs.
|
||||
# it's not *necessarily* required if using a mount helper like `mount.fuse3-sane`
|
||||
# however if using a namespace-based sandbox method (bunpen, bwrap), and you wish
|
||||
# to preserve user mappings, it's still required.
|
||||
"sys_admin"
|
||||
"chown"
|
||||
"dac_override"
|
||||
@@ -16,8 +18,10 @@
|
||||
"setgid"
|
||||
"setuid"
|
||||
];
|
||||
sandbox.tryKeepUsers = true;
|
||||
sandbox.keepPids = true;
|
||||
suggestedPrograms = [
|
||||
"util-linux" #< gocryptfs complains that it can't exec `logger`, otherwise
|
||||
"util-linux" #< gocryptfs complains that it can't exec `logger`, otherwise. TODO(2024-09-09): is this still needed?
|
||||
];
|
||||
};
|
||||
}
|
||||
|
@@ -17,10 +17,12 @@ lib.mkIf config.sane.persist.enable
|
||||
"gocryptfs"
|
||||
];
|
||||
};
|
||||
sandbox.method = "landlock";
|
||||
suggestedPrograms = [ "gocryptfs" ];
|
||||
|
||||
sandbox.method = "bunpen";
|
||||
sandbox.autodetectCliPaths = "existing";
|
||||
sandbox.capabilities = [
|
||||
# "sys_admin" #< omitted: not required if using fuse3-sane with -o pass_fuse_fd
|
||||
"sys_admin" #< XXX: this is required to keep user mappings; for single-user it's actually not necessary if using fuse3-sane with -o pass_fuse_fd
|
||||
"chown"
|
||||
"dac_override"
|
||||
"dac_read_search"
|
||||
@@ -30,7 +32,8 @@ lib.mkIf config.sane.persist.enable
|
||||
"setgid"
|
||||
"setuid"
|
||||
];
|
||||
suggestedPrograms = [ "gocryptfs" ];
|
||||
sandbox.tryKeepUsers = true;
|
||||
sandbox.keepPids = true;
|
||||
};
|
||||
|
||||
sane.persist.stores."ephemeral" = {
|
||||
@@ -59,6 +62,7 @@ lib.mkIf config.sane.persist.enable
|
||||
mount.depends = [
|
||||
config.sane.fs."${backing}".unit
|
||||
];
|
||||
|
||||
# hardening (systemd-analyze security mnt-persist-ephemeral.mount)
|
||||
mount.mountConfig.AmbientCapabilities = "CAP_SYS_ADMIN CAP_DAC_OVERRIDE CAP_DAC_READ_SEARCH CAP_CHOWN CAP_MKNOD CAP_LEASE CAP_SETGID CAP_SETUID CAP_FOWNER";
|
||||
# CAP_LEASE is probably not necessary -- does any fs user use leases?
|
||||
@@ -73,7 +77,7 @@ lib.mkIf config.sane.persist.enable
|
||||
#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 pipefs";
|
||||
mount.mountConfig.RestrictNamespaces = true;
|
||||
# mount.mountConfig.RestrictNamespaces = true;
|
||||
mount.mountConfig.RestrictNetworkInterfaces = "";
|
||||
mount.mountConfig.RestrictRealtime = true;
|
||||
mount.mountConfig.RestrictSUIDSGID = true;
|
||||
|
@@ -7,11 +7,12 @@ backing=$1
|
||||
# facing=$2
|
||||
|
||||
# backing might exist from the last boot, so wipe it:
|
||||
# TODO: should be `rm $backing/*`??
|
||||
rm -fr "$backing"
|
||||
mkdir -p "$backing"
|
||||
|
||||
# the password shows up in /proc/.../env, briefly.
|
||||
# that's inconsequential: we just care that it's not *persisted*.
|
||||
pw=$(dd if=/dev/random bs=128 count=1 | base64 --wrap=0)
|
||||
echo "$pw" | gocryptfs -quiet -passfile /dev/fd/0 -init "$backing"
|
||||
echo "$pw" | exec gocryptfs -quiet -passfile /dev/fd/0 "$@"
|
||||
echo "$pw" | gocryptfs -quiet -nosyslog -passfile /dev/fd/0 -init "$backing"
|
||||
echo "$pw" | exec gocryptfs -quiet -nosyslog -passfile /dev/fd/0 "$@"
|
||||
|
@@ -20,6 +20,7 @@ lib.mkIf config.sane.persist.enable
|
||||
sandbox.method = "bunpen";
|
||||
sandbox.autodetectCliPaths = "parent";
|
||||
sandbox.tryKeepUsers = true;
|
||||
sandbox.keepPids = true;
|
||||
sandbox.capabilities = [ "dac_read_search" ]; #< TODO: this and `tryKeepUsers` shouldn't be needed (it wasn't needed with bwrap)...
|
||||
};
|
||||
sane.programs.gocryptfs-private = {
|
||||
@@ -28,10 +29,10 @@ lib.mkIf config.sane.persist.enable
|
||||
srcRoot = ./.;
|
||||
pkgs = [ "gocryptfs" ];
|
||||
};
|
||||
sandbox.method = "landlock";
|
||||
sandbox.method = "bunpen";
|
||||
sandbox.autodetectCliPaths = "existing";
|
||||
sandbox.capabilities = [
|
||||
# "sys_admin" #< omitted: not required if using fuse3-sane with -o pass_fuse_fd
|
||||
"sys_admin" #< XXX: this is required to keep user mappings; for single-user it's actually not necessary if using fuse3-sane with -o pass_fuse_fd
|
||||
"chown"
|
||||
"dac_override"
|
||||
"dac_read_search"
|
||||
@@ -41,8 +42,10 @@ lib.mkIf config.sane.persist.enable
|
||||
"setgid"
|
||||
"setuid"
|
||||
];
|
||||
sandbox.tryKeepUsers = true;
|
||||
sandbox.keepPids = true;
|
||||
sandbox.extraPaths = [
|
||||
"/run/gocryptfs" #< TODO: teach sanebox about `-o FLAG1=VALUE1,FLAG2=VALUE2` style of argument passing, then use `existingOrParent` autodetect, and remove this
|
||||
"/run/gocryptfs/private.key" #< TODO: teach sanebox about `-o FLAG1=VALUE1,FLAG2=VALUE2` style of argument passing, then use `existing` autodetect, and remove this
|
||||
];
|
||||
suggestedPrograms = [ "gocryptfs" ];
|
||||
};
|
||||
@@ -77,10 +80,10 @@ lib.mkIf config.sane.persist.enable
|
||||
"allow_other" # root ends up being the user that mounts this, so need to make it visible to other users.
|
||||
# "quiet"
|
||||
# "defaults" # "unknown flag: --defaults. Try 'gocryptfs -help'"
|
||||
"passfile=/run/gocryptfs/private.key"
|
||||
# "passfile=/run/gocryptfs/private.key"
|
||||
# options so that we can block for the password file *without* systemd killing us.
|
||||
# see: <https://bbs.archlinux.org/viewtopic.php?pid=1906174#p1906174>
|
||||
"x-systemd.mount-timeout=infinity"
|
||||
# "x-systemd.mount-timeout=infinity"
|
||||
# "retry=10000"
|
||||
# "fg"
|
||||
"pass_fuse_fd"
|
||||
@@ -96,7 +99,7 @@ lib.mkIf config.sane.persist.enable
|
||||
config.sane.fs."/run/gocryptfs/private.key".unit
|
||||
];
|
||||
# unitConfig.DefaultDependencies = "no";
|
||||
mount.mountConfig.TimeoutSec = "infinity";
|
||||
# mount.mountConfig.TimeoutSec = "infinity";
|
||||
|
||||
# hardening (systemd-analyze security mnt-persist-private.mount)
|
||||
mount.mountConfig.AmbientCapabilities = "CAP_SYS_ADMIN CAP_DAC_OVERRIDE CAP_DAC_READ_SEARCH CAP_CHOWN CAP_MKNOD CAP_LEASE CAP_SETGID CAP_SETUID CAP_FOWNER";
|
||||
@@ -110,7 +113,7 @@ lib.mkIf config.sane.persist.enable
|
||||
mount.mountConfig.RemoveIPC = true;
|
||||
mount.mountConfig.RestrictAddressFamilies = "AF_UNIX"; # "none" works, but then it can't connect to the logger
|
||||
mount.mountConfig.RestrictFileSystems = "@common-block @basic-api fuse pipefs";
|
||||
mount.mountConfig.RestrictNamespaces = true;
|
||||
# mount.mountConfig.RestrictNamespaces = true;
|
||||
mount.mountConfig.RestrictNetworkInterfaces = "";
|
||||
mount.mountConfig.RestrictRealtime = true;
|
||||
mount.mountConfig.RestrictSUIDSGID = true;
|
||||
|
@@ -1,6 +1,7 @@
|
||||
#!/usr/bin/env nix-shell
|
||||
#!nix-shell -i bash -p bash -p gocryptfs
|
||||
|
||||
passfile=/run/gocryptfs/private.key
|
||||
gocryptfs --sanebox-path "$passfile" "$@"
|
||||
rm "$passfile"
|
||||
pass_file=/run/gocryptfs/private.key
|
||||
pass_str=$(cat "$pass_file")
|
||||
rm "$pass_file"
|
||||
echo "$pass_str" | exec gocryptfs -nosyslog -passfile /dev/fd/0 "$@"
|
||||
|
@@ -32,6 +32,7 @@ waitForPassfile() {
|
||||
done
|
||||
}
|
||||
validatePassword() {
|
||||
echo "validating password ..."
|
||||
if ! cat "$passfile" | gocryptfs-xray -dumpmasterkey "$conffile" > /dev/null; then
|
||||
echo "failed key validation"
|
||||
rm -f "$passfile"
|
||||
|
Reference in New Issue
Block a user