Kerberos end-to-end authentication
bklotz Jan 17, 2019 3:48 AMWe would like to have client kerberos principal (coming from active directory) authenticate through the complete call chain which consists
client application (http, SPNEGO) ->webservice(frontend jboss instance)->ejb (backend jboss)->(optional other jboss backends)->sqlserver (DB)
we were able to configure the frontend jboss (SPNEGO) which can pass the call to first backend successfully, using the identityForwarding:
static <T> T forwardIdentity(final PrivilegedExceptionAction<T> action) throws PrivilegedActionException {
final AuthenticationConfiguration configuration = AuthenticationConfiguration.empty()
.useForwardedIdentity(SecurityDomain.getCurrent())
.setSaslMechanismSelector(SaslMechanismSelector.ALL);
return AuthenticationContext.empty()
.with(MatchRule.ALL, configuration)
.run(action);
}
and the Kerberos factory (we use it in both role as acceptor server=true and initiator):
<kerberos-security-factory name="krbSF" principal="HTTP/fronend@REALM" path="frontend.keytab" obtain-kerberos-ticket="true" request-lifetime="3600" fail-cache="1" debug="true" mechanism-names="KRB5 SPNEGO" mechanism-oids="1.3.6.1.5.5.2 1.2.840.113554.1.2.2"/>
Now the questions:
- why going deeper in the call chain does not work (from backend to another backend)? maybe due the internal used sun.security.jgss.krb5.Krb5ProxyCredential can not be forwarded again and therefore the
SecurityDomain.getCurrent().getCurrentSecurityIdentity()->getPrivateCredentials()
returns 1 in frontend but 0 on backend?
2. the delegation works only for 10 hours, this is the TGT ticket lifetime of the frontend server, to make this working I patched the elytron GSSCredentialSecurityFactory
log.tracef("Creating GSSName for Principal '%s'", principal);
GSSName name = manager.createName(principal.getName(), GSSName.NT_USER_NAME, KERBEROS_V5);
int type = isServer ? ( obtainKerberosTicket ? GSSCredential.INITIATE_AND_ACCEPT : GSSCredential.ACCEPT_ONLY) : GSSCredential.INITIATE_ONLY;
if (wrapGssCredential) {
return new GSSKerberosCredential(wrapCredential(manager.createCredential(name, requestLifetime, mechanismOids.toArray(new Oid[mechanismOids.size()]),
type)), kerberosTicket);
}
return new GSSKerberosCredential(manager.createCredential(name, requestLifetime, mechanismOids.toArray(new Oid[mechanismOids.size()]),
type), kerberosTicket);
3. tried this DS config (also on the frontend), but does not work:
<datasource jndi-name="java:/comp/env/jdbc/MyDS" pool-name="MyDs" statistics-enabled="true">
<connection-url> jdbc:sqlserver://serverhost:1433;DatabaseName=MyDb;EnableBulkLoad=true;BulkLoadBatchSize=500;integratedSecurity=true;authenticationScheme=JavaKerberos;serverSpn=MSSQLSvc/serverhost:1433@MyREALM</connection-url>
<driver>sqlserver</driver>
<pool>
<max-pool-size>200</max-pool-size>
<allow-multiple-users>true</allow-multiple-users>
</pool>
<security>
<elytron-enabled>true</elytron-enabled>
</security>
<validation>
<valid-connection-checker class-name="org.jboss.jca.adapters.jdbc.extensions.mssql.MSSQLValidConnectionChecker"/>
<validate-on-match>true</validate-on-match>
<background-validation>false</background-validation>
<exception-sorter class-name="org.jboss.jca.adapters.jdbc.extensions.mssql.MSSQLExceptionSorter"/>
</validation>
</datasource>
it does not get any authentication, but when define
<authentication-context>dsAuthContext</authentication-context>
with an auth config using a kerberos factory for the database service user, it does not work as expected, because it does not use the original user principal
but the service account from the keytab
Currently we tested the above on EAP7.1.4 and 7.2 beta.
Has someone experience with such working configuration?