FreeIPA and NFSv4

From Linux NFS

Jump to: navigation, search

This is a WIP by dros@netapp.com - please let me finish before changing/commenting).

This document describes using NFSv4 with FreeIPA.

Historically, setting up a secure NFSv4 export (or even a client) was challenging, requiring the setup of a Kerberos realm and possibly an LDAP server. FreeIPA provides a packaged service of both Kerberos 5 and LDAP with the purpose of making this process much less painful.

These instructions are for Fedora 15. Other distros will require similar setup - the key differences will be a package installation tool other than yum(1), and a different config file layout.


Contents

Disclaimer about the testing environment

For this example I've used a private network (192.168.56.0/24) with a fake DNS realm (example.fake) and there is one server (server.example.fake) and one client (client1.example.fake).

Setup with routable IP addresses and a real DNS realm should be straightforward.

In this example, the DNS server is running on the same machine as the NFSv4 export and the IPA server (server.example.fake). Of course, these could all be different machines.

I have not tried setting up FreeIPA without DNS, or using it's own DNS server.

Notes

I'm using VMs on a private NAT'd network, so I just turned off the firewall on the server! You probably shouldn't do that! You'll need to allow traffic on:

  • port 53 for named
  • port 88 for kerberos
  • port 389 for ldap
  • XXX MORE!! (ipa web interface, etc?)

For the following example, I'm logged in as root on both the client and server. Either login as root or prepend "sudo " to each command.

Set up DNS realm

Again, you might not need to do this. If you're just setting up a client of FreeIPA, you can skip this section entirely. If you already have a name server running for your domain, you can just merge the few key items in this section:

  • full DNS names for server(s) and client(s)
  • reverse mapping for said hosts
  • the service entries for FreeIPA auto discovery

Create the DNS realm on the server

Install named(1) on the server

 [root@server ~]# sudo yum install bind
 

Configure the DNS zone

Create the file "/var/named/example.fake.zone":

$TTL 3D
@       IN      SOA     ns1.example.fake. hostmaster.example.fake. (
                       201107111       ; serial#
                       3600            ; refresh, seconds
                       3600            ; retry, seconds
                       3600            ; expire, seconds
                       3600 )          ; minimum, seconds

                NS      ns1             ; Inet Address of nameserver
example.fake.   MX      10 mail         ; Primary Mail Exchanger

ns1             A       192.168.56.20
server          A       192.168.56.20

client1         A       192.168.56.40

ipa             CNAME   build
mail            CNAME   build

; DNS auto discovery of services
_ldap._tcp      SRV 10 10 389 server.example.fake.
_kerberos._udp  SRV 10 10 88 server.example.fake.
_kerberos._tcp  SRV 10 10 88 server.example.fake.

Configure the reverse mapping

Create the file "/var/named/192-168-56.zone":

$TTL 2d  ; 172800 seconds
$ORIGIN 56.168.192.IN-ADDR.ARPA.
@       IN        SOA        ns1.example.fake.  hostmaster.example.fake. (
                            201107111          ; serial number
                            8H                 ; refresh, seconds
                            2H                 ; retry, seconds
                            4W                 ; expire, seconds
                            1D )               ; minimum, seconds

                IN      NS      ns1.example.fake.
20              IN      PTR     server.example.fake.
40              IN      PTR     client1.example.fake.


Modify named(1) config

Add these sections to file "/etc/named.conf":

zone "example.fake" IN {
	type master;
	file "example.fake.zone";
};

zone "56.168.192.in-addr.arpa" IN {
	type master;
	file "192-168-56.zone";
};

There are a few other things that I needed to configure in my test setup. You probably don't want to turn off dnssec in real world setups!

In the "options" section:

  • change the "listen-on" option to include the server's external address ""{ localhost; 192.168.56.20; }"
  • change "allow-query" option to "{ localhost; 192.168.56.0/24 }"
  • change "dnssec-enable" option to "no"
  • change "dnssec-validation" option to "no"

The resulting /etc/named.conf:

//
// named.conf
//
// Provided by Red Hat bind package to configure the ISC BIND named(8) DNS
// server as a caching only nameserver (as a localhost DNS resolver only).
//
// See /usr/share/doc/bind*/sample/ for example named configuration files.
//

