I'm sure that some of you have dealt with this same problem. I'm hoping that someone has a better answer than what I'm doing now.
So, you've got some users in an LDAP directory, and one day you say "hey! I can authenticate against this thing for SSH!" And it is good.
Then one day you realize you want only certain users to be able to get into a machine. Say, developers should only be able to get into the dev boxes, not prod. You do some googling around and find pam_groupdn
which goes in your LDAP config (/etc/ldap.conf
) like so:
pam_groupdn CN=developers,OU=groups,DC=yourcompany
And, again, it is good. You make another group for prod, another for QA, etc. Maybe one day you have a second product dev group, so they get their own group. Whatever.
Then one day you've got a server that both developers and QA need to be able to log in to. Uh... It turns out that pam_groupdn
doesn't take multiple values. What do you do? Well, if you're not thinking much, you say "oh, I'll just make a developers-and-QA group!".
pam_groupdn CN=developers-and-QA,OU=groups,DC=yourcompany
That's... not good, but it's ok, right?
Then one day you get another developer, and you realize you need to add them to 15 groups because there's developers-and-QA
, product1-and-product2
, developers-who-have-access-to-prod
and so on. Crap.
There's got to be a better way to do this, right? I emailed the developers of pam_ldap
, and they said that unfortunately there's no way to make pam_groupdn
take multiple values (without hacking around in the code).
Anyone want to share how they manage groups-of-groups in LDAP without resorting to copy/paste?
A working solution is to apply a
pam_filter
instead ofpam_groupdn
in/etc/ldap.conf
:"Filter to AND with uid=%s" means the Filter sent to the LDAP-Server will be like this:
&(uid=<your username>)(<your pam_filter>)
The user has to be member of
developers
orQA
. If he is not member of one of these groups, there is an error message in the response from the LDAP server and the password will not even be sent to the LDAP-Server.Works for my RHEL 5.8 Environment.
For different filter variations, check google for "ldap filter syntax"...
If you're using NSS you can set the
AllowGroups
parameter in/etc/ssh/sshd_config
. If not, you should look into dynamic lists:Something like that. You also need to include the schema and include the overlay, etc.... So it's a start.
My solution here is pretty ugly, but slightly less ugly than what you describes above: the group I specify in
pam_groupdn
is a "machine-class" group, e.g.cn=database,ou=NY,dc=mydomain,dc=com
The groups qualify who should have access to a specific class of systems at a specific site (in the above example,
database
servers inNY
).This only really works by virtue of the fact that in my environment granting a user access to one machine in a particular class is pretty much pointless (because they're all effectively identical), so if I'm letting someone log into
db01
there's no reason they shouldn't also be allowed to log in todb02
. (The "site" qualification is born of the logic that I may hire someone to manage California, but I may not want them logging in to NY's machines.)This design does involve some duplication in the groups which makes globally revoking access more difficult (e.g. my account is listed in every group at every site: To lock my user out you would have to edit every group and revoke my membership), but it gives the groups a logical/manageable structure that only grows when new sites/machine classes are added.
Assuming you have some configuration management system like puppet you can devise a PAM-based solution (so it is more general than
AllowGroups
in sshd_config) by using pam_listfile. Have puppet manage something like/etc/allowed_groups
for each server/server group and add to your PAM config:Like the SSH solution it assumes you have LDAP wired into NSS.
If you are using RHEL6+ the conf file is located at
/etc/pam_ldap.conf
and not/etc/openldap/ldap.conf
. If you put thepam_groupdn
entry in there then it will work as designed. The best way to go about it would be to copy yourldap.conf
topam_ldap.conf
or create a symbolic link.