A directory service doesn't make it easy to disable user accounts
A typical reaction on Reddit to my earlier entry on the complexity of disabling accounts is this:
Couldn't this be solved by moving to an LDAP based (or AD for windows environments) login?
Unfortunately, the answer is no; a directory service doesn't make disabling users much easier, not by itself. The problem is inherently complex.
Let's imagine that we have some directory service; it stores user information, including multiple passwords, and it has a 'disabled' flag. What has to pay attention to the 'disabled' flag in an environment like ours?
- a disabled account should fail all password validation; this handles
simple logins, Samba access, IMAP, and things like a VPN.
(The directory service may handle this for you, or you can explicitly invalidate the passwords as well when you set the disabled flag.)
sshdmust refuse to authenticate any disabled account, with or without passwords, even when it's not even running a program through the user's shell (as Dan Astoorian noted in a comment on the last entry).
atdmust ignore crontabs and at jobs for disabled users.
- your MTA must refuse to run programs for disabled users; this handles
pipes in the user's
- the web server must refuse to run CGIs for disabled users.
(Really it needs to refuse to run any code for disabled users, including in-server code in languages such as PHP. But let's assume that you don't allow users to do that; all of their code has to run under their UID in one way or another.)
(Because many of these daemons explicitly run things using
simply changing the user's shell to an invalid shell won't achieve
- your Unix systems need something that kills the processes of (newly) disabled users; this will handle both current logins and background processes that the user's left lying around.
- your network (including VPNs and wireless authentication systems)
need something to terminate the sessions of (newly) disabled users.
- if you have authenticated web services that use cookie-based sessions,
they need to invalidate the sessions of now-disabled users.
(You can do this either preemptively or on the fly as you check the session during a HTTP request, but you have to do it.)
- your DHCP server (or its database) needs to track the user associated with a machine and ignore the machine if it was registered by a disabled user. (If you allow users to register machines you probably should allow such machines to be re-registered by another user, which opens up interesting issues.)
So here's the question: today, how many of your daemons and systems
actually support doing this as they come out of the box? The answer
is almost certainly 'none' or 'very few' (and the example of
shows that support for this may be ad-hoc, inconsistent, and
incomplete). Where they do not have out of the box support for this, you
need to either add it or handle these cases by hand (eg checking for
user crontabs, disabling the user's
Disabling a user using a directory system is only simple if you do not have services that do things on behalf of the user and the user cannot have lingering activity on your systems. This is the case in some environments (such as Windows desktop environments), but it's often not the case in a Unix environment. Where you do have 'on behalf of' services, they have to know to not do things for disabled users; where you have lingering or ongoing activity, something has to know to terminate it. Today this is generally not an integrated feature in anything (at least on Unix; Windows may have better integration for this with AD).
Some but not all of these cases get easier if you can hide (or delete) the disabled user's entry in your directory service. But it isn't a complete solution and it has (probably) undesirably side effects, and the Limoncelli test specifically talked about disabling a user, not deleting them (and hiding a user's entry is much closer to deleting them than simply disabling them).
Another reason why version control systems should support history rewriting
In Wait, Not That Bit!, Greg Wilson writes about the problem of making a bunch of unrelated changes to a single file and then having to commit a big bullet list of changes. A discussion of splitting existing changes into multiple commits and how you test the resulting separate commits then ensued in the rest of the entry and the comments.
However, I'd like to note that there is a fundamental conflict inherent in this workflow. We want VCS commits to be very easy and lightweight so that developers will actually do them (and do them frequently), instead of developing and checkpointing things outside the VCS because it's more convenient. At the same time we want each VCS commit to be for a single separate change, and we want the change (and the commit) to pass tests. These goals are in conflict, and the discussion in Greg Wilson's entry is one sign of it; all of the proposed solutions involve a developer who has a finished chunk of code going through more work before they can capture it in their VCS. What happened to 'commit early, commit often'?
(Among other things, my strong opinion is that as a developer I want to be able to snapshot the code the moment that it actually works. Working code is precious and fragile. Changing the code without a snapshot after it works is an invitation to accidents, mistakes, damaged code and heartburn.)
The reality is that you want to do two sorts of commits here; as you develop you want to capture state (especially 'okay, this code works, make sure I don't lose it'), and once you're done you want to capture distinct changes. Or rather, once you're done you want to turn your captured state into a series of separate changes (and test them one by one). This sounds more or less exactly like 'rewriting history'; you start out with a history that is a series of state snapshots (the degenerate case is a single snapshot) and rewrite it into a history of separate changes. Then you publish only the second, proper history.
Once you're going to be rewriting history, it should be supported in your VCS for reason that I've written about before.
(You can try to argue that your VCS should be used only for the final commits and the state snapshots should be handled through some other mechanism or program. I feel that this is a mistake; among other things, this other mechanism is effectively a version control system itself and that means that someone had to write it, duplicating much or all of the work of writing your main VCS.)