Running Kerberos with Zimbra Collaboration Suite: Difference between revisions
Line 250: | Line 250: | ||
'''''Note:''' Method 2 will overwrite Method 1. If the account has a '''zimbraForeignPrincipal''' in the form of '''kerberos5:<kerberos5-principal>''', the system will resolve the Kerberos principal using Method 2. | '''''Note:''' Method 2 will overwrite Method 1. If the account has a '''zimbraForeignPrincipal''' in the form of '''kerberos5:<kerberos5-principal>''', the system will resolve the Kerberos principal using Method 2. | ||
Now, you | Now, you can authenticate to ZCS by Kerberos protocol. You can test by this way (assume ZCS IMAP port is 7143): | ||
$gsasl --connect zcs.example.com:7143 -a user1@zcs.example.com -d | |||
If authentication fails, try to use "kinit" to get the user credential in client.example.com and imap service credential in zcs.example.com. | |||
==Configure ZCS Proxy (Nginx)== | ==Configure ZCS Proxy (Nginx)== |
Revision as of 09:58, 17 November 2010
Article Information |
---|
This article applies to the following ZCS versions. |
This guide contains instructions for installing, configuring, running, and troubleshooting Kerberos with Zimbra Collaboration Suite. The concepts and descriptions might be not precise, just for general understanding of the mechanisms, steps and usages. For a more detailed reference of Kerberos, consult MIT's Kerberos V5 Admin Guide.
Introduction
General Knowledge of Kerberos Authentication
You may try to authenticate yourself into some service server via simply username/password login or other similar manner such as PLAIN or CRAM-MD5. In these cases you prove to the service server your identity. The server confirms this and authorize you with the requested services. However, in Kerberos protocol, a trusted third party is introduced, which generates "tickets", which hold credentials to both the user and service server. After gaining the credentials, both the user and service server can prove he is who he claims to be. Then they exchange some messages and finish the mutual authentication. This is the general steps of Kerberos authentication protocol.
In implementation, the trusted third party is the KDC (Kerberos Distribution Center) server. It holds a database (comprised of several regular files) of principals and keys.In the Kerberos world, everyone, including users, services, hosts, etc, has a principle associated with it. Principals should be global unique. Each principal has several components, which can be a username, service name, host name or realm. For example, imap/example.com@EXAMPLE.COM is a valid principal, in which "imap" is the service name, "exmaple.com" is the host name who provides this service, and "EXAMPLE.COM" is the realm. Principal is case sensitive. Traditionally, realm is a capitalized domain name like string. Meanwhile, each principal is associated with a key.
A key is a string generated by the password. You can get a ticket contain a principal by giving that password. Also, you can write the keys into the keytabfiles and authenticate with them. A keytab file can contain multiple principals' keys with various encryption types. For example, if you have M principals and N encryption types, you may have M*N entries in a keytab file. Therefore you can consider keytab files and password equivalent. However, it's rather noteworthy that if a key is written into keytabfile, the password is no longer effective.
After authenticating to KDC, the corresponding credential is retrieved and cached locally. In MIT Kerberos implementation, it's cached in a regular file called /tmp/krb5cc_<uid>.Other implementations may cache it in the memory. Each credential has an expired time, commonly several hours or 1 day. Before that you can get it from cache without sending request to KDC. Note the UNIX user you used to get and use the credential. If you get it by root (e.g. sudo), and then use it with a normal user with uid 1000, it will fail because the credential you want to use is in krb5cc_0 rather than krb5cc_1000.
KDC reads the configure file "kdc.conf" to setup itself. This config tells which ports to listen, where the database files located, what encryption types should be supported and so on. KDC also reads "krb5.conf" to decide what the default realm is, how to write logs, ... The client and service server are all clients of KDC. They need to read krb5.conf to decide what the default realm is and where KDC is (address and port). Here you can set KDC for each realm. krb5.conf used by Kerberos server and client are often same.So you can config a valid krb5.conf and copy it to everywhere.
Kerberos Executives
Here are the executives of Kerberos implementation.
Name | Description |
---|---|
krb5kdc | KDC server. Default listen on 88, 750 ports |
kadmin.local | Manage principal database by directly manipulate database files. Only work in the machine where those files locate. |
kadmin | Remotely manage principal database, require kadmind. |
kadmind | Kerberos managment server. Default listen on 749 port. |
kdb5_util | Kerberos database maintainance utility. Can create, destroy, load a database. |
kinit | Authenticate to KDC, get the credential. |
klist | Show the entries in the credential cache or keytab files |
There are some other executives for advanced functions, not necessary to introduce here.
Configuration Overview
The picture in the right shows the overview of ZCS with Kerberos authentication support. There are 3 hosts in logic. "kerberos.example.com" holds KDC server, principal database and configs; "client.example.com" holds the client applications which initiates the authentication; "zcs.example.com" runs ZCS servers. Although they are in logic 3 separated hosts, you can choose to install all of them in the same host like what most developers do.In the rest of this article, I'll use these host names to illustrate the examples.
Install Kerberos
MIT Kerberos
Download Kerberos from Massachusetts Institute of Technology (MIT) at http://web.mit.edu/Kerberos/. Install Kerberos, following the instructions provided in MIT's Kerberos V5 Installation Guide. Normally you just run the command "./configure && make && make install". The build process might report some missing dependency such as "bison (yacc)". The Kerberos executive will be generated in /usr/local/bin and /usr/local/sbin. The most important one is /usr/local/sbin/krb5kdc. It's the KDC server.
After that, you need to copy sample krb5.conf and kdc.conf from <krb-source-root>/src/config-files by yourself. Copy krb5.conf to /etc/krb5.conf; then copy kdc.conf to /usr/local/var/krb5kdc/kdc.conf. /usr/local/var/krb5kdc is also the default location of principal database files.
MIT Kerberos Packages from Ubuntu
If using Ubuntu, you can choose to apt-get install the following packages: krb5-admin-server, krb5-kdc, krb5-config, krb5-user, krb5-clients. For Kerberos clients, no need to install admin server and KDC. In this way, the default location of kdc.conf is /etc/krb5kdc; the default location of principal database files is /var/lib/krb5kdc. Meanwhile, the KDC executive name is /etc/init.d/krb5-kdc.
Heimdal
TODO
Other Related Packages
If KDC and Kerberos clients are planed to run in different hosts, it's necessary to install NTP (Network Time Protocol) packages to make time synchronized. Kerberos protocol requires that time synchronization to improve security and convenience. But if all are going to be installed in the same host, no need to do this.
If want to do some test, you can install gsasl (GNU SASL). It contains APIs and sample client/server to use Kerberos authentication.
Configuration
Prepare Valid Host Name
One of the most important thing to configure a valid kerberos environment is to configure the correct host name. This is because ZCS will generate a request for service principal, which contains a component of host name (e.g. imap/zcs.exmaple.com@EXAMPLE.COM). Then KDC will try to find this principal in its local database. Therefore, what the client requests and what is held in KDC database have to be exactly match.
Commonly, Kerberos suggests to use the FQDN (full qualified domain name) to make the principal. However in the reality, ZCS always uses the local config "zimbra_server_hostname" for this purpose. You can see this config by typing (assuming pwd is /opt/zimbra):
$bin/zmlocalconfig | grep zimbra_server_hostname
and change this config by:
$bin/zmlocalconfig -e zimbra_server_hostname=<new host name> $bin/zmlocalconfig -I
where "-I" is to make this change effective for ZCS.
Besides, if ZCS is built from source, this config is coming from the value of environment variable "ZIMBRA_HOSTNAME". If this variable unset, the result of command "hostname" is used. I suggest to set ZIMBRA_HOST to match the principals to be defined.
Another worthy noting is to make hostname's forward and reverse lookup is correct. This is the issue of network administrator if you are using a DNS service. Consult them to define your FQDN and static IP. If you just want to try in your host without bothering others, you can use /etc/hosts file to achieve this. Just add a line like this:
<ip> <FQDN> <hostname>
For example, in the host "zcs.example.com", you need to add this line:
179.16.143.20 zcs.example.com zcs
A common mistake is to add the FQDN to the ip "127.0.0.1" or "127.0.1.1", which might be resolved as hostname "localhost". In this case,the reverse lookup result is different with the forward one, which might incur some confusing error report.
In the following sections, 3 FQDN ("kdc.example.com","client.example.com" and "zcs.example.com") are employed.
Configure Kerberos
For the Kerberos client side, install the /etc/krb5.conf file on any client machines using Kerberos, including all of the Zimbra Mailbox servers. The content of krb5.conf should be like this:
[libdefaults] default_realm = EXAMPLE.COM [realms] EXAMPLE.COM = { kdc = kdc.example.com:88 admin_server = kdc.example.com:749 default_domain = example.com } [domain_realm] example.com = EXAMPLE.COM .example.com = EXAMPLE.COM
The key point of this config is defining the map between realms and KDC servers. The [realms] section indicates where a request for a specified realm (here is EXAMPLE.COM) should be sent to. [domain_realm] illustrates the map between domain names and realm names.default_realm will be appended if no realm is specified. For example, if you request a credential with principal "user1" with kinit command, it will ask for "user1@EXAMPLE.COM".
In the Kerberos server side (where KDC located),"/etc/krb5.conf" is also necessary. For example, if you want to add or get a principal but without specifying the realm, the default_realm will be appended. Meanwhile, I suggest to add the logging section to detect errors.
[logging] kdc = FILE:/var/log/krb5kdc.log admin_server = FILE:/var/log/kadmin.log default = FILE:/var/log/krb5lib.log
Of course, you can write all of these in one krb5.conf and copy it to any machine you want to deploy kerberos. The kerberos commands will load the necessary config from this file and ignore they don't need.
KDC server also needs "kdc.conf", which looks like this:
[kdcdefaults] kdc_ports = 88,750 [realms] EXAMPLE.COM = { database_name = /usr/local/var/krb5kdc/principal admin_keytab = /usr/local/var/krb5kdc/kadm5.keytab acl_file = /usr/local/var/krb5kdc/kadm5.acl dict_file = /usr/local/var/krb5kdc/kadm5.dict key_stash_file = /usr/local/var/krb5kdc/.k5.EXAMPLE.COM kadmind_port = 749 max_life = 10h 0m 0s max_renewable_life = 7d 0h 0m 0s master_key_type = des3-hmac-sha1 supported_enctypes = des3-hmac-sha1:normal des-cbc-crc:normal }
It controls which ports to be listened and where the local database related files locate. Just make sure these locations are valid. These files are generated by "kdb5_util". Type this command:
$sudo kdb5_util create -s
If not specify a realm, the database files of default realm "EXAMPLE.COM" are generated. A password is required to access these files. "-s" means to generate a stash file to avoid manually input password when start KDC server. It's like the keytab file, the equivalent of password.
Finally, start KDC server:
$sudo /usr/local/sbin/krb5kdc
If nothing is output to the bash, it means KDC starts successfully. Otherwise, check the log of KDC to figure out what's wrong.
Add Principals and Keytabs
Creating Principals
For each ZCS server, create a service principal for the Zimbra services.Here uses IMAP as the example This should be of the form imap/<FQDN>@<realm> where <FQDN> is the value of ZCS local config "zimbra_server_hostname". Meanwhile, create principal for each user.
You can use the command "kadmin.local" to add these principals. This command can only be used in the host where principal database files locate (here, should be "kdc.example.com"). If want to manage the principals in remote hosts, start "kadmind" server and use command kadmin to do it. Here only shows the example of kadmin.local:
$ kadmin.local Authenticating as principal root/admin@EXAMPLE.COM kadmin.local: addprinc -randkey imap/zcs.example.com@EXAMPLE.COM WARNING: no policy specified for imap/zcs.example.com@EXAMPLE.COM; defaulting to no policy Principal "imap/zcs.example.com@EXAMPLE.COM" created. kadmin.local: addprinc user1@EXAMPLE.COM WARNING: no policy specified for user1@EXAMPLE.COM; defaulting to no policy Enter password for principal "user1@EXAMPLE.COM": Re-enter password for principal "user1@EXAMPLE.COM": Principal "user1@EXAMPLE.COM" created.
When type "kadmin.local", the shell enters an interaction mode. Then use the sub command "addprinc" to add a new principal. The parameter "-randkey" allows generating a random key. Without it, you have to type password for the principals added. But as ZCS does the authentication with the keytab file, so the content of key is not important at all. For user principal, here we use the password to generate key.This password should match the one for its ZCS account's password. You can also generate keytab file for user principal. But remember, once keytab files are generated, the password will lose effect.
Besides "addprinc", you can use sub command "listprincs" show the list of existing principals, "getprinc" to get the detailed information of a specified princal, and "delprinc" to delete some of them.
Policy is not important here.It's useful to batch generate principals of the same kind. Just ignore it for now.
Creating a Local Keytab File for the Principal
After adding the principals, you need to generate the corresponding keytab files. This is also done by the command "kadmin.local". If users decide to authenticate with keytab, user keytab is also necessary. Here take IMAP and user1 as the exmaple.
$ kadmin.local Authenticating as principal root/admin@EXAMPLE.COM with password. kadmin: ktadd -keytab ~/krb5-zcs.keytab imap/zcs.example.com@EXAMPLE.COM Entry for principal imap/zcs.example.com@EXAMPLE.COM with kvno 3, encryption type Triple DES cbc mode with HMAC/sha1 added to keytab WRFILE:/home/jxing/krb5-zcs.keytab. Entry for principal imap/zcs.example.com@EXAMPLE.COM with kvno 3, encryption type DES cbc mode with CRC-32 added to keytab WRFILE:/home/jxing/krb5-zcs.keytab kadmin: ktadd -keytab ~/krb5-usr.keytab user1@EXAMPLE.COM Entry for principal imap/zcs.example.com@EXAMPLE.COM with kvno 3, encryption type Triple DES cbc mode with HMAC/sha1 added to keytab WRFILE:/home/jxing/krb5-usr.keytab. Entry for principal imap/zcs.example.com@EXAMPLE.COM with kvno 3, encryption type DES cbc mode with CRC-32 added to keytab WRFILE:/home/jxing/krb5-usr.keytab.
Copy the krb5-zcs.keytab to defaultly is "/opt/zimbra/conf/krb5.keytab" in each ZCS server. Keytab files are commonly generated by root (sudo), and has the permission 600. So use "chown" and "chmod" to change it to make sure this file can be read by ZCS. Otherwise, ZCS may report it can't find this file. In the production scenario, this keytab file's owner user and group should be zimbra:zimbra. In the dev environment, it depends on the user who starts ZCS.
Similarly, copy krb5-usr.keytab to "/etc/krb5.keytab" in each host user1 can authenticate himself, and adjust its permission as need. /etc/krb5.keytab is the default location of Kerberos client to find keytab file. If want to specify other location, use the environment variable "KRB5_KTNAME" (By the way, ZCS proxy employs this way to specify the location).
Now you can test this by the two sample utilities, sserver and sclient. In the zcs.example.com, you can start sserver in this way:
$sserver -p 12345 -s imap -S /opt/zimbra/conf/krb5.keytab
In the client.example.com, first get the user1's credential by "kinit" and take authentication to sserver by sclient:
$kinit -k user1 $sclient zcs.example.com 12345 imap sendauth succeeded, reply is: reply len 25, contents: You are user1@EXAMPLE.COM
"kinit -k" means to use keytab file in the default location to authenticate user1. After successful getting user1's credential, it will ask imap service to zcs.example.com:12345 as specified by sclient. If you see something errors reported, check and make sure the steps mentioned above are done correctly.
Additional Notes
The following principals might be necessary:
- imap/zcs.example.com@EXAMPLE.COM
- pop/zcs.example.com@EXAMPLE.COM
- host/zcs.example.com@EXAMPLE.COM
- user1@EXAMPLE.COM
- user2@EXAMPLE.COM
- user3@EXAMPLE.COM
...
Preparing Zimbra for Kerberos Authentication
When you have installed and configured Kerberos, you must prepare a domain for Kerberos5 Authentication and then provision Zimbra accounts. Here I assume this domain is zcs.example.com. If not, please set it with "zmprov cd" command.
Configure ZCS
The authentication mechanism is set in the domain level. So first, set domain authentication mechanism to kerberos5
zmprov md zcs.example.com zimbraAuthMech kerberos5
Then set the default realm to use.
zmprov md zcs.example.com zimbraAuthKerberos5Realm EXAMPLE.COM
Finally, enable Kerberos authentication for IMAP and POP3.
zmprov ms zcs.example.com zimbraImapSaslGssapiEnabled TRUE zmprov ms zcs.example.com zimbraPop3SaslGssapiEnabled TRUE
Provision Zimbra Accounts
When a user attempts to login to Zimbra as user/password, and when the domain's zimbraAuthMech is kerberos5, the system will authenticate to KDC instead of LDAP.
The Kerberos credential for the user is:
- Password. This is the user's password.
- Principal. The Kerberos principal for a user can be resolved by either of the following methods.
Principal Resolution Method 1
One method of resolving a user's Kerberos principal is to enter the user's address in the form of <local part of Zimbra email address>@<zimbraAuthKerberos5Realm>.
For example, for user1@example.com, the Kerberos principal will be user1@EXAMPLE.COM.
Principal Resolution Method 2
Kerberos principal can also be resolved on a per account basis, instead of using the realm defined in zimbraAuthKerberos5Realm. This allows accounts in the same Zimbra domain to be mapped to different Kerberos Realms.
To use this method, set the account's zimbraForiegnPrincipal as kerberos5:<kerberos5-principal>. If the zimbraForeignPrincipal of the account starts with kerberos5:, the system will authenticate to Kerberos using as the principal the text appearing after the kerberos5: in the zimbraForeignPrincipal.
For example:
zmprov ma user1@example.com +zimbraForeignPrincipal kerberos5:user1@EXAMPLE.COM
In the above example, for user1@example.com, the Kerberos principal will be user1@EXAMPLE.COM.
Note: Method 2 will overwrite Method 1. If the account has a zimbraForeignPrincipal in the form of kerberos5:<kerberos5-principal>, the system will resolve the Kerberos principal using Method 2.
Now, you can authenticate to ZCS by Kerberos protocol. You can test by this way (assume ZCS IMAP port is 7143):
$gsasl --connect zcs.example.com:7143 -a user1@zcs.example.com -d
If authentication fails, try to use "kinit" to get the user credential in client.example.com and imap service credential in zcs.example.com.
Configure ZCS Proxy (Nginx)
Troubleshooting
KDC has no support for encryption type (14) - BAD_ENCRYPTION_TYPE
This note applies to versions of ZCS at least up to and including 5.0.18.
In some environments Kerberos-authenticated users may be unable to log in, or only some users may be able to log in. This is due to a bug in the version of Java included with ZCS. ZCS uses the Sun Java Runtime Environment version 5, which is unable to process credential caches with encryption types it doesn't understand. This will result in errors in /opt/zimbra/log/audit.log like:
Security - cmd=Auth; account=account name; protocol=soap; error=authentication failed for name(kerberos5 principal: principal), KDC has no support for encryption type (14) - BAD_ENCRYPTION_TYPE;
Recent (roughly post-2005) MIT Kerberos principals include enctypes not understood by the Java 5 runtime. To successfully authenticate, uncomment the following lines at the top of your /etc/krb5.conf:
default_tgs_enctypes = des3-hmac-sha1 default_tkt_enctypes = des3-hmac-sha1 permitted_enctypes = des3-hmac-sha1
Encryption type not in permitted_enctypes list
If the keytabs generated by KDCs are built with enctype AES256-CTS, which is not supported in the Java 6 shipped by Zimbra, you will see an error in /opt/zimbra/log/mailbox.log that looks like the following:
javax.security.sasl.SaslException: GSS initiate failed [Caused by GSSException:Failure unspecified at GSS-API level (Mechanism level: AES256 CTS mode with HMAC SHA1- 96 encryption type not in permitted_enctypes list)]
In order to use keytabs that are built with enctype AES256-CTS, you must download Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Files 6 from Sun Microsystems' Java SE Downloads page, and install JCE on your Zimbra servers.