Alright, my attempts over the previous years have all been dismal failures: Connect a Linux box to Active Directory.
In the grand scheme of things, the process itself is simple, and there are several ways to do it. In my case, I had specific requirements. Let me set the stage – a sprawling infrastructure of CentOS production servers with more being added regularly. A fast growing IT staff. Zero tolerance for inaccessibility due to domain controller availability, and therefore, one root login. If someone wipes a disk, we would never know who was at fault. In the end, these are the requirements:
- Single-sign on via Active Directory.
- Permit SSH & Local logon based on Active Directory group memberships.
- Authorize or deny ‘Sudo’ use via Active Directory group memberships.
- Allow both of the above to occur using cached credentials.
I fought with this for ages. The combination of my arguable Linux naivete and flagrant lack of LDAP knowledge played no small part. Here are the methods I tried, and the reasons I abandoned them:
- AD Server for NIS: The prerequisite SSOD agent provided my Microsoft is poorly documented and impossible to get running on CentOS 6, and therefore is useless.
- LDAP + Identity Services for Unix: This provided authentication well enough (and quite easily once you know what a BindDN is), but I gave up on the LDAP+SUDO portion due to horrible documentation when it came to AD. I discovered on my own that it involves manually creating AD objects through ADSI edit. I’m comfortable there, and I still couldn’t get it to work. In the end, no sudo = no go.
- Centrify DirectManage Express: A free third-party offering. I was actually quite impressed with it’s analysis / auto-fix functions, and it’s simple method of integrating Linux hosts into AD, but again, no way of creating a SUDOer (at least that I could find), and it was really unwieldy in a non-segregated demo environment (where the domain SRV records aren’t available through DHCP-provided DNS servers).
The holy grail? Good ol’ WINBIND. That’s right, the one solution that I passed on from the get-go, was the best solution overall.
Here is the entirety of what I needed in order to link CentOS 6 boxes to, authenticate, AND authorize users against, Active Directory.
Active Directory:
- Create a user to bind against. I created a “_service.winbind” user in AD. I gave it a very strong password, member of Domain Admins (I also disallowed interactive logon to any computer, but that is not necessary).
- (Optional): Create a security group to contain users permitted to log into the Linux boxes (I used “Domain Admins“).
- (Optional): Create a security group to contain users permitted to SUDO on the Linux boxes (Can be the same as above. Again, I used “Domain Admins“).
The windows side is done. Seriously. No need to extend schema, Identity Services for Unix isn’t needed, no Kerberos keytabs to create. That was it.
CentOS 6:
- Ensure the server is able to communicate with the Domain Controller via its FQDN. If DHCP-provided DNS is insufficient, create an entry in /etc/hosts file. If you can ping the FQDN, you’re golden.
- Run the following command as root:
authconfig --update --kickstart --enablewinbind --enablewinbindauth --smbsecurity=ads --smbworkgroup=<DOMAIN NETBIOS> \ --smbrealm=<DOMAIN.SUFFIX> --smbservers=<DC FQDN> --winbindjoin=<BIND User> --winbindtemplatehomedir=/home/%U --winbindtemplateshell=/bin/bash \ --enablewinbindusedefaultdomain --enablelocauthorize
- Enter the password you configured for the BIND user when prompted. DNS related errors are OK, as long as it says that it successfully ‘Joined %HOSTNAME to domain’
- Check that the connection worked by running ‘wbinfo -u‘. A list of domain users should appear. A new computer account will also appear in the ‘Computers’ OU within Active Directory Users and Computers.
- Next, is to enable cached logon & set things up for sudo. Change the following lines in /etc/samba/smb.conf:
winbind offline logon = yes # Then add the following beneath it: idmap uid = 10000-20000 idmap gid = 10000-20000 winbind enum users = yes winbind enum groups = yes winbind separator = +
- Then, make the following changes in /etc/security/pam_winbind.conf – this wraps up the enablement of cached logons, authorizes access based on group access, and enables home directories.
cached_login = yes require_membership_of = "logon group in all lowercase" mkhomedir = yes
- Then edit the sudoers file via ‘visudo‘. The line to add will look like this: (Replace ‘domain admins’ with your sudoer group. Don’t forget to escape spaces in the group name with a backslash! ‘\’)
%domain\ admins ALL=(ALL) ALL
- Finally, add the following as the LAST SESSION LINE in /etc/pam.d/sshd – this ensures that user home directories are created when they first log in.
session required /lib/security/pam_mkhomedir.so skel=/etc/skel umask=0022
- Restart the winbind service with ‘service winbind restart‘. That’s it, you’ve won!
To test that it works, try to SSH into the server using a domain-only username (‘ssh user.name@centosbox‘) and the associated password. If it let’s you in, try to sudo something (‘sudo ls‘). It probably won’t print anything since the current directory is the brand new user’s homedir, but if it completes without error, it succeeded!
PROBLEMS I RAN INTO:
Winbind likes to forget user groups on me. While logged in as a domain user, run the command ‘groups‘. If everything is in the clear, a list of all your Domain Group memberships will be displayed. If you’re like me, you may get an error after the first couple groups stating ‘Group XXXXXXXX could not be found’. In my case, that was Domain Admins. I haven’t found a solid solution yet, but restarting winbind (‘service winbind restart‘) and running random winbind commands (‘wbinfo -m‘; ‘wbinfo –own-domain‘; ‘wbinfo –online-status‘) usually fixes it. Because this caused problems with Sudo in my case (since my SUDOer specific group couldn’t be enumerated), I put the group id (as reported in the error) into the sudoers file in place of the group name (‘%\#16777217 ALL=(ALL) ALL‘). The login group doesn’t seem to be affected by this problem.
Permission denied when you try to SSH? Watch the /var/log/secure and /var/log/messages log files for hints.
‘Not in the SUDOer file’? Run ‘visudo‘ and check the line you added. Did you escape your whitespace? Is the group name all lowercase (it should be!)? If you resorted to group ID, is it preceded by ‘\#’ (it should be!)?
A WORD TO THE WISE:
PLEASE, seriously, TEST cached credentials immediately, and test them on ALL SERVERS. Log in and sudo something while the DC is available, and then make sure it works when the DC can’t be contacted (unplug the cable on your CentOS box or something). It may take a while to log in since the winbind service has to time out first, BUT IT SHOULD STILL LET YOU IN. You DO NOT want to discover after a catastrophic network failure that you can’t log into your CentOS servers because they can’t find your DC. Also make sure that winbind is set to start automatically on boot. You could be in for a bad day otherwise.
