0

I have a Linux sever (Ubuntu Server 24.04 LTS) that will be used for developing Linux-oriented software. Using Kerebros + PAM each user can log into the server via SSH/xRDP using their AD credentials (also available on any Windows system we have on our network). If a /home directory is not available, it is automatically created and assigned when a user logs into the server for the first time.

There are multiple NAS drives in the network where the sever is located that require AD authentication. This is due to our Windows-centric ecosystem. Using the CIFS utilities together with mount I have tried two of the options I have found so far and both require the user to be part of the sudo group. Both use the CIFS utilities and mount. One explicitly requires the user to type in their AD username and password, while the other one does this via a credentials files. I am looking for a way to:

  • not include normal users in the sudo group, yet allow them to execute mount
  • automatically mount any AD-dependent storage during the login (SSH/xRDP) of a user (so that they have their files ready)
  • not use a plaintext credentials file (if required) during mount - if not possible, such a file should only be available to the AD user and not visible to anyone else (including anyone with sudo rights)

For the automounting I am almost sure I need to use fstab, which also requires the same invocation of CIFS as when manually using mount.

UPDATE:

As recommended in the proposed answer I looked into autofs. Apparently one can invoke CIFS mounting through it and it also includes a multiuser option for shares, where multiple users have access to.

Inside auto.master I have the following contents:

+dir:/etc/auto.master.d

/cifs /etc/auto.cifs --timeout=200

I have Kerberos authentication in place now, so AD users have access to a ticket (/tmp/krb5cc_XYZ) that can be used to authenticate against the CIFS shares. My auto.cifs script currently looks like this:

#!/usr/bin/python3

import sys import os import syslog import socket import random import subprocess import dns.resolver import glob

Check for valid ticket and create one as /tmp/krb5cc_XYZ

def findValidTicket(): # CC-file of nslcd krb5cc_nslcd = "/tmp/krb5cc_nslcd"

# Check for the CC-file of nslcd
# We assume this one to be always valid as it is
# kept active by k5start
if os.access(krb5cc_nslcd, os.R_OK):
    os.environ['KRB5CCNAME'] = "FILE:" + krb5cc_nslcd
    return

# Check for another CC-file (AD user specific)
ccfiles = glob.glob('/tmp/krb5cc_*')
if len(ccfiles) > 0:
    for ccfile in ccfiles:
        if os.access(ccfile, os.R_OK):
            os.environ['KRB5CCNAME'] = "FILE:"+ccfile
            # check if CC-file is valid
            if (subprocess.call(['klist', '-s']) == 0):
                return

# No valid ticket found so try to acquire one using system keytab
# Requires superuser
if (os.getgid() == 0):
    try:
        # UNCLEAR 1 HOW TO INITIALIZE THIS FOR A NON-SUDO USER
        subprocess.call(['kinit', '-k'])
        return
    except:
        pass

sys.stderr.write("Unable to find a usable kerberos ticket\n")
sys.exit(1)

Retrieve the shares using smbclient

def getShares(srv): srv = srv.split('.')[0] shares = [] FNULL = open(os.devnull, 'w') # UNCLEAR 2 HOW TO USE KEREBROS AND ALSO AVOID USING SUDO sharestr = subprocess.check_output( ["smbclient", "--use-kerberos=required", "-g", "-L", srv], stderr=FNULL) for l in sharestr.decode().split('\n'): line = l.split('|') if (line[0] == "Disk"): if (line[1][-1:] != '$'): shares.append(line[1]) return shares

ldapServer = "ad.example.com"

findValidTicket()

shares = getShares(ldapServer)

print(f'Shares {shares}')

The first UNCLEAR 1 comment refers to kinit. It can run without sudo but then it 1)needs to manually triggered by the AD user and 2)would probably not work for mounting using CIFS for multiple users.

The second UNCLEAR 2 refers to smbclient itself. A normal user cannot run it so this leads me again to believe (also due to the first I've mentioned) that only a superuser can execute such a script. If I use sudo along with specifying the share and username, as a superuser (even one that is not part of the AD) I am able to list shares interact with those. This part of the script is crucial since it would allow me later on (still working on the code) to mount all shares the users have access to in one loop, iterating through the shares smbclient has returned.

I also don't know which options exactly to use once I call the mounting. The following seems plausible:

-fstype=cifs,vers=1.0,multiuser,sec=krb5,noserverino

As you can see there are many unknowns here. A colleague of mine has done a similar setup or so I thought until I discovered that he has given all AD users sudo permissions and everyone is mounting using the CIFS utilities manually, which not really what I am aiming for.

1 Answers1

0

automatically mount any AD-dependent storage during the login (SSH/xRDP) of a user (so that they have their files ready)

I'm tempted to suggest autofs instead of fstab. That's the traditional "mount on access" mechanism for network home directories.

But pam_mount might be a better fit in some other ways. Or if that's not flexible enough, then pam_exec which does the mounting (or maybe starts a mount-for-user@$PAM_USER.service).

not use a plaintext credentials file (if required) during mount - if not possible, such a file should only be available to the AD user and not visible to anyone else (including anyone with sudo rights)

Have PAM obtain a Kerberos ticket for the user. I believe SSSD already does this, Winbind also definitely had an option to acquire a TGT. The user's Kerberos ticket cache is the "credentials file" for -o sec=krb5 mounts.

(Well, not directly. You don't specify it as a credentials file; instead mount finds it automatically in a round-about way.)

This would even allow you to have a single -o multiuser SMB3 mount where each user automatically gains their own privileges with their own tickets – just like the way UNC paths work in Windows.

If you're forced to use NTLM security for some reason: You can also have a custom PAM module stash the password somewhere, e.g. pam_exec.so that would generate a credentials file in a somewhat safe location. There is no really safe location as long as it's a file, but the user's $XDG_RUNTIME_DIR should do.

There even is a pam_cifscreds.so that stashes the password in a kernel keyring, which is a safe location as the keys are marked as only readable by the kernel. It's meant for use with -o multiuser mounts. See also keyctl show and cifscreds add. Unfortunately, there's an impedance mismatch between this facility and systemd's "systemd --user" sessions.

not include normal users in the sudo group, yet allow them to execute mount

General answer: Look at the contents of the sudoers config file. Write a sudoers rule that allows certain users to execute certain binaries.

But specifically regarding mount: Don't. Allowing someone to run, say, mount -o bind, is just one step away from giving them full root privileges. Find a different way that allows users to run only very specific variations of mount.

Perhaps only let them sudo a wrapper script like /usr/local/bin/homemount – which would set the appropriate options for modern mount -t smb3, as well as defining the necessary parameters for SMB Kerberos authentication.

This is all irrelevant if mounting is done by PAM, which runs in a privileged context.

grawity
  • 501,077