How to set up NFS using Kerberos authentication on RHEL 6 using SSSD and Active Directory

Solution Verified - Updated

Environment

  • Red Hat Enterprise Linux 6
  • SSSD
  • Active Directory

Issue

  • How to set up NFS using Kerberos authentication on RHEL 6 using SSSD and Active Directory

Resolution

Notes:

  1. This solution uses SSSD. To use Winbind instead of SSSD, see How to setup NFS using Kerberos authentication on RHEL6 using Winbind and Active Directory.
  2. This solution does not apply to Red Hat Enterprise Linux 7. For Red Hat Enterprise Linux 7, see How to set up NFS using Kerberos authentication on RHEL 7 using SSSD and Active Directory .

Regarding Kerberos principals and Active Directory
Active Directory separates Kerberos principals into two categories: user principals and service principals. User principals are used in the AS (Authentication Service) exchange to obtain a TGT (Ticket-Granting Ticket), and service principals are obtained in the TGS (Ticket-Granting Service) exchange using the TGT. A computer account in Active Directory can have many service principals but only one user principal. As a result, even if you have a key for a principal in your keytab, you can only obtain a TGT using that principal (for example, via kinit) if that principal is in the userPrincipalName field of the computer account in Active Directory. Additionally, you can always obtain a TGT using the principal matching the sAMAccountName attribute in Active Directory (assuming you have a key for that principal in a keytab). The sAMAccountName is typically the short hostname with a $ appended to it.

Also note that if you specify the createupn option when you join an Active Directory domain using the 'net ads join' command, that only updates the userPrincipalName field in Active Directory. You will still need to update the servicePrincipalName field, either using the Active Directory Users and Computers tool in the GUI or the setspn.exe command in the CLI.

Regarding Kerberos principals and NFS
The NFS client will search the keytab for a key to use in the following order (see the rpc.gssd man page):

          <hostname>$@<REALM>
          <HOSTNAME>$@<REALM>
          root/<hostname>@<REALM>
          nfs/<hostname>@<REALM>
          host/<hostname>@<REALM>
          root/<anyname>@<REALM>
          nfs/<anyname>@<REALM>
          host/<anyname>@<REALM>

It will attempt to obtain a TGT using the first matching principal it finds. If it is unable to obtain a TGT using that principal (for example, if that principal does not match the sAMAccountName or userPrincipalName attributes for the computer account in Active Directory), then it will fail to establish a security context with the NFS server. It will not move on to the next principal in the list.

Even though the NFS client can use different principals, the NFS server will only perform NFSv4 callbacks to the client if the client used a service principal (see get_krb5_hostbased_name in the rpc.svcgssd code).

The NFS server will only use the nfs service principal nfs/<hostname>@<REALM> Although rpc.svcgssd has an option to specify a different principal, if you use this then the server will not use callbacks, since the server is hard-coded to use the nfs service principal for NFSv4 callbacks (see set_callback_cred in the kernel code).

Finally, when the NFS server performs a callback to the NFS client the essentially the server becomes the client and the client becomes the server. This means that in order to be able to use callbacks with Kerberized NFS, the client and the server must be running both rpc.gssd and rpc.svcgssd. And since rpc.svcgssd requires an nfs service principal to be present in the keytab in order to start, this means that both the client and the server need to have nfs service principals in this case.

You must decide if you intend to use NFSv4 delegations or not. If NFSv4 delegations are not needed, then you do not need to worry about the server being able to perform callbacks to the client and so the configuration is slightly simpler.

Red Hat's recommendation is to configure both NFS clients and NFS servers to use nfs service principals to ensure maximum functionality of the NFSv4 protocol.

Steps that are common to all machines

  1. Set up the Kerberos configuration in etc/krb5.conf
includedir /var/lib/sss/pubconf/krb5.include.d/

[logging]
 default = FILE:/var/log/krb5libs.log
 kdc = FILE:/var/log/krb5kdc.log
 admin_server = FILE:/var/log/kadmind.log

[libdefaults]
 default_realm = EXAMPLE.COM
 dns_lookup_realm = false
 dns_lookup_kdc = false
 ticket_lifetime = 24h
 renew_lifetime = 7d
 forwardable = true
 rdns = false

[realms]
 EXAMPLE.COM = {
  kdc = ad.example.com
  admin_server = ad.example.com
 }

[domain_realm]
 .example.com = EXAMPLE.COM
 example.com = EXAMPLE.COM
  1. Set up etc/samba/smb.conf This is necessary in order to be able to join the domain via 'net ads join'. You just need the configuration file; you do not need to run Samba or Winbind.
