[Network Authentication]: OS X Kerberos Authentication and LDAP Authorization

I’ve also enabled Kerberos authentication and LDAP authorization on my OSX machine in addition to Linux machines. OSX supports Kerberos out of the box and deploys it for authentication against an OSX server. Also, the native OpenDirectory implementation is OpenLDAP, so we should be able to talk with our LDAP directory. Additionally, we’ve generated the directory entries with the records that we’ll need for OSX authorization, we just need to enable it.

Since support for Kerberos is already enabled in OSX, according to Apple we’ll just need to add the configuration file at /etc/krb5.conf. Again, like for Linux, the configuration file is basically the same file that we used on the server. Here is the file again

[libdefaults]
	default_realm = EXAMPLE.COM

[realms]
	EXAMPLE.COM = {
		kdc = kdc1.internal.example.com:88
		admin_server = kdc1.internal.example.com:749
		default_domain = example.com
	}

[domain_realm]
	example.com = EXAMPLE.COM
	.example.com = EXAMPLE.COM

The documentation from Apple does state that the PAM profile will need to be updated if there is not an appropriate entry for the AuthenticationAuthority record in the directory. We’ve created an appropriate one that points to Kerberos as the authentication method, so we won’t have to add the default_principal option to the pam_krb5 PAM module. But, it’s something to keep in mind if only the standard RFC2307 mapping is used in the LDAP directory because it does not have an AuthenticationAuthority record that maps into the directory.

Once we’ve added the /etc/krb5.conf Kerberos configuration file, we should be able to request a ticket from the KDC.

$ kinit user1
user1@EXAMPLE.COM's Password: 
$ klist
Credentials cache: API:501:5
        Principal: admin@EXAMPLE.COM

  Issued                Expires               Principal
Sep 13 22:20:11 2015  Sep 14 08:20:06 2015  krbtgt/EXAMPLE.COM@EXAMPLE.COM

Now that kerberos is configured, we can continue on to setup the LDAP directory client. This is done through the Directory Utility.

  1. Go to System Preferences -> Users & Groups -> Login Options
  2. Click the padlock to make changes if it’s locked
  3. Select Join or Edit at the bottom to the right of “Network Account Server
  4. Select Open Directory Utility to open Directory Utility
  5. Click the padlock to make changes if it’s locked
  6. Double click on “LDAPv3” in the list to bring up the list of LDAPv3 servers
  7. Select New

