Preventing users from changing their password with PAM

Blocking AD users from using passwd

I had to design a system recently for a client which has a mixture of local users and remote users that are authenticated using LDAP against Active Directory (actually, with Quest Authentication Services running in between). One of the requirements was that AD users should not be able to change their password using the passwd command as they had an external management system for users that fed into AD (and other things). I needed to allow normal users to operate normally but fail AD users with some polite message to tell them what was going on, rather than just a random error that would cause them to call support every time. Trolling the web didn’t seem to reveal much apart from doing nasty things to /bin/passwd like chattr’ing it, or moving it to /sbin… since we’re not in the 90’s anymore I was sure there was a way to do this with PAM.

My PAM knowledge is limited to say the least, and maybe my google-fu isn’t up to much because I struggled to find anything that did exactly what I wanted.

Eventually, after some tweaking, I came up with the following which seems to work on CentOS…

Edit /etc/pam.d/passwd and change it to read :-

This should work normally for root and local users but give a warning and fail to AD users.


Puppet – working with define based virtuals

Define Based Virtuals

Define-based virtuals are quite a powerful feature of Puppet, but many people either don’t understand them or don’t know how to apply them effectivly to their manifests. Due to Puppet’s normalized configuration structure, you can’t configure the same resource in two different places. For example, if the user mysql is configured in your database class, and then you realise that your webserver class also needs the mysql user, then, short of including the whhole database class, you cannot just configure the user here. The answer to this lies in resource virtualization.

Resources that are virtualized are effectivly non-real, they won’t be included in any configuration until they are explicitly realized. The good news is you can realize your resource multiple times in your manifests, so by defining the resource as virtual in a seperate class, both your webserver class and databasse class can realize it.

Version 0.23 of Puppet took this one step further, with the ability to virtualize your definitions rather than just native resource types. Now we can define a collection of resources, virtualize them, and realize them at whim in our manifests. I’ve seen a few Puppet installations and this method is far under used, and under appreciated.

To demonstrate, this is an example of how to manage your users with virtual define-based resources.

User management with defines and virtuals.

I’ve seen a few ways of managing users within a Puppet estate. The following is a quick guide to get you started managing users, passwords and ssh keys for your users. My favourite approach is to use define-based virtuals and split it out into several sections

  • Back end module to specify the definition for a user
  • A class with a list of virtualized users
  • Realizing your users ad-hoc in your classes

The advantage of this approach is that you can keep a central place for users whilst still being able to easily pick and choose which users get deployed with which classes. Lets break it down into our components;

Users module

As we want to manage users as well as ssh keys it makes sense to wrap this up into a definition, which we’ll call localuser. We create a module called users::virtual where we define the following class.

This class sets up our localuser definition in users::virtual, other resources can also be added here that will affect every user.

Creating our users class.

Now you can create a users.pp class that imports your module and defines the specific users you want to configure. We configure these as virtuals to give us the option of realizing them whenever we want.

The passord should be the fully encrypted string as would appear in the shadow file, don’t forget to use single quotes if your password string contains $ to prevent it from being interpereted as a variable.

sshey is optional (note the conditional in our users module), and, if defined will set up the key in ~/.ssh/authorized_keys. Now you have a central list of users as virtuals that call our custom define, they can be easily included, or realized, at whim in your other classes.

Realize the user

Within your manifests for your server profile, whenever you require the user bobsmith to be part of the configuration, you simply realize it like this

The above example realizes the user by the name of “bobsmith”. Another very useful way to realise users is by using Puppet’s collection syntax. For instance, to realize all the users in the users group, you would simply replace the realize statement with:

… and all your virtual users that match the gid of users will be included.


What we’ve acheived by using virtual define-based resources here is primarily,

  • An abstracted module for defining what a user is, rather than who
  • A central place to manage all of our virtual users
  • A very flexible and easy way to pull users into our classes based on name or attribute

For more information on working with Puppet virtuals, check out the documentation here