How to set up NFS using Kerberos authentication on RHEL 6 using SSSD and Active Directory
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:
- This solution uses
SSSD. To useWinbindinstead ofSSSD, see How to setup NFS using Kerberos authentication on RHEL6 using Winbind and Active Directory. - 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
- 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
- Set up
etc/samba/smb.confThis 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
- Add an entry for the local machine to your
etc/hostsfile. 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
- Obtain a Kerberos TGT for a user that has permission to join computers to the domain.
# kinit Adminstrator
- 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.
- Run
nsupdateto 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
- 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
- Start & enable
sssd:
# chkconfig sssd on
# service sssd start
- Run
authconfigto update the NSS and PAM configurations:
# authconfig --enablesssd --enablesssdauth --enablemkhomedir --update
- Edit
etc/sysconfig/nfs, uncommenting the following line:
SECURE_NFS="yes"
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 -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>
- 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
userAccountControlproperty - 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)
- Start the GSS daemon(s):
13a) If NFSv4 delegations are not needed
Enable and startrpc.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
- 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>
- 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
userAccountControlproperty - 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)
- 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"
- Start the GSS daemon(s):
15a)If NFSv4 delegations are not needed
Enable and startrpc.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
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.