options {
	listen-on port 53 { 127.0.0.1; 192.168.56.20; };
	listen-on-v6 port 53 { ::1; };
	directory 	"/var/named";
	dump-file 	"/var/named/data/cache_dump.db";
        statistics-file "/var/named/data/named_stats.txt";
        memstatistics-file "/var/named/data/named_mem_stats.txt";
	allow-query     { localhost; 192.168.56.0/24; };
	recursion yes;

	dnssec-enable yes;
	dnssec-validation no;
	dnssec-lookaside auto;

	/* Path to ISC DLV key */
	bindkeys-file "/etc/named.iscdlv.key";

	managed-keys-directory "/var/named/dynamic";
};

logging {
        channel default_debug {
                file "data/named.run";
                severity dynamic;
        };
};

zone "." IN {
	type hint;
	file "named.ca";
};

zone "example.fake" IN {
        type master;
        file "example.fake.zone";
};

zone "56.168.192.in-addr.arpa" IN {
        type master;
        file "192-168-56.zone";
};

include "/etc/named.rfc1912.zones";
include "/etc/named.root.key";

Restart named(1)

[root@server ~]# service named restart
Restarting named (via systemctl):                          [  OK  ]

Configure the client(s) and server to use the local DNS server

The server and all clients should use this name server (with this testing environment). With a real DNS server, clients shouldn't require this configuration.

Edit file "/etc/sysconfig/network-scripts/ifcfg-eth0" (or whatever is appropriate) and change the DNS1 line to:

DNS1=192.168.56.20

Restart the network service to pick up the change.

[root@server ~]# service network restart
Restarting network (via systemctl):                        [  OK  ]

And verify that it worked:

[root@server ~]# cat /etc/resolv.conf 
# Generated by NetworkManager
search example.fake
nameserver 192.168.56.20
[root@server ~]# nslookup server.example.fake
Server:		192.168.56.20
Address:	192.168.56.20#53

Name:	server.example.fake
Address: 192.168.56.20


Install and configure the FreeIPA server

Install and configure the FreeIPA software on the server (server.example.fake).

Install the FreeIPA server and admintools package

This step fetches and installs FreeIPA and it's dependencies. It will install around 100 packages, depending on what you already have installed.

[root@server ~]# yum install freeipa-server freeipa-admintools

Configure FreeIPA server

Run the ipa-server-install(1) program. This takes a while. All of the default answers should work if DNS hostnames and services are set up correctly and the full domain name is returned by hostname(1).

[root@server ~]# ipa-server-install 

The log file for this installation can be found in /var/log/ipaserver-install.log
==============================================================================
This program will set up the FreeIPA Server.

This includes:
  * Configure the Network Time Daemon (ntpd)
  * Create and configure an instance of Directory Server
  * Create and configure a Kerberos Key Distribution Center (KDC)
  * Configure Apache (httpd)

To accept the default shown in brackets, press the Enter key.

Enter the fully qualified domain name of the computer
on which you're setting up server software. Using the form
<hostname>.<domainname>
Example: master.example.com.


Server host name [server.example.fake]: 

The domain name has been calculated based on the host name.

Please confirm the domain name [example.fake]: 

The IPA Master Server will be configured with
Hostname:    server.example.fake
IP address:  192.168.56.20
Domain name: example.fake

The kerberos protocol requires a Realm name to be defined.
This is typically the domain name converted to uppercase.

Please provide a realm name [EXAMPLE.FAKE]: 
Certain directory server operations require an administrative user.
This user is referred to as the Directory Manager and has full access
to the Directory for system management tasks and will be added to the
instance of directory server created for IPA.
The password must be at least 8 characters long.

Directory Manager password: 
Password (confirm): 

The IPA server requires an administrative user, named 'admin'.
This user is a regular system account used for IPA server administration.

IPA admin password: 
Password (confirm): 


The following operations may take some minutes to complete.
Please wait until the prompt is returned.

Configuring ntpd
  [1/4]: stopping ntpd
  [2/4]: writing configuration
  [3/4]: configuring ntpd to start on boot
  [4/4]: starting ntpd
done configuring ntpd.
Configuring directory server for the CA: Estimated time 30 seconds
  [1/3]: creating directory server user
  [2/3]: creating directory server instance
  [3/3]: restarting directory server
