Thursday, May 10, 2012

HOWTO : OpenLDAP NFS NetGroup Repository for AutoFS

We continue our OpenLDAP 2.4 series with goal number 7. Recall that our goals are :
  1. Install OpenLDAP 2.4.
  2. Configure Transport Layer Security (TLS).
  3. Manage users and groups in OpenLDAP.
  4. Configure pam_ldap to authenticate users via OpenLDAP.
  5. Use OpenLDAP as sudo's configuration repository.
  6. Use OpenLDAP as automount map repository for autofs.
  7. Use OpenLDAP as NFS netgroup repository again for autofs.
  8. Use OpenLDAP as the Kerberos principal repository.
  9. Setup OpenLDAP backup and recovery.
  10. Setup OpenLDAP replication.
In this document, we will learn how to setup our OpenLDAP 2.4 server as a repository of NFS netgroup configuration. Then we will configure an NFS client to see if our netgroup configuration actually works. A netgroup is a set of (host, user, domain) tuples that are to be given similar network access.

Server Configuration


If we followed this OpenLDAP series, we know that the Network Information Service (NIS) schema was installed in the very first blog post. But let's double check just for fun.

sudo ldapsearch -LLLY EXTERNAL -H ldapi:/// -b cn=schema,cn=config dn | grep nis
dn: cn={10}nis,cn=schema,cn=config

Indeed we do have the NIS schema. But does it contain the required attributes for our netgroup purposes? It should, but again, let's take a look.

sudo ldapsearch -LLLY EXTERNAL -H ldapi:/// -b cn={10}nis,cn=schema,cn=config | grep NAME | cut -d' ' -f5 | grep -i netgroup

'memberNisNetgroup'
'nisNetgroup'
'nisNetgroupTriple'

Ok good, we have what it takes. But we don't have anything configured yet to leverage those attributes. So let's create another LDIF file which will create a container for our netgroup configs along with a few example netgroups.


NOTE : be carefull with the use of Fully Qualified Domain Names in the netgroup tuples!

If you do it wrong, it won't work. For example, don't use « nisNetgroupTriple: (bob.company.com,,company.com) » but rather « nisNetgroupTriple: (bob.company.com,,) ». Another way to write the netgroup tuple is to use this version which also works : « nisNetgroupTriple: (bob,,company.com) » Choose a syntax and stick to it.

Add those new entries into the OpenLDAP server.

sudo ldapmodify -aH ldapi:/// -f ~/ldap/netgroup.ldif

Change the netgroup: values in /etc/nsswitch.conf to enable only LDAP queries.

sudo vi /etc/nsswitch.conf
netgroup:   ldap

Test to see what our new LDAP netgroup configuration returns?

getent netgroup
Enumeration not supported on netgroup

Ah that's interesting. Since netgroups are basically a security measure, it won't allow you to list all the netgroups configured. That means you have to list them explicitly.

getent netgroup oracle
oracle                (oracle, , company.com)

getent netgroup dev
dev                   (bob, , company.com)

Great, it seems to work. We can confirm that from the slapd.log file that shows our getent netgroup dev query for example :

slapd[10783]: conn=1109 op=2 SRCH base="dc=company,dc=com" scope=2 deref=0 filter="(&(objectClass=nisNetgroup)(cn=dev))"
slapd[10783]: conn=1109 op=2 SRCH attr=cn nisNetgroupTriple memberNisNetgroup
slapd[10783]: conn=1109 op=2 SEARCH RESULT tag=101 err=0 nentries=1 text=

Next configure the NFS /etc/exports file on the server. This is where we specify which file systems are exported and to whom?

sudo vi /etc/exports

Notice that we specified our new bob netgroup with a « @ » sign. The client machine bob is part of this netgroup. So it should be able to mount the directory. But before we try the client, we need to tell our nfs daemons that we changed the exports file.

sudo /etc/init.d/nfs reload

We can see that the changes have been applied.

showmount -e
Export list for alice.company.com:
/export/home  @bob

We can now test our new netgroups on the client machine bob.

Client Configuration


Connect to the client machine. Make sure to use a user that does NOT have it's home on /nfs/home!

ssh bob.company.com

