[Nix-dev] [PATCH] autofs sshfs-fuse wrapper
Marc Weber
marco-oweber at gmx.de
Fri Dec 18 19:51:34 CET 2009
autofs: Allow mounting ssufs-fuse filesystem using ssh-agents of the users only.
There is afuse as well which might do a better job but that doesn't unmount automatically AFAIK.
Using the example should prevent other users which are logged into your machinge using your mounts.
I'd call it a useful hack
---
modules/services/misc/autofs.nix | 84 ++++++++++++++++++++++++++++++++++---
1 files changed, 77 insertions(+), 7 deletions(-)
diff --git a/modules/services/misc/autofs.nix b/modules/services/misc/autofs.nix
index 079c684..ed0d0bd 100644
--- a/modules/services/misc/autofs.nix
+++ b/modules/services/misc/autofs.nix
@@ -6,6 +6,55 @@ let
cfg = config.services.autofs;
+
+ # ugly but helpful script: if the sshfs mount arguments contain uid= setting
+ # it will try connecting to the remote location using all ssh-agents run by that user.
+ # As the mount is done using sudo only that user can access it unless you use
+ # mount options such as allow_other
+ # See example autoMaster below.
+ sshfsWrapped = pkgs.writeScriptBin "sshfs-wrapped" ''
+ #!/bin/sh -e
+
+ # This is to be run by automount when mounting sshfs-fuse filesystems
+ # for each running ssh-agent it will try connecting using its pid
+ # and auth socket only if the ssh-agent is running as uid = uid of mount
+ # target
+ # This should be much more secure than using empty passwords
+
+ # setuid-wrappers for fusermount
+ export PATH=/var/setuid-wrappers:${pkgs.coreutils}/bin:${pkgs.sshfsFuse}/bin:${pkgs.openssh}/bin:${pkgs.procps}/bin:${pkgs.lsof}/bin:${pkgs.gnused}/bin/:${pkgs.sudo}/bin
+ pids=`pgrep ssh-agent`
+ # get uid=nr from arguments
+ uid=$(echo "$@"| sed -n 's at .*uid=\([0123456789]\+\).*@\1 at p')
+ connect(){
+ sudo=$1; shift
+ $sudo sshfs -o ssh_command="ssh -o NumberOfPasswordPrompts=0" "$@" \
+ && exit 0 || true
+ }
+ # Change ownership of mountpoint. Ownership will be overridden when mount suceeds.
+ # Otherwise fusermount can't access it (?!)
+ chown $uid "$2"
+ chmod u+w "$2"
+ for p in $pids; do
+ res="$(lsof -p $p -a -U -Fnu)"
+ user_id=$(echo "$res"| sed -n 's/^u//p')
+ if [ "$user_id" == "$uid" ]; then
+ export SSH_AUTH_SOCK=$(echo "$res"| sed -n 's/^n//p')
+ export SSH_AGENT_PID=$p
+ echo "trying to connect using ssh-agent $p $SSH_AUTH_SOCK" 1>&2
+ # by using sudo -u allow accessing mount by target user - Is there a better way to achieve this??
+ connect "sudo -E -u#$user_id" "$@"
+ echo -n " .. failed" 1>&2
+ fi
+ done
+ unset SSH_AGENT_PID; unset SSH_AUTH_SOCK
+
+ # no ssh-agent found or they all belong to different users..
+ # Try again. Maybe there is a key without password ?
+ # You should not be using this!
+ connect "" "$@"
+ exit 1
+ '';
in
{
@@ -19,13 +68,15 @@ in
enable = mkOption {
default = false;
description = "
- automatically mount and unmount filesystems
+ automatically mount and unmount filesystems.
+ Note: You should also know about afuse. But afuse doesn't unmount automatically.
+ Known BUGS: If you cd /auto; pkill -TERM automount then /auto/* won't be unmounted (Try umount -l /auto)
";
};
autoMaster = mkOption {
example = ''
- autoMaster = let
+ autoMaster = { sshfs, ... }: let
mapConf = pkgs.writeText "auto" '''
kernel -ro,soft,intr ftp.kernel.org:/pub/linux
boot -fstype=ext2 :/dev/hda1
@@ -36,6 +87,8 @@ in
server -rw,hard,intr / -ro myserver.me.org:/ \
/usr myserver.me.org:/usr \
/home myserver.me.org:/home
+ # replace constants:
+ sshfstarget -fstype=fuse,rw,nodev,nonempty,noatime,max_read=65536,uid=LOCAL_UID,gid=LOCAL_GID ''${sshfs}\#USER at HOST\:
''';
in '''
/auto file:''${mapConf}
@@ -43,9 +96,21 @@ in
'';
description = "
file contents of /etc/auto.master. See man auto.master
- see
- man auto.master and man 5 autofs
+ See man 5 auto.master and man 5 autofs.
";
+
+ apply = textOrFunc: if builtins.isFunction textOrFunc then
+ textOrFunc {
+ #sshfs = pkgs.lib.escape ["/"] "${sshfsWrapped}/bin/sshfs-wrapped";
+ # hacky: work around Nix bug (??)
+ sshfs = "\\/nix\\/store\\/${builtins.baseNameOf (builtins.toString sshfsWrapped)}\\/bin/\\sshfs-wrapped";
+ }
+ else textOrFunc;
+ };
+
+ kernelModules = mkOption {
+ default = ["fuse"];
+ description="kernel modules to load";
};
timeout = mkOption {
@@ -55,7 +120,7 @@ in
debug = mkOption {
default = false;
- description = "pass -d to automount and write log to /var/log/autofs";
+ description = "pass -d and -7 to automount and write log to /var/log/autofs";
};
};
@@ -83,14 +148,19 @@ in
};
preStart =
+ pkgs.lib.concatMapStrings (module : "modprobe ${module} || true\n")
+ (["autofs4"] ++ cfg.kernelModules);
+
+ preStop =
''
- modprobe autofs4 || true
+ set -e; while :; do pkill -TERM automount; sleep 1; done
'';
script =
''
+ # ${sshfsWrapped}/bin/sshfs-wrapped
${if cfg.debug then "exec &> /var/log/autofs" else ""}
- ${pkgs.autofs5}/sbin/automount -f -t ${builtins.toString cfg.timeout} ${if cfg.debug then "-d" else ""} "${pkgs.writeText "auto.master" cfg.autoMaster}"
+ ${pkgs.autofs5}/sbin/automount ${if cfg.debug then "-d" else ""} -f -t ${builtins.toString cfg.timeout} "${pkgs.writeText "auto.master" cfg.autoMaster}" ${if cfg.debug then "-l7" else ""}
'';
};
--
1.6.5.6
More information about the nix-dev
mailing list