done configuring pkids.
Configuring certificate server: Estimated time 6 minutes
  [1/17]: creating certificate server user
  [2/17]: creating pki-ca instance
  [3/17]: restarting certificate server
  [4/17]: configuring certificate server instance
  [5/17]: restarting certificate server
  [6/17]: creating CA agent PKCS#12 file in /root
  [7/17]: creating RA agent certificate database
  [8/17]: importing CA chain to RA certificate database
  [9/17]: restarting certificate server
  [10/17]: requesting RA certificate from CA
  [11/17]: issuing RA agent certificate
  [12/17]: adding RA agent as a trusted user
  [13/17]: fixing RA database permissions
  [14/17]: setting up signing cert profile
  [15/17]: set up CRL publishing
  [16/17]: configuring certificate server to start on boot
  [17/17]: restarting certificate server
done configuring pki-cad.
Configuring directory server: Estimated time 1 minute
  [1/32]: creating directory server user
  [2/32]: creating directory server instance
  [3/32]: adding default schema
  [4/32]: enabling memberof plugin
  [5/32]: enabling referential integrity plugin
  [6/32]: enabling winsync plugin
  [7/32]: configuring replication version plugin
  [8/32]: enabling IPA enrollment plugin
  [9/32]: enabling ldapi
  [10/32]: configuring uniqueness plugin
  [11/32]: configuring uuid plugin
  [12/32]: configuring modrdn plugin
  [13/32]: enabling entryUSN plugin
  [14/32]: configuring lockout plugin
  [15/32]: creating indices
  [16/32]: configuring ssl for ds instance
  [17/32]: configuring certmap.conf
  [18/32]: configure autobind for root
  [19/32]: restarting directory server
  [20/32]: adding default layout
  [21/32]: adding delegation layout
  [22/32]: adding replication acis
  [23/32]: configuring user private groups
  [24/32]: configuring netgroups from hostgroups
  [25/32]: creating default Sudo bind user
  [26/32]: creating default HBAC rule allow_all
  [27/32]: initializing group membership
  [28/32]: adding master entry
  [29/32]: configuring Posix uid/gid generation
  [30/32]: enabling compatibility plugin
  [31/32]: tuning directory server
  [32/32]: configuring directory to start on boot
done configuring dirsrv.
Configuring Kerberos KDC: Estimated time 30 seconds
  [1/14]: setting KDC account password
  [2/14]: adding sasl mappings to the directory
  [3/14]: adding kerberos entries to the DS
  [4/14]: adding default ACIs
  [5/14]: configuring KDC
  [6/14]: adding default keytypes
  [7/14]: adding default password policy
  [8/14]: creating a keytab for the directory
  [9/14]: creating a keytab for the machine
  [10/14]: exporting the kadmin keytab
  [11/14]: adding the password extension to the directory
  [12/14]: adding the kerberos master key to the directory
  [13/14]: starting the KDC
  [14/14]: configuring KDC to start on boot
done configuring krb5kdc.
Configuring ipa_kpasswd
  [1/2]: starting ipa_kpasswd 
  [2/2]: configuring ipa_kpasswd to start on boot
done configuring ipa_kpasswd.
Configuring the web interface: Estimated time 1 minute
  [1/12]: disabling mod_ssl in httpd
  [2/12]: setting mod_nss port to 443
  [3/12]: setting mod_nss password file
  [4/12]: adding URL rewriting rules
  [5/12]: configuring httpd
  [6/12]: setting up ssl
  [7/12]: setting up browser autoconfig
  [8/12]: publish CA cert
  [9/12]: creating a keytab for httpd
  [10/12]: configuring SELinux for httpd
  [11/12]: restarting httpd
  [12/12]: configuring httpd to start on boot
done configuring httpd.
Setting the certificate subject base
restarting certificate server
Applying LDAP updates
Restarting the directory server
Restarting the KDC
Restarting the web server
Sample zone file for bind has been created in /tmp/sample.zone.I_fDwT.db
==============================================================================
Setup complete

Next steps:
	1. You must make sure these network ports are open:
		TCP Ports:
		  * 80, 443: HTTP/HTTPS
		  * 389, 636: LDAP/LDAPS
		  * 88, 464: kerberos
		UDP Ports:
		  * 88, 464: kerberos
		  * 123: ntp

	2. You can now obtain a kerberos ticket using the command: 'kinit admin'
	   This ticket will allow you to use the IPA tools (e.g., ipa user-add)
	   and the web user interface.

Be sure to back up the CA certificate stored in /root/cacert.p12
This file is required to create replicas. The password for this
file is the Directory Manager password

