In this article, I will provide step by step "how to" instructions to use Kerberos authentication from Teiid to HDP platform. It is expected that the user has knowledge about Kerberos authentication and have gathered all the necessary configuration and keytabs before starting this exercise. it is also expected that HDP platform is already configured with Kerberos and tested to work correctly with tools like Beeline. The instructions in the article are for Teiid and WildFly configuration.
For the purposes of this article, we used HDP platform version HDP 2.6.0.3-8, JDBC driver for this version can be found in installation directory in /usr/hdp/2.6.0.3-8/hive/jdbc/hive-jdbc-1.2.1000.2.6.0.3-8-standalone.jar. Before we proceed further let's first make sure HDP connects with simple JDBC class using Kerberos. Use below code to make direct JDBC connection to HDP to verify.
JDBC-based clients must includeprincipal=<HiveServer2-Kerberos-Principal> in the JDBC connection string. For example hive/localhost@EXAMPLE.COM
<HOSTNAME> is the name of the host where HiveServer2 is installed in below server which MUST be replaced with real name.
import javax.security.auth.Subject; import javax.security.auth.login.LoginContext; import java.security.PrivilegedAction; import java.sql.Connection; import java.util.Properties; import org.apache.hive.jdbc.HiveDriver; public class Main{ public static void main(String... args) throws Exception { System.setProperty("java.security.auth.login.config", "/path/to/dv.conf"); System.setProperty("sun.security.krb5.debug", "true"); LoginContext c = new LoginContext("dv"); c.login(); Subject.doAs(c.getSubject(), (PrivilegedAction<Object>)() -> { try{ HiveDriver d = new HiveDriver(); Connection con = d.connect("jdbc:hive2://<HOSTNAME>:10000/default;principal=hive/<HOSTNAME>@EXAMPLE.COM;auth=kerberos;kerberosAuthType=fromSubject", new Properties()); ResultSet rs = con.createStatement().executeQuery("select current_user()"); rs.next(); System.out.println("Logged in user="+rs.getString(1)); con.close(); } catch (Exception ex){ ex.printStackTrace(); } return null; }); } }
with dv.conf file contents like (a variation of this file can be used to make use of ticket cache too)
dv { com.sun.security.auth.module.Krb5LoginModule required principal="dv@EXAMPLE.COM" refreshKrb5Config="false" useTicketCache="false" useKeyTab="true" keyTab="/path/to/dv.keytab" doNotPrompt="true" debug="true"; };
When you execute the above code, the DV user should be printed to the console. Now if this is successful, then now we are ready to for configuration in Teiid/WildFly.
Log into HDP using the Kerberos authentication From Teiid/WildFly
First, we need to create a module for Hive JDBC driver. In the "modules/system/layer/dv/org/hdp/hive/main" directory create a file called module.xml with following contents
<?xml version="1.0" encoding="UTF-8"?> <module xmlns="urn:jboss:module:1.0" name="org.hdp.hive"> <resources> <resource-root path="hive-jdbc-1.2.1000.2.6.0.3-8-standalone.jar"/> </resources> <dependencies> <module name="javax.api"/> <module name="javax.resource.api"/> <module name="sun.jdk"/> <system export="true"> <paths> <path name="sun/security/krb5/internal"/> </paths> </system> </dependencies> </module>
and make sure you copy the Hive JDBC jar file in the same directory from the installation directory mentioned above.
Edit the standalone.xml, could be standalone-teiid.xml depending on how you installed Teiid, and add the following in DataSources subsystem, create connection configuration as
<datasource jndi-name="java:/hive_krb" pool-name="hive_krb" enabled="true"> <connection-url>jdbc:hive2://<HOSTNAME>:10000/default;principal=hive/<HOSTNAME>@EXAMPLE.COM;auth=kerberos;kerberosAuthType=fromSubject</connection-url> <driver>hive</driver> <security> <security-domain>hive_krb</security-domain> </security> <drivers> <driver name="hive" module="org.hdp.hive"> <driver-class>org.apache.hive.jdbc.HiveDriver</driver-class> </driver> </drivers> </datasource>
The <security-domain> element defines the JAAS security domain to be used with the Oracle connection. Now let's configure the security domain specific details. Edit the standalone.xml and add
<system-properties> <property name="java.security.krb5.conf" value="${jboss.home.dir}/krb5.conf"/> <property name="java.security.krb5.debug" value="true"/> </system-properties>
My sample krb5.conf file looks like
[libdefaults] debug = true dns_lookup_realm = false rdns = false forwardable = true ticket_lifetime = 24h renew_lifetime = 7d max_renewable_life = 7d default_realm = EXAMPLE.COM [realms] EXAMPLE.COM = { kdc = kerberos-test.example.com:88 default_domain = EXAMPLE.COM } [domain_realm] .example.com = EXAMPLE.COM example.com = EXAMPLE.COM [login] krb4_convert = true krb4_get_tickets = false [pam] debug = true ticket_lifetime = 36000 renew_lifetime = 36000 krb4_convert = false
copy this file krb5.conf into where Teiid/WildFly is installed, in the home directory.
Continue editing the standalone.xml and add security-domain in "security" subsystem (Make sure the below configuration does not use caching, i.e cache-type either ignored or set to "none")
<security-domain name="hive_krb"> <authentication> <login-module code="Kerberos" flag="required" module="org.jboss.security.negotiation"> <module-option name="storeKey" value="true"/> <module-option name="useKeyTab" value="true"/> <module-option name="keyTab" value="${jboss.home.dir}/DV.keytab"/> <module-option name="principal" value="DV@EXAMPLE.COM"/> <module-option name="doNotPrompt" value="true"/> <module-option name="debug" value="true"/> <module-option name="refreshKrb5Config" value="false"/> <module-option name="addGSSCredential" value="true"/> </login-module> </authentication> </security-domain>
Copy the Key Tab file for user "DV " into the Teiid/WildFly home directory. Now save the file, and start the Teiid server. Deploy a test VDB like
test-hive-vdb.xml
<?xml version="1.0" encoding="utf-8"?> <vdb name="test_hive" version="1"> <model name="usr" type="PHYSICAL"> <source name="usr" connection-jndi-name="java:/hive_krb" translator-name="hive-over"/> <metadata type="NATIVE"/> <metadata type="DDL"><![CDATA[ CREATE FOREIGN FUNCTION current_user() RETURNS string; ]]> </metadata> </model> <translator name="hive-over" type="hive"> <property name="SupportsDirectQueryProcedure" value="true"/> </translator> </vdb>
Now using your favorite JDBC client, connect to the "test_hive" vdb and issue a query
SELECT usr.current_user()
And the DV user should be visible there.
If you want to use "service account" with key tab on your Teiid/WildFly server instead using an individual's credentials, in the configuration above replace, "DV@EXAMPLE.COM" with "SERVICE_ACCT/host@EXAMPLE.COM" and replace with DV.keytab with SERVICE_ACCT.keytab
Pass-Through Authentication to HDP
To be continued.
References
Comments