How-To Docs

Quest Authentication Services and NFSv4 on Solaris 10

This document describes how to use NFSv4+Kerberos with Quest Authentication Services under Solaris. Tests were performed on Solaris 10 x86.

Configuring Kerberos

The Solaris implementation of NFSv4 fully supports Kerberos with automatic credential selection when traversing NFSv4+Kerberos mounted filesystem. It supports all the encryption methods in use today, including RC4-HMAC as introduced by Microsoft Windows Active Directory. This means no special configuration is needed to use Active Directory authentication.

To use Kerberos to authenticate NFS mounts some additional configuration steps need to be performed by the system administrator.

First, the administrator must create and manage the nfs/ service principal name (SPN). There are two ways to create an NFS SPN, we will address both.

Creating a new service with vastool

The easiest method is to use vastool to create a service account. This solution has the advantage of keeping the host keytab and the nfs service keytab separate, on the other hand it requires to copy vas.conf in another file requiring the admin to track and sync relevant configuration changes.

On the NFS server use the command:

sol1# vastool -u Administrator service create nfs/

This will create a service account in the Computers container on the domain named machinename-NFS. If the machine name is sol1, then the service account will be named SOL1-NFS. The SPN of the service account will be nfs/fqdn where fqdn is the fully qualified domain name of the machine. If the FQDN of sol1 is sol1.example.com, then the SPN of the NFS service account will be nfs/sol1.example.com.

The vastool service create command will also create the new keytab file /etc/opt/quest/vas/nfs.keytab.

At this point you should now save the original Solaris krb5.conf and replace it with a copy of vas.conf with commands like these:

sol1# mv /etc/krb5/krb5.conf /etc/krb5/krb5.conf.orig
sol1# cp /etc/opt/quest/vas/vas.conf /etc/krb5/krb5.conf

Once you have done this you next have to modify the new krb5.conf's file section named [libdefaults] and change/add two options as follows:

[libdefaults]
default_keytab_name = /etc/opt/quest/vas/nfs.keytab
dns_lookup_kdc = yes

Adding a new SPN to the machine account

Another way of obtaining an NFS SPN is to use the existing machine account and share the host.keytab file with the nfs server service.

NOTE: you can automate the following two steps (the creation of the SPN in the AD object and the creation of the keytab alias) by using the setspn.sh script found in the appendix.

You need to modify the AD computer object to add the new Service Principal Name. To do this there are 2 ways, either download and run the setspn.exe utility on a Windows domain controller, or use the vastool setattrs command. As the SPN is a multivalued attribute you must take care to ensure all the existing values are written back when using vastool setattrs.

Example:

Once you have added the SPN to the computer account object with either setspn.exe or vastool setattrs you need to add the same SPN to the local keytab:

sol1# /opt/quest/bin/vastool ktutil alias host/sol1.example.com \
    nfs/sol1.example.com

After you have properly added the new nfs/ SPN to both the computer account object and the local host keytab you will have to backup and replace the original krb5.conf with a symbolic link to vas.conf. This is done with commands like these:

sol1# mv /etc/krb5/krb5.conf /etc/krb5/krb5.conf.orig
sol1# ln -s /etc/opt/quest/vas/vas.conf /etc/krb5/krb5.conf

Once you have done this you will have to modify the vas.conf file section named [libdefaults] and add the following option:

[libdefaults]
dns_lookup_kdc = yes

Setting up NFSv4 to share user homes

To test our new configuration we use two machines: an NFS server named sol1 and an NFS client named sol2. On the NFS client it is not necessary to create an nfs/ SPN. All you need to do is to replace the system's krb5.conf file with a link to vas.conf:

sol2# mv /etc/krb5/krb5.conf /etc/krb5/krb5.conf.orig
sol2# ln -s /etc/opt/quest/vas/vas.conf /etc/krb5/krb5.conf

And modify the vas.conf file section named [libdefaults] and add the following option:

[libdefaults]
dns_lookup_kdc = yes

NFS server configuration

Let's say we want to share user homes located under /export/home on the server sol1.

