Here's a solution to enable Active Directory accounts to logon to your linux machines. Many companies are now starting to have more Linux machines in their estate. Traditionally, users who needed access to these machines had an account created locally on each machine. This becomes difficult to manage if you have many Linux machines and many users. Keeping passwords in sync becomes a problem for users, need I go on. Having a central store for user accounts and passwords is a no brainer. Many companies already have such a store: Active Directory. AD domain controllers provide LDAP and Kerberos services that are compatible with the Kerberos and LDAP clients found on Linux. At least the versions of Linux that I've tested this solution with (Fedora 12, and RedHat Enterprise Server 5.2).
Note: This article is for older versions of Fedora/RedHat Linux. Please see Fedora 16 - Logging into Active Directory for more recent configuration information.
New on ITAdminTools.com
ITAdminTools now offers Linux Active Directory User Manager, the GUI for managing Linux users in Active Directory.
ITAdminTools now offers Linux Active Directory User Manager, the GUI for managing Linux users in Active Directory.
The solution uses LDAP to lookup user information from AD, and uses Kerberos to authenticate users. Below are the configuration files neccesary to make it work.
Configuring Kerberos
The first file to edit is /etc/krb5.conf which contains the definition of your AD domain.
[logging]
default = FILE:/var/log/krb5libs.log kdc = FILE:/var/log/krb5kdc.log admin_server = FILE:/var/log/kadmind.log
[libdefaults]
default_realm = MYDOMAIN.COM dns_lookup_realm = false dns_lookup_kdc = false ticket_lifetime = 24h renew_lifetime = 7d forwardable = yes
[realms]
MYDOMAIN.COM = { kdc = mydomain.com:88 admin_server = mydomain.com:749 }
[domain_realm]
mydomain.com = MYDOMAIN.COM .mydomain.com = MYDOMAIN.COM
The key items here are lines that contain MYDOMAIN.COM. Just replace with whatever your domain is. As soon as you've saved this file, you should be able to test Kerberos by acquiring a Kerberos ticket. Of course your Linux system must be able to resolve the DNS name of your domain, so make sure that it's configured to point to DNS servers that can resolve the AD DNS records. To test, type the following in a terminal window:
kinit [email protected]
You should be prompted to enter the AD password for that user. You can then use the klist command to view the ticket cache, and the kdestroy command to get rid of the ticket.
Next, let's configure the LDAP configuration by editing the /etc/ldap.conf file. There's also a copy of the ldap.conf file in /etc/openldap/ldap.conf so whenever you make changes to one, copy it over to the other. Some of the tools use the copy in /etc, others use the copy in /etc/openldap.
#basic settings ldap_version 3 network_timeout 20 bind_policy soft #debug 2
# your AD config uri ldaps://mydc01.mydomain.com ldaps://mydc02.mydomain.com ldaps://mydc03.mydomain.com binddn cn=myLDAPlookupUser,cn=users,dc=mydomain,dc=com bindpw mySecret base dc=mydomain,dc=com scope sub referrals off
#pam settings pam_login_attribute sAMAccountName pam_filter objectCategory=User pam_password ad pam_groupdn cn=myLinuxUsers,cn=users,dc=mydomain,dc=com pam_member_attribute member
#nss settings nss_initgroups_ignoreusers root,bin,daemon,adm,lp,sync,shutdown,halt,mail,uucp,operator,games,gopher,ftp,nobody,vcsa,avahi-autoipd,ntp,dbus,rpc,rpcuser,nfsnobody,nscd,tcpdump,avahi,apache,openvpn,rtkit,mailnull,smmsp,nm-openconnect,sshd,smolt,backuppc,haldaemon,pulse,gdm,abrt,mysql nss_base_passwd dc=mydomain,dc=com?Sub nss_base_shadow dc=mydomain,dc=com?Sub nss_base_group dc=mydomain,dc=com?Sub nss_map_objectclass posixAccount User nss_map_objectclass shadowAccount User nss_map_objectclass posixGroup Group nss_map_attribute uid sAMAccountName nss_map_attribute cn sAMAccountName nss_map_attribute uniqueMember member nss_map_attribute homeDirectory unixHomeDirectory nss_map_attribute gecos name
#ssl settings tls_cacertdir /etc/pki/tls tls_cacertfile /etc/pki/tls/myrootcert.pem tls_checkpeer no ssl on
There's lots of information in this file to discuss. Let's take it one line at a time.
network_timeout 20: As ou can see, I've defined three domain controllers in the uri line. The network timeout allows the LDP client to move onto the next domain controller in a timely fashion if one is unresponsive. You can adjust this setting as you see fit.
bind_policy soft: I can't stress enough how important this line is! Don't forget to put it in! Don't fat finger it! The default is bind_poicy hard, which, if there's anything wrong and LDAP isn't working, your whole Linux box willl slow to an absolute crawl, you might not ever be able to login again, and you might be completely hosed and require a rebuild.
debug: If things aren't working, you can enable debug. There are various levels, I find 2 is a good setting. As you can see, I have it commented out with a # in front of it.
uri: this is the LDAP path to your AD domain controller(s). Do not use quotes. Seperate multiple DC's with a space. If you're going to use secure LDAP (LDAP overl SSL), use ldaps:// as the prefix, otherwise use ldap://.
binddn: This is the distinguished name of the user that you'll use to connect to AD to lookup information about users who are trying to logon to the Linux box. This should not be the account of a user, but rather a dedicated account for ldap lookups. The account should be set so that its password doesn't expire like regular users. Otherwise, the account needs no special privileges in AD.
bindpw: This is the password of the user mentioned above.
base: This is the distinguished name of the domain or organizational unit (OU) where your users are located within AD. If all of your users are in a specific OU, then specify that OU for the base. That will limit the scope of LDAP queries and speed things up.
scope: This can be set to one, base, or sub. sub includes any sub-OU's within the domain or OU specified in base.
referrals: AD can contain numberous directory partitions or contexts. To speed things up, set referrals off to keep LDAP from seaching every stinkin context for a user that doesn't exist.
The next section of the ldap.conf file is related to PAM (Pluggable Authentication Manager). We'll configure PAM to use LDAP a little later, but the following lines configure PAM's ldap module.
pam_login_attribute: This defines which AD attribute is used for the username. Typically, this should be the sAMAccountName attribute (that is the Windows user name).
pam_filter: This is an LDAP query filter that limits the scope of the seach for the user. The tighter you can filter the search, the faster LDAP will work, and the less load you will put on your domain controllers.
pam_groupdn: Specifies the distinguished name of an AD group, that the user must be a member of in order to login to the Linux server. If you don't add this line, then all of your AD users will be able to login.
pam_member_attribute: Specifies the AD attribute of the group mentioned above, that should contain the list of group members.
The next section contains the NSS_LDAP settings. Note that some of the information here appears to be redundant, because it is. Several Linux components (openldap, PAM, and NSS) are using the ldap.conf as their config file).
nss_initgroups_ignoreusers: You should put any local accounts (especially root) in this line, so that NSS knows not to do an LDAP query when these accounts login. I've included all of the local accounts that are created by default in Fedora 12.
nss_base_passwd: This is the distinguished name of the domain or OU where your users are located (same as base), followed by the search scope, seperated by a ?.
nss_map_objectclass: This tells NSS to use AD object classes (users and groups) rather than traditional LDAP object classes.
nss_map_attribute: This tells NSS to use AD attributes rather than traditional LDAP attributes.
The final section relates to SSL settings, which requires a bit of discussion.
LDAP, by default will send a username and password across the network unencrypted, so a sniffer can capture the packets and get the password. This isn't a huge deal in this case, because we're going to use Kerberos to authenticate users, and Kerberos not only encrypts its traffic, but also doesn't really pass the user's password over the network (it sends a hash instead). However, the binddn user that we're using to connect to AD will have its password sent over the network in clear text, so it's possible for that password to be intercepted. If that's a concern, then you can implement secure LDAP.
Secure LDAP uses SSL to setup an encrypted tunnel to send the LDAP traffic through. In order for you to implement SSL, you need to deploy a certificate to your domain controllers, and that means that you either have to have an internal certificate authority (CA) to issue certificates, or you have to buy commercial certificates from a vendor like Verisign or Thawte. Once you have certificates deployed on your domain controllers, you can communicate with your domain controllers using secure LDAP.
If you don't use secure LDAP, the uri line in your ldap.conf should use the prefix ldap:// rather than ldaps://, and the last few lines of the file should be commented out. I recommend that you configure LDAP without SSL at first to get things working, then configure SSL afterwords.
Besides encrypting the traffic, SSL also verifies the authenticity of the server you're communicating with. In order for this to work, you must trust the certificate authority that issued the certificate that is on your domain controllers. If you used a commercial certificate, then it's likely that your Linux server already trusts the vendor, because a copy of the vendor's root certificate is likely already on your Linux server. If you used an internal CA, then you'll need to put a copy of your internal root certificate on your Linux server. The certificate should be in saved in Base-64 encoded X.509 format, and saved with a .pem extension (e.g. myRootCaCert.pem).
Once you have a copy of the root CA certificate, you need to figure out where to put it. To do that, run the following command and take note of the OPENSSLDIR path:
openssl version -a
Now copy the cert into that directory. Next, since Linux uses a hash of the certificate to find the certificate, we need to create a link to the certificate using the hash. To get the hash, use this command:
openssl x509 -noout -hash -in myRootCaCert.pem
The command will return hex digits such as efe71310. Use these digits to create a symbolic link to the certificate. Create the symbolic link in the directory above, like so (using your hash of course):
ln -s myRootCaCert.pem efe71310.0
The trailing .0 is required because it's possible for multiple certs to have the same hash, so you must put an enumerator at the end.
OK, now that you have successfully added your root cert to your server, you should now be able to configure secure LDAP. Let's go back to the ldap.conf and enable it. To do that, simply use the ldaps:// prefix in your uri line, and uncomment the last few lines of the file. The lines specify the location of the certificates and enable SSL. Remember to copy your changes from /etc/ldap.conf to /etc/openldap/ldap.conf.
Next we need to configure PAM, to tell PAM to use LDAP and Kerberos for authentication. Edit the /etc/pam.d/system-auth file as shown below:
#%PAM-1.0 # 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_krb5.so use_first_pass 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 [default=bad success=ok user_unknown=ignore] pam_ldap.so account [default=bad success=ok user_unknown=ignore] pam_krb5.so account required pam_permit.so
password requisite pam_cracklib.so retry=3 password sufficient pam_unix.so md5 shadow nullok try_first_pass use_authtok password sufficient pam_krb5.so 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_mkhomedir.so silent skel=/etc/skel/ umask=0022 session [success=1 default=ignore] pam_succeed_if.so service in crond quiet use_uid session required pam_unix.so session optional pam_krb5.so session optional pam_ldap.so
Notice that a line for LDAP (pam_ldap.so) and a line for Kerberos (pam_krb5.so) have been added to each section (auth, account, password and session), and also I've added a line in the session section that automatically makes a homedir for the user the first time they login (pam_mkhomedir.so).
Next, let's modify NSS to use LDAP for user information lookups. Edit the /etc/nsswitch.conf as follows:
# # /etc/nsswitch.conf # # An example Name Service Switch config file. This file should be # sorted with the most-used services at the beginning. # # The entry '[NOTFOUND=return]' means that the search for an # entry should stop if the search in the previous entry turned # up nothing. Note that if the search failed due to some other reason # (like no NIS server responding) then the search continues with the # next entry. # # Legal entries are: # # nisplus or nis+ Use NIS+ (NIS version 3) # nis or yp Use NIS (NIS version 2), also called YP # dns Use DNS (Domain Name Service) # files Use the local files # db Use the local database (.db) files # compat Use NIS on compat mode # hesiod Use Hesiod for user lookups # [NOTFOUND=return] Stop searching if not found so far #
# To use db, put the "db" in front of "files" for entries you want to be # looked up first in the databases # # Example: #passwd: db files nisplus nis #shadow: db files nisplus nis #group: db files nisplus nis
passwd: files ldap shadow: files ldap group: files ldap
#hosts: db files nisplus nis dns hosts: files dns
# Example - obey only what nisplus tells us... #services: nisplus [NOTFOUND=return] files #networks: nisplus [NOTFOUND=return] files #protocols: nisplus [NOTFOUND=return] files #rpc: nisplus [NOTFOUND=return] files #ethers: nisplus [NOTFOUND=return] files #netmasks: nisplus [NOTFOUND=return] files
bootparams: nisplus [NOTFOUND=return] files
ethers: files netmasks: files networks: files protocols: files rpc: files services: files
netgroup: files ldap
publickey: nisplus
automount: files ldap aliases: files nisplus
Notice that I've added the word ldap to the following lines: passwd, shadow, group, netgroup and automount.
One more thing to tweak, assuming that you plan to use SSH to logon to the Linux server remotely. Let's edit the /etc/ssh/sshd_config file.
# $OpenBSD: sshd_config,v 1.80 2008/07/02 02:24:18 djm Exp $
# This is the sshd server system-wide configuration file. See # sshd_config(5) for more information.
# This sshd was compiled with PATH=/usr/local/bin:/bin:/usr/bin
# The strategy used for options in the default sshd_config shipped with # OpenSSH is to specify options with their default value where # possible, but leave them commented. Uncommented options change a # default value.
#Port 22 #AddressFamily any #ListenAddress 0.0.0.0 #ListenAddress ::
# Disable legacy (protocol version 1) support in the server for new # installations. In future the default will change to require explicit # activation of protocol 1 Protocol 2
# HostKey for protocol version 1 #HostKey /etc/ssh/ssh_host_key # HostKeys for protocol version 2 #HostKey /etc/ssh/ssh_host_rsa_key #HostKey /etc/ssh/ssh_host_dsa_key
# Lifetime and size of ephemeral version 1 server key #KeyRegenerationInterval 1h #ServerKeyBits 1024
# Logging # obsoletes QuietMode and FascistLogging #SyslogFacility AUTH SyslogFacility AUTHPRIV #LogLevel INFO
# Authentication:
#LoginGraceTime 2m #PermitRootLogin yes #StrictModes yes #MaxAuthTries 6 #MaxSessions 10
#RSAAuthentication yes #PubkeyAuthentication yes #AuthorizedKeysFile .ssh/authorized_keys #PubkeyAgent none #PubkeyAgentRunAs nobody
# For this to work you will also need host keys in /etc/ssh/ssh_known_hosts #RhostsRSAAuthentication no # similar for protocol version 2 #HostbasedAuthentication no # Change to yes if you don't trust ~/.ssh/known_hosts for # RhostsRSAAuthentication and HostbasedAuthentication #IgnoreUserKnownHosts no # Don't read the user's ~/.rhosts and ~/.shosts files #IgnoreRhosts yes
# To disable tunneled clear text passwords, change to no here! #PasswordAuthentication yes #PermitEmptyPasswords no PasswordAuthentication yes #PasswordAuthentication no
# Change to no to disable s/key passwords #ChallengeResponseAuthentication yes ChallengeResponseAuthentication no
# Kerberos options #KerberosAuthentication no #KerberosOrLocalPasswd yes #KerberosTicketCleanup yes #KerberosGetAFSToken no
# GSSAPI options GSSAPIAuthentication no #GSSAPIAuthentication yes #GSSAPICleanupCredentials yes #GSSAPICleanupCredentials yes #GSSAPIStrictAcceptorCheck yes #GSSAPIKeyExchange no
# Set this to 'yes' to enable PAM authentication, account processing, # and session processing. If this is enabled, PAM authentication will # be allowed through the ChallengeResponseAuthentication and # PasswordAuthentication. Depending on your PAM configuration, # PAM authentication via ChallengeResponseAuthentication may bypass # the setting of "PermitRootLogin without-password". # If you just want the PAM account and session checks to run without # PAM authentication, then enable this but set PasswordAuthentication # and ChallengeResponseAuthentication to 'no'. #UsePAM no UsePAM yes
# Accept locale-related environment variables AcceptEnv LANG LC_CTYPE LC_NUMERIC LC_TIME LC_COLLATE LC_MONETARY LC_MESSAGES AcceptEnv LC_PAPER LC_NAME LC_ADDRESS LC_TELEPHONE LC_MEASUREMENT AcceptEnv LC_IDENTIFICATION LC_ALL LANGUAGE AcceptEnv XMODIFIERS
#AllowAgentForwarding yes #AllowTcpForwarding yes #GatewayPorts no #X11Forwarding no X11Forwarding yes #X11DisplayOffset 10 #X11UseLocalhost yes #PrintMotd yes #PrintLastLog yes #TCPKeepAlive yes #UseLogin no #UsePrivilegeSeparation yes #PermitUserEnvironment no #Compression delayed #ClientAliveInterval 0 #ClientAliveCountMax 3 #ShowPatchLevel no #UseDNS yes #PidFile /var/run/sshd.pid #MaxStartups 10 #PermitTunnel no #ChrootDirectory none UseDNS no
# no default banner path #Banner none
# override default of no subsystems Subsystem sftp /usr/libexec/openssh/sftp-server
# Example of overriding settings on a per-user basis #Match User anoncvs # X11Forwarding no # AllowTcpForwarding no # ForceCommand cvs server
The imporatant lines here are:
PasswordAuthentication yes
ChallengeResponseAuthentication no
GSSAPIAuthentication no
UsePAM yes
UseDNS no
Finally, we need to populate the necessary attributes in the AD user's account that Linux is looking for. In our ldap.conf, we've specified sAMAccountName as our uid, so that's already populated. However, we need to populate the uidNumber, gidNumber, loginShell, and unixHomedirectory attrbutes. Since these attributes aren't visible in the Active Directory Users and Computers gui, we'll use adsiedit to populate them. ADSIEDIT is a tool that comes with the support tools which are located on the Windows 2003 CD.
New on ITAdminTools.com
ITAdminTools now offers Linux Active Directory User Manager, the GUI for managing Linux users in Active Directory.
ITAdminTools now offers Linux Active Directory User Manager, the GUI for managing Linux users in Active Directory.
You need to populate the attrbutes as follows:
uidNumber - pick a unique number for each user.
gidNumber - pick a number and create a group with this gid on the Linux server. Maybe call the group ADACCESS?
loginShell - /bin/bash is typical for Linux
unixHomedirectory - /home/username would be typical.
Don't forget to add the user to the PAM group we configured earlier. Now that your user's attributes are populated, assuming you didn't fat finger any of the files, you should be able to login to the Linux server using your AD account. If things don't work as expected, look at your logs (/var/log/messages and /var/log/secure) . If necessary, enable debug in the ldap.conf.
Good luck. This post is a bit of a work in progress. I'll do my best to answer any questions.
2 comments:
Hi Brian,
This is a very cool article! With the need to integrate Linux based hosts in AD environments on the rise, it seems like your solution could actually help quite a few admins out there - nice work!
By the way, I run a blog on Free Active Directory Reporting Tools, and if you have any suggestions for any helpful AD tools that are FREE, I hope you'll let me know, as I would like to like to blog about it for everyone's benefit.
Thanks again, and good luck - nice work again!
Adios,
Marc
Thanks,
- Marc
Thanks Marc. I appreciate the feedback. I'll send any tools that I find your way.
Brian
Post a Comment