I solved this problem using GSS API. Now i briefly describe settings and code, which works in my environment
1. Environment
Client java application run on Windows 7 (java SE version 8, swing), application server run on Windows 2012 r2 (java 8, tomcat or jetty, on glassfish did not work), sap hana db run on linux.
Windows user, which will connect to hana db and Windows user, which run application server, is in one windows domain (active directory).
2. Configuration windows domain
Was created spn and .keytab file in windows domain controller
3. Configuration hana
There is good Guide "HowTo_HANA_SSO_Kerberos_v1.7.1.pdf"
Was created db user in hana with external ID user@windowsdomain (account name from windows active directory)
There is good python script for configure hana for kerberos and check configuration. We got this script via sap hana support site.
4. Client configuration
windows registry key allowtgtsessionkey must be set to true
On client were files
login.conf
com.sun.security.jgss.login {
com.sun.security.auth.module.Krb5LoginModule required
useTicketCache=true
doNotPrompt=true
debug=true;
};
com.sun.security.jgss.initiate {
com.sun.security.auth.module.Krb5LoginModule required
useTicketCache=true
principal="saphanauser"
debug=true;
};
and krb5.conf
[libdefaults]
default_realm = DOMAINNAME.NEW
forwardable = true
clockskew = 3000
default_tkt_enctypes = aes256-cts aes128-cts rc4-hmac
default_tgs_enctypes = aes256-cts aes128-cts rc4-hmac
permitted_enctypes = aes256-cts aes128-cts rc4-hmac
[realms]
DOMAINNAME.NEW = {
kdc = KDCSERVERNAME
default_domain = DOMAINNAME.NEW
}
[domain_realm]
.domainname.new = DOMAINNAME.NEW
domainname.new = DOMAINNAME.NEW
5. Server configuration
On server were files
login.conf
com.sun.security.jgss.login {
com.sun.security.auth.module.Krb5LoginModule required
useTicketCache=true
doNotPrompt=true
debug=true;
};
com.sun.security.jgss.initiate {
com.sun.security.auth.module.Krb5LoginModule required
useTicketCache=true
debug=true;
};
com.sun.security.jgss.accept {
com.sun.security.auth.module.Krb5LoginModule required
storeKey=true
keyTab="C:/krb/keytab/krb5_hdb.keytab"
useKeyTab=true
realm="DOMAINNAME.NEW"
principal="HDB/LINUX.DOMAINNAME.NEW"
isInitiator=false
debug=true;
};
and krb5.conf
[libdefaults]
default_realm = DOMAINNAME.NEW
forwardable = true
default_tkt_enctypes = aes256-cts aes128-cts rc4-hmac
default_tgs_enctypes = aes256-cts aes128-cts rc4-hmac
permitted_enctypes = aes256-cts aes128-cts rc4-hmac
[realms]
DOMAINNAME.NEW = {
kdc = KDCSERVERNAME
default_domain = DOMAINNAME.NEW
}
[domain_realm]
.domainname.new = DOMAINNAME.NEW
domainname.new = DOMAINNAME.NEW
6. Client code
Getting token for send it to application server
public static byte[] getTokenGss() throws GSSException {
String spnName = "spn_name";
String oidValue= "1.2.840.113554.1.2.2"; // KERBEROS_MECH_OID
String userLogin = System.getProperty("user.name");
Oid mechOid = new Oid(oidValue);
System.setProperty("javax.security.auth.useSubjectCredsOnly", "false");
Path directoryConf = "C:\\client\\krb";
String pathToGssConfigFile = directoryConf.resolve("login.conf").toString();
System.setProperty("java.security.auth.login.config", pathToGssConfigFile);
String pathToKrb5ConfigFile = directoryConf.resolve("krb5.conf").toString();
System.setProperty("java.security.krb5.conf", pathToKrb5ConfigFile);
System.setProperty("sun.security.krb5.debug", "true");
GSSManager manager = GSSManager.getInstance();
GSSName gssUserName = manager.createName(userLogin, GSSName.NT_USER_NAME, mechOid);
logger.debug("before createCredential");
GSSCredential clientGssCreds =
manager.createCredential(gssUserName.canonicalize(mechOid), GSSCredential.INDEFINITE_LIFETIME, mechOid,
GSSCredential.INITIATE_ONLY);
byte[] token = new byte[0];
// create target server SPN
GSSName gssServerName = manager.createName(spnName, GSSName.NT_USER_NAME);
logger.debug("before createContext");
GSSContext clientContext = manager.createContext(gssServerName.canonicalize(mechOid), mechOid, clientGssCreds,
GSSContext.DEFAULT_LIFETIME);
// optional enable GSS credential delegation
clientContext.requestCredDeleg(true);
token = clientContext.initSecContext(token, 0, token.length);
return token;
}
7. Server code
Creating hibernate EntityManagerFactory using token from client
private EntityManagerFactory createEntNamagerFactoryViaKerberos(byte[] inToken)
throws Exception {
System.setProperty("javax.security.auth.useSubjectCredsOnly", "false");
System.setProperty("java.security.auth.login.config", "C:\\krb\\gsslogin\\login.conf");
System.setProperty("java.security.krb5.conf", "C:\\krb\\krb5.conf");
Oid mechOid = new Oid("1.2.840.113554.1.2.2");
GSSManager manager = GSSManager.getInstance();
//first obtain it's own credentials...
GSSCredential myCred =
manager.createCredential(null, GSSCredential.DEFAULT_LIFETIME, mechOid, GSSCredential.ACCEPT_ONLY);
//...and create a context for this credentials...
GSSContext context = manager.createContext(myCred);
//...then use that context to authenticate the calling peer by reading his token
byte[] tokenForPeer = context.acceptSecContext(inToken, 0, inToken.length);
if (!context.isEstablished()) {
throw new Exception("Context not established!");
}
//...then obtain information from the context
logger.debug("Clientcipal is " + context.getSrcName());
logger.debug("Servercipal is " + context.getTargName());
if (context.getCredDelegState()) {
logger.debug("Then is delegatable.");
} else {
logger.debug("Then is NOT delegatable");
}
GSSCredential clientCr = context.getDelegCred();
Subject s = GSSUtil.createSubject(clientCr.getName(), clientCr);
KerberosActionCreateEmf kerberosAction = new KerberosActionCreateEmf();
kerberosAction.unicalEntFactoryName = "kerb" + System.currentTimeMillis();
Subject.doAs(s, kerberosAction);
EntityManagerFactory emf = kerberosAction.emf;
return emf;
}
class KerberosActionCreateEmf implements PrivilegedExceptionAction {
public EntityManagerFactory emf;
public String modelName;
public String unicalEntFactoryName;
@Override
public Object run() throws Exception {
Properties properties = new Properties();
properties.setProperty("javax.persistence.jdbc.driver", "com.sap.db.jdbc.Driver");
properties.setProperty("hibernate.connection.url", "jdbc:sap://10.0.0.121:31015");
properties.setProperty("hibernate.dialect", "org.hibernate.dialect.HANAColumnStoreDialect");
// do not use login and pass, use kerberos delegation (token)
//properties.setProperty("hibernate.connection.username", login);
//properties.setProperty("hibernate.connection.password", pass);
properties.setProperty("hibernate.default_schema", "default_schema");
properties.setProperty("hibernate.show_sql", model_manager_hibernate_show_sql);
properties.setProperty("hibernate.ejb.entitymanager_factory_name", unicalEntFactoryName);
properties.setProperty("hibernate.cache.use_query_cache", "false");
properties.setProperty("hibernate.query.plan_cache_max_soft_references", "1");
properties.setProperty("hibernate.query.plan_cache_max_strong_references", "1");
properties.setProperty("hibernate.hikari.minimumIdle", "3");
properties.setProperty("hibernate.hikari.maximumPoolSize", "20");
properties.setProperty("hibernate.hikari.idleTimeout", "600000");
properties.setProperty("hibernate.hikari.AutoCommit", "false");
properties.setProperty("hibernate.hikari.poolName", unicalEntFactoryName);
properties.setProperty("hibernate.hikari.connectionTimeout", "1800000");
EntityManagerFactory newEntityManagerFactory =
Persistence.createEntityManagerFactory("persistenceUnitName", properties);
emf = newEntityManagerFactory;
return null;
}
}
8. useful links
http://thejavamonkey.blogspot.com/2008/04/clientserver-hello-world-in-kerberos.html
https://dmdaa.wordpress.com/category/java/jgss/
https://dmdaa.wordpress.com/2010/03/13/kerberos-setup-and-jaas-configuration-for-running-sun-jgss-tutorial-against-ad/
http://cr.openjdk.java.net/~weijun/special/krb5winguide-2/raw_files/new/kwin