[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