This repository contains a set of applications to experiment with spring security kerberos.
Goals of this project:
- use spring-security-kerberos with Spring Boot 2 (existing samples are only based on Spring Boot 1)
- integrate spring-security-kerberos in Zuul (with spring boot 2)
- integrate spring-security-kerberos in Spring Cloud Gateway (with spring boot 2)
The project contains two applications that can be used for local tests: minikdc
and some-service
that are described below.
This app integrates Spring Boot 2, Zuul and Spring Security Kerberos.
cd applications/kerberos-zuul
SERVICE_ENDPOINT=http://some-service SERVICE_PATH=/some-path KRB5_CONF=/tmp/somewhere/krb5.conf SERVICE_PRINCIPAL=service/localhost KEYTAB_LOCATION=/tmp/somelocation mvn spring-boot:run
- KRB5_CONF: path to a
krb5
configuration file. If testing with MiniKDC application, it will be thekrb5.conf
file. - KEYTAB_LOCATION: path to a
keytab
configuration file. If testing with MiniKDC application, it will be theexample.keytab
file. - SERVICE_ENDPOINT: the url to the downstream service. The gateway will redirect the user to this endpoint if
the authentication is ok and the url path matches the
SERVICE_PATH
value. Default value:http://localhost:9090
. - SERVICE_PATH: the path to the downstream service from the gateway. Default value:
/some-service
. - SERVICE_PRINCIPAL: the principal representing the service. Is it really useful ???. Default value:
HTTP/localhost
.
The app will be listening on port 8080 by default.
docker build . -t kerberos-zuul
docker run -it -p9999:8080 -v [LOCAL_CONF_DIR]:/conf -e SERVICE_ENDPOINT=[SERVICE_ENDPOINT_REACHABLE_FROM_CONTAINER] -e SERVICE_PRINCIPAL=[SERVICE_PRINCIPAL] -e SERVICE_PATH=[SERVICE_PATH] kerberos-zuul
- LOCAL_CONF_DIR: local directory containing a
krb5.conf
andgateway.keytab
configuration files. Their names can also be overriden withKRB5_CONF
andKEYTAB_LOCATION
environment variables. If using the MiniKDC application,gateway.keytab
content must be the same thanexample.keytab
andkrb5.conf
must be copied and modified to reference a valid KDC address. - SERVICE_ENDPOINT: the url to the downstream service. The gateway will redirect the user to this endpoint if
the authentication is ok and the url path matches the
SERVICE_PATH
value. - SERVICE_PATH: the path to the downstream service from the gateway.
- SERVICE_PRINCIPAL: the principal representing the service. Is it really useful ???
spring-security-kerberos integrates very well with Zuul and Spring Boot 2. The configuration is straightforward and the same as if you were working with Spring Boot 1.
This app integrates Spring Cloud Gateway and Spring Security Kerberos.
cd applications/kerberos-spring-cloud-gateway
SERVICE_ENDPOINT=http://some-service SERVICE_PATH=/some-path KRB5_CONF=/tmp/somewhere/krb5.conf SERVICE_PRINCIPAL=service/localhost KEYTAB_LOCATION=/tmp/somelocation mvn spring-boot:run
The configuration is the same than the Zuul gateway.
The app will be listening on port 8080 by default.
docker build . -t kerberos-scg
docker run -it -p9999:8080 -v [LOCAL_CONF_DIR]:/conf -e SERVICE_ENDPOINT=[SERVICE_ENDPOINT_REACHABLE_FROM_CONTAINER] -e SERVICE_PRINCIPAL=[SERVICE_PRINCIPAL] -e SERVICE_PATH=[SERVICE_PATH] kerberos-scg
The configuration is the same than the Zuul gateway.
spring-security-kerberos doesn't integrate in a straightforward way with Spring Cloud Gateway. The reason is that SCG is built on Webflux and spring security must be configured in a reactive fashion.
If you try to configure the security in a non reactive way, yow will run in this issue.
To integrate spring-security-kerberos, the following adaptations have been made:
- Create a custom authentication entry point named
ReactiveSpnegoAuthenticationEntryPoint
The goal of this entry point is to:
- set the http header
WWW-Authentication
withNegotiate
value. - save in the session the request that has been performed
Note: it is not done in the non reactive version of this entry point since it is
managed by ExceptionTranslationFilter
. In the reactive world, ExceptionTranslationWebFilter
does not manage this cache
- populate the response body with the login page.
In the non reactive world, a simple request forward is done which is not possible with Spring Webflux.
- Create a custom filter named
ReactiveSpnegoAuthenticationProcessingFilter
It is the equivalent of SpnegoAuthenticationProcessingFilter
filter but in the reactive world.
Note that this version is not as configurable as the original one but it should do the job with its defaults.
For a production-ready version, there will probably need some deeper investigation to check if this level of configuration is good enough or not.
This application is a Kerberos KDC used for local testing.
cd applications/minikdc
mvn clean package
mvn exec:java -Dexec.mainClass=com.fha.minikdc.Application -Dexec.args=[PATH]
- PATH: Path to where the configuration and data files will be generated. Default value:
/tmp/minikdc
When testing with the MiniKDC application, the configuration files will be needed to test the gateways:
krb5.conf
example.keytab
Two principals are created and can be used for testing the gateways:
client/localhost
HTTP/localhost
Their password can be found in the application logs after startup. Look for something like this:
2019-12-27 10:14:08 DEBUG LdifReader:1767 - next(): -- returning ldif dn: uid=HTTP/localhost,ou=users,dc=example,dc=com
uid: HTTP/localhost
krb5keyversionnumber: 0
cn: HTTP/localhost
sn: HTTP/localhost
objectclass: top
objectclass: person
objectclass: inetOrgPerson
objectclass: krb5principal
objectclass: krb5kdcentry
userpassword: a017ab75-3a1c-444e-949f-f2c37eb851c9
krb5principalname: HTTP/localhost@EXAMPLE.COM
The value that interests you is userpassword
.
These principals are the ones to use to test the gateways with MiniKDC.
This is a simple Spring Boot app with one controller endpoint. It is used to fake a downstream service that will be reached from a gateway implementing Kerberos security.
In a real environment, such an application would probably be in a private and secured network since it is not directly secured.
cd applications/some-service
mvn spring-boot:run
The app will be listening on port 9090 by default.