November 22nd, 2012

python-pam 0.1.4

Pure Python interface to the Pluggable Authentication Modules system on Linux.

Setup
Features
Performance
Support
PriceFree

This is the first highly rated package on Python Diary to date, due to all it's appealing attributes. If your a Linux shop, and need a solution to enable authentication throughout your organization, more than likely your using PAM somewhere in there. Since PAM has so many backends and connects to NIS services, using this to authenticate your corporate applications makes complete sense. It may not enable SSO, but I personally think SSO is a tad insecure, since it doesn't protect against idiot employees who leave their workstations unlocked. The convenience of SSO has it's security drawbacks. I admit it's nice to be automatically signed into my intranet services at work.

If you know nothing about UNIX like systems, NIS is something like Active Directory, where it is a central server which stores users and their passwords. However, unlike Active Directory, NIS is not LDAP, and NIS only stores users and their specific information. However, it is possible to use NIS to distribute /etc/hosts files across an organization, or other files such as automounts for NFS. Remember, Linux unlike Windows prefers to be very modular, so unlike Windows, your not going to have a single application doing a dozen things. However, since PAM is very modular(plugable), it supports various methods of authentication, using LDAP and even authentication through Active Directory using the SMB/CIFS protocol. In the end, using PAM in Python on a Linux server which is connected to a Windows domain server, will provide your organization with an authentication system all users can relate to(transparency). The end-users can literally use their Windows domain username and password to authenticate against PAM, so using this Python package will bring utter transparency to your corporate userbase.

Using this package is super easy and almost failproof, just put the variables in the right place and your all set to go. Here's a simple example to show how easy this is:

import pam
from getpass import getuser, getpass
from random import choice

print "Please supply your credentials to receive an awesome quote..."
if pam.authenticate(getuser(), getpass()):
    print choice(open('/usr/share/games/fortunes/fortunes','r').read().split('%'))
else:
    print "The /var/log/auth.log file will be seen by an administration soon and you will be in trouble... That is your fortune."

The code above assumes you have the BSD Fortune program and it's associated fortune files installed on your machine. This example will provide the best fortunate regardless if the username/password combo is correct(also considering how lazy your local *NIX admin is too). Here's how you would create a Django authentication backend for PAM:

from django.contrib.auth.models import User
import pam

class PAMBackend(object):
    supports_inactive_user = False

    def authenticate(self, username=None, password=None):
        if pam.authenticate(username, password):
            try:
                user = User.objects.get(username=username)
            except User.DoesNotExist:
                # Create a new user. Note that we can set password
                # to anything, because it won't be checked; the password
                # from PAM will.
                user = User(username=username, password='get from PAM')
                user.save()
            return user
        return None

    def get_user(self, user_id):
        try:
            return User.objects.get(pk=user_id)
        except User.DoesNotExist:
            return None

Lovely, isn't it? It's super simply to use this package in any framework really, I just thought I'd add a Django example, since most of the readers here use Django. This is why this package is rated so high, it's literally so easy to use and I highly doubt anybody will make a mistake while using it's syntax. There is a third parameter to authenticate which I neglected to mention. It is for the service which you are authenticating against. The default is login which is a rather sane default, so unless you really need to customize which PAM backend you want to authenticate against, it's safe to exclude it entirely.

Pros:

  • Quick and easy to use
  • Zero configuration required
  • Works right after install
  • Easy to learn and understand

Cons:

  • Can conflict with the python_pam module used for writing PAM modules

Verdict:

A great little tool to easily enable a Python application or web application to use PAM authentication. Since PAM is very flexible and can authenticate against... how many backends... It's invaluable as an authentication backend on Linux servers.

Package Website
April 23, 2013, 9:48 p.m. - John

Hi Kevin, I just saw the page and I want to write a simple django project for user authentication. These users are all linux users, so what am I supposed to do?

May 8, 2013, 2 a.m. - Manu

Hi Kevin, I dont understand how PAM works. In your example, you use: pam.authenticate(username, password), and it returns true or false, but, where does PAM query? inside /etc/passwd ? So, you have two methods of auth, because then you create user at Django, really? I'm lost. thanks in advance Kevin

May 12, 2013, 1:22 p.m. - Kevin Veroneau

Hello Manu, that is a great question. PAM queries anywhere you tell it to, it's configured within PAM. Normally /etc/passwd is queries, but other sources can be added such as LDAP, Windows Domain Logon, etc... The reason Django also adds the user is for that "User Relationships" still work. Say if a user creates a new object in the database that needs to be assigned to them somehow, you can't connect MySQL directly to PAM, so a dummy user needs to be created for this purpose. This is how all Django authentication plugins work, such as facebook connect, OpenID, etc...

About Me

My Photo
Names Kevin, hugely into UNIX technologies, not just Linux. I've dabbled with the demons, played with the Sun, and now with the Penguins.




Kevin Veroneau Consulting Services
Do you require the services of a Django contractor? Do you need both a website and hosting services? Perhaps I can help.

If you like what you read, please consider donating to help with hosting costs, and to fund future books to review.

Python Powered | © 2012-2013 Kevin Veroneau