In the previous post, we've already have this client as an NFS client of server alice.company.com via autofs. This time we are going to check if we can automount the /nfs/home directory. The first thing we need to do is to change /etc/nsswitch.conf to enable LDAP queries for netgroups.

sudo vi /etc/nsswitch.conf
netgroup: ldap

Check to see if we can query the netgroup database in LDAP?

getent netgroup dev
dev                   (bob, , company.com)

Good! Now make sure that /nfs/home is not currently mounted. IMPORTANT : don't do this if your current user has it's home on /nfs/home otherwise this command will hang. We need to use a user which does not use /nfs/home as it's home.

sudo umount /nfs/home

Ok, let's check if the server advertises the new netgroup?

showmount -e alice.company.com
Export list for alice.company.com:
/export/home  @bob

It does. So we should be ok to mount it.

cd /nfs/home
df -h .
alice.company.com:/export/home
                      770G   17G  714G   3% /nfs/home

Excellent! It worked!

But will it work if we don't have access? To make sure, we must first unmount the direectory and go back to the server and change the /etc/exports file to use another netgroup.

cd /tmp
sudo umount /nfs/home
exit
ssh alice.company.com
sudo vi /etc/exports

Notice that we changed the @bob for the @oracle netgroup in which the client machine bob is not part of. That will enable us to test if the netgroups work. If they do, then bob should not be able to mount the /nfs/home directory anymore. But we first need to tell our NFS daemons about the change.

sudo /etc/init.d/nfs reload
showmount -e
Export list for alice.company.com:
/export/home  @oracle

Let's see if this prevents bob from mounting the directory? Again, make sure to use a user that does NOT have it's home on /nfs/home!

ssh bob.company.com
cd /nfs/home
-bash: cd: /nfs/home: No such file or directory

Good! That means our netgroups are working! We have achieved goal number 7 :)
  1. Install OpenLDAP 2.4.
  2. Configure Transport Layer Security (TLS).
  3. Manage users and groups in OpenLDAP.
  4. Configure pam_ldap to authenticate users via OpenLDAP.
  5. Use OpenLDAP as sudo's configuration repository.
  6. Use OpenLDAP as automount map repository for autofs.
  7. Use OpenLDAP as NFS netgroup repository again for autofs.
  8. Use OpenLDAP as the Kerberos principal repository.
  9. Setup OpenLDAP backup and recovery.
  10. Setup OpenLDAP replication.
The next blog post will describe how to setup a Kerberos realm using OpenLDAP as the Kerberos principals repository. That's going to be quite a lot of fun. Because once we have a Kerberos realm, we can start using it to secure user authentication via ssh, secure LDAP connections via SASL GSSAPI, secure our NFS automount requests and mount request. Plus a whole lot more!

Stay tuned!

DA+

Update!

I've just tried to add a new nisNetgroupTriple: attribute in the cn=dev,ou=netgroup... netgroup and to my surprise, it generated an error. If I tried via Apache Directory Studio, an error pop-up appeared saying « additional info: modify/add: nisNetgroupTriple: no equality matching rule ». Humm, strange? So I then tried via a simple LDIF file and that got me the following error : « Error: Bad parameter to an ldap routine (-9) ».

Several Google searches later, I realized this was not a bug, but that's how the nis schema is defined. The standard way to change the netgroup is then to delete the entire cn=dev,ou=netgroup object and recreate it with all the desired nisNetgroupTriple: tuples. While this works, it's clearly not easy to maintain, let alone to work with.

Another way to allow us to add/remove tuples is to modify the schema. Here's a diff(1) of the original schema and the modified one with two lines of context (-C 1) to understand where the change takes place.

