Mon, 14 Mar 2016

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

Posted at: 16:52 | category: /computers/python | Link

Sat, 15 Nov 2008

Remctl 2.13 Released

Russ Allbery has released version 2.13 of remctl, a "client/server protocol for running single commands on a remote host using Kerberos v5 authentication and returning the output". It's an incredibly useful piece of software, and I'm using it a lot at home and at work.

I'm especially happy because 2.13 includes with it my python client bindings, so you can make calls to a remctl server directly from python, without having to call the remctl client binary. It's the first real piece of software I've written that has been really released to a wider audiance, which makes me giddy in some respects.

My next project, when I get enough Round Tuits(TM) is to build a python server library, so that one could implement a remctl server directly in python.

Posted at: 00:56 | category: /computers/python | Link

Fri, 07 Mar 2008

Pyremctl 0.4

Obviously, a few updates have happened to pyremctl. Version 0.3 introduced the “complex” interface to remctl, which is useful mostly for sending commands to the remote server that involve null bytes, or want to send more than one command per connection. 0.4 fixed a couple lingering bugs in the “simple” interface — making sure I didn't free a null pointer if a malloc failed, and not calling DECREF on an object I don't need to.

The code can be found here.

Posted at: 20:24 | category: /computers/python | Link

Sat, 23 Feb 2008

Pyremctl 0.1

Today reenforced the rule that if I need to understand something really bizare, I need to go to the Ugly Mug and start drinking espresso.

For over two years I've wanted to write a python module for remctl (I remember working on this sitting out on the patio of Stomping Grounds, back in Ames). My initial attempt was using SWIG, which generated incredibly ugly code and required a small but annoying change to the remctl source. I abandoned that and decided I should try to write, from scratch, a Python module in C. This went nowhere quickly. It seems (to me, at least) that the documentation and examples on writing a Python module in C are a bit lacking.

Today, for some reason, it started to make sense. In a few hours I had a module that implements the "simple" remctl interface, and a wrapper module around that so I can do sanity checking and argument marshallling in Python, instead of having to do all that nonsense in C. The next step, well, the next step is to get more testing of it done. The next thing on the todo list, then, is to implement the "complex" remctl interface. This will be a little bit more difficult, for two reasons. The first reason, which I don't think will be all that hard, is that I'll have to pass around an opaque remctl struct from the C layer to Python and back. The second reason is that I will want to use the remctl_commandv, which uses iovecs, something I've never used before. That also doesn't look too terribly hard, just something new to try.

You can find the code here.

Posted at: 20:17 | category: /computers/python | Link