Moved to wordpress...
Due to some technical issues we had when connecting Planet FreeIPA to livejournal and LJ being seemingly obsolete, I've moved my blog to Wordpress.
Please update your bookmarks!
By logging in to LiveJournal using a third-party service you accept LiveJournal's User agreement
Due to some technical issues we had when connecting Planet FreeIPA to livejournal and LJ being seemingly obsolete, I've moved my blog to Wordpress.
Please update your bookmarks!
Many SSSD users know that SSSD supports fail over from one server to another for authentication with services like su or ssh and even autodiscovers the Kerberos servers using DNS records.
But occasionally users would ask - OK, so SSSD lets me log in with another server but I also need to use kinit manually. Does kinit use the same server SSSD used? If so, how does kinit know which KDC SSSD uses?
The SSSD actually has a plugin that is able to tell what KDC or kadmin server to use for a particular realm. When SSSD discovers a Kerberos server, it puts the IP address of that server into a file stored under the /var/lib/sss/pubconf directory. The file that stores the KDC is called kdcinfo.$REALM and the kpasswd file is called kpasswd.$REALM. When SSSD switches to another Kerberos server during a fail over operation, a new IP address is generated in these files. Also, if SSSD goes offline completely, these files are removed, so that tools using libkrb5 only rely on other means of configuration, such as the krb5.conf file.
As noted above, the kdcinfo files are only refreshed during SSSD operation, like user login. This poses a disadvantage for systems that don't perform many operations using the PAM stack, because the server that SSSD discovered might go offline without SSSD triggering a fail over operation. For these environments, it's better to disable the kdcinfo files altogether by setting the krb5_use_kdcinfo option to False and relying on krb5.conf completely. We plan on improving the kdcinfo plugin in future upstream versions so that it plays better with these kind of setups.
The SSSD kdcinfo plugin even has a man page!
echo "search test.example.com" > /tmp/testresolv.conf echo "nameserver 127.0.0.1" >> /tmp/testresolv.conf LD_PRELOAD=libresolv_wrapper.so RESOLV_WRAPPER_CONF=/tmp/testresolv.conf ./dns_unit_test
echo "SRV _kerberos._tcp.example.com kdc.example.com 88" > /tmp/fakehosts echo "A kdc.example.com 127.0.0.10" >> /tmp/fakehosts
LD_PRELOAD=libresolv_wrapper.so RESOLV_WRAPPER_HOSTS=/tmp/fakehosts ./kinit_unit_test
#include <stdlib.h> #include <unistd.h> #include <string.h> #include <stdio.h> #include <netinet/in.h> #include <arpa/nameser.h> #include <arpa/inet.h> #include <resolv.h> int main(void) { int rv; struct __res_state dnsstate; unsigned char answer[256]; char addr[64] = { 0 } ; ns_msg handle; ns_rr rr; memset(&dnsstate, 0, sizeof(struct __res_state)); res_ninit(&dnsstate); res_nquery(&dnsstate, "kdc.example.com", ns_c_in, ns_t_a, answer, sizeof(answer)); ns_initparse(answer, sizeof(answer), &handle); ns_parserr(&handle, ns_s_an, 0, &rr), 0; inet_ntop(AF_INET, ns_rr_rdata(rr), addr, sizeof(addr)); puts(addr); return 0; }
gcc rwrap_example.c -lresolv -o rwrap_example
LD_PRELOAD=libresolv_wrapper.so RESOLV_WRAPPER_HOSTS=/tmp/fakehosts RESOLV_WRAPPER_DEBUGLEVEL=4 ./rwrap_example RWRAP_TRACE(1970) - _rwrap_load_lib_function: Loaded __res_ninit from libc RWRAP_TRACE(1970) - rwrap_res_nquery: Resolve the domain name [kdc.example.com] - class=1, type=1 RWRAP_TRACE(1970) - rwrap_res_nquery: nameserver: 10.11.5.19 RWRAP_TRACE(1970) - rwrap_res_nquery: nameserver: 10.5.30.160 RWRAP_TRACE(1970) - rwrap_res_nquery: nameserver: 192.168.1.254 RWRAP_TRACE(1970) - rwrap_res_fake_hosts: Searching in fake hosts file /tmp/fakehosts RWRAP_TRACE(1970) - rwrap_res_fake_hosts: Successfully faked answer for [kdc.example.com] RWRAP_TRACE(1970) - rwrap_res_nquery: The returned response length is: 0 127.0.0.10
Centralizing sudo rules in a centralized identity store such as FreeIPA is usually a good choice for your environment as opposed to copying the sudoers files around - the administrator has one place to edit the sudo rules and the rule set is always up to date. Replication mitigates most of the single-point-of-failure woes and by using modern clients like the SSSD, the rules can also be cached on the client side, making the client resilient against network outages.
What if your identity store is Active Directory though? In this post, I'll show you how to load sudo rules to an AD server and how to configure SSSD to retrieve and cache the rules. A prerequisite is a running AD instance and a Linux client enrolled to the AD instance using tools like realmd or adcli. In this post, I'll use dc=DOMAINNAME,dc=LOCAL as the Windows domain name.
The first step is to load the sudo schema into the AD server. The schema describes the objects sudo uses and their attributes and is not part of standard AD installations. In Fedora, the file describing the schema is part of the SUDO RPM and is located at /usr/share/doc/sudo/schema.ActiveDirecto
ldifde -i -f schema.ActiveDirectory -c dc=X dc=DOMAINNAME,dc=LOCAL
In my test, I used "ADSI Edit" again. Just right-click the SUDO container, select "New->Object" and then you should see sudoRole in the list of objectClasses. Create the rule based on the syntax described in the sudoers.ldap man page; as an example, I created a rule that allows the user called "jdoe" to run less, for instance to be able to inspect system log files.dn: CN=lessrule,OU=sudoers,DC=DOMAINNAME,DC=L
objectClass: top
objectClass: sudoRole
cn: lessrule
distinguishedName: CN=lessrule,OU=sudoers,DC=DOMAINNAME,DC=L
name: lessrule
sudoHost: ALL
sudoCommand: /usr/bin/less
sudoUser: jdoe
sudoers: files sss
services = nss, pam, sudo
sudo -l
You should be able to see something like this in the output:User jdoe may run the following commands on adclient:
(lcl) /usr/bin/less
Two interesting COPR repos with SSSD packages were made available recently.
One was prepared by Stephen Gallagher and contains SSSD 1.9.x for RHEL-5. I created the other one with SSSD 1.11 built for RHEL-6. I'd love to see test reports for the RHEL-6 repo, as we are considering upgrading to 1.11 in RHEL-6.6.For more details on the repos see the announcements on sssd-devel about both Stephen's and mine repos.
If you're adding a modern Linux client to an Active Directory domain, you really should be using realmd. It's easy to use, secure and does the right thing by default.
If you haven't heard about realmd already, check out the documentation. In a nutshell, realmd makes the client enrollment as easy as:
# realm join
However, realmd depends on some software that is not available on stable platforms used in production, like RHEL-6 and its derivatives. Still, it's possible to use some of the components realmd builds on separately and have a reasonably user-friendly experience. In this blog post, I'll show you how, using a package called adcli, that is usually just a building block of realmd.
My test AD server domain is called win.example.com and the server that runs the domain is called server.win.example.com. For the test, I've used a mostly default CentOS 6.5 VM.
Typically, you'll want to point your Linux machine to the AD server for DNS:
# cat /etc/resolv.conf
nameserver 192.168.122.70
# host 192.168.122.70
70.122.168.192.in-addr.arpa domain name pointer server.win.example.com.
Start the setup by enabling the EPEL repository and installing the 'adcli' package:
# yum install adcli
You can type just 'adcli' to get an overview of what commands adcli supports. We're interested in joining the client to the AD domain in order to be able to log in as users from Active Directory.
Now you should be able to find your domain already:
# adcli info win.example.com
[domain]
domain-name = WIN.EXAMPLE.COM
domain-short = WIN
domain-forest = WIN.EXAMPLE.COM
domain-controller = SERVER.WIN.EXAMPLE.COM
domain-controller-site = Default-First-Site-Name
domain-controller-flags = pdc gc ldap ds kdc timeserv closest writable good-timeserv full-secret ads-web
domain-controller-usable = yes
domain-controllers = SERVER.WIN.EXAMPLE.COM
[computer]
computer-site = Default-First-Site-Name
As you can see, adcli was able to discover quite a few details about my test domain, so it's time to join the client:
# adcli join win.example.com
Password for Administrator@WIN.EXAMPLE.COM:
You'll be prompted for the Administrator password by default, but it's possible to specify another user with the -U option. See the adcli man page for full list of details.
The join operation creates a keytab the machine will authenticate with. When you inspect the with klist -kt, you should see several entries that contain you client hostname in some form. Here are the keytab contents on my test system:
# klist -k | head
Keytab name: FILE:/etc/krb5.keytab
KVNO Principal
---- ---------------------------------------- ----------------------------------
4 RHEL6$@WIN.EXAMPLE.COM
4 RHEL6$@WIN.EXAMPLE.COM
4 RHEL6$@WIN.EXAMPLE.COM
4 RHEL6$@WIN.EXAMPLE.COM
4 RHEL6$@WIN.EXAMPLE.COM
4 HOST/RHEL6@WIN.EXAMPLE.COM
4 HOST/RHEL6@WIN.EXAMPLE.COM
It's recommeded to also configure /etc/krb5.conf to use the AD domain:
[libdefaults]
default_realm = WIN.EXAMPLE.COM
dns_lookup_realm = true
dns_lookup_kdc = true
ticket_lifetime = 24h
renew_lifetime = 7d
forwardable = true
[realms]
WIN.EXAMPLE.COM = {
kdc = server.win.example.com
admin_server = server.win.example.com
}
[domain_realm]
.win.example.com = WIN.EXAMPLE.COM
win.example.com = WIN.EXAMPLE.COM
The final step is setting up the SSSD (or Winbind if you like) to actually make use of the keytab to resolve users. I'll show how to use the AD back end of SSSD as an example. Make sure sssd and authconfig are installed:
# yum install authconfig sssd
Unfortunately, authconfig in RHEL-6 doesn't support configuring the AD back end directly, so you'll have to do a bit of manual configuration. We can still use authconfig to set up the Name Service Switch and PAM stacks:
# authconfig --enablesssd --enablesssdauth --update
Now you should see 'sss' being present in /etc/nsswitch.conf and the pam stack configuration:
# grep sss /etc/nsswitch.conf
passwd: files sss
shadow: files sss
group: files sss
services: files sss
netgroup: files sss
The final step is to configure the SSSD itself. Open /etc/sssd/sssd.conf and define a single domain:
[sssd]
services = nss, pam, ssh, autofs
config_file_version = 2
domains = WIN.EXAMPLE.COM
[domain/WIN.EXAMPLE.COM]
id_provider = ad
# Uncomment if service discovery is not working
# ad_server = server.win.example.com
Start the SSSD and make sure it's up after reboots:
# service sssd start
# chkconfig sssd on
You should now be able to log in as an AD user just fine:
su - administrator@win.example.com
Password:
-sh-4.1$ id
uid=388000500(administrator) gid=388000513(domain users) groups=388000513(domain users),388000512(domain admins),388000518(schema admins),388000519(enterprise admins),388000520(group policy creator owners),388000572(denied rodc password replication group),388001123(supergroup) context=unconfined_u:unconfined_r:unconf ined_t:s0-s0:c0.c1023
For more information on the SSSD ad provider, see the SSSD wiki page or just sssd-ad the manual page.
id root
id Administrator@ad.example.com
id AD\\Administrator
access_provider = ad
ad_access_filter = (&(sAMAccountName=jo*)(unixHomeDirectory= *))
access_provider = ldap
ldap_access_order = filter, expire
ldap_account_expire_policy = ad
ldap_access_filter = (&(sAMAccountName=jo*)(unixHomeDirectory= *))
ldap_sasl_mech = GSSAPI
ldap_sasl_authid = CLIENT_SHORTNAME$@EXAMPLE.COM
ldap_schema = ad
This post intends to introduce a feature of SSSD, that, despite being around since the release of 1.9, is still not used as often as it should - the Active Directory backend.
Even though 1.9 was released more than a year ago, I still see many deployments configuring the pure LDAP backend when configuring an AD client machine. I'll try to explain the advantages of the AD backend compared to the LDAP backend, but in short, you should always use the AD backend when configuring SSSD with an AD server.
Below is a summary of the biggest advantages of the AD provider in my opinion. A more detailed description of the new features will follow in a next blog post.
# realm join ad.example.com
Even if you opt for manual configuration or have a client already joined to a domain, the simplified configuration might be of interest. While AD can be treated just as an LDAP/Kerberos combo, several configuration options need to be tailored in order to match what is stored on the server side.
For example, user objects in AD are of objectclass user. In contrast, the LDAP provider defaults to posixAccount. Active Directory is also case insensitive, which requires the use of the "case_sensitive" option. The AD provider already comes with all the defaults set out of the box, so the previously complex configuration can be simplified to:
[domain/ad.example.com]
id_provider = ad
The example above assumes that UIDs and GIDs are mapped automatically by the SSSD and the AD servers are autodiscovered from DNS.
In Fedora 17, we are introducing a new feature - the SSSD gets an ability to cache automounter maps and map entries stored in a remote database the SSSD can access, which is mostly LDAP. Because there is no user-facing documentation available to describe how this feature works, I decided to introduce it in a little more detail in this blog post. The post is quite verbose as it explains the native LDAP case as well - if you are familiar with automounter and how automounter is configured to access map in LDAP, feel free to skip to the last section.
The automounter is a very useful software that lets the user access removable media or network shares without explicitly mounting them and unmounts them when they are not needed. The user would simply access the directory where the remote file system is located and the automounter then takes care of mounting the correct share with the desired options. Obviously, the automounter needs to know which share should be mounted from which location. The configuration files for autofs are called maps and are similar to /etc/fstab at a high level. The main, top-level map is called the master map and is typically located in /etc/auto.master. There's quite a lot of resources on automounter on the Internet, the reader may continue to the Red Hat Documentation, for example.
A hands-on example: automounter configured with flat files/shares/ /etc/auto.shares
pub -fstype=nfs filer.example.com:/pub
mkdir /shares
service autofs start
When the maps are stored in files, the administrator faces a problem on a large network - he needs to distribute the files to all the hosts that he manages on the network. One possible solution is to use a tool such as puppet or cfengine to help distributing the files. Another solution is to get rid of the files altogether and fetch the maps from a centralized directory, LDAP in particular. The automounter then only needs to know the location to download the maps from.
A hands-on example: automounter configured to access maps in LDAPdn: cn=automount,dc=example,dc=com
objectClass: nsContainer
objectClass: top
cn: automount
dn: automountMapName=auto.master,cn=automoun t,dc=example,dc=com
objectClass: automountMap
objectClass: top
automountMapName: auto.master
dn: automountMapName=auto.shares,cn=automoun t,dc=example,dc=com
objectClass: automountMap
objectClass: top
automountMapName: auto.shares
dn: automountKey=/shares,automountMapName=au to.master,cn=automount,dc=example,dc=com
objectClass: automount
objectClass: top
automountKey: /shares
automountInformation: auto.shares
dn: automountKey=pub,automountMapName=auto.s hares,cn=automount,dc=example,dc=com
objectClass: automount
objectClass: top
automountKey: pub
automountInformation: filer.example.com:/pub
description: pub
LDAP_URI=ldap://ldap.example.com
SEARCH_BASE="cn=automount,dc=example,dc=c om"
# The schema attributes are present in the config file, just uncomment them
MAP_OBJECT_CLASS="automountMap"
ENTRY_OBJECT_CLASS="automount"
MAP_ATTRIBUTE="automountMapName"
ENTRY_ATTRIBUTE="automountKey"
VALUE_ATTRIBUTE="automountInformation"
[autofs]
services = nss,pam,autofs
ldap_autofs_search_base="cn=automount,dc=e xample,dc=com"
automount: files sss
service sssd restart
ldap_autofs_map_object_class="automountM ap"
ldap_autofs_entry_object_class="automoun t"
ldap_autofs_map_name="automountMapName"
ldap_autofs_entry_key="automountKey"
ldap_autofs_entry_value="automountInform ation"