In this "how to" guide I will go over the steps I took to make kerberos authentication work with Teiid JDBC based login. My setup includes two laptop machines running Fedora OS. They both are connected to my wireless router under same subnet. For simplicity sake, I edited "/etc/hosts" file added following lines
192.168.1.76 primary.example.com 192.168.1.98 secondary.example.com
Most of you already may have your enterprise kerberos system installed and configured to go, however in for my testing I had to install kerberoes server. I took instructions from http://fedoraproject.org/wiki/Kerberos_KDC_Quickstart_Guide here. On my "secondary.example.com" machine, with root permissions
yum -y install krb5-libs krb5-server krb5-workstation
Once the installation is complete, I needed to create database for the kerberos credentials, typically enterprises may attach to LDAP etc, for my test case that is not important, so a simple local store is sufficient. To achieve that execute
kdb5_util create -s
Typically when the time difference between machine is off, kerbeors gives issues, so you can synchronize time using NTP, for that execute
yum install ntp service ntpd restart
Edit the "/var/kerberos/krb5kdc/kadm5.acl" to look like
*/admin *
now edit the "/etc/krb5.conf" file, and it should look like
[logging] default = FILE:/var/log/krb5libs.log kdc = FILE:/var/log/krb5kdc.log admin_server = FILE:/var/log/kadmind.log [libdefaults] dns_lookup_realm = false ticket_lifetime = 24h renew_lifetime = 7d forwardable = true rdns = false default_realm = EXAMPLE.COM [realms] EXAMPLE.COM = { kdc = secondary.example.com:88 admin_server = secondary.example.com:749 } [domain_realm] .example.com = EXAMPLE.COM example.com = EXAMPLE.COM
Now edit firewall permissions and allow "kerberos", for my setting, I used graphical management tool that come with fedora to accomplish that. Then start the kerberos server using following commands
/sbin/service krb5kdc start /sbin/service kadmin start
Now we are ready to create users in the kerberos, to begin with we need a "root" user, you can add that by issuing
kadmin.local -q "addprinc root/admin"
Now login with "root" user in kadmin to create another user
kadmin.local -p root/admin
Then at the command prompt, to add a user say "rareddy", issue command
ank rareddy ank HTTP/primary.example.com
You can also view all the users in the system by issuing
listprincs
you will see users like
root/admin@EXAMPLE.COM rareddy@EXAMPLE.COM krbtgt/EXAMPLE.COM@EXAMPLE.COM HTTP/primary.example.com@EXAMPLE.COM
Here I am going to use "HTTP/primary.example.com@EXAMPLE.COM" user as Service Provider Principle. I could also have used the SPN "krbtgt/EXAMPLE.COM@EXAMPLE.COM". In Kerberos, there are three systems, one is client user (that is you, ex:rareddy), second is where the service you want to access (that is Teiid server), and then the kerberos server itself. In order for the service provider system to authenticate with Kerberos system, you do not want configure using your user token, but need to use a trusted user called SPN. Initially, the client machine talks directly to the Kerberos system gets a token, and then uses that token with service system to negotiate a login. In back end, the service provider system, based on its SPN credentials with authorize the client or not.
To proceed we need to create a keytab, which holds the credentials. To create a keytab, execute below on kadmin console
ktadd -k /path/to/http.keytab HTTP/primary.example.com ktadd -k /path/to/rareddy.keytab rareddy
Now kerberoes is all setup, copy the file "path/to/http.keytab" to the system where Teiid is running, to a known location. In my case it was "primary.example.com" machine. Install JBoss EAP and Teiid on this machine. If you installation directions see Installation Guide. Copy the "/etc/krb5.conf" file to this machine too in the same location.
Now edit the standalone-teiid.xml file, add
<system-properties> <property name="java.security.krb5.conf" value="/etc/krb5.conf"/> <property name="java.security.krb5.debug" value="true"/> <property name="java.security.disable.secdomain.option" value="true"/> <property name="javax.security.auth.useSubjectCredsOnly" value="false"/> </system-properties>
right after the "<extensions>" element. Add the following in the "security-domains" configuration
<security-domain name="host"> <authentication> <login-module code="Kerberos" flag="required"> <module-option name="storeKey" value="true"/> <module-option name="useKeyTab" value="true"/> <module-option name="keyTab" value="/path/to/http.keytab"/> <module-option name="principal" value= "HTTP/primary.example.com@EXAMPLE.COM"/> <module-option name="doNotPrompt" value="true"/> <module-option name="debug" value="true"/> </login-module> </authentication> </security-domain> <security-domain name="EXAMPLE.COM"> <authentication> <login-module code="SPNEGO" flag="requisite"> <module-option name="password-stacking" value="useFirstPass"/> <module-option name="serverSecurityDomain" value="host"/> </login-module> <login-module code="org.jboss.security.auth.spi.UsersRolesLoginModule" flag="requisite"> <module-option name="password-stacking" value="useFirstPass"/> <module-option name="usersProperties" value="${jboss.server.config.dir}/teiid-security-users.properties"/> <module-option name="rolesProperties" value="${jboss.server.config.dir}/teiid-security-roles.properties"/> </login-module> </authentication> </security-domain>
Edit transport setting in the "teiid" subsystem to look like
<transport name="jdbc" socket-binding="teiid-jdbc" protocol="teiid"> <authentication security-domain="EXAMPLE.COM" type="GSS"/> </transport>
Save the file, and start the JBoss EAP + Teiid server using
<jboss-as>/bin/standalone.sh -c standalone-teiid.xml -b primary.example.com
Deploy a VDB to this server, and try connecting to it using a JDBC client.
Copy the "rareddy.keytab" file to the client machine where you going to run the JDBC Client application. The idea is, the JDBC client uses "rareddy" user to login, where "HTTP/primary.example.com@EXAMPLE.COM" is the service principle on the server side. The reason I choose HTTP/primary.example.com as SPN is, for REST based applications I could not switch the SPN (l am sure there may be a way, IDK)
Before you can connect using JDBC, you need to create a file "client.conf" with contents like
Client { com.sun.security.auth.module.Krb5LoginModule required useTicketCache=true storeKey=true useKeyTab=true keyTab="/path/to/rareddy.keytab" doNotPrompt=true debug=true principal="rareddy@EXAMPLE.COM"; };
and set following system properties
-Djava.security.krb5.conf=/etc/krb5.conf -Djava.security.auth.login.config=/path/to/client.conf -Djavax.security.auth.useSubjectCredsOnly=false -Dsun.security.krb5.debug=true
Finally you need to use the following properties on the JDBC connection URL string
jaasName=Client;kerberosServicePrincipleName=HTTP/primary.example.com@EXAMPLE.COM
so, your JDBC connection URL should look like
jdbc:teiid:<vdb>@mm:<host>:31000;jaasName=Client;kerberosServicePrincipleName=HTTP/primary.example.com@EXAMPLE.COM"
Once you connect then you can issue the SQL queries. I used SimpleClient from quick starts from here teiid-quickstarts/simpleclient at master · teiid/teiid-quickstarts · GitHub as the JDBC client as it is easier to configure than the tools like SquirreL.
Gotchas: There are plenty!!!
Specified version of key is not available (44)
Caused by: KrbException: Specified version of key is not available (44)
I found two reasons for this,
* Your keytab is not correct. You may have added a user, or changed password for the user etc and keytab is no longer valid. Note that each time you update the user, there is KVNO identifier which gets incremented, those need to match with your keytab's version. To see what are the KVNO numbers and supported encryption types, execute
$klist -e -k -t /home/rareddy/development/jbossqe-eap-tests-kerberos-datasource/keytabs/rareddy.keytab Keytab name: FILE:/home/rareddy/development/jbossqe-eap-tests-kerberos-datasource/keytabs/rareddy.keytab KVNO Timestamp Principal ---- ------------------- ------------------------------------------------------ 11 06/16/2014 10:07:32 rareddy@EXAMPLE.COM (aes256-cts-hmac-sha1-96) 11 06/16/2014 10:07:32 rareddy@EXAMPLE.COM (aes128-cts-hmac-sha1-96) 11 06/16/2014 10:07:32 rareddy@EXAMPLE.COM (des3-cbc-sha1) 11 06/16/2014 10:07:32 rareddy@EXAMPLE.COM (arcfour-hmac) 11 06/16/2014 10:07:32 rareddy@EXAMPLE.COM (camellia256-cts-cmac) 11 06/16/2014 10:07:32 rareddy@EXAMPLE.COM (camellia128-cts-cmac) 11 06/16/2014 10:07:32 rareddy@EXAMPLE.COM (des-hmac-sha1) 11 06/16/2014 10:07:32 rareddy@EXAMPLE.COM (des-cbc-md5)
* Another is, your Service User Principal is wrong. What I found is, I can typically see what my user's service principle when I execute
$klist Ticket cache: DIR::/run/user/1000/krb5cc/tktk9TXbf Default principal: rareddy@EXAMPLE.COM Valid starting Expires Service principal 06/16/2014 10:27:55 06/17/2014 10:27:55 krbtgt/EXAMPLE.COM@EXAMPLE.COM renew until 06/16/2014 10:27:55 06/16/2014 10:28:15 06/17/2014 10:27:55 HTTP/primary.example.com@EXAMPLE.COM renew until 06/16/2014 10:27:55
For JDBC client, when I used "krbgt/EXAMPLE.COM@EXAMPLE.COM" it worked fine, same was not true when I used the same principal to make a HTTP call. I am not aware who chooses to assign a Service Principal (SPN) in KDC, in my case I took default by KDC. I need to probably further investigate how this works. For HTTP call, it was automatically looking for "HTTP/{host}/{relam}" based SPN.
Checksum Failed
Caused by: java.security.GeneralSecurityException: Checksum failed at sun.security.krb5.internal.crypto.dk.AesDkCrypto.decryptCTS(AesDkCrypto.java:451) [rt.jar:1.7.0_60] at sun.security.krb5.internal.crypto.dk.AesDkCrypto.decrypt(AesDkCrypto.java:272) [rt.jar:1.7.0_60] at sun.security.krb5.internal.crypto.Aes256.decrypt(Aes256.java:76) [rt.jar:1.7.0_60] at sun.security.krb5.internal.crypto.Aes256CtsHmacSha1EType.decrypt(Aes256CtsHmacSha1EType.java:100)
What I saw was typically keytab was wrong, may be configuration or the password has changed.
Encryption Related Issues
Found unsupported keytype (8) for rareddy@EXAMPLE.COM
Often you will see the keytype not supported issues, I installed java security libs from "http://www.oracle.com/technetwork/java/javase/downloads/jce-7-download-432124.html". Here you would need to copy JARs into your "jre/lib/security" directory ans restart the VMs.
Another place you two places you can control keys being used is, when using "ktadd .." in the kadmin routine above, you can use "-e" option to control which encryption to use. If you do not have control over it, then you edit "krb5.conf" file and in [libdefaults] section you can something like below (below is just an example)
default_tgs_enctypes = des3-hmac-sha1 des-cbc-crc des-cbc-md5 des3-cbc-sha1 aes256-cts-hmac-sha1-96 aes128-cts-hmac-sha1-96 arcfour-hmac default_tkt_enctypes = des3-hmac-sha1 des-cbc-crc des-cbc-md5 des3-cbc-sha1 aes256-cts-hmac-sha1-96 aes128-cts-hmac-sha1-96 arcfour-hmac permitted_enctypes = des3-hmac-sha1 des-cbc-crc des-cbc-md5 des3-cbc-sha1 aes256-cts-hmac-sha1-96 aes128-cts-hmac-sha1-96 arcfour-hmac
Further Steps: (for me)
* Need to secure a Windows machine to see if the I can do the same
* Test ODBC from windows machine. This is a must need to test.
* How to use kerberos without using the keytabs?
Hopefully above gave some instructions for configuring kerberos with Teiid. If you got any ideas on above further steps please do post.
Ramesh..
Comments