Elytron and Kerberos using gssproxy

This tutorial describes how to configure WildFly to use Elytron to use gssproxy for Kerberos authentication.

WARNING: The GS2-* SASL mechanisms will not work with native Kerberos in latest Oracle JDK (JKD8u121 and upstream JDK9). There is patch for OpenJDK (jkalina-openjdk-native-gss.patch), but it is going to be merged into JDK 11 in November 2018. (see OpenJDK mailing list)

Testing environment

For needs of this tutorial you can use simple Kerberos server and keytab generator by Josef Cacek:

git clone https://github.com/hkalina/kerberos-using-apacheds/
cd kerberos-using-apacheds
mvn install

Generate keytab file both.keytab (which will contain key for both, remoting and HTTP) to be used by gssproxy for WildFly:

java -classpath target/kerberos-using-apacheds.jar org.jboss.test.kerberos.CreateKeytab HTTP/localhost@JBOSS.ORG httppwd remote/localhost@JBOSS.ORG remotepwd both.keytab

Lets start testing Kerberos server:

java -jar target/kerberos-using-apacheds.jar test.ldif

Gssproxy

Prepare following gssproxy.conf and keytab both.keytab in directory readable only by root:

The gssproxy.conf file:

[gssproxy]
  debug = true
  debug_level = 3

[service/wildfly]
  mechs = krb5
  euid = 1000 # UID of the user running the WildFly
  cred_store = keytab:/root/both.keytab

Note: Even through only krb5 is supported in mechs, this does not affect possibility to use gssproxy for SPNEGO authentication.

sudo gssproxy -i -d -c /root/gssproxy.conf

Configuring WildFly to use Kerberos

Start the WildFly server with following parameters:

GSSPROXY_BEHAVIOR=REMOTE_FIRST \
GSS_USE_PROXY=1 \
JAVA_OPTS="-Djavax.security.auth.useSubjectCredsOnly=false \
           -Dsun.security.jgss.lib=/usr/lib64/libgssapi_krb5.so \
           -Dsun.security.jgss.native=true \
           -Dsun.security.nativegss.debug=true \
           -Dsun.security.krb5.debug=true \
           -Dsun.security.jgss.debug=true" \
bin/standalone.sh

The *.debug properties should be omitted in production environment.

As the gssproxy will be used, there is no need to configure java.security.krb5.conf property.

The path to the keytab in kerberos-security-factory will not be used when native Kerberos is enabled, but this property is currently required, so let dummy.keytab here for now:

/subsystem=elytron/kerberos-security-factory=krbSFhttp:add(principal=HTTP/localhost@JBOSS.ORG, path=dummy.keytab, mechanism-names=[KRB5, SPNEGO])
/subsystem=elytron/kerberos-security-factory=krbSFremote:add(principal=remote/localhost@JBOSS.ORG, path=dummy.keytab, mechanism-names=[KRB5])

Now can be required mechanisms added into authentication factory:

/subsystem=elytron/http-authentication-factory=management-http-authentication:list-add(name=mechanism-configurations, \
    value={mechanism-name=SPNEGO, credential-security-factory=krbSFhttp})
/subsystem=elytron/sasl-authentication-factory=management-sasl-authentication:list-add(name=mechanism-configurations, \
    value={mechanism-name=GSSAPI, credential-security-factory=krbSFremote})

As Kerberos provides authentication only, in practical deployment this would be done in combination with obtaining users from LDAP. Check Kerberos tutorial to configure it.

In this tutorial this will be simplified by using predefined properties-realm. You need to ensure users exists in appropriate security realm - add them into mgmt-users.properties:

hnelson@JBOSS.ORG=

Enabling Elytron for management authentication

To use authentication factories above we need to switch to them from legacy security realms:

/core-service=management/management-interface=http-interface:write-attribute(name=http-authentication-factory,value=management-http-authentication)
/core-service=management/management-interface=http-interface:write-attribute(name=http-upgrade.sasl-authentication-factory, value=management-sasl-authentication)
/core-service=management/management-interface=http-interface:undefine-attribute(name=security-realm)

(http-upgrade defines parameters for using SASL in HTTP connections)

Simple workaround for JDK bug

In latest Oracle JDK and OpenJDK there is bug JDK-8194073, which needs to be workarounded if you get messages like following:

GSSException: Provider SunNativeGSS does not support mechanism 1.2.840.113554.1.2.2

