======================================== Notes on user/group manipulation in ldap ======================================== Security issues: ================ * End users can overwrite shadowlastchange settings thereby circumventing password aging restrictions * ssh/pka does not honor forced password resets (pwdrest=true), pwd aging restrictions when using ppolicy pwdmaxage, nor pwd locking via pwdAccountLockedTime. * ssh/pka does honor these settings for local accounts * ssh does honor these settings (not using keys) Goals: ====== * How to enforce pwd aging and restrictions (ppolicy: pwdmaxage: done) * How to force a pwd change upon first acess after a pwd reset. (pwdreset: done) * How to administratively (un)lock an account. (pwdAccountLockedTime: done) * How to force password complexity. * Experiment with alternate password policies. * How to lock users to a specific set of hosts * host object done: * sssd ldap_access_filter in the works * How to add/delete users from groups (done) * How to configure sudo privs via ldap * Update centos installation doc with requisite overlays: * ppolicy * memberof * Update centos installation doc with updates to group definitions required by rfc2307bis: * member * objectclass: groupofnames Status: ======= 01/10/14: Working on a blog entry at http://itdavid.blogspot.com/2012/05/howto-openldap-2.html **IMMEDIATELY** got irritated w/the constant ldif crap that has to come about... So, I wrote and documented a script_ .. _script: http://www.olearycomputers.com/ll/ldap/ldap_wrapper.html That'll get me past the tedious crap and we can continue on with more interesting aspects. Script covered the past few days so I'm going to take a break for awhile. Password restrictions: ====================== W/openldap 2.4, this is apparently done as an overlay. While reading through the overlay section of the admin guide, I see something called *Reverse Group Membership Maintenance* which provides support for identifying which groups an entry is a member of without performing an additional search. Examples for the usefulness is using the DIT for access control based on group authorization. Guide doesn't go into how to configure that authentication, though. From the slapo-ppolicy(5) man page: *Every account that should be subject to password policy control should have a pwdPolicySubentry attribute containing the DN of a valid pwdPolicy entry, or they can simply use the configured default.* Enables having different password policies for different users. Could be useful for system accounts, ones that have NP set as their encrypted password (and, thusly disabling password authentication). * Aging parameters measured in seconds. * pwdMaxAge : 7776000 = 90 days. * Nothing specific for password complexity. There is a pwdCheckModule which looks like it'd fit the bill; but nothing pre-defined. Finding out what I don't know. I need to add a module section of the cn=config. Apparently, I don't have one of those... The ldif looks like: :: dn: cn=module,cn=config objectClass: olcModuleList cn: module olcModuleLoad: ppolicy olcModulePath: /usr/lib64/openldap and the command: :: # ldapadd -Y EXTERNAL -H ldapi:/// -f ./module.ldif SASL/EXTERNAL authentication started SASL username: gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth SASL SSF: 0 adding new entry "cn=module,cn=config" Well, that's a good sign. The guide from which I'm taking this_ says I should restart slapd. Got a warning, though. Not too happy about that. Continuing, in the hopes that the warning is simply missing policy info # service slapd restart Stopping slapd: [ OK ] Checking configuration files for slapd: [WARNING] config error processing cn=module,cn=config,cn=config: config file testing succeeded Starting slapd: [ OK ] .. _this: http://www.flagword.net/2013/02/openldap-with-tls-ppolicy-and-master-master-replication-on-rhel6-3/comment-page-1/ Not so good... it won't let me do anything anymore w/any authentication. Restoring my backup to see if I can regain access. That's good... //later that same day. I re'genned the ldap directory and then made another copy of the ldapsvr disk so that I can always get back to the clean ldap server. The reason I did this is that I was suspecting permissions issues with the ppolicy addition. Now that everything's back up and running, I don't believe that's the case; however, it's good to have the new starting point anyway. 01/16/14: It seems I've gotten further. This time around, I added the policies ou then added the module. When I restarted slapd, no warnings... Interesting. Wonder what was different from the other day. The password policy is currently active. Steps: * Add the policies ou - (top part of policies.oci.com.ldif), as cn=admin * Add the loadable module: module.ldif: as cn=config * Add the ppolicy overlay: ppolicy-overlay.ldif as cn=config * Add default policy as cn=admin :: dn: cn=default,ou=policies,dc=oci,dc=com cn: default objectClass: top objectClass: device objectClass: pwdPolicyChecker objectClass: pwdPolicy pwdAttribute: userPassword pwdInHistory: 8 pwdMinLength: 8 pwdMaxFailure: 3 pwdFailureCountInterval: 900 pwdCheckQuality: 1 pwdMustChange: TRUE pwdGraceAuthNLimit: 0 pwdMaxAge: 7776000 pwdExpireWarning: 604800 pwdLockoutDuration: 300 pwdLockout: TRUE 01/18/14 After getting everything added as described above, I found that any log ins to client1 were repeatedly getting forced to change passwords and I could cycle them back and forth. Examining everything showed that I messed up the ppolicy overly by having ``olcPPolicyDefault: cn=default,ou=policies,dc=example,dc=com``. dc=example vs dc=oci Correcting that should have been simple but it took me a bit to find: :: # cat modify_ppolicy-overlay.ldif dn: olcOverlay={0}ppolicy,olcDatabase={2}bdb,cn=config changetype: modify replace: olcPPolicyDefault olcPPolicyDefault: cn=default,ou=policies,dc=oci,dc=com # ldapmodify -Y EXTERNAL -H ldapi:/// -f ./modify_ppolicy-overlay.ldif SASL/EXTERNAL authentication started SASL username: gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth SASL SSF: 0 modifying entry "olcOverlay={0}ppolicy,olcDatabase={2}bdb,cn=config" That corrected, user accesses to client1 **still** constantly forced a pwd reset. On a whim, I tried one of the other systems and the pwd policy's working. WTF? Oh yea, client1 is using legacy nslcd vs sssd authentication. Another troubleshooting thing to go on the list. I'm going to reset client1 to use sssd so I have three clients with which to play. While that's going on, the next challenge was how to figure out that an account is actually locked. Turns out that it's not that easy. I purposely locked an account, then viewed the entry: :: # ldapsearch -LLLxD cn=admin,dc=oci,dc=com -w "${pwd}" \ -b dc=oci,dc=com uid=aaaa dn: uid=aaaa,ou=users,dc=oci,dc=com cn: aaaa gecos: aaaa test user objectClass: top objectClass: account objectClass: posixAccount objectClass: shadowAccount shadowMin: 0 shadowMax: 90 shadowWarning: 7 loginShell: /bin/bash uidNumber: 604 gidNumber: 614 homeDirectory: /home/aaaa uid: aaaa userPassword:: [[snipped]] Nothing in there says locked. After **much** searching, I finally found out the parameter is that I'm looking for is ``pwdAccountLockedTime`` and that it's not displayed in the normal uid. :: # ldapsearch -LLLxD cn=admin,dc=oci,dc=com -w "${pwd}" \ -b dc=oci,dc=com uid=aaaa pwdaccountlockedtime dn: uid=aaaa,ou=users,dc=oci,dc=com pwdAccountLockedTime: 20140118190653Z I updated the ldap script to show that parameter on searches: :: # ldap -search uid=dddd ------------------------------------------------------------------------ dn:uid=dddd,ou=users,dc=oci,dc=com cn: dddd gecos: dddd test user objectClass: top account posixAccount shadowAccount shadowMin: 0 shadowMax: 90 shadowWarning: 7 loginShell: /bin/bash uidNumber: 940 gidNumber: 614 homeDirectory: /home/dddd uid: dddd userPassword: [[snipped]] pwdAccountLockedTime: 20140119043611Z Also had some practice with modifying the password policy. The LDIF is: :: # cat modify_policies.ldif dn: cn=default,ou=policies,dc=oci,dc=com changetype: modify replace: pwdMustChange pwdMustChange: TRUE - replace: pwdCheckQuality pwdCheckQuality: 0 Just changed lockout time to half an hour to give me some time to work out the process for unlocking the poor dear. LDIF to reset a pwd and forcing a pwd reset on next login: :: # cat reset_pwd.ldif dn: uid=aaaa,ou=users,dc=oci,dc=com changetype: modify replace: userPassword userPassword: {SSHA}GP5kKswAvk+PBRvZDsPKzcG6rD4lTp8E - add: pwdReset pwdReset: TRUE That encrypted pwd is '1changeme' Interestingly, the next login wouldn't let me use my standard pwds which should meet just about any complexity guidelines... Which, turned out to be the pwd history depth. Very misleading message. :: Password change failed. Server message: Please make sure the password meets the complexity constraints. passwd: Authentication token is no longer valid; new one required Connection to client1 closed. Reset the pwd history to 2 while I work through the pwd policy. Next step is to modify the ldap script to reset passwords. Don't want to do that today, though. // later that same day OK; so that's done. the ldap command re-enables accounts and resets passwords with an optional force arg. nice. Reviewing today's progress: To set up password policies: 1. Enable the ppolicy module and restart slapd: :: # cat module.ldif dn: cn=module,cn=config objectClass: olcModuleList cn: module olcModuleLoad: ppolicy olcModulePath: /usr/lib64/openldap # ldapadd -Y EXTERNAL -H ldapi:/// -f ./module.ldif SASL/EXTERNAL authentication started SASL username: gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth SASL SSF: 0 adding new entry "cn=module,cn=config" # service slapd restart Stopping slapd: [ OK ] Starting slapd: [ OK ] 2. Define the ppolicy overlay and default policy: :: # cat ppolicy-overlay.ldif dn: olcOverlay=ppolicy,olcDatabase={2}bdb,cn=config objectClass: olcPPolicyConfig olcOverlay: ppolicy olcPPolicyDefault: cn=default,ou=policies,dc=oci,dc=com # olcPPolicyUseLockout: TRUE # olcPPolicyHashCleartext: TRUE # ldapadd -Y EXTERNAL -H ldapi:/// -f ./ppolicy-overlay.ldif SASL/EXTERNAL authentication started SASL username: gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth SASL SSF: 0 adding new entry "olcOverlay=ppolicy,olcDatabase={2}bdb,cn=config" 3. Create the policies ou and the default policy: :: # cat policies.oci.com.ldif dn: ou=policies,dc=oci,dc=com objectClass: organizationalUnit objectClass: top ou: policies dn: cn=default,ou=policies,dc=oci,dc=com cn: default objectClass: top objectClass: device objectClass: pwdPolicyChecker objectClass: pwdPolicy pwdAttribute: userPassword pwdInHistory: 8 pwdMinLength: 8 pwdMaxFailure: 3 pwdFailureCountInterval: 900 pwdCheckQuality: 1 pwdMustChange: TRUE pwdGraceAuthNLimit: 0 pwdMaxAge: 7776000 pwdExpireWarning: 604800 pwdLockoutDuration: 300 pwdLockout: TRUE # ldapadd -x -D cn=admin,dc=oci,dc=com -w "${pwd}" -f ./policies.oci.com.ldif adding new entry "ou=policies,dc=oci,dc=com" adding new entry "cn=default,ou=policies,dc=oci,dc=com" Other useful ldifs: * To identify if an account is locked: :: # ldapsearch -LLLxD cn=admin,dc=oci,dc=com -w "${pwd}" \ -b dc=oci,dc=com uid=aaaa pwdaccountlockedtime dn: uid=aaaa,ou=users,dc=oci,dc=com pwdAccountLockedTime: 20140118190653Z if pwdAccountLockedTime is present and the time is within the pwdLockoutDuration, then the account is locked. * To reenable a locked account: (use the ldap script or): :: # cat enable_acct.ldif dn: uid=aaaa,ou=users,dc=oci,dc=com changetype: modify delete: pwdAccountLockedTime # ldapmodify -x -D cn=admin,dc=oci,dc=com -w "${pwd}" -f ./enable_acct.ldif * To reset an account's password: * ldappasswd (automatically encrypts password): :: ldappasswd -xD cn=admin,dc=oci,dc=com -w "${pwd}" \ -s "new_secret" uid=aaaa,ou=users,dc=oci,dc=com * Use the ldap script * ldif: :: # cat reset_pwd.ldif dn: uid=dddd,ou=users,dc=oci,dc=com changetype: modify replace: userPassword userPassword: ${new_hash_from_slappasswd} # ldapmodify -x -D cn=admin,dc=oci,dc=com -w "${pwd}" -f ./reset_pwd.ldif * To force a passwd change on next access: * Use the ldap script * ldif: :: # cat reset_pwd.ldif dn: uid=dddd,ou=users,dc=oci,dc=com changetype: modify replace: userPassword userPassword: {SSHA}9AqxMA9lUKLmYAmjLADsBMbttu0FRJ2k - add: pwdReset pwdReset: TRUE # ldapmodify -x -D cn=admin,dc=oci,dc=com -w "${pwd}" -f ./reset_pwd.ldif Tomorrow's goal is to: * (done) First and foremost, redo the updates to ldap wrapper script * (done) Reset ldapsvr to empty directory * (done) Reset clients to clean set ups, using sssd authentication * (done) Verify end to end ppolicy configuration * Write up an ll entry 01/19/14: Like a dumb fuck, I reverted the ldapsvr image before backing up the ldap wrapper script so I lost my changes to the fucker. Damn me as a dumb fuck! Finally got smart and created a bare repo on mgmt to hold any updates to the ldap govno. Interesting: I'm finding evidence that the shadow entries in the account aren't used anymore - particularly once the the ppolicy is in place. I finally have a need to update the ldap command to add/replace/delete arbitrary shit in a dn. This should make it **incredibly** dangerous. Updating today's goals: * Research different impacts of pwdchangetime/shadowlastchange on policy standards of pwdMaxAge/shadowMax That's going to be a bit interesting. I was hoping I'd be able to set the pwdchangedtime back; but, apparently, I can't edit that parameter. Nice! Attempts to do so resulted in: :: failed to alter attribute: pwdchangedtime: no user modification allowed I can change the pwdmaxage parameter in the policy to be something like 5 minutes; that'd at least let me experiment with expired passwords - how to verify them and how to repair them. I also *parameterized* the userdn and groupdn so the ldap wrapper script should be finished. Time to update the ll entry 01/20/14: Not going to get a lot of time today. I want to play around w/passwd expiration via the ppolicy overlay. I set the pwdmaxage to 300 seconds - 5 minutes. Boy, that'd irritate the little darlin's, wouldn't it? Set the pwdmaxage to 5 minutes and verified that anyone not changing their passwords in that five minutes were forced to change them again. That sure would upset the poor darlins, wouldn't it? That, and set the pwdinhistory to 50. heh. Next, I just verified that a normal user can rewrite the shadowLastChange parameter with a simple ldapmodify command: :: # cat reset_shadowLastChange.ldif dn: uid=aaaa,ou=users,dc=oci,dc=com changetype: modify replace: shadowLastChange shadowLastChange: 16045 ldapmodify -xD uid=aaaa,ou=users,dc=oci,dc=com -w "${pwd}" \ -f ./reset_shadowLastChange.ldif modifying entry "uid=aaaa,ou=users,dc=oci,dc=com" I wonder if I can do that @ work... Fuck, sure enough, that's not just a openldap issue. So, an incredibly good reason to convert from the shadow functionality to the ppolicy. That goes into the lessons learned... 02/15/14: Been a bit since I've been able to work on this. Got the password policy functionality pretty well hammered down. I want to play around with some alternate password polices, maybe ones that say no password expiration or password different password complexities. Next on the hit list is password complexity //later that same day: Out-f'ing-standing! ldap honors the password comlexity settings defined in /etc/pam.d/system-auth. :: password required pam_cracklib.so retry=3 minlen=12 difok=4 ucredit=1 lcredit=0 dcredit=1 ocredit=2 password required pam_pwhistory.so use_authtok remember=2 password [success=2 default=ignore] pam_unix.so obscure remember=2 use_authtok try_first_pass sha512 password [success=1 user_unknown=ignore default=die] pam_sss.so remember=2 use_authtok try_first_pass password requisite pam_deny.so password required pam_permit.so Once I got that working for a local user, I reset *a*'s password and tried it. Sure enough, it maintained the restriction. This has some interesting possibilities. Thoughts, in no particular order: * Could be used to avoid whole issue of setting a ldap based password complexity module which, seemingly, has to be compiled. * One issue is that we'd have to update system-auth everywhere; however, if we're already doing that for group access, then it doesn't seem like that big a deal. * Potentially bigger issue would be a mixed env in which a user could change his password to something simpler, matching the reqs on an older or different variant. If it's accepted on the old system, I imagine it'd be accepted by the directory which means the guy could log in on the more restrictive system with the simpler password. Turns out that's not quite as easy as it sounds, but it does, in fact, work that way. 03/23/13: Been a bit since the last bit of studying. In that time, though, I found out that ssh/pka does not honor pwdreset=true or pwd aging via the ppolicy pwdmaxage parm. Put out questions to the centos forums and to the openldap mailing list without any successful answers. Seems like someone would have fixed this already. I want to verify how to administratively lock and unlock a user account. Maybe add those as functions to the ldap script. Mostly previously identified: * Account is locked if pwdAccountLockedTime is set. * Account automatically gets unlocked after pwdLockoutDuration is set in the ppolicy. * To manually unlock an account, remove the pwdLockoutDuration entry from the account. * To permanently lock an account, set pwdAccountLockedTime to 000001010000Z OK: 2 hours today. Hammered the account lock one and for all. Try to remember that. Next goal is to experiment w/pwd complexity rules. As I found out about 5 weeks back, I can use the system-auth to enforce complexity. That kind of circumvents the whole centralized management, though. Would like to get something internal to the directory server. 05/06/14: Been awhile. Went and got my rhce so that took a wee bit of studying. It was also looking like I was going to be rolling off of Multiplan; however, the buggers came up with a salary I can live with. Won't be great, but it'll be livable.. So, back to the ldap studying First goal of the return should be reasonably easy - getting the ldap script able to update group membership. // a few minutes later. Well, that turned out even easier than I expected. The logic's aleady in the ldap script. It's a simple modify run. :: # ldap -modify -dn cn=infra,ou=groups,dc=oci,dc=com add memberuid=ddddd alter: add -> memberuid -> ddddd: done # ldap -search cn=infra ------------------------------------------------------------------------ dn:cn=infra,ou=groups,dc=oci,dc=com cn: infra objectClass: top posixGroup gidNumber: 635 description: System Admins memberUid: d dd ddd dddd ddddd # ldap -modify -dn cn=infra,ou=groups,dc=oci,dc=com delete memberuid=ddddd alter: delete -> memberuid -> ddddd: done # ldap -search cn=infra ------------------------------------------------------------------------ dn:cn=infra,ou=groups,dc=oci,dc=com cn: infra objectClass: top posixGroup gidNumber: 635 description: System Admins memberUid: d dd ddd dddd Also updated the ldap_wrapper doc to include examples of adding/deleting group membership. On to restricting access. * Found a reasonable pdf that described how to set up pam_ldap. Unfortunatley, as I read further, I found that pam_ldap is obsolete in rhel6. The short version of configuring pam_ldap is: :: * Add ``pam_check_host_attr yes`` to /etc/openldap/ldap.conf * Update /etc/pam.d/system-auth to include the line below as the first account line: :: account [success=done new_authtok_reqd=done perm_denied=bad default=ignore] pam_ldap.so * Add host entries to individual accounts. * As mentioned, though, that's not working on my centos 6.5 variant. * rhel6/sssd - using host object in user entry: * After running authconfig, verify authentication is working. First, get it working globally before trying to limit it. * Once it is, rearrange /etc/sssd/sssd.conf (not strictly required, but helps figure out WTF is going on): :: [sssd] ... [domain/default] ... ${rest-o-them} * Add three entries: :: access_provider = ldap ldap_access_order = host ldap_user_authorized_host = host * Total domain/default entry: :: [domain/default] id_provider = ldap auth_provider = ldap chpass_provider = ldap access_provider = ldap #----------------------------- cache_credentials = True ldap_search_base = dc=oci,dc=com krb5_realm = EXAMPLE.COM krb5_server = kerberos.example.com ldap_uri = ldaps://ldapsvr.olearycomputers.com ldap_tls_cacertdir = /etc/openldap/cacerts ldap_tls_reqcert = allow #----------------------------- ldap_access_order = host ldap_user_authorized_host = host * Tests show that only hosts allowed in users' entries are allowed in. :: for u in d dd ddd do ldap -search uid=${u} done ------------------------------------------------------------------------ dn:uid=d,ou=users,dc=oci,dc=com cn: d gecos: test user: d objectClass: top account posixAccount shadowAccount shadowMin: 0 shadowMax: 90 shadowWarning: 7 loginShell: /bin/bash uidNumber: 856 gidNumber: 639 homeDirectory: /home/d uid: d pwdChangedTime: 20140427175416Z host: client1 ------------------------------------------------------------------------ dn:uid=dd,ou=users,dc=oci,dc=com cn: dd gecos: test user: dd objectClass: top account posixAccount shadowAccount shadowMin: 0 shadowMax: 90 shadowWarning: 7 loginShell: /bin/bash uidNumber: 920 gidNumber: 639 homeDirectory: /home/dd uid: dd pwdChangedTime: 20140427175435Z host: * !client3 ------------------------------------------------------------------------ dn:uid=ddd,ou=users,dc=oci,dc=com cn: ddd gecos: test user: ddd objectClass: top account posixAccount shadowAccount shadowMin: 0 shadowMax: 90 shadowWarning: 7 loginShell: /bin/bash uidNumber: 936 gidNumber: 639 homeDirectory: /home/ddd uid: ddd pwdChangedTime: 20140427175440Z Well, this got a bit longer than expected. Got the hostobject style of access restriction down. Next, I was originally going to look at authorized_service; however, I now believe those are authorized sssd services.. I think. I want to do some more research on authorized_service style. Lastly, it'll be the groups that are used at MPI. 05/11/14: Working on the group access to systems. I found where to input the access filter but I can't get it working right. The syntax is supposed to be something like: :: ldap_access_filter = (|(memberOf=cn=dba,ou=groups,dc=oci,dc=com)(memberOf=cn=infra,ou=groups,dc=oci,dc=com)) Interestingly, even simplifying that to infra alone didn't work. Now, check this: :: # h client1 # groups d d : infra # ldapsearch -xLLL cn=infra dn dn: cn=infra,ou=groups,dc=oci,dc=com # ldapsearch -xLLL cn=infra,ou=groups,dc=oci,dc=com # I suspect that inability to resolve fully qualifie search filtes is what's causing the sssd issue. Every access attempt results in: May 10 14:56:39 client1 sshd[2642]: Connection from 192.168.122.20 port 39420 May 10 14:56:39 client1 sshd[2642]: Failed publickey for d from 192.168.122.20 port 39420 ssh2 May 10 14:56:43 client1 sshd[2642]: pam_unix(sshd:auth): authentication failure; logname= uid=0 euid=0 tty=ssh ruser= rhost=ldapsvr user=d May 10 14:56:43 client1 sshd[2642]: pam_sss(sshd:auth): authentication success; logname= uid=0 euid=0 tty=ssh ruser= rhost=ldapsvr user=d May 10 14:56:43 client1 sshd[2642]: pam_sss(sshd:account): Access denied for user d: 6 (Permission denied) May 10 14:56:43 client1 sshd[2642]: Failed password for d from 192.168.122.20 port 39420 ssh2 May 10 14:56:43 client1 sshd[2643]: fatal: Access denied for user d by PAM account configuration To see if it's something I fucked up in the pam configuration files, I'm recreating a new client. I don't think it is; but, it's an easy check. //later that same day. OK: the fully qualified search is not the issue as I'm not able to run those queries at work either. I **am** able to run ``getent group ${group}`` queries, though, whereas I can't on my ldap environment. So, let's figure that one out... More detail: based on searches, there's the possibility that openldap will display group numbers, but not group names. Sure enough, that's the symptom: :: # h client4.olearycomputers.com # getent group 635 infra :*:635:d,dd,ddd,dddd # getent group infra # I noticed the space in the entry above. Searching for 'infra ' shows the data. # getent group 'infra ' infra :*:635:d,dd,ddd,dddd Deleted, recreated the groups w/o spaces. Still having the same access issue I finally posted a message on the centos forum. No answer yet, though, unfortunately. If nothing comes of it by tomorrow, I'll try playing around with it a little more then move on to something a little more productive. sudo 05/11/14: Some **major** progress. It's not working quite yet, but I know what the core problem was. After several google searches, I finally figured out that the memberof search wasn't working out because the memberof overlay wasn't installed. I finally got that installed by, basically, following the same procedure as the ppolicy overlay. An overlay... Fuck! What a long time to get to this point. So, overlay's installed. I removed and re-added the groups so the memberof searches should be working by now. //later I'm getting closer. There is a major discrepancy, though. Appears I can't have normal group definitions that have both *objectclass: posixgroup* and *objectclass: groupofnames*. If I define posixgroup, I can't seem to use member; but, if I use groupofnames, I can't use the other group definitions. Reason is that they're both structural. Fuck. One interesting comment that I found: :: There seem to be two possible approaches. Either use the OpenLDAP dynlist extension to dynamically fake one list from the other, or to drop the default 'nis' schema and replace it with RFC2307bis, which does permit the two to co- exist. 05/12/14: OK; got the sssd ldap_access_filter working but what a kludge. I updated the ldap script to automatically generate a groupofnames group whenever a posixgroup is added. I also added d, dd, ddd, and dddd to the groupofnames group infra: :: # ldap -b ${gondn} -search cn=infra ------------------------------------------------------------------------ dn:cn=infra,ou=gon,dc=oci,dc=com cn: infra objectClass: top groupOfNames description: System Admins member: uid=place_holder,ou=users,dc=oci,dc=com uid=d,ou=users,dc=oci,dc=com uid=dd,ou=users,dc=oci,dc=com uid=ddd,ou=users,dc=oci,dc=com uid=dddd,ou=users,dc=oci,dc=com Finally, the memberof search is returning valid data: :: ldapsearch -xLLL \ '(&(uid=d)(objectclass=posixAccount)(memberof=cn=infra,ou=gon,dc=oci,dc=com))' dn: uid=d,ou=users,dc=oci,dc=com cn: d gecos: test user d objectClass: top objectClass: account objectClass: posixAccount objectClass: shadowAccount shadowMin: 0 shadowMax: 90 shadowWarning: 7 loginShell: /bin/bash uidNumber: 856 gidNumber: 639 homeDirectory: /home/d uid: d And, once all that was done, and client4's sssd.conf file updated with the new group ou, I'm able to limit who has access to the system via sssd.conf. As long as it's not too complex... I **really** object to having duplicate groupnames. That's just asking for trouble even if the updates are automated. Just to press on with the ldap_access_filter, I tried a couple of different ways to make the access filter more readable and more maintainable. All failed. This is going to be an ugly way of going about it. So, the line, with two groups, looks like: :: ldap_access_filter = (|(memberof=cn=infra,ou=gon,dc=oci,dc=com)\ (memberOf=cn=dba,ou=gon,dc=oci,dc=com)) That **has** to be one line - no line breaks, no new lines. I also tried setting the lda_group_search_base to see if I could get away with short group names. No joy. So, the long and the short of it: * posixgroup groups are used for unix related activities. * groupofnames groups can be used for access filtering. * Those two are **not** the same; but, procedures/scripts can be developed to help make them look like the same. * The syntax is positively heinous for maintenance and readability. Wow; host object is bad and ldap_access_filter is bad. yikes. 05/18/14: I'm going to see if I can get the ingroup govno working via /etc/pam.d/system-auth. That seems like the cleanest, easiest method of limiting access to linux systems. Starting out with a clean system, though. Blasting client1 and 4 and rebuilding client1. Heh: in my effort to be more efficient, I have to rebuild client1 again. After the power outage, mgmt rebooted with a firewall running, so the nfs exports weren't functional which means my archive_vm script killed client1 without backing it up. Need to update that little functionality too... First thing, once we have client1 back, is to see if I can get the ingroup lines working outside of ldap. Then, we add ldap and see if it's still working and troubleshoot from there. Line should look like: :: # This file is auto-generated. # User changes will be destroyed the next time authconfig is run. auth required pam_env.so auth sufficient pam_unix.so nullok try_first_pass auth requisite pam_succeed_if.so uid >= 500 quiet auth sufficient pam_ldap.so use_first_pass auth required pam_deny.so account required pam_unix.so broken_shadow account sufficient pam_localuser.so account sufficient pam_succeed_if.so uid < 500 quiet # account sufficient pam_succeed_if.so uid < 100 quiet # account sufficient pam_succeed_if.so user ingroup backup-ops # account sufficient pam_succeed_if.so user ingroup monitor-ops # account sufficient pam_succeed_if.so user ingroup devfees # account sufficient pam_succeed_if.so user ingroup dev # account sufficient pam_succeed_if.so user ingroup devsolr # account sufficient pam_succeed_if.so user ingroup dba # account sufficient pam_succeed_if.so user ingroup ops # account sufficient pam_succeed_if.so user ingroup its account sufficient pam_succeed_if.so user ingroup scm account sufficient pam_succeed_if.so user ingroup infosec account requisite pam_succeed_if.so user ingroup infra account [default=bad success=ok user_unknown=ignore] pam_ldap.so account required pam_permit.so password requisite pam_cracklib.so try_first_pass retry=3 type= password sufficient pam_unix.so md5 shadow nullok try_first_pass use_authtok password sufficient pam_ldap.so use_authtok password required pam_deny.so session optional pam_keyinit.so revoke session required pam_limits.so session optional pam_oddjob_mkhomedir.so session [success=1 default=ignore] pam_succeed_if.so service in crond quiet use_uid session required pam_unix.so session optional pam_ldap.so # add if you need ( create home directory automatically if it's none ) session optional pam_mkhomedir.so skel=/etc/skel umask=077 Delete some of those lines when you get this working. Don't want live data in a lessons learned entry. 1230: 2 hours and no joy. I can't even get pam to display text via the pam_echo. I've tried it in sshd password-auth and system-auth to no avail. The reason I'm trying the pam_echo is that the ingroup lines I tried in both system-auth and password-auth are not working. While researching this, I did find this little bit of trivia here: http://wpollock.com/AUnix2/PAM-Help.htm :: The Linux pam_unix module in a PAM configuration file with the context (module type) of “account” checks that an account exists and isn't expired. It does not check if an account has been locked or has an invalid shell! (Apparently pam_unix assumes the auth component will fail if the account is locked.) This means that users using SSH keys to log in will be allowed to do, so even if you lock their accounts with the “passwd -l” command (since sshd doesn't use the PAM auth modules in this case)! Setting an invalid shell is checked with the Linux pam_shells module, but that is usually included only in the configuration files for FTP servers. (I've been locking users out this way for years and I've never realized the danger. Now I always add pam_shells in the account part of my PAM configuration (as required), and lock accounts by specifying an invalid shell such as /bin/false, for login, sshd, and other remote access services.) So, ssh doesn't use the auth modules which is why the keys work. That's the cause; how do we work out the solution? 05/23/14: I got the pam stuff above working. The short version is that the pam_localuser.so had sufficient as its permission setting. Since a and d were both local accounts, it was sufficient and they were permitted. I tried changing that to *optional* and, suddenly, only the infra group was allowed access. OK: That gets an understanding of pam; but, I still have the posixgroup vs groupofnames issue to deal with. Looks like the right answer is to recreate the directory with rfc2307bis support. The best site I've seen so far, in my limited research on it is: http://www.omnisys.com/docs/newdevbox/slapd.html Once I get done upgrading my laptop (again, I really shouldn't wait so long...) I'm going to regenerate the ldap server virtual and try the steps out for rfc2307bis support. Assuming I can get all that working, I'll be a happy camper, and I'll have to update the lessons learned entry again. 05/25/14: Getting a few more whacks at this. I got the rfc2307bis schema installed and enambed. I also added the memberof overlay and it's working. One interesting search that doesn't appear to work at work is the memberof: :: # ldapsearch -xLLL -s sub '(cn=admin)' memberof dn: cn=admin,dc=oci,dc=com memberOf: cn=backup-ops,ou=groups,dc=oci,dc=com memberOf: cn=bamboo-consult,ou=groups,dc=oci,dc=com memberOf: cn=dba,ou=groups,dc=oci,dc=com memberOf: cn=dbusers,ou=groups,dc=oci,dc=com memberOf: cn=dev,ou=groups,dc=oci,dc=com memberOf: cn=devsolr,ou=groups,dc=oci,dc=com memberOf: cn=devweblogic,ou=groups,dc=oci,dc=com memberOf: cn=tomcat,ou=groups,dc=oci,dc=com memberOf: cn=infosec,ou=groups,dc=oci,dc=com memberOf: cn=infra,ou=groups,dc=oci,dc=com memberOf: cn=intadmin,ou=groups,dc=oci,dc=com memberOf: cn=ldap-Administrators,ou=groups,dc=oci,dc=com memberOf: cn=ldap-Monitors,ou=groups,dc=oci,dc=com memberOf: cn=ldap-users,ou=groups,dc=oci,dc=com memberOf: cn=manager,ou=groups,dc=oci,dc=com memberOf: cn=middleware,ou=groups,dc=oci,dc=com memberOf: cn=monitor-ops,ou=groups,dc=oci,dc=com memberOf: cn=oem12cinstall,ou=groups,dc=oci,dc=com memberOf: cn=oinstall,ou=groups,dc=oci,dc=com memberOf: cn=Operations,ou=groups,dc=oci,dc=com memberOf: cn=ops,ou=groups,dc=oci,dc=com memberOf: cn=rdcms,ou=groups,dc=oci,dc=com memberOf: cn=scm,ou=groups,dc=oci,dc=com memberOf: cn=tomcat-managers,ou=groups,dc=oci,dc=com memberOf: cn=weblogic,ou=groups,dc=oci,dc=com memberOf: cn=wlsqadeploy,ou=groups,dc=oci,dc=com Need to figure out how to get that into the ldap search functionality. I'm still flumoxed, though. In order to support posixgroup and groupofnames functionality, I **still** have to create two member types: * memberuid: doleary * member: uid=doleary,ou=users,dc=oci,dc=com If I'm stuck with that, I can't really see the puprose of groupofnames - which might be why it got dropped from IETF consideration. Going to try poinsting another question to openldap forum and see if anyeone, other than that flaming asshole, will answer. 10/05/14: Been at openldap users the better part of a year. Time to put ldap users to bed and move on to hosts/puppet interaction. New server, time to reinstall, reinvigorate, re-everything. New environment: * 3xldap servers on different networks (wonder where these names came from?) Only nap to be build initially in order to finish the users. Others when I start playing with replication * nap: 192.169.122.0/24 * rock: 192.168.100.0/24 * wall: 192.168.110.0/24 * At least 1xclient in each: * napc1 * rockc1 * walc1 * syslog server: OK: All done. Ready for the next step... :: # virsh list --all Id Name State ---------------------------------------------------- 6 syslog running 10 nap running 11 napc1 running 14 rockc1 running 15 walc1 running - xymon shut off 10/07/14: had some time today to take a whack at my new directory. Have to update the install directions. If installing rfc2307bis, I need to update the group addition to include a few extra lines: groupofnames object class and a member.:: # cat qwer.group.ldif dn: cn=qwer,ou=groups,dc=oci,dc=com objectClass: posixGroup objectclass: groupofnames objectClass: top cn: qwer userPassword: {crypt}x gidNumber: 100000 member: uid=qwer,ou=users,dc=oci,dc=com I don't remember having to do that before; but, the latest ldap script does have the member attrbite in the add group function. I can wrestle with that some more. Finish the install/config. 10/09/14: Got everything running; tried enabling the sssd auth on the nap host and, of course, it doesn't work. Fuck me to tears. I'll search more on that later. I'm just happy I got the directory working, the ldap wrapper script working, the memberof searches, etc. Authentication... Damn.. After running on that for a few minutes, I dropped it. I got it working before, I'll do it again. I wanted to find host schemas - and ran into a wall there, too. No pre-defined schema. The puppet one looks pretty close though... Of the list of attributes from the mpi cmdb, several are already defined: +--------------+-----------------+ | Field | ldap attr | +==============+=================+ | Host: | host | +--------------+-----------------+ | IP: | iphostnumber | +--------------+-----------------+ | NM: | ipnetmasknumber | +--------------+-----------------+ | GW: | Nope | +--------------+-----------------+ | Console: | Nope | +--------------+-----------------+ | Arch: | Nope | +--------------+-----------------+ | Serial: | Nope | +--------------+-----------------+ | Application: | Nope | +--------------+-----------------+ | Contacts: | Nope | +--------------+-----------------+