Python-ldap, gssapi, keytabs, authz and you

Documented here because this took me far too long to remember this.

For a project at work, I need to talk to our LDAP server and munge with some directory entries. The server (OpenLDAP), is configured to handle GSSAPI authentication which is good because I want to use the authzto rules that the gooey pile of kerberos/gssapi/sasl gives me.

I also want to use a keytab, because this is a long running process and I don't want to also have to have something like k5start running in the background. I vaguely remembered that the MIT gssapi libraries, which I'm using, allowed to you point at a keytab, but I couldn't for the life of me remember how. After a bit of digging, it's the KRB5_CLIENT_KTNAME environment variable --- if that's set, the gssapi library will use that for credentials, and will use the identity of the first entry in the keytab as the identity to authenticate as.

Authz setup is pretty simple: OpenLDAP is already set to convert uid=principal,cn=gssapi,cn=auth identites into LDAP directory entries (via authz-regexp rules). This maps the principal in the keytab to an identity like cn=example-app,ou=Applications,dc=example,dc=com; that entry has a authzto entity like: dn.regex:^uid=[^,]*,ou=People,dc=example,dc=com, and in the slapd.conf configuration we have authz-policy to set.

Now I can:

import os
import ldap

os.environ['KRB5_CLIENT_KTNAME'] = '/path/to/keytab'
ldap_conn = ldap.initialize('ldaps://ldap.example.com')
ldap_conn.sasl_non_interactive_bind_s('GSSAPI')
print ldap_conn.whoami_s()
    
and connect as the application identity, or:
...
ldap_conn.sasl_non_interactive_bind_s('GSSAPI',
    authz_id='dn:uid=sampleuser,ou=People,dc=example,dc=com')
...
    
to connect and assume the identity of sampleuser