Install and configure FreeIPA client(s)

Install the freeipa-client package on each machine (besides the FreeIPA server) that want to participate in the FreeIPA domain.

Install the FreeIPA client package

This step fetches just the client-side software needed to connect to a FreeIPA server.

[root@client1 ~]# yum install freeipa-client
...


Configure the FreeIPA client package (OOPS!)

Again, if DNS is setup correctly and hostname(1) returns the full DNS name, the default answers should work.

You want to use "admin" (the administrator user you created when configuring the FreeIPA server) as the enrollment principal.

Oh no! Currently, Fedora 15 gives me this problem:

[root@client1 ~]# ipa-client-install 
Discovery was successful!
Hostname: client1.example.fake
Realm: EXAMPLE.FAKE
DNS Domain: example.fake
IPA Server: server.example.fake
BaseDN: dc=example,dc=fake


Continue to configure the system with these values? [no]: yes
Enrollment principal: admin
Password for admin@EXAMPLE.FAKE: 

Joining realm failed because of failing XML-RPC request.
  This error may be caused by incompatible server/client major versions.

This problem is easily worked around, but you may not need to - I'm sure this will be fixed soon.

Configure the FreeIPA client package (The Workaround)

The problem and workaround are described here: https://www.redhat.com/archives/freeipa-users/2011-July/msg00029.html

Get credentials and add the host to FreeIPA

Both of these commands should be run on the *server*.

First, get admin credentials. If you are configuring multiple clients, this only needs to be run the first time.

[root@server ~]# kinit admin
Password for admin@EXAMPLE.FAKE: 

Now that you have credentials, you can add the (client) host to FreeIPA.

[root@server ~]# ipa host-add client1.example.fake
---------------------------------
Added host "client1.example.fake"
---------------------------------
  Host name: client1.example.fake
  Principal name: host/client1.example.fake@EXAMPLE.FAKE
  Managed by: client1.example.fake

(Force) Configure FreeIPA client

Back on the client now. Run ipa-client-install again, but this time use the --force flag:

[root@client1 ~]# ipa-client-install --force
Discovery was successful!
Hostname: client1.example.fake
Realm: EXAMPLE.FAKE
DNS Domain: example.fake
IPA Server: server.example.fake
BaseDN: dc=example,dc=fake


Continue to configure the system with these values? [no]: yes
Enrollment principal: admin
Password for admin@EXAMPLE.FAKE: 

Joining realm failed because of failing XML-RPC request.
  This error may be caused by incompatible server/client major versions.
  Use ipa-getkeytab to obtain a host principal for this server.
Created /etc/ipa/default.conf
Configured /etc/sssd/sssd.conf
Configured /etc/krb5.conf for IPA realm EXAMPLE.FAKE
Failed to configure automatic startup of the NSCD daemon
SSSD enabled
nss_ldap is not able to use DNS discovery!
Changing configuration to use hardcoded server name: server.example.fake
Kerberos 5 enabled
NTP enabled
Client configuration complete.

Manually fetch the keytab entry for the client

Still on the client, the last step is to fetch the keytab entry that ipa-client-install(1) wasn't able to get.

To do this, you'll need to authenticate as admin again (but this time on the client):

[root@client1 ~]# kinit admin
Password for admin@EXAMPLE.FAKE: 

Now run ipa-getkeytab:

[root@client1 ~]# ipa-getkeytab -s server.example.fake -p host/client1.example.fake -k /etc/krb5.keytab
Keytab successfully retrieved and stored in: /etc/krb5.keytab

Now, FreeIPA should be setup on the client.

Add FreeIPA NFS service for each host

The next step is to setup kerberos principals for the NFS service on each host - the server and the client(s).

Add FreeIPA NFS service for server

[root@server ~]# ipa service-add nfs/server.example.fake
----------------------------------------------------
Added service "nfs/server.example.fake@EXAMPLE.FAKE"
----------------------------------------------------
  Principal: nfs/server.example.fake@EXAMPLE.FAKE
  Managed by: server.example.fake

Add FreeIPA NFS service for client(s)

[root@server ~]# ipa service-add nfs/client1.example.fake
-----------------------------------------------------
Added service "nfs/client1.example.fake@EXAMPLE.FAKE"
-----------------------------------------------------
  Principal: nfs/client1.example.fake@EXAMPLE.FAKE
  Managed by: client1.example.fake