[global]
   security = ads
   realm = EXAMPLE.COM
   workgroup = EXAMPLE
   kerberos method = system keytab
  1. Add an entry for the local machine to your etc/hosts file. This is to prevent the 'net ads join' from failing with the error 'No DNS domain configured for ... Unable to perform DNS Update.' (see https://wiki.samba.org/index.php/Troubleshooting_error_messages_during_Domain_Member_join).
192.168.100.101        server.example.com server
  1. Obtain a Kerberos TGT for a user that has permission to join computers to the domain.
# kinit Adminstrator
  1. Join the domain.
    5a) If NFSv4 delegations are not needed:
# net ads join -k

5b) If NFSv4 delegations are needed:

# net ads join createupn=nfs/server.example.com@EXAMPLE.COM -k

Note 1: The above command is using the hostname of the server as an example; adjust accordingly when running on the client.
Note 2: The createupn option updates the userPrincipalName field of the computer account in Active Directory. Unlike the servicePrincipalName field, which is a list, the userPrincipalName field can contain only one principal. As such, there is no use in running net ads join createupn=... multiple times, as some sources have suggested in the past.

  1. Run nsupdate to create a PTR record for the computer in DNS (see https://access.redhat.com/solutions/331523)
# nsupdate -g
> zone 100.168.192.in-addr.arpa.
> update add 101.100.168.192.in-addr.arpa 3600 in ptr server.example.com.
> send
> CTRL+D
  1. Set up etc/sssd/sssd.conf:
[sssd]
domains = example.com
config_file_version = 2
services = nss, pam

[domain/example.com]
ad_domain = example.com
krb5_realm = EXAMPLE.COM
cache_credentials = True
id_provider = ad
krb5_store_password_if_offline = True
default_shell = /bin/bash
ldap_id_mapping = True
fallback_homedir = /home/%u
access_provider = ad
  1. Start & enable sssd:
# chkconfig sssd on
# service sssd start
  1. Run authconfig to update the NSS and PAM configurations:
# authconfig --enablesssd --enablesssdauth --enablemkhomedir --update
  1. Edit etc/sysconfig/nfs, uncommenting the following line:
SECURE_NFS="yes"

Steps that are specific to NFS servers

  1. Log into the Active Directory Domain Controller and use the setspn command add an nfs service principal for the server:
PS C:\Users\Administrator> setspn -A nfs/server.example.com server
Checking domain DC=example,DC=com

Registering ServicePrincipalNames for CN=server,CN=Computers,DC=example,DC=com
        nfs/server.example.com
Updated object
PS C:\Users\Administrator> setspn -L server
Registered ServicePrincipalNames for CN=server,CN=Computers,DC=example,DC=com:
        nfs/server.example.com
        HOST/server.example.com
        HOST/SERVER
PS C:\Users\Administrator>
  1. Configure the Active Directory KDC omit the PAC data when generating a service ticket for the NFS server (see NFSv4 doesn't handle large Kerberos tickets):
  • Go into Active Directory Users and Computers
  • Select View -> Advanced Features
  • Expand the Computers branch in the tree view and open the account corresponding to the NFS server
  • Select the Attribute Editor tab of the Properties dialog that appears
  • Edit the userAccountControl property
  • Add 33554432 (0x2000000) to the existing value and click OK
  • Make sure that the Value column now shows NO_AUTH_DATA_REQUIRED (it may be necessary to expand the column to see it)
  1. Start the GSS daemon(s):
    13a) If NFSv4 delegations are not needed
    Enable and start rpc.svcgssd:
# chkconfig rpcsvcgssd on
# service rpcsvcgssd start

13b) If NFSv4 delegations are needed
Enable and start rpc.gssd AND rpc.svcgssd:

# chkconfig rpcgssd on
# chkconfig rpcsvcgssd on
# service rpcgssd start
# service rpcsvcgssd start
  1. Create an entry in /etc/exports:
/export *(rw,sec=krb5:krb5i:krb5p)

Steps that are specific to NFS clients


11) If NFSv4 delegations **are not** needed, skip to step 15. Otherwise, log into the Active Directory Domain Controller and use the `setspn` command add an nfs service principal for the client:
PS C:\Users\Administrator> setspn -A nfs/client.example.com client
Checking domain DC=example,DC=com

Registering ServicePrincipalNames for CN=client,CN=Computers,DC=example,DC=com
        nfs/client.example.com
Updated object
PS C:\Users\Administrator> setspn -L client
Registered ServicePrincipalNames for CN=client,CN=Computers,DC=example,DC=com:
        nfs/client.example.com
        HOST/client.example.com
        HOST/CLIENT
