Hi guys,
I'm using a docker-compose file to start a keycloak container in https. In order to do that, I've added these services to my compose:
keycloak-db:
image: postgres
volumes:
- keycloak-db-pgdata:/var/lib/postgresql/data
- ./docker/keycloak-db/init.sql:/docker-entrypoint-initdb.d/init.sql
env_file:
- docker/keycloak-db/keycloak-db.env
ports:
- 10005:5432
keycloak:
image: jboss/keycloak
env_file:
- docker/keycloak/keycloak.env
volumes:
- ./docker/keycloak/https/:/etc/x509/https
ports:
- 10006:8443
volumes:
keycloak-db-pgdata:
driver: local
This is the content of keycloak.env and keycloak-db.env:
(keycloak.env)
KEYCLOAK_USER=admin
KEYCLOAK_PASSWORD=admin
KEYCLOAK_LOGLEVEL=INFO
DB_VENDOR=POSTGRES
DB_ADDR=keycloak-db
DB_DATABASE=keycloak
DB_USER=keycloak-admin
DB_PASSWORD=password
KEYCLOAK_FRONTEND_URL=https://localhost:10006/auth
(keycloak-db.env)
POSTGRES_DB=keycloak
POSTGRES_USER=keycloak-admin
POSTGRES_PASSWORD=password
The file init.sql is simply a dump file to restore the database in case of necessity.
The /docker/keycloak/https folder contains two files that I've generated to start keycloak instance in https.
These files are:
- A self-signed certificate: tls.crt
- A private key: tls.key
I used the "keytool" and "openssl" commands from the command prompt to create these files, as follow:
- keytool -genkey -alias localhost -keyalg RSA -keystore keycloak.jks -validity 10950
- keytool -importkeystore -srckeystore keycloak.jks -destkeystore keycloak.p12 -deststoretype PKCS12
- openssl pkcs12 -in keycloak.p12 -nokeys -out tls.crt
- openssl pkcs12 -in keycloak.p12 -nocerts -nodes -out tls.key
- keytool -import -trustcacerts -keystore trust.keystore -storepass password -alias localhost -file tls.crt
The keycloak instance runs correctly in https.
The problem is a spring boot application which wants to communicate with it.
This application is managed with maven and uses the keycloak-spring-boot-starter dependency to secure its endpoints with spring security:
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-spring-boot-starter</artifactId>
<version>16.1.1</version>
</dependency>
This is the configuration bean:
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(jsr250Enabled = true)
@Profile("!test")
public class KeycloakSecurityConfiguration extends KeycloakWebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
super.configure(http);
http.authorizeRequests()
.antMatchers(HttpMethod.GET, "/tests").hasAnyRole("USER")
.anyRequest()
.authenticated();
http.csrf().disable();
}
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) {
KeycloakAuthenticationProvider keycloakAuthenticationProvider = keycloakAuthenticationProvider();
keycloakAuthenticationProvider.setGrantedAuthoritiesMapper(new SimpleAuthorityMapper());
auth.authenticationProvider(keycloakAuthenticationProvider);
}
@Bean
@Override
protected SessionAuthenticationStrategy sessionAuthenticationStrategy() {
return new RegisterSessionAuthenticationStrategy(new SessionRegistryImpl());
}
@Bean
public KeycloakConfigResolver keycloakConfigResolver() {
return new KeycloakSpringBootConfigResolver();
}
}
and this is the content of application.properties file:
logging.level.root=INFO
server.port=8080
keycloak.realm=${The name of realm in keycloak}
keycloak.auth-server-url=https://localhost:10006/auth
keycloak.ssl-required=external
keycloak.resource=${The name of client in keycloak}
keycloak.credentials.secret=${The client secret in keycloak}
keycloak.use-resource-role-mappings=true
keycloak.bearer-only=true
# this is the file I've previously generated using keytool (I also tried to use keycloak.jks
# here but I obtained the same error)
keycloak.truststore=classpath:trust.keystore
keycloak.truststore-password=password
keycloak.confidential-port=10006
When I try to call /tests endpoint by postman (with a valid token), I obtain a 500 internal server error with this stacktrace:
Caused by: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at java.base/sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:439) ~[na:na]
at java.base/sun.security.validator.PKIXValidator.engineValidate(PKIXValidator.java:306) ~[na:na]
at java.base/sun.security.validator.Validator.validate(Validator.java:264) ~[na:na]
at java.base/sun.security.ssl.X509TrustManagerImpl.validate(X509TrustManagerImpl.java:313) ~[na:na]
at java.base/sun.security.ssl.X509TrustManagerImpl.checkTrusted(X509TrustManagerImpl.java:222) ~[na:na]
at java.base/sun.security.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:129) ~[na:na]
at java.base/sun.security.ssl.CertificateMessage$T12CertificateConsumer.checkServerCerts(CertificateMessage.java:630) ~[na:na]
... 84 common frames omitted
Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at java.base/sun.security.provider.certpath.SunCertPathBuilder.build(SunCertPathBuilder.java:141) ~[na:na]
at java.base/sun.security.provider.certpath.SunCertPathBuilder.engineBuild(SunCertPathBuilder.java:126) ~[na:na]
at java.base/java.security.cert.CertPathBuilder.build(CertPathBuilder.java:297) ~[na:na]
at java.base/sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:434) ~[na:na]
... 90 common frames omitted
Can anyone help me?
Thank you