sudo diff -C 1 cn\=\{10\}nis.ldif.original cn\=\{10\}nis.ldif.modified 
*** cn={10}nis.ldif.original 2012-05-17 17:26:18.479629651 -0400
--- cn={10}nis.ldif.modified 2012-05-17 17:28:46.289627851 -0400
***************
*** 33,35 ****
  olcAttributeTypes: {12}( 1.3.6.1.1.1.1.14 NAME 'nisNetgroupTriple' DESC 'Netgr
!  oup triple' SYNTAX 1.3.6.1.1.1.0.0 )
  olcAttributeTypes: {13}( 1.3.6.1.1.1.1.15 NAME 'ipServicePort' EQUALITY intege
--- 33,35 ----
  olcAttributeTypes: {12}( 1.3.6.1.1.1.1.14 NAME 'nisNetgroupTriple' DESC 'Netgr
!  oup triple' EQUALITY caseExactIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) 
  olcAttributeTypes: {13}( 1.3.6.1.1.1.1.15 NAME 'ipServicePort' EQUALITY intege

As we can see, this is a trivial modification to the nisNetgroupTriple object in the nis schema.

But in the end, the fastest way to update the netgroup is still via an LDIF file such as this one.

Note to self : write a script to update the netgroups...

HTH,

DA+

8 comments:

  1. I can't seem to get it to mount setting the nisNetgroupTriple to a host (client,,company.com) or (client.company.com,,). I can get it to work fine if I set the user (,test.user,) or (,test.user,company.com). Am I missing something?

    ReplyDelete
    Replies
    1. Hello jbnewyorker,

      I prefer the (client.company.com,,) form, but that's just me as I've tried both versions and it works.

      I'm in vacation right now and so away from my setup. Ping me next week when I'll be back if I don't answer this question with more detail.

      DA+

      Delete
  2. Hi!
    This is my netgroup.ldif file:

    dn: ou=netgroup,ou=services,dc=suri,dc=com
    ou: netgroup
    objectClass: top
    objectClass: organizationalUnit
    description: nfs netgroup

    dn: cn=oracle,ou=netgroup,ou=services,dc=suri,dc=com
    objectClass: top
    objectClass: nisNetgroup
    cn: oracle
    nisNetgroupTriple: (oracle.suri.com,,)
    description: all oracle machines

    dn: cn=dev,ou=netgroup,ou=services,dc=suri,dc=com
    objectClass: top
    objectClass: nisNetgroup
    cn: dev
    nisNetgroupTriple: (bob.suri.com,,)
    description: All development services

    After adding these when I try to use "getent netgroup dev" command it showing me nathing.
    What is wrong with it.

    Thanks!!!

    ReplyDelete
    Replies
    1. Hello,

      Are you trying this from the client or the server?
      Is your netgroup properly configured in /etc/nsswitch.conf to fetch the info from ldap?
      What is the slapd.log generated when you run getent netgroup dev?

      DA+

      Delete
  3. Hello David,

    Can the nisNetgroupTriple to be filled by an IP address as following example?

    dn: cn=users,ou=netgroup,ou=services,dc=company,dc=com
    objectClass: top
    objectClass: nisNetgroup
    cn: users
    nisNetgroupTriple: (192.168.1.101,,)
    nisNetgroupTriple: (192.168.1.102,,)
    nisNetgroupTriple: (192.168.1.103,,)
    description: All Oracle machines

    And define the NFS exports to allow only machines with 192.168.1.101, 192.168.1.102, 192.168.1.103 to connect to the NFS server?

    /exports/mnt @users(rw,sync)






    ReplyDelete
    Replies
    1. Hello Mike,

      I must admit I've never tried with IP addresses. I prefer working with FQDNs. A quick search on this returned that it doesn't seem to work. I guess you'll have to try it out. If you do, then please let me know the outcome.

      Thanks,

      DA+

      Delete
  4. After dozens of web-searches you've given me the workaround to entering a new nisNetgroupTriple to an LDAP server I inherited - THANK YOU so much.

    However I'd like to fix it, i.e. modify the attribute schema, because we add users very frequently, but I can't work out the ldif format for removing the old SYNTAX and adding the new SYNTAX & EQUALITY.

    Any chance you could provide an example ldif for modifying the schema as you did new/replacement netgroup?

    Thanks again Dave

    Brigitte

    ReplyDelete
    Replies
    1. Hello Brigitte,

      Glad I could help :)

      The only thing I really don't like with this nisNetgroupTriple thing is that I can't just update it. The way the schema is built it forces us to completely erase the entire subdirectory and recreate it from scratch. If I was in your shoes, I'd simply write a script which would poll the OpenLDAP server, fetch the entire nisNetgroupTriple entries, delete them and then generate a new LDIF file which it would subsequently push into the OpenLDAP's DIT.

      But since I almost never had to do so, I didn't invest time and resources to write that script. I can't believe I'm the only one out there. Good luck in your endeavor!

      HTH,

      DA+

      Delete