PS C:\Users\Administrator>
  1. Configure the Active Directory KDC omit the PAC data when generating a service ticket for the NFS client (see NFSv4 doesn't handle large Kerberos tickets):
  • Go into Active Directory Users and Computers
  • Select View -> Advanced Features
  • Expand the Computers branch in the tree view and open the account corresponding to the NFS client
  • Select the Attribute Editor tab of the Properties dialog that appears
  • Edit the userAccountControl property
  • Add 33554432 (0x2000000) to the existing value and click OK
  • Make sure that the Value column now shows NO_AUTH_DATA_REQUIRED (it may be necessary to expand the column to see it)
  1. Use ktutil to create a keytab containing only the nfs principal (this is necessary to ensure that rpc.gssd will find the nfs service principal first):

A few helpful hints on using ktutil

  • ktutil has only a few simple commands, which can be viewed using ?.
  • When you use the delent command, the remaining entries are shifted upwards in the list. For that reason, it is easier to start with the last entry you wish to delete and work your way upwards.
  • When writing a keytab file using the wkt command, if the keytab file already exists then the records in memory will be appended to the file. You should check for the existence of the keytab file beforehand if this behavior is not desired.
[root@client ~]# ktutil
ktutil:  rkt /etc/krb5.keytab
ktutil:  l
slot KVNO Principal
---- ---- ---------------------------------------------------------------------
   1    2        host/client.example.com@EXAMPLE.COM
   2    2        host/client.example.com@EXAMPLE.COM
   3    2        host/client.example.com@EXAMPLE.COM
   4    2        host/client.example.com@EXAMPLE.COM
   5    2        host/client.example.com@EXAMPLE.COM
   6    2                   host/client@EXAMPLE.COM
   7    2                   host/client@EXAMPLE.COM
   8    2                   host/client@EXAMPLE.COM
   9    2                   host/client@EXAMPLE.COM
  10    2                   host/client@EXAMPLE.COM
  11    2                       CLIENT$@EXAMPLE.COM
  12    2                       CLIENT$@EXAMPLE.COM
  13    2                       CLIENT$@EXAMPLE.COM
  14    2                       CLIENT$@EXAMPLE.COM
  15    2                       CLIENT$@EXAMPLE.COM
  16    2         nfs/client.example.com@EXAMPLE.COM
  17    2         nfs/client.example.com@EXAMPLE.COM
  18    2         nfs/client.example.com@EXAMPLE.COM
  19    2         nfs/client.example.com@EXAMPLE.COM
  20    2         nfs/client.example.com@EXAMPLE.COM
ktutil:  delent 15
ktutil:  delent 14
ktutil:  delent 13
ktutil:  delent 12
ktutil:  delent 11
ktutil:  delent 10
ktutil:  delent 9
ktutil:  delent 8
ktutil:  delent 7
ktutil:  delent 6
ktutil:  delent 5
ktutil:  delent 4
ktutil:  delent 3
ktutil:  delent 2
ktutil:  delent 1
ktutil:  l
slot KVNO Principal
---- ---- ---------------------------------------------------------------------
   1    2         nfs/client.example.com@EXAMPLE.COM
   2    2         nfs/client.example.com@EXAMPLE.COM
   3    2         nfs/client.example.com@EXAMPLE.COM
   4    2         nfs/client.example.com@EXAMPLE.COM
   5    2         nfs/client.example.com@EXAMPLE.COM
ktutil:  wkt /etc/nfs.keytab
ktutil:  q
[root@client ~]# 
  1. If NFSv4 delegations are needed, edit etc/sysconfig/nfs, uncommenting the RPCGSSDARGS line and adding the following:
RPCGSSDARGS="-k /etc/nfs.keytab"
  1. Start the GSS daemon(s):
    15a)If NFSv4 delegations are not needed
    Enable and start rpc.gssd:
# chkconfig rpcgssd on
# service rpcgssd start

15b) If NFSv4 delegations are needed
Enable and start rpc.gssd AND rpc.svcgssd:

# chkconfig rpcgssd on
# chkconfig rpcsvcgssd on
# service rpcgssd start
# service rpcsvcgssd start

You should now be able to mount the NFS filesystem using sec=krb5, sec=krb5i, or sec=krb5p.

Additional Information
Red Hat Enterprise Linux 6.8 and higher include the adcli command, which can simplify the process of joining an Active Directory domain. You do not have to create a minimal smb.conf to use the adcli command, eliminating step 2 in the above instructions. The adcli command also allows you to manipulate both the userPrincipalName and servicePrincipalName attributes, eliminating step 11 in the above instructions.

If using adcli instead of net ads join, step 5 then becomes:

# adcli join --login-ccache=/tmp/krb5cc_0 --user-principal=nfs/server.example.com@EXAMPL.COM --service-name=host --service-name=nfs  example.com
Components
Category

This solution is part of Red Hat’s fast-track publication program, providing a huge library of solutions that Red Hat engineers have created while supporting our customers. To give you the knowledge you need the instant it becomes available, these articles may be presented in a raw and unedited form.