Once here we can start to enter the information for our LDAP server. You’ll need to provide the LDAP hostname. Our LDAP server is configured to require SSL connections, so the checkbox “Encrypt using SSL” needs to be checked. Also, we’ll be using this for authentication, so the checkbox “Use for authentication” is also checked. The last checkbox relates to using the directory for contacts, which we’ll address later. Select “Manual“.
NOTE: if you are using an alias to get at your LDAP server like I am, you’ll need to provide the actual A record name of the machine from the DNS records. This means, the hostname of the machine, and not the CNAME alias like “ldapalias.internal.example.com“. When OSX attempts to bind to the server through GSSAPI it will try to request a ticket using the name that is entered in the box, but it resolves the host to connect from the DNS server. The two names will not match and the ticket request will fail.
This adds an entry into the table. Highlight the entry and select “Edit” to bring up the next dialog box.

    LDAP configuration paramaters

  • Connection:
    The “Configuration Name” is just a logical name. Most of the defaults should work just file. The main thing on this page is that the connections is encrypted using SSL, and that it connects on port 636 (which is the standard port associated with ldaps:///).
  • Search & Mappings:
    This part is where the configuration really lies. To enable network accounts from LDAP, we need to have Group and User type of records. Select “Custom“, or “RFC2307“. Selecting “Custom” will clear all of the records and mappings. Selecting “RFC2308“, will start with just the RFC2307 mappings, which is what we are basing our mappings on. You add native records on the left pane, and the LDAP attributes on the right. Here is the mapping that we use:
    Groups:

    • Map to “all” items in list: “posixGroup“,”apple-group
    • Search Base is first level only of “ou=groups,dc=example,dc=com” — The OU that the entries that we added sit under.
      • Mapping:

      • Comment -> description
      • CreationTimestamp -> createTimestamp
      • GroupMembership -> memberUid
      • Member -> memberUid
      • ModificationTimestamp -> modifyTimestamp
      • NestedGroups -> apple-group-nestedgroup
      • PrimaryGroupID -> gidNumber
      • RecordName -> cn

    Users:

    • Map to “all” items in list: “posixAccount“,”posixShadow“,”inetOrgPerson“,”apple-user
    • Search Base is first level only of “ou=users,dc=example,dc=com” — The OU that the entries that we added sit under.
      • Mapping:

      • AuthenticationAuthority -> authAthority
      • Change -> shadowLastChange
      • Comment -> description
      • CreationTimestamp -> createTimestamp
      • Expire -> shadowExpire
      • FirstName -> givenName
      • GeneratedUID -> uidNumber
      • HomeDirectory -> apple-user-homeurl
      • LastName -> sn
      • ModificationTimestamp -> modifyTimestamp
      • NFSHomeDirectory -> homeDirectory
      • Password -> userPassword
      • PrimaryGroupID -> gidNumber
      • RealName -> cn
      • RecordName -> uid
      • UniqueID -> uidNumber
      • UserShell -> loginShell
  • Security
    The checkboxes on this page are all cleared

Once these are entered, or loaded as the RFC2307 mapping and augmented, select “OK” to return to the server list, and select “OK” again to save the server list.

We can test the connection to the LDAP server by requesting the account information:

$ id user1
uid=20000(user1) gid=20000(group1) groups=20000(group1),401(com.apple.access_screensharing),12(everyone),33(_appstore),62(netaccounts),79(_appserverusr),80(admin),81(_appserveradm),98(_lpadmin),100(_lpoperator),204(_developer)

Once the connection returns correct information, we still need to configure GSSAPI to connect to the LDAP server, which OS X uses to bind. (Or more properly, it attempts to bind with GSSAPI, and if it fails will attempt to bind using the CRAM-MD5 SASL mechanism.) This needs to be enabled on the server side either through the configuration LDIF file, or added through ldapmodify to the cn=config DN as a global option.

dn: cn=config
objectClass: olcGlobal
cn: config
#

#
# SASL options
# Define the SASL realm and host
olcSaslHost: kdc1.internal.example.com
olcSaslRealm: EXAMPLE.COM
# Setup the mappings from SASL authorization to user entries
olcSaslSecProps: noanonymous,noplain,minssf=56
olcAuthzRegexp:
  uid=admin,cn=[^,]*,cn=auth
  cn=admin,dc=example,dc=com
olcAuthzRegexp:
  uid=([^,]*),cn=[^,]*,cn=auth
  uid=$1,ou=users,dc=example,dc=com

We’ve added the SASL mechanism host to be the Kerberos KDC, and the Kerberos realm as our SASL realm. The olcAuthzRegexp will need to map to a correct users DN, which we setup with the olcAuthzRegexp mapping. It maps the SASL name that comes to a user DN. See the LDAP manual for more information on the mapping, and using SASL in general. After the LDAP server is updated GSSAPI should be enabled and work. Try with:

ldapsearch -Y GSSAPI -ZZ -x -h ldap.internal.example.com -b "ou=groups,dc=example,dc=com" dn

The command should return the DN of the group in the directory. If not, you will want to check the KDC log file (in our case /var/log/krb5/krb5kdc.log like we set in our server /etc/krb5.conf configuration file) that the proper tickets are getting requested and issued. There should be a service ticket for the LDAP host called ldap/hostname.internal.example.com that is issued. If an LDAP service principal does not exist, then one will need to be added to the database and a keytab generated. Note: The principal needs to have the actual hostname, not an alias.

kadmin> addprinc -randkey ldap/hostnameinternal.example.com
kadmin> ktadd -k /usr/local/etc/openldap/openldap.keytab ldap/hostname.internal.example.com

sudo chown openldap:openldap /usr/local/etc/openldap/openldap.keytab
sudo chmod u=rw,g=r,o= /usr/local/etc/openldap/openldap.keytab

After configuring kerberos, the connection to the LDAP server, and the records, we should be able to open a session as a network user:

$ su user1
Password:
[shannon:/Users/admin] user1% ls
Desktop		Documents	Downloads	Library		Movies		Music		Pictures	Public		output
[shannon:/Users/admin] user1% id
uid=20000(user1) gid=20000(group1) groups=20000(group1),401(com.apple.access_screensharing),12(everyone),33(_appstore),62(netaccounts),79(_appserverusr),80(admin),81(_appserveradm),98(_lpadmin),100(_lpoperator),204(_developer)
$ klist
Credentials cache: API:501:5
        Principal: user1@EXAMPLE.COM

  Issued                Expires               Principal
Sep 13 22:20:11 2015  Sep 14 08:20:06 2015  krbtgt/EXAMPLE.COM@EXAMPLE.COM
Advertisements

2 thoughts on “[Network Authentication]: OS X Kerberos Authentication and LDAP Authorization

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s