How to set up NFS using Kerberos authentication on RHEL 7 using SSSD and Active Directory
Environment
- Red Hat Enterprise Linux 7
- SSSD
- realmd
- Active Directory
Issue
- How to set up NFS using Kerberos authentication on RHEL 7 using SSSD and Active Directory
Resolution
Note: This solution applies to Red Hat Enterprise Linux 7. The configuration required for Red Hat Enterprise Linux 6 is documented in How to set up NFS using Kerberos authentication on RHEL 6 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 the last block in gssp_accept_sec_context_upcall in net/sunrpc/auth_gss/gss_rpc_upcall.c in the kernel code).
The NFS server will only use the nfs service principal nfs/<hostname>@<REALM>.
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 gssproxy.
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
- Install the necessary packages (Note this will install any necessary dependencies as well).
yum install realmd krb5-workstation sssd adcli samba-common oddjob oddjob-mkhomedir
- 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 = addc.example.com
admin_server = addc.example.com
}
[domain_realm]
.example.com = EXAMPLE.COM
example.com = EXAMPLE.COM
- Obtain a Kerberos TGT for a user that has permission to join computers to the domain.
# kinit Administrator
- Use
realm discoverbefore joining the domain.
# realm discover example.com
example.com
type: kerberos
realm-name: EXAMPLE.COM
domain-name: example.com
configured: no
server-software: active-directory
client-software: sssd
required-package: oddjob
required-package: oddjob-mkhomedir
required-package: sssd
required-package: adcli
required-package: samba-common
- Join the domain.
5a) If NFSv4 delegations are not needed:
# realm join example.com
5b) If NFSv4 delegations are needed:
# realm join --user-principal=nfs/server.example.com@EXAMPLE.COM example.com
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 --user-principal 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.
Note 3: The 'realm join' command automatically updates the SSSD, PAM, and nsswitch configurations, and starts the SSSD service.
Steps that are specific to NFS servers
- Log into the Active Directory Domain Controller and use the
setspncommand add an nfs service principal for the server:
PS C:\Users\Administrator> setspn -S 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>
- Start the GSS daemon(s).
Note: In RHEL 7, handling of Kerberos credentials on behalf of thenfsdkernel threads on the NFS server, as well as the NFSv4 callback service on the NFS client, is handled bygssproxyrather thanrpc.svcgssd.rpc.svcgssdhas been deprecated. See Chapter 24 of the RHEL 7.0 Release Notes.
7a) If NFSv4 delegations are not needed
Verify that gssproxy is running. It should already be running by default, and it is not necessary to enable it in systemd.
# systemctl status gssproxy
7b) If NFSv4 delegations are needed
Verify that gssproxy is running, and start the rpc-gssd service. This is only necessary right after joining the domain. On subsequent reboots both service should start automatically, and it is not necessary to enable either in systemd.
# systemctl status gssproxy
# systemctl start rpc-gssd
- Create an entry in
/etc/exports:
/export *(rw,sec=krb5:krb5i:krb5p)
Steps that are specific to NFS clients
6) If NFSv4 delegations **are not** needed, skip to step 10. 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 -S 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>
- Use
ktutilto 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
ktutilhas only a few simple commands, which can be viewed using?.- When you use the
delentcommand, 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
wktcommand, 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 ~]#
- If NFSv4 delegations are needed, edit
etc/sysconfig/nfs, uncommenting theRPCGSSDARGSline and adding the following:
RPCGSSDARGS="-k /etc/nfs.keytab"
- Refresh the NFS configuration
systemctl restart nfs-config
- Start the GSS daemon(s).
Note: In RHEL 7, handling of Kerberos credentials on behalf of thenfsdkernel threads on the NFS server, as well as the NFSv4 callback service on the NFS client, is handled bygssproxyrather thanrpc.svcgssd.rpc.svcgssdhas been deprecated. See Chapter 24 of the RHEL 7.0 Release Notes.
10a) If NFSv4 delegations are not needed
Start the rpc-gssd service. This is only necessary right after joining the domain. On subsequent reboots the service should start automatically, and it is not necessary to enable it in systemd.
# systemctl start rpc-gssd
10b) If NFSv4 delegations are needed
Verify that gssproxy is running, and start the rpc-gssd service. This is only necessary right after joining the domain. On subsequent reboots both service should start automatically, and it is not necessary to enable either in systemd.
# systemctl status gssproxy
# systemctl start rpc-gssd
You should now be able to mount the NFS filesystem using sec=krb5, sec=krb5i, or sec=krb5p.
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.