I have a spring boot application that requires an X509 certificate for authentication.
This is already configured and working properly in the local dev environment when running from eclipse using docker desktop and fabric8 maven docker plugin to build the image.
Now I would like to deploy this to our k8s test cluster where I already succeeded to deploy a simple spring boot application with 8080 as a port. and I can reach it in the browser with https.
https://testcluster.exmaple.com/namespace/myapp-test/
As you see in the url the kuberntes cluster is already forwarding HTTP ports such as 8080 to a secure connection, Because I belive Kubernetes with ambassador will leverage that for you; you just need to provide a targetPort in your service.yaml (we are using helm):
kind: Service
apiVersion: v1
metadata:
name: {{ include "component.web.fullname" . }}
{{- include "helper.labels" . | nindent 2 }}
spec:
selector:
app: "{{ .Values.application.name }}"
component: "{{ .Values.component.web.name }}"
instance: "{{ .Values.instance }}"
type: ClusterIP
ports:
- name: https
port: 80
targetPort: 8080
The question is; if take my current local working config which is for spring boot :
#development only.
server.port=8443
server.ssl.key-store=/dev/server.jks
server.ssl.key-store-password=123123
server.ssl.key-alias=localhost
server.ssl.key-password=123123
server.ssl.enabled=true
server.ssl.trust-store=/dev/clients.jks
server.ssl.trust-store-password=123123
server.ssl.client-auth=need
With the following spring security config :
@Override
protected void configure(HttpSecurity http) throws Exception {
http.requiresChannel()
.anyRequest()
.requiresSecure()
.and().csrf().disable()
// .exceptionHandling()
// .accessDeniedPage("/403")
// .and()
.x509()
.userDetailsService(userDetailsService)
.and()
.authorizeRequests()
.antMatchers("/**").access("hasAuthority('SYSADMIN')");
}
But before deploying that,I tried with simple spring boot app with a hello world controller and no spring security config, just the server certificate only with a config that looks like this :
server.port=8443
server.ssl.key-store=/dev/server.jks
server.ssl.key-store-password=123123
server.ssl.key-alias=localhost
server.ssl.key-password=123123
server.ssl.enabled=true
And deployed to Kubernetes and updated the deployment.yaml and service.yaml to use port 8443 of the application and I got this :
Bad Request
This combination of host and port requires TLS.
So, If I can deploy a spring boot app that doesn't require client cert without any SSL config and I still can reach the application with SSL connection, how should I do for an optimal configuration to run mutual SSL applications, because as far as I know, I cannot configure mutual SSL in spring boot with only the trustore config only (be aware of the commented lines):
server.port=8443
#server.ssl.key-store=/dev/server.jks
#server.ssl.key-store-password=123123
#server.ssl.key-alias=localhost
#server.ssl.key-password=123123
server.ssl.enabled=true
server.ssl.trust-store=/dev/clients.jks
server.ssl.trust-store-password=123123
server.ssl.client-auth=need
this will result in spring boot complaining with the stack below :
org.springframework.context.ApplicationContextException: Unable to start web server; nested exception is org.springframework.boot.web.server.WebServerException: Could not load key store 'null'
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.onRefresh(ServletWebServerApplicationContext.java:156) ~[spring-boot-2.2.5.RELEASE.jar:2.2.5.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:544) ~[spring-context-5.2.4.RELEASE.jar:5.2.4.RELEASE]
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:141) ~[spring-boot-2.2.5.RELEASE.jar:2.2.5.RELEASE]
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:747) [spring-boot-2.2.5.RELEASE.jar:2.2.5.RELEASE]
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:397) [spring-boot-2.2.5.RELEASE.jar:2.2.5.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:315) [spring-boot-2.2.5.RELEASE.jar:2.2.5.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1226) [spring-boot-2.2.5.RELEASE.jar:2.2.5.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1215) [spring-boot-2.2.5.RELEASE.jar:2.2.5.RELEASE]
at com.sample.Application.main(Application.java:19) [classes/:na]
Caused by: org.springframework.boot.web.server.WebServerException: Could not load key store 'null'
at org.springframework.boot.web.embedded.tomcat.SslConnectorCustomizer.configureSslKeyStore(SslConnectorCustomizer.java:128) ~[spring-boot-2.2.5.RELEASE.jar:2.2.5.RELEASE]
at org.springframework.boot.web.embedded.tomcat.SslConnectorCustomizer.configureSsl(SslConnectorCustomizer.java:88) ~[spring-boot-2.2.5.RELEASE.jar:2.2.5.RELEASE]
at org.springframework.boot.web.embedded.tomcat.SslConnectorCustomizer.customize(SslConnectorCustomizer.java:57) ~[spring-boot-2.2.5.RELEASE.jar:2.2.5.RELEASE]
at org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory.customizeSsl(TomcatServletWebServerFactory.java:339) ~[spring-boot-2.2.5.RELEASE.jar:2.2.5.RELEASE]
at org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory.customizeConnector(TomcatServletWebServerFactory.java:317) ~[spring-boot-2.2.5.RELEASE.jar:2.2.5.RELEASE]
at org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory.getWebServer(TomcatServletWebServerFactory.java:183) ~[spring-boot-2.2.5.RELEASE.jar:2.2.5.RELEASE]
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.createWebServer(ServletWebServerApplicationContext.java:180) ~[spring-boot-2.2.5.RELEASE.jar:2.2.5.RELEASE]
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.onRefresh(ServletWebServerApplicationContext.java:153) ~[spring-boot-2.2.5.RELEASE.jar:2.2.5.RELEASE]
... 8 common frames omitted
Caused by: java.lang.IllegalArgumentException: Resource location must not be null
at org.springframework.util.Assert.notNull(Assert.java:198) ~[spring-core-5.2.4.RELEASE.jar:5.2.4.RELEASE]
at org.springframework.util.ResourceUtils.getURL(ResourceUtils.java:130) ~[spring-core-5.2.4.RELEASE.jar:5.2.4.RELEASE]
at org.springframework.boot.web.embedded.tomcat.SslConnectorCustomizer.configureSslKeyStore(SslConnectorCustomizer.java:125) ~[spring-boot-2.2.5.RELEASE.jar:2.2.5.RELEASE]
... 15 common frames omitted