Import FreeIPA NFS service tickets on the server

[root@server ~]# ipa-getkeytab -s server.example.fake -p nfs/server.example.fake -k /etc/krb5.keytab 
Keytab successfully retrieved and stored in: /etc/krb5.keytab

You can check to see what's in the keytab like this:

[root@server ~]# ktutil 
ktutil:  read_kt /etc/krb5.keytab 
ktutil:  list
slot KVNO Principal
---- ---- ---------------------------------------------------------------------
   1    2    host/server.example.fake@EXAMPLE.FAKE
   2    2    host/server.example.fake@EXAMPLE.FAKE
   3    2    host/server.example.fake@EXAMPLE.FAKE
   4    2    host/server.example.fake@EXAMPLE.FAKE
   5    2    host/server.example.fake@EXAMPLE.FAKE
   6    2    host/server.example.fake@EXAMPLE.FAKE
   7    1     nfs/server.example.fake@EXAMPLE.FAKE
   8    1     nfs/server.example.fake@EXAMPLE.FAKE
   9    1     nfs/server.example.fake@EXAMPLE.FAKE
  10    1     nfs/server.example.fake@EXAMPLE.FAKE
ktutil:  q

Import FreeIPA NFS service tickets on the client(s)

[root@client1 ~]# ipa-getkeytab -s server.example.fake -p nfs/client1.example.fake -k /etc/krb5.keytab
Keytab successfully retrieved and stored in: /etc/krb5.keytab

And here's what /etc/krb5.kettab has in it:

[root@client1 ~]# ktutil 
ktutil:  read_kt /etc/krb5.keytab 
ktutil:  list
slot KVNO Principal
---- ---- ---------------------------------------------------------------------
   1    1   host/client1.example.fake@EXAMPLE.FAKE
   2    1   host/client1.example.fake@EXAMPLE.FAKE
   3    1   host/client1.example.fake@EXAMPLE.FAKE
   4    1   host/client1.example.fake@EXAMPLE.FAKE
   5    1    nfs/client1.example.fake@EXAMPLE.FAKE
   6    1    nfs/client1.example.fake@EXAMPLE.FAKE
   7    1    nfs/client1.example.fake@EXAMPLE.FAKE
   8    1    nfs/client1.example.fake@EXAMPLE.FAKE
ktutil:  q

 ???

  - host/
  - nfs/
  - root/ (is this needed?)
- configure client/server with right tickets
  - klist -ea
      ...

Turn on "Secure NFS"

This turns on NFS secure mounts and enables rpc.gssd and rpc.svcgssd.

Edit these lines in file "/etc/sysconfig/nfs":

# Set to turn on Secure NFS mounts.
SECURE_NFS="yes"
# Optional arguments passed to rpc.gssd. See rpc.gssd(8)
RPCGSSDARGS="-vvv"
# Optional arguments passed to rpc.svcgssd. See rpc.svcgssd(8)
RPCSVCGSSDARGS="-vvv"

The -vvv flags are for better debugging output.

To pick up the changes, you must restart nfs services:

[root@client1 ~]# service nfs restart
Restarting nfs (via systemctl):                            [  OK  ]
[root@client1 ~]# service rpcgssd restart
Restarting rpcgssd (via systemctl):                        [  OK  ]
[root@client1 ~]# service rpcsvcgssd restart
Restarting rpcsvcgssd (via systemctl):                     [  OK  ]

This must be run on both clients (XXX ?) and servers.

Add full entry for the local host in /etc/hosts

rpc.gssd(1) (???) requires that the full dns name of the host be in /etc/hosts. The full DNS name must be the only entry on that line.

On the server:

[root@server ~]# cat /etc/hosts
127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6

192.168.56.20 server.example.fake

This must be done on the client(s) as well:

[root@client1 ~]# cat /etc/hosts
127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6

192.168.56.40 client1.example.fake


Set up /etc/exports on the server

Edit file "/etc/exports":

[root@server ~]# cat /etc/exports 
/export gss/krb5(rw,fsid=0,insecure,no_subtree_check,no_root_squash)
[root@server ~]# exportfs -av
exportfs: scandir /etc/exports.d: No such file or directory

exporting gss/krb5:/export

restart nfs service:

[root@server ~]# service nfs restart
Restarting nfs (via systemctl):                            [  OK  ]
- common debugging problems
  - named starts *after*
- clock skew
Personal tools