To resolve, enable workaround implemented in Elytron - set wildfly.sasl.gssapi.server.create-name-gss-init to true for GSSAPI SASL server or org.wildfly.security.http.create-name-gss-init for SPNEGO HTTP mechanism:

/subsystem=elytron/configurable-sasl-server-factory=configured:map-put(name=properties, key=wildfly.sasl.gssapi.server.create-name-gss-init, value=true)
/subsystem=elytron/configurable-http-server-mechanism-factory=configurableHttp:add(http-server-mechanism-factory=global, properties={org.wildfly.security.http.create-name-gss-init=true})
/subsystem=elytron/http-authentication-factory=management-http-authentication:write-attribute(name=http-server-mechanism-factory,value=configurableHttp)
/subsystem=elytron/http-authentication-factory=application-http-authentication:write-attribute(name=http-server-mechanism-factory,value=configurableHttp)

Just note that this workaround workarounds JDK-8194073 only, which will allow you to use SASL GSSAPI and HTTP SPNEGO mechanisms. To use GS2-* SASL mechanism you need to apply OpenJDK patch for JDK-8194630 mentioned in the top of this tutorial. (GS2 mechanism requires channel binding, which is broken for native Kerberos otherwise.)

Testing using CLI or Firefox

At first use kinit to log-in:

export KRB5_CONFIG=/home/jkalina/tutorial/kerberos-using-apacheds/krb5.conf
kinit hnelson@JBOSS.ORG

Now you can run :whoami command, authenticated using Kerberos:

bin/jboss-cli.sh -c --no-local-auth \
    -Djavax.security.auth.useSubjectCredsOnly=false \
    -Djava.security.krb5.conf=/home/jkalina/work/tutorial-kerberos/kerberos-using-apacheds/krb5.conf \
    :whoami
{
    "outcome" => "success",
    "result" => {"identity" => {"username" => "hnelson@JBOSS.ORG"}}
}

Firefox

In about:config set network.negotiate-auth.trusted-uris to contain localhost - individual hostnames needs to be delimited by comma AND space - for example:

.redhat.com, .fedoraproject.org, localhost

Run Firefox with KRB5_CONFIG property set: (In this tutorial we has setup gssproxy only for server-side - Firefox still needs krb5.conf)

export KRB5_CONFIG=/home/jkalina/Desktop/tutorial/kerberos-using-apacheds/krb5.conf
firefox http://localhost:9990/

Because the SPNEGO is now last in order, you need to press Cancel to cancel BASIC/DIGEST authentication. Now you should be logged into the management console as hnelson@JBOSS.ORG.

Getting debug output

We can specify property to enable Kerberos debug in Oracle JDK:

/system-property=sun.security.krb5.debug:add(value=true)

Trace messages from Elytron and from remoting will be also useful:

/subsystem=logging/logger=org.wildfly.security:add(level=TRACE)
/subsystem=logging/logger=org.jboss.remoting.remote.server:add(level=TRACE)

Add following to the JAVA_OPTS to obtain debug messages of the Kerberos from Oracle JDK:

-Dsun.security.nativegss.debug=true
-Dsun.security.krb5.debug=true
-Dsun.security.jgss.debug=true

(Some properties needs to be set on start of the JVM - are ignored when set in standalone.xml)

To get debug output from gssproxy add following into gssproxy section:

[gssproxy]
  debug = true
  debug_level = 3

Often error messages

No server entry found for kerberos principal name HTTP/127.0.0.1@JBOSS.ORG

You are accessing the WildFly server from browser by different hostname (127.0.0.1) then for which kerberos account exists (localhost).

KrbException: Fail to create credential. (63) - No service creds

Probably wrong mapping of hostname to realm in [domain_realm] section of krb5.conf - or wrong path to krb5.conf on client.

GSSException: No valid credentials provided (Mechanism level: Failed to find any Kerberos tgt)

Probably property javax.security.auth.useSubjectCredsOnly not set to false while trying to use local-kerberos credential.

GSSException: Invalid name provided (Mechanism level: KrbException: Cannot locate default realm)

Wrong path to the krb5.conf file.

Config file(s) not found!

Invalid path to the gssproxy.conf when starting gssproxy, OR invalid content of the file.

Key table file ‘/root/both.keytab # the keytab’ not found

Remove comments after end of the line in gssproxy.conf - are not supported correctly by gssproxy.

Encryption type not permitted

Add non-weak encryption type into krb5.conf, into default_tgs_enctypes and default_tkt_enctypes - for example aes128-cts-hmac-sha1-96.