First of all we need to tell the nfs server that we want to use Kerberos authentication. To do that we need to uncomment (or add if missing) three lines in the file /etc/nfssec.conf file:

krb5      390003  kerberos_v5  default -         # RPCSEC_GSS
krb5i     390004  kerberos_v5  default integrity # RPCSEC_GSS
krb5p     390005  kerberos_v5  default privacy   # RPCSEC_GSS

These three lines activate three different kerberos modes: auth only, auth and integrity (sign), auth and privacy (sing+encrypt). We will use auth only in our example, but you can easily switch to any mode provide that both the server and the client support them. (Not all platforms implement all modes).

At this point we will tell the NFS server which directory we want to export by modifying the file /etc/dfs/dfstab. We do this by adding this line:

share -F nfs -o sec=krb5 -d "Users home directories" /export/home

The option sec=krb5 instructs the server to use Kerberos authentication.

This is all you need on the server side. Restart the server so that it rereads the new configuration:

sol1# svcadm restart network/nfs/server

NFS client configuration

For the client we need to configure /etc/nfssec.conf the same way we did on the server, plus we want to automount the home directories from the server at user login. Add the following line to the /etc/auto_master file on the client host:

/home           auto_home       -nosuid,sec=krb5

And add the following line to /etc/auto_home file:

*	sol1:/export/home/&

This line will match all usernames and will try to mount the directory /export/home/username from sol1.

You can test your configuration as root with the following steps:

  1. aqcuire a user ticket
    sol2# vastool kinit user1
  2. verify the ticket is stored in the file /tmp/krb5cc_0
    sol2# klist
  3. mount user1's home directory (or any other user's home directory)
    sol2# mount -F nfs -o sec=krb5 sol1:/export/home/user1 /mnt

Under /mnt on sol2 you will now see user1's home directory as served from the NFS server sol1. All the filesystem activity on NFSv4 mount points by the root user will be conducted using the credentials as stored in /tmp/krb5cc_0. Because you obtained a ticket for user1 as root, if you create a new file as root in /mnt on sol2, the new file will not be created as root on sol1 but as user1.

Unmount the test share with these steps:

  1. unmount user1
    sol2# umount /mnt
  2. destroy the ticket
    sol2# vastool kdestroy

At this point you can test a user login to make sure verything works and the user gets their home directory mounted via NFS.

When you access a mount point mount with NFSv4 using Kerberos credentials, the system will automatically detect if you have a valid Kerberos ticket. In case you do you will be automatically authenticated and files manipulation will happen with your Kerberos user's uid/gid. If you don't have a valid ticket then all access will be performed on the server by the user nobody.

NFVv4 and UPM

If you are using Unix personality management (UPM) and you assign a different unix username you will have trouble making the system recognize what UPN to use to authenticate. Normally, NFSv4 uses nsswitch to map UIDs to usernames and then appends to the username the realm to build up the UPN: i.e. username@realm. In a UPM environment you can fix this by manually mapping the user UID to the right UPN with the gsscred utility.

We are evaluating how to address this problem in a transparent way.

Appendix 1

The setspn.sh script.
#!/bin/sh

if [ $# -ne 1 ]; then
        echo "usage: $0 <service>/"
        exit 1
fi

SERVICE="$1"

for i in `/opt/quest/bin/vastool -u host/ service list host`; do
        if  [ -z "$SPN" ]; then
                # Save the first host SPN
                SPN=`echo $i |grep "^host/.*\."`
        fi
        SPNLIST="$SPNLIST $i"
done

if [ -z "$SPN" ]; then
        echo "error: unable to determine current SPN"
        exit 1
fi

NEWSPN=`echo $SPN | sed -e 's,host/,$SERVICE,'`

SPNLIST="$SPNLIST $NEWSPN"

/opt/quest/bin/vastool -u host/ setattrs -m \
    -s $SPN servicePrincipalName $SPNLIST

echo "New SPN List:"
/opt/quest/bin/vastool service list host

— S Sorce, 2006