Often it is desirable to automatically mount a Windows network share. This can be achieved using pam_mount combined with PAM sessions in Posit Workbench.
Install required packages
On Ubuntu 14.04 or later you will need:
sudo apt-get install libpam-mount cifs-utils
On RHEL/CentOS 6 or later you will need:
sudo yum install pam_mount cifs-utils
Test the connection parameters
It makes sense to test the connection parameters for the network share manually:
sudo mount -t cifs //server/path/on/server /local/path -o username=<username>
Configure PAM
A good starting point for the PAM session profile is the su
profile. Copy the PAM config for su
using
sudo cp /etc/pam.d/su /etc/pam.d/rstudio-session
and comment the line auth sufficient pam_rootok.so
that is probably in it.
Test the config
sudo /usr/lib/rstudio-server/bin/pamtester --verbose rstudio-session <username> authenticate
Possible reasons why this fails:
-
su
is only allowed for members of groupwheel
viaauth required pam_wheel.so use_uid
. Comment that line inrstudio-session
.
The next step is to add pam_mount
to the config. How and where one does that depends on the explicit PAM configuration one is using. For example, on a RHEL/CentOS 7 system one could use:
auth substack system-auth auth optional pam_mount.so ### new auth include postlogin account sufficient pam_succeed_if.so uid = 0 use_uid quiet account include system-auth password include system-auth session include system-auth session include postlogin session optional pam_xauth.so session optional pam_mount.so ### new
You have to be careful where you place pam_mount
in the auth
stack. Especially together with LDAP or AD the sufficient
keyword is often used. In that case you must make sure that pam_mount
comes before that entry. This is also true when the include
keyword is used. The replacement substack
protects against this. The pam_mount(8)
man page contains more details on this. The session
stack does not pose such problems.
Configure pam_mount
Now would be a good time to test the configuration again with pamtester
. If it still works you can configure the share that is to be mounted in /etc/security/pam_mount.conf.xml
:
<?xml version="1.0" encoding="utf-8" ?> <!DOCTYPE pam_mount SYSTEM "pam_mount.conf.xml.dtd"> <pam_mount> <volume fstype="cifs" server="server" path="path/on/server" mountpoint="/local/path" /> <!-- ... --> </pam_mount>
Notes:
- This is just the configuration for the mount point. See the
pam_mount.conf(5)
man page for further configuration options. - You can use
%(USER)
inpath
andmountpoint
- You can use
~
as short cut for the user'sHOME
inmountpoint
- There must not be a leading slash in
path
Configure Workbench
Test the rstudio-session
profile again with pamtester
. If you are still able to authenticate, enable it in /etc/rstudio/rserver.conf
:
auth-pam-sessions-enabled=1
auth-pam-sessions-profile=rstudio-session
auth-pam-sessions-use-password=1
After restarting RStudio Workbench and starting a new session you should see the share being mounted in the desired location. Note that when using RStudio Launcher, you will have to configure SSL, c.f. https://docs.posit.co/ide/server-pro/access_and_security/pam_sessions.html.
Hello Ralf,
thanks for the useful article.
Is it possible to combine pam_mount with kerberos, so that a kerberised user automatically mounts a cifs share with his own kerberos ticket on login?
Thanks,
Josef
Hello Josef,
I have never tried that myself, but in the end `pam_mount` only issues `mount` commands and `mount.cifs` in particular supports Kerberos authentication. See the sec=... mount options in mount.cifs(8) (https://linux.die.net/man/8/mount.cifs). Within pam_mount.conf.xml you can specify such options using an options attribute of the volume element.
HTH
Ralf
FYI for anyone attempting to implement this in RHEL 9, as of this post, the pam_mount package is not available. I'm currently trying a 3rd party implementation of it to see if it will work. Also, when I tested in RHEL 8, I found I had to add options to my volume definitions, as it was somehow not seeing the domain suffix how we needed it and it wouldn't work with the naming scheme we used on our CIFS, so had to add:
options='domain="