h1

CentOS 6: Authenticate (AND sudo!) Active Directory users!

2013-06-05

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:

  1. Single-sign on via Active Directory.
  2. Permit SSH & Local logon based on Active Directory group memberships.
  3. Authorize or deny ‘Sudo’ use via Active Directory group memberships.
  4. 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:

  1. 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).
  2. (Optional): Create a security group to contain users permitted to log into the Linux boxes (I used “Domain Admins“).
  3. (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:

  1. 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.
  2. 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
  1. 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’
  2. 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.
  3. 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 = +
  1. 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
  1. 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
  1. 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
  1. 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.

h1

WinPE With WDS: A reusable crash-course

2010-02-16

Getting started with WDS (especially with no other experience with deployment systems) is pretty rough; Microsoft has semi-decent documentation, but it’s nearly impossible to find, and there are many pitfalls that will have you pulling your hair out. I got to experience this first hand.

Task: Build a reusable imaging system using WDS.

Scenario:

  1. 6 Dell Optiplex GX280 XP desktops – 1 Master, 5 Clients. Clients will be constantly reimaged as QA needs to match a controlled master.
  2. 1 Windows 2008 Server Standard with WDS
  3. 1 Network share
  4. 1 overly dedicated sysadmin.

Process:

To start off, I selected and built up the master to include all the applications I knew QA would need. An important step naturally. Since this machine would be constantly captured by WDS, I needed an idiot-proof method of  sysprep-ing the machine capture. I created a ‘Sysprep’ folder on the network share, containing both a batch file and all the resources Sysprep needs to run. A link on the quick-launch bar would run the batch, copy the files down, and run Sysprep with the required commands. Easy enough.

Second, I needed to ensure that the WDS server was working properly. Add a capture image, PXE-Boot the master, connect and upload. Also very easy.

The next part is more difficult. Since these are XP machines, unattend.xml is useless. We have to use Sysprep.inf files. This means that before the mini setup runs, we have to copy the answer file to the C:\Sysprep folder manually. Otherwise our less-than-savvy QA will be prompted for all the information (including license keys). Initially I’d hoped that I could place the answer file FIRST, and pull down an image without formatting – no such luck. I had to determine a method of running a script before (wipe the HDD) and after (place the correct answer file) the WDS installation.

Enter WinPE + WAIK; Microsoft’s solution to weird deployment scenarios. WAIK lets you customize WinPE (or any other WIM for that matter) to do exactly what you need. I quickly found that the most difficult thing to do was MANUALLY connect to WDS from within WinPE.  Here’s where it get’s heavy. To do this:

  1. Install WAIK.
  2. Create a DISCOVER image in WDS, and export it to WIM
  3. Within WAIK, run ‘imagex /mountrw <discover.wim> 1 <empty folder>
  4. Navigate to <folder>\sources and rename ‘setup’ to ‘wdssetup’ (the name isn’t really important). This disconnects all the autostart functions.
  5. Navigate to <folder>\Windows\System32, and add any scripts or resources you will need. Since modifying images non-trivial, I suggest using a batch that connects to a network drive and runs a batch there. That way, any modifications that need to be made don’t require rebuilding the image  (WinPE has networking / net use support).
  6. Delete the winpeshl.ini file. This is an autostart config file.
  7. Edit ‘startnet.cmd’ – this is effectively an autoexec.bat; wpeinit MUST be included in this, and I would suggest leaving it first.
  8. When you are finished making the necessary changes, go back to the WAIK prompt and run ‘imagex /unmount <folder> /commit’ – this will save all the modifications back to the WIM file.
  9. Create a new boot image in WDS using this WIM.

This creates a boot image that will allow you to MANUALLY run a WDS pull. The batch file for a manual imaging will look like this:

> /* script before imaging */

> X:\sources\wdssetup /wds /wdsdiscover /wdsserver:<ip / fqdn> /noreboot

> /* script after imaging */

I spend 18 hours over a weekend fighting with WAIK / WinPE to come up with this disturbingly simple solution. I hope it helps someone.

Design a site like this with WordPress.com
Get started