python + kerberos + apache GSSAPI Example

July 6th, 2009

I’m writing a kerberos enabled tool at work. The primary interface is the web ui which we will forward our kerberos tickets to apache and use gssapi to authenticate. The secondary interface is a cli that we use to push data into the server. In interest of kinit letting us login though the web ui or the cli without having to type our password again I wanted the cli to also be able to pass the nessesary headers to apache for a password-less authentication. I’m not the most experienced programmer at kerb implementations so I figured I’d just figure it out and learn how to do it. I found there was a distinct lack of tutorials on how to implement a kerberos client. So here’s my experience.

Pre-established kerberos infrastructure would include you being able to kinit and have firefox login to a kerberos enabled website using your ticket. If you have a valid service principal and you have a valid ticket make sure that firefox knows the domain is trusted. Visit about:config and set network.negotiate-auth.trusted-uris to the trusted domain you’re logging into. Don’t use a widecard. So use example.com, not *.example.com. For example sake I’ll use HTTP/myhost.example.com and myuser@EXAMPLE.COM as my principals.

From here I would recommend using python-kerberos. I was browsing the code of another kerberos enabled cli app today. It implemented krbV and I think the server side also did. I also think this was a custom implementation that did not match gssapi’s implementation. From here the code is quite simple using python-kerberos, here’s a quick little example using httplib.

import kerberos
import httplib

# setup kerb
_ignore, ctx = authGSSClientInit(‘HTTP@myhost.example.com’, gssflags=GSS_C_DELEG_FLAG|GSS_C_MUTUAL_FLAG|GSS_C_SEQUENCE_FLAG)
_ignore = authGSSClientStep(ctx, ”)
tgt = authGSSClientResponse(ctx)

# setup http connection
servername, port = (‘myhost.exmple.com’, 443)
h = httplib.HTTPSConnection(servername, port)
h.connect()

# Setup Headers
http_conn.putrequest(“GET”, “/XMLRPC/”)
if tgt:
h.putheader(‘Authorization’, ‘Negotiate %s’ % tgt)
h.endheaders()

# Make http call
resp = http_conn.getresponse()
if resp.status != 200:
print “Error: %s” % str(resp.status)
return None

#Check for kerb header
krb_reply = resp.getheader(‘WWW-Authenticate’)
if not krb_reply:
print “Server did not send kerberos reply”
return None

# print html contents
print resp.read()

There’s all kinds of validation and such missing here. This just worked so I figured I post it for reference. The _ignore variables get populated with a 1 or a 0. You can read more about those in the python-kerberos docs. There is another example in the python-kerberos package that is more in depth on using these properly and validating other things. I think my biggest problem ended up being the choice of syntax and flags to pass to authGSSClientInit. My next issue is that I’d like to pump this through xmlrpclib instead of httplib. Though, I think that there are some better examples out there on how to add the header to xmlrpclib. Hope this simple snip helps someone with getting a proof of concept runnning.

Leave a Reply

You must be logged in to post a comment.