Enabling Active Directory Authentication
for VMWare Server running on Linux
Version 0.2 - Adam Breidenbaugh - 2007-06-29
Purpose
The purpose of this guide is as follows:
When you are finished with these steps, you will be able to delegate permissions to Windows user accounts to allow Active Directory users the ability to log on to and manage the VMWare Server and its virtual machines.
Disclaimer:
I developed these procedures after countless hours of trial & error, blood, sweat and tears. They are the result of information I've gleaned from searching Samba documentation, Linux howtos, various blogs, vmware forum posts, and dozens of other sources. I know these procedures work, as I am using this setup on all of my production VMWare Servers. If you make even the smallest change, it could break things. Please try to get things working exactly as I have outlined them here before you try changing things.
Also... don't try this on a production server (blah blah blah...) There are a number of changes in this document which could cause serious authentication problems on your server if not followed correctly. In addition, I can't guarantee that I haven't made mistakes in this document. Please, PLEASE don't try this procedure for the first time in a production environment...
Software Used
These guidelines assume the use of the following software:
Furthermore, I will also assume that you have basic system administration skills when it comes to managing CentOS. In other words, you are comfortable with installing packages, editing configuration files, managing services, etc...
In production, I run VMWare Server on CentOS Linux. Most (or all) of the instructions in this guide should apply to other Linux distributions as well, with the main differences being perhaps differing locations for certain configuration files.
Limitations:
The configuration in this guide works well for a simple environment. It has the following limitations:
Step 1: Prepare the Linux Server to join the Active Directory Domain
This file controls where the Linux server gets its account, name, protocol and service resolution information. Let's look at the some of the lines that control where Linux goes to authenticate the users and passwords:
passwd: files
shadow: files
This tells the Linux server that it will look in its local password file when checking the password a user provides. We need to configure the server to use a Service named "winbind" to authenticate users, but we also want to make sure that the server can still authenticate local users as well, using it's local files. To do this we need to change the following lines in the /etc/nsswitch.conf:
passwd: files winbind
shadow: files winbind
group: files winbind
protocols: files winbind
services: files winbind
netgroup: files winbind
automount: files winbind
This file must be configured properly in order to allow the Linux server to perform Kerberos authentication in the Windows Domain. We will assume that the DNS name of the active directory domain is 'company.com' and that the NetBIOS name is 'COMPANY'. Make the following changes:
[libdefaults]
default_realm = COMPANY.COM
dns_lookup_realm = true
dns_lookup_kdc = true
[domain_realm]
company.com = COMPANY.COM
.company.com = COMPANY.COM
Don't touch the [realms] section. Specifying dns_lookup_realm = true and dns_lookup_kdc = true under the [libdefaults] section allows the Linux Server to dynamically locate the key distribution service and Kerberos password service using the Active Directory resource records stored in DNS. If you list a specific Domain Controller under the [realms] section, then Active Directory authentication will fail if that server is unavailable, even though other Domain Controllers may still be available.
Replace the contents with the following lines:
[global]
workgroup = COMPANY
netbios name = VMWARESRV01
server string = WMWare Server 01
log file = /var/log/samba/%m.log
max log size = 50
security = ADS
realm = COMPANY.COM
encrypt passwords = yes
server signing = yes
smb passwd file = /etc/samba/smbpasswd
allow trusted domains = no
unix password sync = yes
passwd program = /usr/bin/passwd %u
passwd chat = *New*password* %n\n *Retype*new*password* %n\n*passwd:*all*authentication*tokens*updated*successfully*
pam password change = yes
obey pam restrictions = yes
socket options = TCP_NODELAY SO_RCVBUF=8192 SO_SNDBUF=8192
dns proxy = no
idmap uid = 10000-1000000
idmap gid = 10000-1000000
idmap backend = idmap_rid:COMPANY=10000-1000000
winbind use default domain = yes
winbind separator = +
winbind enum users = yes
winbind enum groups = yes
template shell = /bin/bash
template homedir = /home/%U
[vmware]
comment = VMWare Share
path = /var/lib/vmware
admin users = "COMPANY+VMWare Admins"
valid users = "COMPANY+VMWare Admins"
force group = "COMPANY+VMWare Admins"
public = no
writable = no
create mask = 770
force create mode = 770
force directory mode = 770
The following lines need to be changed, or need special consideration:
[global] Section:
workgroup = COMPANY - Change this to be the NetBIOS name fo your domain
netbios name = VMWARESRV01 - This will be the name of the Linux Server's Active Directory computer account
realm = COMPANY.COM - Change to the dns domain name of your Active Directory Domain - in CAPital letters -
idmap uid = 10000-1000000 and idmap gid = 10000-1000000 - These control the range of user id numbers & group id numbers that the Linux server will use for Active Directory users and groups. You will need to change this if your Linux server already has users and groups that have uid and gid numbers in these ranges. Increase the range to accomodate environments with more than 90,000 users or groups.
idmap backend = idmap_rid:COMPANY=10000-1000000 - Make sure you change COMPANY to the NetBIOS name of your Windows Domain. Increase the range to accomodate environments with more than 90,000 users or groups.
allow trusted domains = no and idmap backend - The idmap backend used here ensures that every Linux Server configured this way will generate the same uid and gid for Active Directory users and groups. Without this parameter, uid and gid numbers are assigned to Windows users and groups on a first come first serve basis, and Domain accounts and groups will not have the same uid and gid across different Linux Servers. Unfortunately, the way this is implemented precludes trusted domains from being authenticated, and you must specify the allow trusted domains = no parameter.
winbind separator = + - This tells the Linux Server to use the '+' symbol to separate the domain name from the user or group name. On Windows, you can specify a domain account in the format 'DOMAIN\ACCOUNT'. In Linux, the backslash ( \ ) has special significance, and cannot be used. Because of this, we will need to use the '+' symbol as the separator, like this: 'DOMAIN+ACCOUNT'.
[vmware] Section:
This section defines a Windows file share (named 'vmware') that can be used to easily copy Virtual Machines on to, or off of the Linux Server. I am assuming you have a Windows Domain group created named 'VMWare Admins' to which you will add the user accounts that should be able to administer the VMWare Server installation.
admin users, valid users, and force group - This share definition restricts access to ONLY the 'VMWare Admins' Windows group. Make sure you update the COMPANY+VMWare Admins" lines to match the Domain and group name you are actually using.
writable = no - This makes the share read only, even for admin users. The LAST thing in the world you want is to accidentally delete or corrupt a Virtual Machine's files. Remember, Linux has no file locking, and will not stop you from deleting a Virtual Machine's files, even while the Virtual Machine is running and accessing them! If you need to copy a Virtual Machine into the share, change this parameter to writable = yes, and then change it back to 'no' when you are done.
This file globally controls how all (or most) of the services on the Linux Server perform authentication. By editing this file, we are enabling most services and applications on the Linux Server to Authenticate Windows users and groups. Replace the contents with the following lines:
#%PAM-1.0
# This file is auto-generated.
# User changes will be destroyed the next time authconfig is run.
Auth required /lib/security/$ISA/pam_listfile.so item=user sense=allow file=/etc/security/system_operators onerr=fail
auth required /lib/security/$ISA/pam_env.so
auth sufficient /lib/security/$ISA/pam_unix.so likeauth nullok
auth sufficient /lib/security/$ISA/pam_krb5.so use_first_pass
auth sufficient /lib/security/$ISA/pam_winbind.so use_first_pass
auth required /lib/security/$ISA/pam_deny.so
account required /lib/security/$ISA/pam_unix.so
account sufficient /lib/security/$ISA/pam_succeed_if.so uid < 100 quiet
account sufficient /lib/security/$ISA/pam_krb5.so
account sufficient /lib/security/$ISA/pam_winbind.so
password requisite /lib/security/$ISA/pam_cracklib.so retry=3
password sufficient /lib/security/$ISA/pam_unix.so nullok use_authtok md5 shadow
password sufficient /lib/security/$ISA/pam_krb5.so use_authtok
password sufficient /lib/security/$ISA/pam_winbind.so use_authtok
password required /lib/security/$ISA/pam_deny.so
session required /lib/security/$ISA/pam_limits.so
session required /lib/security/$ISA/pam_unix.so
session optional /lib/security/$ISA/pam_mkhomedir.so skel=etc/skel/ umask=0022
session optional /lib/security/$ISA/pam_krb5.so
The very first line, (the one that uses the pam_listfile.so library,) allows us to enter a list of users who should have the ability to log on to the local system into the file /etc/security/system_operators. If a user is not listed in this file, they will not be able to log on to the system through ssh, or at the local console.
Set permissions to 0700 on this file to prevent unprivileged users from discovering who has access to the system. In this file, add the users who should be able to logon to the Linux Server, one per line. Make sure you add root! Domain users can be specified in lower case, without the domain name. Here is an example of what the contents should look like:
root
amcmillan
dsanchez
cdonnelly
rkruger
If you wish to disable root logons through ssh, you can do this by setting PermitRootLogin no in /etc/ssh/sshd_config. This way, admins will be forced to login remotely using their unprivileged Windows account, and then su to root to perform system admin tasks.
This file controls how VMWare authenticates users. Because it is not configured to use the global system-auth configuration that we modified above, we will need to make some specific changes to this file to enable Windows Authentication for VMWare. Replace the contents with the following lines:
#%PAM-1.0
auth sufficient /lib/security/$ISA/pam_unix.so shadow nullok
auth sufficient /lib/security/$ISA/pam_winbind.so use_first_pass
auth required /lib/security/$ISA/pam_unix_auth.so shadow nullok
account sufficient /lib/security/$ISA/pam_unix.so
account sufficient /lib/security/$ISA/pam_winbind.so
account required /lib/security/$ISA/pam_unix_acct.so
Note that every time you run /usr/bin/vmware-config.pl (after upgrading VMWare Server, or upgrading the Linux kernel,) this file will be replaced with the default file, and Windows authentication to VMWare will fail. Any time you reconfigure the VMWare Server installation, you must update this file.
Step 2: Configure Services and Join The Domain
Winbind is the service that retrieves user and group information from Active Directory. By default, it uses an anonymous connection to retrieve this information. This works fine, if your domain is set to use "Windows 2000 Compatible Permissions". On a Domain that restricts anonymous connections, Winbind will fail. To prevent this from happening, Winbind must be provided with an account to authenticate as:
· Create a domain user named 'winbind'. Set the account's password not to expire. Because the account's password will seldom (if ever) be changed, it requires a secure password. (20+ randomly generated characters, using alpha-numeric, upper/lower case, and punctuation marks.)
· Set the winbind user account on the Linux Server by running the following command:
wbinfo --domain=AINET --set-auth-user=winbind
You will probably see the two following messages, which can be ignored:
could not obtain winbind separator!
could not obtain winbind domain name!
This step will fail if there is a time difference greater than 5 minutes (by default) between the Linux Server and your Windows Domain Controllers. Run the following command to authenticate and obtain the ticket:
kinit [email protected]
UserID should be a Windows Domain user account that has permissions to create a computer account and add machines to the domain. The DNS Active Directory domain name must be upper case
To join the Linux machine to the domain, run the following command:
net ads join
This step creates a computer account in Active Directory. Unlike a Windows Server, you won't be able to manage the Linux computer with Group Policies, but the computer account is necessary for the Linux Server to participate in Domain authentication.
For some unexplained reason, I frequently see segmentation faults occur during the join process similar to the following:
[2007/05/17 12:34:20, 0] libads/kerberos.c:get_service_ticket(335)
get_service_ticket: kerberos_kinit_password [email protected]@COMPANY.COM failed: Client not found in Kerberos database
Segmentation fault
While it may appear to have failed, it usually works anyway. Next, we'll start winbind and test the join to see if the join was successful.
Now that the Linux Server is a member of the domain, we can start the winbind service and verify that it is able to obtain user and group information from Active Directory. Configure winbind for automatic startup and start the service:
chkconfig winbind on
service winbind start
The following commands should return a list of the Active Directory user accounts, and Active directory groups:
wbinfo -u
wbinfo -g
If these commands return users and groups, you are all set. You should be able to log in remotely through ssh, or locally, using any of the users (domain or local) that are listed in the /etc/security/system_operators file. When you log in with a domain user, a home directory should automatically be created for you.
If you get an error, wait a minute and try again. If it's still not working, you can reset everything and try joining the domain again using the following procedure:
service winbind stop
net ads leave
kdestroy
rm -rf /var/cache/samba
Now go back to step 1 of this section to try again. In my experience, it works in spite of the errors the vast majority of the time. It can take winbind half a minute or so to begin working after the service starts, so if it doesn't work at first, be patient. Once wbinfo starts returning users and groups, you are all set. I've never had any authentication problems once a server has successfully joined. After that, it just works.
You might as well start up Samba now:
chkconfig smb on
service smb start
Remember that you won't be able to write to the share, until you change the writable = no parameter to a "Yes". Only do this temporarily when you need to copy a Virtual Machine to the VMWare Server. Even though only VMWare Admins have access to the share, it's still a huge risk to leave it writeable.
Step 3: Secure the Virtual Machines
The Linux server is now a functioning member of your Active Directory Domain. All that needs to be done now, is to configure appropriate permissions on your virtual machine's files to restrict who can access them. This is done by setting the permissions on each Virtual Machine's vmx file. Here is a summary of the permissions available:
We will now configure the file system containing the virtual machines, so that it can support the types of permissions we need to set.
POSIX file permissions only allow settings for one user, one group, and everyone else. We need to enable ACL support on the file system containing the virtual machines, so that we can set ACL entries for additional users and groups. In my example, I am mounting a logical volume to /var/lib/vmware. Here is my fstab entry. Modify yours appropriately, adding acl to the options. Note that I also add noatime to increase performance by removing the last access time update that normally occurs every time a file is accessed:
/dev/rootvg/vmwarelv /var/lib/vmware ext3 noatime,acl 1 2
The file system needs to be remounted before this takes effect. You can do an online remount, which is particularly handy if you have running virtual machines that you don't want to shut down. Use the following command:
mount /var/lib/vmware -o remount,acl,noatime
We want to give root and the Domain group "VMWare Admins" full control over the VMWare file system and all Virtual Machines. To do this, run the following commands:
chmod -R 770 /var/lib/vmware
chown -R root."VMWare Admins" /var/lib/vmware
Now that ACLs are enabled, we can also use setfacl and getfacl to set additional and more granular permissions on your Virtual Machines. Let's say that we decide that members of the Help Desk should be able to connect to the Virtual Machines, and reboot them if need be. Create a "Help Desk" group in Active Directory, and give them permissions to connect and change power states to the virtual machines with this command:
setfacl -R -m g:"Help Desk":rx /var/lib/vmware
Now let's suppose that the Help Desk group is not allowed to touch domain controllers, but you do want them to be able to see whether or not the Domain Controllers are running. Let's say a Domain Controller is running in a Virtual Machine in the folder /var/lib/vmware/machines/FLHQDC03. You would restrict them to read only access like this:
setfacl -R -m g:"Help Desk":r /var/lib/vmware/machines/FLHQDC03
And let's give Members of the Developers Active directory group the ability to connect to and operate their SQL Server:
setfacl -R -m g:"Developers":rx /var/lib/vmware/machines/DEVSQL01
You can use getfacl to view permissions on an object like this:
getfacl /var/lib/vmware/machines/FLHQDC03
Check the man pages on setfacl for more information. As you can see, it is possible to set very granular permissions on your Virtual Machines with this method. These file permissions affect what users can do in the VMWare Server Console, and in the MUI Web Management interface. They also affect what users can do with the vmware-cmd command line utility. Remember that in order to allow a user to log on via ssh or onto the Linux Server's consoleand use vmware-cmd, you will have to add their Windows or Linux UserID to /etc/security/system_operators.
Conclusion
At work, I use a much more streamlined version of this document. This is my first attempt at fleshing it out into instructions that someone else can use. If you spot errors, or have suggestions, feel free to email them to me here: adam (at) Breidenbaugh (dot) net.
It is possible to perform all of these steps on a server running live Virtual Machines, without shutting anything down. Although I definitely would NOT recommend that, unless you are intimately familiar with the procedure.
A few recommendations for running VMWare Server on CentOS (this could be made into a book):