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

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 ]

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 <sigh>

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